diff --git a/clients/opal/models/send_receive/include/config.h b/clients/opal/models/send_receive/include/config.h index 1b28c4cfc..6136864ea 100644 --- a/clients/opal/models/send_receive/include/config.h +++ b/clients/opal/models/send_receive/include/config.h @@ -8,18 +8,18 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#define PROGNAME "VILLASnode-OPAL-UDP" -#define VERSION "0.7" +#define PROGNAME "VILLASnode-OPAL-UDP" +#define VERSION "0.7" -#define MAX_VALUES 64 +#define MAX_VALUES 64 // List of protocols -#define VILLAS 1 -#define GTNET_SKT 2 +#define VILLAS 1 +#define GTNET_SKT 2 // Default protocol #ifndef PROTOCOL - #define PROTOCOL VILLAS +#define PROTOCOL VILLAS #endif // PROTOCOL #endif // _CONFIG_H_ diff --git a/clients/opal/models/send_receive/include/msg_format.h b/clients/opal/models/send_receive/include/msg_format.h index 95b7e769f..c3a9cf08a 100644 --- a/clients/opal/models/send_receive/include/msg_format.h +++ b/clients/opal/models/send_receive/include/msg_format.h @@ -10,65 +10,63 @@ #include // The current version number for the message format -#define MSG_VERSION 2 +#define MSG_VERSION 2 // TODO: Implement more message types -#define MSG_TYPE_DATA 0 // Message contains float values -#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case -#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case +#define MSG_TYPE_DATA 0 // Message contains float values +#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case +#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case // The total size in bytes of a message -#define MSG_LEN(values) (sizeof(struct msg) + MSG_DATA_LEN(values)) +#define MSG_LEN(values) (sizeof(struct msg) + MSG_DATA_LEN(values)) // The length of \p values values in bytes -#define MSG_DATA_LEN(values) (sizeof(float) * (values)) +#define MSG_DATA_LEN(values) (sizeof(float) * (values)) // The offset to the first data value in a message -#define MSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct msg, data)) +#define MSG_DATA_OFFSET(msg) ((char *)(msg) + offsetof(struct msg, data)) // Initialize a message with default values -#define MSG_INIT(len, seq) (struct msg) {\ - .version = MSG_VERSION, \ - .type = MSG_TYPE_DATA, \ - .length = len, \ - .sequence = seq, \ - .id = 0 \ -} +#define MSG_INIT(len, seq) \ + (struct msg) { \ + .version = MSG_VERSION, .type = MSG_TYPE_DATA, .length = len, \ + .sequence = seq, .id = 0 \ + } // The timestamp of a message in struct timespec format -#define MSG_TS(msg) (struct timespec) { \ - .tv_sec = (msg)->ts.sec, \ - .tv_nsec = (msg)->ts.nsec \ -} +#define MSG_TS(msg) \ + (struct timespec) { .tv_sec = (msg)->ts.sec, .tv_nsec = (msg)->ts.nsec } // This message format is used by all clients -struct msg -{ +struct msg { #if BYTE_ORDER == BIG_ENDIAN - unsigned version: 4; // Specifies the format of the remaining message (see MGS_VERSION) - unsigned type : 2; // Data or control message (see MSG_TYPE_*) - unsigned reserved1 : 2; // Reserved bits + unsigned + version : 4; // Specifies the format of the remaining message (see MGS_VERSION) + unsigned type : 2; // Data or control message (see MSG_TYPE_*) + unsigned reserved1 : 2; // Reserved bits #elif BYTE_ORDER == LITTLE_ENDIAN - unsigned reserved1 : 2; // Reserved bits - unsigned type : 2; // Data or control message (see MSG_TYPE_*) - unsigned version: 4; // Specifies the format of the remaining message (see MGS_VERSION) + unsigned reserved1 : 2; // Reserved bits + unsigned type : 2; // Data or control message (see MSG_TYPE_*) + unsigned + version : 4; // Specifies the format of the remaining message (see MGS_VERSION) #else - #error Invalid byte-order +#error Invalid byte-order #endif // BYTEORDER - uint8_t id; // An id which identifies the source of this sample - uint16_t length; // The number of values in msg::data[] - uint32_t sequence; // The sequence number is incremented by one for consecutive messages + uint8_t id; // An id which identifies the source of this sample + uint16_t length; // The number of values in msg::data[] + uint32_t + sequence; // The sequence number is incremented by one for consecutive messages - // A timestamp per message - struct { - uint32_t sec; // Seconds since 1970-01-01 00:00:00 - uint32_t nsec; // Nanoseconds of the current second - } ts; + // A timestamp per message + struct { + uint32_t sec; // Seconds since 1970-01-01 00:00:00 + uint32_t nsec; // Nanoseconds of the current second + } ts; - // The message payload - union { - float f; // Floating point values - uint32_t i; // Integer values - } data[]; + // The message payload + union { + float f; // Floating point values + uint32_t i; // Integer values + } data[]; } __attribute__((packed)); diff --git a/clients/opal/models/send_receive/include/socket.h b/clients/opal/models/send_receive/include/socket.h index 372ad6ce2..427ce28a9 100644 --- a/clients/opal/models/send_receive/include/socket.h +++ b/clients/opal/models/send_receive/include/socket.h @@ -13,13 +13,13 @@ #define RT #include "OpalGenAsyncParamCtrl.h" -#define UDP_PROTOCOL 1 -#define TCP_PROTOCOL 2 +#define UDP_PROTOCOL 1 +#define TCP_PROTOCOL 2 struct socket { - struct sockaddr_in send_ad; // Send address - struct sockaddr_in recv_ad; // Receive address - int sd; // socket descriptor + struct sockaddr_in send_ad; // Send address + struct sockaddr_in recv_ad; // Receive address + int sd; // socket descriptor }; int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct); diff --git a/clients/opal/models/send_receive/src/compat.c b/clients/opal/models/send_receive/src/compat.c index e68c73b26..d127fcca3 100644 --- a/clients/opal/models/send_receive/src/compat.c +++ b/clients/opal/models/send_receive/src/compat.c @@ -9,27 +9,21 @@ #include -size_t __intel_sse2_strlen(const char *s) -{ - return strlen(s); +size_t __intel_sse2_strlen(const char *s) { return strlen(s); } + +void *_intel_fast_memset(void *b, int c, size_t len) { + return memset(b, c, len); } -void * _intel_fast_memset(void *b, int c, size_t len) -{ - return memset(b, c, len); +void *_intel_fast_memcpy(void *restrict dst, const void *restrict src, + size_t n) { + return memcpy(dst, src, n); } -void * _intel_fast_memcpy(void *restrict dst, const void *restrict src, size_t n) -{ - return memcpy(dst, src, n); +int _intel_fast_memcmp(const void *s1, const void *s2, size_t n) { + return memcmp(s1, s2, n); } -int _intel_fast_memcmp(const void *s1, const void *s2, size_t n) -{ - return memcmp(s1, s2, n); -} - -void * _intel_fast_memmove(void *dest, const void *src, size_t num) -{ - return memmove(dest, src, num); +void *_intel_fast_memmove(void *dest, const void *src, size_t num) { + return memmove(dest, src, num); } diff --git a/clients/opal/models/send_receive/src/main.c b/clients/opal/models/send_receive/src/main.c index 5714a4f86..147196f80 100644 --- a/clients/opal/models/send_receive/src/main.c +++ b/clients/opal/models/send_receive/src/main.c @@ -6,22 +6,22 @@ */ // Standard ANSI C headers needed for this program -#include -#include -#include #include #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include /* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ #define RTLAB -#include "OpalPrint.h" #include "AsyncApi.h" +#include "OpalPrint.h" // This is the message format #include "config.h" @@ -29,322 +29,334 @@ #include "utils.h" #if PROTOCOL == VILLAS - #include "msg.h" - #include "msg_format.h" +#include "msg.h" +#include "msg_format.h" #endif /* This is just for initializing the shared memory access to communicate * with the RT-LAB model. It's easier to remember the arguments like this */ -#define ASYNC_SHMEM_NAME argv[1] -#define ASYNC_SHMEM_SIZE atoi(argv[2]) -#define PRINT_SHMEM_NAME argv[3] +#define ASYNC_SHMEM_NAME argv[1] +#define ASYNC_SHMEM_SIZE atoi(argv[2]) +#define PRINT_SHMEM_NAME argv[3] // Global Variables struct socket skt; -static -void * SendToIPPort(void *arg) -{ - unsigned int ModelState, SendID, Sequence = 0; - int nbSend = 0, ret, cnt, len; +static void *SendToIPPort(void *arg) { + unsigned int ModelState, SendID, Sequence = 0; + int nbSend = 0, ret, cnt, len; - // Data from OPAL-RT model - double mdldata[MAX_VALUES]; - int mdldata_size; + // Data from OPAL-RT model + double mdldata[MAX_VALUES]; + int mdldata_size; #if PROTOCOL == VILLAS - char buf[MSG_LEN(MAX_VALUES)]; - struct msg *msg = (struct msg *) buf; + char buf[MSG_LEN(MAX_VALUES)]; + struct msg *msg = (struct msg *)buf; #elif PROTOCOL == GTNET_SKT - char buf[MAX_VALUES * sizeof(float)]; - float *msg = (float *) buf; + char buf[MAX_VALUES * sizeof(float)]; + float *msg = (float *)buf; #endif - OpalPrint("%s: SendToIPPort thread started\n", PROGNAME); + OpalPrint("%s: SendToIPPort thread started\n", PROGNAME); - OpalGetNbAsyncSendIcon(&nbSend); - if (nbSend < 1) { - OpalPrint("%s: SendToIPPort: No transimission block for this controller. Stopping thread.\n", PROGNAME); - return NULL; - } + OpalGetNbAsyncSendIcon(&nbSend); + if (nbSend < 1) { + OpalPrint("%s: SendToIPPort: No transimission block for this controller. " + "Stopping thread.\n", + PROGNAME); + return NULL; + } - do { - // This call unblocks when the 'Data Ready' line of a send icon is asserted. - ret = OpalWaitForAsyncSendRequest(&SendID); - if (ret != EOK) { - ModelState = OpalGetAsyncModelState(); - if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) { - OpalSetAsyncSendIconError(ret, SendID); - OpalPrint("%s: OpalWaitForAsyncSendRequest(), errno %d\n", PROGNAME, ret); - } + do { + // This call unblocks when the 'Data Ready' line of a send icon is asserted. + ret = OpalWaitForAsyncSendRequest(&SendID); + if (ret != EOK) { + ModelState = OpalGetAsyncModelState(); + if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) { + OpalSetAsyncSendIconError(ret, SendID); + OpalPrint("%s: OpalWaitForAsyncSendRequest(), errno %d\n", PROGNAME, + ret); + } - continue; - } + continue; + } - // No errors encountered yet - OpalSetAsyncSendIconError(0, SendID); + // No errors encountered yet + OpalSetAsyncSendIconError(0, SendID); - // Get the size of the data being sent by the unblocking SendID - OpalGetAsyncSendIconDataLength(&mdldata_size, SendID); - cnt = mdldata_size / sizeof(double); - if (cnt > MAX_VALUES) { - OpalPrint("%s: Number of signals for SendID=%d exceeds allowed maximum (%d). Limiting...\n", - PROGNAME, SendID, MAX_VALUES); - cnt = MAX_VALUES; - } + // Get the size of the data being sent by the unblocking SendID + OpalGetAsyncSendIconDataLength(&mdldata_size, SendID); + cnt = mdldata_size / sizeof(double); + if (cnt > MAX_VALUES) { + OpalPrint("%s: Number of signals for SendID=%d exceeds allowed maximum " + "(%d). Limiting...\n", + PROGNAME, SendID, MAX_VALUES); + cnt = MAX_VALUES; + } - // Read data from the model - OpalGetAsyncSendIconData(mdldata, mdldata_size, SendID); + // Read data from the model + OpalGetAsyncSendIconData(mdldata, mdldata_size, SendID); #if PROTOCOL == VILLAS - // Get current time - struct timespec now; - clock_gettime(CLOCK_REALTIME, &now); + // Get current time + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); - msg->version = MSG_VERSION; - msg->type = MSG_TYPE_DATA; - msg->reserved1 = 0; - msg->id = SendID; - msg->length = cnt; - msg->sequence = Sequence++; - msg->ts.sec = now.tv_sec; - msg->ts.nsec = now.tv_nsec; + msg->version = MSG_VERSION; + msg->type = MSG_TYPE_DATA; + msg->reserved1 = 0; + msg->id = SendID; + msg->length = cnt; + msg->sequence = Sequence++; + msg->ts.sec = now.tv_sec; + msg->ts.nsec = now.tv_nsec; - for (int i = 0; i < msg->length; i++) - msg->data[i].f = (float) mdldata[i]; + for (int i = 0; i < msg->length; i++) + msg->data[i].f = (float)mdldata[i]; - len = MSG_LEN(msg->length); + len = MSG_LEN(msg->length); - msg_hton(msg); + msg_hton(msg); #elif PROTOCOL == GTNET_SKT - uint32_t *imsg = (uint32_t *) msg; - for (int i = 0; i < cnt; i++) { - msg[i] = (float) mdldata[i]; - imsg[i] = htonl(imsg[i]); - } + uint32_t *imsg = (uint32_t *)msg; + for (int i = 0; i < cnt; i++) { + msg[i] = (float)mdldata[i]; + imsg[i] = htonl(imsg[i]); + } - len = cnt * sizeof(float); + len = cnt * sizeof(float); #else - #error Unknown protocol +#error Unknown protocol #endif - // Perform the actual write to the ip port - ret = socket_send(&skt, (char *) msg, len); - if (ret < 0) - OpalSetAsyncSendIconError(errno, SendID); - else - OpalSetAsyncSendIconError(0, SendID); + // Perform the actual write to the ip port + ret = socket_send(&skt, (char *)msg, len); + if (ret < 0) + OpalSetAsyncSendIconError(errno, SendID); + else + OpalSetAsyncSendIconError(0, SendID); - /* This next call allows the execution of the "asynchronous" process + /* This next call allows the execution of the "asynchronous" process * to actually be synchronous with the model. To achieve this, you * should set the "Sending Mode" in the Async_Send block to * NEED_REPLY_BEFORE_NEXT_SEND or NEED_REPLY_NOW. This will force * the model to wait for this process to call this * OpalAsyncSendRequestDone function before continuing. */ - OpalAsyncSendRequestDone(SendID); + OpalAsyncSendRequestDone(SendID); - /* Before continuing, we make sure that the real-time model + /* Before continuing, we make sure that the real-time model * has not been stopped. If it has, we quit. */ - ModelState = OpalGetAsyncModelState(); - } while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)); + ModelState = OpalGetAsyncModelState(); + } while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)); - OpalPrint("%s: SendToIPPort: Finished\n", PROGNAME); + OpalPrint("%s: SendToIPPort: Finished\n", PROGNAME); - return NULL; + return NULL; } -static -void * RecvFromIPPort(void *arg) -{ - unsigned int ModelState, RecvID; - int nbRecv = 0, ret, cnt; +static void *RecvFromIPPort(void *arg) { + unsigned int ModelState, RecvID; + int nbRecv = 0, ret, cnt; - // Data from OPAL-RT model - double mdldata[MAX_VALUES]; - int mdldata_size; + // Data from OPAL-RT model + double mdldata[MAX_VALUES]; + int mdldata_size; #if PROTOCOL == VILLAS - char buf[MSG_LEN(MAX_VALUES)]; - struct msg *msg = (struct msg *) buf; + char buf[MSG_LEN(MAX_VALUES)]; + struct msg *msg = (struct msg *)buf; #elif PROTOCOL == GTNET_SKT - char buf[MAX_VALUES * sizeof(float)]; - float *msg = (float *) buf; + char buf[MAX_VALUES * sizeof(float)]; + float *msg = (float *)buf; #else - #error Unknown protocol +#error Unknown protocol #endif - OpalPrint("%s: RecvFromIPPort thread started\n", PROGNAME); + OpalPrint("%s: RecvFromIPPort thread started\n", PROGNAME); - OpalGetNbAsyncRecvIcon(&nbRecv); - if (nbRecv < 1) { - OpalPrint("%s: RecvFromIPPort: No reception block for this controller. Stopping thread.\n", PROGNAME); - return NULL; - } + OpalGetNbAsyncRecvIcon(&nbRecv); + if (nbRecv < 1) { + OpalPrint("%s: RecvFromIPPort: No reception block for this controller. " + "Stopping thread.\n", + PROGNAME); + return NULL; + } - // Get list of RecvIds - unsigned int RecvIDs[nbRecv]; - ret = OpalGetAsyncRecvIDList(RecvIDs, sizeof(RecvIDs)); - if (ret != EOK) { - OpalPrint("%s: Failed to get list of RecvIDs\n", PROGNAME); - return NULL; - } + // Get list of RecvIds + unsigned int RecvIDs[nbRecv]; + ret = OpalGetAsyncRecvIDList(RecvIDs, sizeof(RecvIDs)); + if (ret != EOK) { + OpalPrint("%s: Failed to get list of RecvIDs\n", PROGNAME); + return NULL; + } - do { - // Receive message - ret = socket_recv(&skt, (char *) msg, sizeof(buf), 1.0); - if (ret < 1) { - ModelState = OpalGetAsyncModelState(); - if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) { - if (ret == 0) // timeout, so we continue silently - OpalPrint("%s: Timeout while waiting for data\n", PROGNAME, errno); - if (ret == -1) // a more serious error, so we print it - OpalPrint("%s: Error %d while waiting for data\n", PROGNAME, errno); + do { + // Receive message + ret = socket_recv(&skt, (char *)msg, sizeof(buf), 1.0); + if (ret < 1) { + ModelState = OpalGetAsyncModelState(); + if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) { + if (ret == 0) // timeout, so we continue silently + OpalPrint("%s: Timeout while waiting for data\n", PROGNAME, errno); + if (ret == -1) // a more serious error, so we print it + OpalPrint("%s: Error %d while waiting for data\n", PROGNAME, errno); - continue; - } - break; - } + continue; + } + break; + } #if PROTOCOL == VILLAS - RecvID = msg->id; + RecvID = msg->id; #elif PROTOCOL == GTNET_SKT - RecvID = 1; + RecvID = 1; #else - #error Unknown protocol +#error Unknown protocol #endif - // Check if this RecvID exists - for (int i = 0; i < nbRecv; i++) { - if (RecvIDs[i] == RecvID) - goto found; - } + // Check if this RecvID exists + for (int i = 0; i < nbRecv; i++) { + if (RecvIDs[i] == RecvID) + goto found; + } - OpalPrint("%s: Received message with non-existent RecvID=%d. Changing to RecvID=%d...\n", PROGNAME, RecvID, RecvIDs[0]); - RecvID = RecvIDs[0]; + OpalPrint("%s: Received message with non-existent RecvID=%d. Changing to " + "RecvID=%d...\n", + PROGNAME, RecvID, RecvIDs[0]); + RecvID = RecvIDs[0]; -found: // Get the number of signals to send back to the model - OpalGetAsyncRecvIconDataLength(&mdldata_size, RecvID); - cnt = mdldata_size / sizeof(double); - if (cnt > MAX_VALUES) { - OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds allowed maximum (%d)\n", - PROGNAME, RecvID, cnt, MAX_VALUES); - return NULL; - } + found: // Get the number of signals to send back to the model + OpalGetAsyncRecvIconDataLength(&mdldata_size, RecvID); + cnt = mdldata_size / sizeof(double); + if (cnt > MAX_VALUES) { + OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds allowed " + "maximum (%d)\n", + PROGNAME, RecvID, cnt, MAX_VALUES); + return NULL; + } #if PROTOCOL == VILLAS - msg_ntoh(msg); + msg_ntoh(msg); - ret = msg_verify(msg); - if (ret) { - OpalPrint("%s: Skipping invalid packet\n", PROGNAME); - continue; - } + ret = msg_verify(msg); + if (ret) { + OpalPrint("%s: Skipping invalid packet\n", PROGNAME); + continue; + } - if (cnt > msg->length) { - OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds what was received (%d)\n", - PROGNAME, RecvID, cnt, msg->length); - } + if (cnt > msg->length) { + OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds what was " + "received (%d)\n", + PROGNAME, RecvID, cnt, msg->length); + } - for (int i = 0; i < msg->length; i++) - mdldata[i] = (double) msg->data[i].f; + for (int i = 0; i < msg->length; i++) + mdldata[i] = (double)msg->data[i].f; - // Update OPAL model - OpalSetAsyncRecvIconStatus(msg->sequence, RecvID); // Set the Status to the message ID + // Update OPAL model + OpalSetAsyncRecvIconStatus(msg->sequence, + RecvID); // Set the Status to the message ID #elif PROTOCOL == GTNET_SKT - uint32_t *imsg = (uint32_t *) msg; - for (int i = 0; i < cnt; i++) { - imsg[i] = ntohl(imsg[i]); - mdldata[i] = (double) msg[i]; - } + uint32_t *imsg = (uint32_t *)msg; + for (int i = 0; i < cnt; i++) { + imsg[i] = ntohl(imsg[i]); + mdldata[i] = (double)msg[i]; + } #else - #error Unknown protocol +#error Unknown protocol #endif - OpalSetAsyncRecvIconError(0, RecvID); // Set the Error to 0 + OpalSetAsyncRecvIconError(0, RecvID); // Set the Error to 0 - OpalSetAsyncRecvIconData(mdldata, mdldata_size, RecvID); + OpalSetAsyncRecvIconData(mdldata, mdldata_size, RecvID); - /* Before continuing, we make sure that the real-time model + /* Before continuing, we make sure that the real-time model * has not been stopped. If it has, we quit. */ - ModelState = OpalGetAsyncModelState(); - } while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)); + ModelState = OpalGetAsyncModelState(); + } while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)); - OpalPrint("%s: RecvFromIPPort: Finished\n", PROGNAME); + OpalPrint("%s: RecvFromIPPort: Finished\n", PROGNAME); - return NULL; + return NULL; } -int main(int argc, char *argv[]) -{ - int ret; +int main(int argc, char *argv[]) { + int ret; - Opal_GenAsyncParam_Ctrl IconCtrlStruct; + Opal_GenAsyncParam_Ctrl IconCtrlStruct; - pthread_t tid_send, tid_recv; + pthread_t tid_send, tid_recv; - OpalPrint("%s: This is %s client version %s\n", PROGNAME, PROGNAME, VERSION); + OpalPrint("%s: This is %s client version %s\n", PROGNAME, PROGNAME, VERSION); - // Check for the proper arguments to the program - if (argc < 4) { - printf("Invalid Arguments: 1-AsyncShmemName 2-AsyncShmemSize 3-PrintShmemName\n"); - exit(0); - } + // Check for the proper arguments to the program + if (argc < 4) { + printf("Invalid Arguments: 1-AsyncShmemName 2-AsyncShmemSize " + "3-PrintShmemName\n"); + exit(0); + } - // Enable the OpalPrint function. This prints to the OpalDisplay. - ret = OpalSystemCtrl_Register(PRINT_SHMEM_NAME); - if (ret != EOK) { - printf("%s: ERROR: OpalPrint() access not available\n", PROGNAME); - exit(EXIT_FAILURE); - } + // Enable the OpalPrint function. This prints to the OpalDisplay. + ret = OpalSystemCtrl_Register(PRINT_SHMEM_NAME); + if (ret != EOK) { + printf("%s: ERROR: OpalPrint() access not available\n", PROGNAME); + exit(EXIT_FAILURE); + } - // Open Share Memory created by the model. - ret = OpalOpenAsyncMem(ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); - if (ret != EOK) { - OpalPrint("%s: ERROR: Model shared memory not available\n", PROGNAME); - exit(EXIT_FAILURE); - } + // Open Share Memory created by the model. + ret = OpalOpenAsyncMem(ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); + if (ret != EOK) { + OpalPrint("%s: ERROR: Model shared memory not available\n", PROGNAME); + exit(EXIT_FAILURE); + } - AssignProcToCpu0(); + AssignProcToCpu0(); - /* Get IP Controler Parameters (ie: ip address, port number...) and + /* Get IP Controler Parameters (ie: ip address, port number...) and * initialize the device on the QNX node. */ - memset(&IconCtrlStruct, 0, sizeof(IconCtrlStruct)); + memset(&IconCtrlStruct, 0, sizeof(IconCtrlStruct)); - ret = OpalGetAsyncCtrlParameters(&IconCtrlStruct, sizeof(IconCtrlStruct)); - if (ret != EOK) { - OpalPrint("%s: ERROR: Could not get controller parameters (%d).\n", PROGNAME, ret); - exit(EXIT_FAILURE); - } + ret = OpalGetAsyncCtrlParameters(&IconCtrlStruct, sizeof(IconCtrlStruct)); + if (ret != EOK) { + OpalPrint("%s: ERROR: Could not get controller parameters (%d).\n", + PROGNAME, ret); + exit(EXIT_FAILURE); + } - // Initialize socket - ret = socket_init(&skt, IconCtrlStruct); - if (ret != EOK) { - OpalPrint("%s: ERROR: Failed to create socket.\n", PROGNAME); - exit(EXIT_FAILURE); - } + // Initialize socket + ret = socket_init(&skt, IconCtrlStruct); + if (ret != EOK) { + OpalPrint("%s: ERROR: Failed to create socket.\n", PROGNAME); + exit(EXIT_FAILURE); + } - // Start send/receive threads - ret = pthread_create(&tid_send, NULL, SendToIPPort, NULL); - if (ret < 0) - OpalPrint("%s: ERROR: Could not create thread (SendToIPPort), errno %d\n", PROGNAME, errno); + // Start send/receive threads + ret = pthread_create(&tid_send, NULL, SendToIPPort, NULL); + if (ret < 0) + OpalPrint("%s: ERROR: Could not create thread (SendToIPPort), errno %d\n", + PROGNAME, errno); - ret = pthread_create(&tid_recv, NULL, RecvFromIPPort, NULL); - if (ret < 0) - OpalPrint("%s: ERROR: Could not create thread (RecvFromIPPort), errno %d\n", PROGNAME, errno); + ret = pthread_create(&tid_recv, NULL, RecvFromIPPort, NULL); + if (ret < 0) + OpalPrint("%s: ERROR: Could not create thread (RecvFromIPPort), errno %d\n", + PROGNAME, errno); - // Wait for both threads to finish - ret = pthread_join(tid_send, NULL); - if (ret) - OpalPrint("%s: ERROR: pthread_join (SendToIPPort), errno %d\n", PROGNAME, ret); + // Wait for both threads to finish + ret = pthread_join(tid_send, NULL); + if (ret) + OpalPrint("%s: ERROR: pthread_join (SendToIPPort), errno %d\n", PROGNAME, + ret); - ret = pthread_join(tid_recv, NULL); - if (ret) - OpalPrint("%s: ERROR: pthread_join (RecvFromIPPort), errno %d\n", PROGNAME, ret); + ret = pthread_join(tid_recv, NULL); + if (ret) + OpalPrint("%s: ERROR: pthread_join (RecvFromIPPort), errno %d\n", PROGNAME, + ret); - // Close the ip port and shared memories - socket_close(&skt, IconCtrlStruct); + // Close the ip port and shared memories + socket_close(&skt, IconCtrlStruct); - OpalCloseAsyncMem (ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); - OpalSystemCtrl_UnRegister(PRINT_SHMEM_NAME); + OpalCloseAsyncMem(ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME); + OpalSystemCtrl_UnRegister(PRINT_SHMEM_NAME); - return 0; + return 0; } diff --git a/clients/opal/models/send_receive/src/msg.c b/clients/opal/models/send_receive/src/msg.c index d07252191..d966b5fb4 100644 --- a/clients/opal/models/send_receive/src/msg.c +++ b/clients/opal/models/send_receive/src/msg.c @@ -10,46 +10,41 @@ #include "msg.h" #include "msg_format.h" -void msg_ntoh(struct msg *m) -{ - msg_hdr_ntoh(m); +void msg_ntoh(struct msg *m) { + msg_hdr_ntoh(m); - for (int i = 0; i < m->length; i++) - m->data[i].i = ntohl(m->data[i].i); + for (int i = 0; i < m->length; i++) + m->data[i].i = ntohl(m->data[i].i); } -void msg_hton(struct msg *m) -{ - for (int i = 0; i < m->length; i++) - m->data[i].i = htonl(m->data[i].i); +void msg_hton(struct msg *m) { + for (int i = 0; i < m->length; i++) + m->data[i].i = htonl(m->data[i].i); - msg_hdr_hton(m); + msg_hdr_hton(m); } -void msg_hdr_hton(struct msg *m) -{ - m->length = htons(m->length); - m->sequence = htonl(m->sequence); - m->ts.sec = htonl(m->ts.sec); - m->ts.nsec = htonl(m->ts.nsec); +void msg_hdr_hton(struct msg *m) { + m->length = htons(m->length); + m->sequence = htonl(m->sequence); + m->ts.sec = htonl(m->ts.sec); + m->ts.nsec = htonl(m->ts.nsec); } -void msg_hdr_ntoh(struct msg *m) -{ - m->length = ntohs(m->length); - m->sequence = ntohl(m->sequence); - m->ts.sec = ntohl(m->ts.sec); - m->ts.nsec = ntohl(m->ts.nsec); +void msg_hdr_ntoh(struct msg *m) { + m->length = ntohs(m->length); + m->sequence = ntohl(m->sequence); + m->ts.sec = ntohl(m->ts.sec); + m->ts.nsec = ntohl(m->ts.nsec); } -int msg_verify(struct msg *m) -{ - if (m->version != MSG_VERSION) - return -1; - else if (m->type != MSG_TYPE_DATA) - return -2; - else if (m->reserved1 != 0) - return -3; - else - return 0; +int msg_verify(struct msg *m) { + if (m->version != MSG_VERSION) + return -1; + else if (m->type != MSG_TYPE_DATA) + return -2; + else if (m->reserved1 != 0) + return -3; + else + return 0; } diff --git a/clients/opal/models/send_receive/src/socket.c b/clients/opal/models/send_receive/src/socket.c index a4d314b3e..77cc5ec3b 100644 --- a/clients/opal/models/send_receive/src/socket.c +++ b/clients/opal/models/send_receive/src/socket.c @@ -5,165 +5,177 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include /* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ #define RTLAB -#include "OpalPrint.h" #include "AsyncApi.h" +#include "OpalPrint.h" #include "config.h" #include "socket.h" -int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) -{ - struct ip_mreq mreq; // Multicast group structure - unsigned char TTL = 1, LOOP = 0; - int rc, proto, ret; +int socket_init(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) { + struct ip_mreq mreq; // Multicast group structure + unsigned char TTL = 1, LOOP = 0; + int rc, proto, ret; - proto = (int) IconCtrlStruct.FloatParam[0]; - if (proto != UDP_PROTOCOL) { - OpalPrint("%s: This version of %s only supports UDP\n", PROGNAME, PROGNAME); - return EIO; - } + proto = (int)IconCtrlStruct.FloatParam[0]; + if (proto != UDP_PROTOCOL) { + OpalPrint("%s: This version of %s only supports UDP\n", PROGNAME, PROGNAME); + return EIO; + } - OpalPrint("%s: Version : %s\n", PROGNAME, VERSION); - OpalPrint("%s: Remote Address : %s\n", PROGNAME, IconCtrlStruct.StringParam[0]); - OpalPrint("%s: Remote Port : %d\n", PROGNAME, (int) IconCtrlStruct.FloatParam[1]); + OpalPrint("%s: Version : %s\n", PROGNAME, VERSION); + OpalPrint("%s: Remote Address : %s\n", PROGNAME, + IconCtrlStruct.StringParam[0]); + OpalPrint("%s: Remote Port : %d\n", PROGNAME, + (int)IconCtrlStruct.FloatParam[1]); - // Initialize the socket - s->sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (s->sd < 0) { - OpalPrint("%s: ERROR: Could not open socket\n", PROGNAME); - return EIO; - } + // Initialize the socket + s->sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (s->sd < 0) { + OpalPrint("%s: ERROR: Could not open socket\n", PROGNAME); + return EIO; + } - // Set the structure for the remote port and address - memset(&s->send_ad, 0, sizeof(s->send_ad)); - s->send_ad.sin_family = AF_INET; - s->send_ad.sin_addr.s_addr = inet_addr(IconCtrlStruct.StringParam[0]); - s->send_ad.sin_port = htons((u_short) IconCtrlStruct.FloatParam[1]); + // Set the structure for the remote port and address + memset(&s->send_ad, 0, sizeof(s->send_ad)); + s->send_ad.sin_family = AF_INET; + s->send_ad.sin_addr.s_addr = inet_addr(IconCtrlStruct.StringParam[0]); + s->send_ad.sin_port = htons((u_short)IconCtrlStruct.FloatParam[1]); - // Set the structure for the local port and address - memset(&s->recv_ad, 0, sizeof(s->recv_ad)); - s->recv_ad.sin_family = AF_INET; - s->recv_ad.sin_addr.s_addr = INADDR_ANY; - s->recv_ad.sin_port = htons((u_short) IconCtrlStruct.FloatParam[2]); + // Set the structure for the local port and address + memset(&s->recv_ad, 0, sizeof(s->recv_ad)); + s->recv_ad.sin_family = AF_INET; + s->recv_ad.sin_addr.s_addr = INADDR_ANY; + s->recv_ad.sin_port = htons((u_short)IconCtrlStruct.FloatParam[2]); - // Bind local port and address to socket. - ret = bind(s->sd, (struct sockaddr *) &s->recv_ad, sizeof(struct sockaddr_in)); - if (ret < 0) { - OpalPrint("%s: ERROR: Could not bind local port to socket\n", PROGNAME); - return EIO; - } - else - OpalPrint("%s: Local Port : %d\n", PROGNAME, (int) IconCtrlStruct.FloatParam[2]); + // Bind local port and address to socket. + ret = bind(s->sd, (struct sockaddr *)&s->recv_ad, sizeof(struct sockaddr_in)); + if (ret < 0) { + OpalPrint("%s: ERROR: Could not bind local port to socket\n", PROGNAME); + return EIO; + } else + OpalPrint("%s: Local Port : %d\n", PROGNAME, + (int)IconCtrlStruct.FloatParam[2]); - // If sending to a multicast address - if ((inet_addr(IconCtrlStruct.StringParam[0]) & inet_addr("240.0.0.0")) == inet_addr("224.0.0.0")) { - ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &TTL, sizeof(TTL)); - if (ret == -1) { - OpalPrint("%s: ERROR: Could not set TTL for multicast send (%d)\n", PROGNAME, errno); - return EIO; - } + // If sending to a multicast address + if ((inet_addr(IconCtrlStruct.StringParam[0]) & inet_addr("240.0.0.0")) == + inet_addr("224.0.0.0")) { + ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&TTL, + sizeof(TTL)); + if (ret == -1) { + OpalPrint("%s: ERROR: Could not set TTL for multicast send (%d)\n", + PROGNAME, errno); + return EIO; + } - ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&LOOP, sizeof(LOOP)); - if (ret == -1) { - OpalPrint("%s: ERROR: Could not set loopback for multicast send (%d)\n", PROGNAME, errno); - return EIO; - } + ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&LOOP, + sizeof(LOOP)); + if (ret == -1) { + OpalPrint("%s: ERROR: Could not set loopback for multicast send (%d)\n", + PROGNAME, errno); + return EIO; + } - OpalPrint("%s: Configured socket for sending to multicast address\n", PROGNAME); - } + OpalPrint("%s: Configured socket for sending to multicast address\n", + PROGNAME); + } - // If receiving from a multicast group, register for it. - if (inet_addr(IconCtrlStruct.StringParam[1]) > 0) { - if ((inet_addr(IconCtrlStruct.StringParam[1]) & inet_addr("240.0.0.0")) == inet_addr("224.0.0.0")) { - mreq.imr_multiaddr.s_addr = inet_addr(IconCtrlStruct.StringParam[1]); - mreq.imr_interface.s_addr = INADDR_ANY; + // If receiving from a multicast group, register for it. + if (inet_addr(IconCtrlStruct.StringParam[1]) > 0) { + if ((inet_addr(IconCtrlStruct.StringParam[1]) & inet_addr("240.0.0.0")) == + inet_addr("224.0.0.0")) { + mreq.imr_multiaddr.s_addr = inet_addr(IconCtrlStruct.StringParam[1]); + mreq.imr_interface.s_addr = INADDR_ANY; - // Have the multicast socket join the multicast group - ret = setsockopt(s->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq)); - if (ret == -1) { - OpalPrint("%s: ERROR: Could not join multicast group (%d)\n", PROGNAME, errno); - return EIO; - } + // Have the multicast socket join the multicast group + ret = setsockopt(s->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, + sizeof(mreq)); + if (ret == -1) { + OpalPrint("%s: ERROR: Could not join multicast group (%d)\n", PROGNAME, + errno); + return EIO; + } - OpalPrint("%s: Added process to multicast group (%s)\n", PROGNAME, IconCtrlStruct.StringParam[1]); - } - else - OpalPrint("%s: WARNING: IP address for multicast group is not in multicast range. Ignored\n", PROGNAME); - } + OpalPrint("%s: Added process to multicast group (%s)\n", PROGNAME, + IconCtrlStruct.StringParam[1]); + } else + OpalPrint("%s: WARNING: IP address for multicast group is not in " + "multicast range. Ignored\n", + PROGNAME); + } - return EOK; + return EOK; } -int socket_close(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) -{ - int ret; +int socket_close(struct socket *s, Opal_GenAsyncParam_Ctrl IconCtrlStruct) { + int ret; - ret = shutdown(s->sd, SHUT_RDWR); - if (ret) - return ret; + ret = shutdown(s->sd, SHUT_RDWR); + if (ret) + return ret; - ret = close(s->sd); - if (ret) - return ret; + ret = close(s->sd); + if (ret) + return ret; - return 0; + return 0; } -int socket_send(struct socket *s, char *data, int len) -{ - return sendto(s->sd, data, len, 0, (struct sockaddr *) &s->send_ad, sizeof(s->send_ad)); +int socket_send(struct socket *s, char *data, int len) { + return sendto(s->sd, data, len, 0, (struct sockaddr *)&s->send_ad, + sizeof(s->send_ad)); } -int socket_recv(struct socket *s, char *data, int len, double timeout) -{ - int ret; - struct sockaddr_in client_ad; - struct timeval tv; - socklen_t client_ad_size = sizeof(client_ad); - fd_set sd_set; +int socket_recv(struct socket *s, char *data, int len, double timeout) { + int ret; + struct sockaddr_in client_ad; + struct timeval tv; + socklen_t client_ad_size = sizeof(client_ad); + fd_set sd_set; - // Set the descriptor set for the select() call - FD_ZERO(&sd_set); - FD_SET(s->sd, &sd_set); + // Set the descriptor set for the select() call + FD_ZERO(&sd_set); + FD_SET(s->sd, &sd_set); - // Set the tv structure to the correct timeout value - tv.tv_sec = (int) timeout; - tv.tv_usec = (int) ((timeout - tv.tv_sec) * 1000000); + // Set the tv structure to the correct timeout value + tv.tv_sec = (int)timeout; + tv.tv_usec = (int)((timeout - tv.tv_sec) * 1000000); - /* Wait for a packet. We use select() to have a timeout. This is + /* Wait for a packet. We use select() to have a timeout. This is * necessary when reseting the model so we don't wait indefinitely * and prevent the process from exiting and freeing the port for * a future instance (model load). */ - ret = select(s->sd + 1, &sd_set, (fd_set *) 0, (fd_set *) 0, &tv); - switch (ret) { - case -1: // Error - return -1; - case 0: // We hit the timeout - return 0; - default: - if (!(FD_ISSET(s->sd, &sd_set))) { - /* We received something, but it's not on "sd". Since sd is the only + ret = select(s->sd + 1, &sd_set, (fd_set *)0, (fd_set *)0, &tv); + switch (ret) { + case -1: // Error + return -1; + case 0: // We hit the timeout + return 0; + default: + if (!(FD_ISSET(s->sd, &sd_set))) { + /* We received something, but it's not on "sd". Since sd is the only * descriptor in the set... */ - OpalPrint("%s: RecvPacket: God, is that You trying to reach me?\n", PROGNAME); - return -1; - } - } + OpalPrint("%s: RecvPacket: God, is that You trying to reach me?\n", + PROGNAME); + return -1; + } + } - // Clear the data array (in case we receive an incomplete packet) - memset(data, 0, len); + // Clear the data array (in case we receive an incomplete packet) + memset(data, 0, len); - // Perform the reception - return recvfrom(s->sd, data, len, 0, (struct sockaddr *) &client_ad, &client_ad_size); + // Perform the reception + return recvfrom(s->sd, data, len, 0, (struct sockaddr *)&client_ad, + &client_ad_size); } diff --git a/clients/opal/models/send_receive/src/utils.c b/clients/opal/models/send_receive/src/utils.c index 3015fc344..76e1daa7e 100644 --- a/clients/opal/models/send_receive/src/utils.c +++ b/clients/opal/models/send_receive/src/utils.c @@ -18,20 +18,19 @@ #include "config.h" #include "utils.h" -int AssignProcToCpu0(void) -{ - int ret; - cpu_set_t bindSet; - - CPU_ZERO(&bindSet); - CPU_SET(0, &bindSet); +int AssignProcToCpu0(void) { + int ret; + cpu_set_t bindSet; - // Changing process cpu affinity - ret = sched_setaffinity(0, sizeof(cpu_set_t), &bindSet); - if (ret) { - OpalPrint("Unable to bind the process to CPU 0: %d\n", errno); - return EINVAL; - } + CPU_ZERO(&bindSet); + CPU_SET(0, &bindSet); - return 0; + // Changing process cpu affinity + ret = sched_setaffinity(0, sizeof(cpu_set_t), &bindSet); + if (ret) { + OpalPrint("Unable to bind the process to CPU 0: %d\n", errno); + return EINVAL; + } + + return 0; } diff --git a/clients/shmem/villas-shmem.cpp b/clients/shmem/villas-shmem.cpp index 289970905..0f2f05ca2 100644 --- a/clients/shmem/villas-shmem.cpp +++ b/clients/shmem/villas-shmem.cpp @@ -8,19 +8,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include +#include +#include #include +#include +#include #include #include #include -#include #include -#include #include -#include namespace villas { namespace node { @@ -29,101 +29,94 @@ namespace tools { class Shmem : public Tool { public: - Shmem(int argc, char *argv[]) : - Tool(argc, argv, "shmem"), - stop(false) - { } + Shmem(int argc, char *argv[]) : Tool(argc, argv, "shmem"), stop(false) {} protected: - std::atomic stop; + std::atomic stop; - void usage() - { - std::cout << "Usage: villas-test-shmem WNAME VECTORIZE" << std::endl - << " WNAME name of the shared memory object for the output queue" << std::endl - << " RNAME name of the shared memory object for the input queue" << std::endl - << " VECTORIZE maximum number of samples to read/write at a time" << std::endl; + void usage() { + std::cout + << "Usage: villas-test-shmem WNAME VECTORIZE" << std::endl + << " WNAME name of the shared memory object for the output queue" + << std::endl + << " RNAME name of the shared memory object for the input queue" + << std::endl + << " VECTORIZE maximum number of samples to read/write at a time" + << std::endl; - printCopyright(); - } + printCopyright(); + } - void handler(int, siginfo_t *, void *) - { - stop = true; - } + void handler(int, siginfo_t *, void *) { stop = true; } - int main() - { - int ret, readcnt, writecnt, avail; + int main() { + int ret, readcnt, writecnt, avail; - struct ShmemInterface shm; - struct ShmemConfig conf = { - .polling = 0, - .queuelen = DEFAULT_SHMEM_QUEUELEN, - .samplelen = DEFAULT_SHMEM_SAMPLELEN - }; + struct ShmemInterface shm; + struct ShmemConfig conf = {.polling = 0, + .queuelen = DEFAULT_SHMEM_QUEUELEN, + .samplelen = DEFAULT_SHMEM_SAMPLELEN}; - if (argc != 4) { - usage(); - return 1; - } + if (argc != 4) { + usage(); + return 1; + } - std::string wname = argv[1]; - std::string rname = argv[2]; - int vectorize = atoi(argv[3]); + std::string wname = argv[1]; + std::string rname = argv[2]; + int vectorize = atoi(argv[3]); - ret = shmem_int_open(wname.c_str(), rname.c_str(), &shm, &conf); - if (ret < 0) - throw RuntimeError("Failed to open shared-memory interface"); + ret = shmem_int_open(wname.c_str(), rname.c_str(), &shm, &conf); + if (ret < 0) + throw RuntimeError("Failed to open shared-memory interface"); - struct Sample *insmps[vectorize], *outsmps[vectorize]; + struct Sample *insmps[vectorize], *outsmps[vectorize]; - while (!stop) { - readcnt = shmem_int_read(&shm, insmps, vectorize); - if (readcnt == -1) { - logger->info("Node stopped, exiting"); - break; - } + while (!stop) { + readcnt = shmem_int_read(&shm, insmps, vectorize); + if (readcnt == -1) { + logger->info("Node stopped, exiting"); + break; + } - avail = shmem_int_alloc(&shm, outsmps, readcnt); - if (avail < readcnt) - logger->warn("Pool underrun: {} / {}", avail, readcnt); + avail = shmem_int_alloc(&shm, outsmps, readcnt); + if (avail < readcnt) + logger->warn("Pool underrun: {} / {}", avail, readcnt); - for (int i = 0; i < avail; i++) { - outsmps[i]->sequence = insmps[i]->sequence; - outsmps[i]->ts = insmps[i]->ts; + for (int i = 0; i < avail; i++) { + outsmps[i]->sequence = insmps[i]->sequence; + outsmps[i]->ts = insmps[i]->ts; - int len = MIN(insmps[i]->length, outsmps[i]->capacity); - memcpy(outsmps[i]->data, insmps[i]->data, SAMPLE_DATA_LENGTH(len)); + int len = MIN(insmps[i]->length, outsmps[i]->capacity); + memcpy(outsmps[i]->data, insmps[i]->data, SAMPLE_DATA_LENGTH(len)); - outsmps[i]->length = len; - } + outsmps[i]->length = len; + } - for (int i = 0; i < readcnt; i++) - sample_decref(insmps[i]); + for (int i = 0; i < readcnt; i++) + sample_decref(insmps[i]); - writecnt = shmem_int_write(&shm, outsmps, avail); - if (writecnt < avail) - logger->warn("Short write"); + writecnt = shmem_int_write(&shm, outsmps, avail); + if (writecnt < avail) + logger->warn("Short write"); - logger->info("Read / Write: {}/{}", readcnt, writecnt); - } + logger->info("Read / Write: {}/{}", readcnt, writecnt); + } - ret = shmem_int_close(&shm); - if (ret) - throw RuntimeError("Failed to close shared-memory interface"); + ret = shmem_int_close(&shm); + if (ret) + throw RuntimeError("Failed to close shared-memory interface"); - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Shmem t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Shmem t(argc, argv); - return t.run(); + return t.run(); } diff --git a/include/villas/api.hpp b/include/villas/api.hpp index 59622799f..7ced72a0a 100644 --- a/include/villas/api.hpp +++ b/include/villas/api.hpp @@ -11,15 +11,15 @@ #include #include -#include #include +#include #include -#include #include -#include #include +#include +#include namespace villas { namespace node { @@ -35,41 +35,35 @@ class Request; class Error : public RuntimeError { public: + template + Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, + const std::string &msg = "Invalid API request", Args &&...args) + : RuntimeError(msg, std::forward(args)...), code(c), json(nullptr) { + } - template - Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, const std::string &msg = "Invalid API request", Args&&... args) : - RuntimeError(msg, std::forward(args)...), - code(c), - json(nullptr) - { } + template + Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, + const std::string &msg = "Invalid API request", + const char *fmt = nullptr, Args &&...args) + : RuntimeError(msg), code(c), + json(fmt ? json_pack(fmt, std::forward(args)...) : nullptr) {} - template - Error(int c = HTTP_STATUS_INTERNAL_SERVER_ERROR, const std::string &msg = "Invalid API request", const char *fmt = nullptr, Args&&... args) : - RuntimeError(msg), - code(c), - json(fmt - ? json_pack(fmt, std::forward(args)...) - : nullptr - ) - { } - - int code; - json_t *json; + int code; + json_t *json; }; class BadRequest : public Error { public: - template - BadRequest(const std::string &msg = "Bad API request", Args&&... args) : - Error(HTTP_STATUS_BAD_REQUEST, msg, std::forward(args)...) - { } + template + BadRequest(const std::string &msg = "Bad API request", Args &&...args) + : Error(HTTP_STATUS_BAD_REQUEST, msg, std::forward(args)...) {} }; class InvalidMethod : public BadRequest { public: - InvalidMethod(Request *req); + InvalidMethod(Request *req); }; } // namespace api @@ -80,36 +74,34 @@ class SuperNode; class Api { protected: - Logger logger; + Logger logger; - enum State state; + enum State state; - std::thread thread; - std::atomic running; // Atomic flag for signalizing thread termination. + std::thread thread; + std::atomic running; // Atomic flag for signalizing thread termination. - SuperNode *super_node; + SuperNode *super_node; - void run(); - void worker(); + void run(); + void worker(); public: - /* Initialize the API. + /* Initialize the API. * * Save references to list of paths / nodes for command execution. */ - Api(SuperNode *sn); - ~Api(); + Api(SuperNode *sn); + ~Api(); - void start(); - void stop(); + void start(); + void stop(); - SuperNode * getSuperNode() - { - return super_node; - } + SuperNode *getSuperNode() { return super_node; } - std::list sessions; // List of currently active connections - villas::QueueSignalled pending; // A queue of api_sessions which have pending requests. + std::list sessions; // List of currently active connections + villas::QueueSignalled + pending; // A queue of api_sessions which have pending requests. }; } // namespace node diff --git a/include/villas/api/request.hpp b/include/villas/api/request.hpp index 45fcb0d5e..69bdcd0b7 100644 --- a/include/villas/api/request.hpp +++ b/include/villas/api/request.hpp @@ -7,17 +7,19 @@ #pragma once -#include -#include #include +#include +#include -#include +#include #include +#include #include #include -#include -#define RE_UUID "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}" +#define RE_UUID \ + "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{" \ + "12}" namespace villas { namespace node { @@ -30,152 +32,107 @@ class RequestFactory; class Request { - friend Session; - friend RequestFactory; - friend Response; + friend Session; + friend RequestFactory; + friend Response; protected: - Session *session; + Session *session; - Logger logger; - Buffer buffer; + Logger logger; + Buffer buffer; public: - std::vector matches; - Session::Method method; - unsigned long contentLength; - json_t *body; + std::vector matches; + Session::Method method; + unsigned long contentLength; + json_t *body; - RequestFactory *factory; + RequestFactory *factory; - Request(Session *s) : - session(s), - method(Session::Method::UNKNOWN), - contentLength(0), - body(nullptr), - factory(nullptr) - { } + Request(Session *s) + : session(s), method(Session::Method::UNKNOWN), contentLength(0), + body(nullptr), factory(nullptr) {} - virtual - ~Request() - { - if (body) - json_decref(body); - } + virtual ~Request() { + if (body) + json_decref(body); + } - virtual - void prepare() - { } + virtual void prepare() {} - virtual - Response * execute() = 0; + virtual Response *execute() = 0; - virtual - void decode(); + virtual void decode(); - const std::string & getMatch(int idx) const - { - return matches[idx]; - } + const std::string &getMatch(int idx) const { return matches[idx]; } - std::string getQueryArg(const std::string &arg) - { - char buf[1024]; - const char *val; + std::string getQueryArg(const std::string &arg) { + char buf[1024]; + const char *val; - val = lws_get_urlarg_by_name(session->wsi, (arg + "=").c_str(), buf, sizeof(buf)); + val = lws_get_urlarg_by_name(session->wsi, (arg + "=").c_str(), buf, + sizeof(buf)); - return val ? std::string(val) : std::string(); - } + return val ? std::string(val) : std::string(); + } - std::string getHeader(enum lws_token_indexes hdr) - { - char buf[1024]; + std::string getHeader(enum lws_token_indexes hdr) { + char buf[1024]; - lws_hdr_copy(session->wsi, buf, sizeof(buf), hdr); + lws_hdr_copy(session->wsi, buf, sizeof(buf), hdr); - return std::string(buf); - } + return std::string(buf); + } - virtual - std::string toString(); + virtual std::string toString(); }; class RequestFactory : public plugin::Plugin { public: - using plugin::Plugin::Plugin; + using plugin::Plugin::Plugin; - virtual - bool match(const std::string &uri, std::smatch &m) const = 0; + virtual bool match(const std::string &uri, std::smatch &m) const = 0; - virtual - Request * make(Session *s) = 0; + virtual Request *make(Session *s) = 0; - static - Request * create(Session *s, const std::string &uri, Session::Method meth, unsigned long ct); + static Request *create(Session *s, const std::string &uri, + Session::Method meth, unsigned long ct); - virtual - void init(Request *r) - { - r->logger = getLogger(); - } + virtual void init(Request *r) { r->logger = getLogger(); } - virtual - std::string - getType() const - { - return "api:request"; - } + virtual std::string getType() const { return "api:request"; } - virtual - bool isHidden() const - { - return false; - } + virtual bool isHidden() const { return false; } }; -template +template class RequestPlugin : public RequestFactory { protected: - std::regex regex; + std::regex regex; public: - RequestPlugin() : - RequestFactory(), - regex(re) - { } + RequestPlugin() : RequestFactory(), regex(re) {} - virtual - Request * make(Session *s) - { - auto *r = new T(s); + virtual Request *make(Session *s) { + auto *r = new T(s); - init(r); + init(r); - return r; - } + return r; + } - // Get plugin name - virtual - std::string getName() const - { - return name; - } + // Get plugin name + virtual std::string getName() const { return name; } - // Get plugin description - virtual - std::string getDescription() const - { - return desc; - } + // Get plugin description + virtual std::string getDescription() const { return desc; } - virtual - bool match(const std::string &uri, std::smatch &match) const - { - return std::regex_match(uri, match, regex); - } + virtual bool match(const std::string &uri, std::smatch &match) const { + return std::regex_match(uri, match, regex); + } }; } // namespace api diff --git a/include/villas/api/requests/node.hpp b/include/villas/api/requests/node.hpp index dda48a628..831a7ba43 100644 --- a/include/villas/api/requests/node.hpp +++ b/include/villas/api/requests/node.hpp @@ -20,13 +20,12 @@ namespace api { class NodeRequest : public Request { protected: - Node *node; + Node *node; public: - using Request::Request; + using Request::Request; - virtual - void prepare(); + virtual void prepare(); }; } // namespace api diff --git a/include/villas/api/requests/path.hpp b/include/villas/api/requests/path.hpp index 260aaf385..2ea23f6c1 100644 --- a/include/villas/api/requests/path.hpp +++ b/include/villas/api/requests/path.hpp @@ -18,13 +18,12 @@ namespace api { class PathRequest : public Request { protected: - class Path *path; + class Path *path; public: - using Request::Request; + using Request::Request; - virtual - void prepare(); + virtual void prepare(); }; } // namespace api diff --git a/include/villas/api/requests/universal.hpp b/include/villas/api/requests/universal.hpp index c5772c6a6..2452c8e7e 100644 --- a/include/villas/api/requests/universal.hpp +++ b/include/villas/api/requests/universal.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include namespace villas { namespace node { @@ -21,13 +21,12 @@ namespace api { class UniversalRequest : public NodeRequest { protected: - APINode *api_node; + APINode *api_node; public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - void prepare(); + virtual void prepare(); }; } // namespace api diff --git a/include/villas/api/response.hpp b/include/villas/api/response.hpp index ebf1286ef..2fc9e3ec3 100644 --- a/include/villas/api/response.hpp +++ b/include/villas/api/response.hpp @@ -11,11 +11,11 @@ #include -#include +#include #include #include +#include #include -#include namespace villas { namespace node { @@ -28,71 +28,60 @@ class Request; class Response { public: - friend Session; + friend Session; - Response(Session *s, int c = HTTP_STATUS_OK, const std::string &ct = "text/html; charset=UTF-8", const Buffer &b = Buffer()); + Response(Session *s, int c = HTTP_STATUS_OK, + const std::string &ct = "text/html; charset=UTF-8", + const Buffer &b = Buffer()); - virtual - ~Response() - { } + virtual ~Response() {} - virtual - void encodeBody() - { } + virtual void encodeBody() {} - int - writeBody(struct lws *wsi); + int writeBody(struct lws *wsi); - int - writeHeaders(struct lws *wsi); + int writeHeaders(struct lws *wsi); - void - setHeader(const std::string &key, const std::string &value) - { - headers[key] = value; - } + void setHeader(const std::string &key, const std::string &value) { + headers[key] = value; + } protected: - Session *session; - Logger logger; - Buffer buffer; + Session *session; + Logger logger; + Buffer buffer; - int code; - std::string contentType; - std::map headers; + int code; + std::string contentType; + std::map headers; }; class JsonResponse : public Response { protected: - json_t *response; + json_t *response; public: - JsonResponse(Session *s, int c, json_t *r) : - Response(s, c, "application/json"), - response(r) - { } + JsonResponse(Session *s, int c, json_t *r) + : Response(s, c, "application/json"), response(r) {} - virtual - ~JsonResponse(); + virtual ~JsonResponse(); - virtual - void encodeBody(); + virtual void encodeBody(); }; class ErrorResponse : public JsonResponse { public: - ErrorResponse(Session *s, const RuntimeError &e) : - JsonResponse(s, HTTP_STATUS_INTERNAL_SERVER_ERROR, json_pack("{ s: s }", "error", e.what())) - { } + ErrorResponse(Session *s, const RuntimeError &e) + : JsonResponse(s, HTTP_STATUS_INTERNAL_SERVER_ERROR, + json_pack("{ s: s }", "error", e.what())) {} - ErrorResponse(Session *s, const Error &e) : - JsonResponse(s, e.code, json_pack("{ s: s }", "error", e.what())) - { - if (e.json) - json_object_update(response, e.json); - } + ErrorResponse(Session *s, const Error &e) + : JsonResponse(s, e.code, json_pack("{ s: s }", "error", e.what())) { + if (e.json) + json_object_update(response, e.json); + } }; } // namespace api diff --git a/include/villas/api/session.hpp b/include/villas/api/session.hpp index 901d727a1..005374221 100644 --- a/include/villas/api/session.hpp +++ b/include/villas/api/session.hpp @@ -9,9 +9,9 @@ #include -#include -#include #include +#include +#include namespace villas { namespace node { @@ -33,72 +33,53 @@ class RequestFactory; class Session { public: - friend Request; // Requires access to wsi for getting URL args and headers - friend StatusRequest; // Requires access to wsi for context status - friend RequestFactory; + friend Request; // Requires access to wsi for getting URL args and headers + friend StatusRequest; // Requires access to wsi for context status + friend RequestFactory; - enum State { - ESTABLISHED, - SHUTDOWN - }; + enum State { ESTABLISHED, SHUTDOWN }; - enum Version { - UNKNOWN_VERSION = 0, - VERSION_1 = 1, - VERSION_2 = 2 - }; + enum Version { UNKNOWN_VERSION = 0, VERSION_1 = 1, VERSION_2 = 2 }; - enum Method { - UNKNOWN, - GET, - POST, - DELETE, - OPTIONS, - PUT, - PATCH - }; + enum Method { UNKNOWN, GET, POST, DELETE, OPTIONS, PUT, PATCH }; protected: - enum State state; - enum Version version; + enum State state; + enum Version version; - lws *wsi; + lws *wsi; - Web *web; - Api *api; + Web *web; + Api *api; - Logger logger; + Logger logger; - std::unique_ptr request; - std::unique_ptr response; + std::unique_ptr request; + std::unique_ptr response; - bool headersSent; + bool headersSent; public: - Session(struct lws *w); - ~Session(); + Session(struct lws *w); + ~Session(); - std::string getName() const; + std::string getName() const; - SuperNode * getSuperNode() const - { - return api->getSuperNode(); - } + SuperNode *getSuperNode() const { return api->getSuperNode(); } - void open(void *in, size_t len); - int writeable(); - void body(void *in, size_t len); - void bodyComplete(); - void execute(); - void shutdown(); + void open(void *in, size_t len); + int writeable(); + void body(void *in, size_t len); + void bodyComplete(); + void execute(); + void shutdown(); - static - int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); - Method getRequestMethod() const; + Method getRequestMethod() const; - static - std::string methodToString(Method meth); + static std::string methodToString(Method meth); }; } // namespace api diff --git a/include/villas/api/universal.hpp b/include/villas/api/universal.hpp index 20b497ec7..96ac12447 100644 --- a/include/villas/api/universal.hpp +++ b/include/villas/api/universal.hpp @@ -8,9 +8,9 @@ #pragma once +#include #include #include -#include #include @@ -21,33 +21,30 @@ namespace node { namespace api { namespace universal { -enum PayloadType { - SAMPLES = 0, - EVENTS = 1 -}; +enum PayloadType { SAMPLES = 0, EVENTS = 1 }; // Channel (uAPI) is a synonym for signal (VILLAS) class Channel { public: - std::string description; - PayloadType payload; - double range_min; - double range_max; - std::vector range_options; - double rate; - bool readable; - bool writable; + std::string description; + PayloadType payload; + double range_min; + double range_max; + std::vector range_options; + double rate; + bool readable; + bool writable; - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - void parse(json_t *json); - json_t * toJson(Signal::Ptr sig) const; + void parse(json_t *json); + json_t *toJson(Signal::Ptr sig) const; }; class ChannelList : public std::vector { public: - void parse(json_t *json, bool readable, bool writable); + void parse(json_t *json, bool readable, bool writable); }; } // namespace universal diff --git a/include/villas/capabilities.hpp b/include/villas/capabilities.hpp index 48c2f58a1..9420c1d2a 100644 --- a/include/villas/capabilities.hpp +++ b/include/villas/capabilities.hpp @@ -12,7 +12,7 @@ namespace villas { namespace node { -json_t * getCapabilities(); +json_t *getCapabilities(); } // namespace node -} // namepace vilals +} // namespace villas diff --git a/include/villas/config_class.hpp b/include/villas/config_class.hpp index 68dbf6445..60acdc251 100644 --- a/include/villas/config_class.hpp +++ b/include/villas/config_class.hpp @@ -8,17 +8,17 @@ #pragma once #include -#include #include +#include #include #include -#include #include +#include #ifdef WITH_CONFIG - #include +#include #endif namespace villas { @@ -27,65 +27,66 @@ namespace node { class Config { protected: - using str_walk_fcn_t = std::function; + using str_walk_fcn_t = std::function; - Logger logger; + Logger logger; - std::list includeDirectories; + std::list includeDirectories; - // Check if file exists on local system. - static - bool isLocalFile(const std::string &uri) - { - return access(uri.c_str(), F_OK) != -1; - } + // Check if file exists on local system. + static bool isLocalFile(const std::string &uri) { + return access(uri.c_str(), F_OK) != -1; + } - // Decode configuration file. - json_t * decode(FILE *f); + // Decode configuration file. + json_t *decode(FILE *f); #ifdef WITH_CONFIG - // Convert libconfig .conf file to libjansson .json file. - json_t * libconfigDecode(FILE *f); + // Convert libconfig .conf file to libjansson .json file. + json_t *libconfigDecode(FILE *f); - static - const char ** includeFuncStub(config_t *cfg, const char *include_dir, const char *path, const char **error); + static const char **includeFuncStub(config_t *cfg, const char *include_dir, + const char *path, const char **error); - const char ** includeFunc(config_t *cfg, const char *include_dir, const char *path, const char **error); + const char **includeFunc(config_t *cfg, const char *include_dir, + const char *path, const char **error); #endif // WITH_CONFIG - // Load configuration from standard input (stdim). - FILE * loadFromStdio(); + // Load configuration from standard input (stdim). + FILE *loadFromStdio(); - // Load configuration from local file. - FILE * loadFromLocalFile(const std::string &u); + // Load configuration from local file. + FILE *loadFromLocalFile(const std::string &u); - std::list resolveIncludes(const std::string &name); + std::list resolveIncludes(const std::string &name); - void resolveEnvVars(std::string &text); + void resolveEnvVars(std::string &text); - // Resolve custom include directives. - json_t * expandIncludes(json_t *in); + // Resolve custom include directives. + json_t *expandIncludes(json_t *in); - // To shell-like subsitution of environment variables in strings. - json_t * expandEnvVars(json_t *in); + // To shell-like subsitution of environment variables in strings. + json_t *expandEnvVars(json_t *in); - // Run a callback function for each string in the config - json_t * walkStrings(json_t *in, str_walk_fcn_t cb); + // Run a callback function for each string in the config + json_t *walkStrings(json_t *in, str_walk_fcn_t cb); - // Get the include dirs - std::list getIncludeDirectories(FILE *f) const; + // Get the include dirs + std::list getIncludeDirectories(FILE *f) const; public: - json_t *root; + json_t *root; - Config(); - Config(const std::string &u); + Config(); + Config(const std::string &u); - ~Config(); + ~Config(); - json_t * load(std::FILE *f, bool resolveIncludes = true, bool resolveEnvVars = true); + json_t *load(std::FILE *f, bool resolveIncludes = true, + bool resolveEnvVars = true); - json_t * load(const std::string &u, bool resolveIncludes = true, bool resolveEnvVars = true); + json_t *load(const std::string &u, bool resolveIncludes = true, + bool resolveEnvVars = true); }; } // namespace node diff --git a/include/villas/config_helper.hpp b/include/villas/config_helper.hpp index 6a1ea189c..1fa578891 100644 --- a/include/villas/config_helper.hpp +++ b/include/villas/config_helper.hpp @@ -8,7 +8,7 @@ #pragma once #ifdef WITH_CONFIG - #include +#include #endif #include @@ -22,7 +22,7 @@ namespace node { #ifdef WITH_CONFIG // Convert a libconfig object to a jansson object -json_t * config_to_json(struct config_setting_t *cfg); +json_t *config_to_json(struct config_setting_t *cfg); // Convert a jansson object into a libconfig object. int json_to_config(json_t *json, struct config_setting_t *parent); @@ -31,14 +31,16 @@ int json_to_config(json_t *json, struct config_setting_t *parent); int json_object_extend_str(json_t *orig, const char *str); -void json_object_extend_key_value(json_t *obj, const char *key, const char *value); +void json_object_extend_key_value(json_t *obj, const char *key, + const char *value); -void json_object_extend_key_value_token(json_t *obj, const char *key, const char *value); +void json_object_extend_key_value_token(json_t *obj, const char *key, + const char *value); // Merge two JSON objects recursively. int json_object_extend(json_t *orig, json_t *merge); -json_t * json_load_cli(int argc, const char *argv[]); +json_t *json_load_cli(int argc, const char *argv[]); } // namespace node } // namespace villas diff --git a/include/villas/dumper.hpp b/include/villas/dumper.hpp index 9eb34fea0..61fa61c03 100644 --- a/include/villas/dumper.hpp +++ b/include/villas/dumper.hpp @@ -17,25 +17,25 @@ namespace node { class Dumper { protected: - bool active; - int socketFd; - std::string socketPath; - bool supressRepeatedWarning; - uint64_t warningCounter; - Logger logger; + bool active; + int socketFd; + std::string socketPath; + bool supressRepeatedWarning; + uint64_t warningCounter; + Logger logger; public: - Dumper(); - ~Dumper(); + Dumper(); + ~Dumper(); - int openSocket(); - int closeSocket(); - bool isActive(); - int setActive(); + int openSocket(); + int closeSocket(); + bool isActive(); + int setActive(); - int setPath(const std::string &socketPathIn); - void writeDataCSV(unsigned len, double *yData, double *xData = nullptr); - void writeDataBinary(unsigned len, double *yData, double *xData = nullptr); + int setPath(const std::string &socketPathIn); + void writeDataCSV(unsigned len, double *yData, double *xData = nullptr); + void writeDataBinary(unsigned len, double *yData, double *xData = nullptr); }; } // namespace node diff --git a/include/villas/format.hpp b/include/villas/format.hpp index 4d570a8e7..4f670ce3a 100644 --- a/include/villas/format.hpp +++ b/include/villas/format.hpp @@ -22,58 +22,46 @@ class FormatFactory; class Format { - friend FormatFactory; + friend FormatFactory; public: - using Ptr = std::unique_ptr; + using Ptr = std::unique_ptr; protected: + int flags; // A set of flags which is automatically used. + int real_precision; // Number of digits used for floatint point numbers - int flags; // A set of flags which is automatically used. - int real_precision; // Number of digits used for floatint point numbers + Logger logger; - Logger logger; + struct { + char *buffer; + size_t buflen; + } in, out; - struct { - char *buffer; - size_t buflen; - } in, out; - - SignalList::Ptr signals; // Signal meta data for parsed samples by Format::scan() + SignalList::Ptr + signals; // Signal meta data for parsed samples by Format::scan() public: - Format(int fl); + Format(int fl); - virtual - ~Format(); + virtual ~Format(); - const SignalList::Ptr getSignals() const - { - return signals; - } + const SignalList::Ptr getSignals() const { return signals; } - int getFlags() const - { - return flags; - } + int getFlags() const { return flags; } - void start(const SignalList::Ptr sigs, int fl = (int) SampleFlags::HAS_ALL); - void start(const std::string &dtypes, int fl = (int) SampleFlags::HAS_ALL); + void start(const SignalList::Ptr sigs, int fl = (int)SampleFlags::HAS_ALL); + void start(const std::string &dtypes, int fl = (int)SampleFlags::HAS_ALL); - virtual - void start() - { } + virtual void start() {} - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - int print(FILE *f, const struct Sample * const smps[], unsigned cnt); + virtual int print(FILE *f, const struct Sample *const smps[], unsigned cnt); - virtual - int scan(FILE *f, struct Sample * const smps[], unsigned cnt); + virtual int scan(FILE *f, struct Sample *const smps[], unsigned cnt); - /* Print \p cnt samples from \p smps into buffer \p buf of length \p len. + /* Print \p cnt samples from \p smps into buffer \p buf of length \p len. * * @param buf[out] The buffer which should be filled with serialized data. * @param len[in] The length of the buffer \p buf. @@ -84,10 +72,10 @@ public: * @retval >=0 The number of samples from \p smps which have been written into \p buf. * @retval <0 Something went wrong. */ - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) = 0; + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) = 0; - /* Parse samples from the buffer \p buf with a length of \p len bytes. + /* Parse samples from the buffer \p buf with a length of \p len bytes. * * @param buf[in] The buffer of data which should be parsed / de-serialized. * @param len[in] The length of the buffer \p buf. @@ -98,98 +86,65 @@ public: * @retval >=0 The number of samples which have been parsed from \p buf and written into \p smps. * @retval <0 Something went wrong. */ - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) = 0; + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) = 0; - // Wrappers for sending a (un)parsing single samples + // Wrappers for sending a (un)parsing single samples - int print(FILE *f, const struct Sample *smp) - { - return print(f, &smp, 1); - } + int print(FILE *f, const struct Sample *smp) { return print(f, &smp, 1); } - int scan(FILE *f, struct Sample *smp) - { - return scan(f, &smp, 1); - } + int scan(FILE *f, struct Sample *smp) { return scan(f, &smp, 1); } - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample *smp) - { - return sprint(buf, len, wbytes, &smp, 1); - } + int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample *smp) { + return sprint(buf, len, wbytes, &smp, 1); + } - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample *smp) - { - return sscan(buf, len, rbytes, &smp, 1); - } + int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample *smp) { + return sscan(buf, len, rbytes, &smp, 1); + } }; class BinaryFormat : public Format { public: - using Format::Format; + using Format::Format; }; class FormatFactory : public plugin::Plugin { public: - using plugin::Plugin::Plugin; + using plugin::Plugin::Plugin; - virtual - Format * make() = 0; + virtual Format *make() = 0; - static - Format * make(json_t *json); + static Format *make(json_t *json); - static - Format * make(const std::string &format); + static Format *make(const std::string &format); - virtual - void init(Format *f) - { - f->logger = getLogger(); - } + virtual void init(Format *f) { f->logger = getLogger(); } - virtual - std::string getType() const - { - return "format"; - } + virtual std::string getType() const { return "format"; } - virtual - bool isHidden() const - { - return false; - } + virtual bool isHidden() const { return false; } }; template class FormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - auto *f = new T(flags); + virtual Format *make() { + auto *f = new T(flags); - init(f); + init(f); - return f; - } + return f; + } - virtual - std::string getName() const - { - return name; - } + virtual std::string getName() const { return name; } - virtual - std::string getDescription() const - { - return desc; - } + virtual std::string getDescription() const { return desc; } }; } // namespace node diff --git a/include/villas/formats/column.hpp b/include/villas/formats/column.hpp index 528b68091..2c47ed1fa 100644 --- a/include/villas/formats/column.hpp +++ b/include/villas/formats/column.hpp @@ -20,51 +20,36 @@ struct Sample; class ColumnLineFormat : public LineFormat { protected: - virtual - size_t sprintLine(char *buf, size_t len, const struct Sample *smp); - virtual - size_t sscanLine(const char *buf, size_t len, struct Sample *smp); + virtual size_t sprintLine(char *buf, size_t len, const struct Sample *smp); + virtual size_t sscanLine(const char *buf, size_t len, struct Sample *smp); - char separator; // Column separator + char separator; // Column separator public: - ColumnLineFormat(int fl, char delim, char sep) : - LineFormat(fl, delim), - separator(sep) - { } + ColumnLineFormat(int fl, char delim, char sep) + : LineFormat(fl, delim), separator(sep) {} - virtual - void header(FILE *f, const SignalList::Ptr sigs); + virtual void header(FILE *f, const SignalList::Ptr sigs); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; -template +template class ColumnLineFormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - return new ColumnLineFormat(flags, delimiter, separator); - } + virtual Format *make() { + return new ColumnLineFormat(flags, delimiter, separator); + } - /// Get plugin name - virtual - std::string getName() const - { - return name; - } + /// Get plugin name + virtual std::string getName() const { return name; } - /// Get plugin description - virtual - std::string getDescription() const - { - return desc; - } + /// Get plugin description + virtual std::string getDescription() const { return desc; } }; } // namespace node diff --git a/include/villas/formats/iotagent_ul.hpp b/include/villas/formats/iotagent_ul.hpp index d7ec53fc1..e7398fd57 100644 --- a/include/villas/formats/iotagent_ul.hpp +++ b/include/villas/formats/iotagent_ul.hpp @@ -18,14 +18,14 @@ struct Sample; class IotAgentUltraLightFormat : public Format { protected: - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); public: - using Format::Format; + using Format::Format; }; } // namespace node diff --git a/include/villas/formats/json.hpp b/include/villas/formats/json.hpp index 234ffb47e..1183948b1 100644 --- a/include/villas/formats/json.hpp +++ b/include/villas/formats/json.hpp @@ -20,41 +20,32 @@ struct Sample; class JsonFormat : public Format { protected: - static - enum SignalType detect(const json_t *val); + static enum SignalType detect(const json_t *val); - json_t * packTimestamps(const struct Sample *smp); - int unpackTimestamps(json_t *json_ts, struct Sample *smp); + json_t *packTimestamps(const struct Sample *smp); + int unpackTimestamps(json_t *json_ts, struct Sample *smp); - virtual - int packSample(json_t **j, const struct Sample *smp); - virtual - int packSamples(json_t **j, const struct Sample * const smps[], unsigned cnt); - virtual - int unpackSample(json_t *json_smp, struct Sample *smp); - virtual - int unpackSamples(json_t *json_smps, struct Sample * const smps[], unsigned cnt); + virtual int packSample(json_t **j, const struct Sample *smp); + virtual int packSamples(json_t **j, const struct Sample *const smps[], + unsigned cnt); + virtual int unpackSample(json_t *json_smp, struct Sample *smp); + virtual int unpackSamples(json_t *json_smps, struct Sample *const smps[], + unsigned cnt); - int dump_flags; + int dump_flags; public: - JsonFormat(int fl) : - Format(fl), - dump_flags(0) - { } + JsonFormat(int fl) : Format(fl), dump_flags(0) {} - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - int print(FILE *f, const struct Sample * const smps[], unsigned cnt); - virtual - int scan(FILE *f, struct Sample * const smps[], unsigned cnt); + virtual int print(FILE *f, const struct Sample *const smps[], unsigned cnt); + virtual int scan(FILE *f, struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; } // namespace node diff --git a/include/villas/formats/json_edgeflex.hpp b/include/villas/formats/json_edgeflex.hpp index 05c897ecb..ebb544532 100644 --- a/include/villas/formats/json_edgeflex.hpp +++ b/include/villas/formats/json_edgeflex.hpp @@ -15,13 +15,11 @@ namespace node { class JsonEdgeflexFormat : public JsonFormat { protected: - virtual - int packSample(json_t **j, const struct Sample *smp); - virtual - int unpackSample(json_t *json_smp, struct Sample *smp); + virtual int packSample(json_t **j, const struct Sample *smp); + virtual int unpackSample(json_t *json_smp, struct Sample *smp); public: - using JsonFormat::JsonFormat; + using JsonFormat::JsonFormat; }; } // namespace node diff --git a/include/villas/formats/json_kafka.hpp b/include/villas/formats/json_kafka.hpp index 492b4da6b..3edc0a566 100644 --- a/include/villas/formats/json_kafka.hpp +++ b/include/villas/formats/json_kafka.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include namespace villas { namespace node { @@ -16,20 +16,17 @@ namespace node { class JsonKafkaFormat : public JsonFormat { protected: - virtual - int packSample(json_t **j, const struct Sample *smp); - virtual - int unpackSample(json_t *json_smp, struct Sample *smp); + virtual int packSample(json_t **j, const struct Sample *smp); + virtual int unpackSample(json_t *json_smp, struct Sample *smp); - const char * villasToKafkaType(enum SignalType vt); + const char *villasToKafkaType(enum SignalType vt); - json_t *json_schema; + json_t *json_schema; public: - JsonKafkaFormat(int fl); + JsonKafkaFormat(int fl); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; } // namespace node diff --git a/include/villas/formats/json_reserve.hpp b/include/villas/formats/json_reserve.hpp index f90ee2feb..46efe15c3 100644 --- a/include/villas/formats/json_reserve.hpp +++ b/include/villas/formats/json_reserve.hpp @@ -15,13 +15,11 @@ namespace node { class JsonReserveFormat : public JsonFormat { protected: - virtual - int packSample(json_t **j, const struct Sample *smp); - virtual - int unpackSample(json_t *json_smp, struct Sample *smp); + virtual int packSample(json_t **j, const struct Sample *smp); + virtual int unpackSample(json_t *json_smp, struct Sample *smp); public: - using JsonFormat::JsonFormat; + using JsonFormat::JsonFormat; }; } // namespace node diff --git a/include/villas/formats/line.hpp b/include/villas/formats/line.hpp index 45fd1dcfe..f4b1c0aeb 100644 --- a/include/villas/formats/line.hpp +++ b/include/villas/formats/line.hpp @@ -15,77 +15,54 @@ namespace node { class LineFormat : public Format { protected: - virtual - size_t sprintLine(char *buf, size_t len, const struct Sample *smp) = 0; - virtual - size_t sscanLine(const char *buf, size_t len, struct Sample *smp) = 0; + virtual size_t sprintLine(char *buf, size_t len, + const struct Sample *smp) = 0; + virtual size_t sscanLine(const char *buf, size_t len, struct Sample *smp) = 0; - char delimiter; // Newline delimiter. - char comment; // Prefix for comment lines. + char delimiter; // Newline delimiter. + char comment; // Prefix for comment lines. - bool skip_first_line; // While reading, the first line is skipped (header) - bool print_header; // Before any data, a header line is printed + bool skip_first_line; // While reading, the first line is skipped (header) + bool print_header; // Before any data, a header line is printed - bool first_line_skipped; - bool header_printed; + bool first_line_skipped; + bool header_printed; public: - LineFormat(int fl, char delim = '\n', char com = '#') : - Format(fl), - delimiter(delim), - comment(com), - skip_first_line(false), - print_header(true), - first_line_skipped(false), - header_printed(false) - { } + LineFormat(int fl, char delim = '\n', char com = '#') + : Format(fl), delimiter(delim), comment(com), skip_first_line(false), + print_header(true), first_line_skipped(false), header_printed(false) {} - // Print a header - virtual - void header(FILE *f, const SignalList::Ptr sigs) - { - header_printed = true; - } + // Print a header + virtual void header(FILE *f, const SignalList::Ptr sigs) { + header_printed = true; + } - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); - virtual - int scan(FILE *f, struct Sample * const smps[], unsigned cnt); - virtual - int print(FILE *f, const struct Sample * const smps[], unsigned cnt); + virtual int scan(FILE *f, struct Sample *const smps[], unsigned cnt); + virtual int print(FILE *f, const struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; -template +template class LineFormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - return new T(flags, delimiter); - } + virtual Format *make() { return new T(flags, delimiter); } - /// Get plugin name - virtual - std::string getName() const - { - return name; - } + /// Get plugin name + virtual std::string getName() const { return name; } - /// Get plugin description - virtual - std::string getDescription() const - { - return desc; - } + /// Get plugin description + virtual std::string getDescription() const { return desc; } }; } // namespace node diff --git a/include/villas/formats/msg.hpp b/include/villas/formats/msg.hpp index 0dac505aa..8b125577b 100644 --- a/include/villas/formats/msg.hpp +++ b/include/villas/formats/msg.hpp @@ -7,7 +7,7 @@ #pragma once -#include +#include namespace villas { @@ -43,10 +43,12 @@ void msg_hdr_ntoh(struct Message *m); int msg_verify(const struct Message *m); // Copy fields from \p msg into \p smp. -int msg_to_sample(const struct Message *msg, struct Sample *smp, const SignalList::Ptr sigs, uint8_t *source_index); +int msg_to_sample(const struct Message *msg, struct Sample *smp, + const SignalList::Ptr sigs, uint8_t *source_index); // Copy fields form \p smp into \p msg. -int msg_from_sample(struct Message *msg, const struct Sample *smp, const SignalList::Ptr sigs, uint8_t source_index); +int msg_from_sample(struct Message *msg, const struct Sample *smp, + const SignalList::Ptr sigs, uint8_t source_index); } // namespace node } // namespace villas diff --git a/include/villas/formats/msg_format.hpp b/include/villas/formats/msg_format.hpp index 7512c3e24..2b58d3c8f 100644 --- a/include/villas/formats/msg_format.hpp +++ b/include/villas/formats/msg_format.hpp @@ -10,60 +10,62 @@ #include // The current version number for the message format -#define MSG_VERSION 2 +#define MSG_VERSION 2 // TODO: Implement more message types -#define MSG_TYPE_DATA 0 // Message contains float / integer values -#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case -#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case +#define MSG_TYPE_DATA 0 // Message contains float / integer values +#define MSG_TYPE_START 1 // Message marks the beginning of a new simulation case +#define MSG_TYPE_STOP 2 // Message marks the end of a simulation case // The total size in bytes of a message -#define MSG_LEN(values) (sizeof(struct Message) + MSG_DATA_LEN(values)) +#define MSG_LEN(values) (sizeof(struct Message) + MSG_DATA_LEN(values)) // The length of \p values values in bytes. -#define MSG_DATA_LEN(values) (sizeof(float) * (values)) +#define MSG_DATA_LEN(values) (sizeof(float) * (values)) // The offset to the first data value in a message. -#define MSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct Message, data)) +#define MSG_DATA_OFFSET(msg) ((char *)(msg) + offsetof(struct Message, data)) // The timestamp of a message in struct timespec format -#define MSG_TS(msg, i) \ - i.tv_sec = (msg)->ts.sec; \ - i.tv_nsec = (msg)->ts.nsec; +#define MSG_TS(msg, i) \ + i.tv_sec = (msg)->ts.sec; \ + i.tv_nsec = (msg)->ts.nsec; namespace villas { namespace node { // This message format is used by all clients -struct Message -{ +struct Message { #if BYTE_ORDER == BIG_ENDIAN - unsigned version: 4; // Specifies the format of the remaining message (see MGS_VERSION) - unsigned type : 2; // Data or control message (see MSG_TYPE_*) - unsigned reserved1 : 2; // Reserved bits + unsigned + version : 4; // Specifies the format of the remaining message (see MGS_VERSION) + unsigned type : 2; // Data or control message (see MSG_TYPE_*) + unsigned reserved1 : 2; // Reserved bits #elif BYTE_ORDER == LITTLE_ENDIAN - unsigned reserved1 : 2; // Reserved bits - unsigned type : 2; // Data or control message (see MSG_TYPE_*) - unsigned version: 4; // Specifies the format of the remaining message (see MGS_VERSION) + unsigned reserved1 : 2; // Reserved bits + unsigned type : 2; // Data or control message (see MSG_TYPE_*) + unsigned + version : 4; // Specifies the format of the remaining message (see MGS_VERSION) #else - #error Invalid byte-order +#error Invalid byte-order #endif - uint8_t source_index; // An id which identifies the source of this sample. - uint16_t length; // The number of values in msg::data[]. - uint32_t sequence; // The sequence number is incremented by one for consecutive messages. + uint8_t source_index; // An id which identifies the source of this sample. + uint16_t length; // The number of values in msg::data[]. + uint32_t + sequence; // The sequence number is incremented by one for consecutive messages. - // A timestamp per message. - struct { - uint32_t sec; // Seconds since 1970-01-01 00:00:00 - uint32_t nsec; // Nanoseconds of the current second - } ts; + // A timestamp per message. + struct { + uint32_t sec; // Seconds since 1970-01-01 00:00:00 + uint32_t nsec; // Nanoseconds of the current second + } ts; - // The message payload. - union { - float f; // Floating point values - uint32_t i; // Integer values - } data[]; + // The message payload. + union { + float f; // Floating point values + uint32_t i; // Integer values + } data[]; } __attribute__((packed)); } // namespace node diff --git a/include/villas/formats/opal_asyncip.hpp b/include/villas/formats/opal_asyncip.hpp index cae90984e..4be7cecb1 100644 --- a/include/villas/formats/opal_asyncip.hpp +++ b/include/villas/formats/opal_asyncip.hpp @@ -20,56 +20,45 @@ struct Sample; class OpalAsyncIPFormat : public BinaryFormat { protected: - const unsigned MAXSIZE = 64; + const unsigned MAXSIZE = 64; - struct Payload { - int16_t dev_id; // (2 bytes) Sender device ID - int32_t msg_id; // (4 bytes) Message ID - int16_t msg_len; // (2 bytes) Message length (data only) - double data[]; // Up to MAXSIZE doubles (8 bytes each) - } __attribute__((packed)); + struct Payload { + int16_t dev_id; // (2 bytes) Sender device ID + int32_t msg_id; // (4 bytes) Message ID + int16_t msg_len; // (2 bytes) Message length (data only) + double data[]; // Up to MAXSIZE doubles (8 bytes each) + } __attribute__((packed)); - int16_t dev_id; + int16_t dev_id; public: - OpalAsyncIPFormat(int fl, uint8_t did = 0) : - BinaryFormat(fl), - dev_id(did) - { } + OpalAsyncIPFormat(int fl, uint8_t did = 0) : BinaryFormat(fl), dev_id(did) {} - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; class OpalAsyncIPFormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - return new OpalAsyncIPFormat((int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA); - } + virtual Format *make() { + return new OpalAsyncIPFormat((int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_DATA); + } - /// Get plugin name - virtual - std::string getName() const - { - return "opal.asyncip"; - } + /// Get plugin name + virtual std::string getName() const { return "opal.asyncip"; } - /// Get plugin description - virtual - std::string getDescription() const - { - return "OPAL-RTs AsyncIP example format"; - } + /// Get plugin description + virtual std::string getDescription() const { + return "OPAL-RTs AsyncIP example format"; + } }; } // namespace node diff --git a/include/villas/formats/protobuf.hpp b/include/villas/formats/protobuf.hpp index 549ed831d..09048ad72 100644 --- a/include/villas/formats/protobuf.hpp +++ b/include/villas/formats/protobuf.hpp @@ -23,15 +23,15 @@ struct Sample; class ProtobufFormat : public BinaryFormat { protected: - enum SignalType detect(const Villas__Node__Value *val); + enum SignalType detect(const Villas__Node__Value *val); public: - using BinaryFormat::BinaryFormat; + using BinaryFormat::BinaryFormat; - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); }; } // namespace node diff --git a/include/villas/formats/raw.hpp b/include/villas/formats/raw.hpp index a917e696a..42d8632d2 100644 --- a/include/villas/formats/raw.hpp +++ b/include/villas/formats/raw.hpp @@ -7,14 +7,14 @@ #pragma once -#include #include +#include #include // float128 is currently not yet supported as htole128() functions a missing #if 0 && defined(__GNUC__) && defined(__linux__) - #define HAS_128BIT +#define HAS_128BIT #endif namespace villas { @@ -26,43 +26,32 @@ struct Sample; class RawFormat : public BinaryFormat { public: - enum Endianess { - BIG, - LITTLE - }; + enum Endianess { BIG, LITTLE }; protected: - - enum Endianess endianess; - int bits; - bool fake; + enum Endianess endianess; + int bits; + bool fake; public: - RawFormat(int fl, int b = 32, enum Endianess e = Endianess::LITTLE) : - BinaryFormat(fl), - endianess(e), - bits(b), - fake(false) - { - if (fake) - flags |= (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN; - } + RawFormat(int fl, int b = 32, enum Endianess e = Endianess::LITTLE) + : BinaryFormat(fl), endianess(e), bits(b), fake(false) { + if (fake) + flags |= (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_TS_ORIGIN; + } - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; class GtnetRawFormat : public RawFormat { public: - GtnetRawFormat(int fl) : - RawFormat(fl, 32, Endianess::BIG) - { } + GtnetRawFormat(int fl) : RawFormat(fl, 32, Endianess::BIG) {} }; } // namespace node diff --git a/include/villas/formats/value.hpp b/include/villas/formats/value.hpp index 087f4d792..f2ca9c68d 100644 --- a/include/villas/formats/value.hpp +++ b/include/villas/formats/value.hpp @@ -17,12 +17,12 @@ namespace node { class ValueFormat : public Format { public: - using Format::Format; + using Format::Format; - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); }; } // namespace node diff --git a/include/villas/formats/villas_binary.hpp b/include/villas/formats/villas_binary.hpp index e72286532..4597aca4b 100644 --- a/include/villas/formats/villas_binary.hpp +++ b/include/villas/formats/villas_binary.hpp @@ -20,63 +20,56 @@ struct Sample; class VillasBinaryFormat : public BinaryFormat { protected: - uint8_t source_index; - bool web; - bool validate_source_index; + uint8_t source_index; + bool web; + bool validate_source_index; public: - VillasBinaryFormat(int fl, bool w, uint8_t sid = 0) : - BinaryFormat(fl), - source_index(sid), - web(w), - validate_source_index(false) - { } + VillasBinaryFormat(int fl, bool w, uint8_t sid = 0) + : BinaryFormat(fl), source_index(sid), web(w), + validate_source_index(false) {} - virtual - int sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt); - virtual - int sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt); + virtual int sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt); + virtual int sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); }; -template +template class VillasBinaryFormatPlugin : public FormatFactory { public: - using FormatFactory::FormatFactory; + using FormatFactory::FormatFactory; - virtual - Format * make() - { - return new VillasBinaryFormat((int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA, web); - } + virtual Format *make() { + return new VillasBinaryFormat((int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_DATA, + web); + } - /// Get plugin name - virtual - std::string getName() const - { - std::stringstream ss; + /// Get plugin name + virtual std::string getName() const { + std::stringstream ss; - ss << "villas." << (web ? "web" : "binary"); + ss << "villas." << (web ? "web" : "binary"); - return ss.str(); - } + return ss.str(); + } - /// Get plugin description - virtual - std::string getDescription() const - { - std::stringstream ss; + /// Get plugin description + virtual std::string getDescription() const { + std::stringstream ss; - ss << "VILLAS binary network format"; + ss << "VILLAS binary network format"; - if (web) - ss << " for WebSockets"; + if (web) + ss << " for WebSockets"; - return ss.str(); - } + return ss.str(); + } }; } // namespace node diff --git a/include/villas/formats/villas_human.hpp b/include/villas/formats/villas_human.hpp index e7a3ef2f3..fbf620174 100644 --- a/include/villas/formats/villas_human.hpp +++ b/include/villas/formats/villas_human.hpp @@ -17,16 +17,13 @@ namespace node { class VILLASHumanFormat : public LineFormat { protected: - virtual - size_t sprintLine(char *buf, size_t len, const struct Sample *smp); - virtual - size_t sscanLine(const char *buf, size_t len, struct Sample *smp); + virtual size_t sprintLine(char *buf, size_t len, const struct Sample *smp); + virtual size_t sscanLine(const char *buf, size_t len, struct Sample *smp); public: - using LineFormat::LineFormat; + using LineFormat::LineFormat; - virtual - void header(FILE *f, const SignalList::Ptr sigs); + virtual void header(FILE *f, const SignalList::Ptr sigs); }; } // namespace node diff --git a/include/villas/hook.hpp b/include/villas/hook.hpp index 7ef81e269..a83b1d9fe 100644 --- a/include/villas/hook.hpp +++ b/include/villas/hook.hpp @@ -11,12 +11,12 @@ #pragma once +#include #include -#include -#include #include #include -#include +#include +#include namespace villas { namespace node { @@ -29,285 +29,195 @@ class HookFactory; class Hook { - friend HookFactory; + friend HookFactory; public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - enum class Flags { - BUILTIN = (1 << 0), // Should we add this hook by default to every path?. - PATH = (1 << 1), // This hook type is used by paths. - NODE_READ = (1 << 2), // This hook type is used by nodes. - NODE_WRITE = (1 << 3) // This hook type is used by nodes. - }; + enum class Flags { + BUILTIN = (1 << 0), // Should we add this hook by default to every path?. + PATH = (1 << 1), // This hook type is used by paths. + NODE_READ = (1 << 2), // This hook type is used by nodes. + NODE_WRITE = (1 << 3) // This hook type is used by nodes. + }; - enum class Reason { - OK = 0, - ERROR, - SKIP_SAMPLE, - STOP_PROCESSING - }; + enum class Reason { OK = 0, ERROR, SKIP_SAMPLE, STOP_PROCESSING }; protected: - Logger logger; + Logger logger; - HookFactory *factory; + HookFactory *factory; - enum State state; + enum State state; - int flags; - unsigned priority; // A priority to change the order of execution within one type of hook. - bool enabled; // Is this hook active? + int flags; + unsigned + priority; // A priority to change the order of execution within one type of hook. + bool enabled; // Is this hook active? - Path *path; - Node *node; + Path *path; + Node *node; - SignalList::Ptr signals; + SignalList::Ptr signals; - json_t *config; // A JSON object containing the configuration of the hook. + json_t *config; // A JSON object containing the configuration of the hook. public: - Hook(Path *p, Node *n, int fl, int prio, bool en = true); + Hook(Path *p, Node *n, int fl, int prio, bool en = true); - virtual - ~Hook() - { } + virtual ~Hook() {} - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - void prepare(SignalList::Ptr sigs); + void prepare(SignalList::Ptr sigs); - Logger getLogger() - { - return logger; - } + Logger getLogger() { return logger; } - // Called whenever a hook is started; before threads are created. - virtual - void start() - { - assert(state == State::PREPARED); + // Called whenever a hook is started; before threads are created. + virtual void start() { + assert(state == State::PREPARED); - state = State::STARTED; - } + state = State::STARTED; + } - // Called whenever a hook is stopped; after threads are destoyed. - virtual - void stop() - { - assert(state == State::STARTED); + // Called whenever a hook is stopped; after threads are destoyed. + virtual void stop() { + assert(state == State::STARTED); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - void check() - { - assert(state == State::PARSED); + virtual void check() { + assert(state == State::PARSED); - state = State::CHECKED; - } + state = State::CHECKED; + } - virtual - void prepare() - { - assert(state == State::CHECKED); + virtual void prepare() { + assert(state == State::CHECKED); - state = State::PREPARED; - } + state = State::PREPARED; + } - // Called periodically. Period is set by global 'stats' option in the configuration file. - virtual - void periodic() - { - assert(state == State::STARTED); - } + // Called periodically. Period is set by global 'stats' option in the configuration file. + virtual void periodic() { assert(state == State::STARTED); } - // Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. - virtual - void restart() - { - assert(state == State::STARTED); - } + // Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. + virtual void restart() { assert(state == State::STARTED); } - // Called whenever a sample is processed. - virtual - Reason process(struct Sample *smp) - { - return Reason::OK; - }; + // Called whenever a sample is processed. + virtual Reason process(struct Sample *smp) { return Reason::OK; }; - unsigned getPriority() const - { - return priority; - } + unsigned getPriority() const { return priority; } - int getFlags() const - { - return flags; - } + int getFlags() const { return flags; } - virtual - SignalList::Ptr getSignals() const - { - return signals; - } + virtual SignalList::Ptr getSignals() const { return signals; } - json_t * getConfig() const - { - return config; - } + json_t *getConfig() const { return config; } - HookFactory * getFactory() const - { - return factory; - } + HookFactory *getFactory() const { return factory; } - bool isEnabled() const - { - return enabled; - } + bool isEnabled() const { return enabled; } }; class SingleSignalHook : public Hook { protected: - unsigned signalIndex; - std::string signalName; + unsigned signalIndex; + std::string signalName; public: - SingleSignalHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - signalIndex(0) - { } + SingleSignalHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), signalIndex(0) {} - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - void prepare(); + virtual void prepare(); }; class MultiSignalHook : public Hook { protected: - std::list signalIndices; - std::vector signalNames; + std::list signalIndices; + std::vector signalNames; public: - using Hook::Hook; + using Hook::Hook; - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - void prepare(); + virtual void prepare(); - virtual - void check(); + virtual void check(); }; class LimitHook : public Hook { public: - using Ptr = std::shared_ptr; - using Hook::Hook; + using Ptr = std::shared_ptr; + using Hook::Hook; - virtual - void setRate(double rate, double maxRate = -1) = 0; + virtual void setRate(double rate, double maxRate = -1) = 0; - virtual - void parse() - { - assert(state == State::INITIALIZED); + virtual void parse() { + assert(state == State::INITIALIZED); - state = State::PARSED; - } + state = State::PARSED; + } - void init() - { - parse(); - check(); - prepare(); - start(); - } + void init() { + parse(); + check(); + prepare(); + start(); + } }; class HookFactory : public plugin::Plugin { protected: - virtual - void init(Hook::Ptr h) - { - h->logger = getLogger(); - h->factory = this; - } + virtual void init(Hook::Ptr h) { + h->logger = getLogger(); + h->factory = this; + } public: - using plugin::Plugin::Plugin; + using plugin::Plugin::Plugin; - virtual - Hook::Ptr make(Path *p, Node *n) = 0; + virtual Hook::Ptr make(Path *p, Node *n) = 0; - virtual - int getFlags() const = 0; + virtual int getFlags() const = 0; - virtual - unsigned getPriority() const = 0; + virtual unsigned getPriority() const = 0; - virtual - std::string getType() const - { - return "hook"; - } + virtual std::string getType() const { return "hook"; } - virtual - bool isHidden() const - { - return false; - } + virtual bool isHidden() const { return false; } }; -template +template class HookPlugin : public HookFactory { public: - using HookFactory::HookFactory; + using HookFactory::HookFactory; - virtual - Hook::Ptr make(Path *p, Node *n) - { - auto h = std::make_shared(p, n, getFlags(), getPriority()); + virtual Hook::Ptr make(Path *p, Node *n) { + auto h = std::make_shared(p, n, getFlags(), getPriority()); - init(h); + init(h); - return h; - } + return h; + } - virtual - std::string getName() const - { - return name; - } + virtual std::string getName() const { return name; } - virtual - std::string getDescription() const - { - return desc; - } + virtual std::string getDescription() const { return desc; } - virtual - int getFlags() const - { - return flags; - } + virtual int getFlags() const { return flags; } - virtual - unsigned getPriority() const - { - return prio; - } + virtual unsigned getPriority() const { return prio; } }; } // namespace node diff --git a/include/villas/hook_list.hpp b/include/villas/hook_list.hpp index 597b57ae1..daa1bc86e 100644 --- a/include/villas/hook_list.hpp +++ b/include/villas/hook_list.hpp @@ -24,10 +24,9 @@ struct Sample; class HookList : public std::list { public: - HookList() - { } + HookList() {} - /* Parses an object of hooks + /* Parses an object of hooks * * Example: * @@ -41,25 +40,25 @@ public: * hooks = [ "print" ] * } */ - void parse(json_t *json, int mask, Path *p, Node *n); + void parse(json_t *json, int mask, Path *p, Node *n); - void check(); + void check(); - void prepare(SignalList::Ptr sigs, int mask, Path *p, Node *n); + void prepare(SignalList::Ptr sigs, int mask, Path *p, Node *n); - int process(struct Sample *smps[], unsigned cnt); - void periodic(); - void start(); - void stop(); + int process(struct Sample *smps[], unsigned cnt); + void periodic(); + void start(); + void stop(); - void dump(villas::Logger logger, std::string subject) const; + void dump(villas::Logger logger, std::string subject) const; - SignalList::Ptr getSignals() const; + SignalList::Ptr getSignals() const; - // Get the maximum number of signals which is used by any of the hooks in the list. - unsigned getSignalsMaxCount() const; + // Get the maximum number of signals which is used by any of the hooks in the list. + unsigned getSignalsMaxCount() const; - json_t * toJson() const; + json_t *toJson() const; }; } // namespace node diff --git a/include/villas/hooks/decimate.hpp b/include/villas/hooks/decimate.hpp index 01a5388f2..c9e3767a1 100644 --- a/include/villas/hooks/decimate.hpp +++ b/include/villas/hooks/decimate.hpp @@ -15,38 +15,30 @@ namespace node { class DecimateHook : public LimitHook { protected: - int ratio; - bool renumber; - unsigned counter; + int ratio; + bool renumber; + unsigned counter; public: - using LimitHook::LimitHook; + using LimitHook::LimitHook; - virtual - void setRate(double rate, double maxRate = -1) - { - assert(maxRate > 0); + virtual void setRate(double rate, double maxRate = -1) { + assert(maxRate > 0); - int ratio = maxRate / rate; - if (ratio == 0) - ratio = 1; + int ratio = maxRate / rate; + if (ratio == 0) + ratio = 1; - setRatio(ratio); - } + setRatio(ratio); + } - void setRatio(int r) - { - ratio = r; - } + void setRatio(int r) { ratio = r; } - virtual - void start(); + virtual void start(); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; } // namespace node diff --git a/include/villas/hooks/limit_rate.hpp b/include/villas/hooks/limit_rate.hpp index 2ee99b3a3..3ee606069 100644 --- a/include/villas/hooks/limit_rate.hpp +++ b/include/villas/hooks/limit_rate.hpp @@ -15,35 +15,24 @@ namespace node { class LimitRateHook : public LimitHook { protected: - // The timestamp which should be used for limiting. - enum { - LIMIT_RATE_LOCAL, - LIMIT_RATE_RECEIVED, - LIMIT_RATE_ORIGIN - } mode; + // The timestamp which should be used for limiting. + enum { LIMIT_RATE_LOCAL, LIMIT_RATE_RECEIVED, LIMIT_RATE_ORIGIN } mode; - double deadtime; - timespec last; + double deadtime; + timespec last; public: - LimitRateHook(Path *p, Node *n, int fl, int prio, bool en = true) : - LimitHook(p, n, fl, prio, en), - mode(LIMIT_RATE_LOCAL), - deadtime(0), - last({0, 0}) - { } + LimitRateHook(Path *p, Node *n, int fl, int prio, bool en = true) + : LimitHook(p, n, fl, prio, en), mode(LIMIT_RATE_LOCAL), deadtime(0), + last({0, 0}) {} - virtual - void setRate(double rate, double maxRate = -1) - { - deadtime = 1.0 / rate; - } + virtual void setRate(double rate, double maxRate = -1) { + deadtime = 1.0 / rate; + } - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; } // namespace node diff --git a/include/villas/hooks/lua.hpp b/include/villas/hooks/lua.hpp index 85b3365ee..42ba1bece 100644 --- a/include/villas/hooks/lua.hpp +++ b/include/villas/hooks/lua.hpp @@ -7,13 +7,13 @@ #pragma once -#include #include +#include #include extern "C" { - #include "lua.h" +#include "lua.h" }; namespace villas { @@ -26,115 +26,105 @@ enum SignalType; class LuaSignalExpression { protected: - int cookie; - lua_State *L; + int cookie; + lua_State *L; - std::string expression; + std::string expression; - json_t *cfg; + json_t *cfg; public: - LuaSignalExpression(lua_State *L, json_t *json_sig); + LuaSignalExpression(lua_State *L, json_t *json_sig); - void prepare(); + void prepare(); - void parseExpression(const std::string &expr); + void parseExpression(const std::string &expr); - void evaluate(union SignalData *data, enum SignalType type); + void evaluate(union SignalData *data, enum SignalType type); }; class LuaHook : public Hook { - friend LuaSignalExpression; + friend LuaSignalExpression; private: - static - const int SELF_REFERENCE = 55; + static const int SELF_REFERENCE = 55; protected: - std::string script; - std::vector expressions; + std::string script; + std::vector expressions; - SignalList::Ptr signalsProcessed; // Signals as emited by Lua process() function - SignalList::Ptr signalsExpressions; // Signals as emited by Lua expressions + SignalList::Ptr + signalsProcessed; // Signals as emited by Lua process() function + SignalList::Ptr signalsExpressions; // Signals as emited by Lua expressions - lua_State *L; - std::mutex mutex; + lua_State *L; + std::mutex mutex; - bool useNames; - bool hasExpressions; - bool needsLocking; + bool useNames; + bool hasExpressions; + bool needsLocking; - // Function indices - struct { - int start; - int stop; - int restart; - int process; - int periodic; - int prepare; - } functions; + // Function indices + struct { + int start; + int stop; + int restart; + int process; + int periodic; + int prepare; + } functions; - void parseExpressions(json_t *json_sigs); + void parseExpressions(json_t *json_sigs); - void loadScript(); - void lookupFunctions(); - void setupEnvironment(); + void loadScript(); + void lookupFunctions(); + void setupEnvironment(); - // Lua functions + // Lua functions - int luaInfo(lua_State *L); - int luaWarn(lua_State *L); - int luaError(lua_State *L); - int luaDebug(lua_State *L); + int luaInfo(lua_State *L); + int luaWarn(lua_State *L); + int luaError(lua_State *L); + int luaDebug(lua_State *L); - int luaRegisterApiHandler(lua_State *L); + int luaRegisterApiHandler(lua_State *L); - typedef int (LuaHook::*mem_func)(lua_State * L); + typedef int (LuaHook::*mem_func)(lua_State *L); - // This template wraps a member function into a C-style "free" function compatible with lua. - template - static - int dispatch(lua_State * L) { - lua_rawgeti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); - void *vptr = lua_touserdata(L, -1); - lua_pop(L, 1); + // This template wraps a member function into a C-style "free" function compatible with lua. + template static int dispatch(lua_State *L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); + void *vptr = lua_touserdata(L, -1); + lua_pop(L, 1); - LuaHook *ptr = static_cast(vptr); - return ((*ptr).*func)(L); - } + LuaHook *ptr = static_cast(vptr); + return ((*ptr).*func)(L); + } public: - LuaHook(Path *p, Node *n, int fl, int prio, bool en = true); + LuaHook(Path *p, Node *n, int fl, int prio, bool en = true); - virtual - ~LuaHook(); + virtual ~LuaHook(); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - void prepare(); + virtual void prepare(); - // Periodically called by the main thread. - virtual - void periodic(); + // Periodically called by the main thread. + virtual void periodic(); - // Called whenever a hook is started; before threads are created. - virtual - void start(); + // Called whenever a hook is started; before threads are created. + virtual void start(); - // Called whenever a hook is stopped; after threads are destoyed. - virtual - void stop(); + // Called whenever a hook is stopped; after threads are destoyed. + virtual void stop(); - // Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. - virtual - void restart(); + // Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. + virtual void restart(); - // Called whenever a sample is processed. - virtual - Reason process(struct Sample *smp); + // Called whenever a sample is processed. + virtual Reason process(struct Sample *smp); }; } // namespace node diff --git a/include/villas/hooks/pmu.hpp b/include/villas/hooks/pmu.hpp index e530c2632..4b0fd2b0a 100644 --- a/include/villas/hooks/pmu.hpp +++ b/include/villas/hooks/pmu.hpp @@ -15,72 +15,59 @@ namespace node { class PmuHook : public MultiSignalHook { protected: - enum class Status { - INVALID, - VALID - }; + enum class Status { INVALID, VALID }; - struct Phasor { - double frequency; - double amplitude; - double phase; - double rocof; // Rate of change of frequency. - Status valid; - }; + struct Phasor { + double frequency; + double amplitude; + double phase; + double rocof; // Rate of change of frequency. + Status valid; + }; - enum class WindowType { - NONE, - FLATTOP, - HANN, - HAMMING, - NUTTAL, - BLACKMAN - }; + enum class WindowType { NONE, FLATTOP, HANN, HAMMING, NUTTAL, BLACKMAN }; - enum class TimeAlign { - LEFT, - CENTER, - RIGHT, - }; + enum class TimeAlign { + LEFT, + CENTER, + RIGHT, + }; - std::vector*> windows; - dsp::Window *windowsTs; - std::vector lastPhasors; + std::vector *> windows; + dsp::Window *windowsTs; + std::vector lastPhasors; - enum TimeAlign timeAlignType; - enum WindowType windowType; + enum TimeAlign timeAlignType; + enum WindowType windowType; - unsigned sampleRate; - double phasorRate; - double nominalFreq; - double numberPlc; - unsigned windowSize; - bool channelNameEnable; - double angleUnitFactor; - uint64_t lastSequence; - timespec nextRun; - bool init; - unsigned initSampleCount; - // Correction factors. - double phaseOffset; - double amplitudeOffset; - double frequencyOffset; - double rocofOffset; + unsigned sampleRate; + double phasorRate; + double nominalFreq; + double numberPlc; + unsigned windowSize; + bool channelNameEnable; + double angleUnitFactor; + uint64_t lastSequence; + timespec nextRun; + bool init; + unsigned initSampleCount; + // Correction factors. + double phaseOffset; + double amplitudeOffset; + double frequencyOffset; + double rocofOffset; public: - PmuHook(Path *p, Node *n, int fl, int prio, bool en = true); + PmuHook(Path *p, Node *n, int fl, int prio, bool en = true); - virtual - void prepare(); + virtual void prepare(); - virtual - void parse(json_t *json); + virtual void parse(json_t *json); - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); - virtual - Phasor estimatePhasor(dsp::CosineWindow *window, Phasor lastPhasor); + virtual Phasor estimatePhasor(dsp::CosineWindow *window, + Phasor lastPhasor); }; } // namespace node diff --git a/include/villas/kernel/if.hpp b/include/villas/kernel/if.hpp index fce1038bb..a295e80f7 100644 --- a/include/villas/kernel/if.hpp +++ b/include/villas/kernel/if.hpp @@ -12,13 +12,14 @@ #include -#include #include +#include #include #ifndef SO_MARK - #define SO_MARK 36 // Workaround: add missing constant for OPAL-RT Redhawk target +#define SO_MARK \ + 36 // Workaround: add missing constant for OPAL-RT Redhawk target #endif // Forward declarations @@ -33,7 +34,7 @@ namespace node { class Node; class SuperNode; -} +} // namespace node namespace kernel { @@ -41,23 +42,24 @@ namespace kernel { class Interface { public: - struct rtnl_link *nl_link; // libnl3: Handle of interface. - struct rtnl_qdisc *tc_qdisc; // libnl3: Root priority queuing discipline (qdisc). + struct rtnl_link *nl_link; // libnl3: Handle of interface. + struct rtnl_qdisc + *tc_qdisc; // libnl3: Root priority queuing discipline (qdisc). protected: - int affinity; // IRQ / Core Affinity of this interface. + int affinity; // IRQ / Core Affinity of this interface. - std::list irqs; // List of IRQs of the NIC. - std::list nodes; // List of nodes which use this interface. + std::list irqs; // List of IRQs of the NIC. + std::list nodes; // List of nodes which use this interface. - Logger logger; + Logger logger; public: - // Add a new interface to the global list and lookup name, irqs... - Interface(struct rtnl_link *link, int affinity = 0); - ~Interface(); + // Add a new interface to the global list and lookup name, irqs... + Interface(struct rtnl_link *link, int affinity = 0); + ~Interface(); - /* Start interface. + /* Start interface. * * This setups traffic controls queue discs, network emulation and * maps interface IRQs according to affinity. @@ -66,9 +68,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int start(); + int start(); - /* Stop interface + /* Stop interface * * This resets traffic qdiscs ant network emulation * and maps interface IRQs to all CPUs. @@ -77,16 +79,14 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int stop(); + int stop(); - /* Find existing or create new interface instance on which packets for a certain destination + /* Find existing or create new interface instance on which packets for a certain destination * will leave the system. */ - static - Interface * - getEgress(struct sockaddr *sa, node::SuperNode *sn); + static Interface *getEgress(struct sockaddr *sa, node::SuperNode *sn); - /* Get all IRQs for this interface. + /* Get all IRQs for this interface. * * Only MSI IRQs are determined by looking at: * /sys/class/net/{ifname}/device/msi_irqs/ @@ -95,23 +95,20 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int getIRQs(); + int getIRQs(); - /* Change the SMP affinity of NIC interrupts. + /* Change the SMP affinity of NIC interrupts. * * @param i A pointer to the interface structure * @param affinity A mask specifying which cores should handle this interrupt. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int setAffinity(int affinity); + int setAffinity(int affinity); - std::string getName() const; + std::string getName() const; - void addNode(node::Node *n) - { - nodes.push_back(n); - } + void addNode(node::Node *n) { nodes.push_back(n); } }; } // namespace kernel diff --git a/include/villas/kernel/nl-private.h b/include/villas/kernel/nl-private.h index b7d6ff799..37d185cfa 100644 --- a/include/villas/kernel/nl-private.h +++ b/include/villas/kernel/nl-private.h @@ -16,44 +16,39 @@ extern "C" { #define SCH_NETEM_ATTR_DIST 0x2000 -struct rtnl_netem_corr -{ - uint32_t nmc_delay; - uint32_t nmc_loss; - uint32_t nmc_duplicate; +struct rtnl_netem_corr { + uint32_t nmc_delay; + uint32_t nmc_loss; + uint32_t nmc_duplicate; }; -struct rtnl_netem_reo -{ - uint32_t nmro_probability; - uint32_t nmro_correlation; +struct rtnl_netem_reo { + uint32_t nmro_probability; + uint32_t nmro_correlation; }; -struct rtnl_netem_crpt -{ - uint32_t nmcr_probability; - uint32_t nmcr_correlation; +struct rtnl_netem_crpt { + uint32_t nmcr_probability; + uint32_t nmcr_correlation; }; -struct rtnl_netem_dist -{ - int16_t * dist_data; - size_t dist_size; +struct rtnl_netem_dist { + int16_t *dist_data; + size_t dist_size; }; -struct rtnl_netem -{ - uint32_t qnm_latency; - uint32_t qnm_limit; - uint32_t qnm_loss; - uint32_t qnm_gap; - uint32_t qnm_duplicate; - uint32_t qnm_jitter; - uint32_t qnm_mask; - struct rtnl_netem_corr qnm_corr; - struct rtnl_netem_reo qnm_ro; - struct rtnl_netem_crpt qnm_crpt; - struct rtnl_netem_dist qnm_dist; +struct rtnl_netem { + uint32_t qnm_latency; + uint32_t qnm_limit; + uint32_t qnm_loss; + uint32_t qnm_gap; + uint32_t qnm_duplicate; + uint32_t qnm_jitter; + uint32_t qnm_mask; + struct rtnl_netem_corr qnm_corr; + struct rtnl_netem_reo qnm_ro; + struct rtnl_netem_crpt qnm_crpt; + struct rtnl_netem_dist qnm_dist; }; void *rtnl_tc_data(struct rtnl_tc *tc); diff --git a/include/villas/kernel/nl.hpp b/include/villas/kernel/nl.hpp index 2317a347b..94d4af69d 100644 --- a/include/villas/kernel/nl.hpp +++ b/include/villas/kernel/nl.hpp @@ -10,8 +10,8 @@ #include #include -#include #include +#include namespace villas { namespace kernel { @@ -32,10 +32,10 @@ int get_egress(struct nl_addr *addr); * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ -struct rtnl_link * get_egress_link(struct sockaddr *sa); +struct rtnl_link *get_egress_link(struct sockaddr *sa); // Get or create global netlink socket. -struct nl_sock * init(); +struct nl_sock *init(); // Close and free global netlink socket. void shutdown(); diff --git a/include/villas/kernel/tc.hpp b/include/villas/kernel/tc.hpp index 540ba90e1..923f0062b 100644 --- a/include/villas/kernel/tc.hpp +++ b/include/villas/kernel/tc.hpp @@ -14,8 +14,8 @@ #include -#include #include +#include #include @@ -47,7 +47,8 @@ int reset(Interface *i); * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ -int prio(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t, int bands); +int prio(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t, + int bands); /* Add a new filter based on the netfilter mark. * diff --git a/include/villas/kernel/tc_netem.hpp b/include/villas/kernel/tc_netem.hpp index 4fe586759..a119fcd09 100644 --- a/include/villas/kernel/tc_netem.hpp +++ b/include/villas/kernel/tc_netem.hpp @@ -14,8 +14,8 @@ #include -#include #include +#include #include @@ -43,7 +43,7 @@ int netem_parse(struct rtnl_qdisc **ne, json_t *json); * @param tc A pointer to the libnl3 qdisc object where settings will be read from. * @return A pointer to a string which must be freed() by the caller. */ -char * netem_print(struct rtnl_qdisc *ne); +char *netem_print(struct rtnl_qdisc *ne); /* Add a new network emulator (netem) discipline. * @@ -54,7 +54,8 @@ char * netem_print(struct rtnl_qdisc *ne); * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ -int netem(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t parent); +int netem(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, + tc_hdl_t parent); int netem_set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json); diff --git a/include/villas/log_opal_sink.hpp b/include/villas/log_opal_sink.hpp index e0e85eb79..76520091e 100644 --- a/include/villas/log_opal_sink.hpp +++ b/include/villas/log_opal_sink.hpp @@ -9,44 +9,41 @@ #include -#include #include +#include -#include #include +#include extern "C" { - /* Define RTLAB before including OpalPrint.h for messages to be sent +/* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ - #define RTLAB - #include +#define RTLAB +#include } namespace villas { namespace node { -template -class OpalSink : public spdlog::sinks::base_sink -{ +template +class OpalSink : public spdlog::sinks::base_sink { protected: - void sink_it_(const spdlog::details::log_msg &msg) override - { + void sink_it_(const spdlog::details::log_msg &msg) override { #ifdef WITH_NODE_OPAL - fmt::memory_buffer formatted; + fmt::memory_buffer formatted; - sink::formatter_->format(msg, formatted); + sink::formatter_->format(msg, formatted); - auto str = fmt::to_string(formatted).c_str(); + auto str = fmt::to_string(formatted).c_str(); - OpalPrint(PROJECT_NAME ": %s\n", str); + OpalPrint(PROJECT_NAME ": %s\n", str); #endif - } + } - void flush_() override - { - // nothing to do - } + void flush_() override { + // nothing to do + } }; using OpalSink_mt = OpalSink; diff --git a/include/villas/mapping.hpp b/include/villas/mapping.hpp index d347cb959..5a04b9c3e 100644 --- a/include/villas/mapping.hpp +++ b/include/villas/mapping.hpp @@ -11,18 +11,21 @@ #include #include -#include #include +#include #define RE_MAPPING_INDEX "[a-zA-Z0-9_]+" #define RE_MAPPING_RANGE "(" RE_MAPPING_INDEX ")(?:-(" RE_MAPPING_INDEX "))?" #define RE_MAPPING_STATS "stats\\.([a-z]+)\\.([a-z]+)" -#define RE_MAPPING_HDR "hdr\\.(sequence|length)" -#define RE_MAPPING_TS "ts\\.(origin|received)" +#define RE_MAPPING_HDR "hdr\\.(sequence|length)" +#define RE_MAPPING_TS "ts\\.(origin|received)" #define RE_MAPPING_DATA1 "data\\[" RE_MAPPING_RANGE "\\]" #define RE_MAPPING_DATA2 "(?:data\\.)?(" RE_MAPPING_INDEX ")" -#define RE_MAPPING "(?:(" RE_NODE_NAME ")\\.(?:" RE_MAPPING_STATS "|" RE_MAPPING_HDR "|" RE_MAPPING_TS "|" RE_MAPPING_DATA1 "|" RE_MAPPING_DATA2 ")|(" RE_NODE_NAME ")(?:\\[" RE_MAPPING_RANGE "\\])?)" +#define RE_MAPPING \ + "(?:(" RE_NODE_NAME ")\\.(?:" RE_MAPPING_STATS "|" RE_MAPPING_HDR \ + "|" RE_MAPPING_TS "|" RE_MAPPING_DATA1 "|" RE_MAPPING_DATA2 \ + ")|(" RE_NODE_NAME ")(?:\\[" RE_MAPPING_RANGE "\\])?)" namespace villas { namespace node { @@ -35,74 +38,62 @@ class Signal; class MappingEntry { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - enum class Type { - UNKNOWN, - DATA, - STATS, - HEADER, - TIMESTAMP - }; + enum class Type { UNKNOWN, DATA, STATS, HEADER, TIMESTAMP }; - enum class HeaderType { - LENGTH, - SEQUENCE - }; + enum class HeaderType { LENGTH, SEQUENCE }; - enum class TimestampType { - ORIGIN, - RECEIVED - }; + enum class TimestampType { ORIGIN, RECEIVED }; - Node *node; // The node to which this mapping refers. - enum Type type; // The mapping type. Selects one of the union fields below. + Node *node; // The node to which this mapping refers. + enum Type type; // The mapping type. Selects one of the union fields below. - /* The number of values which is covered by this mapping entry. + /* The number of values which is covered by this mapping entry. * * A value of 0 indicates that all remaining values starting from the offset of a sample should be mapped. */ - int length; - unsigned offset; // Offset of this mapping entry within sample::data + int length; + unsigned offset; // Offset of this mapping entry within sample::data - union { - struct { - int offset; - Signal *signal; + union { + struct { + int offset; + Signal *signal; - char *first; - char *last; - } data; + char *first; + char *last; + } data; - struct { - enum Stats::Metric metric; - enum Stats::Type type; - } stats; + struct { + enum Stats::Metric metric; + enum Stats::Type type; + } stats; - struct { - enum HeaderType type; - } header; + struct { + enum HeaderType type; + } header; - struct { - enum TimestampType type; - } timestamp; - }; + struct { + enum TimestampType type; + } timestamp; + }; - std::string nodeName; // Used for between parse and prepare only. + std::string nodeName; // Used for between parse and prepare only. - MappingEntry(); + MappingEntry(); - int prepare(NodeList &nodes); + int prepare(NodeList &nodes); - int update(struct Sample *remapped, const struct Sample *original) const; + int update(struct Sample *remapped, const struct Sample *original) const; - int parse(json_t *json); + int parse(json_t *json); - int parseString(const std::string &str); + int parseString(const std::string &str); - std::string toString(unsigned index) const; + std::string toString(unsigned index) const; - Signal::Ptr toSignal(unsigned index) const; + Signal::Ptr toSignal(unsigned index) const; }; } // namespace node diff --git a/include/villas/mapping_list.hpp b/include/villas/mapping_list.hpp index 47218ef6e..10f228af7 100644 --- a/include/villas/mapping_list.hpp +++ b/include/villas/mapping_list.hpp @@ -18,13 +18,14 @@ namespace node { class MappingList : public std::list { public: - int parse(json_t *json); + int parse(json_t *json); - int prepare(NodeList &nodes); + int prepare(NodeList &nodes); - int remap(struct Sample *remapped, const struct Sample *original) const; + int remap(struct Sample *remapped, const struct Sample *original) const; - int update(const MappingEntry::Ptr me, struct Sample *remapped, const struct Sample *original); + int update(const MappingEntry::Ptr me, struct Sample *remapped, + const struct Sample *original); }; } // namespace node diff --git a/include/villas/memory/ib.h b/include/villas/memory/ib.h index 56e2a559c..26c313cf8 100644 --- a/include/villas/memory/ib.h +++ b/include/villas/memory/ib.h @@ -14,11 +14,11 @@ namespace node { namespace memory { struct IB { - struct ibv_pd *pd; - struct Type *parent; + struct ibv_pd *pd; + struct Type *parent; }; -struct ibv_mr * ib_get_mr(void *ptr); +struct ibv_mr *ib_get_mr(void *ptr); } // namespace memory } // namespace node diff --git a/include/villas/node.h b/include/villas/node.h index f0f504eb4..333670f66 100644 --- a/include/villas/node.h +++ b/include/villas/node.h @@ -14,7 +14,7 @@ typedef void *vnode; typedef void *vsample; -vnode * node_new(const char *id_str, const char *json_str); +vnode *node_new(const char *id_str, const char *json_str); int node_prepare(vnode *n); @@ -32,13 +32,13 @@ int node_restart(vnode *n); int node_destroy(vnode *n); -const char * node_name(vnode *n); +const char *node_name(vnode *n); -const char * node_name_short(vnode *n); +const char *node_name_short(vnode *n); -const char * node_name_full(vnode *n); +const char *node_name_full(vnode *n); -const char * node_details(vnode *n); +const char *node_details(vnode *n); unsigned node_input_signals_max_cnt(vnode *n); @@ -58,18 +58,22 @@ bool node_is_valid_name(const char *name); bool node_is_enabled(const vnode *n); -json_t * node_to_json(const vnode *n); +json_t *node_to_json(const vnode *n); -const char * node_to_json_str(vnode *n); +const char *node_to_json_str(vnode *n); -vsample * sample_alloc(unsigned len); +vsample *sample_alloc(unsigned len); unsigned sample_length(vsample *smp); void sample_decref(vsample *smp); -vsample * sample_pack(unsigned seq, struct timespec *ts_origin, struct timespec *ts_received, unsigned len, double *values); +vsample *sample_pack(unsigned seq, struct timespec *ts_origin, + struct timespec *ts_received, unsigned len, + double *values); -void sample_unpack(vsample *s, unsigned *seq, struct timespec *ts_origin, struct timespec *ts_received, int *flags, unsigned *len, double *values); +void sample_unpack(vsample *s, unsigned *seq, struct timespec *ts_origin, + struct timespec *ts_received, int *flags, unsigned *len, + double *values); int memory_init(int hugepages); diff --git a/include/villas/node.hpp b/include/villas/node.hpp index 666210516..73c7dd491 100644 --- a/include/villas/node.hpp +++ b/include/villas/node.hpp @@ -8,31 +8,31 @@ #pragma once #include -#include #include +#include -#include -#include -#include -#include -#include -#include #include #include -#include +#include #include -#include -#include +#include +#include +#include #include +#include +#include +#include +#include +#include #if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__) - #define WITH_NETEM +#define WITH_NETEM #endif // LIBNL3_ROUTE_FOUND // Forward declarations #ifdef WITH_NETEM - struct rtnl_qdisc; - struct rtnl_cls; +struct rtnl_qdisc; +struct rtnl_cls; #endif // WITH_NETEM #define RE_NODE_NAME "[a-z0-9_-]{2,32}" @@ -51,123 +51,102 @@ class SuperNode; */ class Node { - friend NodeFactory; + friend NodeFactory; public: - Logger logger; + Logger logger; - uint64_t sequence_init; - uint64_t sequence; // This is a counter of received samples, in case the node-type does not generate sequence numbers itself. + uint64_t sequence_init; + uint64_t + sequence; // This is a counter of received samples, in case the node-type does not generate sequence numbers itself. - NodeDirection in, out; + NodeDirection in, out; - PathSourceList sources; // A list of path sources which reference this node. - PathDestinationList destinations; // A list of path destinations which reference this node. + PathSourceList sources; // A list of path sources which reference this node. + PathDestinationList + destinations; // A list of path destinations which reference this node. #ifdef __linux__ - int fwmark; // Socket mark for netem, routing and filtering + int fwmark; // Socket mark for netem, routing and filtering #ifdef WITH_NETEM - struct rtnl_qdisc *tc_qdisc; // libnl3: Network emulator queuing discipline - struct rtnl_cls *tc_classifier; // libnl3: Firewall mark classifier -#endif // WITH_NETEM -#endif // __linux__ + struct rtnl_qdisc *tc_qdisc; // libnl3: Network emulator queuing discipline + struct rtnl_cls *tc_classifier; // libnl3: Firewall mark classifier +#endif // WITH_NETEM +#endif // __linux__ protected: - enum State state; + enum State state; - uuid_t uuid; + uuid_t uuid; - bool enabled; + bool enabled; - Stats::Ptr stats; // Statistic counters. This is a pointer to the statistic hooks private data. + Stats::Ptr + stats; // Statistic counters. This is a pointer to the statistic hooks private data. - json_t *config; // A JSON object containing the configuration of the node. + json_t *config; // A JSON object containing the configuration of the node. - std::string name_short; // A short identifier of the node, only used for configuration and logging - std::string name_long; // Singleton: A string used to print to screen. - std::string name_full; // Singleton: A string used to print to screen. - std::string details; + std::string + name_short; // A short identifier of the node, only used for configuration and logging + std::string name_long; // Singleton: A string used to print to screen. + std::string name_full; // Singleton: A string used to print to screen. + std::string details; - int affinity; // CPU Affinity of this node + int affinity; // CPU Affinity of this node - NodeFactory *factory; // The factory which created this instance + NodeFactory *factory; // The factory which created this instance - virtual - int _read(struct Sample * smps[], unsigned cnt) - { - return -1; - } + virtual int _read(struct Sample *smps[], unsigned cnt) { return -1; } - virtual - int _write(struct Sample * smps[], unsigned cnt) - { - return -1; - } + virtual int _write(struct Sample *smps[], unsigned cnt) { return -1; } - virtual - json_t * _readStatus() const - { - return nullptr; - } + virtual json_t *_readStatus() const { return nullptr; } public: - // Initialize node with default values - Node(const uuid_t &id = {}, const std::string &name = ""); + // Initialize node with default values + Node(const uuid_t &id = {}, const std::string &name = ""); - // Destroy node by freeing dynamically allocated memory. - virtual - ~Node(); + // Destroy node by freeing dynamically allocated memory. + virtual ~Node(); - // Do initialization after parsing the configuration - virtual - int prepare(); + // Do initialization after parsing the configuration + virtual int prepare(); - /* Parse settings of a node. + /* Parse settings of a node. * * @param json A JSON object containing the configuration of the node. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - // Validate node configuration. - virtual - int check(); + // Validate node configuration. + virtual int check(); - // Start operation of a node. - virtual - int start(); + // Start operation of a node. + virtual int start(); - // Stops operation of a node. - virtual - int stop(); + // Stops operation of a node. + virtual int stop(); - // Pauses operation of a node. - virtual - int pause() - { - if (state != State::STARTED) - return -1; + // Pauses operation of a node. + virtual int pause() { + if (state != State::STARTED) + return -1; - logger->info("Pausing node"); + logger->info("Pausing node"); - return 0; - } + return 0; + } - // Resumes operation of a node. - virtual - int resume() - { - return 0; - } + // Resumes operation of a node. + virtual int resume() { return 0; } - // Restarts operation of a node. - virtual - int restart(); + // Restarts operation of a node. + virtual int restart(); - /* Receive multiple messages at once. + /* Receive multiple messages at once. * * This callback is optional. It will only be called if non-null. * @@ -181,9 +160,9 @@ public: * @param cnt The number of samples that are allocated by the calling function. * @return The number of messages actually received. */ - int read(struct Sample * smps[], unsigned cnt); + int read(struct Sample *smps[], unsigned cnt); - /* Send multiple messages in a single datagram / packet. + /* Send multiple messages in a single datagram / packet. * * This callback is optional. It will only be called if non-null. * @@ -196,290 +175,193 @@ public: * @param cnt The number of samples that are allocated by the calling function. * @return The number of messages actually sent. */ - int write(struct Sample * smps[], unsigned cnt); + int write(struct Sample *smps[], unsigned cnt); - // Reverse local and remote socket address. - virtual - int reverse() - { - return -1; - } + // Reverse local and remote socket address. + virtual int reverse() { return -1; } - /* Get a list of file descriptors on which the path should poll + /* Get a list of file descriptors on which the path should poll * to detect the availability of new samples which can be read. */ - virtual - std::vector getPollFDs() - { - return {}; - } + virtual std::vector getPollFDs() { return {}; } - /* Get a list of socket file descriptors which are used by the node + /* Get a list of socket file descriptors which are used by the node * To perform network IO. We use those to selectively apply network emulation */ - virtual - std::vector getNetemFDs() - { - return {}; - } + virtual std::vector getNetemFDs() { return {}; } - /* Get the memory type which this node-type expects. + /* Get the memory type which this node-type expects. * * This is useful for special node-types like Infiniband, GPUs & FPGAs * which require DMA-backed memory. */ - virtual - struct villas::node::memory::Type * getMemoryType() - { - return villas::node::memory::default_type; - } + virtual struct villas::node::memory::Type *getMemoryType() { + return villas::node::memory::default_type; + } - // Get the factory which was used to construct this node. - villas::node::NodeFactory * getFactory() const - { - return factory; - } + // Get the factory which was used to construct this node. + villas::node::NodeFactory *getFactory() const { return factory; } - /* Return a pointer to a string which should be used to print this node. + /* Return a pointer to a string which should be used to print this node. * * @param n A pointer to the node structure. */ - std::string getNameShort() const - { - return name_short; - } + std::string getNameShort() const { return name_short; } - // Return a pointer to a string which should be used to print this node. - const std::string & getName() const - { - return name_long; - } + // Return a pointer to a string which should be used to print this node. + const std::string &getName() const { return name_long; } - // Get the full name including type and details of the node. - const std::string & getNameFull(); + // Get the full name including type and details of the node. + const std::string &getNameFull(); - // Just get the config details of this node as a string - virtual - const std::string & getDetails() - { - static - std::string empty; + // Just get the config details of this node as a string + virtual const std::string &getDetails() { + static std::string empty; - return empty; - } + return empty; + } - /* Return a pointer to a string which should be used to print this node. + /* Return a pointer to a string which should be used to print this node. * * @param n A pointer to the node structure. */ - const std::string & getNameLong(); + const std::string &getNameLong(); - /* Return a list of signals which are sent to this node. + /* Return a list of signals which are sent to this node. * * This list is derived from the path which uses the node as destination. */ - SignalList::Ptr getOutputSignals(bool after_hooks = true) const; - SignalList::Ptr getInputSignals(bool after_hooks = true) const; + SignalList::Ptr getOutputSignals(bool after_hooks = true) const; + SignalList::Ptr getInputSignals(bool after_hooks = true) const; - // Get the number of input signals (received by this node) - unsigned getInputSignalsMaxCount() const; + // Get the number of input signals (received by this node) + unsigned getInputSignalsMaxCount() const; - // Get the number of output signals (send out via this node) - unsigned getOutputSignalsMaxCount() const; + // Get the number of output signals (send out via this node) + unsigned getOutputSignalsMaxCount() const; - void swapSignals(); + void swapSignals(); - // Get the node configuration as JSON. - json_t * getConfig() - { - return config; - } + // Get the node configuration as JSON. + json_t *getConfig() { return config; } - // Get the state of this node. - enum State getState() const - { - return state; - } + // Get the state of this node. + enum State getState() const { return state; } - // Set the state of this node. - void setState(enum State s) - { - state = s; - } + // Set the state of this node. + void setState(enum State s) { state = s; } - // Get the UUID of this node. - const uuid_t & getUuid() const - { - return uuid; - } + // Get the UUID of this node. + const uuid_t &getUuid() const { return uuid; } - std::shared_ptr getStats() - { - return stats; - } + std::shared_ptr getStats() { return stats; } - void setStats(std::shared_ptr sts) - { - stats = sts; - } + void setStats(std::shared_ptr sts) { stats = sts; } - void setEnabled(bool en) - { - enabled = en; - } + void setEnabled(bool en) { enabled = en; } - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const Node &n) - { - os << n.getName(); + // Custom formatter for spdlog + template + friend OStream &operator<<(OStream &os, const Node &n) { + os << n.getName(); - return os; - } + return os; + } - json_t * toJson() const; + json_t *toJson() const; - static - bool isValidName(const std::string &name); + static bool isValidName(const std::string &name); - bool isEnabled() const - { - return enabled; - } + bool isEnabled() const { return enabled; } }; class NodeFactory : public villas::plugin::Plugin { - friend Node; + friend Node; protected: - virtual - void init(Node *n) - { - n->logger = getLogger(); - n->factory = this; + virtual void init(Node *n) { + n->logger = getLogger(); + n->factory = this; - n->name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", n->name_short, getName()); + n->name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", + n->name_short, getName()); - instances.push_back(n); - } + instances.push_back(n); + } - State state; + State state; public: - enum class Flags { - SUPPORTS_POLL = (1 << 0), - SUPPORTS_READ = (1 << 1), - SUPPORTS_WRITE = (1 << 2), - REQUIRES_WEB = (1 << 3), - PROVIDES_SIGNALS = (1 << 4), - INTERNAL = (1 << 5), - HIDDEN = (1 << 6) - }; + enum class Flags { + SUPPORTS_POLL = (1 << 0), + SUPPORTS_READ = (1 << 1), + SUPPORTS_WRITE = (1 << 2), + REQUIRES_WEB = (1 << 3), + PROVIDES_SIGNALS = (1 << 4), + INTERNAL = (1 << 5), + HIDDEN = (1 << 6) + }; - NodeList instances; + NodeList instances; - NodeFactory() : - Plugin() - { - state = State::INITIALIZED; - } + NodeFactory() : Plugin() { state = State::INITIALIZED; } - virtual - Node * make(const uuid_t &id = {}, const std::string &nme = "") = 0; + virtual Node *make(const uuid_t &id = {}, const std::string &nme = "") = 0; - static - Node * make(json_t *json, const uuid_t &id, const std::string &name = ""); + static Node *make(json_t *json, const uuid_t &id, + const std::string &name = ""); - static - Node * make(const std::string &type, const uuid_t &id = {}, const std::string &name = ""); + static Node *make(const std::string &type, const uuid_t &id = {}, + const std::string &name = ""); - virtual - std::string getType() const - { - return "node"; - } + virtual std::string getType() const { return "node"; } - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const NodeFactory &f) - { - os << f.getName(); + // Custom formatter for spdlog + template + friend OStream &operator<<(OStream &os, const NodeFactory &f) { + os << f.getName(); - return os; - } + return os; + } - virtual - int getFlags() const - { - return 0; - } + virtual int getFlags() const { return 0; } - virtual - int getVectorize() const - { - return 0; - } + virtual int getVectorize() const { return 0; } - bool isInternal() const - { - return getFlags() & (int) Flags::INTERNAL; - } + bool isInternal() const { return getFlags() & (int)Flags::INTERNAL; } - bool isHidden() const - { - return isInternal() || getFlags() & (int) Flags::HIDDEN; - } + bool isHidden() const { + return isInternal() || getFlags() & (int)Flags::HIDDEN; + } - virtual - int start(SuperNode *sn); + virtual int start(SuperNode *sn); - virtual - int stop(); + virtual int stop(); - State getState() const - { - return state; - } + State getState() const { return state; } }; -template +template class NodePlugin : public NodeFactory { public: - virtual - Node * make(const uuid_t &id = {}, const std::string &nme = "") - { - T* n = new T(id, nme); + virtual Node *make(const uuid_t &id = {}, const std::string &nme = "") { + T *n = new T(id, nme); - init(n); + init(n); - return n; - } + return n; + } - virtual - int getFlags() const - { - return flags; - } + virtual int getFlags() const { return flags; } - virtual - int getVectorize() const - { - return vectorize; - } + virtual int getVectorize() const { return vectorize; } - virtual - std::string getName() const - { - return name; - } + virtual std::string getName() const { return name; } - virtual - std::string getDescription() const - { - return desc; - } + virtual std::string getDescription() const { return desc; } }; } // namespace node diff --git a/include/villas/node/exceptions.hpp b/include/villas/node/exceptions.hpp index 0093585f8..e84eba2a9 100644 --- a/include/villas/node/exceptions.hpp +++ b/include/villas/node/exceptions.hpp @@ -7,11 +7,11 @@ #pragma once -#include #include +#include #ifdef WITH_CONFIG - #include +#include #endif namespace villas { @@ -20,54 +20,40 @@ namespace node { class ParseError : public RuntimeError { protected: - std::string text; - std::string file; - int line; - int column; + std::string text; + std::string file; + int line; + int column; public: - ParseError(const std::string &t, const std::string &f, int l, int c = 0) : - RuntimeError("Failed to parse configuration: {} in {}:{}", t, f, l), - text(t), - file(f), - line(l), - column(c) - { } + ParseError(const std::string &t, const std::string &f, int l, int c = 0) + : RuntimeError("Failed to parse configuration: {} in {}:{}", t, f, l), + text(t), file(f), line(l), column(c) {} }; #ifdef WITH_CONFIG class LibconfigParseError : public ParseError { protected: - const config_t *config; + const config_t *config; public: - LibconfigParseError(const config_t *c) : - ParseError( - config_error_text(c), - config_error_file(c) ? config_error_file(c) : "", - config_error_line(c) - ), - config(c) - { } + LibconfigParseError(const config_t *c) + : ParseError(config_error_text(c), + config_error_file(c) ? config_error_file(c) : "", + config_error_line(c)), + config(c) {} }; #endif // WITH_CONFIG class JanssonParseError : public ParseError { protected: - json_error_t error; + json_error_t error; public: - JanssonParseError(json_error_t e) : - ParseError( - e.text, - e.source, - e.line, - e.column - ), - error(e) - { } + JanssonParseError(json_error_t e) + : ParseError(e.text, e.source, e.line, e.column), error(e) {} }; } // namespace node diff --git a/include/villas/node/memory.hpp b/include/villas/node/memory.hpp index 82431c808..1fcdc8c54 100644 --- a/include/villas/node/memory.hpp +++ b/include/villas/node/memory.hpp @@ -8,7 +8,7 @@ #pragma once #ifdef IBVERBS_FOUND - #include +#include #endif // IBVERBS_FOUND #include @@ -24,36 +24,36 @@ namespace memory { /* Descriptor of a memory block. Associated block always starts at * &m + sizeof(struct Block). */ struct Block { - struct Block *prev; - struct Block *next; - size_t length; // Length of the block; doesn't include the descriptor itself - bool used; + struct Block *prev; + struct Block *next; + size_t length; // Length of the block; doesn't include the descriptor itself + bool used; }; // TODO: Unused for now struct Allocation { - struct Type *type; + struct Type *type; - struct Allocation *parent; + struct Allocation *parent; - void *address; - size_t alignment; - size_t length; + void *address; + size_t alignment; + size_t length; - union { + union { #ifdef IBVERBS_FOUND - struct { - struct ibv_mr *mr; - } ib; + struct { + struct ibv_mr *mr; + } ib; #endif - struct { - struct Block *block; - } managed; - }; + struct { + struct Block *block; + } managed; + }; }; // Initilialize memory subsystem -int init(int hugepages) __attribute__ ((warn_unused_result)); +int init(int hugepages) __attribute__((warn_unused_result)); int lock(size_t lock); @@ -62,13 +62,14 @@ int lock(size_t lock); * @retval nullptr If allocation failed. * @retval <>0 If allocation was successful. */ -void * alloc(size_t len, struct Type *m = default_type); +void *alloc(size_t len, struct Type *m = default_type); -void * alloc_aligned(size_t len, size_t alignment, struct Type *m = default_type); +void *alloc_aligned(size_t len, size_t alignment, + struct Type *m = default_type); int free(void *ptr); -struct Allocation * get_allocation(void *ptr); +struct Allocation *get_allocation(void *ptr); } // namespace memory } // namespace node diff --git a/include/villas/node/memory_type.hpp b/include/villas/node/memory_type.hpp index 553a94483..6f832dd51 100644 --- a/include/villas/node/memory_type.hpp +++ b/include/villas/node/memory_type.hpp @@ -20,41 +20,38 @@ namespace memory { struct Type; -typedef struct Allocation * (*allocator_t)(size_t len, size_t alignment, struct Type *mem); -typedef int (*deallocator_t)(struct Allocation * ma, struct Type *mem); +typedef struct Allocation *(*allocator_t)(size_t len, size_t alignment, + struct Type *mem); +typedef int (*deallocator_t)(struct Allocation *ma, struct Type *mem); enum class Flags { - MMAP = (1 << 0), - DMA = (1 << 1), - HUGEPAGE = (1 << 2), - HEAP = (1 << 3) + MMAP = (1 << 0), + DMA = (1 << 1), + HUGEPAGE = (1 << 2), + HEAP = (1 << 3) }; struct Type { - const char *name; - int flags; + const char *name; + int flags; - size_t alignment; + size_t alignment; - allocator_t alloc; - deallocator_t free; + allocator_t alloc; + deallocator_t free; - void *_vd; // Virtual data for internal state + void *_vd; // Virtual data for internal state }; -extern -struct Type heap; -extern -struct Type mmap; -extern -struct Type mmap_hugetlb; -extern -struct Type *default_type; +extern struct Type heap; +extern struct Type mmap; +extern struct Type mmap_hugetlb; +extern struct Type *default_type; -struct Type * ib(NodeCompat *n, struct Type *parent); -struct Type * managed(void *ptr, size_t len); +struct Type *ib(NodeCompat *n, struct Type *parent); +struct Type *managed(void *ptr, size_t len); -int mmap_init(int hugepages) __attribute__ ((warn_unused_result)); +int mmap_init(int hugepages) __attribute__((warn_unused_result)); } // namespace memory } // namespace node diff --git a/include/villas/node_compat.hpp b/include/villas/node_compat.hpp index b023bfb3f..00e8b4016 100644 --- a/include/villas/node_compat.hpp +++ b/include/villas/node_compat.hpp @@ -5,14 +5,13 @@ * SPDX-License-Identifier: Apache-2.0 */ - #pragma once #include -#include #include #include +#include namespace villas { namespace node { @@ -23,174 +22,132 @@ class NodeCompatFactory; class NodeCompat : public Node { protected: - struct NodeCompatType *_vt; // Virtual functions (C++ OOP style) - void *_vd; // Virtual data (used by struct vnode::_vt functions) + struct NodeCompatType *_vt; // Virtual functions (C++ OOP style) + void *_vd; // Virtual data (used by struct vnode::_vt functions) - std::string _details; + std::string _details; - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample *smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); public: - NodeCompat *node; - json_t *cfg; + NodeCompat *node; + json_t *cfg; - NodeCompat(struct NodeCompatType *vt, const uuid_t &id, const std::string &name); - NodeCompat(const NodeCompat& n); + NodeCompat(struct NodeCompatType *vt, const uuid_t &id, + const std::string &name); + NodeCompat(const NodeCompat &n); - NodeCompat& operator=(const NodeCompat& other); + NodeCompat &operator=(const NodeCompat &other); - virtual - ~NodeCompat(); + virtual ~NodeCompat(); - template - T * getData() - { - return static_cast(_vd); - } + template T *getData() { return static_cast(_vd); } - virtual - NodeCompatType * getType() const - { - return _vt; - } + virtual NodeCompatType *getType() const { return _vt; } - /* Parse node connection details. + /* Parse node connection details. * * @param json A JSON object containing the configuration of the node. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - // Returns a string with a textual represenation of this node. - virtual - const std::string & getDetails(); + // Returns a string with a textual represenation of this node. + virtual const std::string &getDetails(); - /* Check the current node configuration for plausability and errors. + /* Check the current node configuration for plausability and errors. * * @retval 0 Success. Node configuration is good. * @retval <0 Error. The node configuration is bogus. */ - virtual - int check(); + virtual int check(); - virtual - int prepare(); + virtual int prepare(); - /* Start this node. + /* Start this node. * * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int start(); + virtual int start(); - /* Stop this node. + /* Stop this node. * * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int stop(); + virtual int stop(); - /* Restart this node. + /* Restart this node. * * @param n A pointer to the node object. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int restart(); + virtual int restart(); - /* Pause this node. + /* Pause this node. * * @param n A pointer to the node object. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int pause(); + virtual int pause(); - /* Resume this node. + /* Resume this node. * * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - virtual - int resume(); + virtual int resume(); - /* Reverse source and destination of a node. + /* Reverse source and destination of a node. */ - virtual - int reverse(); + virtual int reverse(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - // Get list of socket file descriptors for configuring network emulation. - virtual - std::vector getNetemFDs(); + // Get list of socket file descriptors for configuring network emulation. + virtual std::vector getNetemFDs(); - // Return a memory allocator which should be used for sample pools passed to this node. - virtual - struct memory::Type * getMemoryType(); + // Return a memory allocator which should be used for sample pools passed to this node. + virtual struct memory::Type *getMemoryType(); }; class NodeCompatFactory : public NodeFactory { protected: - struct NodeCompatType *_vt; + struct NodeCompatType *_vt; public: - NodeCompatFactory(struct NodeCompatType *vt) : - NodeFactory(), - _vt(vt) - { } + NodeCompatFactory(struct NodeCompatType *vt) : NodeFactory(), _vt(vt) {} - virtual - Node * make(const uuid_t &id = {}, const std::string &name = ""); + virtual Node *make(const uuid_t &id = {}, const std::string &name = ""); - /// Get plugin name - virtual - std::string getName() const - { - return _vt->name; - } + /// Get plugin name + virtual std::string getName() const { return _vt->name; } - /// Get plugin description - virtual - std::string getDescription() const - { - return _vt->description; - } + /// Get plugin description + virtual std::string getDescription() const { return _vt->description; } - virtual - int getFlags() const; + virtual int getFlags() const; - virtual - int getVectorize() const - { - return _vt->vectorize; - } + virtual int getVectorize() const { return _vt->vectorize; } - virtual - int start(SuperNode *sn); + virtual int start(SuperNode *sn); - virtual - int stop(); + virtual int stop(); }; } // namespace node diff --git a/include/villas/node_compat_type.hpp b/include/villas/node_compat_type.hpp index bfb9ec120..72877456b 100644 --- a/include/villas/node_compat_type.hpp +++ b/include/villas/node_compat_type.hpp @@ -11,8 +11,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -25,18 +25,19 @@ class SuperNode; class NodeCompatType { public: - const char *name; - const char *description; + const char *name; + const char *description; - unsigned vectorize; // Maximal vector length supported by this node type. Zero is unlimited. - int flags; + unsigned + vectorize; // Maximal vector length supported by this node type. Zero is unlimited. + int flags; - enum State state; // State of this node-type. + enum State state; // State of this node-type. - size_t size; // Size of private data bock. @see node::_vd + size_t size; // Size of private data bock. @see node::_vd - struct { - /* Global initialization per node type. + struct { + /* Global initialization per node type. * * This callback is invoked once per node-type. * This callback is optional. It will only be called if non-null. @@ -44,9 +45,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*start)(SuperNode *sn); + int (*start)(SuperNode *sn); - /* Global de-initialization per node type. + /* Global de-initialization per node type. * * This callback is invoked once per node-type. * This callback is optional. It will only be called if non-null. @@ -54,27 +55,27 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*stop)(); - } type; + int (*stop)(); + } type; - /* Initialize a new node instance. + /* Initialize a new node instance. * * This callback is optional. It will only be called if non-null. * * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*init)(NodeCompat *n); + int (*init)(NodeCompat *n); - /* Free memory of an instance of this type. + /* Free memory of an instance of this type. * * This callback is optional. It will only be called if non-null. * * @param n A pointer to the node object. */ - int (*destroy)(NodeCompat *n); + int (*destroy)(NodeCompat *n); - /* Parse node connection details. + /* Parse node connection details. * * This callback is optional. It will only be called if non-null. * @@ -83,9 +84,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*parse)(NodeCompat *n, json_t *json); + int (*parse)(NodeCompat *n, json_t *json); - /* Check the current node configuration for plausability and errors. + /* Check the current node configuration for plausability and errors. * * This callback is optional. It will only be called if non-null. * @@ -93,20 +94,20 @@ public: * @retval 0 Success. Node configuration is good. * @retval <0 Error. The node configuration is bogus. */ - int (*check)(NodeCompat *n); + int (*check)(NodeCompat *n); - int (*prepare)(NodeCompat *n); + int (*prepare)(NodeCompat *n); - /* Returns a string with a textual represenation of this node. + /* Returns a string with a textual represenation of this node. * * This callback is optional. It will only be called if non-null. * * @param n A pointer to the node object. * @return A pointer to a dynamically allocated string. Must be freed(). */ - char * (*print)(NodeCompat *n); + char *(*print)(NodeCompat *n); - /* Start this node. + /* Start this node. * * This callback is optional. It will only be called if non-null. * @@ -114,9 +115,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*start)(NodeCompat *n); + int (*start)(NodeCompat *n); - /* Restart this node. + /* Restart this node. * * This callback is optional. It will only be called if non-null. * @@ -124,9 +125,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*restart)(NodeCompat *n); + int (*restart)(NodeCompat *n); - /* Stop this node. + /* Stop this node. * * This callback is optional. It will only be called if non-null. * @@ -134,9 +135,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*stop)(NodeCompat *n); + int (*stop)(NodeCompat *n); - /* Pause this node. + /* Pause this node. * * This callback is optional. It will only be called if non-null. * @@ -144,9 +145,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*pause)(NodeCompat *n); + int (*pause)(NodeCompat *n); - /* Resume this node. + /* Resume this node. * * This callback is optional. It will only be called if non-null. * @@ -154,9 +155,9 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*resume)(NodeCompat *n); + int (*resume)(NodeCompat *n); - /* Receive multiple messages at once. + /* Receive multiple messages at once. * * This callback is optional. It will only be called if non-null. * @@ -172,9 +173,9 @@ public: * @param release The number of samples that should be released after read is called. * @return The number of messages actually received. */ - int (*read)(NodeCompat *n, struct Sample * const smps[], unsigned cnt); + int (*read)(NodeCompat *n, struct Sample *const smps[], unsigned cnt); - /* Send multiple messages in a single datagram / packet. + /* Send multiple messages in a single datagram / packet. * * This callback is optional. It will only be called if non-null. * @@ -189,34 +190,35 @@ public: * @param release The number of samples that should be released after write is called * @return The number of messages actually sent. */ - int (*write)(NodeCompat *n, struct Sample * const smps[], unsigned cnt); + int (*write)(NodeCompat *n, struct Sample *const smps[], unsigned cnt); - /* Reverse source and destination of a node. + /* Reverse source and destination of a node. * * This callback is optional. It will only be called if non-null. * * @param n A pointer to the node object. */ - int (*reverse)(NodeCompat *n); + int (*reverse)(NodeCompat *n); - /* Get list of file descriptors which can be used by poll/select to detect the availability of new data. + /* Get list of file descriptors which can be used by poll/select to detect the availability of new data. * * This callback is optional. It will only be called if non-null. * * @return The number of file descriptors which have been put into \p fds. */ - int (*poll_fds)(NodeCompat *n, int fds[]); + int (*poll_fds)(NodeCompat *n, int fds[]); - /* Get list of socket file descriptors for configuring network emulation. + /* Get list of socket file descriptors for configuring network emulation. * * This callback is optional. It will only be called if non-null. * * @return The number of file descriptors which have been put into \p sds. */ - int (*netem_fds)(NodeCompat *n, int sds[]); + int (*netem_fds)(NodeCompat *n, int sds[]); - // Return a memory allocator which should be used for sample pools passed to this node. - struct memory::Type * (*memory_type)(NodeCompat *n, struct memory::Type *parent); + // Return a memory allocator which should be used for sample pools passed to this node. + struct memory::Type *(*memory_type)(NodeCompat *n, + struct memory::Type *parent); }; } // namespace node diff --git a/include/villas/node_direction.hpp b/include/villas/node_direction.hpp index 503865f96..2a3a97167 100644 --- a/include/villas/node_direction.hpp +++ b/include/villas/node_direction.hpp @@ -10,9 +10,9 @@ #include #include +#include #include #include -#include namespace villas { namespace node { @@ -22,42 +22,43 @@ class Node; class Path; class NodeDirection { - friend Node; + friend Node; public: - enum class Direction { - IN, // VILLASnode is receiving/reading - OUT // VILLASnode is sending/writing - } direction; + enum class Direction { + IN, // VILLASnode is receiving/reading + OUT // VILLASnode is sending/writing + } direction; - /* The path which uses this node as a source/destination. + /* The path which uses this node as a source/destination. * * Usually every node should be used only by a single path as destination. * Otherwise samples from different paths would be interleaved. */ - Path *path; - Node *node; + Path *path; + Node *node; - int enabled; - int builtin; // This node should use built-in hooks by default. - unsigned vectorize; // Number of messages to send / recv at once (scatter / gather) + int enabled; + int builtin; // This node should use built-in hooks by default. + unsigned + vectorize; // Number of messages to send / recv at once (scatter / gather) - HookList hooks; // List of read / write hooks (struct hook). - SignalList::Ptr signals; // Signal description. + HookList hooks; // List of read / write hooks (struct hook). + SignalList::Ptr signals; // Signal description. - json_t *config; // A JSON object containing the configuration of the node. + json_t *config; // A JSON object containing the configuration of the node. - NodeDirection(enum NodeDirection::Direction dir, Node *n); + NodeDirection(enum NodeDirection::Direction dir, Node *n); - int parse(json_t *json); - void check(); - int prepare(); - int start(); - int stop(); + int parse(json_t *json); + void check(); + int prepare(); + int start(); + int stop(); - SignalList::Ptr getSignals(int after_hooks = true) const; + SignalList::Ptr getSignals(int after_hooks = true) const; - unsigned getSignalsMaxCount() const; + unsigned getSignalsMaxCount() const; }; } // namespace node diff --git a/include/villas/node_list.hpp b/include/villas/node_list.hpp index 8e85c7c9c..c164e66be 100644 --- a/include/villas/node_list.hpp +++ b/include/villas/node_list.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include @@ -22,13 +22,13 @@ class Node; class NodeList : public std::list { public: - // Lookup a node from the list based on its name - Node * lookup(const std::string &name); + // Lookup a node from the list based on its name + Node *lookup(const std::string &name); - // Lookup a node from the list based on its UUID - Node * lookup(const uuid_t &uuid); + // Lookup a node from the list based on its UUID + Node *lookup(const uuid_t &uuid); - /* Parse an array or single node and checks if they exist in the "nodes" section. + /* Parse an array or single node and checks if they exist in the "nodes" section. * * Examples: * out = [ "sintef", "scedu" ] @@ -38,9 +38,9 @@ public: * @param nodes The nodes will be added to this list. * @param all This list contains all valid nodes. */ - int parse(json_t *json, NodeList &all); + int parse(json_t *json, NodeList &all); - json_t * toJson() const; + json_t *toJson() const; }; } // namespace node diff --git a/include/villas/nodes/amqp.hpp b/include/villas/nodes/amqp.hpp index 636ea4e3b..8d6ca9cfb 100644 --- a/include/villas/nodes/amqp.hpp +++ b/include/villas/nodes/amqp.hpp @@ -15,8 +15,8 @@ #include #endif -#include #include +#include namespace villas { namespace node { @@ -25,30 +25,30 @@ namespace node { class NodeCompat; struct amqp_ssl_info { - int verify_peer; - int verify_hostname; - char *ca_cert; - char *client_cert; - char *client_key; + int verify_peer; + int verify_hostname; + char *ca_cert; + char *client_cert; + char *client_key; }; struct amqp { - char *uri; + char *uri; - struct amqp_connection_info connection_info; - struct amqp_ssl_info ssl_info; + struct amqp_connection_info connection_info; + struct amqp_ssl_info ssl_info; - amqp_bytes_t routing_key; - amqp_bytes_t exchange; + amqp_bytes_t routing_key; + amqp_bytes_t exchange; - // We need to create two connection because rabbitmq-c is not thread-safe! - amqp_connection_state_t producer; - amqp_connection_state_t consumer; + // We need to create two connection because rabbitmq-c is not thread-safe! + amqp_connection_state_t producer; + amqp_connection_state_t consumer; - Format *formatter; + Format *formatter; }; -char * amqp_print(NodeCompat *n); +char *amqp_print(NodeCompat *n); int amqp_parse(NodeCompat *n, json_t *json); @@ -62,9 +62,9 @@ int amqp_poll_fds(NodeCompat *n, int fds[]); int amqp_stop(NodeCompat *n); -int amqp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int amqp_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int amqp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int amqp_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/api.hpp b/include/villas/nodes/api.hpp index 361a123a1..3e1c7f8ab 100644 --- a/include/villas/nodes/api.hpp +++ b/include/villas/nodes/api.hpp @@ -8,9 +8,9 @@ #pragma once -#include -#include #include +#include +#include namespace villas { namespace node { @@ -21,33 +21,28 @@ struct Sample; class APINode : public Node { public: - APINode(const uuid_t &id = {}, const std::string &name = ""); + APINode(const uuid_t &id = {}, const std::string &name = ""); - struct Direction { - Sample *sample; - api::universal::ChannelList channels; - pthread_cond_t cv; - pthread_mutex_t mutex; - }; + struct Direction { + Sample *sample; + api::universal::ChannelList channels; + pthread_cond_t cv; + pthread_mutex_t mutex; + }; - // Accessed by api::universal::SignalRequest - Direction read, write; + // Accessed by api::universal::SignalRequest + Direction read, write; - virtual - int prepare(); + virtual int prepare(); - virtual - int check(); + virtual int check(); protected: - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample *smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); }; } // namespace node diff --git a/include/villas/nodes/can.hpp b/include/villas/nodes/can.hpp index acb5ce59a..5c398357a 100644 --- a/include/villas/nodes/can.hpp +++ b/include/villas/nodes/can.hpp @@ -19,22 +19,22 @@ class NodeCompat; union SignalData; struct can_signal { - uint32_t id; - int offset; - int size; + uint32_t id; + int offset; + int size; }; struct can { - // Settings - char *interface_name; - struct can_signal *in; - struct can_signal *out; + // Settings + char *interface_name; + struct can_signal *in; + struct can_signal *out; - // States - int socket; - union SignalData *sample_buf; - size_t sample_buf_num; - struct timespec start_time; + // States + int socket; + union SignalData *sample_buf; + size_t sample_buf_num; + struct timespec start_time; }; int can_init(NodeCompat *n); @@ -43,7 +43,7 @@ int can_destroy(NodeCompat *n); int can_parse(NodeCompat *n, json_t *json); -char * can_print(NodeCompat *n); +char *can_print(NodeCompat *n); int can_check(NodeCompat *n); @@ -53,9 +53,9 @@ int can_start(NodeCompat *n); int can_stop(NodeCompat *n); -int can_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int can_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int can_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int can_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int can_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/comedi.hpp b/include/villas/nodes/comedi.hpp index d59c7cb9f..b922b466a 100644 --- a/include/villas/nodes/comedi.hpp +++ b/include/villas/nodes/comedi.hpp @@ -23,47 +23,46 @@ class NodeCompat; //#define COMEDI_USE_READ (0) struct comedi_chanspec { - unsigned int maxdata; - comedi_range *range; + unsigned int maxdata; + comedi_range *range; }; struct comedi_direction { - int subdevice; ///< Comedi subdevice - int buffer_size; ///< Comedi's kernel buffer size in kB - int sample_size; ///< Size of a single measurement sample - int sample_rate_hz; ///< Sample rate in Hz - bool present; ///< Config present - bool enabled; ///< Card is started successfully - bool running; ///< Card is actively transfering samples - struct timespec started; ///< Timestamp when sampling started - struct timespec last_debug; ///< Timestamp of last debug output - size_t counter; ///< Number of villas samples transfered - struct comedi_chanspec *chanspecs; ///< Range and maxdata config of channels - unsigned *chanlist; ///< Channel list in comedi's packed format - size_t chanlist_len; ///< Number of channels for this direction + int subdevice; ///< Comedi subdevice + int buffer_size; ///< Comedi's kernel buffer size in kB + int sample_size; ///< Size of a single measurement sample + int sample_rate_hz; ///< Sample rate in Hz + bool present; ///< Config present + bool enabled; ///< Card is started successfully + bool running; ///< Card is actively transfering samples + struct timespec started; ///< Timestamp when sampling started + struct timespec last_debug; ///< Timestamp of last debug output + size_t counter; ///< Number of villas samples transfered + struct comedi_chanspec *chanspecs; ///< Range and maxdata config of channels + unsigned *chanlist; ///< Channel list in comedi's packed format + size_t chanlist_len; ///< Number of channels for this direction - char* buffer; - char* bufptr; + char *buffer; + char *bufptr; }; struct comedi { - char *device; - struct comedi_direction in, out; - comedi_t *dev; + char *device; + struct comedi_direction in, out; + comedi_t *dev; #if COMEDI_USE_READ - char *buf; - char *bufptr; + char *buf; + char *bufptr; #else - char *map; - size_t bufpos; - size_t front; - size_t back; + char *map; + size_t bufpos; + size_t front; + size_t back; #endif - }; -char * comedi_print(NodeCompat *n); +char *comedi_print(NodeCompat *n); int comedi_parse(NodeCompat *n, json_t *json); @@ -73,9 +72,9 @@ int comedi_stop(NodeCompat *n); int comedi_poll_fds(NodeCompat *n, int fds[]); -int comedi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int comedi_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int comedi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int comedi_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/ethercat.hpp b/include/villas/nodes/ethercat.hpp index 35cf7cbf1..bd16c7b65 100644 --- a/include/villas/nodes/ethercat.hpp +++ b/include/villas/nodes/ethercat.hpp @@ -11,12 +11,12 @@ #include -#include -#include -#include #include -#include #include +#include +#include +#include +#include namespace villas { namespace node { @@ -29,37 +29,38 @@ class SuperNode; #include extern "C" { - #include +#include } -#define DEFAULT_ETHERCAT_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) +#define DEFAULT_ETHERCAT_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) // Internal data per ethercat node struct ethercat { - // Settings - double rate; + // Settings + double rate; - struct { - unsigned num_channels; - double range; - unsigned position; - unsigned product_code; // Product ID of EtherCAT slave - unsigned vendor_id; // Vendor ID of EtherCAT slave + struct { + unsigned num_channels; + double range; + unsigned position; + unsigned product_code; // Product ID of EtherCAT slave + unsigned vendor_id; // Vendor ID of EtherCAT slave - ec_slave_config_t *sc; - unsigned *offsets; // Offsets for PDO entries - } in, out; + ec_slave_config_t *sc; + unsigned *offsets; // Offsets for PDO entries + } in, out; - ec_domain_t *domain; - ec_pdo_entry_reg_t *domain_regs; - uint8_t *domain_pd; // Process data + ec_domain_t *domain; + ec_pdo_entry_reg_t *domain_regs; + uint8_t *domain_pd; // Process data - std::thread thread; // Cyclic task thread - struct Task task; // Periodic timer - struct Pool pool; - struct CQueueSignalled queue; // For samples which are received from WebSockets + std::thread thread; // Cyclic task thread + struct Task task; // Periodic timer + struct Pool pool; + struct CQueueSignalled + queue; // For samples which are received from WebSockets - std::atomic send; // Last sample to be sent via EtherCAT + std::atomic send; // Last sample to be sent via EtherCAT }; // Internal datastructures @@ -84,11 +85,11 @@ int ethercat_stop(NodeCompat *n); int ethercat_poll_fds(NodeCompat *n, int fds[]); -char * ethercat_print(NodeCompat *n); +char *ethercat_print(NodeCompat *n); -int ethercat_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ethercat_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int ethercat_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ethercat_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/ethercat_config.hpp b/include/villas/nodes/ethercat_config.hpp index ed1386b0b..4b1c2816f 100644 --- a/include/villas/nodes/ethercat_config.hpp +++ b/include/villas/nodes/ethercat_config.hpp @@ -33,8 +33,7 @@ * Revision number: 0x00140000 */ -static -ec_pdo_entry_info_t slave_3_pdo_entries[] = { +static ec_pdo_entry_info_t slave_3_pdo_entries[] = { {0x7000, 0x01, 16}, // Analog output {0x7010, 0x01, 16}, // Analog output {0x7020, 0x01, 16}, // Analog output @@ -45,8 +44,7 @@ ec_pdo_entry_info_t slave_3_pdo_entries[] = { {0x7070, 0x01, 16}, // Analog output }; -static -ec_pdo_info_t slave_3_pdos[] = { +static ec_pdo_info_t slave_3_pdos[] = { {0x1600, 1, slave_3_pdo_entries + 0}, // AO RxPDO-Map Outputs Ch.1 {0x1601, 1, slave_3_pdo_entries + 1}, // AO RxPDO-Map Outputs Ch.2 {0x1602, 1, slave_3_pdo_entries + 2}, // AO RxPDO-Map Outputs Ch.3 @@ -57,14 +55,12 @@ ec_pdo_info_t slave_3_pdos[] = { {0x1607, 1, slave_3_pdo_entries + 7}, // AO RxPDO-Map Outputs Ch.8 }; -static -ec_sync_info_t slave_3_syncs[] = { +static ec_sync_info_t slave_3_syncs[] = { {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {2, EC_DIR_OUTPUT, 8, slave_3_pdos + 0, EC_WD_DISABLE}, {3, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, - {0xff} -}; + {0xff}}; /* Master 0, Slave 4, "EL3008" * Vendor ID: 0x00000002 @@ -72,93 +68,91 @@ ec_sync_info_t slave_3_syncs[] = { * Revision number: 0x00150000 */ -static -ec_pdo_entry_info_t slave_4_pdo_entries[] = { - {0x6000, 0x01, 1}, // Underrange - {0x6000, 0x02, 1}, // Overrange - {0x6000, 0x03, 2}, // Limit 1 - {0x6000, 0x05, 2}, // Limit 2 - {0x6000, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6000, 0x0f, 1}, // TxPDO State - {0x6000, 0x10, 1}, // TxPDO Toggle +static ec_pdo_entry_info_t slave_4_pdo_entries[] = { + {0x6000, 0x01, 1}, // Underrange + {0x6000, 0x02, 1}, // Overrange + {0x6000, 0x03, 2}, // Limit 1 + {0x6000, 0x05, 2}, // Limit 2 + {0x6000, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6000, 0x0f, 1}, // TxPDO State + {0x6000, 0x10, 1}, // TxPDO Toggle {0x6000, 0x11, 16}, // Value - {0x6010, 0x01, 1}, // Underrange - {0x6010, 0x02, 1}, // Overrange - {0x6010, 0x03, 2}, // Limit 1 - {0x6010, 0x05, 2}, // Limit 2 - {0x6010, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6010, 0x0f, 1}, // TxPDO State - {0x6010, 0x10, 1}, // TxPDO Toggle + {0x6010, 0x01, 1}, // Underrange + {0x6010, 0x02, 1}, // Overrange + {0x6010, 0x03, 2}, // Limit 1 + {0x6010, 0x05, 2}, // Limit 2 + {0x6010, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6010, 0x0f, 1}, // TxPDO State + {0x6010, 0x10, 1}, // TxPDO Toggle {0x6010, 0x11, 16}, // Value - {0x6020, 0x01, 1}, // Underrange - {0x6020, 0x02, 1}, // Overrange - {0x6020, 0x03, 2}, // Limit 1 - {0x6020, 0x05, 2}, // Limit 2 - {0x6020, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6020, 0x0f, 1}, // TxPDO State - {0x6020, 0x10, 1}, // TxPDO Toggle + {0x6020, 0x01, 1}, // Underrange + {0x6020, 0x02, 1}, // Overrange + {0x6020, 0x03, 2}, // Limit 1 + {0x6020, 0x05, 2}, // Limit 2 + {0x6020, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6020, 0x0f, 1}, // TxPDO State + {0x6020, 0x10, 1}, // TxPDO Toggle {0x6020, 0x11, 16}, // Value - {0x6030, 0x01, 1}, // Underrange - {0x6030, 0x02, 1}, // Overrange - {0x6030, 0x03, 2}, // Limit 1 - {0x6030, 0x05, 2}, // Limit 2 - {0x6030, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6030, 0x0f, 1}, // TxPDO State - {0x6030, 0x10, 1}, // TxPDO Toggle + {0x6030, 0x01, 1}, // Underrange + {0x6030, 0x02, 1}, // Overrange + {0x6030, 0x03, 2}, // Limit 1 + {0x6030, 0x05, 2}, // Limit 2 + {0x6030, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6030, 0x0f, 1}, // TxPDO State + {0x6030, 0x10, 1}, // TxPDO Toggle {0x6030, 0x11, 16}, // Value - {0x6040, 0x01, 1}, // Underrange - {0x6040, 0x02, 1}, // Overrange - {0x6040, 0x03, 2}, // Limit 1 - {0x6040, 0x05, 2}, // Limit 2 - {0x6040, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6040, 0x0f, 1}, // TxPDO State - {0x6040, 0x10, 1}, // TxPDO Toggle + {0x6040, 0x01, 1}, // Underrange + {0x6040, 0x02, 1}, // Overrange + {0x6040, 0x03, 2}, // Limit 1 + {0x6040, 0x05, 2}, // Limit 2 + {0x6040, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6040, 0x0f, 1}, // TxPDO State + {0x6040, 0x10, 1}, // TxPDO Toggle {0x6040, 0x11, 16}, // Value - {0x6050, 0x01, 1}, // Underrange - {0x6050, 0x02, 1}, // Overrange - {0x6050, 0x03, 2}, // Limit 1 - {0x6050, 0x05, 2}, // Limit 2 - {0x6050, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6050, 0x0f, 1}, // TxPDO State - {0x6050, 0x10, 1}, // TxPDO Toggle + {0x6050, 0x01, 1}, // Underrange + {0x6050, 0x02, 1}, // Overrange + {0x6050, 0x03, 2}, // Limit 1 + {0x6050, 0x05, 2}, // Limit 2 + {0x6050, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6050, 0x0f, 1}, // TxPDO State + {0x6050, 0x10, 1}, // TxPDO Toggle {0x6050, 0x11, 16}, // Value - {0x6060, 0x01, 1}, // Underrange - {0x6060, 0x02, 1}, // Overrange - {0x6060, 0x03, 2}, // Limit 1 - {0x6060, 0x05, 2}, // Limit 2 - {0x6060, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6060, 0x0f, 1}, // TxPDO State - {0x6060, 0x10, 1}, // TxPDO Toggle + {0x6060, 0x01, 1}, // Underrange + {0x6060, 0x02, 1}, // Overrange + {0x6060, 0x03, 2}, // Limit 1 + {0x6060, 0x05, 2}, // Limit 2 + {0x6060, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6060, 0x0f, 1}, // TxPDO State + {0x6060, 0x10, 1}, // TxPDO Toggle {0x6060, 0x11, 16}, // Value - {0x6070, 0x01, 1}, // Underrange - {0x6070, 0x02, 1}, // Overrange - {0x6070, 0x03, 2}, // Limit 1 - {0x6070, 0x05, 2}, // Limit 2 - {0x6070, 0x07, 1}, // Error - {0x0000, 0x00, 1}, // Gap - {0x0000, 0x00, 6}, // Gap - {0x6070, 0x0f, 1}, // TxPDO State - {0x6070, 0x10, 1}, // TxPDO Toggle + {0x6070, 0x01, 1}, // Underrange + {0x6070, 0x02, 1}, // Overrange + {0x6070, 0x03, 2}, // Limit 1 + {0x6070, 0x05, 2}, // Limit 2 + {0x6070, 0x07, 1}, // Error + {0x0000, 0x00, 1}, // Gap + {0x0000, 0x00, 6}, // Gap + {0x6070, 0x0f, 1}, // TxPDO State + {0x6070, 0x10, 1}, // TxPDO Toggle {0x6070, 0x11, 16}, // Value }; -static -ec_pdo_info_t slave_4_pdos[] = { - {0x1a00, 10, slave_4_pdo_entries + 0}, // AI TxPDO-Map Standard Ch.1 +static ec_pdo_info_t slave_4_pdos[] = { + {0x1a00, 10, slave_4_pdo_entries + 0}, // AI TxPDO-Map Standard Ch.1 {0x1a02, 10, slave_4_pdo_entries + 10}, // AI TxPDO-Map Standard Ch.2 {0x1a04, 10, slave_4_pdo_entries + 20}, // AI TxPDO-Map Standard Ch.3 {0x1a06, 10, slave_4_pdo_entries + 30}, // AI TxPDO-Map Standard Ch.4 @@ -168,11 +162,9 @@ ec_pdo_info_t slave_4_pdos[] = { {0x1a0e, 10, slave_4_pdo_entries + 70}, // AI TxPDO-Map Standard Ch.8 }; -static -ec_sync_info_t slave_4_syncs[] = { +static ec_sync_info_t slave_4_syncs[] = { {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {2, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {3, EC_DIR_INPUT, 8, slave_4_pdos + 0, EC_WD_DISABLE}, - {0xff} -}; + {0xff}}; diff --git a/include/villas/nodes/example.hpp b/include/villas/nodes/example.hpp index 86813e20b..55129bbb4 100644 --- a/include/villas/nodes/example.hpp +++ b/include/villas/nodes/example.hpp @@ -10,8 +10,8 @@ #pragma once -#include #include +#include #include namespace villas { @@ -23,72 +23,64 @@ struct Sample; class ExampleNode : public Node { protected: - // Place any configuration and per-node state here + // Place any configuration and per-node state here - // Settings - int setting1; + // Settings + int setting1; - std::string setting2; + std::string setting2; - // States - int state1; - struct timespec start_time; + // States + int state1; + struct timespec start_time; - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample *smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); public: - ExampleNode(const uuid_t &id = {}, const std::string &name = ""); + ExampleNode(const uuid_t &id = {}, const std::string &name = ""); - /* All of the following virtual-declared functions are optional. + /* All of the following virtual-declared functions are optional. * Have a look at node.hpp/node.cpp for the default behaviour. */ - virtual - ~ExampleNode(); + virtual ~ExampleNode(); - virtual - int prepare(); + virtual int prepare(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - // Validate node configuration - virtual - int check(); + // Validate node configuration + virtual int check(); - virtual - int start(); + virtual int start(); - // virtual - // int stop(); + // virtual + // int stop(); - // virtual - // int pause(); + // virtual + // int pause(); - // virtual - // int resume(); + // virtual + // int resume(); - // virtual - // int restart(); + // virtual + // int restart(); - // virtual - // int reverse(); + // virtual + // int reverse(); - // virtual - // std::vector getPollFDs(); + // virtual + // std::vector getPollFDs(); - // virtual - // std::vector getNetemFDs(); + // virtual + // std::vector getNetemFDs(); - // virtual - // struct villas::node::memory::Type * getMemoryType(); + // virtual + // struct villas::node::memory::Type * getMemoryType(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); }; } // namespace node diff --git a/include/villas/nodes/exec.hpp b/include/villas/nodes/exec.hpp index 000222a57..0c061b866 100644 --- a/include/villas/nodes/exec.hpp +++ b/include/villas/nodes/exec.hpp @@ -7,9 +7,9 @@ #pragma once +#include #include #include -#include namespace villas { namespace node { @@ -20,55 +20,42 @@ struct Sample; class ExecNode : public Node { protected: - std::unique_ptr proc; - std::unique_ptr formatter; + std::unique_ptr proc; + std::unique_ptr formatter; - FILE *stream_in, *stream_out; + FILE *stream_in, *stream_out; - bool flush; - bool shell; + bool flush; + bool shell; - std::string working_dir; - std::string command; + std::string working_dir; + std::string command; - villas::utils::Popen::arg_list arguments; - villas::utils::Popen::env_map environment; + villas::utils::Popen::arg_list arguments; + villas::utils::Popen::env_map environment; - virtual - int _read(struct Sample * smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample * smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); public: - ExecNode(const uuid_t &id = {}, const std::string &name = "") : - Node(id, name), - stream_in(nullptr), - stream_out(nullptr), - flush(true), - shell(false) - { } + ExecNode(const uuid_t &id = {}, const std::string &name = "") + : Node(id, name), stream_in(nullptr), stream_out(nullptr), flush(true), + shell(false) {} - virtual - ~ExecNode(); + virtual ~ExecNode(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); - virtual - int start(); + virtual int start(); - virtual - int stop(); + virtual int stop(); - virtual - int prepare(); + virtual int prepare(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); }; } // namespace node diff --git a/include/villas/nodes/file.hpp b/include/villas/nodes/file.hpp index 5157f82ba..f148ac364 100644 --- a/include/villas/nodes/file.hpp +++ b/include/villas/nodes/file.hpp @@ -18,43 +18,48 @@ namespace node { // Forward declarations class NodeCompat; -#define FILE_MAX_PATHLEN 512 +#define FILE_MAX_PATHLEN 512 struct file { - Format *formatter; - FILE *stream_in; - FILE *stream_out; + Format *formatter; + FILE *stream_in; + FILE *stream_out; - char *uri_tmpl; // Format string for file name. - char *uri; // Real file name. + char *uri_tmpl; // Format string for file name. + char *uri; // Real file name. - unsigned skip_lines; // Skip the first n-th lines/samples of the file. - int flush; // Flush / upload file contents after each write. - struct Task task; // Timer file descriptor. Blocks until 1 / rate seconds are elapsed. - double rate; // The read rate. - size_t buffer_size_out; // Defines size of output stream buffer. No buffer is created if value is set to zero. - size_t buffer_size_in; // Defines size of input stream buffer. No buffer is created if value is set to zero. + unsigned skip_lines; // Skip the first n-th lines/samples of the file. + int flush; // Flush / upload file contents after each write. + struct Task + task; // Timer file descriptor. Blocks until 1 / rate seconds are elapsed. + double rate; // The read rate. + size_t + buffer_size_out; // Defines size of output stream buffer. No buffer is created if value is set to zero. + size_t + buffer_size_in; // Defines size of input stream buffer. No buffer is created if value is set to zero. - enum class EpochMode { - DIRECT, - WAIT, - RELATIVE, - ABSOLUTE, - ORIGINAL - } epoch_mode; // Specifies how file::offset is calculated. + enum class EpochMode { + DIRECT, + WAIT, + RELATIVE, + ABSOLUTE, + ORIGINAL + } epoch_mode; // Specifies how file::offset is calculated. - enum class EOFBehaviour { - STOP, // Terminate when EOF is reached. - REWIND, // Rewind the file when EOF is reached. - SUSPEND // Blocking wait when EOF is reached. - } eof_mode; + enum class EOFBehaviour { + STOP, // Terminate when EOF is reached. + REWIND, // Rewind the file when EOF is reached. + SUSPEND // Blocking wait when EOF is reached. + } eof_mode; - struct timespec first; // The first timestamp in the file file::{read,write}::uri - struct timespec epoch; // The epoch timestamp from the configuration. - struct timespec offset; // An offset between the timestamp in the input file and the current time + struct timespec + first; // The first timestamp in the file file::{read,write}::uri + struct timespec epoch; // The epoch timestamp from the configuration. + struct timespec + offset; // An offset between the timestamp in the input file and the current time }; -char * file_print(NodeCompat *n); +char *file_print(NodeCompat *n); int file_parse(NodeCompat *n, json_t *json); @@ -68,9 +73,9 @@ int file_destroy(NodeCompat *n); int file_poll_fds(NodeCompat *n, int fds[]); -int file_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int file_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int file_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int file_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/fpga.hpp b/include/villas/nodes/fpga.hpp index 4f7065134..7a25dbf7f 100644 --- a/include/villas/nodes/fpga.hpp +++ b/include/villas/nodes/fpga.hpp @@ -7,15 +7,15 @@ #pragma once -#include -#include #include +#include +#include #include #include -#include -#include #include +#include +#include namespace villas { namespace node { @@ -26,89 +26,68 @@ namespace node { class FpgaNode : public Node { protected: - int irqFd; - int coalesce; - bool polling; + int irqFd; + int coalesce; + bool polling; - std::shared_ptr card; + std::shared_ptr card; - std::shared_ptr dma; - std::shared_ptr intf; + std::shared_ptr dma; + std::shared_ptr intf; - std::unique_ptr blockRx; - std::unique_ptr blockTx; + std::unique_ptr blockRx; + std::unique_ptr blockTx; - // Config only - std::string cardName; - std::string intfName; - std::string dmaName; + // Config only + std::string cardName; + std::string intfName; + std::string dmaName; protected: - virtual - int _read(Sample *smps[], unsigned cnt); + virtual int _read(Sample *smps[], unsigned cnt); - virtual - int _write(Sample *smps[], unsigned cnt); + virtual int _write(Sample *smps[], unsigned cnt); public: - FpgaNode(const uuid_t &id = {}, const std::string &name = ""); + FpgaNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~FpgaNode(); + virtual ~FpgaNode(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); - virtual - int check(); + virtual int check(); - virtual - int prepare(); + virtual int prepare(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); }; class FpgaNodeFactory : public NodeFactory { public: - using NodeFactory::NodeFactory; + using NodeFactory::NodeFactory; - virtual - Node * make(const uuid_t &id = {}, const std::string &nme = "") - { - auto *n = new FpgaNode(id, nme); + virtual Node *make(const uuid_t &id = {}, const std::string &nme = "") { + auto *n = new FpgaNode(id, nme); - init(n); + init(n); - return n; - } + return n; + } - virtual - int getFlags() const - { - return (int) NodeFactory::Flags::SUPPORTS_READ | - (int) NodeFactory::Flags::SUPPORTS_WRITE | - (int) NodeFactory::Flags::SUPPORTS_POLL; - } + virtual int getFlags() const { + return (int)NodeFactory::Flags::SUPPORTS_READ | + (int)NodeFactory::Flags::SUPPORTS_WRITE | + (int)NodeFactory::Flags::SUPPORTS_POLL; + } - virtual - std::string getName() const - { - return "fpga"; - } + virtual std::string getName() const { return "fpga"; } - virtual - std::string getDescription() const - { - return "VILLASfpga"; - } + virtual std::string getDescription() const { return "VILLASfpga"; } - virtual - int start(SuperNode *sn); + virtual int start(SuperNode *sn); }; } // namespace node diff --git a/include/villas/nodes/iec60870.hpp b/include/villas/nodes/iec60870.hpp index 4abeebbb0..4ac89bc2e 100644 --- a/include/villas/nodes/iec60870.hpp +++ b/include/villas/nodes/iec60870.hpp @@ -7,18 +7,18 @@ #pragma once -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -27,167 +27,185 @@ namespace iec60870 { /// A supported CS101 information data type class ASDUData { public: - enum Type { - SINGLE_POINT = M_SP_NA_1, // SinglePointInformation - SINGLE_POINT_WITH_TIMESTAMP = M_SP_TB_1, // SinglePointWithCP56Time2a - DOUBLE_POINT = M_DP_NA_1, // DoublePointInformation - DOUBLE_POINT_WITH_TIMESTAMP = M_DP_TB_1, // DoublePointWithCP56Time2a - SCALED_INT = M_ME_NB_1, // MeasuredValueScaled - SCALED_INT_WITH_TIMESTAMP = M_ME_TE_1, // MeasuredValueScaledWithCP56Time2a - NORMALIZED_FLOAT = M_ME_NA_1, // MeasuredValueNormalized - NORMALIZED_FLOAT_WITH_TIMESTAMP = M_ME_TD_1, // MeasuredValueNormalizedWithCP56Time2a - SHORT_FLOAT = M_ME_NC_1, // MeasuredValueShort - SHORT_FLOAT_WITH_TIMESTAMP = M_ME_TF_1, // MeasuredValueShortWithCP56Time2a - }; + enum Type { + SINGLE_POINT = M_SP_NA_1, // SinglePointInformation + SINGLE_POINT_WITH_TIMESTAMP = M_SP_TB_1, // SinglePointWithCP56Time2a + DOUBLE_POINT = M_DP_NA_1, // DoublePointInformation + DOUBLE_POINT_WITH_TIMESTAMP = M_DP_TB_1, // DoublePointWithCP56Time2a + SCALED_INT = M_ME_NB_1, // MeasuredValueScaled + SCALED_INT_WITH_TIMESTAMP = M_ME_TE_1, // MeasuredValueScaledWithCP56Time2a + NORMALIZED_FLOAT = M_ME_NA_1, // MeasuredValueNormalized + NORMALIZED_FLOAT_WITH_TIMESTAMP = + M_ME_TD_1, // MeasuredValueNormalizedWithCP56Time2a + SHORT_FLOAT = M_ME_NC_1, // MeasuredValueShort + SHORT_FLOAT_WITH_TIMESTAMP = M_ME_TF_1, // MeasuredValueShortWithCP56Time2a + }; - struct Sample { - SignalData signal_data; - QualityDescriptor quality; - std::optional timestamp; - }; + struct Sample { + SignalData signal_data; + QualityDescriptor quality; + std::optional timestamp; + }; - // Parse the config json - static - ASDUData parse(json_t *json_signal, std::optional last_data, bool duplicate_ioa_is_sequence); + // Parse the config json + static ASDUData parse(json_t *json_signal, std::optional last_data, + bool duplicate_ioa_is_sequence); - // Does this data include a timestamp - bool hasTimestamp() const; + // Does this data include a timestamp + bool hasTimestamp() const; - // The IEC104 type - ASDUData::Type type() const; + // The IEC104 type + ASDUData::Type type() const; - // The config file identifier for this type - char const * name() const; + // The config file identifier for this type + char const *name() const; - // Get equivalent IEC104 type without timestamp (e.g. for general interrogation response) - ASDUData::Type typeWithoutTimestamp() const; + // Get equivalent IEC104 type without timestamp (e.g. for general interrogation response) + ASDUData::Type typeWithoutTimestamp() const; - // Get equivalent ASDUData without timestamp (e.g. for general interrogation response) - ASDUData withoutTimestamp() const; + // Get equivalent ASDUData without timestamp (e.g. for general interrogation response) + ASDUData withoutTimestamp() const; - // Corresponding signal type - SignalType signalType() const; + // Corresponding signal type + SignalType signalType() const; - // Check if ASDU contains this data - std::optional checkASDU(CS101_ASDU const &asdu) const; + // Check if ASDU contains this data + std::optional checkASDU(CS101_ASDU const &asdu) const; - // Add SignalData to an ASDU, returns false when sample couldn't be added (insufficient space in ASDU) - bool addSampleToASDU(CS101_ASDU &asdu, ASDUData::Sample sample) const; + // Add SignalData to an ASDU, returns false when sample couldn't be added (insufficient space in ASDU) + bool addSampleToASDU(CS101_ASDU &asdu, ASDUData::Sample sample) const; - // Every value in an ASDU has an associated "information object address" (ioa) - int ioa; + // Every value in an ASDU has an associated "information object address" (ioa) + int ioa; + + // Start of the ioa sequence + int ioa_sequence_start; - // Start of the ioa sequence - int ioa_sequence_start; private: - struct Descriptor { - ASDUData::Type type; - char const *name; - char const *type_id; - bool has_timestamp; - ASDUData::Type type_without_timestamp; - SignalType signal_type; - }; + struct Descriptor { + ASDUData::Type type; + char const *name; + char const *type_id; + bool has_timestamp; + ASDUData::Type type_without_timestamp; + SignalType signal_type; + }; - inline static - std::array const descriptors { - ASDUData::Descriptor { Type::SINGLE_POINT, "single-point", "M_SP_NA_1", false, Type::SINGLE_POINT, SignalType::BOOLEAN }, - ASDUData::Descriptor { Type::SINGLE_POINT_WITH_TIMESTAMP, "single-point", "M_SP_TB_1", true, Type::SINGLE_POINT, SignalType::BOOLEAN }, - ASDUData::Descriptor { Type::DOUBLE_POINT, "double-point", "M_DP_NA_1", false, Type::DOUBLE_POINT, SignalType::INTEGER }, - ASDUData::Descriptor { Type::DOUBLE_POINT_WITH_TIMESTAMP, "double-point", "M_DP_TB_1", true, Type::DOUBLE_POINT, SignalType::INTEGER }, - ASDUData::Descriptor { Type::SCALED_INT, "scaled-int", "M_ME_NB_1", false, Type::SCALED_INT, SignalType::INTEGER }, - ASDUData::Descriptor { Type::SCALED_INT_WITH_TIMESTAMP, "scaled-int", "M_ME_TE_1", true, Type::SCALED_INT, SignalType::INTEGER }, - ASDUData::Descriptor { Type::NORMALIZED_FLOAT, "normalized-float", "M_ME_NA_1", false, Type::NORMALIZED_FLOAT, SignalType::FLOAT }, - ASDUData::Descriptor { Type::NORMALIZED_FLOAT_WITH_TIMESTAMP, "normalized-float", "M_ME_TD_1", true, Type::NORMALIZED_FLOAT, SignalType::FLOAT }, - ASDUData::Descriptor { Type::SHORT_FLOAT, "short-float", "M_ME_NC_1", false, Type::SHORT_FLOAT, SignalType::FLOAT }, - ASDUData::Descriptor { Type::SHORT_FLOAT_WITH_TIMESTAMP, "short-float", "M_ME_TF_1", true, Type::SHORT_FLOAT, SignalType::FLOAT }, - }; + inline static std::array const descriptors{ + ASDUData::Descriptor{Type::SINGLE_POINT, "single-point", "M_SP_NA_1", + false, Type::SINGLE_POINT, SignalType::BOOLEAN}, + ASDUData::Descriptor{Type::SINGLE_POINT_WITH_TIMESTAMP, "single-point", + "M_SP_TB_1", true, Type::SINGLE_POINT, + SignalType::BOOLEAN}, + ASDUData::Descriptor{Type::DOUBLE_POINT, "double-point", "M_DP_NA_1", + false, Type::DOUBLE_POINT, SignalType::INTEGER}, + ASDUData::Descriptor{Type::DOUBLE_POINT_WITH_TIMESTAMP, "double-point", + "M_DP_TB_1", true, Type::DOUBLE_POINT, + SignalType::INTEGER}, + ASDUData::Descriptor{Type::SCALED_INT, "scaled-int", "M_ME_NB_1", false, + Type::SCALED_INT, SignalType::INTEGER}, + ASDUData::Descriptor{Type::SCALED_INT_WITH_TIMESTAMP, "scaled-int", + "M_ME_TE_1", true, Type::SCALED_INT, + SignalType::INTEGER}, + ASDUData::Descriptor{Type::NORMALIZED_FLOAT, "normalized-float", + "M_ME_NA_1", false, Type::NORMALIZED_FLOAT, + SignalType::FLOAT}, + ASDUData::Descriptor{Type::NORMALIZED_FLOAT_WITH_TIMESTAMP, + "normalized-float", "M_ME_TD_1", true, + Type::NORMALIZED_FLOAT, SignalType::FLOAT}, + ASDUData::Descriptor{Type::SHORT_FLOAT, "short-float", "M_ME_NC_1", false, + Type::SHORT_FLOAT, SignalType::FLOAT}, + ASDUData::Descriptor{Type::SHORT_FLOAT_WITH_TIMESTAMP, "short-float", + "M_ME_TF_1", true, Type::SHORT_FLOAT, + SignalType::FLOAT}, + }; - ASDUData(ASDUData::Descriptor const *descriptor, int ioa, int ioa_sequence_start); + ASDUData(ASDUData::Descriptor const *descriptor, int ioa, + int ioa_sequence_start); - // Lookup datatype for config key asdu_type - static - std::optional lookupName(char const *name, bool with_timestamp, int ioa, int ioa_sequence_start); + // Lookup datatype for config key asdu_type + static std::optional lookupName(char const *name, + bool with_timestamp, int ioa, + int ioa_sequence_start); - // Lookup datatype for config key asdu_type_id - static - std::optional lookupTypeId(char const *type_id, int ioa, int ioa_sequence_start); + // Lookup datatype for config key asdu_type_id + static std::optional lookupTypeId(char const *type_id, int ioa, + int ioa_sequence_start); - // Lookup datatype for numeric type identifier - static - std::optional lookupType(int type, int ioa, int ioa_sequence_start); + // Lookup datatype for numeric type identifier + static std::optional lookupType(int type, int ioa, + int ioa_sequence_start); - // Descriptor within the descriptors table above - ASDUData::Descriptor const *descriptor; + // Descriptor within the descriptors table above + ASDUData::Descriptor const *descriptor; }; class SlaveNode : public Node { protected: - struct Server { - // Slave state - enum { NONE, STOPPED, READY } state; + struct Server { + // Slave state + enum { NONE, STOPPED, READY } state; - // Config (use explicit defaults) - std::string local_address; - int local_port; - int common_address; - int low_priority_queue; - int high_priority_queue; + // Config (use explicit defaults) + std::string local_address; + int local_port; + int common_address; + int low_priority_queue; + int high_priority_queue; - // Config (use lib60870 defaults if std::nullopt) - std::optional apci_t0; - std::optional apci_t1; - std::optional apci_t2; - std::optional apci_t3; - std::optional apci_k; - std::optional apci_w; + // Config (use lib60870 defaults if std::nullopt) + std::optional apci_t0; + std::optional apci_t1; + std::optional apci_t2; + std::optional apci_t3; + std::optional apci_k; + std::optional apci_w; - // Lib60870 - CS104_Slave slave; - CS101_AppLayerParameters asdu_app_layer_parameters; - } server; + // Lib60870 + CS104_Slave slave; + CS101_AppLayerParameters asdu_app_layer_parameters; + } server; - struct Output { - bool enabled = false; - std::vector mapping; - std::vector asdu_types; + struct Output { + bool enabled = false; + std::vector mapping; + std::vector asdu_types; - mutable std::mutex last_values_mutex; - std::vector last_values; - } output; + mutable std::mutex last_values_mutex; + std::vector last_values; + } output; - void createSlave() noexcept; - void destroySlave() noexcept; + void createSlave() noexcept; + void destroySlave() noexcept; - void startSlave() noexcept(false); - void stopSlave() noexcept; + void startSlave() noexcept(false); + void stopSlave() noexcept; - void debugPrintMessage(IMasterConnection connection, uint8_t *message, int message_size, bool sent) const noexcept; - void debugPrintConnection(IMasterConnection connection, CS104_PeerConnectionEvent event) const noexcept; + void debugPrintMessage(IMasterConnection connection, uint8_t *message, + int message_size, bool sent) const noexcept; + void debugPrintConnection(IMasterConnection connection, + CS104_PeerConnectionEvent event) const noexcept; - bool onClockSync(IMasterConnection connection, CS101_ASDU asdu, CP56Time2a new_time) const noexcept; - bool onInterrogation(IMasterConnection connection, CS101_ASDU asdu, uint8_t _of_inter) const noexcept; - bool onASDU(IMasterConnection connection, CS101_ASDU asdu) const noexcept; + bool onClockSync(IMasterConnection connection, CS101_ASDU asdu, + CP56Time2a new_time) const noexcept; + bool onInterrogation(IMasterConnection connection, CS101_ASDU asdu, + uint8_t _of_inter) const noexcept; + bool onASDU(IMasterConnection connection, CS101_ASDU asdu) const noexcept; - void sendPeriodicASDUsForSample(Sample const *sample) const noexcept(false); + void sendPeriodicASDUsForSample(Sample const *sample) const noexcept(false); - virtual - int _write(struct Sample *smps[], unsigned cnt) override; + virtual int _write(struct Sample *smps[], unsigned cnt) override; public: - SlaveNode(const uuid_t &id = {}, const std::string &name = ""); + SlaveNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~SlaveNode() override; + virtual ~SlaveNode() override; - virtual - int parse(json_t *json) override; + virtual int parse(json_t *json) override; - virtual - int start() override; + virtual int start() override; - virtual - int stop() override; + virtual int stop() override; }; } // namespace iec60870 diff --git a/include/villas/nodes/iec61850.hpp b/include/villas/nodes/iec61850.hpp index 2807206c9..0e4931bc2 100644 --- a/include/villas/nodes/iec61850.hpp +++ b/include/villas/nodes/iec61850.hpp @@ -11,8 +11,8 @@ #include -#include #include +#include #include #include @@ -20,7 +20,8 @@ #include #ifndef CONFIG_GOOSE_DEFAULT_DST_ADDRESS - #define CONFIG_GOOSE_DEFAULT_DST_ADDRESS {0x01, 0x0c, 0xcd, 0x01, 0x00, 0x01} +#define CONFIG_GOOSE_DEFAULT_DST_ADDRESS \ + { 0x01, 0x0c, 0xcd, 0x01, 0x00, 0x01 } #endif namespace villas { @@ -30,67 +31,67 @@ namespace node { class NodeCompat; enum class IEC61850Type { - // According to IEC 61850-7-2 - BOOLEAN, - INT8, - INT16, - INT32, - INT64, - INT8U, - INT16U, - INT32U, - INT64U, - FLOAT32, - FLOAT64, - ENUMERATED, - CODED_ENUM, - OCTET_STRING, - VISIBLE_STRING, - OBJECTNAME, - OBJECTREFERENCE, - TIMESTAMP, - ENTRYTIME, + // According to IEC 61850-7-2 + BOOLEAN, + INT8, + INT16, + INT32, + INT64, + INT8U, + INT16U, + INT32U, + INT64U, + FLOAT32, + FLOAT64, + ENUMERATED, + CODED_ENUM, + OCTET_STRING, + VISIBLE_STRING, + OBJECTNAME, + OBJECTREFERENCE, + TIMESTAMP, + ENTRYTIME, - // According to IEC 61850-8-1 - BITSTRING + // According to IEC 61850-8-1 + BITSTRING }; struct iec61850_type_descriptor { - const char *name; - enum IEC61850Type iec_type; - enum SignalType type; - unsigned size; - bool publisher; - bool subscriber; + const char *name; + enum IEC61850Type iec_type; + enum SignalType type; + unsigned size; + bool publisher; + bool subscriber; }; struct iec61850_receiver { - char *interface; + char *interface; - EthernetSocket socket; + EthernetSocket socket; - enum class Type { - GOOSE, - SAMPLED_VALUES - } type; + enum class Type { GOOSE, SAMPLED_VALUES } type; - union { - SVReceiver sv; - GooseReceiver goose; - }; + union { + SVReceiver sv; + GooseReceiver goose; + }; }; int iec61850_type_start(villas::node::SuperNode *sn); int iec61850_type_stop(); -const struct iec61850_type_descriptor * iec61850_lookup_type(const char *name); +const struct iec61850_type_descriptor *iec61850_lookup_type(const char *name); -int iec61850_parse_signals(json_t *json_signals, struct List *signals, SignalList::Ptr node_signals); +int iec61850_parse_signals(json_t *json_signals, struct List *signals, + SignalList::Ptr node_signals); -struct iec61850_receiver * iec61850_receiver_lookup(enum iec61850_receiver::Type t, const char *intf); +struct iec61850_receiver * +iec61850_receiver_lookup(enum iec61850_receiver::Type t, const char *intf); -struct iec61850_receiver * iec61850_receiver_create(enum iec61850_receiver::Type t, const char *intf); +struct iec61850_receiver * +iec61850_receiver_create(enum iec61850_receiver::Type t, const char *intf); int iec61850_receiver_start(struct iec61850_receiver *r); @@ -98,7 +99,7 @@ int iec61850_receiver_stop(struct iec61850_receiver *r); int iec61850_receiver_destroy(struct iec61850_receiver *r); -const struct iec61850_type_descriptor * iec61850_lookup_type(const char *name); +const struct iec61850_type_descriptor *iec61850_lookup_type(const char *name); } // namespace node } // namespace villas diff --git a/include/villas/nodes/iec61850_goose.hpp b/include/villas/nodes/iec61850_goose.hpp index 4d2826d37..d613f25b7 100644 --- a/include/villas/nodes/iec61850_goose.hpp +++ b/include/villas/nodes/iec61850_goose.hpp @@ -8,21 +8,21 @@ #pragma once #include -#include #include #include #include #include +#include #include #include #include +#include #include #include -#include -#include #include +#include #include #include #include @@ -34,82 +34,89 @@ namespace iec61850 { // A GooseSignal is a SignalData value with attached Metadata for the MmsType and SignalType class GooseSignal { public: - union Meta { - int size; - }; + union Meta { + int size; + }; - struct Descriptor { - std::string name; - SignalType signal_type; - MmsType mms_type; - Meta default_meta; - }; + struct Descriptor { + std::string name; + SignalType signal_type; + MmsType mms_type; + Meta default_meta; + }; - using Type = Descriptor const *; + using Type = Descriptor const *; - // The config file identifier for this type - std::string const & name() const; + // The config file identifier for this type + std::string const &name() const; - // The type of this value - Type type() const; + // The type of this value + Type type() const; - // Corresponding mms type - MmsType mmsType() const; + // Corresponding mms type + MmsType mmsType() const; - // Corresponding signal type - SignalType signalType() const; + // Corresponding signal type + SignalType signalType() const; - // Create a GooseSignal from an MmsValue - static - std::optional fromMmsValue(MmsValue *mms_value); + // Create a GooseSignal from an MmsValue + static std::optional fromMmsValue(MmsValue *mms_value); - // Create a GooseSignal from type name and SignalData value - static - std::optional fromNameAndValue(char const *name, SignalData value, std::optional meta = std::nullopt); + // Create a GooseSignal from type name and SignalData value + static std::optional + fromNameAndValue(char const *name, SignalData value, + std::optional meta = std::nullopt); - // Create a MmsValue from this GooseSignal - MmsValue * toMmsValue() const; + // Create a MmsValue from this GooseSignal + MmsValue *toMmsValue() const; - static - std::optional lookupMmsType(int mms_type); + static std::optional lookupMmsType(int mms_type); - static - std::optional lookupMmsTypeName(char const *name); + static std::optional lookupMmsTypeName(char const *name); - GooseSignal(Type type, SignalData value, std::optional meta = std::nullopt); + GooseSignal(Type type, SignalData value, + std::optional meta = std::nullopt); + + SignalData signal_data; + Meta meta; - SignalData signal_data; - Meta meta; private: - inline static - std::array const descriptors { - Descriptor { "boolean", SignalType::BOOLEAN, MmsType::MMS_BOOLEAN }, - Descriptor { "int8", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 8 } }, - Descriptor { "int16", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 16 } }, - Descriptor { "int32", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 32 } }, - Descriptor { "int64", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 64 } }, - Descriptor { "int8u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 8 } }, - Descriptor { "int16u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 16 } }, - Descriptor { "int32u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 32 } }, - Descriptor { "bitstring", SignalType::INTEGER, MmsType::MMS_BIT_STRING, {.size = 32 } }, - Descriptor { "float32", SignalType::FLOAT, MmsType::MMS_FLOAT, {.size = 32 } }, - Descriptor { "float64", SignalType::FLOAT, MmsType::MMS_FLOAT, {.size = 64 } }, - }; + inline static std::array const descriptors{ + Descriptor{"boolean", SignalType::BOOLEAN, MmsType::MMS_BOOLEAN}, + Descriptor{ + "int8", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 8}}, + Descriptor{ + "int16", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 16}}, + Descriptor{ + "int32", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 32}}, + Descriptor{ + "int64", SignalType::INTEGER, MmsType::MMS_INTEGER, {.size = 64}}, + Descriptor{ + "int8u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 8}}, + Descriptor{ + "int16u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 16}}, + Descriptor{ + "int32u", SignalType::INTEGER, MmsType::MMS_UNSIGNED, {.size = 32}}, + Descriptor{"bitstring", + SignalType::INTEGER, + MmsType::MMS_BIT_STRING, + {.size = 32}}, + Descriptor{ + "float32", SignalType::FLOAT, MmsType::MMS_FLOAT, {.size = 32}}, + Descriptor{ + "float64", SignalType::FLOAT, MmsType::MMS_FLOAT, {.size = 64}}, + }; - static - MmsValue * newMmsInteger(int64_t i, int size); + static MmsValue *newMmsInteger(int64_t i, int size); - static - MmsValue * newMmsUnsigned(uint64_t i, int size); + static MmsValue *newMmsUnsigned(uint64_t i, int size); - static - MmsValue * newMmsBitString(uint32_t i, int size); + static MmsValue *newMmsBitString(uint32_t i, int size); - static - MmsValue * newMmsFloat(double i, int size); + static MmsValue *newMmsFloat(double i, int size); - // Descriptor within the descriptors table above - Descriptor const *descriptor; + // Descriptor within the descriptors table above + Descriptor const *descriptor; }; bool operator==(GooseSignal &lhs, GooseSignal &rhs); @@ -117,141 +124,134 @@ bool operator!=(GooseSignal &lhs, GooseSignal &rhs); class GooseNode : public Node { protected: - enum InputTrigger { - CHANGE, - ALWAYS, - }; + enum InputTrigger { + CHANGE, + ALWAYS, + }; - struct InputMapping { - std::string subscriber; - unsigned int index; - GooseSignal::Type type; - }; + struct InputMapping { + std::string subscriber; + unsigned int index; + GooseSignal::Type type; + }; - struct SubscriberConfig { - std::string go_cb_ref; - InputTrigger trigger; - std::optional> dst_address; - std::optional app_id; - }; + struct SubscriberConfig { + std::string go_cb_ref; + InputTrigger trigger; + std::optional> dst_address; + std::optional app_id; + }; - struct InputEventContext { - SubscriberConfig subscriber_config; + struct InputEventContext { + SubscriberConfig subscriber_config; - GooseNode *node; - std::vector> values; - int last_state_num; - }; + GooseNode *node; + std::vector> values; + int last_state_num; + }; - struct Input { - enum { NONE, STOPPED, READY } state; - GooseReceiver receiver; - CQueueSignalled queue; - Pool pool; + struct Input { + enum { NONE, STOPPED, READY } state; + GooseReceiver receiver; + CQueueSignalled queue; + Pool pool; - std::map contexts; - std::vector mappings; - std::string interface_id; - bool with_timestamp; - unsigned int queue_length; - } input; + std::map contexts; + std::vector mappings; + std::string interface_id; + bool with_timestamp; + unsigned int queue_length; + } input; - struct OutputData { - std::optional signal; - GooseSignal default_value; - }; + struct OutputData { + std::optional signal; + GooseSignal default_value; + }; - struct PublisherConfig { - std::string go_id; - std::string go_cb_ref; - std::string data_set_ref; - std::array dst_address; - uint16_t app_id; - uint32_t conf_rev; - uint32_t time_allowed_to_live; - int burst; - std::vector data; - }; + struct PublisherConfig { + std::string go_id; + std::string go_cb_ref; + std::string data_set_ref; + std::array dst_address; + uint16_t app_id; + uint32_t conf_rev; + uint32_t time_allowed_to_live; + int burst; + std::vector data; + }; - struct OutputContext { - PublisherConfig config; - std::vector values; + struct OutputContext { + PublisherConfig config; + std::vector values; - GoosePublisher publisher; - }; + GoosePublisher publisher; + }; - struct Output { - enum { NONE, STOPPED, READY } state; - std::vector contexts; - std::string interface_id; - double resend_interval; + struct Output { + enum { NONE, STOPPED, READY } state; + std::vector contexts; + std::string interface_id; + double resend_interval; - std::mutex send_mutex; - bool changed; - bool resend_thread_stop; - std::optional resend_thread; - std::condition_variable resend_thread_cv; - } output; + std::mutex send_mutex; + bool changed; + bool resend_thread_stop; + std::optional resend_thread; + std::condition_variable resend_thread_cv; + } output; - void createReceiver() noexcept; - void destroyReceiver() noexcept; + void createReceiver() noexcept; + void destroyReceiver() noexcept; - void startReceiver() noexcept(false); - void stopReceiver() noexcept; + void startReceiver() noexcept(false); + void stopReceiver() noexcept; - void createPublishers() noexcept; - void destroyPublishers() noexcept; + void createPublishers() noexcept; + void destroyPublishers() noexcept; - void startPublishers() noexcept(false); - void stopPublishers() noexcept; + void startPublishers() noexcept(false); + void stopPublishers() noexcept; - static - void onEvent(GooseSubscriber subscriber, InputEventContext &context) noexcept; + static void onEvent(GooseSubscriber subscriber, + InputEventContext &context) noexcept; - void addSubscriber(InputEventContext &ctx) noexcept; - void pushSample(uint64_t timestamp) noexcept; + void addSubscriber(InputEventContext &ctx) noexcept; + void pushSample(uint64_t timestamp) noexcept; - static - void publish_values(GoosePublisher publisher, std::vector &values, bool changed, int burst = 1) noexcept; - static - void resend_thread(GooseNode::Output *output) noexcept; + static void publish_values(GoosePublisher publisher, + std::vector &values, bool changed, + int burst = 1) noexcept; + static void resend_thread(GooseNode::Output *output) noexcept; - void parseInput(json_t *json); - void parseSubscriber(json_t *json, SubscriberConfig &sc); - void parseSubscribers(json_t *json, std::map &ctx); - void parseInputSignals(json_t *json, std::vector &mappings); + void parseInput(json_t *json); + void parseSubscriber(json_t *json, SubscriberConfig &sc); + void parseSubscribers(json_t *json, + std::map &ctx); + void parseInputSignals(json_t *json, std::vector &mappings); - void parseOutput(json_t *json); - void parsePublisherData(json_t *json, std::vector &data); - void parsePublisher(json_t *json, PublisherConfig &pc); - void parsePublishers(json_t *json, std::vector &ctx); + void parseOutput(json_t *json); + void parsePublisherData(json_t *json, std::vector &data); + void parsePublisher(json_t *json, PublisherConfig &pc); + void parsePublishers(json_t *json, std::vector &ctx); - virtual - int _read(struct Sample *smps[], unsigned cnt) override; + virtual int _read(struct Sample *smps[], unsigned cnt) override; - virtual - int _write(struct Sample *smps[], unsigned cnt) override; + virtual int _write(struct Sample *smps[], unsigned cnt) override; public: - GooseNode(const uuid_t &id = {}, const std::string &name = ""); + GooseNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~GooseNode() override; + virtual ~GooseNode() override; - virtual - std::vector getPollFDs() override; + virtual std::vector getPollFDs() override; - virtual - int parse(json_t *json) override; + virtual int parse(json_t *json) override; - virtual - int prepare() override; + virtual int prepare() override; - virtual - int start() override; + virtual int start() override; - virtual - int stop() override; + virtual int stop() override; }; } // namespace iec61850 diff --git a/include/villas/nodes/iec61850_sv.hpp b/include/villas/nodes/iec61850_sv.hpp index f46612834..65d40851f 100644 --- a/include/villas/nodes/iec61850_sv.hpp +++ b/include/villas/nodes/iec61850_sv.hpp @@ -12,10 +12,10 @@ #include #include -#include -#include #include #include +#include +#include namespace villas { namespace node { @@ -24,47 +24,47 @@ namespace node { class NodeCompat; struct iec61850_sv { - char *interface; - int app_id; - struct ether_addr dst_address; + char *interface; + int app_id; + struct ether_addr dst_address; - struct { - bool enabled; + struct { + bool enabled; - SVSubscriber subscriber; - SVReceiver receiver; + SVSubscriber subscriber; + SVReceiver receiver; - struct CQueueSignalled queue; - struct Pool pool; + struct CQueueSignalled queue; + struct Pool pool; - struct List signals; // Mappings of type struct iec61850_type_descriptor - int total_size; - } in; + struct List signals; // Mappings of type struct iec61850_type_descriptor + int total_size; + } in; - struct { - bool enabled; + struct { + bool enabled; - SVPublisher publisher; - SVPublisher_ASDU asdu; + SVPublisher publisher; + SVPublisher_ASDU asdu; - char *svid; + char *svid; - int vlan_priority; - int vlan_id; - int smpmod; - int smprate; - int confrev; + int vlan_priority; + int vlan_id; + int smpmod; + int smprate; + int confrev; - struct List signals; // Mappings of type struct iec61850_type_descriptor - int total_size; - } out; + struct List signals; // Mappings of type struct iec61850_type_descriptor + int total_size; + } out; }; int iec61850_sv_type_stop(); int iec61850_sv_parse(NodeCompat *n, json_t *json); -char * iec61850_sv_print(NodeCompat *n); +char *iec61850_sv_print(NodeCompat *n); int iec61850_sv_start(NodeCompat *n); @@ -72,9 +72,9 @@ int iec61850_sv_stop(NodeCompat *n); int iec61850_sv_destroy(NodeCompat *n); -int iec61850_sv_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int iec61850_sv_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int iec61850_sv_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int iec61850_sv_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int iec61850_sv_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/infiniband.hpp b/include/villas/nodes/infiniband.hpp index f733ffd25..8cd1e25f9 100644 --- a/include/villas/nodes/infiniband.hpp +++ b/include/villas/nodes/infiniband.hpp @@ -7,10 +7,10 @@ #pragma once -#include -#include -#include #include +#include +#include +#include namespace villas { namespace node { @@ -25,76 +25,76 @@ class NodeCompat; #define CHK_PER_ITER 2048 struct infiniband { - // IBV/RDMA CM structs - struct context_s { - struct rdma_cm_id *listen_id; - struct rdma_cm_id *id; - struct rdma_event_channel *ec; + // IBV/RDMA CM structs + struct context_s { + struct rdma_cm_id *listen_id; + struct rdma_cm_id *id; + struct rdma_event_channel *ec; - struct ibv_pd *pd; - struct ibv_cq *recv_cq; - struct ibv_cq *send_cq; - struct ibv_comp_channel *comp_channel; - } ctx; + struct ibv_pd *pd; + struct ibv_cq *recv_cq; + struct ibv_cq *send_cq; + struct ibv_comp_channel *comp_channel; + } ctx; - // Queue Pair init variables - struct ibv_qp_init_attr qp_init; + // Queue Pair init variables + struct ibv_qp_init_attr qp_init; - // Size of receive and send completion queue - int recv_cq_size; - int send_cq_size; + // Size of receive and send completion queue + int recv_cq_size; + int send_cq_size; - // Bool, set if threads should be aborted - int stopThreads; + // Bool, set if threads should be aborted + int stopThreads; - // When most messages are sent inline, once every cycles a signal must be sent. - unsigned signaling_counter; - unsigned periodic_signaling; + // When most messages are sent inline, once every cycles a signal must be sent. + unsigned signaling_counter; + unsigned periodic_signaling; - // Connection specific variables - struct connection_s { - struct addrinfo *src_addr; - struct addrinfo *dst_addr; + // Connection specific variables + struct connection_s { + struct addrinfo *src_addr; + struct addrinfo *dst_addr; - // RDMA_PS_TCP or RDMA_PS_UDP - enum rdma_port_space port_space; + // RDMA_PS_TCP or RDMA_PS_UDP + enum rdma_port_space port_space; - // Timeout for rdma_resolve_route - int timeout; + // Timeout for rdma_resolve_route + int timeout; - // Thread to monitor RDMA CM Event threads - pthread_t rdma_cm_event_thread; + // Thread to monitor RDMA CM Event threads + pthread_t rdma_cm_event_thread; - // Bool, should data be send inline if possible? - int send_inline; + // Bool, should data be send inline if possible? + int send_inline; - // Bool, should node have a fallback if it can't connect to a remote host? - int use_fallback; + // Bool, should node have a fallback if it can't connect to a remote host? + int use_fallback; - // Counter to keep track of available recv. WRs - unsigned available_recv_wrs; + // Counter to keep track of available recv. WRs + unsigned available_recv_wrs; - /* Fixed number to substract from min. number available + /* Fixed number to substract from min. number available * WRs in receive queue */ - unsigned buffer_subtraction; + unsigned buffer_subtraction; - // Unrealiable connectionless data - struct ud_s { - struct rdma_ud_param ud; - struct ibv_ah *ah; - void *grh_ptr; - struct ibv_mr *grh_mr; - } ud; + // Unrealiable connectionless data + struct ud_s { + struct rdma_ud_param ud; + struct ibv_ah *ah; + void *grh_ptr; + struct ibv_mr *grh_mr; + } ud; - } conn; + } conn; - // Misc settings - int is_source; + // Misc settings + int is_source; }; int ib_reverse(NodeCompat *n); -char * ib_print(NodeCompat *n); +char *ib_print(NodeCompat *n); int ib_parse(NodeCompat *n, json_t *json); @@ -106,9 +106,9 @@ int ib_destroy(NodeCompat *n); int ib_stop(NodeCompat *n); -int ib_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ib_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int ib_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ib_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/influxdb.hpp b/include/villas/nodes/influxdb.hpp index 2352a12ed..184d32f09 100644 --- a/include/villas/nodes/influxdb.hpp +++ b/include/villas/nodes/influxdb.hpp @@ -17,16 +17,16 @@ class NodeCompat; struct Sample; struct influxdb { - char *host; - char *port; - char *key; + char *host; + char *port; + char *key; - struct List fields; + struct List fields; - int sd; + int sd; }; -char * influxdb_print(NodeCompat *n); +char *influxdb_print(NodeCompat *n); int influxdb_parse(NodeCompat *n, json_t *json); @@ -34,7 +34,7 @@ int influxdb_open(NodeCompat *n); int influxdb_close(NodeCompat *n); -int influxdb_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int influxdb_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/kafka.hpp b/include/villas/nodes/kafka.hpp index d4438d824..4ca6a765a 100644 --- a/include/villas/nodes/kafka.hpp +++ b/include/villas/nodes/kafka.hpp @@ -9,8 +9,8 @@ #include -#include #include +#include #include namespace villas { @@ -20,42 +20,42 @@ namespace node { class NodeCompat; struct kafka { - struct CQueueSignalled queue; - struct Pool pool; + struct CQueueSignalled queue; + struct Pool pool; - double timeout; // Timeout in seconds. - char *server; // Hostname/IP:Port address of the bootstrap server. - char *protocol; // Security protocol. - char *produce; // Producer topic. - char *consume; // Consumer topic. - char *client_id; // Client ID. + double timeout; // Timeout in seconds. + char *server; // Hostname/IP:Port address of the bootstrap server. + char *protocol; // Security protocol. + char *produce; // Producer topic. + char *consume; // Consumer topic. + char *client_id; // Client ID. - struct { - rd_kafka_t *client; - rd_kafka_topic_t *topic; - } producer; + struct { + rd_kafka_t *client; + rd_kafka_topic_t *topic; + } producer; - struct { - rd_kafka_t *client; - char *group_id; // Group id. - } consumer; + struct { + rd_kafka_t *client; + char *group_id; // Group id. + } consumer; - struct { - char *ca; // SSL CA file. - } ssl; + struct { + char *ca; // SSL CA file. + } ssl; - struct { - char *mechanisms; // SASL mechanisms. - char *username; // SSL CA path. - char *password; // SSL certificate. - } sasl; + struct { + char *mechanisms; // SASL mechanisms. + char *username; // SSL CA path. + char *password; // SSL certificate. + } sasl; - Format *formatter; + Format *formatter; }; int kafka_reverse(NodeCompat *n); -char * kafka_print(NodeCompat *n); +char *kafka_print(NodeCompat *n); int kafka_init(NodeCompat *n); @@ -75,9 +75,9 @@ int kafka_type_stop(); int kafka_poll_fds(NodeCompat *n, int fds[]); -int kafka_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int kafka_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int kafka_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int kafka_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/loopback.hpp b/include/villas/nodes/loopback.hpp index 404ce1571..5632f96df 100644 --- a/include/villas/nodes/loopback.hpp +++ b/include/villas/nodes/loopback.hpp @@ -17,36 +17,28 @@ namespace node { class LoopbackNode : public Node { protected: - int queuelen; - struct CQueueSignalled queue; - enum QueueSignalledMode mode; + int queuelen; + struct CQueueSignalled queue; + enum QueueSignalledMode mode; - virtual - int _write(struct Sample * smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); - virtual - int _read(struct Sample * smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); public: - LoopbackNode(const uuid_t &id = {}, const std::string &name = ""); + LoopbackNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~LoopbackNode(); + virtual ~LoopbackNode(); - virtual - int prepare(); + virtual int prepare(); - virtual - int stop(); + virtual int stop(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); }; } // namespace node diff --git a/include/villas/nodes/loopback_internal.hpp b/include/villas/nodes/loopback_internal.hpp index 8317164a2..566ad0b21 100644 --- a/include/villas/nodes/loopback_internal.hpp +++ b/include/villas/nodes/loopback_internal.hpp @@ -16,62 +16,48 @@ namespace node { class InternalLoopbackNode : public Node { protected: - unsigned queuelen; - struct CQueueSignalled queue; + unsigned queuelen; + struct CQueueSignalled queue; - Node *source; + Node *source; - virtual - int _write(struct Sample * smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); - virtual - int _read(struct Sample * smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); public: - InternalLoopbackNode(Node *src, unsigned id = 0, unsigned ql = DEFAULT_QUEUE_LENGTH); + InternalLoopbackNode(Node *src, unsigned id = 0, + unsigned ql = DEFAULT_QUEUE_LENGTH); - virtual - ~InternalLoopbackNode(); + virtual ~InternalLoopbackNode(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - virtual - int stop(); + virtual int stop(); }; class InternalLoopbackNodeFactory : public NodeFactory { public: - using NodeFactory::NodeFactory; + using NodeFactory::NodeFactory; - virtual - Node * make(const uuid_t &id = {}, const std::string &name = "") - { - return nullptr; - } + virtual Node *make(const uuid_t &id = {}, const std::string &name = "") { + return nullptr; + } - virtual - int getFlags() const - { - return (int) NodeFactory::Flags::INTERNAL | - (int) NodeFactory::Flags::PROVIDES_SIGNALS | - (int) NodeFactory::Flags::SUPPORTS_READ | - (int) NodeFactory::Flags::SUPPORTS_WRITE | - (int) NodeFactory::Flags::SUPPORTS_POLL; - } + virtual int getFlags() const { + return (int)NodeFactory::Flags::INTERNAL | + (int)NodeFactory::Flags::PROVIDES_SIGNALS | + (int)NodeFactory::Flags::SUPPORTS_READ | + (int)NodeFactory::Flags::SUPPORTS_WRITE | + (int)NodeFactory::Flags::SUPPORTS_POLL; + } - virtual - std::string getName() const - { - return "loopback.internal"; - } + virtual std::string getName() const { return "loopback.internal"; } - virtual - std::string getDescription() const - { - return "internal loopback node"; - } + virtual std::string getDescription() const { + return "internal loopback node"; + } }; } // namespace node diff --git a/include/villas/nodes/modbus.hpp b/include/villas/nodes/modbus.hpp index 27436d2be..e0f9b61c7 100644 --- a/include/villas/nodes/modbus.hpp +++ b/include/villas/nodes/modbus.hpp @@ -7,22 +7,22 @@ #pragma once -#include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include #include -#include -#include -#include -#include #include +#include +#include +#include #include +#include namespace villas { namespace node { @@ -32,37 +32,35 @@ using modbus_addr_t = uint16_t; using modbus_addrdiff_t = int32_t; enum class Parity : char { - None = 'N', - Even = 'E', - Odd = 'O', + None = 'N', + Even = 'E', + Odd = 'O', }; enum class Endianess : char { - Big, - Little, + Big, + Little, }; // The settings for an RTU modbus connection. struct Rtu { - std::string device; - Parity parity; - int baudrate; - int data_bits; - int stop_bits; - unsigned char unit; + std::string device; + Parity parity; + int baudrate; + int data_bits; + int stop_bits; + unsigned char unit; - static - Rtu parse(json_t *json); + static Rtu parse(json_t *json); }; // The settings for an TCP MODBUS connection. struct Tcp { - std::string remote; - uint16_t port; - std::optional unit; + std::string remote; + uint16_t port; + std::optional unit; - static - Tcp parse(json_t *json); + static Tcp parse(json_t *json); }; // Forward declarations @@ -72,7 +70,8 @@ class RegisterMappingSingle; using RegisterMappingBlock = std::vector; // Either a single mapping or a merged block of mappings. -using RegisterMapping = std::variant; +using RegisterMapping = + std::variant; // Swap the two bytes of a 16 bit integer. uint16_t byteswap(uint16_t i); @@ -105,13 +104,16 @@ modbus_addr_t mappedRegisters(RegisterMappingBlock const &block); modbus_addr_t mappedRegisters(RegisterMapping const &mapping); // The distance between two blocks. -modbus_addrdiff_t blockDistance(RegisterMapping const &lhs, RegisterMapping const &rhs); +modbus_addrdiff_t blockDistance(RegisterMapping const &lhs, + RegisterMapping const &rhs); // Whether there are overlapping bit mappings between lhs and rhs. -bool hasOverlappingBitMapping(RegisterMapping const &lhs, RegisterMapping const &rhs); +bool hasOverlappingBitMapping(RegisterMapping const &lhs, + RegisterMapping const &rhs); // The compare the addresses of two mappings. -bool compareBlockAddress(RegisterMapping const &lhs, RegisterMapping const &rhs); +bool compareBlockAddress(RegisterMapping const &lhs, + RegisterMapping const &rhs); // Parse an Endianess from a null terminated string. Endianess parseEndianess(char const *str); @@ -122,170 +124,176 @@ Parity parseParity(char const *str); // The mapping from a register to a signal. class RegisterMappingSingle { public: - inline static constexpr - size_t MAX_REGISTERS = sizeof(int64_t) / sizeof(int16_t); + inline static constexpr size_t MAX_REGISTERS = + sizeof(int64_t) / sizeof(int16_t); - struct IntegerToInteger { - Endianess word_endianess; - Endianess byte_endianess; - modbus_addr_t num_registers; + struct IntegerToInteger { + Endianess word_endianess; + Endianess byte_endianess; + modbus_addr_t num_registers; - int64_t read(uint16_t const *registers) const; - void write(int64_t i, uint16_t *registers) const; - }; + int64_t read(uint16_t const *registers) const; + void write(int64_t i, uint16_t *registers) const; + }; - struct IntegerToFloat { - IntegerToInteger integer_conversion; - double offset; - double scale; + struct IntegerToFloat { + IntegerToInteger integer_conversion; + double offset; + double scale; - double read(uint16_t const *registers) const; - void write(double d, uint16_t *registers) const; - }; + double read(uint16_t const *registers) const; + void write(double d, uint16_t *registers) const; + }; - struct FloatToFloat { - Endianess word_endianess; - Endianess byte_endianess; - double offset; - double scale; + struct FloatToFloat { + Endianess word_endianess; + Endianess byte_endianess; + double offset; + double scale; - double read(uint16_t const *registers) const; - void write(double d, uint16_t *registers) const; - }; + double read(uint16_t const *registers) const; + void write(double d, uint16_t *registers) const; + }; - struct BitToBool { - uint8_t bit; + struct BitToBool { + uint8_t bit; - bool read(uint16_t reg) const; - }; + bool read(uint16_t reg) const; + }; - // Conversion rule for registers. - // - // - IntegerToInteger means merging multiple registers. - // - FloatToFloat converts from IEEE float to float. - // - IntegerToFloat converts registers to integer, casts to float - // and then applies offset and scale to produce a float. - // - BitToBool takes a single bit from a registers and reports it as a boolean. - std::variant conversion; + // Conversion rule for registers. + // + // - IntegerToInteger means merging multiple registers. + // - FloatToFloat converts from IEEE float to float. + // - IntegerToFloat converts registers to integer, casts to float + // and then applies offset and scale to produce a float. + // - BitToBool takes a single bit from a registers and reports it as a boolean. + std::variant + conversion; - RegisterMappingSingle(unsigned int signal_index, modbus_addr_t address); + RegisterMappingSingle(unsigned int signal_index, modbus_addr_t address); - unsigned int signal_index; - modbus_addr_t address; + unsigned int signal_index; + modbus_addr_t address; - static - RegisterMappingSingle parse(unsigned int index, Signal::Ptr signal, json_t *json); + static RegisterMappingSingle parse(unsigned int index, Signal::Ptr signal, + json_t *json); - SignalData read(uint16_t const *registers, modbus_addr_t length) const; - void write(SignalData data, uint16_t *registers, modbus_addr_t length) const; + SignalData read(uint16_t const *registers, modbus_addr_t length) const; + void write(SignalData data, uint16_t *registers, modbus_addr_t length) const; - modbus_addr_t num_registers() const; + modbus_addr_t num_registers() const; }; class ModbusNode final : public Node { private: - // The maximum size of a RegisterMappingBlock created during mergeMappings. - // The size of a block here is defined as the difference between blockBegin and blockEnd. - modbus_addr_t max_block_size; + // The maximum size of a RegisterMappingBlock created during mergeMappings. + // The size of a block here is defined as the difference between blockBegin and blockEnd. + modbus_addr_t max_block_size; - // The minimum block usage of a RegisterMappingBlock created during mergeMappings. - // The usage of a block is defined as the ration of registers used in mappings to the size of the block. - // The size of a block here is defined as the difference between blockBegin and blockEnd. - float min_block_usage; + // The minimum block usage of a RegisterMappingBlock created during mergeMappings. + // The usage of a block is defined as the ration of registers used in mappings to the size of the block. + // The size of a block here is defined as the difference between blockBegin and blockEnd. + float min_block_usage; - // The type of connection settings used to initialize the modbus_context. - std::variant connection_settings; + // The type of connection settings used to initialize the modbus_context. + std::variant connection_settings; - // The rate used for periodically querying the modbus device registers. - double rate; + // The rate used for periodically querying the modbus device registers. + double rate; - // The timeout in seconds when waiting for a response from a modbus slave/server. - double response_timeout; + // The timeout in seconds when waiting for a response from a modbus slave/server. + double response_timeout; - // Mappings used to create the input signals from the read registers. - std::vector in_mappings; + // Mappings used to create the input signals from the read registers. + std::vector in_mappings; - // Number of in signals. - unsigned int num_in_signals; + // Number of in signals. + unsigned int num_in_signals; - // Mappings used to create the input signals from the read registers. - std::vector out_mappings; + // Mappings used to create the input signals from the read registers. + std::vector out_mappings; - // Number of out signals. - unsigned int num_out_signals; + // Number of out signals. + unsigned int num_out_signals; - // The interval in seconds for trying to reconnect on connection loss. - double reconnect_interval; + // The interval in seconds for trying to reconnect on connection loss. + double reconnect_interval; - std::vector read_buffer; - std::vector write_buffer; - modbus_t *modbus_context; - Task read_task; - std::atomic reconnecting; + std::vector read_buffer; + std::vector write_buffer; + modbus_t *modbus_context; + Task read_task; + std::atomic reconnecting; - bool isReconnecting(); - void reconnect(); + bool isReconnecting(); + void reconnect(); - static - void mergeMappingInplace(RegisterMapping &lhs, RegisterMappingBlock const &rhs); + static void mergeMappingInplace(RegisterMapping &lhs, + RegisterMappingBlock const &rhs); - static - void mergeMappingInplace(RegisterMapping &lhs, RegisterMappingSingle const &rhs); + static void mergeMappingInplace(RegisterMapping &lhs, + RegisterMappingSingle const &rhs); - bool tryMergeMappingInplace(RegisterMapping &lhs, RegisterMapping const &rhs); + bool tryMergeMappingInplace(RegisterMapping &lhs, RegisterMapping const &rhs); - void mergeMappings(std::vector &mappings, modbus_addrdiff_t max_block_distance); + void mergeMappings(std::vector &mappings, + modbus_addrdiff_t max_block_distance); - unsigned int parseMappings(std::vector &mappings, json_t *json); + unsigned int parseMappings(std::vector &mappings, + json_t *json); - int readMapping(RegisterMappingSingle const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals); + int readMapping(RegisterMappingSingle const &mapping, + uint16_t const *registers, modbus_addr_t num_registers, + SignalData *signals, unsigned int num_signals); - int readMapping(RegisterMappingBlock const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals); + int readMapping(RegisterMappingBlock const &mapping, + uint16_t const *registers, modbus_addr_t num_registers, + SignalData *signals, unsigned int num_signals); - int readMapping(RegisterMapping const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals); + int readMapping(RegisterMapping const &mapping, uint16_t const *registers, + modbus_addr_t num_registers, SignalData *signals, + unsigned int num_signals); - int readBlock(RegisterMapping const &mapping, SignalData *signals, size_t num_signals); + int readBlock(RegisterMapping const &mapping, SignalData *signals, + size_t num_signals); - virtual - int _read(struct Sample *smps[], unsigned int cnt); + virtual int _read(struct Sample *smps[], unsigned int cnt); - int writeMapping(RegisterMappingSingle const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals); - int writeMapping(RegisterMappingBlock const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals); - int writeMapping(RegisterMapping const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals); - int writeBlock(RegisterMapping const &mapping, SignalData const *signals, size_t num_signals); + int writeMapping(RegisterMappingSingle const &mapping, uint16_t *registers, + modbus_addr_t num_registers, SignalData const *signals, + unsigned int num_signals); + int writeMapping(RegisterMappingBlock const &mapping, uint16_t *registers, + modbus_addr_t num_registers, SignalData const *signals, + unsigned int num_signals); + int writeMapping(RegisterMapping const &mapping, uint16_t *registers, + modbus_addr_t num_registers, SignalData const *signals, + unsigned int num_signals); + int writeBlock(RegisterMapping const &mapping, SignalData const *signals, + size_t num_signals); - virtual - int _write(struct Sample *smps[], unsigned int cnt); + virtual int _write(struct Sample *smps[], unsigned int cnt); public: - ModbusNode(const uuid_t &id = {}, const std::string &name = ""); + ModbusNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~ModbusNode(); + virtual ~ModbusNode(); - virtual - int prepare(); + virtual int prepare(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - int check(); + virtual int check(); - virtual - int start(); + virtual int start(); - virtual - int stop(); + virtual int stop(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - virtual - std::vector getNetemFDs(); + virtual std::vector getNetemFDs(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); }; } // namespace modbus diff --git a/include/villas/nodes/mqtt.hpp b/include/villas/nodes/mqtt.hpp index 30f421a96..53c9ea750 100644 --- a/include/villas/nodes/mqtt.hpp +++ b/include/villas/nodes/mqtt.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include @@ -22,38 +22,38 @@ namespace node { class NodeCompat; struct mqtt { - struct mosquitto *client; - struct CQueueSignalled queue; - struct Pool pool; + struct mosquitto *client; + struct CQueueSignalled queue; + struct Pool pool; - int keepalive; // Keep-alive interval in seconds. Zero for no keepalive. - int port; // Hostname / IP address of the broker. - int qos; // Integer value 0, 1 or 2 indicating the Quality of Service to be used for publishing messages. - int retain; // Mark published messages as retained. - char *host; // Hostname / IP address of the broker. - char *username; // Username for authentication to the broker. - char *password; // Password for authentication to the broker. - char *publish; // Publish topic. - char *subscribe; // Subscribe topic. + int keepalive; // Keep-alive interval in seconds. Zero for no keepalive. + int port; // Hostname / IP address of the broker. + int qos; // Integer value 0, 1 or 2 indicating the Quality of Service to be used for publishing messages. + int retain; // Mark published messages as retained. + char *host; // Hostname / IP address of the broker. + char *username; // Username for authentication to the broker. + char *password; // Password for authentication to the broker. + char *publish; // Publish topic. + char *subscribe; // Subscribe topic. - struct { - int enabled; // Enable SSL encrypted connection to broker. - int insecure; // Allow insecure SSL connections. - char *cafile; // SSL CA file. - char *capath; // SSL CA path. - char *certfile; // SSL certificate. - char *keyfile; // SSL private key. - int cert_reqs; // SSL_VERIFY_NONE(0) or SSL_VERIFY_PEER(1) - char *tls_version; // SSL tls verion - char *ciphers; // SSL chipher list. - } ssl; + struct { + int enabled; // Enable SSL encrypted connection to broker. + int insecure; // Allow insecure SSL connections. + char *cafile; // SSL CA file. + char *capath; // SSL CA path. + char *certfile; // SSL certificate. + char *keyfile; // SSL private key. + int cert_reqs; // SSL_VERIFY_NONE(0) or SSL_VERIFY_PEER(1) + char *tls_version; // SSL tls verion + char *ciphers; // SSL chipher list. + } ssl; - Format *formatter; + Format *formatter; }; int mqtt_reverse(NodeCompat *n); -char * mqtt_print(NodeCompat *n); +char *mqtt_print(NodeCompat *n); int mqtt_prepare(NodeCompat *n); @@ -75,9 +75,9 @@ int mqtt_type_stop(); int mqtt_poll_fds(NodeCompat *n, int fds[]); -int mqtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int mqtt_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int mqtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int mqtt_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/nanomsg.hpp b/include/villas/nodes/nanomsg.hpp index e45c1ec8a..775149002 100644 --- a/include/villas/nodes/nanomsg.hpp +++ b/include/villas/nodes/nanomsg.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include namespace villas { namespace node { @@ -20,15 +20,15 @@ class NodeCompat; #define NANOMSG_MAX_PACKET_LEN 1500 struct nanomsg { - struct { - int socket; - struct List endpoints; - } in, out; + struct { + int socket; + struct List endpoints; + } in, out; - Format *formatter; + Format *formatter; }; -char * nanomsg_print(NodeCompat *n); +char *nanomsg_print(NodeCompat *n); int nanomsg_init(NodeCompat *n); @@ -48,9 +48,9 @@ int nanomsg_poll_fds(NodeCompat *n, int fds[]); int nanomsg_netem_fds(NodeCompat *n, int fds[]); -int nanomsg_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int nanomsg_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int nanomsg_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int nanomsg_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/ngsi.hpp b/include/villas/nodes/ngsi.hpp index ebcd6dbfd..8604343a7 100644 --- a/include/villas/nodes/ngsi.hpp +++ b/include/villas/nodes/ngsi.hpp @@ -26,26 +26,28 @@ namespace node { class NodeCompat; struct ngsi { - const char *endpoint; // The NGSI context broker endpoint URL. - const char *entity_id; // The context broker entity id related to this node - const char *entity_type; // The type of the entity - const char *access_token; // An optional authentication token which will be sent as HTTP header. + const char *endpoint; // The NGSI context broker endpoint URL. + const char *entity_id; // The context broker entity id related to this node + const char *entity_type; // The type of the entity + const char * + access_token; // An optional authentication token which will be sent as HTTP header. - bool create; // Weather we want to create the context element during startup. - bool remove; // Weather we want to delete the context element during startup. + bool create; // Weather we want to create the context element during startup. + bool remove; // Weather we want to delete the context element during startup. - double timeout; // HTTP timeout in seconds - double rate; // Rate used for polling. + double timeout; // HTTP timeout in seconds + double rate; // Rate used for polling. - struct Task task; // Timer for periodic events. - int ssl_verify; // Boolean flag whether SSL server certificates should be verified or not. + struct Task task; // Timer for periodic events. + int ssl_verify; // Boolean flag whether SSL server certificates should be verified or not. - struct curl_slist *headers; // List of HTTP request headers for libcurl + struct curl_slist *headers; // List of HTTP request headers for libcurl - struct { - CURL *curl; // libcurl: handle - struct List signals; // A mapping between indices of the VILLASnode samples and the attributes in ngsi::context - } in, out; + struct { + CURL *curl; // libcurl: handle + struct List + signals; // A mapping between indices of the VILLASnode samples and the attributes in ngsi::context + } in, out; }; int ngsi_type_start(SuperNode *sn); @@ -54,7 +56,7 @@ int ngsi_type_stop(); int ngsi_parse(NodeCompat *n, json_t *json); -char * ngsi_print(NodeCompat *n); +char *ngsi_print(NodeCompat *n); int ngsi_init(NodeCompat *n); @@ -66,9 +68,9 @@ int ngsi_stop(NodeCompat *n); int ngsi_reverse(NodeCompat *n); -int ngsi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ngsi_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int ngsi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int ngsi_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int ngsi_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/opal.hpp b/include/villas/nodes/opal.hpp index 17117b4d4..b613bbdbf 100644 --- a/include/villas/nodes/opal.hpp +++ b/include/villas/nodes/opal.hpp @@ -18,19 +18,19 @@ namespace node { class NodeCompat; extern "C" { - #include +#include } struct opal { - int reply; - int mode; - int sequenceNo; + int reply; + int mode; + int sequenceNo; - unsigned sendID; - unsigned recvID; + unsigned sendID; + unsigned recvID; - Opal_SendAsyncParam sendParams; - Opal_RecvAsyncParam recvParams; + Opal_SendAsyncParam sendParams; + Opal_RecvAsyncParam recvParams; }; int opal_type_start(SuperNode *sn); @@ -41,15 +41,15 @@ int opal_type_stop(); int opal_parse(NodeCompat *n, json_t *json); -char * opal_print(NodeCompat *n); +char *opal_print(NodeCompat *n); int opal_start(NodeCompat *n); int opal_stop(NodeCompat *n); -int opal_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int opal_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int opal_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int opal_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/redis.hpp b/include/villas/nodes/redis.hpp index 4a56002c2..ab9b43c4d 100644 --- a/include/villas/nodes/redis.hpp +++ b/include/villas/nodes/redis.hpp @@ -13,80 +13,71 @@ #include -#include -#include -#include #include -#include +#include +#include #include #include +#include +#include namespace villas { namespace node { -enum class RedisMode { - KEY, - HASH, - CHANNEL -}; +enum class RedisMode { KEY, HASH, CHANNEL }; class RedisConnection { public: - sw::redis::Redis context; + sw::redis::Redis context; protected: - enum State { - INITIALIZED, - RUNNING, - STOPPING - }; + enum State { INITIALIZED, RUNNING, STOPPING }; - std::thread thread; - std::atomic state; + std::thread thread; + std::atomic state; - void onMessage(const std::string &channel, const std::string &msg); + void onMessage(const std::string &channel, const std::string &msg); - void loop(); + void loop(); - std::unordered_multimap subscriberMap; + std::unordered_multimap subscriberMap; - sw::redis::Subscriber subscriber; + sw::redis::Subscriber subscriber; - villas::Logger logger; + villas::Logger logger; public: + RedisConnection(const sw::redis::ConnectionOptions &opts); - RedisConnection(const sw::redis::ConnectionOptions &opts); + static RedisConnection *get(const sw::redis::ConnectionOptions &opts); - static - RedisConnection * get(const sw::redis::ConnectionOptions &opts); + void start(); + void stop(); - void start(); - void stop(); - - void subscribe(NodeCompat *n, const std::string &channel); - void unsubscribe(NodeCompat *n, const std::string &channel); + void subscribe(NodeCompat *n, const std::string &channel); + void unsubscribe(NodeCompat *n, const std::string &channel); }; struct redis { - sw::redis::ConnectionOptions options; + sw::redis::ConnectionOptions options; - RedisConnection *conn; + RedisConnection *conn; - enum RedisMode mode; + enum RedisMode mode; - std::string key; + std::string key; - bool notify; // Use Redis Keyspace notifications to listen for updates. + bool notify; // Use Redis Keyspace notifications to listen for updates. - struct Task task; // Timer for periodic events. - double rate; // Rate for polling key updates if keyspace notifications are disabled. + struct Task task; // Timer for periodic events. + double + rate; // Rate for polling key updates if keyspace notifications are disabled. - Format *formatter; + Format *formatter; - struct Pool pool; - struct CQueueSignalled queue; + struct Pool pool; + struct CQueueSignalled queue; }; int redis_init(NodeCompat *n); @@ -95,7 +86,7 @@ int redis_destroy(NodeCompat *n); int redis_parse(NodeCompat *n, json_t *json); -char * redis_print(NodeCompat *n); +char *redis_print(NodeCompat *n); int redis_check(NodeCompat *n); @@ -109,9 +100,9 @@ int redis_pause(NodeCompat *n); int redis_resume(NodeCompat *n); -int redis_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int redis_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int redis_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int redis_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int redis_reverse(NodeCompat *n); diff --git a/include/villas/nodes/redis_helpers.hpp b/include/villas/nodes/redis_helpers.hpp index e8fe617b9..701bde7ec 100644 --- a/include/villas/nodes/redis_helpers.hpp +++ b/include/villas/nodes/redis_helpers.hpp @@ -9,57 +9,42 @@ #include #include -#include #include +#include #include namespace std { -template -struct hash> -{ - std::size_t operator()(std::chrono::duration<_rep, ratio> const& s) const - { - return std::hash<_rep>{}(s.count()); - } +template +struct hash> { + std::size_t operator()(std::chrono::duration<_rep, ratio> const &s) const { + return std::hash<_rep>{}(s.count()); + } }; -template <> -struct hash -{ - std::size_t operator()(const sw::redis::tls::TlsOptions& t) const - { +template <> struct hash { + std::size_t operator()(const sw::redis::tls::TlsOptions &t) const { #ifdef REDISPP_WITH_TLS - return hash()(t.enabled) ^ - hash()(t.cacert) ^ - hash()(t.cacertdir) ^ - hash()(t.cert) ^ - hash()(t.key) ^ - hash()(t.sni); + return hash()(t.enabled) ^ hash()(t.cacert) ^ + hash()(t.cacertdir) ^ hash()(t.cert) ^ + hash()(t.key) ^ hash()(t.sni); #else - return 0; + return 0; #endif // REDISPP_WITH_TLS - } + } }; -template <> -struct hash -{ - std::size_t operator()(const sw::redis::ConnectionOptions& o) const - { - return hash()(static_cast(o.type)) ^ - hash()(o.host) ^ - hash()(o.port) ^ - hash()(o.path) ^ - hash()(o.user) ^ - hash()(o.password) ^ - hash()(o.db) ^ - hash()(o.keep_alive) ^ - hash()(o.connect_timeout) ^ - hash()(o.socket_timeout) ^ - hash()(o.tls); - } +template <> struct hash { + std::size_t operator()(const sw::redis::ConnectionOptions &o) const { + return hash()(static_cast(o.type)) ^ hash()(o.host) ^ + hash()(o.port) ^ hash()(o.path) ^ + hash()(o.user) ^ hash()(o.password) ^ + hash()(o.db) ^ hash()(o.keep_alive) ^ + hash()(o.connect_timeout) ^ + hash()(o.socket_timeout) ^ + hash()(o.tls); + } }; } // namespace std @@ -67,140 +52,123 @@ struct hash namespace sw { namespace redis { -bool operator==(const tls::TlsOptions &o1, const tls::TlsOptions &o2) -{ +bool operator==(const tls::TlsOptions &o1, const tls::TlsOptions &o2) { #ifdef REDISPP_WITH_TLS - return o1.enabled == o2.enabled && - o1.cacert == o2.cacert && - o1.cacertdir == o2.cacertdir && - o1.cert == o2.cert && - o1.key == o2.key && - o1.sni == o2.sni; + return o1.enabled == o2.enabled && o1.cacert == o2.cacert && + o1.cacertdir == o2.cacertdir && o1.cert == o2.cert && + o1.key == o2.key && o1.sni == o2.sni; #else - return true; + return true; #endif // REDISPP_WITH_TLS } -bool operator==(const ConnectionOptions &o1, const ConnectionOptions &o2) -{ - return o1.type == o2.type && - o1.host == o2.host && - o1.port == o2.port && - o1.path == o2.path && - o1.user == o2.user && - o1.password == o2.password && - o1.db == o2.db && - o1.keep_alive == o2.keep_alive && - o1.connect_timeout == o2.connect_timeout && - o1.socket_timeout == o2.socket_timeout && - o1.tls == o2.tls; +bool operator==(const ConnectionOptions &o1, const ConnectionOptions &o2) { + return o1.type == o2.type && o1.host == o2.host && o1.port == o2.port && + o1.path == o2.path && o1.user == o2.user && + o1.password == o2.password && o1.db == o2.db && + o1.keep_alive == o2.keep_alive && + o1.connect_timeout == o2.connect_timeout && + o1.socket_timeout == o2.socket_timeout && o1.tls == o2.tls; } #ifdef REDISPP_WITH_TLS -template -OStream &operator<<(OStream &os, const tls::TlsOptions &t) -{ - os << "tls.enabled=" << (t.enabled ? "yes" : "no"); +template +OStream &operator<<(OStream &os, const tls::TlsOptions &t) { + os << "tls.enabled=" << (t.enabled ? "yes" : "no"); - if (t.enabled) { - if (!t.cacert.empty()) - os << ", tls.cacert=" << t.cacert; + if (t.enabled) { + if (!t.cacert.empty()) + os << ", tls.cacert=" << t.cacert; - if (!t.cacertdir.empty()) - os << ", tls.cacertdir=" << t.cacertdir; + if (!t.cacertdir.empty()) + os << ", tls.cacertdir=" << t.cacertdir; - if (!t.cert.empty()) - os << ", tls.cert=" << t.cert; + if (!t.cert.empty()) + os << ", tls.cert=" << t.cert; - if (!t.key.empty()) - os << ", tls.key=" << t.key; + if (!t.key.empty()) + os << ", tls.key=" << t.key; - if (!t.sni.empty()) - os << ", tls.sni=" << t.sni; - } + if (!t.sni.empty()) + os << ", tls.sni=" << t.sni; + } - return os; + return os; } #endif // REDISPP_WITH_TLS -template -OStream &operator<<(OStream &os, const ConnectionType &t) -{ - switch (t) { - case ConnectionType::TCP: - os << "tcp"; - break; +template +OStream &operator<<(OStream &os, const ConnectionType &t) { + switch (t) { + case ConnectionType::TCP: + os << "tcp"; + break; - case ConnectionType::UNIX: - os << "unix"; - break; - } + case ConnectionType::UNIX: + os << "unix"; + break; + } - return os; + return os; } -template -OStream &operator<<(OStream &os, const ConnectionOptions &o) -{ - os << "type=" << o.type; +template +OStream &operator<<(OStream &os, const ConnectionOptions &o) { + os << "type=" << o.type; - switch (o.type) { - case ConnectionType::TCP: - os << ", host=" << o.host << ", port=" << o.port; - break; + switch (o.type) { + case ConnectionType::TCP: + os << ", host=" << o.host << ", port=" << o.port; + break; - case ConnectionType::UNIX: - os << ", path=" << o.path; - break; - } + case ConnectionType::UNIX: + os << ", path=" << o.path; + break; + } - os << ", db=" << o.db - << ", user=" << o.user - << ", keepalive=" << (o.keep_alive ? "yes" : "no"); + os << ", db=" << o.db << ", user=" << o.user + << ", keepalive=" << (o.keep_alive ? "yes" : "no"); #ifdef REDISPP_WITH_TLS - os << ", " << o.tls; + os << ", " << o.tls; #endif - return os; + return os; } } // namespace redis } // namespace sw -template -OStream &operator<<(OStream &os, const enum villas::node::RedisMode &m) -{ - switch (m) { - case villas::node::RedisMode::KEY: - os << "key"; - break; +template +OStream &operator<<(OStream &os, const enum villas::node::RedisMode &m) { + switch (m) { + case villas::node::RedisMode::KEY: + os << "key"; + break; - case villas::node::RedisMode::HASH: - os << "hash"; - break; + case villas::node::RedisMode::HASH: + os << "hash"; + break; - case villas::node::RedisMode::CHANNEL: - os << "channel"; - break; - } + case villas::node::RedisMode::CHANNEL: + os << "channel"; + break; + } - return os; + return os; } namespace villas { namespace node { #ifdef REDISPP_WITH_URI - sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) - { - auto u = sw::redis::Uri { uri }; - return u.connection_options(); - } +sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { + auto u = sw::redis::Uri{uri}; + return u.connection_options(); +} #else - sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) - { - return sw::redis::ConnectionOptions { uri }; - } +sw::redis::ConnectionOptions make_redis_connection_options(char const *uri) { + return sw::redis::ConnectionOptions{uri}; +} #endif -} // node -} // villas +} // namespace node +} // namespace villas diff --git a/include/villas/nodes/rtp.hpp b/include/villas/nodes/rtp.hpp index 2ef6b736c..e5a44745a 100644 --- a/include/villas/nodes/rtp.hpp +++ b/include/villas/nodes/rtp.hpp @@ -12,17 +12,17 @@ #include +#include +#include +#include +#include #include #include -#include #include -#include -#include -#include extern "C" { - #include - #include +#include +#include } namespace villas { @@ -36,53 +36,49 @@ class SuperNode; #define RTP_INITIAL_BUFFER_LEN 1500 #define RTP_PACKET_TYPE 21 -enum class RTPHookType { - DISABLED, - DECIMATE, - LIMIT_RATE -}; +enum class RTPHookType { DISABLED, DECIMATE, LIMIT_RATE }; struct rtp { - struct rtp_sock *rs; // RTP socket + struct rtp_sock *rs; // RTP socket - struct { - struct sa saddr_rtp; // Local/Remote address of the RTP socket - struct sa saddr_rtcp; // Local/Remote address of the RTCP socket - } in, out; + struct { + struct sa saddr_rtp; // Local/Remote address of the RTP socket + struct sa saddr_rtcp; // Local/Remote address of the RTCP socket + } in, out; - Format *formatter; + Format *formatter; - struct { - int enabled; + struct { + int enabled; - int num_rrs; - } rtcp; + int num_rrs; + } rtcp; - struct { - double a; - double b; + struct { + double a; + double b; - enum RTPHookType rate_hook_type; + enum RTPHookType rate_hook_type; - LimitHook::Ptr rate_hook; - dsp::PID rate_pid; + LimitHook::Ptr rate_hook; + dsp::PID rate_pid; - // PID parameters for rate controller - double Kp, Ki, Kd; - double rate_min; + // PID parameters for rate controller + double Kp, Ki, Kd; + double rate_min; - double rate; - double rate_source; // Sample rate of source + double rate; + double rate_source; // Sample rate of source - std::ofstream *log; - char *log_filename; - } aimd; // AIMD state + std::ofstream *log; + char *log_filename; + } aimd; // AIMD state - struct CQueueSignalled recv_queue; - struct mbuf *send_mb; + struct CQueueSignalled recv_queue; + struct mbuf *send_mb; }; -char * rtp_print(NodeCompat *n); +char *rtp_print(NodeCompat *n); int rtp_parse(NodeCompat *n, json_t *json); @@ -104,9 +100,9 @@ int rtp_netem_fds(NodeCompat *n, int fds[]); int rtp_poll_fds(NodeCompat *n, int fds[]); -int rtp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int rtp_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int rtp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int rtp_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/shmem.hpp b/include/villas/nodes/shmem.hpp index 7fbf4d81e..a47f8d377 100644 --- a/include/villas/nodes/shmem.hpp +++ b/include/villas/nodes/shmem.hpp @@ -7,10 +7,10 @@ #pragma once +#include #include #include #include -#include #include namespace villas { @@ -20,14 +20,14 @@ namespace node { class NodeCompat; struct shmem { - const char* out_name; // Name of the shm object for the output queue. - const char* in_name; // Name of the shm object for the input queue. - struct ShmemConfig conf; // Interface configuration struct. - char **exec; // External program to execute on start. - struct ShmemInterface intf; // Shmem interface + const char *out_name; // Name of the shm object for the output queue. + const char *in_name; // Name of the shm object for the input queue. + struct ShmemConfig conf; // Interface configuration struct. + char **exec; // External program to execute on start. + struct ShmemInterface intf; // Shmem interface }; -char * shmem_print(NodeCompat *n); +char *shmem_print(NodeCompat *n); int shmem_parse(NodeCompat *n, json_t *json); @@ -39,9 +39,9 @@ int shmem_init(NodeCompat *n); int shmem_prepare(NodeCompat *n); -int shmem_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int shmem_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int shmem_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int shmem_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/signal.hpp b/include/villas/nodes/signal.hpp index e0a09a0e0..2a3895d34 100644 --- a/include/villas/nodes/signal.hpp +++ b/include/villas/nodes/signal.hpp @@ -7,9 +7,9 @@ #pragma once -#include -#include #include +#include +#include namespace villas { namespace node { @@ -20,86 +20,80 @@ struct Sample; class SignalNodeSignal { public: - enum class Type { - RANDOM, - SINE, - SQUARE, - TRIANGLE, - RAMP, - COUNTER, - CONSTANT, - PULSE, - MIXED - }; + enum class Type { + RANDOM, + SINE, + SQUARE, + TRIANGLE, + RAMP, + COUNTER, + CONSTANT, + PULSE, + MIXED + }; - enum Type type; + enum Type type; - double frequency; // Frequency of the generated signals. - double amplitude; // Amplitude of the generated signals. - double stddev; // Standard deviation of random signals (normal distributed). - double offset; // A constant bias. - double pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) - double pulse_low; // Amplitude when pulse signal is off - double pulse_high; // Amplitude when pulse signal is on - double phase; // Phase (rad) offset with respect to program start - double last; // The values from the previous period which are required for random walk. + double frequency; // Frequency of the generated signals. + double amplitude; // Amplitude of the generated signals. + double stddev; // Standard deviation of random signals (normal distributed). + double offset; // A constant bias. + double + pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) + double pulse_low; // Amplitude when pulse signal is off + double pulse_high; // Amplitude when pulse signal is on + double phase; // Phase (rad) offset with respect to program start + double + last; // The values from the previous period which are required for random walk. public: - SignalNodeSignal(json_t *json); + SignalNodeSignal(json_t *json); - int parse(json_t *json); + int parse(json_t *json); - static - enum Type lookupType(const std::string &type); + static enum Type lookupType(const std::string &type); - static - std::string typeToString(enum Type type); + static std::string typeToString(enum Type type); - void start(); + void start(); - void read(unsigned c, double t, double rate, SignalData *d); + void read(unsigned c, double t, double rate, SignalData *d); - Signal::Ptr toSignal(Signal::Ptr tpl) const; + Signal::Ptr toSignal(Signal::Ptr tpl) const; }; class SignalNode : public Node { protected: - std::vector signals; + std::vector signals; - struct Task task; // Timer for periodic events. - int rt; // Real-time mode? + struct Task task; // Timer for periodic events. + int rt; // Real-time mode? - double rate; // Sampling rate. - bool monitor_missed; // Boolean, if set, node counts missed steps and warns user. - int limit; // The number of values which should be generated by this node. <0 for infinite. + double rate; // Sampling rate. + bool + monitor_missed; // Boolean, if set, node counts missed steps and warns user. + int limit; // The number of values which should be generated by this node. <0 for infinite. - struct timespec started; // Point in time when this node was started. - unsigned missed_steps; // Total number of missed steps. + struct timespec started; // Point in time when this node was started. + unsigned missed_steps; // Total number of missed steps. - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); public: - SignalNode(const uuid_t &id = {}, const std::string &name = ""); + SignalNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - int start(); + virtual int start(); - virtual - int stop(); + virtual int stop(); - virtual - int prepare(); + virtual int prepare(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); }; } // namespace node diff --git a/include/villas/nodes/signal_old.hpp b/include/villas/nodes/signal_old.hpp index 9617d4a1a..e63556ccc 100644 --- a/include/villas/nodes/signal_old.hpp +++ b/include/villas/nodes/signal_old.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include namespace villas { namespace node { @@ -18,43 +18,46 @@ class NodeCompat; struct Sample; struct signal_node { - struct Task task; // Timer for periodic events. - int rt; // Real-time mode? + struct Task task; // Timer for periodic events. + int rt; // Real-time mode? - enum class SignalType { - RANDOM, - SINE, - SQUARE, - TRIANGLE, - RAMP, - COUNTER, - CONSTANT, - MIXED, - PULSE - } *type; // Signal type + enum class SignalType { + RANDOM, + SINE, + SQUARE, + TRIANGLE, + RAMP, + COUNTER, + CONSTANT, + MIXED, + PULSE + } * + type; // Signal type - double rate; // Sampling rate. - double *frequency; // Frequency of the generated signals. - double *amplitude; // Amplitude of the generated signals. - double *stddev; // Standard deviation of random signals (normal distributed). - double *offset; // A constant bias. - double *pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) - double *pulse_low; // Amplitude when pulse signal is off - double *pulse_high; // Amplitude when pulse signal is on - double *phase; // Phase (rad) offset with respect to program start - int monitor_missed; // Boolean, if set, node counts missed steps and warns user. + double rate; // Sampling rate. + double *frequency; // Frequency of the generated signals. + double *amplitude; // Amplitude of the generated signals. + double *stddev; // Standard deviation of random signals (normal distributed). + double *offset; // A constant bias. + double * + pulse_width; // Width of a pulse with respect to the rate (duration = pulse_width/rate) + double *pulse_low; // Amplitude when pulse signal is off + double *pulse_high; // Amplitude when pulse signal is on + double *phase; // Phase (rad) offset with respect to program start + int monitor_missed; // Boolean, if set, node counts missed steps and warns user. - double *last; // The values from the previous period which are required for random walk. + double * + last; // The values from the previous period which are required for random walk. - unsigned values; // The number of values which will be emitted by this node. - int limit; // The number of values which should be generated by this node. <0 for infinitve. + unsigned values; // The number of values which will be emitted by this node. + int limit; // The number of values which should be generated by this node. <0 for infinitve. - struct timespec started; // Point in time when this node was started. - unsigned counter; // The number of packets already emitted. - unsigned missed_steps; // Total number of missed steps. + struct timespec started; // Point in time when this node was started. + unsigned counter; // The number of packets already emitted. + unsigned missed_steps; // Total number of missed steps. }; -char * signal_node_print(NodeCompat *n); +char *signal_node_print(NodeCompat *n); int signal_node_parse(NodeCompat *n, json_t *json); @@ -68,7 +71,7 @@ int signal_node_destroy(NodeCompat *n); int signal_node_prepare(NodeCompat *n); -int signal_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int signal_node_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int signal_node_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/socket.hpp b/include/villas/nodes/socket.hpp index cd14d1f51..8882a607d 100644 --- a/include/villas/nodes/socket.hpp +++ b/include/villas/nodes/socket.hpp @@ -7,9 +7,9 @@ #pragma once +#include #include #include -#include namespace villas { namespace node { @@ -18,29 +18,30 @@ namespace node { class NodeCompat; // The maximum length of a packet which contains stuct msg. -#define SOCKET_INITIAL_BUFFER_LEN (64*1024) +#define SOCKET_INITIAL_BUFFER_LEN (64 * 1024) struct Socket { - int sd; // The socket descriptor - int verify_source; // Verify the source address of incoming packets against socket::remote. + int sd; // The socket descriptor + int verify_source; // Verify the source address of incoming packets against socket::remote. - enum SocketLayer layer; // The OSI / IP layer which should be used for this socket + enum SocketLayer + layer; // The OSI / IP layer which should be used for this socket - Format *formatter; + Format *formatter; - // Multicast options - struct multicast { - int enabled; // Is multicast enabled? - unsigned char loop; // Loopback multicast packets to local host? - unsigned char ttl; // The time to live for multicast packets. - struct ip_mreq mreq; // A multicast group to join. - } multicast; + // Multicast options + struct multicast { + int enabled; // Is multicast enabled? + unsigned char loop; // Loopback multicast packets to local host? + unsigned char ttl; // The time to live for multicast packets. + struct ip_mreq mreq; // A multicast group to join. + } multicast; - struct { - char *buf; // Buffer for receiving messages - size_t buflen; - union sockaddr_union saddr; // Remote address of the socket - } in, out; + struct { + char *buf; // Buffer for receiving messages + size_t buflen; + union sockaddr_union saddr; // Remote address of the socket + } in, out; }; int socket_type_start(SuperNode *sn); @@ -61,13 +62,13 @@ int socket_reverse(NodeCompat *n); int socket_fds(NodeCompat *n, int fds[]); -int socket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int socket_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int socket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int socket_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int socket_parse(NodeCompat *n, json_t *json); -char * socket_print(NodeCompat *n); +char *socket_print(NodeCompat *n); } // namespace node } // namespace villas diff --git a/include/villas/nodes/stats.hpp b/include/villas/nodes/stats.hpp index f25dac4b5..9b622a4e1 100644 --- a/include/villas/nodes/stats.hpp +++ b/include/villas/nodes/stats.hpp @@ -9,9 +9,9 @@ #include +#include #include #include -#include namespace villas { namespace node { @@ -20,19 +20,19 @@ namespace node { class NodeCompat; struct stats_node_signal { - Node *node; - char *node_str; + Node *node; + char *node_str; - enum villas::Stats::Metric metric; - enum villas::Stats::Type type; + enum villas::Stats::Metric metric; + enum villas::Stats::Type type; }; struct stats_node { - double rate; + double rate; - struct Task task; + struct Task task; - struct List signals; // List of type struct stats_node_signal + struct List signals; // List of type struct stats_node_signal }; int stats_node_type_start(SuperNode *sn); @@ -51,7 +51,7 @@ int stats_node_start(NodeCompat *n); int stats_node_stop(NodeCompat *n); -int stats_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int stats_node_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int stats_node_parse_signal(struct stats_node_signal *s, json_t *json); diff --git a/include/villas/nodes/temper.hpp b/include/villas/nodes/temper.hpp index 4bbecd157..e48533d42 100644 --- a/include/villas/nodes/temper.hpp +++ b/include/villas/nodes/temper.hpp @@ -7,11 +7,11 @@ #pragma once -#include #include +#include +#include #include #include -#include namespace villas { namespace node { @@ -22,123 +22,86 @@ class NodeCompat; class TEMPerDevice : public villas::usb::Device { protected: - constexpr static - unsigned char question_temperature[] = { 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 }; + constexpr static unsigned char question_temperature[] = { + 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00}; - float scale; - float offset; + float scale; + float offset; - int timeout; + int timeout; - villas::Logger logger; + villas::Logger logger; + + virtual void decode(unsigned char *answer, float *temp) = 0; - virtual - void decode(unsigned char *answer, float *temp) = 0; public: - static - TEMPerDevice * make(struct libusb_device *desc); + static TEMPerDevice *make(struct libusb_device *desc); - TEMPerDevice(struct libusb_device *dev); - virtual - ~TEMPerDevice() - { } + TEMPerDevice(struct libusb_device *dev); + virtual ~TEMPerDevice() {} - void open(bool reset = true); - void close(); + void open(bool reset = true); + void close(); - virtual - int getNumSensors() const - { - return 1; - } + virtual int getNumSensors() const { return 1; } - virtual - bool hasHumiditySensor() const - { - return false; - } + virtual bool hasHumiditySensor() const { return false; } - void read(struct Sample *smp); + void read(struct Sample *smp); }; class TEMPer1Device : public TEMPerDevice { protected: - virtual - void decode(unsigned char *answer, float *temp); + virtual void decode(unsigned char *answer, float *temp); - using TEMPerDevice::TEMPerDevice; + using TEMPerDevice::TEMPerDevice; public: - static - bool match(struct libusb_device *dev); + static bool match(struct libusb_device *dev); - static - std::string getName() - { - return "TEMPer1"; - } + static std::string getName() { return "TEMPer1"; } }; class TEMPer2Device : public TEMPer1Device { protected: - virtual - void decode(unsigned char *answer, float *temp); + virtual void decode(unsigned char *answer, float *temp); - using TEMPer1Device::TEMPer1Device; + using TEMPer1Device::TEMPer1Device; public: - static - bool match(struct libusb_device *dev); + static bool match(struct libusb_device *dev); - static - std::string getName() - { - return "TEMPer2"; - } + static std::string getName() { return "TEMPer2"; } - virtual - int getNumSensors() const - { - return 2; - } + virtual int getNumSensors() const { return 2; } }; class TEMPerHUMDevice : public TEMPerDevice { protected: - virtual - void decode(unsigned char *answer, float *temp); + virtual void decode(unsigned char *answer, float *temp); - using TEMPerDevice::TEMPerDevice; + using TEMPerDevice::TEMPerDevice; public: - static - bool match(struct libusb_device *dev); + static bool match(struct libusb_device *dev); - static - std::string getName() - { - return "TEMPerHUM"; - } + static std::string getName() { return "TEMPerHUM"; } - virtual - bool hasHumiditySensor() const - { - return true; - } + virtual bool hasHumiditySensor() const { return true; } }; struct temper { - struct { - double scale; - double offset; - } calibration; + struct { + double scale; + double offset; + } calibration; - struct villas::usb::Filter filter; + struct villas::usb::Filter filter; - TEMPerDevice *device; + TEMPerDevice *device; }; int temper_type_start(SuperNode *sn); @@ -153,7 +116,7 @@ int temper_destroy(NodeCompat *n); int temper_parse(NodeCompat *n, json_t *json); -char * temper_print(NodeCompat *n); +char *temper_print(NodeCompat *n); int temper_check(); @@ -167,9 +130,9 @@ int temper_pause(NodeCompat *n); int temper_resume(NodeCompat *n); -int temper_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int temper_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int temper_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int temper_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int temper_reverse(NodeCompat *n); diff --git a/include/villas/nodes/test_rtt.hpp b/include/villas/nodes/test_rtt.hpp index 1d04ef4a5..56c78058f 100644 --- a/include/villas/nodes/test_rtt.hpp +++ b/include/villas/nodes/test_rtt.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include namespace villas { @@ -21,33 +21,33 @@ struct Sample; struct test_rtt; struct test_rtt_case { - double rate; - unsigned values; - unsigned limit; // The number of samples we take per test. + double rate; + unsigned values; + unsigned limit; // The number of samples we take per test. - char *filename; - char *filename_formatted; + char *filename; + char *filename_formatted; - NodeCompat *node; + NodeCompat *node; }; struct test_rtt { - struct Task task; // The periodic task for test_rtt_read() - Format *formatter;// The format of the output file - FILE *stream; + struct Task task; // The periodic task for test_rtt_read() + Format *formatter; // The format of the output file + FILE *stream; - double cooldown; // Number of seconds to wait beween tests. + double cooldown; // Number of seconds to wait beween tests. - int current; // Index of current test in test_rtt::cases - int counter; + int current; // Index of current test in test_rtt::cases + int counter; - struct List cases; // List of test cases + struct List cases; // List of test cases - char *output; // The directory where we place the results. - char *prefix; // An optional prefix in the filename. + char *output; // The directory where we place the results. + char *prefix; // An optional prefix in the filename. }; -char * test_rtt_print(NodeCompat *n); +char *test_rtt_print(NodeCompat *n); int test_rtt_parse(NodeCompat *n, json_t *json); @@ -61,9 +61,9 @@ int test_rtt_start(NodeCompat *n); int test_rtt_stop(NodeCompat *n); -int test_rtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int test_rtt_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int test_rtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int test_rtt_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); int test_rtt_poll_fds(NodeCompat *n, int fds[]); diff --git a/include/villas/nodes/uldaq.hpp b/include/villas/nodes/uldaq.hpp index 0a13c00fc..628ae7fc6 100644 --- a/include/villas/nodes/uldaq.hpp +++ b/include/villas/nodes/uldaq.hpp @@ -10,8 +10,8 @@ #include -#include #include +#include #include @@ -22,34 +22,34 @@ namespace villas { namespace node { struct uldaq { - const char *device_id; + const char *device_id; - DaqDeviceHandle device_handle; - DaqDeviceDescriptor *device_descriptor; - DaqDeviceInterface device_interface_type; + DaqDeviceHandle device_handle; + DaqDeviceDescriptor *device_descriptor; + DaqDeviceInterface device_interface_type; - uint64_t sequence; + uint64_t sequence; - struct { - double sample_rate; - double *buffer; - size_t buffer_len; - size_t buffer_pos; - size_t channel_count; + struct { + double sample_rate; + double *buffer; + size_t buffer_len; + size_t buffer_pos; + size_t channel_count; - ScanOption scan_options; - AInScanFlag flags; - AiQueueElement *queues; - ScanStatus status; // protected by mutex - TransferStatus transfer_status; // protected by mutex + ScanOption scan_options; + AInScanFlag flags; + AiQueueElement *queues; + ScanStatus status; // protected by mutex + TransferStatus transfer_status; // protected by mutex - pthread_mutex_t mutex; - pthread_cond_t cv; - } in; + pthread_mutex_t mutex; + pthread_cond_t cv; + } in; - struct { - // TODO - } out; + struct { + // TODO + } out; }; int uldaq_type_start(SuperNode *sn); @@ -60,7 +60,7 @@ int uldaq_destroy(NodeCompat *n); int uldaq_parse(NodeCompat *n, json_t *json); -char * uldaq_print(NodeCompat *n); +char *uldaq_print(NodeCompat *n); int uldaq_check(NodeCompat *n); @@ -68,7 +68,7 @@ int uldaq_start(NodeCompat *n); int uldaq_stop(NodeCompat *n); -int uldaq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int uldaq_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/webrtc.hpp b/include/villas/nodes/webrtc.hpp index c0f327c33..3238738ff 100644 --- a/include/villas/nodes/webrtc.hpp +++ b/include/villas/nodes/webrtc.hpp @@ -11,12 +11,12 @@ #include -#include -#include -#include -#include #include +#include +#include +#include #include +#include namespace villas { namespace node { @@ -27,91 +27,70 @@ struct Sample; class WebRTCNode : public Node { protected: - std::string server; - std::string session; - std::string peer; + std::string server; + std::string session; + std::string peer; - int wait_seconds; - Format *format; - struct CQueueSignalled queue; - struct Pool pool; + int wait_seconds; + Format *format; + struct CQueueSignalled queue; + struct Pool pool; - std::shared_ptr conn; - rtc::Configuration rtcConf; - rtc::DataChannelInit dci; + std::shared_ptr conn; + rtc::Configuration rtcConf; + rtc::DataChannelInit dci; - virtual - int _read(struct Sample *smps[], unsigned cnt); + virtual int _read(struct Sample *smps[], unsigned cnt); - virtual - int _write(struct Sample *smps[], unsigned cnt); + virtual int _write(struct Sample *smps[], unsigned cnt); - virtual - json_t * _readStatus() const; + virtual json_t *_readStatus() const; public: - WebRTCNode(const uuid_t &id = {}, const std::string &name = ""); + WebRTCNode(const uuid_t &id = {}, const std::string &name = ""); - virtual - ~WebRTCNode(); + virtual ~WebRTCNode(); - virtual - int prepare(); + virtual int prepare(); - virtual - int parse(json_t *json); + virtual int parse(json_t *json); - virtual - int start(); + virtual int start(); - virtual - int stop(); + virtual int stop(); - virtual - std::vector getPollFDs(); + virtual std::vector getPollFDs(); - virtual - const std::string & getDetails(); + virtual const std::string &getDetails(); }; class WebRTCNodeFactory : public NodeFactory { public: - using NodeFactory::NodeFactory; + using NodeFactory::NodeFactory; - virtual - Node * make(const uuid_t &id = {}, const std::string &nme = "") - { - auto *n = new WebRTCNode(id, nme); + virtual Node *make(const uuid_t &id = {}, const std::string &nme = "") { + auto *n = new WebRTCNode(id, nme); - init(n); + init(n); - return n; - } + return n; + } - virtual - int getFlags() const - { - return (int) NodeFactory::Flags::SUPPORTS_READ | - (int) NodeFactory::Flags::SUPPORTS_WRITE | - (int) NodeFactory::Flags::SUPPORTS_POLL | - (int) NodeFactory::Flags::REQUIRES_WEB; - } + virtual int getFlags() const { + return (int)NodeFactory::Flags::SUPPORTS_READ | + (int)NodeFactory::Flags::SUPPORTS_WRITE | + (int)NodeFactory::Flags::SUPPORTS_POLL | + (int)NodeFactory::Flags::REQUIRES_WEB; + } - virtual - std::string getName() const - { - return "webrtc"; - } + virtual std::string getName() const { return "webrtc"; } - virtual - std::string getDescription() const - { - return "Web Real-time Communication"; - } + virtual std::string getDescription() const { + return "Web Real-time Communication"; + } - virtual - int start(SuperNode *sn); + virtual int start(SuperNode *sn); }; } // namespace node diff --git a/include/villas/nodes/webrtc/peer_connection.hpp b/include/villas/nodes/webrtc/peer_connection.hpp index cb122bf30..26fb62d74 100644 --- a/include/villas/nodes/webrtc/peer_connection.hpp +++ b/include/villas/nodes/webrtc/peer_connection.hpp @@ -13,9 +13,9 @@ #include #include -#include -#include #include +#include +#include namespace villas { namespace node { @@ -24,69 +24,72 @@ namespace webrtc { class PeerConnection { public: - PeerConnection(const std::string &server, const std::string &session, const std::string &peer, std::shared_ptr signals, rtc::Configuration config, Web *w, rtc::DataChannelInit d); - ~PeerConnection(); + PeerConnection(const std::string &server, const std::string &session, + const std::string &peer, std::shared_ptr signals, + rtc::Configuration config, Web *w, rtc::DataChannelInit d); + ~PeerConnection(); - bool waitForDataChannel(std::chrono::seconds timeout); - void onMessage(std::function callback); - void sendMessage(rtc::binary msg); + bool waitForDataChannel(std::chrono::seconds timeout); + void onMessage(std::function callback); + void sendMessage(rtc::binary msg); - json_t * readStatus() const; + json_t *readStatus() const; - void connect(); - void disconnect(); + void connect(); + void disconnect(); protected: - Web *web; - std::vector extraServers; - rtc::DataChannelInit dataChannelInit; - rtc::Configuration defaultConfig; + Web *web; + std::vector extraServers; + rtc::DataChannelInit dataChannelInit; + rtc::Configuration defaultConfig; - std::shared_ptr conn; - std::shared_ptr chan; - std::shared_ptr client; - std::shared_ptr signals; + std::shared_ptr conn; + std::shared_ptr chan; + std::shared_ptr client; + std::shared_ptr signals; - Logger logger; + Logger logger; - std::mutex mutex; + std::mutex mutex; - std::condition_variable_any startupCondition; - bool stopStartup; + std::condition_variable_any startupCondition; + bool stopStartup; - bool warnNotConnected; - bool standby; - bool first; - int firstID; - int secondID; + bool warnNotConnected; + bool standby; + bool first; + int firstID; + int secondID; - std::function onMessageCallback; + std::function onMessageCallback; - void resetConnection(std::unique_lock &lock); - void resetConnectionAndStandby(std::unique_lock &lock); - void notifyStartup(); + void resetConnection(std::unique_lock &lock); + void resetConnectionAndStandby( + std::unique_lock &lock); + void notifyStartup(); - void setupPeerConnection(std::shared_ptr = nullptr); - void setupDataChannel(std::shared_ptr = nullptr); + void setupPeerConnection(std::shared_ptr = nullptr); + void setupDataChannel(std::shared_ptr = nullptr); - void onLocalDescription(rtc::Description sdp); - void onLocalCandidate(rtc::Candidate cand); + void onLocalDescription(rtc::Description sdp); + void onLocalCandidate(rtc::Candidate cand); - void onConnectionStateChange(rtc::PeerConnection::State state); - void onSignalingStateChange(rtc::PeerConnection::SignalingState state); - void onGatheringStateChange(rtc::PeerConnection::GatheringState state); + void onConnectionStateChange(rtc::PeerConnection::State state); + void onSignalingStateChange(rtc::PeerConnection::SignalingState state); + void onGatheringStateChange(rtc::PeerConnection::GatheringState state); - void onSignalingConnected(); - void onSignalingDisconnected(); - void onSignalingError(std::string err); - void onSignalingMessage(SignalingMessage msg); + void onSignalingConnected(); + void onSignalingDisconnected(); + void onSignalingError(std::string err); + void onSignalingMessage(SignalingMessage msg); - void onDataChannel(std::shared_ptr dc); - void onDataChannelOpen(); - void onDataChannelClosed(); - void onDataChannelError(std::string err); - void onDataChannelMessage(rtc::string msg); - void onDataChannelMessage(rtc::binary msg); + void onDataChannel(std::shared_ptr dc); + void onDataChannelOpen(); + void onDataChannelClosed(); + void onDataChannelError(std::string err); + void onDataChannelMessage(rtc::string msg); + void onDataChannelMessage(rtc::binary msg); }; } // namespace webrtc diff --git a/include/villas/nodes/webrtc/signaling_client.hpp b/include/villas/nodes/webrtc/signaling_client.hpp index 5d6a63e9d..edfa8853b 100644 --- a/include/villas/nodes/webrtc/signaling_client.hpp +++ b/include/villas/nodes/webrtc/signaling_client.hpp @@ -9,16 +9,16 @@ #pragma once -#include #include +#include #include -#include #include -#include #include #include +#include +#include namespace villas { namespace node { @@ -31,87 +31,82 @@ namespace webrtc { class SignalingClient { protected: - struct sul_offsetof_helper { - lws_sorted_usec_list_t sul; // Schedule connection retry - SignalingClient *self; - } sul_helper; + struct sul_offsetof_helper { + lws_sorted_usec_list_t sul; // Schedule connection retry + SignalingClient *self; + } sul_helper; - uint16_t retry_count; // Count of consecutive retries + uint16_t retry_count; // Count of consecutive retries - struct lws *wsi; - struct lws_client_connect_info info; + struct lws *wsi; + struct lws_client_connect_info info; - // The retry and backoff policy we want to use for our client connections - static constexpr - uint32_t backoff_ms[] = { 1<<4, 1<<6, 1<<8, 1<<10, 1<<12, 1<<14, 1<<16 }; - static constexpr - lws_retry_bo_t retry = { - .retry_ms_table = backoff_ms, - .retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms), - .conceal_count = LWS_ARRAY_SIZE(backoff_ms) + 1, + // The retry and backoff policy we want to use for our client connections + static constexpr uint32_t backoff_ms[] = {1 << 4, 1 << 6, 1 << 8, 1 << 10, + 1 << 12, 1 << 14, 1 << 16}; + static constexpr lws_retry_bo_t retry = { + .retry_ms_table = backoff_ms, + .retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms), + .conceal_count = LWS_ARRAY_SIZE(backoff_ms) + 1, - .secs_since_valid_ping = 3, // force PINGs after secs idle - .secs_since_valid_hangup = 10, // hangup after secs idle + .secs_since_valid_ping = 3, // force PINGs after secs idle + .secs_since_valid_hangup = 10, // hangup after secs idle - .jitter_percent = 20, - }; + .jitter_percent = 20, + }; - std::function cbMessage; - std::function cbConnected; - std::function cbDisconnected; - std::function cbError; + std::function cbMessage; + std::function cbConnected; + std::function cbDisconnected; + std::function cbError; - Queue outgoingMessages; + Queue outgoingMessages; - Web *web; + Web *web; - char *uri; - char *path; + char *uri; + char *path; - std::atomic running; + std::atomic running; - Buffer buffer; // A buffer for received fragments before JSON decoding. + Buffer buffer; // A buffer for received fragments before JSON decoding. - Logger logger; + Logger logger; - int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *in, size_t len); + int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, + void *in, size_t len); - static - void connectStatic(struct lws_sorted_usec_list *sul); + static void connectStatic(struct lws_sorted_usec_list *sul); - int writable(); + int writable(); public: - SignalingClient(const std::string &server, const std::string &session, const std::string &peer, Web *w); - ~SignalingClient(); + SignalingClient(const std::string &server, const std::string &session, + const std::string &peer, Web *w); + ~SignalingClient(); - static - int protocolCallbackStatic(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int protocolCallbackStatic(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len); - void connect(); - void disconnect(); + void connect(); + void disconnect(); - void sendMessage(SignalingMessage); + void sendMessage(SignalingMessage); - void onMessage(std::function callback) - { - cbMessage = callback; - } + void onMessage(std::function callback) { + cbMessage = callback; + } - void onConnected(std::function callback) - { - cbConnected = callback; - } + void onConnected(std::function callback) { cbConnected = callback; } - void onDisconnected(std::function callback) - { - cbDisconnected = callback; - } + void onDisconnected(std::function callback) { + cbDisconnected = callback; + } - void onError(std::function callback) - { - cbError = callback; - } + void onError(std::function callback) { + cbError = callback; + } }; } // namespace webrtc diff --git a/include/villas/nodes/webrtc/signaling_message.hpp b/include/villas/nodes/webrtc/signaling_message.hpp index 2a9039693..62ba4a63f 100644 --- a/include/villas/nodes/webrtc/signaling_message.hpp +++ b/include/villas/nodes/webrtc/signaling_message.hpp @@ -9,13 +9,13 @@ #pragma once -#include #include -#include +#include #include +#include -#include #include +#include #include @@ -24,37 +24,38 @@ namespace node { namespace webrtc { struct Peer { - int id; - std::string name; - std::string remote; - std::string userAgent; - std::chrono::time_point created; + int id; + std::string name; + std::string remote; + std::string userAgent; + std::chrono::time_point created; - Peer(json_t *j); - json_t * toJson() const; + Peer(json_t *j); + json_t *toJson() const; }; struct RelayMessage { - std::vector servers; + std::vector servers; - RelayMessage(json_t *j); + RelayMessage(json_t *j); }; struct ControlMessage { - int peerID; - std::vector peers; + int peerID; + std::vector peers; - ControlMessage(json_t *j); - json_t * toJson() const; + ControlMessage(json_t *j); + json_t *toJson() const; }; struct SignalingMessage { - std::variant message; + std::variant + message; - static - SignalingMessage fromJson(json_t *j); - json_t * toJson() const; - std::string toString() const; + static SignalingMessage fromJson(json_t *j); + json_t *toJson() const; + std::string toString() const; }; } // namespace webrtc diff --git a/include/villas/nodes/websocket.hpp b/include/villas/nodes/websocket.hpp index c8f72ef99..071fe1af0 100644 --- a/include/villas/nodes/websocket.hpp +++ b/include/villas/nodes/websocket.hpp @@ -9,14 +9,14 @@ #include -#include -#include -#include #include +#include #include #include #include #include +#include +#include // Forward declarations struct lws; @@ -24,84 +24,89 @@ struct lws; namespace villas { namespace node { -#define DEFAULT_WEBSOCKET_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) +#define DEFAULT_WEBSOCKET_QUEUE_LENGTH (DEFAULT_QUEUE_LENGTH * 64) // Internal data per websocket node struct websocket { - struct List destinations; // List of websocket servers connect to in client mode (struct websocket_destination). + struct List + destinations; // List of websocket servers connect to in client mode (struct websocket_destination). - bool wait; // Wait until all destinations are connected. + bool wait; // Wait until all destinations are connected. - struct Pool pool; - struct CQueueSignalled queue; // For samples which are received from WebSockets + struct Pool pool; + struct CQueueSignalled + queue; // For samples which are received from WebSockets }; struct websocket_destination { - char *uri; - struct lws_client_connect_info info; + char *uri; + struct lws_client_connect_info info; }; // Internal datastructures struct websocket_connection { - enum State { - DESTROYED, - INITIALIZED, - CONNECTING, - RECONNECTING, - ESTABLISHED, - CLOSING, - CLOSED, - ERROR - } state; // The current status of this connection. + enum State { + DESTROYED, + INITIALIZED, + CONNECTING, + RECONNECTING, + ESTABLISHED, + CLOSING, + CLOSED, + ERROR + } state; // The current status of this connection. - enum class Mode { - CLIENT, - SERVER, - } mode; + enum class Mode { + CLIENT, + SERVER, + } mode; - struct lws *wsi; - NodeCompat *node; - Format *formatter; - struct CQueue queue; // For samples which are sent to the Websocket + struct lws *wsi; + NodeCompat *node; + Format *formatter; + struct CQueue queue; // For samples which are sent to the Websocket - struct websocket_destination *destination; + struct websocket_destination *destination; - struct { - villas::Buffer *recv; // A buffer for reconstructing fragmented messages. - villas::Buffer *send; // A buffer for constructing messages before calling lws_write() - } buffers; + struct { + villas::Buffer *recv; // A buffer for reconstructing fragmented messages. + villas::Buffer + *send; // A buffer for constructing messages before calling lws_write() + } buffers; - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const struct websocket_connection &c) - { - if (c.wsi) { - char name[128]; + // Custom formatter for spdlog + template + friend OStream &operator<<(OStream &os, + const struct websocket_connection &c) { + if (c.wsi) { + char name[128]; - lws_get_peer_simple(c.wsi, name, sizeof(name)); + lws_get_peer_simple(c.wsi, name, sizeof(name)); - os << "remote=" << name; - } - else if (c.mode == websocket_connection::Mode::CLIENT && c.destination != nullptr) - os << "dest=" << c.destination->info.address << ":" << c.destination->info.port; + os << "remote=" << name; + } else if (c.mode == websocket_connection::Mode::CLIENT && + c.destination != nullptr) + os << "dest=" << c.destination->info.address << ":" + << c.destination->info.port; - if (c.node) - os << ", node=" << c.node->getName(); + if (c.node) + os << ", node=" << c.node->getName(); - os << ", mode=" << (c.mode == websocket_connection::Mode::CLIENT ? "client" : "server"); + os << ", mode=" + << (c.mode == websocket_connection::Mode::CLIENT ? "client" : "server"); - return os; - } + return os; + } - std::string toString() - { - std::stringstream ss; - ss << *this; - return ss.str(); - } + std::string toString() { + std::stringstream ss; + ss << *this; + return ss.str(); + } }; -int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); +int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); int websocket_type_start(SuperNode *sn); @@ -109,7 +114,7 @@ int websocket_type_stop(); int websocket_parse(NodeCompat *n, json_t *j); -char * websocket_print(NodeCompat *n); +char *websocket_print(NodeCompat *n); int websocket_start(NodeCompat *n); @@ -121,9 +126,9 @@ int websocket_destroy(NodeCompat *n); int websocket_poll_fds(NodeCompat *n, int fds[]); -int websocket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int websocket_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int websocket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int websocket_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/nodes/zeromq.hpp b/include/villas/nodes/zeromq.hpp index 60d7d985a..1478ae727 100644 --- a/include/villas/nodes/zeromq.hpp +++ b/include/villas/nodes/zeromq.hpp @@ -10,12 +10,14 @@ #include #include -#include -#include #include +#include +#include -#if ZMQ_BUILD_DRAFT_API && (ZMQ_VERSION_MAJOR > 4 || (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR >= 2)) - #define ZMQ_BUILD_DISH 1 +#if ZMQ_BUILD_DRAFT_API && \ + (ZMQ_VERSION_MAJOR > 4 || \ + (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR >= 2)) +#define ZMQ_BUILD_DISH 1 #endif namespace villas { @@ -26,35 +28,35 @@ class NodeCompat; struct Sample; struct zeromq { - int ipv6; + int ipv6; - Format *formatter; + Format *formatter; - struct Curve { - int enabled; - struct { - char public_key[41]; - char secret_key[41]; - } server, client; - } curve; + struct Curve { + int enabled; + struct { + char public_key[41]; + char secret_key[41]; + } server, client; + } curve; - enum class Pattern { - PUBSUB, + enum class Pattern { + PUBSUB, #ifdef ZMQ_BUILD_DISH - RADIODISH + RADIODISH #endif - } pattern; + } pattern; - struct Dir { - void *socket; // ZeroMQ socket. - void *mon_socket; - struct List endpoints; - char *filter; - int bind, pending; - } in, out; + struct Dir { + void *socket; // ZeroMQ socket. + void *mon_socket; + struct List endpoints; + char *filter; + int bind, pending; + } in, out; }; -char * zeromq_print(NodeCompat *n); +char *zeromq_print(NodeCompat *n); int zeromq_parse(NodeCompat *n, json_t *json); @@ -78,9 +80,9 @@ int zeromq_poll_fds(NodeCompat *n, int fds[]); int zeromq_netem_fds(NodeCompat *n, int fds[]); -int zeromq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int zeromq_read(NodeCompat *n, struct Sample *const smps[], unsigned cnt); -int zeromq_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); +int zeromq_write(NodeCompat *n, struct Sample *const smps[], unsigned cnt); } // namespace node } // namespace villas diff --git a/include/villas/path.hpp b/include/villas/path.hpp index 2aaa3c88d..90e06b499 100644 --- a/include/villas/path.hpp +++ b/include/villas/path.hpp @@ -9,23 +9,23 @@ #include -#include -#include #include +#include #include +#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include +#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include #include @@ -40,125 +40,123 @@ class Node; // The datastructure for a path. class Path { - friend PathSource; - friend SecondaryPathSource; - friend PathDestination; + friend PathSource; + friend SecondaryPathSource; + friend PathDestination; protected: - void * runSingle(); - void * runPoll(); + void *runSingle(); + void *runPoll(); - static - void * runWrapper(void *arg); + static void *runWrapper(void *arg); - void startPoll(); + void startPoll(); - static - int id; + static int id; public: - enum State state; // Path state. + enum State state; // Path state. - // The register mode determines under which condition the path is triggered. - enum class Mode { - ANY, // The path is triggered whenever one of the sources receives samples. - ALL // The path is triggered only after all sources have received at least 1 sample. - } mode; // Determines when this path is triggered. + // The register mode determines under which condition the path is triggered. + enum class Mode { + ANY, // The path is triggered whenever one of the sources receives samples. + ALL // The path is triggered only after all sources have received at least 1 sample. + } mode; // Determines when this path is triggered. - uuid_t uuid; + uuid_t uuid; - std::vector pfds; + std::vector pfds; - struct Pool pool; - struct Sample *last_sample; - int last_sequence; + struct Pool pool; + struct Sample *last_sample; + int last_sequence; - NodeList masked; - MappingList mappings; // List of all input mappings. - PathSourceList sources; // List of all incoming nodes. - PathDestinationList destinations; // List of all outgoing nodes. - HookList hooks; // List of processing hooks. - SignalList::Ptr signals; // List of signals which this path creates. + NodeList masked; + MappingList mappings; // List of all input mappings. + PathSourceList sources; // List of all incoming nodes. + PathDestinationList destinations; // List of all outgoing nodes. + HookList hooks; // List of processing hooks. + SignalList::Ptr signals; // List of signals which this path creates. - struct Task timeout; + struct Task timeout; - double rate; // A timeout for - int affinity; // Thread affinity. - bool enabled; // Is this path enabled? - int poll; // Weather or not to use poll(2). - bool reversed; // This path has a matching reverse path. - bool builtin; // This path should use built-in hooks by default. - int original_sequence_no; // Use original source sequence number when multiplexing - unsigned queuelen; // The queue length for each path_destination::queue + double rate; // A timeout for + int affinity; // Thread affinity. + bool enabled; // Is this path enabled? + int poll; // Weather or not to use poll(2). + bool reversed; // This path has a matching reverse path. + bool builtin; // This path should use built-in hooks by default. + int original_sequence_no; // Use original source sequence number when multiplexing + unsigned queuelen; // The queue length for each path_destination::queue - pthread_t tid; // The thread id for this path. - json_t *config; // A JSON object containing the configuration of the path. + pthread_t tid; // The thread id for this path. + json_t *config; // A JSON object containing the configuration of the path. - Logger logger; + Logger logger; - std::bitset mask; // A mask of PathSources which are enabled for poll(). - std::bitset received; // A mask of PathSources for which we already received samples. + std::bitset + mask; // A mask of PathSources which are enabled for poll(). + std::bitset + received; // A mask of PathSources for which we already received samples. - // Custom formatter for spdlog - template - friend OStream &operator<<(OStream &os, const Path &p) - { - if (p.sources.size() > 1) - os << "[ "; + // Custom formatter for spdlog + template + friend OStream &operator<<(OStream &os, const Path &p) { + if (p.sources.size() > 1) + os << "[ "; - for (auto ps : p.sources) - os << ps->getNode()->getNameShort() << " "; + for (auto ps : p.sources) + os << ps->getNode()->getNameShort() << " "; - if (p.sources.size() > 1) - os << "] "; + if (p.sources.size() > 1) + os << "] "; - os << CLR_MAG("=>"); + os << CLR_MAG("=>"); - if (p.destinations.size() != 1) - os << " ["; + if (p.destinations.size() != 1) + os << " ["; - for (auto pd : p.destinations) - os << " " << pd->getNode()->getNameShort(); + for (auto pd : p.destinations) + os << " " << pd->getNode()->getNameShort(); - if (p.destinations.size() != 1) - os << " ]"; + if (p.destinations.size() != 1) + os << " ]"; - return os; - } + return os; + } - std::string toString() - { - std::stringstream ss; - ss << *this; - return ss.str(); - } + std::string toString() { + std::stringstream ss; + ss << *this; + return ss.str(); + } - Path(); - ~Path(); + Path(); + ~Path(); - void prepare(NodeList &nodes); + void prepare(NodeList &nodes); - // Check if path configuration is proper. - void check(); + // Check if path configuration is proper. + void check(); - // Check prepared path. - void checkPrepared(); + // Check prepared path. + void checkPrepared(); - /* Start a path. + /* Start a path. * * Start a new pthread for receiving/sending messages over this path. */ - void start(); + void start(); - // Stop a path. - void stop(); + // Stop a path. + void stop(); - // Get a list of signals which is emitted by the path. - SignalList::Ptr getOutputSignals(bool after_hooks = true); + // Get a list of signals which is emitted by the path. + SignalList::Ptr getOutputSignals(bool after_hooks = true); - unsigned getOutputSignalsMaxCount(); + unsigned getOutputSignalsMaxCount(); - /* Parse a single path and add it to the global configuration. + /* Parse a single path and add it to the global configuration. * * @param json A JSON object containing the configuration of the path. * @param p Pointer to the allocated memory for this path @@ -166,35 +164,23 @@ public: * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - void parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid); + void parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid); - void parseMask(json_t *json_mask, NodeList &nodes); + void parseMask(json_t *json_mask, NodeList &nodes); - bool isSimple() const; - bool isMuxed() const; + bool isSimple() const; + bool isMuxed() const; - bool isEnabled() const - { - return enabled; - } + bool isEnabled() const { return enabled; } - bool isReversed() const - { - return reversed; - } + bool isReversed() const { return reversed; } - State getState() const - { - return state; - } + State getState() const { return state; } - // Get the UUID of this path. - const uuid_t & getUuid() const - { - return uuid; - } + // Get the UUID of this path. + const uuid_t &getUuid() const { return uuid; } - json_t * toJson() const; + json_t *toJson() const; }; } // namespace node diff --git a/include/villas/path_destination.hpp b/include/villas/path_destination.hpp index 8ea9e908d..2a97a6a3a 100644 --- a/include/villas/path_destination.hpp +++ b/include/villas/path_destination.hpp @@ -21,35 +21,32 @@ struct Sample; class PathDestination; class PathDestination { - friend Path; + friend Path; public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; protected: - Node *node; - Path *path; + Node *node; + Path *path; - struct CQueue queue; + struct CQueue queue; public: - PathDestination(Path *p, Node *n); + PathDestination(Path *p, Node *n); - ~PathDestination(); + ~PathDestination(); - int prepare(int queuelen); + int prepare(int queuelen); - void check(); + void check(); - static - void enqueueAll(class Path *p, const struct Sample * const smps[], unsigned cnt); + static void enqueueAll(class Path *p, const struct Sample *const smps[], + unsigned cnt); - void write(); + void write(); - Node * getNode() const - { - return node; - } + Node *getNode() const { return node; } }; using PathDestinationList = std::vector; diff --git a/include/villas/path_list.hpp b/include/villas/path_list.hpp index 8ad9e3e39..d76a689a6 100644 --- a/include/villas/path_list.hpp +++ b/include/villas/path_list.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include @@ -22,10 +22,10 @@ class Path; class PathList : public std::list { public: - // Lookup a path from the list based on its UUID - Path * lookup(const uuid_t &uuid) const; + // Lookup a path from the list based on its UUID + Path *lookup(const uuid_t &uuid) const; - json_t * toJson() const; + json_t *toJson() const; }; } // namespace node diff --git a/include/villas/path_source.hpp b/include/villas/path_source.hpp index f5412a17b..bfe272038 100644 --- a/include/villas/path_source.hpp +++ b/include/villas/path_source.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include #include #include @@ -22,43 +22,34 @@ class Node; class Path; class PathSource { - friend Path; + friend Path; public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; protected: - Node *node; - Path *path; + Node *node; + Path *path; - bool masked; + bool masked; - struct Pool pool; + struct Pool pool; - MappingList mappings; // List of mappings (struct MappingEntry). + MappingList mappings; // List of mappings (struct MappingEntry). public: - PathSource(Path *p, Node *n); - virtual - ~PathSource(); + PathSource(Path *p, Node *n); + virtual ~PathSource(); - void check(); + void check(); - int read(int i); + int read(int i); - virtual - void writeToSecondaries(struct Sample *smps[], unsigned cnt) - { } + virtual void writeToSecondaries(struct Sample *smps[], unsigned cnt) {} - Node * getNode() const - { - return node; - } + Node *getNode() const { return node; } - Path * getPath() const - { - return path; - } + Path *getPath() const { return path; } }; using PathSourceList = std::vector; @@ -66,12 +57,13 @@ using PathSourceList = std::vector; class SecondaryPathSource : public PathSource { protected: - PathSource::Ptr master; + PathSource::Ptr master; public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - SecondaryPathSource(Path *p, Node *n, NodeList &nodes, PathSource::Ptr master); + SecondaryPathSource(Path *p, Node *n, NodeList &nodes, + PathSource::Ptr master); }; using SecondaryPathSourceList = std::vector; @@ -79,25 +71,18 @@ using SecondaryPathSourceList = std::vector; class MasterPathSource : public PathSource { protected: - SecondaryPathSourceList secondaries; // List of secondary path sources (PathSource). + SecondaryPathSourceList + secondaries; // List of secondary path sources (PathSource). public: - MasterPathSource(Path *p, Node *n); + MasterPathSource(Path *p, Node *n); - void addSecondary(SecondaryPathSource::Ptr ps) - { - secondaries.push_back(ps); - } + void addSecondary(SecondaryPathSource::Ptr ps) { secondaries.push_back(ps); } - SecondaryPathSourceList getSecondaries() - { - return secondaries; - } + SecondaryPathSourceList getSecondaries() { return secondaries; } - virtual - void writeToSecondaries(struct Sample *smps[], unsigned cnt); + virtual void writeToSecondaries(struct Sample *smps[], unsigned cnt); }; - } // namespace node } // namespace villas diff --git a/include/villas/pool.hpp b/include/villas/pool.hpp index 41fb88caf..bfcc4065e 100644 --- a/include/villas/pool.hpp +++ b/include/villas/pool.hpp @@ -12,27 +12,28 @@ #include #include -#include #include #include +#include namespace villas { namespace node { // A thread-safe memory pool struct Pool { - enum State state; + enum State state; - off_t buffer_off; // Offset from the struct address to the underlying memory area + off_t + buffer_off; // Offset from the struct address to the underlying memory area - size_t len; // Length of the underlying memory area - size_t blocksz; // Length of a block in bytes - size_t alignment; // Alignment of a block in bytes + size_t len; // Length of the underlying memory area + size_t blocksz; // Length of a block in bytes + size_t alignment; // Alignment of a block in bytes - struct CQueue queue; // The queue which is used to keep track of free blocks + struct CQueue queue; // The queue which is used to keep track of free blocks }; -#define pool_buffer(p) ((char *) (p) + (p)->buffer_off) +#define pool_buffer(p) ((char *)(p) + (p)->buffer_off) /* Initiazlize a pool * @@ -43,10 +44,12 @@ struct Pool { * @retval 0 The pool has been successfully initialized. * @retval <>0 There was an error during the pool initialization. */ -int pool_init(struct Pool *p, size_t cnt, size_t blocksz, struct memory::Type *mem = memory::default_type) __attribute__ ((warn_unused_result)); +int pool_init(struct Pool *p, size_t cnt, size_t blocksz, + struct memory::Type *mem = memory::default_type) + __attribute__((warn_unused_result)); // Destroy and release memory used by pool. -int pool_destroy(struct Pool *p) __attribute__ ((warn_unused_result)); +int pool_destroy(struct Pool *p) __attribute__((warn_unused_result)); /* Pop up to \p cnt values from the stack an place them in the array \p blocks. * @@ -60,7 +63,7 @@ ssize_t pool_get_many(struct Pool *p, void *blocks[], size_t cnt); ssize_t pool_put_many(struct Pool *p, void *blocks[], size_t cnt); // Get a free memory block from pool. -void * pool_get(struct Pool *p); +void *pool_get(struct Pool *p); // Release a memory block back to the pool. int pool_put(struct Pool *p, void *buf); diff --git a/include/villas/queue.h b/include/villas/queue.h index 4b35d5ac0..aabe06438 100644 --- a/include/villas/queue.h +++ b/include/villas/queue.h @@ -49,35 +49,37 @@ namespace node { typedef char cacheline_pad_t[CACHELINE_SIZE]; struct CQueue_cell { - std::atomic sequence; - off_t data_off; // Pointer relative to the queue struct + std::atomic sequence; + off_t data_off; // Pointer relative to the queue struct }; // A lock-free multiple-producer, multiple-consumer (MPMC) queue. struct CQueue { - std::atomic state; + std::atomic state; - cacheline_pad_t _pad0; // Shared area: all threads read + cacheline_pad_t _pad0; // Shared area: all threads read - size_t buffer_mask; - off_t buffer_off; // Relative pointer to struct CQueue_cell[] + size_t buffer_mask; + off_t buffer_off; // Relative pointer to struct CQueue_cell[] - cacheline_pad_t _pad1; // Producer area: only producers read & write + cacheline_pad_t _pad1; // Producer area: only producers read & write - std::atomic tail; // Queue tail pointer + std::atomic tail; // Queue tail pointer - cacheline_pad_t _pad2; // Consumer area: only consumers read & write + cacheline_pad_t _pad2; // Consumer area: only consumers read & write - std::atomic head; // Queue head pointer + std::atomic head; // Queue head pointer - cacheline_pad_t _pad3; // TODO: Why needed? + cacheline_pad_t _pad3; // TODO: Why needed? }; // Initialize MPMC queue -int queue_init(struct CQueue *q, size_t size, struct memory::Type *mem = memory::default_type) __attribute__ ((warn_unused_result)); +int queue_init(struct CQueue *q, size_t size, + struct memory::Type *mem = memory::default_type) + __attribute__((warn_unused_result)); // Desroy MPMC queue and release memory -int queue_destroy(struct CQueue *q) __attribute__ ((warn_unused_result)); +int queue_destroy(struct CQueue *q) __attribute__((warn_unused_result)); /* Return estimation of current queue usage. * diff --git a/include/villas/queue.hpp b/include/villas/queue.hpp index f04835619..236bd62d4 100644 --- a/include/villas/queue.hpp +++ b/include/villas/queue.hpp @@ -12,38 +12,33 @@ namespace villas { -template -class Queue { +template class Queue { protected: - std::queue queue; - std::mutex mtx; + std::queue queue; + std::mutex mtx; public: - void push(T p) - { - std::unique_lock guard(mtx); + void push(T p) { + std::unique_lock guard(mtx); - queue.push(p); - } + queue.push(p); + } - T pop() - { - std::unique_lock guard(mtx); + T pop() { + std::unique_lock guard(mtx); - T res = queue.front(); - queue.pop(); + T res = queue.front(); + queue.pop(); - return res; - } + return res; + } - bool empty() - { - std::unique_lock guard(mtx); - - return queue.empty(); - } + bool empty() { + std::unique_lock guard(mtx); + return queue.empty(); + } }; } // namespace villas diff --git a/include/villas/queue_signalled.h b/include/villas/queue_signalled.h index a33cd65e2..4fe7b5aef 100644 --- a/include/villas/queue_signalled.h +++ b/include/villas/queue_signalled.h @@ -9,59 +9,67 @@ #include -#include #include +#include namespace villas { namespace node { enum class QueueSignalledMode { - AUTO, // We will choose the best method available on the platform - PTHREAD, - POLLING, + AUTO, // We will choose the best method available on the platform + PTHREAD, + POLLING, #ifdef HAS_EVENTFD - EVENTFD, + EVENTFD, #endif }; -enum class QueueSignalledFlags { - PROCESS_SHARED = (1 << 4) -}; +enum class QueueSignalledFlags { PROCESS_SHARED = (1 << 4) }; // Wrapper around queue that uses POSIX CV's for signalling writes. struct CQueueSignalled { - struct CQueue queue; // Actual underlying queue. + struct CQueue queue; // Actual underlying queue. - enum QueueSignalledMode mode; - enum QueueSignalledFlags flags; + enum QueueSignalledMode mode; + enum QueueSignalledFlags flags; - union { - struct { - pthread_cond_t ready; // Condition variable to signal writes to the queue. - pthread_mutex_t mutex; // Mutex for ready. - } pthread; + union { + struct { + pthread_cond_t ready; // Condition variable to signal writes to the queue. + pthread_mutex_t mutex; // Mutex for ready. + } pthread; #ifdef __linux__ - int eventfd; + int eventfd; #endif - }; + }; }; #define queue_signalled_available(q) queue_available(&((q)->queue)) -int queue_signalled_init(struct CQueueSignalled *qs, size_t size = DEFAULT_QUEUE_LENGTH, struct memory::Type *mem = memory::default_type, enum QueueSignalledMode mode = QueueSignalledMode::AUTO, int flags = 0) __attribute__ ((warn_unused_result)); +int queue_signalled_init( + struct CQueueSignalled *qs, size_t size = DEFAULT_QUEUE_LENGTH, + struct memory::Type *mem = memory::default_type, + enum QueueSignalledMode mode = QueueSignalledMode::AUTO, int flags = 0) + __attribute__((warn_unused_result)); -int queue_signalled_destroy(struct CQueueSignalled *qs) __attribute__ ((warn_unused_result)); +int queue_signalled_destroy(struct CQueueSignalled *qs) + __attribute__((warn_unused_result)); -int queue_signalled_push(struct CQueueSignalled *qs, void *ptr) __attribute__ ((warn_unused_result)); +int queue_signalled_push(struct CQueueSignalled *qs, void *ptr) + __attribute__((warn_unused_result)); -int queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) __attribute__ ((warn_unused_result)); +int queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) + __attribute__((warn_unused_result)); -int queue_signalled_push_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) __attribute__ ((warn_unused_result)); +int queue_signalled_push_many(struct CQueueSignalled *qs, void *ptr[], + size_t cnt) __attribute__((warn_unused_result)); -int queue_signalled_pull_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) __attribute__ ((warn_unused_result)); +int queue_signalled_pull_many(struct CQueueSignalled *qs, void *ptr[], + size_t cnt) __attribute__((warn_unused_result)); -int queue_signalled_close(struct CQueueSignalled *qs) __attribute__ ((warn_unused_result)); +int queue_signalled_close(struct CQueueSignalled *qs) + __attribute__((warn_unused_result)); // Returns a file descriptor which can be used with poll / select to wait for new data int queue_signalled_fd(struct CQueueSignalled *qs); diff --git a/include/villas/queue_signalled.hpp b/include/villas/queue_signalled.hpp index 6e474b533..631cda832 100644 --- a/include/villas/queue_signalled.hpp +++ b/include/villas/queue_signalled.hpp @@ -7,39 +7,36 @@ #pragma once -#include #include +#include #include namespace villas { -template -class QueueSignalled : public Queue { +template class QueueSignalled : public Queue { private: - std::condition_variable cv; + std::condition_variable cv; public: - void push(const T &data) - { - Queue::push(data); + void push(const T &data) { + Queue::push(data); - cv.notify_one(); - } + cv.notify_one(); + } - T pop() - { - std::unique_lock l(Queue::mtx); + T pop() { + std::unique_lock l(Queue::mtx); - while (Queue::queue.empty()) - cv.wait(l); + while (Queue::queue.empty()) + cv.wait(l); - T res = Queue::queue.front(); - Queue::queue.pop(); + T res = Queue::queue.front(); + Queue::queue.pop(); - return res; - } + return res; + } }; } // namespace villas diff --git a/include/villas/sample.hpp b/include/villas/sample.hpp index 600037e00..80f3f3878 100644 --- a/include/villas/sample.hpp +++ b/include/villas/sample.hpp @@ -10,8 +10,8 @@ #include #include -#include #include +#include #include #include @@ -19,16 +19,16 @@ #include // The length of a sample datastructure with \p values values in bytes. -#define SAMPLE_LENGTH(len) (sizeof(struct Sample) + SAMPLE_DATA_LENGTH(len)) +#define SAMPLE_LENGTH(len) (sizeof(struct Sample) + SAMPLE_DATA_LENGTH(len)) // The length of a sample data portion of a sample datastructure with \p values values in bytes. -#define SAMPLE_DATA_LENGTH(len) ((len) * sizeof(double)) +#define SAMPLE_DATA_LENGTH(len) ((len) * sizeof(double)) // The number of values in a sample datastructure. -#define SAMPLE_NUMBER_OF_VALUES(len) ((len) / sizeof(double)) +#define SAMPLE_NUMBER_OF_VALUES(len) ((len) / sizeof(double)) // The offset to the beginning of the data section. -#define SAMPLE_DATA_OFFSET(smp) ((char *) (smp) + offsetof(struct Sample, data)) +#define SAMPLE_DATA_OFFSET(smp) ((char *)(smp) + offsetof(struct Sample, data)) namespace villas { namespace node { @@ -38,37 +38,41 @@ struct Pool; // Parts of a sample that can be serialized / de-serialized by the IO formats enum class SampleFlags { - HAS_TS_ORIGIN = (1 << 0), // Include origin timestamp in output. - HAS_TS_RECEIVED = (1 << 1), // Include receive timestamp in output. - HAS_OFFSET = (1 << 2), // Include offset (received - origin timestamp) in output. - HAS_SEQUENCE = (1 << 3), // Include sequence number in output. - HAS_DATA = (1 << 4), // Include values in output. + HAS_TS_ORIGIN = (1 << 0), // Include origin timestamp in output. + HAS_TS_RECEIVED = (1 << 1), // Include receive timestamp in output. + HAS_OFFSET = + (1 << 2), // Include offset (received - origin timestamp) in output. + HAS_SEQUENCE = (1 << 3), // Include sequence number in output. + HAS_DATA = (1 << 4), // Include values in output. - HAS_TS = HAS_TS_ORIGIN | HAS_TS_RECEIVED, // Include origin timestamp in output. - HAS_ALL = (1 << 5) - 1, // Enable all output options. + HAS_TS = + HAS_TS_ORIGIN | HAS_TS_RECEIVED, // Include origin timestamp in output. + HAS_ALL = (1 << 5) - 1, // Enable all output options. - IS_FIRST = (1 << 16), // This sample is the first of a new simulation case - IS_LAST = (1 << 17) // This sample is the last of a running simulation case + IS_FIRST = (1 << 16), // This sample is the first of a new simulation case + IS_LAST = (1 << 17) // This sample is the last of a running simulation case }; struct Sample { - uint64_t sequence; // The sequence number of this sample. - unsigned length; // The number of values in sample::values which are valid. - unsigned capacity; // The number of values in sample::values for which memory is reserved. - int flags; // Flags are used to store binary properties of a sample. + uint64_t sequence; // The sequence number of this sample. + unsigned length; // The number of values in sample::values which are valid. + unsigned + capacity; // The number of values in sample::values for which memory is reserved. + int flags; // Flags are used to store binary properties of a sample. - SignalList::Ptr signals; // The list of signal descriptors. + SignalList::Ptr signals; // The list of signal descriptors. - std::atomic refcnt; // Reference counter. - ptrdiff_t pool_off; // This sample belongs to this memory pool (relative pointer). See sample_pool(). + std::atomic refcnt; // Reference counter. + ptrdiff_t + pool_off; // This sample belongs to this memory pool (relative pointer). See sample_pool(). - // All timestamps are seconds / nano seconds after 1.1.1970 UTC - struct { - struct timespec origin; // The point in time when this data was sampled. - struct timespec received; // The point in time when this data was received. - } ts; + // All timestamps are seconds / nano seconds after 1.1.1970 UTC + struct { + struct timespec origin; // The point in time when this data was sampled. + struct timespec received; // The point in time when this data was received. + } ts; - /* The sample signal values. + /* The sample signal values. * * This variable length array (VLA) extends over the end of struct Sample. * Make sure that pointers to struct Sample point to memory blocks of adequate size. @@ -78,21 +82,24 @@ struct Sample { * are stored in the struct Sample::signals list. Each entry in this list corresponedents * to an entry in the struct Sample::data array. */ - union SignalData data[]; + union SignalData data[]; }; #define SAMPLE_NON_POOL PTRDIFF_MIN // Get the address of the pool to which the sample belongs. -#define sample_pool(s) ((s)->pool_off == SAMPLE_NON_POOL ? nullptr : (struct Pool *) ((char *) (s) + (s)->pool_off)) +#define sample_pool(s) \ + ((s)->pool_off == SAMPLE_NON_POOL \ + ? nullptr \ + : (struct Pool *)((char *)(s) + (s)->pool_off)) -struct Sample * sample_alloc(struct Pool *p); +struct Sample *sample_alloc(struct Pool *p); -struct Sample * sample_alloc_mem(int capacity); +struct Sample *sample_alloc_mem(int capacity); int sample_init(struct Sample *s); -struct Sample * sample_clone(struct Sample *smp); +struct Sample *sample_clone(struct Sample *smp); void sample_free(struct Sample *s); @@ -118,14 +125,17 @@ void sample_dump(villas::Logger logger, struct Sample *s); // Compare two samples int sample_cmp(struct Sample *a, struct Sample *b, double epsilon, int flags); -int sample_clone_many(struct Sample *dsts[], const struct Sample * const srcs[], int cnt); -int sample_copy_many(struct Sample * const dsts[], const struct Sample * const srcs[], int cnt); -int sample_incref_many(struct Sample * const smps[], int cnt); -int sample_decref_many(struct Sample * const smps[], int cnt); +int sample_clone_many(struct Sample *dsts[], const struct Sample *const srcs[], + int cnt); +int sample_copy_many(struct Sample *const dsts[], + const struct Sample *const srcs[], int cnt); +int sample_incref_many(struct Sample *const smps[], int cnt); +int sample_decref_many(struct Sample *const smps[], int cnt); enum SignalType sample_format(const struct Sample *s, unsigned idx); -void sample_data_insert(struct Sample *smp, const union SignalData *src, size_t offset, size_t len); +void sample_data_insert(struct Sample *smp, const union SignalData *src, + size_t offset, size_t len); void sample_data_remove(struct Sample *smp, size_t offset, size_t len); } // namespace node diff --git a/include/villas/shmem.hpp b/include/villas/shmem.hpp index d8940c24c..17119deeb 100644 --- a/include/villas/shmem.hpp +++ b/include/villas/shmem.hpp @@ -12,8 +12,8 @@ #include #include -#define DEFAULT_SHMEM_QUEUELEN 512u -#define DEFAULT_SHMEM_SAMPLELEN 64u +#define DEFAULT_SHMEM_QUEUELEN 512u +#define DEFAULT_SHMEM_SAMPLELEN 64u namespace villas { namespace node { @@ -21,30 +21,30 @@ namespace node { /* Struct containing all parameters that need to be known when creating a new * shared memory object. */ struct ShmemConfig { - int polling; // Whether to use polling instead of POSIX CVs - int queuelen; // Size of the queues (in elements) - int samplelen; // Maximum number of data entries in a single sample + int polling; // Whether to use polling instead of POSIX CVs + int queuelen; // Size of the queues (in elements) + int samplelen; // Maximum number of data entries in a single sample }; // The structure that actually resides in the shared memory. struct ShmemShared { - int polling; // Whether to use a pthread_cond_t to signal if new samples are written to incoming queue. - struct CQueueSignalled queue; // Queue for samples passed in both directions. - struct Pool pool; // Pool for the samples in the queues. + int polling; // Whether to use a pthread_cond_t to signal if new samples are written to incoming queue. + struct CQueueSignalled queue; // Queue for samples passed in both directions. + struct Pool pool; // Pool for the samples in the queues. }; // Relevant information for one direction of the interface. struct shmem_dir { - void *base; // Base address of the region. - const char *name; // Name of the shmem object. - size_t len; // Total size of the region. - struct ShmemShared *shared; // Actually shared datastructure + void *base; // Base address of the region. + const char *name; // Name of the shmem object. + size_t len; // Total size of the region. + struct ShmemShared *shared; // Actually shared datastructure }; // Main structure representing the shared memory interface. struct ShmemInterface { - struct shmem_dir read, write; - std::atomic readers, writers, closed; + struct shmem_dir read, write; + std::atomic readers, writers, closed; }; /* Open the shared memory objects and retrieve / initialize the shared data structures. @@ -58,7 +58,8 @@ struct ShmemInterface { * @retval 0 The objects were opened and initialized successfully. * @retval <0 An error occured; errno is set accordingly. */ -int shmem_int_open(const char* wname, const char* rname, struct ShmemInterface* shm, struct ShmemConfig* conf); +int shmem_int_open(const char *wname, const char *rname, + struct ShmemInterface *shm, struct ShmemConfig *conf); /* Close and destroy the shared memory interface and related structures. * @@ -77,7 +78,8 @@ int shmem_int_close(struct ShmemInterface *shm); * @retval >=0 Number of samples that were read. Can be less than cnt (including 0) in case not enough samples were available. * @retval -1 The other process closed the interface; no samples can be read anymore. */ -int shmem_int_read(struct ShmemInterface *shm, struct Sample * const smps[], unsigned cnt); +int shmem_int_read(struct ShmemInterface *shm, struct Sample *const smps[], + unsigned cnt); /* Write samples to the interface. * @@ -87,7 +89,8 @@ int shmem_int_read(struct ShmemInterface *shm, struct Sample * const smps[], uns * @retval >=0 Number of samples that were successfully written. Can be less than cnt (including 0) in case of a full queue. * @retval -1 The write failed for some reason; no more samples can be written. */ -int shmem_int_write(struct ShmemInterface *shm, const struct Sample * const smps[], unsigned cnt); +int shmem_int_write(struct ShmemInterface *shm, + const struct Sample *const smps[], unsigned cnt); /* Allocate samples to be written to the interface. * @@ -97,7 +100,8 @@ int shmem_int_write(struct ShmemInterface *shm, const struct Sample * const smps * @param cnt Number of samples to allocate. * @return Number of samples that were successfully allocated (may be less then cnt). */ -int shmem_int_alloc(struct ShmemInterface *shm, struct Sample *smps[], unsigned cnt); +int shmem_int_alloc(struct ShmemInterface *shm, struct Sample *smps[], + unsigned cnt); /* Returns the total size of the shared memory region with the given size of * the input/output queues (in elements) and the given number of data elements diff --git a/include/villas/signal.hpp b/include/villas/signal.hpp index 58a9ef14a..71e90e629 100644 --- a/include/villas/signal.hpp +++ b/include/villas/signal.hpp @@ -11,8 +11,8 @@ #include -#include #include +#include // "I" defined by complex.h collides with a define in OpenSSL #undef I @@ -27,26 +27,27 @@ namespace node { class Signal { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - std::string name; // The name of the signal. - std::string unit; // The unit of the signal. + std::string name; // The name of the signal. + std::string unit; // The unit of the signal. - union SignalData init; // The initial value of the signal. - enum SignalType type; + union SignalData init; // The initial value of the signal. + enum SignalType type; - // Initialize a signal with default values. - Signal(const std::string &n = "", const std::string &u = "", enum SignalType t = SignalType::INVALID); + // Initialize a signal with default values. + Signal(const std::string &n = "", const std::string &u = "", + enum SignalType t = SignalType::INVALID); - // Parse signal description. - int parse(json_t *json); + // Parse signal description. + int parse(json_t *json); - std::string toString(const union SignalData *d = nullptr) const; + std::string toString(const union SignalData *d = nullptr) const; - // Produce JSON representation of signal. - json_t * toJson() const; + // Produce JSON representation of signal. + json_t *toJson() const; - bool isNext(const Signal &sig); + bool isNext(const Signal &sig); }; } // namespace node diff --git a/include/villas/signal_data.hpp b/include/villas/signal_data.hpp index 56ee7105f..e4351e84e 100644 --- a/include/villas/signal_data.hpp +++ b/include/villas/signal_data.hpp @@ -9,8 +9,8 @@ #include -#include #include +#include #include #include @@ -23,46 +23,40 @@ namespace node { * Data is in host endianess! */ union SignalData { - double f; // Floating point values. - int64_t i; // Integer values. - bool b; // Boolean values. - std::complex z; // Complex values. + double f; // Floating point values. + int64_t i; // Integer values. + bool b; // Boolean values. + std::complex z; // Complex values. - SignalData() : - i(0) - { } + SignalData() : i(0) {} - static - union SignalData nan() - { - union SignalData d; + static union SignalData nan() { + union SignalData d; - d.f = std::numeric_limits::quiet_NaN(); + d.f = std::numeric_limits::quiet_NaN(); - return d; - } + return d; + } - bool is_nan() - { - return f == std::numeric_limits::quiet_NaN(); - } + bool is_nan() { return f == std::numeric_limits::quiet_NaN(); } - // Convert signal data from one description/format to another. - SignalData cast(enum SignalType type, enum SignalType to) const; + // Convert signal data from one description/format to another. + SignalData cast(enum SignalType type, enum SignalType to) const; - // Set data from double - void set(enum SignalType type, double val); + // Set data from double + void set(enum SignalType type, double val); - // Print value of a signal to a character buffer. - int printString(enum SignalType type, char *buf, size_t len, int precision = 5) const; + // Print value of a signal to a character buffer. + int printString(enum SignalType type, char *buf, size_t len, + int precision = 5) const; - int parseString(enum SignalType type, const char *ptr, char **end); + int parseString(enum SignalType type, const char *ptr, char **end); - int parseJson(enum SignalType type, json_t *json); + int parseJson(enum SignalType type, json_t *json); - json_t * toJson(enum SignalType type) const; + json_t *toJson(enum SignalType type) const; - std::string toString(enum SignalType type, int precision = 5) const; + std::string toString(enum SignalType type, int precision = 5) const; }; } // namespace node diff --git a/include/villas/signal_list.hpp b/include/villas/signal_list.hpp index 8fe04c777..9a326abfd 100644 --- a/include/villas/signal_list.hpp +++ b/include/villas/signal_list.hpp @@ -12,9 +12,9 @@ #include +#include #include #include -#include namespace villas { namespace node { @@ -22,31 +22,30 @@ namespace node { class SignalList : public std::vector { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - SignalList() - { } + SignalList() {} - SignalList(unsigned len, enum SignalType fmt); - SignalList(const char *dt); - SignalList(json_t *json) - { - int ret = parse(json); - if (ret) - throw RuntimeError("Failed to parse signal list"); - } + SignalList(unsigned len, enum SignalType fmt); + SignalList(const char *dt); + SignalList(json_t *json) { + int ret = parse(json); + if (ret) + throw RuntimeError("Failed to parse signal list"); + } - int parse(json_t *json); + int parse(json_t *json); - Ptr clone(); + Ptr clone(); - void dump(villas::Logger logger, const union SignalData *data = nullptr, unsigned len = 0) const; + void dump(villas::Logger logger, const union SignalData *data = nullptr, + unsigned len = 0) const; - json_t * toJson() const; + json_t *toJson() const; - int getIndexByName(const std::string &name); - Signal::Ptr getByName(const std::string &name); - Signal::Ptr getByIndex(unsigned idx); + int getIndexByName(const std::string &name); + Signal::Ptr getByName(const std::string &name); + Signal::Ptr getByIndex(unsigned idx); }; } // namespace node diff --git a/include/villas/signal_type.hpp b/include/villas/signal_type.hpp index f890afd67..30af86e4a 100644 --- a/include/villas/signal_type.hpp +++ b/include/villas/signal_type.hpp @@ -13,11 +13,11 @@ namespace villas { namespace node { enum class SignalType { - INVALID = 0, // Signal type is invalid. - FLOAT = 1, // See SignalData::f - INTEGER = 2, // See SignalData::i - BOOLEAN = 3, // See SignalData::b - COMPLEX = 4 // See SignalData::z + INVALID = 0, // Signal type is invalid. + FLOAT = 1, // See SignalData::f + INTEGER = 2, // See SignalData::i + BOOLEAN = 3, // See SignalData::b + COMPLEX = 4 // See SignalData::z }; enum SignalType signalTypeFromString(const std::string &str); diff --git a/include/villas/socket_addr.hpp b/include/villas/socket_addr.hpp index 07e9de46d..d3947a171 100644 --- a/include/villas/socket_addr.hpp +++ b/include/villas/socket_addr.hpp @@ -7,40 +7,35 @@ #pragma once -#include -#include -#include #include +#include +#include +#include #include #if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__) - #define WITH_SOCKET_LAYER_ETH +#define WITH_SOCKET_LAYER_ETH - #include - #include +#include +#include #endif // LIBNL3_ROUTE_FOUND union sockaddr_union { - struct sockaddr sa; - struct sockaddr_storage ss; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - struct sockaddr_un sun; + struct sockaddr sa; + struct sockaddr_storage ss; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_un sun; #ifdef WITH_SOCKET_LAYER_ETH - struct sockaddr_ll sll; + struct sockaddr_ll sll; #endif }; namespace villas { namespace node { -enum class SocketLayer { - ETH, - IP, - UDP, - UNIX -}; +enum class SocketLayer { ETH, IP, UDP, UNIX }; /* Generate printable socket address depending on the address family * @@ -50,7 +45,7 @@ enum class SocketLayer { * @param sa A pointer to the socket address. * @return The buffer containing the textual representation of the address. The caller is responsible to free() this buffer! */ -char * socket_print_addr(struct sockaddr *saddr); +char *socket_print_addr(struct sockaddr *saddr); /* Parse a socket address depending on the address family * @@ -66,7 +61,8 @@ char * socket_print_addr(struct sockaddr *saddr); * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ -int socket_parse_address(const char *str, struct sockaddr *sa, enum SocketLayer layer, int flags); +int socket_parse_address(const char *str, struct sockaddr *sa, + enum SocketLayer layer, int flags); int socket_compare_addr(struct sockaddr *x, struct sockaddr *y); diff --git a/include/villas/stats.hpp b/include/villas/stats.hpp index 696aa29c1..b550b80d1 100644 --- a/include/villas/stats.hpp +++ b/include/villas/stats.hpp @@ -10,15 +10,15 @@ #include #include -#include #include #include +#include #include #include -#include -#include #include +#include +#include namespace villas { namespace node { @@ -27,104 +27,82 @@ namespace node { struct Sample; class Node; -} +} // namespace node class Stats { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; - enum class Format { - HUMAN, - JSON, - MATLAB - }; + enum class Format { HUMAN, JSON, MATLAB }; - enum class Metric { - SMPS_SKIPPED, // Counter for skipped samples due to hooks. - SMPS_REORDERED, // Counter for reordered samples. + enum class Metric { + SMPS_SKIPPED, // Counter for skipped samples due to hooks. + SMPS_REORDERED, // Counter for reordered samples. - // Timings - GAP_SAMPLE, // Histogram for inter sample timestamps (as sent by remote). - GAP_RECEIVED, // Histogram for inter sample arrival time (as seen by this instance). - OWD, // Histogram for one-way-delay (OWD) of received samples. - AGE, // Processing time of packets within VILLASnode. - SIGNAL_COUNT, // Number of signals per sample. + // Timings + GAP_SAMPLE, // Histogram for inter sample timestamps (as sent by remote). + GAP_RECEIVED, // Histogram for inter sample arrival time (as seen by this instance). + OWD, // Histogram for one-way-delay (OWD) of received samples. + AGE, // Processing time of packets within VILLASnode. + SIGNAL_COUNT, // Number of signals per sample. - // RTP metrics - RTP_LOSS_FRACTION, // Fraction lost since last RTP SR/RR. - RTP_PKTS_LOST, // Cumul. no. pkts lost. - RTP_JITTER // Interarrival jitter. - }; + // RTP metrics + RTP_LOSS_FRACTION, // Fraction lost since last RTP SR/RR. + RTP_PKTS_LOST, // Cumul. no. pkts lost. + RTP_JITTER // Interarrival jitter. + }; - enum class Type { - LAST, - HIGHEST, - LOWEST, - MEAN, - VAR, - STDDEV, - TOTAL - }; + enum class Type { LAST, HIGHEST, LOWEST, MEAN, VAR, STDDEV, TOTAL }; protected: - std::unordered_map histograms; + std::unordered_map histograms; - struct MetricDescription { - const char *name; - const char *unit; - const char *desc; - }; + struct MetricDescription { + const char *name; + const char *unit; + const char *desc; + }; - struct TypeDescription { - const char *name; - enum node::SignalType signal_type; - }; + struct TypeDescription { + const char *name; + enum node::SignalType signal_type; + }; - static - std::shared_ptr table; + static std::shared_ptr
table; - static - void setupTable(); + static void setupTable(); - Logger logger; + Logger logger; public: + Stats(int buckets, int warmup); - Stats(int buckets, int warmup); + static enum Format lookupFormat(const std::string &str); - static - enum Format lookupFormat(const std::string &str); + static enum Metric lookupMetric(const std::string &str); - static - enum Metric lookupMetric(const std::string &str); + static enum Type lookupType(const std::string &str); - static - enum Type lookupType(const std::string &str); + void update(enum Metric id, double val); - void update(enum Metric id, double val); + void reset(); - void reset(); + json_t *toJson() const; - json_t * toJson() const; + static void printHeader(enum Format fmt); - static - void printHeader(enum Format fmt); + void printPeriodic(FILE *f, enum Format fmt, node::Node *n) const; - void printPeriodic(FILE *f, enum Format fmt, node::Node *n) const; + void print(FILE *f, enum Format fmt, int verbose) const; - void print(FILE *f, enum Format fmt, int verbose) const; + union node::SignalData getValue(enum Metric sm, enum Type st) const; - union node::SignalData getValue(enum Metric sm, enum Type st) const; + const Hist &getHistogram(enum Metric sm) const; - const Hist & getHistogram(enum Metric sm) const; - - static - std::unordered_map metrics; - static - std::unordered_map types; - static - std::vector columns; + static std::unordered_map metrics; + static std::unordered_map types; + static std::vector columns; }; } // namespace villas diff --git a/include/villas/super_node.hpp b/include/villas/super_node.hpp index a843a8bc6..0bf2d4b60 100644 --- a/include/villas/super_node.hpp +++ b/include/villas/super_node.hpp @@ -11,22 +11,22 @@ #ifdef WITH_GRAPHVIZ extern "C" { - #include +#include } #endif #include #include -#include -#include +#include #include +#include +#include #include #include #include #include -#include -#include +#include namespace villas { namespace node { @@ -38,159 +38,117 @@ class Node; class SuperNode { protected: - enum State state; + enum State state; - int idleStop; + int idleStop; - Logger logger; + Logger logger; - NodeList nodes; - PathList paths; - std::list interfaces; + NodeList nodes; + PathList paths; + std::list interfaces; #ifdef WITH_API - Api api; + Api api; #endif #ifdef WITH_WEB - Web web; + Web web; #endif - int priority; // Process priority (lower is better) - int affinity; // Process affinity of the server and all created threads - int hugepages; // Number of hugepages to reserve. - double statsRate; // Rate at which we display the periodic stats. + int priority; // Process priority (lower is better) + int affinity; // Process affinity of the server and all created threads + int hugepages; // Number of hugepages to reserve. + double statsRate; // Rate at which we display the periodic stats. - struct Task task; // Task for periodic stats output + struct Task task; // Task for periodic stats output - uuid_t uuid; // A globally unique identifier of the instance + uuid_t uuid; // A globally unique identifier of the instance - struct timespec started; // The time at which the instance has been started. + struct timespec started; // The time at which the instance has been started. - std::string uri; // URI of configuration + std::string uri; // URI of configuration - Config config; // The configuration file. + Config config; // The configuration file. public: - // Inititalize configuration object before parsing the configuration. - SuperNode(); + // Inititalize configuration object before parsing the configuration. + SuperNode(); - int init(); + int init(); - // Wrapper for parse() which loads the config first. - void parse(const std::string &name); + // Wrapper for parse() which loads the config first. + void parse(const std::string &name); - /* Parse super-node configuration. + /* Parse super-node configuration. * * @param json A libjansson object which contains the configuration. */ - void parse(json_t *json); + void parse(json_t *json); - // Check validity of super node configuration. - void check(); + // Check validity of super node configuration. + void check(); - // Initialize after parsing the configuration file. - void prepare(); - void start(); - void stop(); - void run(); + // Initialize after parsing the configuration file. + void prepare(); + void start(); + void stop(); + void run(); - void preparePaths(); - void prepareNodes(); - void prepareNodeTypes(); + void preparePaths(); + void prepareNodes(); + void prepareNodeTypes(); - void startPaths(); - void startNodes(); - void startInterfaces(); + void startPaths(); + void startNodes(); + void startInterfaces(); - void stopPaths(); - void stopNodes(); - void stopNodeTypes(); - void stopInterfaces(); + void stopPaths(); + void stopNodes(); + void stopNodeTypes(); + void stopInterfaces(); #ifdef WITH_GRAPHVIZ - graph_t * getGraph(); + graph_t *getGraph(); #endif - // Run periodic hooks of this super node. - int periodic(); + // Run periodic hooks of this super node. + int periodic(); - void setState(enum State st) - { - state = st; - } + void setState(enum State st) { state = st; } - Node * getNode(const std::string &name) - { - return nodes.lookup(name); - } + Node *getNode(const std::string &name) { return nodes.lookup(name); } - NodeList & getNodes() - { - return nodes; - } + NodeList &getNodes() { return nodes; } - PathList & getPaths() - { - return paths; - } + PathList &getPaths() { return paths; } - std::list & getInterfaces() - { - return interfaces; - } + std::list &getInterfaces() { return interfaces; } - enum State getState() const - { - return state; - } + enum State getState() const { return state; } - const uuid_t & getUuid() const - { - return uuid; - } + const uuid_t &getUuid() const { return uuid; } - struct timespec getStartTime() const - { - return started; - } + struct timespec getStartTime() const { return started; } #ifdef WITH_API - Api * getApi() - { - return &api; - } + Api *getApi() { return &api; } #endif #ifdef WITH_WEB - Web * getWeb() - { - return &web; - } + Web *getWeb() { return &web; } #endif - json_t * getConfig() - { - return config.root; - } + json_t *getConfig() { return config.root; } - std::string getConfigUri() const - { - return uri; - } + std::string getConfigUri() const { return uri; } - int getAffinity() const - { - return affinity; - } + int getAffinity() const { return affinity; } - Logger getLogger() - { - return logger; - } + Logger getLogger() { return logger; } - // Destroy configuration object. - ~SuperNode(); + // Destroy configuration object. + ~SuperNode(); }; } // namespace node diff --git a/include/villas/usb.hpp b/include/villas/usb.hpp index 67be5f560..7c0086b71 100644 --- a/include/villas/usb.hpp +++ b/include/villas/usb.hpp @@ -15,96 +15,82 @@ namespace villas { namespace usb { struct Filter { - int bus; - int port; - int vendor_id; - int product_id; + int bus; + int port; + int vendor_id; + int product_id; }; class Error : public std::runtime_error { protected: - enum libusb_error err; - char *msg; + enum libusb_error err; + char *msg; public: - Error(enum libusb_error e, const std::string &what) : - std::runtime_error(what), - err(e) - { - int ret __attribute__((unused)); - ret = asprintf(&msg, "%s: %s", std::runtime_error::what(), libusb_strerror(err)); - } + Error(enum libusb_error e, const std::string &what) + : std::runtime_error(what), err(e) { + int ret __attribute__((unused)); + ret = asprintf(&msg, "%s: %s", std::runtime_error::what(), + libusb_strerror(err)); + } - template - Error(enum libusb_error e, const std::string &what, Args&&... args) : - usb::Error(e, fmt::format(what, std::forward(args)...)) - { } + template + Error(enum libusb_error e, const std::string &what, Args &&...args) + : usb::Error(e, fmt::format(what, std::forward(args)...)) {} - // Same as above but with int - Error(int e, const std::string &what) : - usb::Error((enum libusb_error) e, what) - { } + // Same as above but with int + Error(int e, const std::string &what) + : usb::Error((enum libusb_error)e, what) {} - template - Error(int e, const std::string &what, Args&&... args) : - usb::Error((enum libusb_error) e, what, std::forward(args)...) - { } + template + Error(int e, const std::string &what, Args &&...args) + : usb::Error((enum libusb_error)e, what, std::forward(args)...) {} - ~Error() - { - if (msg) - free(msg); - } + ~Error() { + if (msg) + free(msg); + } - virtual - const char * what() const noexcept - { - return msg; - } + virtual const char *what() const noexcept { return msg; } }; class Device { protected: - struct libusb_device *device; - struct libusb_device_handle *handle; - struct libusb_device_descriptor desc; + struct libusb_device *device; + struct libusb_device_handle *handle; + struct libusb_device_descriptor desc; - std::string getStringDescriptor(uint8_t desc_id) const; + std::string getStringDescriptor(uint8_t desc_id) const; public: - Device(struct libusb_device *dev) : - device(dev), - handle(nullptr) - { } + Device(struct libusb_device *dev) : device(dev), handle(nullptr) {} - const struct libusb_device_descriptor & getDescriptor() const - { return desc; } + const struct libusb_device_descriptor &getDescriptor() const { return desc; } - int getBus() const - { return libusb_get_bus_number(device); } + int getBus() const { return libusb_get_bus_number(device); } - int getPort() const - { return libusb_get_port_number(device); } + int getPort() const { return libusb_get_port_number(device); } - std::string getManufacturer() const - { return getStringDescriptor(desc.iManufacturer); } + std::string getManufacturer() const { + return getStringDescriptor(desc.iManufacturer); + } - std::string getProduct() const - { return getStringDescriptor(desc.iProduct); } + std::string getProduct() const { return getStringDescriptor(desc.iProduct); } - std::string getSerial() const - { return getStringDescriptor(desc.iSerialNumber); } + std::string getSerial() const { + return getStringDescriptor(desc.iSerialNumber); + } - bool match(const Filter *flt) const; + bool match(const Filter *flt) const; }; -struct libusb_context * init(); +struct libusb_context *init(); void deinit_context(struct libusb_context *ctx); -struct libusb_context * get_context(); +struct libusb_context *get_context(); void detach(struct libusb_device_handle *hdl, int iface); diff --git a/include/villas/web.hpp b/include/villas/web.hpp index acf73edbd..b31727cd2 100644 --- a/include/villas/web.hpp +++ b/include/villas/web.hpp @@ -10,11 +10,11 @@ #include #include -#include #include +#include -#include #include +#include #include namespace villas { @@ -26,74 +26,57 @@ class Api; class Web final { private: - enum State state; + enum State state; - Logger logger; + Logger logger; - lws_context *context; // The libwebsockets server context. - lws_vhost *vhost; // The libwebsockets vhost. + lws_context *context; // The libwebsockets server context. + lws_vhost *vhost; // The libwebsockets vhost. - Queue writables; // Queue of WSIs for which we will call lws_callback_on_writable() + Queue + writables; // Queue of WSIs for which we will call lws_callback_on_writable() - int port; // Port of the build in HTTP / WebSocket server. - std::string ssl_cert; // Path to the SSL certitifcate for HTTPS / WSS. - std::string ssl_private_key; // Path to the SSL private key for HTTPS / WSS. + int port; // Port of the build in HTTP / WebSocket server. + std::string ssl_cert; // Path to the SSL certitifcate for HTTPS / WSS. + std::string ssl_private_key; // Path to the SSL private key for HTTPS / WSS. - std::thread thread; - std::atomic running; // Atomic flag for signalizing thread termination. + std::thread thread; + std::atomic running; // Atomic flag for signalizing thread termination. - Api *api; + Api *api; - void worker(); + void worker(); public: - - /* Initialize the web interface. + /* Initialize the web interface. * * The web interface is based on the libwebsockets library. */ - Web(Api *a = nullptr); + Web(Api *a = nullptr); - ~Web(); + ~Web(); - void start(); - void stop(); + void start(); + void stop(); - static - void lwsLogger(int level, const char *msg); - static - int lwsLogLevel(Log::Level lvl); + static void lwsLogger(int level, const char *msg); + static int lwsLogLevel(Log::Level lvl); - // Parse HTTPd and WebSocket related options - int parse(json_t *json); + // Parse HTTPd and WebSocket related options + int parse(json_t *json); - Api * getApi() - { - return api; - } + Api *getApi() { return api; } - // for C-compatability - lws_context * getContext() - { - return context; - } + // for C-compatability + lws_context *getContext() { return context; } - lws_vhost * getVHost() - { - return vhost; - } + lws_vhost *getVHost() { return vhost; } - enum State getState() const - { - return state; - } + enum State getState() const { return state; } - void callbackOnWritable(struct lws *wsi); + void callbackOnWritable(struct lws *wsi); - bool isEnabled() - { - return port != CONTEXT_PORT_NO_LISTEN; - } + bool isEnabled() { return port != CONTEXT_PORT_NO_LISTEN; } }; } // namespace node diff --git a/lib/api.cpp b/lib/api.cpp index 01b0e7547..c53bd47bb 100644 --- a/lib/api.cpp +++ b/lib/api.cpp @@ -6,84 +6,75 @@ */ #include -#include -#include #include -#include +#include +#include #include #include -#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::node::api; -InvalidMethod::InvalidMethod(Request *req) : - BadRequest("The '{}' API endpoint does not support {} requests", - req->factory->getName(), - Session::methodToString(req->method) - ) -{ } +InvalidMethod::InvalidMethod(Request *req) + : BadRequest("The '{}' API endpoint does not support {} requests", + req->factory->getName(), + Session::methodToString(req->method)) {} -Api::Api(SuperNode *sn) : - logger(logging.get("api")), - state(State::INITIALIZED), - super_node(sn) -{ } +Api::Api(SuperNode *sn) + : logger(logging.get("api")), state(State::INITIALIZED), super_node(sn) {} -Api::~Api() -{ - if (state == State::STARTED) - stop(); +Api::~Api() { + if (state == State::STARTED) + stop(); } -void Api::start() -{ - assert(state != State::STARTED); +void Api::start() { + assert(state != State::STARTED); - logger->info("Starting sub-system"); + logger->info("Starting sub-system"); - running = true; - thread = std::thread(&Api::worker, this); + running = true; + thread = std::thread(&Api::worker, this); - state = State::STARTED; + state = State::STARTED; } -void Api::stop() -{ - assert(state == State::STARTED); +void Api::stop() { + assert(state == State::STARTED); - logger->info("Stopping sub-system"); + logger->info("Stopping sub-system"); - for (Session *s : sessions) - s->shutdown(); + for (Session *s : sessions) + s->shutdown(); - for (int i = 0; i < 2 && sessions.size() > 0; i++) { - logger->info("Waiting for {} sessions to terminate", sessions.size()); - usleep(1 * 1e6); - } + for (int i = 0; i < 2 && sessions.size() > 0; i++) { + logger->info("Waiting for {} sessions to terminate", sessions.size()); + usleep(1 * 1e6); + } - running = false; - pending.push(nullptr); // unblock thread - thread.join(); + running = false; + pending.push(nullptr); // unblock thread + thread.join(); - state = State::STOPPED; + state = State::STOPPED; } -void Api::worker() -{ - logger->info("Started worker"); +void Api::worker() { + logger->info("Started worker"); - // Process pending requests - while (running) { - Session *s = pending.pop(); - if (s) { - // Check that the session is still alive - auto it = std::find(sessions.begin(), sessions.end(), s); - if (it != sessions.end()) - s->execute(); - } - } + // Process pending requests + while (running) { + Session *s = pending.pop(); + if (s) { + // Check that the session is still alive + auto it = std::find(sessions.begin(), sessions.end(), s); + if (it != sessions.end()) + s->execute(); + } + } - logger->info("Stopped worker"); + logger->info("Stopped worker"); } diff --git a/lib/api/request.cpp b/lib/api/request.cpp index 2f9b20fda..e8e508ada 100644 --- a/lib/api/request.cpp +++ b/lib/api/request.cpp @@ -5,50 +5,47 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include using namespace villas; using namespace villas::node::api; -void Request::decode() -{ - body = buffer.decode(); - if (!body) - throw BadRequest("Failed to decode request payload"); +void Request::decode() { + body = buffer.decode(); + if (!body) + throw BadRequest("Failed to decode request payload"); } -std::string Request::toString() -{ - return fmt::format("endpoint={}, method={}", factory->getName(), Session::methodToString(method)); +std::string Request::toString() { + return fmt::format("endpoint={}, method={}", factory->getName(), + Session::methodToString(method)); } -Request * RequestFactory::create(Session *s, const std::string &uri, Session::Method meth, unsigned long ct) -{ - s->logger->info("Lookup request handler for: uri={}", uri); +Request *RequestFactory::create(Session *s, const std::string &uri, + Session::Method meth, unsigned long ct) { + s->logger->info("Lookup request handler for: uri={}", uri); - for (auto *rf : plugin::registry->lookup()) { - std::smatch mr; - if (not rf->match(uri, mr)) - continue; + for (auto *rf : plugin::registry->lookup()) { + std::smatch mr; + if (not rf->match(uri, mr)) + continue; - auto *p = rf->make(s); + auto *p = rf->make(s); - for (auto m : mr) - p->matches.push_back(m.str()); + for (auto m : mr) + p->matches.push_back(m.str()); - p->factory = rf; - p->method = meth; - p->contentLength = ct; + p->factory = rf; + p->method = meth; + p->contentLength = ct; - p->prepare(); + p->prepare(); - return p; - } + return p; + } - throw BadRequest("Unknown API request", "{ s: s, s: s }", - "uri", uri.c_str(), - "method", Session::methodToString(meth).c_str() - ); + throw BadRequest("Unknown API request", "{ s: s, s: s }", "uri", uri.c_str(), + "method", Session::methodToString(meth).c_str()); } diff --git a/lib/api/requests/capabiltities.cpp b/lib/api/requests/capabiltities.cpp index 68c30346b..a26048e35 100644 --- a/lib/api/requests/capabiltities.cpp +++ b/lib/api/requests/capabiltities.cpp @@ -16,27 +16,26 @@ namespace api { class CapabilitiesRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Capabilities endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Capabilities endpoint does not accept any body data"); - auto *json_capabilities = getCapabilities(); + auto *json_capabilities = getCapabilities(); - return new JsonResponse(session, HTTP_STATUS_OK, json_capabilities); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_capabilities); + } }; // Register API request static char n[] = "capabilities"; static char r[] = "/capabilities"; -static char d[] = "get capabiltities and details about this VILLASnode instance"; +static char d[] = + "get capabiltities and details about this VILLASnode instance"; static RequestPlugin p; } // namespace api diff --git a/lib/api/requests/config.cpp b/lib/api/requests/config.cpp index ae8a76f29..79fed58e9 100644 --- a/lib/api/requests/config.cpp +++ b/lib/api/requests/config.cpp @@ -5,10 +5,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include #include +#include +#include namespace villas { namespace node { @@ -17,25 +17,21 @@ namespace api { class ConfigRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - json_t *json = session->getSuperNode()->getConfig(); + virtual Response *execute() { + json_t *json = session->getSuperNode()->getConfig(); - if (method != Session::Method::GET) - throw InvalidMethod(this); + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Config endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Config endpoint does not accept any body data"); - auto *json_config = json - ? json_incref(json) - : json_object(); + auto *json_config = json ? json_incref(json) : json_object(); - return new JsonResponse(session, HTTP_STATUS_OK, json_config); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_config); + } }; // Register API request diff --git a/lib/api/requests/graph.cpp b/lib/api/requests/graph.cpp index cddb698c3..a8bf96ce9 100644 --- a/lib/api/requests/graph.cpp +++ b/lib/api/requests/graph.cpp @@ -6,12 +6,12 @@ */ extern "C" { - #include +#include } -#include #include #include +#include namespace villas { namespace node { @@ -20,92 +20,90 @@ namespace api { class GraphRequest : public Request { protected: - GVC_t *gvc; + GVC_t *gvc; - std::string layout; - std::string format; + std::string layout; + std::string format; public: - GraphRequest(Session *s) : - Request(s), - gvc(gvContext()), - layout(getQueryArg("layout")) - { - if (layout.empty()) - layout = "neato"; - } + GraphRequest(Session *s) + : Request(s), gvc(gvContext()), layout(getQueryArg("layout")) { + if (layout.empty()) + layout = "neato"; + } - ~GraphRequest() - { - gvFreeContext(gvc); - } + ~GraphRequest() { gvFreeContext(gvc); } - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Status endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Status endpoint does not accept any body data"); - auto *sn = session->getSuperNode(); - auto *graph = sn->getGraph(); + auto *sn = session->getSuperNode(); + auto *graph = sn->getGraph(); - char *data; - unsigned len; + char *data; + unsigned len; - std::list supportedLayouts = { "circo", "dot", "fdp", "neato", "nop", "nop1", "nop2", "osage", "patchwork", "sfdp", "twopi" }; - std::list supportedFormats = { "ps", "eps", "txt", "svg", "svgz", "gif", "png", "jpg", "jpeg", "bmp", "dot", "fig", "json", "pdf" }; + std::list supportedLayouts = { + "circo", "dot", "fdp", "neato", "nop", "nop1", + "nop2", "osage", "patchwork", "sfdp", "twopi"}; + std::list supportedFormats = { + "ps", "eps", "txt", "svg", "svgz", "gif", "png", + "jpg", "jpeg", "bmp", "dot", "fig", "json", "pdf"}; - format = matches[1]; + format = matches[1]; - auto lit = std::find(supportedLayouts.begin(), supportedLayouts.end(), layout); - if (lit == supportedLayouts.end()) - throw BadRequest("Unsupported layout: {}", layout); + auto lit = + std::find(supportedLayouts.begin(), supportedLayouts.end(), layout); + if (lit == supportedLayouts.end()) + throw BadRequest("Unsupported layout: {}", layout); - auto fit = std::find(supportedFormats.begin(), supportedFormats.end(), format); - if (fit == supportedFormats.end()) - throw BadRequest("Unsupported format: {}", format); + auto fit = + std::find(supportedFormats.begin(), supportedFormats.end(), format); + if (fit == supportedFormats.end()) + throw BadRequest("Unsupported format: {}", format); - std::string ct = "text/plain"; - if (format == "svg") - ct = "image/svg+xml"; - else if (format == "eps" || format == "ps") - ct = "application/postscript"; - else if (format == "txt") - ct = "text/plain"; - else if (format == "gif") - ct = "image/gif"; - else if (format == "png") - ct = "image/png"; - else if (format == "jpg" || format == "jpeg") - ct = "image/jpeg"; - else if (format == "bmp") - ct = "image/bmp"; - else if (format == "dot") - ct = "text/vnd.graphviz"; - else if (format == "json") - ct = "application/json"; - else if (format == "pdf") - ct = "application/pdf"; + std::string ct = "text/plain"; + if (format == "svg") + ct = "image/svg+xml"; + else if (format == "eps" || format == "ps") + ct = "application/postscript"; + else if (format == "txt") + ct = "text/plain"; + else if (format == "gif") + ct = "image/gif"; + else if (format == "png") + ct = "image/png"; + else if (format == "jpg" || format == "jpeg") + ct = "image/jpeg"; + else if (format == "bmp") + ct = "image/bmp"; + else if (format == "dot") + ct = "text/vnd.graphviz"; + else if (format == "json") + ct = "application/json"; + else if (format == "pdf") + ct = "application/pdf"; - gvLayout(gvc, graph, layout.c_str()); - gvRenderData(gvc, graph, format.c_str(), &data, &len); + gvLayout(gvc, graph, layout.c_str()); + gvRenderData(gvc, graph, format.c_str(), &data, &len); - auto buf = Buffer(data, len); - auto *resp = new Response(session, HTTP_STATUS_OK, ct, buf); + auto buf = Buffer(data, len); + auto *resp = new Response(session, HTTP_STATUS_OK, ct, buf); - if (format == "svgz") - resp->setHeader("Content-Encoding", "gzip"); + if (format == "svgz") + resp->setHeader("Content-Encoding", "gzip"); #if 0 gvFreeRenderData(data); #endif - gvFreeLayout(gvc, graph); + gvFreeLayout(gvc, graph); - return resp; - } + return resp; + } }; // Register API request diff --git a/lib/api/requests/node.cpp b/lib/api/requests/node.cpp index fd4452359..b66f869ce 100644 --- a/lib/api/requests/node.cpp +++ b/lib/api/requests/node.cpp @@ -9,26 +9,21 @@ using namespace villas::node::api; -void NodeRequest::prepare() -{ - int ret; +void NodeRequest::prepare() { + int ret; - auto &nodes = session->getSuperNode()->getNodes(); + auto &nodes = session->getSuperNode()->getNodes(); - uuid_t uuid; - ret = uuid_parse(matches[1].c_str(), uuid); - if (ret) { - node = nodes.lookup(matches[1]); - if (!node) - throw BadRequest("Unknown node", "{ s: s }", - "node", matches[1].c_str() - ); - } - else { - node = nodes.lookup(uuid); - if (!node) - throw BadRequest("No node found with with matching UUID", "{ s: s }", - "uuid", matches[1].c_str() - ); - } + uuid_t uuid; + ret = uuid_parse(matches[1].c_str(), uuid); + if (ret) { + node = nodes.lookup(matches[1]); + if (!node) + throw BadRequest("Unknown node", "{ s: s }", "node", matches[1].c_str()); + } else { + node = nodes.lookup(uuid); + if (!node) + throw BadRequest("No node found with with matching UUID", "{ s: s }", + "uuid", matches[1].c_str()); + } } diff --git a/lib/api/requests/node_action.cpp b/lib/api/requests/node_action.cpp index d3d811601..f7c1718d0 100644 --- a/lib/api/requests/node_action.cpp +++ b/lib/api/requests/node_action.cpp @@ -7,42 +7,36 @@ #include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include namespace villas { namespace node { namespace api { -template -class NodeActionRequest : public NodeRequest { +template class NodeActionRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Node endpoints do not accept any body data"); + if (body != nullptr) + throw BadRequest("Node endpoints do not accept any body data"); - int ret = (node->*func)(); - if (ret) - throw BadRequest("Failed to execute action", "{ s: d }", - "ret", ret - ); - - return new Response(session, HTTP_STATUS_OK); - } + int ret = (node->*func)(); + if (ret) + throw BadRequest("Failed to execute action", "{ s: d }", "ret", ret); + return new Response(session, HTTP_STATUS_OK); + } }; // Register API requests diff --git a/lib/api/requests/node_file.cpp b/lib/api/requests/node_file.cpp index 200c61189..124a8bd31 100644 --- a/lib/api/requests/node_file.cpp +++ b/lib/api/requests/node_file.cpp @@ -5,14 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include #include +#include +#include +#include #include #include -#include namespace villas { namespace node { @@ -21,32 +21,29 @@ namespace api { class FileRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET && method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET && method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("File endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("File endpoint does not accept any body data"); - NodeFactory *nf = plugin::registry->lookup("file"); + NodeFactory *nf = plugin::registry->lookup("file"); - if (node->getFactory() != nf) - throw BadRequest("This node is not a file node", "{ s: s }", - "type", node->getFactory()->getName() - ); + if (node->getFactory() != nf) + throw BadRequest("This node is not a file node", "{ s: s }", "type", + node->getFactory()->getName()); - auto *nc = dynamic_cast(node); - auto *f = nc->getData(); + auto *nc = dynamic_cast(node); + auto *f = nc->getData(); - if (matches[2] == "rewind") - rewind(f->stream_in); + if (matches[2] == "rewind") + rewind(f->stream_in); - return new Response(session, HTTP_STATUS_OK); - } + return new Response(session, HTTP_STATUS_OK); + } }; // Register API request diff --git a/lib/api/requests/node_info.cpp b/lib/api/requests/node_info.cpp index bd5ca0c27..f13bdc432 100644 --- a/lib/api/requests/node_info.cpp +++ b/lib/api/requests/node_info.cpp @@ -7,13 +7,13 @@ #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -22,28 +22,26 @@ namespace api { class NodeInfoRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Nodes endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Nodes endpoint does not accept any body data"); - auto *json_node = node->toJson(); + auto *json_node = node->toJson(); - auto sigs = node->getOutputSignals(); - if (sigs) { - auto *json_out = json_object_get(json_node, "out"); - if (json_out) - json_object_set_new(json_out, "signals", sigs->toJson()); - } + auto sigs = node->getOutputSignals(); + if (sigs) { + auto *json_out = json_object_get(json_node, "out"); + if (json_out) + json_object_set_new(json_out, "signals", sigs->toJson()); + } - return new JsonResponse(session, HTTP_STATUS_OK, json_node); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_node); + } }; // Register API request diff --git a/lib/api/requests/node_stats.cpp b/lib/api/requests/node_stats.cpp index 271764d67..8c12906f8 100644 --- a/lib/api/requests/node_stats.cpp +++ b/lib/api/requests/node_stats.cpp @@ -7,14 +7,14 @@ #include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include namespace villas { namespace node { @@ -23,22 +23,22 @@ namespace api { class StatsRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Stats endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Stats endpoint does not accept any body data"); - if (node->getStats() == nullptr) - throw BadRequest("The statistics collection for this node is not enabled"); + if (node->getStats() == nullptr) + throw BadRequest( + "The statistics collection for this node is not enabled"); - return new JsonResponse(session, HTTP_STATUS_OK, node->getStats()->toJson()); - } + return new JsonResponse(session, HTTP_STATUS_OK, + node->getStats()->toJson()); + } }; // Register API requests diff --git a/lib/api/requests/node_stats_reset.cpp b/lib/api/requests/node_stats_reset.cpp index 778c15e44..27ee85ce1 100644 --- a/lib/api/requests/node_stats_reset.cpp +++ b/lib/api/requests/node_stats_reset.cpp @@ -7,40 +7,39 @@ #include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include namespace villas { namespace node { namespace api { -class StatsRequest : public NodeRequest { +class StatsRequest : public NodeRequest { public: - using NodeRequest::NodeRequest; + using NodeRequest::NodeRequest; - virtual - Response * execute() - { - if (method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Stats endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Stats endpoint does not accept any body data"); - if (node->getStats() == nullptr) - throw BadRequest("The statistics collection for this node is not enabled"); + if (node->getStats() == nullptr) + throw BadRequest( + "The statistics collection for this node is not enabled"); - node->getStats()->reset(); + node->getStats()->reset(); - return new Response(session, HTTP_STATUS_OK); - } + return new Response(session, HTTP_STATUS_OK); + } }; // Register API requests diff --git a/lib/api/requests/nodes.cpp b/lib/api/requests/nodes.cpp index b73230639..4cf4ebb6f 100644 --- a/lib/api/requests/nodes.cpp +++ b/lib/api/requests/nodes.cpp @@ -7,13 +7,13 @@ #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -22,21 +22,19 @@ namespace api { class NodesRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Nodes endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Nodes endpoint does not accept any body data"); - json_t *json_nodes = session->getSuperNode()->getNodes().toJson(); + json_t *json_nodes = session->getSuperNode()->getNodes().toJson(); - return new JsonResponse(session, HTTP_STATUS_OK, json_nodes); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_nodes); + } }; // Register API request diff --git a/lib/api/requests/path.cpp b/lib/api/requests/path.cpp index f5dc2cd74..aae5cddb4 100644 --- a/lib/api/requests/path.cpp +++ b/lib/api/requests/path.cpp @@ -10,21 +10,17 @@ using namespace villas::node::api; -void PathRequest::prepare() -{ - int ret; - uuid_t uuid; +void PathRequest::prepare() { + int ret; + uuid_t uuid; - ret = uuid_parse(matches[1].c_str(), uuid); - if (ret) - throw BadRequest("Invalid UUID", "{ s: s }", - "uuid", matches[1].c_str() - ); + ret = uuid_parse(matches[1].c_str(), uuid); + if (ret) + throw BadRequest("Invalid UUID", "{ s: s }", "uuid", matches[1].c_str()); - auto paths = session->getSuperNode()->getPaths(); - path = paths.lookup(uuid); - if (!path) - throw BadRequest("No path found with with matching UUID", "{ s: s }", - "uuid", matches[1].c_str() - ); + auto paths = session->getSuperNode()->getPaths(); + path = paths.lookup(uuid); + if (!path) + throw BadRequest("No path found with with matching UUID", "{ s: s }", + "uuid", matches[1].c_str()); } diff --git a/lib/api/requests/path_action.cpp b/lib/api/requests/path_action.cpp index 020ab91b1..b48ff9d66 100644 --- a/lib/api/requests/path_action.cpp +++ b/lib/api/requests/path_action.cpp @@ -7,38 +7,34 @@ #include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include namespace villas { namespace node { namespace api { -template -class PathActionRequest : public PathRequest { +template class PathActionRequest : public PathRequest { public: - using PathRequest::PathRequest; + using PathRequest::PathRequest; - virtual - Response * execute() - { - if (method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Path endpoints do not accept any body data"); + if (body != nullptr) + throw BadRequest("Path endpoints do not accept any body data"); - (path->*func)(); - - return new Response(session, HTTP_STATUS_OK); - } + (path->*func)(); + return new Response(session, HTTP_STATUS_OK); + } }; // Register API requests diff --git a/lib/api/requests/path_info.cpp b/lib/api/requests/path_info.cpp index 9b834d180..57478d710 100644 --- a/lib/api/requests/path_info.cpp +++ b/lib/api/requests/path_info.cpp @@ -7,13 +7,13 @@ #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -22,19 +22,17 @@ namespace api { class PathInfoRequest : public PathRequest { public: - using PathRequest::PathRequest; + using PathRequest::PathRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Endpoint does not accept any body data"); - return new JsonResponse(session, HTTP_STATUS_OK, path->toJson()); - } + return new JsonResponse(session, HTTP_STATUS_OK, path->toJson()); + } }; // Register API request diff --git a/lib/api/requests/paths.cpp b/lib/api/requests/paths.cpp index 8043d8dad..da37b4bbb 100644 --- a/lib/api/requests/paths.cpp +++ b/lib/api/requests/paths.cpp @@ -7,13 +7,13 @@ #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include namespace villas { namespace node { @@ -22,21 +22,19 @@ namespace api { class PathsRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Paths endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Paths endpoint does not accept any body data"); - json_t *json_paths = session->getSuperNode()->getPaths().toJson(); + json_t *json_paths = session->getSuperNode()->getPaths().toJson(); - return new JsonResponse(session, HTTP_STATUS_OK, json_paths); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_paths); + } }; // Register API request diff --git a/lib/api/requests/restart.cpp b/lib/api/requests/restart.cpp index 9f481c26b..f470bbda4 100644 --- a/lib/api/requests/restart.cpp +++ b/lib/api/requests/restart.cpp @@ -5,13 +5,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include namespace villas { namespace node { @@ -20,103 +20,92 @@ namespace api { class RestartRequest : public Request { protected: - static - std::string configUri; + static std::string configUri; - static - void handler() - { - int ret; - const char *cfg = !configUri.empty() - ? configUri.c_str() - : nullptr; + static void handler() { + int ret; + const char *cfg = !configUri.empty() ? configUri.c_str() : nullptr; - const char *argv[] = { "villas-node", cfg, nullptr }; + const char *argv[] = {"villas-node", cfg, nullptr}; - Logger logger = logging.get("api:restart"); + Logger logger = logging.get("api:restart"); - if (cfg) - logger->info("Restarting instance: config={}", cfg); - else - logger->info("Restarting instance"); + if (cfg) + logger->info("Restarting instance: config={}", cfg); + else + logger->info("Restarting instance"); - ret = execvp("/proc/self/exe", (char **) argv); - if (ret) - throw SystemError("Failed to restart"); - } + ret = execvp("/proc/self/exe", (char **)argv); + if (ret) + throw SystemError("Failed to restart"); + } public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - int ret; - json_error_t err; + virtual Response *execute() { + int ret; + json_error_t err; - if (method != Session::Method::POST) - throw InvalidMethod(this); + if (method != Session::Method::POST) + throw InvalidMethod(this); - json_t *json_config = nullptr; + json_t *json_config = nullptr; - if (body) { - ret = json_unpack_ex(body, &err, 0, "{ s?: o }", - "config", &json_config - ); - if (ret < 0) - throw BadRequest("Failed to parse request body"); - } + if (body) { + ret = json_unpack_ex(body, &err, 0, "{ s?: o }", "config", &json_config); + if (ret < 0) + throw BadRequest("Failed to parse request body"); + } - if (json_config) { - if (json_is_string(json_config)) - configUri = json_string_value(json_config); - else if (json_is_object(json_config)) { - char configUriBuf[] = "villas-node.json.XXXXXX"; - int configFd = mkstemp(configUriBuf); + if (json_config) { + if (json_is_string(json_config)) + configUri = json_string_value(json_config); + else if (json_is_object(json_config)) { + char configUriBuf[] = "villas-node.json.XXXXXX"; + int configFd = mkstemp(configUriBuf); - FILE *configFile = fdopen(configFd, "w+"); + FILE *configFile = fdopen(configFd, "w+"); - ret = json_dumpf(json_config, configFile, JSON_INDENT(4)); - if (ret < 0) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to create temporary config file"); + ret = json_dumpf(json_config, configFile, JSON_INDENT(4)); + if (ret < 0) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to create temporary config file"); - fclose(configFile); - configUri = configUriBuf; - } - else if (json_config != nullptr) - throw BadRequest("Parameter 'config' must be either a URL (string) or a configuration (object)"); - } - else // If no config is provided via request, we will use the previous one - configUri = session->getSuperNode()->getConfigUri(); + fclose(configFile); + configUri = configUriBuf; + } else if (json_config != nullptr) + throw BadRequest("Parameter 'config' must be either a URL (string) or " + "a configuration (object)"); + } else // If no config is provided via request, we will use the previous one + configUri = session->getSuperNode()->getConfigUri(); - logger->info("Restarting to {}", configUri); + logger->info("Restarting to {}", configUri); - // Increment API restart counter - char *scnt = getenv("VILLAS_API_RESTART_COUNT"); - int cnt = scnt ? atoi(scnt) : 0; - char buf[32]; - snprintf(buf, sizeof(buf), "%d", cnt + 1); + // Increment API restart counter + char *scnt = getenv("VILLAS_API_RESTART_COUNT"); + int cnt = scnt ? atoi(scnt) : 0; + char buf[32]; + snprintf(buf, sizeof(buf), "%d", cnt + 1); - // We pass some env variables to the new process - setenv("VILLAS_API_RESTART_COUNT", buf, 1); + // We pass some env variables to the new process + setenv("VILLAS_API_RESTART_COUNT", buf, 1); - auto *json_response = json_pack("{ s: i, s: o }", - "restarts", cnt, - "config", configUri.empty() - ? json_null() - : json_string(configUri.c_str()) - ); + auto *json_response = json_pack( + "{ s: i, s: o }", "restarts", cnt, "config", + configUri.empty() ? json_null() : json_string(configUri.c_str())); - // Register exit handler - ret = atexit(handler); - if (ret) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to restart VILLASnode instance"); + // Register exit handler + ret = atexit(handler); + if (ret) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to restart VILLASnode instance"); - // Properly terminate current instance - utils::killme(SIGTERM); + // Properly terminate current instance + utils::killme(SIGTERM); - return new JsonResponse(session, HTTP_STATUS_OK, json_response); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_response); + } }; std::string RestartRequest::configUri; diff --git a/lib/api/requests/shutdown.cpp b/lib/api/requests/shutdown.cpp index c7869f4e4..ebfad3e29 100644 --- a/lib/api/requests/shutdown.cpp +++ b/lib/api/requests/shutdown.cpp @@ -7,9 +7,9 @@ #include -#include #include #include +#include namespace villas { namespace node { @@ -18,21 +18,19 @@ namespace api { class ShutdownRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - if (method != Session::Method::POST) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::POST) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Shutdown endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Shutdown endpoint does not accept any body data"); - utils::killme(SIGTERM); + utils::killme(SIGTERM); - return new Response(session, HTTP_STATUS_OK); - } + return new Response(session, HTTP_STATUS_OK); + } }; // Register API request diff --git a/lib/api/requests/status.cpp b/lib/api/requests/status.cpp index a1895eef4..1ccaff634 100644 --- a/lib/api/requests/status.cpp +++ b/lib/api/requests/status.cpp @@ -5,14 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include -#include -#include #include #include +#include +#include namespace villas { namespace node { @@ -21,92 +21,79 @@ namespace api { class StatusRequest : public Request { public: - using Request::Request; + using Request::Request; - virtual - Response * execute() - { - int ret; + virtual Response *execute() { + int ret; - if (method != Session::Method::GET) - throw InvalidMethod(this); + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("Status endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("Status endpoint does not accept any body data"); - auto *sn = session->getSuperNode(); + auto *sn = session->getSuperNode(); - struct utsname uts; - struct sysinfo sinfo; - char hname[128]; + struct utsname uts; + struct sysinfo sinfo; + char hname[128]; - auto now = time_now(); - auto started = sn->getStartTime(); + auto now = time_now(); + auto started = sn->getStartTime(); - ret = gethostname(hname, sizeof(hname)); - if (ret) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to get system hostname"); + ret = gethostname(hname, sizeof(hname)); + if (ret) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to get system hostname"); - ret = uname(&uts); - if (ret) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to get kernel information"); + ret = uname(&uts); + if (ret) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to get kernel information"); - ret = sysinfo(&sinfo); - if (ret) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to get system information"); + ret = sysinfo(&sinfo); + if (ret) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to get system information"); - float f_load = 1.f / (1 << SI_LOAD_SHIFT); + float f_load = 1.f / (1 << SI_LOAD_SHIFT); - tzset(); + tzset(); - json_error_t err; - json_t *json_status = json_pack_ex(&err, 0, "{ s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: f, s: f, s: { s: s, s: I, s: b }, s: { s: s, s: s, s: s, s: s, s: s, s: s}, s: { s: i, s: i, s: I, s: I, s: [ f, f, f ], s: { s: I, s, I, s: I, s: I }, s: { s: I, s: I }, s: { s: I, s: I } } }", - "state", stateToString(sn->getState()).c_str(), - "version", PROJECT_VERSION_STR, - "release", PROJECT_RELEASE, - "build_id", PROJECT_BUILD_ID, - "build_date", PROJECT_BUILD_DATE, - "hostname", hname, - "uuid", uuid::toString(sn->getUuid()).c_str(), - "time_now", time_to_double(&now), - "time_started", time_to_double(&started), - "timezone", - "name", tzname[daylight], - "offset", (json_int_t) timezone, - "dst", daylight, - "kernel", - "sysname", uts.sysname, - "nodename", uts.nodename, - "release", uts.release, - "version", uts.version, - "machine", uts.machine, - "domainname", uts.domainname, - "system", - "cores_configured", get_nprocs_conf(), - "cores", get_nprocs(), - "processes", (json_int_t) sinfo.procs, - "uptime", (json_int_t) sinfo.uptime, - "load", - f_load * sinfo.loads[0], - f_load * sinfo.loads[1], - f_load * sinfo.loads[2], - "ram", - "total", (json_int_t) (sinfo.totalram * sinfo.mem_unit), - "free", (json_int_t) (sinfo.freeram * sinfo.mem_unit), - "shared", (json_int_t) (sinfo.sharedram * sinfo.mem_unit), - "buffer", (json_int_t) (sinfo.bufferram * sinfo.mem_unit), - "swap", - "total", (json_int_t) (sinfo.totalswap * sinfo.mem_unit), - "free", (json_int_t) (sinfo.freeswap * sinfo.mem_unit), - "highmem", - "total", (json_int_t) (sinfo.totalhigh * sinfo.mem_unit), - "free", (json_int_t) (sinfo.freehigh * sinfo.mem_unit) - ); - if (!json_status) - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to prepare response: {}", err.text); + json_error_t err; + json_t *json_status = json_pack_ex( + &err, 0, + "{ s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: f, s: f, s: { s: s, s: " + "I, s: b }, s: { s: s, s: s, s: s, s: s, s: s, s: s}, s: { s: i, s: i, " + "s: I, s: I, s: [ f, f, f ], s: { s: I, s, I, s: I, s: I }, s: { s: I, " + "s: I }, s: { s: I, s: I } } }", + "state", stateToString(sn->getState()).c_str(), "version", + PROJECT_VERSION_STR, "release", PROJECT_RELEASE, "build_id", + PROJECT_BUILD_ID, "build_date", PROJECT_BUILD_DATE, "hostname", hname, + "uuid", uuid::toString(sn->getUuid()).c_str(), "time_now", + time_to_double(&now), "time_started", time_to_double(&started), + "timezone", "name", tzname[daylight], "offset", (json_int_t)timezone, + "dst", daylight, "kernel", "sysname", uts.sysname, "nodename", + uts.nodename, "release", uts.release, "version", uts.version, "machine", + uts.machine, "domainname", uts.domainname, "system", "cores_configured", + get_nprocs_conf(), "cores", get_nprocs(), "processes", + (json_int_t)sinfo.procs, "uptime", (json_int_t)sinfo.uptime, "load", + f_load * sinfo.loads[0], f_load * sinfo.loads[1], + f_load * sinfo.loads[2], "ram", "total", + (json_int_t)(sinfo.totalram * sinfo.mem_unit), "free", + (json_int_t)(sinfo.freeram * sinfo.mem_unit), "shared", + (json_int_t)(sinfo.sharedram * sinfo.mem_unit), "buffer", + (json_int_t)(sinfo.bufferram * sinfo.mem_unit), "swap", "total", + (json_int_t)(sinfo.totalswap * sinfo.mem_unit), "free", + (json_int_t)(sinfo.freeswap * sinfo.mem_unit), "highmem", "total", + (json_int_t)(sinfo.totalhigh * sinfo.mem_unit), "free", + (json_int_t)(sinfo.freehigh * sinfo.mem_unit)); + if (!json_status) + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, + "Failed to prepare response: {}", err.text); - return new JsonResponse(session, HTTP_STATUS_OK, json_status); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_status); + } }; // Register API request diff --git a/lib/api/requests/universal.cpp b/lib/api/requests/universal.cpp index 9ae25c389..d3083cef5 100644 --- a/lib/api/requests/universal.cpp +++ b/lib/api/requests/universal.cpp @@ -11,11 +11,11 @@ using namespace villas::node; using namespace villas::node::api; using namespace villas::node::api::universal; -void UniversalRequest::prepare() -{ - NodeRequest::prepare(); +void UniversalRequest::prepare() { + NodeRequest::prepare(); - api_node = dynamic_cast(node); - if (!api_node) - throw BadRequest("Node {} is not an univeral API node!", node->getNameShort()); + api_node = dynamic_cast(node); + if (!api_node) + throw BadRequest("Node {} is not an univeral API node!", + node->getNameShort()); } diff --git a/lib/api/requests/universal/channel.cpp b/lib/api/requests/universal/channel.cpp index 94e0851fa..b27216124 100644 --- a/lib/api/requests/universal/channel.cpp +++ b/lib/api/requests/universal/channel.cpp @@ -16,145 +16,137 @@ namespace universal { class ChannelRequest : public UniversalRequest { public: - using UniversalRequest::UniversalRequest; + using UniversalRequest::UniversalRequest; - Response * executeGet(const std::string &signalName, PayloadType payload) - { - if (body != nullptr) - throw BadRequest("This endpoint does not accept any body data"); + Response *executeGet(const std::string &signalName, PayloadType payload) { + if (body != nullptr) + throw BadRequest("This endpoint does not accept any body data"); - pthread_mutex_lock(&api_node->write.mutex); + pthread_mutex_lock(&api_node->write.mutex); - auto *smp = api_node->write.sample; - if (!smp) { - pthread_mutex_unlock(&api_node->write.mutex); - throw Error(HTTP_STATUS_NOT_FOUND, "No data available"); - } + auto *smp = api_node->write.sample; + if (!smp) { + pthread_mutex_unlock(&api_node->write.mutex); + throw Error(HTTP_STATUS_NOT_FOUND, "No data available"); + } - auto idx = smp->signals->getIndexByName(signalName); - if (idx < 0) { - pthread_mutex_unlock(&api_node->write.mutex); - throw Error(HTTP_STATUS_NOT_FOUND, "Unknown signal id: {}", signalName); - } + auto idx = smp->signals->getIndexByName(signalName); + if (idx < 0) { + pthread_mutex_unlock(&api_node->write.mutex); + throw Error(HTTP_STATUS_NOT_FOUND, "Unknown signal id: {}", signalName); + } - auto sig = smp->signals->getByIndex(idx); - auto ch = api_node->write.channels.at(idx); + auto sig = smp->signals->getByIndex(idx); + auto ch = api_node->write.channels.at(idx); - if (payload != ch->payload) - throw BadRequest("Mismatching payload type"); + if (payload != ch->payload) + throw BadRequest("Mismatching payload type"); - auto *json_signal = json_pack("{ s: f, s: o, s: s, s: s, s: s }", - "timestamp", time_to_double(&smp->ts.origin), - "value", smp->data[idx].toJson(sig->type), - "validity", "unknown", - "source", "unknown", - "timesource", "unknown" - ); + auto *json_signal = + json_pack("{ s: f, s: o, s: s, s: s, s: s }", "timestamp", + time_to_double(&smp->ts.origin), "value", + smp->data[idx].toJson(sig->type), "validity", "unknown", + "source", "unknown", "timesource", "unknown"); - if (smp->length <= (unsigned) idx) - smp->length = idx + 1; + if (smp->length <= (unsigned)idx) + smp->length = idx + 1; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN | (int)SampleFlags::HAS_DATA; - pthread_mutex_unlock(&api_node->write.mutex); + pthread_mutex_unlock(&api_node->write.mutex); - return new JsonResponse(session, HTTP_STATUS_OK, json_signal); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_signal); + } - Response * executePut(const std::string &signalName, PayloadType payload) - { - int ret; + Response *executePut(const std::string &signalName, PayloadType payload) { + int ret; - pthread_mutex_lock(&api_node->read.mutex); + pthread_mutex_lock(&api_node->read.mutex); - auto *smp = api_node->read.sample; - if (!smp) { - pthread_mutex_unlock(&api_node->read.mutex); - throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Not initialized yet"); - } + auto *smp = api_node->read.sample; + if (!smp) { + pthread_mutex_unlock(&api_node->read.mutex); + throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Not initialized yet"); + } - auto idx = smp->signals->getIndexByName(signalName); - if (idx < 0) { - pthread_mutex_unlock(&api_node->read.mutex); - throw BadRequest("Unknown signal id: {}", signalName); - } + auto idx = smp->signals->getIndexByName(signalName); + if (idx < 0) { + pthread_mutex_unlock(&api_node->read.mutex); + throw BadRequest("Unknown signal id: {}", signalName); + } - auto sig = smp->signals->getByIndex(idx); - auto ch = api_node->read.channels.at(idx); + auto sig = smp->signals->getByIndex(idx); + auto ch = api_node->read.channels.at(idx); - if (payload != ch->payload) - throw BadRequest("Mismatching payload type"); + if (payload != ch->payload) + throw BadRequest("Mismatching payload type"); - double timestamp = 0; - json_t *json_value; - const char *validity = nullptr; - const char *source = nullptr; - const char *timesource = nullptr; + double timestamp = 0; + json_t *json_value; + const char *validity = nullptr; + const char *source = nullptr; + const char *timesource = nullptr; - json_error_t err; - ret = json_unpack_ex(body, &err, 0, "{ s: F, s: o, s?: s, s?: s, s?: s }", - "timestamp", ×tamp, - "value", &json_value, - "validity", &validity, - "timesource", ×ource, - "source", &source - ); - if (ret) { - pthread_mutex_unlock(&api_node->read.mutex); - throw BadRequest("Malformed body: {}", err.text); - } + json_error_t err; + ret = json_unpack_ex(body, &err, 0, "{ s: F, s: o, s?: s, s?: s, s?: s }", + "timestamp", ×tamp, "value", &json_value, + "validity", &validity, "timesource", ×ource, + "source", &source); + if (ret) { + pthread_mutex_unlock(&api_node->read.mutex); + throw BadRequest("Malformed body: {}", err.text); + } - if (validity) - logger->warn("Attribute 'validity' is not supported by VILLASnode"); + if (validity) + logger->warn("Attribute 'validity' is not supported by VILLASnode"); - if (source) - logger->warn("Attribute 'source' is not supported by VILLASnode"); + if (source) + logger->warn("Attribute 'source' is not supported by VILLASnode"); - if (timesource) - logger->warn("Attribute 'timesource' is not supported by VILLASnode"); + if (timesource) + logger->warn("Attribute 'timesource' is not supported by VILLASnode"); - ret = smp->data[idx].parseJson(sig->type, json_value); - if (ret) { - pthread_mutex_unlock(&api_node->read.mutex); - throw BadRequest("Malformed value"); - } + ret = smp->data[idx].parseJson(sig->type, json_value); + if (ret) { + pthread_mutex_unlock(&api_node->read.mutex); + throw BadRequest("Malformed value"); + } - smp->ts.origin = time_from_double(timestamp); + smp->ts.origin = time_from_double(timestamp); - pthread_cond_signal(&api_node->read.cv); - pthread_mutex_unlock(&api_node->read.mutex); + pthread_cond_signal(&api_node->read.cv); + pthread_mutex_unlock(&api_node->read.mutex); - return new JsonResponse(session, HTTP_STATUS_OK, json_object()); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_object()); + } - virtual - Response * execute() - { - auto const &signalName = matches[2]; - auto const &subResource = matches[3]; + virtual Response *execute() { + auto const &signalName = matches[2]; + auto const &subResource = matches[3]; - PayloadType payload; - if (subResource == "event") - payload = PayloadType::EVENTS; - else if (subResource == "sample") - payload = PayloadType::EVENTS; - else - throw BadRequest("Unsupported sub-resource: {}", subResource); + PayloadType payload; + if (subResource == "event") + payload = PayloadType::EVENTS; + else if (subResource == "sample") + payload = PayloadType::EVENTS; + else + throw BadRequest("Unsupported sub-resource: {}", subResource); - switch (method) { - case Session::Method::GET: - return executeGet(signalName, payload); - case Session::Method::PUT: - return executePut(signalName, payload); - default: - throw InvalidMethod(this); - } - } + switch (method) { + case Session::Method::GET: + return executeGet(signalName, payload); + case Session::Method::PUT: + return executePut(signalName, payload); + default: + throw InvalidMethod(this); + } + } }; // Register API requests static char n[] = "universal/channel/sample"; -static char r[] = "/universal/(" RE_NODE_NAME ")/channel/([a-z0-9_-]+)/(sample|event)"; +static char r[] = + "/universal/(" RE_NODE_NAME ")/channel/([a-z0-9_-]+)/(sample|event)"; static char d[] = "retrieve or send samples via universal data-exchange API"; static RequestPlugin p; diff --git a/lib/api/requests/universal/channels.cpp b/lib/api/requests/universal/channels.cpp index ae7a720a1..139724822 100644 --- a/lib/api/requests/universal/channels.cpp +++ b/lib/api/requests/universal/channels.cpp @@ -5,9 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include namespace villas { namespace node { @@ -16,37 +16,39 @@ namespace universal { class SignalsRequest : public UniversalRequest { public: - using UniversalRequest::UniversalRequest; + using UniversalRequest::UniversalRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("This endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("This endpoint does not accept any body data"); - auto *json_sigs = json_array(); + auto *json_sigs = json_array(); - for (size_t i = 0; i < MIN(api_node->getOutputSignals()->size(), api_node->write.channels.size()); i++) { - auto sig = api_node->getOutputSignals()->at(i); - auto ch = api_node->write.channels.at(i); - auto *json_sig = ch->toJson(sig); + for (size_t i = 0; i < MIN(api_node->getOutputSignals()->size(), + api_node->write.channels.size()); + i++) { + auto sig = api_node->getOutputSignals()->at(i); + auto ch = api_node->write.channels.at(i); + auto *json_sig = ch->toJson(sig); - json_array_append(json_sigs, json_sig); - } + json_array_append(json_sigs, json_sig); + } - for (size_t i = 0; i < MIN(api_node->getInputSignals()->size(), api_node->read.channels.size()); i++) { - auto sig = api_node->getInputSignals()->at(i); - auto ch = api_node->read.channels.at(i); - auto *json_sig = ch->toJson(sig); + for (size_t i = 0; i < MIN(api_node->getInputSignals()->size(), + api_node->read.channels.size()); + i++) { + auto sig = api_node->getInputSignals()->at(i); + auto ch = api_node->read.channels.at(i); + auto *json_sig = ch->toJson(sig); - json_array_append(json_sigs, json_sig); - } + json_array_append(json_sigs, json_sig); + } - return new JsonResponse(session, HTTP_STATUS_OK, json_sigs); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_sigs); + } }; // Register API requests diff --git a/lib/api/requests/universal/info.cpp b/lib/api/requests/universal/info.cpp index 6ec3b58bd..9101f131a 100644 --- a/lib/api/requests/universal/info.cpp +++ b/lib/api/requests/universal/info.cpp @@ -5,10 +5,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include +#include namespace villas { namespace node { @@ -17,29 +17,24 @@ namespace universal { class InfoRequest : public UniversalRequest { public: - using UniversalRequest::UniversalRequest; + using UniversalRequest::UniversalRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("This endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("This endpoint does not accept any body data"); - auto *info = json_pack("{ s: s, s: s, s: { s: s, s: s, s: s } }", - "id", node->getNameShort().c_str(), - "uuid", uuid::toString(node->getUuid()).c_str(), + auto *info = json_pack("{ s: s, s: s, s: { s: s, s: s, s: s } }", "id", + node->getNameShort().c_str(), "uuid", + uuid::toString(node->getUuid()).c_str(), - "transport", - "type", "villas", - "version", PROJECT_VERSION, - "build", PROJECT_BUILD_ID - ); + "transport", "type", "villas", "version", + PROJECT_VERSION, "build", PROJECT_BUILD_ID); - return new JsonResponse(session, HTTP_STATUS_OK, info); - } + return new JsonResponse(session, HTTP_STATUS_OK, info); + } }; // Register API requests diff --git a/lib/api/requests/universal/status.cpp b/lib/api/requests/universal/status.cpp index dc4d43130..d77aae217 100644 --- a/lib/api/requests/universal/status.cpp +++ b/lib/api/requests/universal/status.cpp @@ -16,24 +16,22 @@ namespace universal { class StatusRequest : public UniversalRequest { public: - using UniversalRequest::UniversalRequest; + using UniversalRequest::UniversalRequest; - virtual - Response * execute() - { - if (method != Session::Method::GET) - throw InvalidMethod(this); + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); - if (body != nullptr) - throw BadRequest("This endpoint does not accept any body data"); + if (body != nullptr) + throw BadRequest("This endpoint does not accept any body data"); - auto *json_response = json_pack("{ s: s }", - // TODO: Add connectivity check or heuristic here. - "connected", "unknown" - ); + auto *json_response = + json_pack("{ s: s }", + // TODO: Add connectivity check or heuristic here. + "connected", "unknown"); - return new JsonResponse(session, HTTP_STATUS_OK, json_response); - } + return new JsonResponse(session, HTTP_STATUS_OK, json_response); + } }; // Register API requests diff --git a/lib/api/response.cpp b/lib/api/response.cpp index 8048a0890..62914191e 100644 --- a/lib/api/response.cpp +++ b/lib/api/response.cpp @@ -5,79 +5,68 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include using namespace villas::node::api; -Response::Response(Session *s, int c, const std::string &ct, const Buffer &b) : - session(s), - logger(logging.get("api:response")), - buffer(b), - code(c), - contentType(ct), - headers{ - { "Server:", HTTP_USER_AGENT }, - { "Access-Control-Allow-Origin:", "*" }, - { "Access-Control-Allow-Methods:", "GET, POST, OPTIONS" }, - { "Access-Control-Allow-Headers:", "Content-Type" }, - { "Access-Control-Max-Age:", "86400" } - } -{ } +Response::Response(Session *s, int c, const std::string &ct, const Buffer &b) + : session(s), logger(logging.get("api:response")), buffer(b), code(c), + contentType(ct), + headers{{"Server:", HTTP_USER_AGENT}, + {"Access-Control-Allow-Origin:", "*"}, + {"Access-Control-Allow-Methods:", "GET, POST, OPTIONS"}, + {"Access-Control-Allow-Headers:", "Content-Type"}, + {"Access-Control-Max-Age:", "86400"}} {} -int Response::writeBody(struct lws *wsi) -{ - int ret; +int Response::writeBody(struct lws *wsi) { + int ret; - ret = lws_write(wsi, (unsigned char *) buffer.data(), buffer.size(), LWS_WRITE_HTTP_FINAL); - if (ret < 0) - return -1; + ret = lws_write(wsi, (unsigned char *)buffer.data(), buffer.size(), + LWS_WRITE_HTTP_FINAL); + if (ret < 0) + return -1; - return 1; + return 1; } -int Response::writeHeaders(struct lws *wsi) -{ - int ret; - uint8_t headerBuffer[2048], *p = headerBuffer, *end = &headerBuffer[sizeof(headerBuffer) - 1]; +int Response::writeHeaders(struct lws *wsi) { + int ret; + uint8_t headerBuffer[2048], *p = headerBuffer, + *end = &headerBuffer[sizeof(headerBuffer) - 1]; - // We need to encode the buffer here for getting the real content length of the response - encodeBody(); + // We need to encode the buffer here for getting the real content length of the response + encodeBody(); - ret = lws_add_http_common_headers(wsi, code, contentType.c_str(), - buffer.size(), - &p, end); - if (ret) - return 1; + ret = lws_add_http_common_headers(wsi, code, contentType.c_str(), + buffer.size(), &p, end); + if (ret) + return 1; - for (auto &hdr : headers) { - ret = lws_add_http_header_by_name (wsi, - reinterpret_cast(hdr.first.c_str()), - reinterpret_cast(hdr.second.c_str()), - hdr.second.size(), &p, end); - if (ret) - return -1; - } + for (auto &hdr : headers) { + ret = lws_add_http_header_by_name( + wsi, reinterpret_cast(hdr.first.c_str()), + reinterpret_cast(hdr.second.c_str()), + hdr.second.size(), &p, end); + if (ret) + return -1; + } - ret = lws_finalize_write_http_header(wsi, headerBuffer, &p, end); - if (ret) - return 1; + ret = lws_finalize_write_http_header(wsi, headerBuffer, &p, end); + if (ret) + return 1; - // Do we have a body to send? - if (buffer.size() > 0) - lws_callback_on_writable(wsi); + // Do we have a body to send? + if (buffer.size() > 0) + lws_callback_on_writable(wsi); - return 0; + return 0; } -JsonResponse::~JsonResponse() -{ - if (response) - json_decref(response); +JsonResponse::~JsonResponse() { + if (response) + json_decref(response); } -void JsonResponse::encodeBody() -{ - buffer.encode(response, JSON_INDENT(4)); -} +void JsonResponse::encodeBody() { buffer.encode(response, JSON_INDENT(4)); } diff --git a/lib/api/session.cpp b/lib/api/session.cpp index a734f015d..123599237 100644 --- a/lib/api/session.cpp +++ b/lib/api/session.cpp @@ -9,281 +9,271 @@ #include -#include #include +#include -#include #include #include +#include using namespace villas; using namespace villas::node; using namespace villas::node::api; -Session::Session(lws *w) : - version(Version::VERSION_2), - wsi(w), - logger(logging.get("api:session")) -{ - lws_context *ctx = lws_get_context(wsi); - void *user_ctx = lws_context_user(ctx); +Session::Session(lws *w) + : version(Version::VERSION_2), wsi(w), logger(logging.get("api:session")) { + lws_context *ctx = lws_get_context(wsi); + void *user_ctx = lws_context_user(ctx); - web = static_cast(user_ctx); - api = web->getApi(); + web = static_cast(user_ctx); + api = web->getApi(); - if (!api) - throw RuntimeError("API is disabled"); + if (!api) + throw RuntimeError("API is disabled"); - api->sessions.push_back(this); + api->sessions.push_back(this); - logger->debug("Initiated API session: {}", getName()); + logger->debug("Initiated API session: {}", getName()); - state = Session::State::ESTABLISHED; + state = Session::State::ESTABLISHED; } -Session::~Session() -{ - api->sessions.remove(this); +Session::~Session() { + api->sessions.remove(this); - logger->debug("Destroyed API session: {}", getName()); + logger->debug("Destroyed API session: {}", getName()); } -void Session::execute() -{ - logger->debug("Running API request: {}", request->toString()); +void Session::execute() { + logger->debug("Running API request: {}", request->toString()); - try { - response = std::unique_ptr(request->execute()); + try { + response = std::unique_ptr(request->execute()); - logger->debug("Completed API request: {}", request->toString()); - } catch (const Error &e) { - response = std::make_unique(this, e); + logger->debug("Completed API request: {}", request->toString()); + } catch (const Error &e) { + response = std::make_unique(this, e); - logger->warn("API request failed: {}, code={}: {}", request->toString(), e.code, e.what()); - } catch (const RuntimeError &e) { - response = std::make_unique(this, e); + logger->warn("API request failed: {}, code={}: {}", request->toString(), + e.code, e.what()); + } catch (const RuntimeError &e) { + response = std::make_unique(this, e); - logger->warn("API request failed: {}: {}", request->toString(), e.what()); - } + logger->warn("API request failed: {}: {}", request->toString(), e.what()); + } - logger->debug("Ran pending API requests. Triggering on_writeable callback: wsi={}", (void *) wsi); + logger->debug( + "Ran pending API requests. Triggering on_writeable callback: wsi={}", + (void *)wsi); - web->callbackOnWritable(wsi); + web->callbackOnWritable(wsi); } -std::string Session::getName() const -{ - std::stringstream ss; +std::string Session::getName() const { + std::stringstream ss; - ss << "version=" << version; + ss << "version=" << version; - if (wsi) { - char name[128]; - char ip[128]; + if (wsi) { + char name[128]; + char ip[128]; - lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), ip, sizeof(ip)); + lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), ip, + sizeof(ip)); - ss << ", remote.name=" << name << ", remote.ip=" << ip; - } + ss << ", remote.name=" << name << ", remote.ip=" << ip; + } - return ss.str(); + return ss.str(); } -void Session::shutdown() -{ - state = State::SHUTDOWN; +void Session::shutdown() { + state = State::SHUTDOWN; - web->callbackOnWritable(wsi); + web->callbackOnWritable(wsi); } -void Session::open(void *in, size_t len) -{ - int ret; - char buf[32]; +void Session::open(void *in, size_t len) { + int ret; + char buf[32]; - auto uri = reinterpret_cast(in); + auto uri = reinterpret_cast(in); - try { - unsigned int len; - auto method = getRequestMethod(); - if (method == Method::UNKNOWN) - throw RuntimeError("Invalid request method"); + try { + unsigned int len; + auto method = getRequestMethod(); + if (method == Method::UNKNOWN) + throw RuntimeError("Invalid request method"); - ret = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_LENGTH); - if (ret < 0) - throw RuntimeError("Failed to get content length"); + ret = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_LENGTH); + if (ret < 0) + throw RuntimeError("Failed to get content length"); - try { - len = std::stoull(buf); - } catch (const std::invalid_argument &) { - len = 0; - } + try { + len = std::stoull(buf); + } catch (const std::invalid_argument &) { + len = 0; + } - request = std::unique_ptr(RequestFactory::create(this, uri, method, len)); + request = std::unique_ptr( + RequestFactory::create(this, uri, method, len)); - /* This is an OPTIONS request. + /* This is an OPTIONS request. * * We immediatly send headers and close the connection * without waiting for a POST body */ - if (method == Method::OPTIONS) - lws_callback_on_writable(wsi); - /* This request has no body. + if (method == Method::OPTIONS) + lws_callback_on_writable(wsi); + /* This request has no body. * We can reply immediatly */ - else if (len == 0) - api->pending.push(this); - else { - // This request has a HTTP body. We wait for more data to arrive - } - } catch (const Error &e) { - response = std::make_unique(this, e); - lws_callback_on_writable(wsi); - } catch (const RuntimeError &e) { - response = std::make_unique(this, e); - lws_callback_on_writable(wsi); - } + else if (len == 0) + api->pending.push(this); + else { + // This request has a HTTP body. We wait for more data to arrive + } + } catch (const Error &e) { + response = std::make_unique(this, e); + lws_callback_on_writable(wsi); + } catch (const RuntimeError &e) { + response = std::make_unique(this, e); + lws_callback_on_writable(wsi); + } } -void Session::body(void *in, size_t len) -{ - request->buffer.append((const char *) in, len); +void Session::body(void *in, size_t len) { + request->buffer.append((const char *)in, len); } -void Session::bodyComplete() -{ - try { - request->decode(); +void Session::bodyComplete() { + try { + request->decode(); - api->pending.push(this); - } catch (const Error &e) { - response = std::make_unique(this, e); + api->pending.push(this); + } catch (const Error &e) { + response = std::make_unique(this, e); - logger->warn("Failed to decode API request: {}", e.what()); - } + logger->warn("Failed to decode API request: {}", e.what()); + } } -int Session::writeable() -{ - if (!response) - return 0; +int Session::writeable() { + if (!response) + return 0; - if (!headersSent) { - response->writeHeaders(wsi); + if (!headersSent) { + response->writeHeaders(wsi); - // Now wait, until we can send the body - headersSent = true; + // Now wait, until we can send the body + headersSent = true; - return 0; - } - else { - if (response) - return response->writeBody(wsi); - else - return 0; - } + return 0; + } else { + if (response) + return response->writeBody(wsi); + else + return 0; + } } -int Session::protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - int ret; - Session *s = reinterpret_cast(user); +int Session::protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + int ret; + Session *s = reinterpret_cast(user); - switch (reason) { - case LWS_CALLBACK_HTTP_BIND_PROTOCOL: - try { - new (s) Session(wsi); - } catch (const RuntimeError &e) { - return -1; - } + switch (reason) { + case LWS_CALLBACK_HTTP_BIND_PROTOCOL: + try { + new (s) Session(wsi); + } catch (const RuntimeError &e) { + return -1; + } - break; + break; - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - if (s == nullptr) - return -1; + case LWS_CALLBACK_HTTP_DROP_PROTOCOL: + if (s == nullptr) + return -1; - s->~Session(); + s->~Session(); - break; + break; - case LWS_CALLBACK_HTTP: - s->open(in, len); + case LWS_CALLBACK_HTTP: + s->open(in, len); - break; + break; - case LWS_CALLBACK_HTTP_BODY: - s->body(in, len); + case LWS_CALLBACK_HTTP_BODY: + s->body(in, len); - break; + break; - case LWS_CALLBACK_HTTP_BODY_COMPLETION: - s->bodyComplete(); + case LWS_CALLBACK_HTTP_BODY_COMPLETION: + s->bodyComplete(); - break; + break; - case LWS_CALLBACK_HTTP_WRITEABLE: - ret = s->writeable(); + case LWS_CALLBACK_HTTP_WRITEABLE: + ret = s->writeable(); - /* + /* * HTTP/1.0 no keepalive: close network connection * HTTP/1.1 or HTTP1.0 + KA: wait / process next transaction * HTTP/2: stream ended, parent connection remains up */ - if (ret) { - if (lws_http_transaction_completed(wsi)) - return -1; - } - else - lws_callback_on_writable(wsi); + if (ret) { + if (lws_http_transaction_completed(wsi)) + return -1; + } else + lws_callback_on_writable(wsi); - break; + break; - default: - break; - } + default: + break; + } - return 0; + return 0; } -Session::Method Session::getRequestMethod() const -{ - if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) - return Method::GET; - else if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) - return Method::POST; +Session::Method Session::getRequestMethod() const { + if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) + return Method::GET; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) + return Method::POST; #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) - else if (lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI)) - return Method::PUT; - else if (lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI)) - return Method::PATCH; - else if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) - return Method::OPTIONS; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI)) + return Method::PUT; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI)) + return Method::PATCH; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) + return Method::OPTIONS; #endif - else - return Method::UNKNOWN; + else + return Method::UNKNOWN; } -std::string Session::methodToString(Method method) -{ - switch (method) { - case Method::POST: - return "POST"; +std::string Session::methodToString(Method method) { + switch (method) { + case Method::POST: + return "POST"; - case Method::GET: - return "GET"; + case Method::GET: + return "GET"; - case Method::DELETE: - return "DELETE"; + case Method::DELETE: + return "DELETE"; - case Method::PUT: - return "PUT"; + case Method::PUT: + return "PUT"; - case Method::PATCH: - return "GPATCHET"; + case Method::PATCH: + return "GPATCHET"; - case Method::OPTIONS: - return "OPTIONS"; + case Method::OPTIONS: + return "OPTIONS"; - default: - return "UNKNOWN"; - } + default: + return "UNKNOWN"; + } } diff --git a/lib/api/universal.cpp b/lib/api/universal.cpp index 1788f09b2..bae23be14 100644 --- a/lib/api/universal.cpp +++ b/lib/api/universal.cpp @@ -5,140 +5,137 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include #include +#include using namespace villas::node::api::universal; -void ChannelList::parse(json_t *json, bool readable, bool writable) -{ - if (!json_is_array(json)) - throw ConfigError(json, "node-config-node-api-signals", "Signal list of API node must be an array"); +void ChannelList::parse(json_t *json, bool readable, bool writable) { + if (!json_is_array(json)) + throw ConfigError(json, "node-config-node-api-signals", + "Signal list of API node must be an array"); - clear(); + clear(); - size_t i; - json_t *json_channel; - json_array_foreach(json, i, json_channel) { - auto channel = std::make_shared(); + size_t i; + json_t *json_channel; + json_array_foreach(json, i, json_channel) { + auto channel = std::make_shared(); - channel->parse(json_channel); - channel->readable = readable; - channel->writable = writable; + channel->parse(json_channel); + channel->readable = readable; + channel->writable = writable; - push_back(channel); - } + push_back(channel); + } } -void Channel::parse(json_t *json) -{ - const char *desc = nullptr; - const char *pl = nullptr; - json_t *json_range = nullptr; +void Channel::parse(json_t *json) { + const char *desc = nullptr; + const char *pl = nullptr; + json_t *json_range = nullptr; - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o, s?: F }", - "description", &desc, - "payload", &pl, - "range", &json_range, - "rate", &rate - ); - if (ret) - throw ConfigError(json, err, "node-config-node-api-signals"); + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o, s?: F }", + "description", &desc, "payload", &pl, "range", + &json_range, "rate", &rate); + if (ret) + throw ConfigError(json, err, "node-config-node-api-signals"); - if (desc) - description = desc; + if (desc) + description = desc; - if (pl) { - if (!strcmp(pl, "samples")) - payload = PayloadType::SAMPLES; - else if (!strcmp(pl, "events")) - payload = PayloadType::EVENTS; - else - throw ConfigError(json, "node-config-node-api-signals-payload", "Invalid payload type: {}", pl); - } + if (pl) { + if (!strcmp(pl, "samples")) + payload = PayloadType::SAMPLES; + else if (!strcmp(pl, "events")) + payload = PayloadType::EVENTS; + else + throw ConfigError(json, "node-config-node-api-signals-payload", + "Invalid payload type: {}", pl); + } - range_min = std::numeric_limits::quiet_NaN(); - range_max = std::numeric_limits::quiet_NaN(); - if (json_range) { - if (json_is_array(json_range)) { - ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }", - "min", &range_min, - "max", &range_max - ); - if (ret) - throw ConfigError(json, err, "node-config-node-api-signals-range", "Failed to parse channel range"); - } else if (json_is_object(json_range)) { - size_t i; - json_t *json_option; + range_min = std::numeric_limits::quiet_NaN(); + range_max = std::numeric_limits::quiet_NaN(); + if (json_range) { + if (json_is_array(json_range)) { + ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }", "min", &range_min, + "max", &range_max); + if (ret) + throw ConfigError(json, err, "node-config-node-api-signals-range", + "Failed to parse channel range"); + } else if (json_is_object(json_range)) { + size_t i; + json_t *json_option; - range_options.clear(); + range_options.clear(); - json_array_foreach(json_range, i, json_option) { - if (!json_is_string(json_option)) - throw ConfigError(json, err, "node-config-node-api-signals-range", "Channel range options must be strings"); + json_array_foreach(json_range, i, json_option) { + if (!json_is_string(json_option)) + throw ConfigError(json, err, "node-config-node-api-signals-range", + "Channel range options must be strings"); - auto *option = json_string_value(json_option); - range_options.push_back(option); - } - } else - throw ConfigError(json, "node-config-node-api-signals-range", "Channel range must be an array or object"); - } + auto *option = json_string_value(json_option); + range_options.push_back(option); + } + } else + throw ConfigError(json, "node-config-node-api-signals-range", + "Channel range must be an array or object"); + } } -json_t * Channel::toJson(Signal::Ptr sig) const -{ - json_error_t err; - json_t *json_ch = json_pack_ex(&err, 0, "{ s: s, s: s, s: b, s: b }", - "id", sig->name.c_str(), - "datatype", signalTypeToString(sig->type).c_str(), - "readable", (int) readable, - "writable", (int) writable - ); +json_t *Channel::toJson(Signal::Ptr sig) const { + json_error_t err; + json_t *json_ch = json_pack_ex( + &err, 0, "{ s: s, s: s, s: b, s: b }", "id", sig->name.c_str(), + "datatype", signalTypeToString(sig->type).c_str(), "readable", + (int)readable, "writable", (int)writable); - if (!description.empty()) - json_object_set(json_ch, "description", json_string(description.c_str())); + if (!description.empty()) + json_object_set(json_ch, "description", json_string(description.c_str())); - if (!sig->unit.empty()) - json_object_set(json_ch, "unit", json_string(sig->unit.c_str())); + if (!sig->unit.empty()) + json_object_set(json_ch, "unit", json_string(sig->unit.c_str())); - if (rate > 0) - json_object_set(json_ch, "rate", json_real(rate)); + if (rate > 0) + json_object_set(json_ch, "rate", json_real(rate)); - switch (payload) { - case PayloadType::EVENTS: - json_object_set(json_ch, "payload", json_string("events")); - break; + switch (payload) { + case PayloadType::EVENTS: + json_object_set(json_ch, "payload", json_string("events")); + break; - case PayloadType::SAMPLES: - json_object_set(json_ch, "payload", json_string("samples")); - break; + case PayloadType::SAMPLES: + json_object_set(json_ch, "payload", json_string("samples")); + break; - default: {} - } + default: { + } + } - switch (sig->type) { - case SignalType::FLOAT: { - if (std::isnan(range_min) && std::isnan(range_max)) - break; + switch (sig->type) { + case SignalType::FLOAT: { + if (std::isnan(range_min) && std::isnan(range_max)) + break; - json_t *json_range = json_object(); + json_t *json_range = json_object(); - if (!std::isnan(range_min)) - json_object_set(json_range, "min", json_real(range_min)); + if (!std::isnan(range_min)) + json_object_set(json_range, "min", json_real(range_min)); - if (!std::isnan(range_max)) - json_object_set(json_range, "max", json_real(range_max)); + if (!std::isnan(range_max)) + json_object_set(json_range, "max", json_real(range_max)); - json_object_set(json_ch, "range", json_range); - break; - } + json_object_set(json_ch, "range", json_range); + break; + } - default: {} - } + default: { + } + } - return json_ch; + return json_ch; } diff --git a/lib/capabilities.cpp b/lib/capabilities.cpp index 2c8f9cbb8..2296c2438 100644 --- a/lib/capabilities.cpp +++ b/lib/capabilities.cpp @@ -7,52 +7,48 @@ #include -#include -#include -#include #include +#include +#include +#include using namespace villas; using namespace villas::node; -json_t * villas::node::getCapabilities() -{ - json_t *json_hooks = json_array(); - json_t *json_apis = json_array(); - json_t *json_nodes = json_array(); - json_t *json_formats = json_array(); - json_t *json_name; +json_t *villas::node::getCapabilities() { + json_t *json_hooks = json_array(); + json_t *json_apis = json_array(); + json_t *json_nodes = json_array(); + json_t *json_formats = json_array(); + json_t *json_name; - for (auto p : plugin::registry->lookup()) { - json_name = json_string(p->getName().c_str()); + for (auto p : plugin::registry->lookup()) { + json_name = json_string(p->getName().c_str()); - json_array_append_new(json_apis, json_name); - } + json_array_append_new(json_apis, json_name); + } - for (auto p : plugin::registry->lookup()) { - json_name = json_string(p->getName().c_str()); + for (auto p : plugin::registry->lookup()) { + json_name = json_string(p->getName().c_str()); - json_array_append_new(json_hooks, json_name); - } + json_array_append_new(json_hooks, json_name); + } - for (auto p : plugin::registry->lookup()) { - json_name = json_string(p->getName().c_str()); + for (auto p : plugin::registry->lookup()) { + json_name = json_string(p->getName().c_str()); - json_array_append_new(json_formats, json_name); - } + json_array_append_new(json_formats, json_name); + } - for (auto f : plugin::registry->lookup()) { - if (f->isInternal()) - continue; + for (auto f : plugin::registry->lookup()) { + if (f->isInternal()) + continue; - json_name = json_string(f->getName().c_str()); + json_name = json_string(f->getName().c_str()); - json_array_append_new(json_nodes, json_name); - } + json_array_append_new(json_nodes, json_name); + } - return json_pack("{ s: o, s: o, s: o, s: o }", - "hooks", json_hooks, - "nodes", json_nodes, - "apis", json_apis, - "formats", json_formats); + return json_pack("{ s: o, s: o, s: o, s: o }", "hooks", json_hooks, "nodes", + json_nodes, "apis", json_apis, "formats", json_formats); } diff --git a/lib/config.cpp b/lib/config.cpp index 221cfdebd..66acc5205 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -5,370 +5,355 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include #include -#include -#include -#include #include -#include #include +#include +#include -#include -#include -#include -#include #include -#include +#include #include +#include +#include +#include +#include #ifdef WITH_CONFIG - #include +#include #endif using namespace villas; using namespace villas::node; -Config::Config() : - logger(logging.get("config")), - root(nullptr) -{ } +Config::Config() : logger(logging.get("config")), root(nullptr) {} -Config::Config(const std::string &u) : - Config() -{ - root = load(u); +Config::Config(const std::string &u) : Config() { root = load(u); } + +Config::~Config() { json_decref(root); } + +json_t *Config::load(std::FILE *f, bool resolveInc, bool resolveEnvVars) { + json_t *root = decode(f); + + if (resolveInc) { + json_t *root_old = root; + root = expandIncludes(root); + json_decref(root_old); + } + + if (resolveEnvVars) { + json_t *root_old = root; + root = expandEnvVars(root); + json_decref(root_old); + } + + return root; } -Config::~Config() -{ - json_decref(root); +json_t *Config::load(const std::string &u, bool resolveInc, + bool resolveEnvVars) { + FILE *f; + + if (u == "-") + f = loadFromStdio(); + else + f = loadFromLocalFile(u); + + json_t *root = load(f, resolveInc, resolveEnvVars); + + fclose(f); + + return root; } -json_t * Config::load(std::FILE *f, bool resolveInc, bool resolveEnvVars) -{ - json_t *root = decode(f); +FILE *Config::loadFromStdio() { + logger->info("Reading configuration from standard input"); - if (resolveInc) { - json_t *root_old = root; - root = expandIncludes(root); - json_decref(root_old); - } - - if (resolveEnvVars) { - json_t *root_old = root; - root = expandEnvVars(root); - json_decref(root_old); - } - - return root; + return stdin; } -json_t * Config::load(const std::string &u, bool resolveInc, bool resolveEnvVars) -{ - FILE *f; +FILE *Config::loadFromLocalFile(const std::string &u) { + logger->info("Reading configuration from local file: {}", u); - if (u == "-") - f = loadFromStdio(); - else - f = loadFromLocalFile(u); + FILE *f = fopen(u.c_str(), "r"); + if (!f) + throw RuntimeError("Failed to open configuration from: {}", u); - json_t *root = load(f, resolveInc, resolveEnvVars); - - fclose(f); - - return root; + return f; } -FILE * Config::loadFromStdio() -{ - logger->info("Reading configuration from standard input"); +json_t *Config::decode(FILE *f) { + json_error_t err; - return stdin; -} + // Update list of include directories + auto incDirs = getIncludeDirectories(f); + includeDirectories.insert(includeDirectories.end(), incDirs.begin(), + incDirs.end()); -FILE * Config::loadFromLocalFile(const std::string &u) -{ - logger->info("Reading configuration from local file: {}", u); - - FILE *f = fopen(u.c_str(), "r"); - if (!f) - throw RuntimeError("Failed to open configuration from: {}", u); - - return f; -} - -json_t * Config::decode(FILE *f) -{ - json_error_t err; - - // Update list of include directories - auto incDirs = getIncludeDirectories(f); - includeDirectories.insert(includeDirectories.end(), incDirs.begin(), incDirs.end()); - - json_t *root = json_loadf(f, 0, &err); - if (root == nullptr) { + json_t *root = json_loadf(f, 0, &err); + if (root == nullptr) { #ifdef WITH_CONFIG - // We try again to parse the config in the legacy format - root = libconfigDecode(f); + // We try again to parse the config in the legacy format + root = libconfigDecode(f); #else - throw JanssonParseError(err); + throw JanssonParseError(err); #endif // WITH_CONFIG - } + } - return root; + return root; } -std::list Config::getIncludeDirectories(FILE *f) const -{ - int ret, fd; - char buf[PATH_MAX]; - char *dir; +std::list Config::getIncludeDirectories(FILE *f) const { + int ret, fd; + char buf[PATH_MAX]; + char *dir; - std::list dirs; + std::list dirs; - // Adding directory of base configuration file - fd = fileno(f); - if (fd < 0) - throw SystemError("Failed to get file descriptor"); + // Adding directory of base configuration file + fd = fileno(f); + if (fd < 0) + throw SystemError("Failed to get file descriptor"); - auto path = fmt::format("/proc/self/fd/{}", fd); + auto path = fmt::format("/proc/self/fd/{}", fd); - ret = readlink(path.c_str(), buf, sizeof(buf)); - if (ret > 0) { - buf[ret] = 0; - if (isLocalFile(buf)) { - dir = dirname(buf); - dirs.push_back(dir); - } - } + ret = readlink(path.c_str(), buf, sizeof(buf)); + if (ret > 0) { + buf[ret] = 0; + if (isLocalFile(buf)) { + dir = dirname(buf); + dirs.push_back(dir); + } + } - // Adding current working directory - dir = getcwd(buf, sizeof(buf)); - if (dir != nullptr) - dirs.push_back(dir); + // Adding current working directory + dir = getcwd(buf, sizeof(buf)); + if (dir != nullptr) + dirs.push_back(dir); - return dirs; + return dirs; } -std::list Config::resolveIncludes(const std::string &n) -{ - glob_t gb; - int ret, flags = 0; +std::list Config::resolveIncludes(const std::string &n) { + glob_t gb; + int ret, flags = 0; - memset(&gb, 0, sizeof(gb)); + memset(&gb, 0, sizeof(gb)); - auto name = n; - resolveEnvVars(name); + auto name = n; + resolveEnvVars(name); - if (name.size() >= 1 && name[0] == '/') { // absolute path - ret = glob(name.c_str(), flags, nullptr, &gb); - if (ret && ret != GLOB_NOMATCH) - gb.gl_pathc = 0; - } - else { // relative path - for (auto &dir : includeDirectories) { - auto pattern = fmt::format("{}/{}", dir, name.c_str()); + if (name.size() >= 1 && name[0] == '/') { // absolute path + ret = glob(name.c_str(), flags, nullptr, &gb); + if (ret && ret != GLOB_NOMATCH) + gb.gl_pathc = 0; + } else { // relative path + for (auto &dir : includeDirectories) { + auto pattern = fmt::format("{}/{}", dir, name.c_str()); - ret = glob(pattern.c_str(), flags, nullptr, &gb); - if (ret && ret != GLOB_NOMATCH) { - gb.gl_pathc = 0; + ret = glob(pattern.c_str(), flags, nullptr, &gb); + if (ret && ret != GLOB_NOMATCH) { + gb.gl_pathc = 0; - goto out; - } + goto out; + } - flags |= GLOB_APPEND; - } - } + flags |= GLOB_APPEND; + } + } -out: std::list files; - for (unsigned i = 0; i < gb.gl_pathc; i++) - files.push_back(gb.gl_pathv[i]); +out: + std::list files; + for (unsigned i = 0; i < gb.gl_pathc; i++) + files.push_back(gb.gl_pathv[i]); - globfree(&gb); + globfree(&gb); - return files; + return files; } -void Config::resolveEnvVars(std::string &text) -{ - static - const std::regex env_re{R"--(\$\{([^}]+)\})--"}; +void Config::resolveEnvVars(std::string &text) { + static const std::regex env_re{R"--(\$\{([^}]+)\})--"}; - std::smatch match; - while (std::regex_search(text, match, env_re)) { - auto const from = match[0]; - auto const var_name = match[1].str().c_str(); - char *var_value = std::getenv(var_name); - if (!var_value) - throw RuntimeError("Unresolved environment variable: {}", var_name); + std::smatch match; + while (std::regex_search(text, match, env_re)) { + auto const from = match[0]; + auto const var_name = match[1].str().c_str(); + char *var_value = std::getenv(var_name); + if (!var_value) + throw RuntimeError("Unresolved environment variable: {}", var_name); - text.replace(from.first - text.begin(), from.second - from.first, var_value); + text.replace(from.first - text.begin(), from.second - from.first, + var_value); - logger->debug("Replace env var {} in \"{}\" with value \"{}\"", - var_name, text, var_value); - } + logger->debug("Replace env var {} in \"{}\" with value \"{}\"", var_name, + text, var_value); + } } #ifdef WITH_CONFIG -#if (LIBCONFIG_VER_MAJOR > 1) || ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) -const char ** Config::includeFuncStub(config_t *cfg, const char *include_dir, const char *path, const char **error) -{ - void *ctx = config_get_hook(cfg); +#if (LIBCONFIG_VER_MAJOR > 1) || \ + ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) +const char **Config::includeFuncStub(config_t *cfg, const char *include_dir, + const char *path, const char **error) { + void *ctx = config_get_hook(cfg); - return reinterpret_cast(ctx)->includeFunc(cfg, include_dir, path, error); + return reinterpret_cast(ctx)->includeFunc(cfg, include_dir, path, + error); } -const char ** Config::includeFunc(config_t *cfg, const char *include_dir, const char *path, const char **error) -{ - auto paths = resolveIncludes(path); +const char **Config::includeFunc(config_t *cfg, const char *include_dir, + const char *path, const char **error) { + auto paths = resolveIncludes(path); - unsigned i = 0; - auto files = (const char **) malloc(sizeof(char **) * (paths.size() + 1)); + unsigned i = 0; + auto files = (const char **)malloc(sizeof(char **) * (paths.size() + 1)); - for (auto &path : paths) - files[i++] = strdup(path.c_str()); + for (auto &path : paths) + files[i++] = strdup(path.c_str()); - files[i] = NULL; + files[i] = NULL; - return files; + return files; } #endif -json_t * Config::libconfigDecode(FILE *f) -{ - int ret; +json_t *Config::libconfigDecode(FILE *f) { + int ret; - config_t cfg; - config_setting_t *cfg_root; - config_init(&cfg); - config_set_auto_convert(&cfg, 1); + config_t cfg; + config_setting_t *cfg_root; + config_init(&cfg); + config_set_auto_convert(&cfg, 1); - // Setup libconfig include path -#if (LIBCONFIG_VER_MAJOR > 1) || ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) - config_set_hook(&cfg, this); + // Setup libconfig include path +#if (LIBCONFIG_VER_MAJOR > 1) || \ + ((LIBCONFIG_VER_MAJOR == 1) && (LIBCONFIG_VER_MINOR >= 7)) + config_set_hook(&cfg, this); - config_set_include_func(&cfg, includeFuncStub); + config_set_include_func(&cfg, includeFuncStub); #else - if (includeDirectories.size() > 0) { - logger->info("Setting include dir to: {}", includeDirectories.front()); + if (includeDirectories.size() > 0) { + logger->info("Setting include dir to: {}", includeDirectories.front()); - config_set_include_dir(&cfg, includeDirectories.front().c_str()); + config_set_include_dir(&cfg, includeDirectories.front().c_str()); - if (includeDirectories.size() > 1) { - logger->warn("Ignoring all but the first include directories for libconfig"); - logger->warn(" libconfig does not support more than a single include dir!"); - } - } + if (includeDirectories.size() > 1) { + logger->warn( + "Ignoring all but the first include directories for libconfig"); + logger->warn( + " libconfig does not support more than a single include dir!"); + } + } #endif - // Rewind before re-reading - rewind(f); + // Rewind before re-reading + rewind(f); - ret = config_read(&cfg, f); - if (ret != CONFIG_TRUE) - throw LibconfigParseError(&cfg); + ret = config_read(&cfg, f); + if (ret != CONFIG_TRUE) + throw LibconfigParseError(&cfg); - cfg_root = config_root_setting(&cfg); + cfg_root = config_root_setting(&cfg); - json_t *root = config_to_json(cfg_root); - if (!root) - throw RuntimeError("Failed to convert JSON to configuration file"); + json_t *root = config_to_json(cfg_root); + if (!root) + throw RuntimeError("Failed to convert JSON to configuration file"); - config_destroy(&cfg); + config_destroy(&cfg); - return root; + return root; } #endif // WITH_CONFIG -json_t * Config::walkStrings(json_t *root, str_walk_fcn_t cb) -{ - const char *key; - size_t index; - json_t *val, *new_val, *new_root; +json_t *Config::walkStrings(json_t *root, str_walk_fcn_t cb) { + const char *key; + size_t index; + json_t *val, *new_val, *new_root; - switch (json_typeof(root)) { - case JSON_STRING: - return cb(root); + switch (json_typeof(root)) { + case JSON_STRING: + return cb(root); - case JSON_OBJECT: - new_root = json_object(); + case JSON_OBJECT: + new_root = json_object(); - json_object_foreach(root, key, val) { - new_val = walkStrings(val, cb); + json_object_foreach(root, key, val) { + new_val = walkStrings(val, cb); - json_object_set_new(new_root, key, new_val); - } + json_object_set_new(new_root, key, new_val); + } - return new_root; + return new_root; - case JSON_ARRAY: - new_root = json_array(); + case JSON_ARRAY: + new_root = json_array(); - json_array_foreach(root, index, val) { - new_val = walkStrings(val, cb); + json_array_foreach(root, index, val) { + new_val = walkStrings(val, cb); - json_array_append_new(new_root, new_val); - } + json_array_append_new(new_root, new_val); + } - return new_root; + return new_root; - default: - return json_incref(root); - }; + default: + return json_incref(root); + }; } -json_t * Config::expandEnvVars(json_t *in) -{ - return walkStrings(in, [this](json_t *str) -> json_t * { - std::string text = json_string_value(str); +json_t *Config::expandEnvVars(json_t *in) { + return walkStrings(in, [this](json_t *str) -> json_t * { + std::string text = json_string_value(str); - resolveEnvVars(text); + resolveEnvVars(text); - return json_string(text.c_str()); - }); + return json_string(text.c_str()); + }); } -json_t * Config::expandIncludes(json_t *in) -{ - return walkStrings(in, [this](json_t *str) -> json_t * { - int ret; - std::string text = json_string_value(str); - static - const std::string kw = "@include "; +json_t *Config::expandIncludes(json_t *in) { + return walkStrings(in, [this](json_t *str) -> json_t * { + int ret; + std::string text = json_string_value(str); + static const std::string kw = "@include "; - if (text.find(kw) != 0) - return json_incref(str); - else { - std::string pattern = text.substr(kw.size()); + if (text.find(kw) != 0) + return json_incref(str); + else { + std::string pattern = text.substr(kw.size()); - resolveEnvVars(pattern); + resolveEnvVars(pattern); - json_t *incl = nullptr; + json_t *incl = nullptr; - for (auto &path : resolveIncludes(pattern)) { - json_t *other = load(path); - if (!other) - throw ConfigError(str, "Failed to include config file from {}", path); + for (auto &path : resolveIncludes(pattern)) { + json_t *other = load(path); + if (!other) + throw ConfigError(str, "Failed to include config file from {}", path); - if (!incl) - incl = other; - else if (json_is_object(incl) && json_is_object(other)) { - ret = json_object_update_recursive(incl, other); - if (ret) - throw ConfigError(str, "Can not mix object and array-typed include files"); - } - else if (json_is_array(incl) && json_is_array(other)) { - ret = json_array_extend(incl, other); - if (ret) - throw ConfigError(str, "Can not mix object and array-typed include files"); - } + if (!incl) + incl = other; + else if (json_is_object(incl) && json_is_object(other)) { + ret = json_object_update_recursive(incl, other); + if (ret) + throw ConfigError( + str, "Can not mix object and array-typed include files"); + } else if (json_is_array(incl) && json_is_array(other)) { + ret = json_array_extend(incl, other); + if (ret) + throw ConfigError( + str, "Can not mix object and array-typed include files"); + } - logger->debug("Included config from: {}", path); - } + logger->debug("Included config from: {}", path); + } - return incl; - } - }); + return incl; + } + }); } diff --git a/lib/config_helper.cpp b/lib/config_helper.cpp index 5e0747518..7e4da1b31 100644 --- a/lib/config_helper.cpp +++ b/lib/config_helper.cpp @@ -5,347 +5,337 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include -#include #include +#include #include #ifdef WITH_CONFIG -static -int json_to_config_type(int type) -{ - switch (type) { - case JSON_OBJECT: - return CONFIG_TYPE_GROUP; +static int json_to_config_type(int type) { + switch (type) { + case JSON_OBJECT: + return CONFIG_TYPE_GROUP; - case JSON_ARRAY: - return CONFIG_TYPE_LIST; + case JSON_ARRAY: + return CONFIG_TYPE_LIST; - case JSON_STRING: - return CONFIG_TYPE_STRING; + case JSON_STRING: + return CONFIG_TYPE_STRING; - case JSON_INTEGER: - return CONFIG_TYPE_INT64; + case JSON_INTEGER: + return CONFIG_TYPE_INT64; - case JSON_REAL: - return CONFIG_TYPE_FLOAT; + case JSON_REAL: + return CONFIG_TYPE_FLOAT; - case JSON_TRUE: - case JSON_FALSE: - case JSON_NULL: - return CONFIG_TYPE_BOOL; - } + case JSON_TRUE: + case JSON_FALSE: + case JSON_NULL: + return CONFIG_TYPE_BOOL; + } - return -1; + return -1; } -json_t * villas::node::config_to_json(config_setting_t *cfg) -{ - switch (config_setting_type(cfg)) { - case CONFIG_TYPE_INT: - return json_integer(config_setting_get_int(cfg)); +json_t *villas::node::config_to_json(config_setting_t *cfg) { + switch (config_setting_type(cfg)) { + case CONFIG_TYPE_INT: + return json_integer(config_setting_get_int(cfg)); - case CONFIG_TYPE_INT64: - return json_integer(config_setting_get_int64(cfg)); + case CONFIG_TYPE_INT64: + return json_integer(config_setting_get_int64(cfg)); - case CONFIG_TYPE_FLOAT: - return json_real(config_setting_get_float(cfg)); + case CONFIG_TYPE_FLOAT: + return json_real(config_setting_get_float(cfg)); - case CONFIG_TYPE_STRING: - return json_string(config_setting_get_string(cfg)); + case CONFIG_TYPE_STRING: + return json_string(config_setting_get_string(cfg)); - case CONFIG_TYPE_BOOL: - return json_boolean(config_setting_get_bool(cfg)); + case CONFIG_TYPE_BOOL: + return json_boolean(config_setting_get_bool(cfg)); - case CONFIG_TYPE_ARRAY: - case CONFIG_TYPE_LIST: { - json_t *json = json_array(); + case CONFIG_TYPE_ARRAY: + case CONFIG_TYPE_LIST: { + json_t *json = json_array(); - for (int i = 0; i < config_setting_length(cfg); i++) { - auto *elm = config_setting_get_elem(cfg, i); - json_array_append_new(json, config_to_json(elm)); - } + for (int i = 0; i < config_setting_length(cfg); i++) { + auto *elm = config_setting_get_elem(cfg, i); + json_array_append_new(json, config_to_json(elm)); + } - return json; - } + return json; + } - case CONFIG_TYPE_GROUP: { - json_t *json = json_object(); + case CONFIG_TYPE_GROUP: { + json_t *json = json_object(); - for (int i = 0; i < config_setting_length(cfg); i++) { - auto *elm = config_setting_get_elem(cfg, i); - json_object_set_new(json, - config_setting_name(elm), - config_to_json(elm) - ); - } + for (int i = 0; i < config_setting_length(cfg); i++) { + auto *elm = config_setting_get_elem(cfg, i); + json_object_set_new(json, config_setting_name(elm), config_to_json(elm)); + } - return json; - } + return json; + } - default: - return json_object(); - } + default: + return json_object(); + } } -int villas::node::json_to_config(json_t *json, config_setting_t *parent) -{ - config_setting_t *cfg; - int ret, type; +int villas::node::json_to_config(json_t *json, config_setting_t *parent) { + config_setting_t *cfg; + int ret, type; - if (config_setting_is_root(parent)) { - if (!json_is_object(json)) - return -1; // The root must be an object! - } + if (config_setting_is_root(parent)) { + if (!json_is_object(json)) + return -1; // The root must be an object! + } - switch (json_typeof(json)) { - case JSON_OBJECT: { - const char *key; - json_t *json_value; + switch (json_typeof(json)) { + case JSON_OBJECT: { + const char *key; + json_t *json_value; - json_object_foreach(json, key, json_value) { - type = json_to_config_type(json_typeof(json_value)); + json_object_foreach(json, key, json_value) { + type = json_to_config_type(json_typeof(json_value)); - cfg = config_setting_add(parent, key, type); - ret = json_to_config(json_value, cfg); - if (ret) - return ret; - } - break; - } + cfg = config_setting_add(parent, key, type); + ret = json_to_config(json_value, cfg); + if (ret) + return ret; + } + break; + } - case JSON_ARRAY: { - size_t i; - json_t *json_value; + case JSON_ARRAY: { + size_t i; + json_t *json_value; - json_array_foreach(json, i, json_value) { - type = json_to_config_type(json_typeof(json_value)); + json_array_foreach(json, i, json_value) { + type = json_to_config_type(json_typeof(json_value)); - cfg = config_setting_add(parent, nullptr, type); - ret = json_to_config(json_value, cfg); - if (ret) - return ret; - } - break; - } + cfg = config_setting_add(parent, nullptr, type); + ret = json_to_config(json_value, cfg); + if (ret) + return ret; + } + break; + } - case JSON_STRING: - config_setting_set_string(parent, json_string_value(json)); - break; + case JSON_STRING: + config_setting_set_string(parent, json_string_value(json)); + break; - case JSON_INTEGER: - config_setting_set_int64(parent, json_integer_value(json)); - break; + case JSON_INTEGER: + config_setting_set_int64(parent, json_integer_value(json)); + break; - case JSON_REAL: - config_setting_set_float(parent, json_real_value(json)); - break; + case JSON_REAL: + config_setting_set_float(parent, json_real_value(json)); + break; - case JSON_TRUE: - case JSON_FALSE: - case JSON_NULL: - config_setting_set_bool(parent, json_is_true(json)); - break; - } + case JSON_TRUE: + case JSON_FALSE: + case JSON_NULL: + config_setting_set_bool(parent, json_is_true(json)); + break; + } - return 0; + return 0; } #endif // WITH_CONFIG -void villas::node::json_object_extend_key_value_token(json_t *obj, const char *key, const char *value) -{ - char *str = strdup(value); - const char *delim = ","; +void villas::node::json_object_extend_key_value_token(json_t *obj, + const char *key, + const char *value) { + char *str = strdup(value); + const char *delim = ","; - char *lasts; - char *token = strtok_r(str, delim, &lasts); + char *lasts; + char *token = strtok_r(str, delim, &lasts); - while (token) { - json_object_extend_key_value(obj, key, token); + while (token) { + json_object_extend_key_value(obj, key, token); - token = strtok_r(nullptr, delim, &lasts); - } + token = strtok_r(nullptr, delim, &lasts); + } - free(str); + free(str); } -void villas::node::json_object_extend_key_value(json_t *obj, const char *key, const char *value) -{ - char *end, *cpy, *key1, *key2, *lasts; +void villas::node::json_object_extend_key_value(json_t *obj, const char *key, + const char *value) { + char *end, *cpy, *key1, *key2, *lasts; - double real; - long integer; + double real; + long integer; - json_t *arr, *add, *existing, *subobj; + json_t *arr, *add, *existing, *subobj; - // Is the key pointing to an object? - subobj = obj; - cpy = strdup(key); + // Is the key pointing to an object? + subobj = obj; + cpy = strdup(key); - key1 = strtok_r(cpy, ".", &lasts); - key2 = strtok_r(nullptr, ".", &lasts); + key1 = strtok_r(cpy, ".", &lasts); + key2 = strtok_r(nullptr, ".", &lasts); - while (key1 && key2) { - existing = json_object_get(subobj, key1); - if (existing) - subobj = existing; - else { - add = json_object(); - json_object_set(subobj, key1, add); + while (key1 && key2) { + existing = json_object_get(subobj, key1); + if (existing) + subobj = existing; + else { + add = json_object(); + json_object_set(subobj, key1, add); - subobj = add; - } + subobj = add; + } - key1 = key2; - key2 = strtok_r(nullptr, ".", &lasts); - } + key1 = key2; + key2 = strtok_r(nullptr, ".", &lasts); + } - // Try to parse as integer - integer = strtol(value, &end, 0); - if (*end == 0) { - add = json_integer(integer); - goto success; - } + // Try to parse as integer + integer = strtol(value, &end, 0); + if (*end == 0) { + add = json_integer(integer); + goto success; + } - // Try to parse as floating point - real = strtod(value, &end); - if (*end == 0) { - add = json_real(real); - goto success; - } + // Try to parse as floating point + real = strtod(value, &end); + if (*end == 0) { + add = json_real(real); + goto success; + } - // Try to parse special types - if (!strcmp(value, "true")) { - add = json_true(); - goto success; - } + // Try to parse special types + if (!strcmp(value, "true")) { + add = json_true(); + goto success; + } - if (!strcmp(value, "false")) { - add = json_false(); - goto success; - } + if (!strcmp(value, "false")) { + add = json_false(); + goto success; + } - if (!strcmp(value, "null")) { - add = json_null(); - goto success; - } + if (!strcmp(value, "null")) { + add = json_null(); + goto success; + } - // Fallback to string - add = json_string(value); + // Fallback to string + add = json_string(value); success: - /* Does the key already exist? + /* Does the key already exist? * If yes, transform to array. */ - existing = json_object_get(subobj, key1); - if (existing) { - if (json_is_array(existing)) - arr = existing; - else { - arr = json_array(); - json_object_set(subobj, key1, arr); - json_array_append(arr, existing); - } + existing = json_object_get(subobj, key1); + if (existing) { + if (json_is_array(existing)) + arr = existing; + else { + arr = json_array(); + json_object_set(subobj, key1, arr); + json_array_append(arr, existing); + } - json_array_append(arr, add); - } - else - json_object_set(subobj, key1, add); + json_array_append(arr, add); + } else + json_object_set(subobj, key1, add); } -json_t * villas::node::json_load_cli(int argc, const char *argv[]) -{ - const char *opt; - const char *key = nullptr; - const char *value = nullptr; - const char *sep; - char *cpy, *lasts; +json_t *villas::node::json_load_cli(int argc, const char *argv[]) { + const char *opt; + const char *key = nullptr; + const char *value = nullptr; + const char *sep; + char *cpy, *lasts; - json_t *json = json_object(); + json_t *json = json_object(); - for (int i = 1; i < argc; i++) { - opt = argv[i]; + for (int i = 1; i < argc; i++) { + opt = argv[i]; - // Long Option - if (opt[0] == '-' && opt[1] == '-') { - // Option without value? Abort - if (key != nullptr) - return nullptr; + // Long Option + if (opt[0] == '-' && opt[1] == '-') { + // Option without value? Abort + if (key != nullptr) + return nullptr; - key = opt + 2; + key = opt + 2; - // Does this option has the form "--option=value"? - sep = strchr(key, '='); - if (sep) { - cpy = strdup(key); + // Does this option has the form "--option=value"? + sep = strchr(key, '='); + if (sep) { + cpy = strdup(key); - key = strtok_r(cpy, "=", &lasts); - value = strtok_r(nullptr, "", &lasts); + key = strtok_r(cpy, "=", &lasts); + value = strtok_r(nullptr, "", &lasts); - json_object_extend_key_value_token(json, key, value); + json_object_extend_key_value_token(json, key, value); - free(cpy); - key = nullptr; - } - } - // Value - else { - // Value without key. Abort - if (key == nullptr) - return nullptr; + free(cpy); + key = nullptr; + } + } + // Value + else { + // Value without key. Abort + if (key == nullptr) + return nullptr; - value = opt; + value = opt; - json_object_extend_key_value_token(json, key, value); - key = nullptr; - } - } + json_object_extend_key_value_token(json, key, value); + key = nullptr; + } + } - return json; + return json; } -int villas::node::json_object_extend(json_t *obj, json_t *merge) -{ - const char *key; - int ret; - json_t *merge_value, *obj_value; +int villas::node::json_object_extend(json_t *obj, json_t *merge) { + const char *key; + int ret; + json_t *merge_value, *obj_value; - if (!json_is_object(obj) || !json_is_object(merge)) - return -1; + if (!json_is_object(obj) || !json_is_object(merge)) + return -1; - json_object_foreach(merge, key, merge_value) { - obj_value = json_object_get(obj, key); - if (obj_value && json_is_object(obj_value)) - ret = json_object_extend(obj_value, merge_value); - else - ret = json_object_set(obj, key, merge_value); + json_object_foreach(merge, key, merge_value) { + obj_value = json_object_get(obj, key); + if (obj_value && json_is_object(obj_value)) + ret = json_object_extend(obj_value, merge_value); + else + ret = json_object_set(obj, key, merge_value); - if (ret) - return ret; - } + if (ret) + return ret; + } - return 0; + return 0; } -int villas::node::json_object_extend_str(json_t *obj, const char *str) -{ - char *key, *value, *cpy, *lasts; +int villas::node::json_object_extend_str(json_t *obj, const char *str) { + char *key, *value, *cpy, *lasts; - cpy = strdup(str); + cpy = strdup(str); - key = strtok_r(cpy, "=", &lasts); - value = strtok_r(nullptr, "", &lasts); + key = strtok_r(cpy, "=", &lasts); + value = strtok_r(nullptr, "", &lasts); - if (!key || !value) - return -1; + if (!key || !value) + return -1; - json_object_extend_key_value_token(obj, key, value); + json_object_extend_key_value_token(obj, key, value); - free(cpy); + free(cpy); - return 0; + return 0; } diff --git a/lib/dumper.cpp b/lib/dumper.cpp index f4e4f186a..7b0862605 100644 --- a/lib/dumper.cpp +++ b/lib/dumper.cpp @@ -10,119 +10,106 @@ #include #include -#include #include +#include #include using namespace villas; using namespace villas::node; -Dumper::Dumper() : - active(false), - socketFd(0), - socketPath(""), - supressRepeatedWarning(true), - warningCounter(0), - logger(logging.get("dumper")) -{} +Dumper::Dumper() + : active(false), socketFd(0), socketPath(""), supressRepeatedWarning(true), + warningCounter(0), logger(logging.get("dumper")) {} -Dumper::~Dumper() { - closeSocket(); +Dumper::~Dumper() { closeSocket(); } + +bool Dumper::isActive() { return active; } + +int Dumper::setActive() { + active = true; + return 1; } -bool Dumper::isActive() -{ - return active; +int Dumper::openSocket() { + socketFd = socket(AF_LOCAL, SOCK_STREAM, 0); + if (socketFd < 0) { + logger->info("Error creating socket {}", socketPath); + return -1; + } + + sockaddr_un socketaddrUn; + socketaddrUn.sun_family = AF_UNIX; + strcpy(socketaddrUn.sun_path, socketPath.c_str()); + + int ret = + connect(socketFd, (struct sockaddr *)&socketaddrUn, sizeof(socketaddrUn)); + if (!ret) + return ret; + + return 0; } -int Dumper::setActive() -{ - active = true; - return 1; +int Dumper::closeSocket() { + int ret = close(socketFd); + if (!ret) + return ret; + + return 0; } -int Dumper::openSocket() -{ - socketFd = socket(AF_LOCAL, SOCK_STREAM, 0); - if (socketFd < 0) { - logger->info("Error creating socket {}", socketPath); - return -1; - } - - sockaddr_un socketaddrUn; - socketaddrUn.sun_family = AF_UNIX; - strcpy(socketaddrUn.sun_path, socketPath.c_str()); - - int ret = connect(socketFd, (struct sockaddr *) &socketaddrUn, sizeof(socketaddrUn)); - if (!ret) - return ret; - - return 0; +int Dumper::setPath(const std::string &socketPathIn) { + socketPath = socketPathIn; + return 1; } -int Dumper::closeSocket() -{ - int ret = close(socketFd); - if (!ret) - return ret; +void Dumper::writeDataBinary(unsigned len, double *yData, double *xData) { - return 0; + if (warningCounter > 10) + return; + + if (yData == nullptr) + return; + + unsigned dataLen = len * sizeof(double); + ssize_t bytesWritten = write(socketFd, &dataLen, sizeof(dataLen)); + if ((size_t)bytesWritten != sizeof(len)) { + logger->warn("Could not send all content (Len) to socket {}", socketPath); + warningCounter++; + } + + static const char buf[] = "d000"; + bytesWritten = write(socketFd, buf, sizeof(buf)); + if (bytesWritten != sizeof(buf)) { + logger->warn("Could not send all content (Type) to socket {}", socketPath); + warningCounter++; + } + + bytesWritten = write(socketFd, yData, dataLen); + if (bytesWritten != (ssize_t)dataLen && + (!supressRepeatedWarning || warningCounter < 1)) { + logger->warn("Could not send all content (Data) to socket {}", socketPath); + warningCounter++; + } } -int Dumper::setPath(const std::string &socketPathIn) -{ - socketPath = socketPathIn; - return 1; -} - -void Dumper::writeDataBinary(unsigned len, double *yData, double *xData) -{ - - if (warningCounter > 10) - return; - - if (yData == nullptr) - return; - - unsigned dataLen = len * sizeof(double); - ssize_t bytesWritten = write(socketFd, &dataLen, sizeof(dataLen)); - if ((size_t) bytesWritten != sizeof(len)) { - logger->warn("Could not send all content (Len) to socket {}", socketPath); - warningCounter++; - } - - static const char buf[] = "d000"; - bytesWritten = write(socketFd, buf, sizeof(buf)); - if (bytesWritten != sizeof(buf)) { - logger->warn("Could not send all content (Type) to socket {}", socketPath); - warningCounter++; - } - - bytesWritten = write(socketFd, yData, dataLen ); - if (bytesWritten != (ssize_t) dataLen && (!supressRepeatedWarning || warningCounter <1 )) { - logger->warn("Could not send all content (Data) to socket {}", socketPath); - warningCounter++; - } -} - -void Dumper::writeDataCSV(unsigned len, double *yData, double *xData) -{ - for (unsigned i = 0; i < len; i++) { - std::stringstream ss; - - ss << yData[i]; - - if (xData != nullptr) - ss << ";" << xData[i]; - - ss << std::endl; - - auto str = ss.str(); - auto bytesWritten = write(socketFd, str.c_str(), str.length()); - if ((size_t) bytesWritten != str.length() && (!supressRepeatedWarning || warningCounter < 1)) { - logger->warn("Could not send all content to socket {}", socketPath); - warningCounter++; - } - } +void Dumper::writeDataCSV(unsigned len, double *yData, double *xData) { + for (unsigned i = 0; i < len; i++) { + std::stringstream ss; + + ss << yData[i]; + + if (xData != nullptr) + ss << ";" << xData[i]; + + ss << std::endl; + + auto str = ss.str(); + auto bytesWritten = write(socketFd, str.c_str(), str.length()); + if ((size_t)bytesWritten != str.length() && + (!supressRepeatedWarning || warningCounter < 1)) { + logger->warn("Could not send all content to socket {}", socketPath); + warningCounter++; + } + } } diff --git a/lib/format.cpp b/lib/format.cpp index 02e7ae293..0c5b5c5fc 100644 --- a/lib/format.cpp +++ b/lib/format.cpp @@ -5,159 +5,144 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include +#include #include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -Format * FormatFactory::make(json_t *json) -{ - std::string type; - Format *f; +Format *FormatFactory::make(json_t *json) { + std::string type; + Format *f; - if (json_is_string(json)) { - type = json_string_value(json); + if (json_is_string(json)) { + type = json_string_value(json); - return FormatFactory::make(type); - } - else if (json_is_object(json)) { - json_t *json_type = json_object_get(json, "type"); + return FormatFactory::make(type); + } else if (json_is_object(json)) { + json_t *json_type = json_object_get(json, "type"); - type = json_string_value(json_type); + type = json_string_value(json_type); - f = FormatFactory::make(type); - if (!f) - return nullptr; + f = FormatFactory::make(type); + if (!f) + return nullptr; - f->parse(json); + f->parse(json); - return f; - } - else - throw ConfigError(json, "node-config-format", "Invalid format config"); + return f; + } else + throw ConfigError(json, "node-config-format", "Invalid format config"); } -Format * FormatFactory::make(const std::string &format) -{ - FormatFactory *ff = plugin::registry->lookup(format); - if (!ff) - throw RuntimeError("Unknown format: {}", format); +Format *FormatFactory::make(const std::string &format) { + FormatFactory *ff = plugin::registry->lookup(format); + if (!ff) + throw RuntimeError("Unknown format: {}", format); - return ff->make(); + return ff->make(); } -Format::Format(int fl) : - flags(fl), - real_precision(17), - signals(nullptr) -{ - in.buflen = - out.buflen = DEFAULT_FORMAT_BUFFER_LENGTH; +Format::Format(int fl) : flags(fl), real_precision(17), signals(nullptr) { + in.buflen = out.buflen = DEFAULT_FORMAT_BUFFER_LENGTH; - in.buffer = new char[in.buflen]; - out.buffer = new char[out.buflen]; + in.buffer = new char[in.buflen]; + out.buffer = new char[out.buflen]; - if (!in.buffer || !out.buffer) - throw MemoryAllocationError(); + if (!in.buffer || !out.buffer) + throw MemoryAllocationError(); } -Format::~Format() -{ - int ret __attribute__((unused)); +Format::~Format() { + int ret __attribute__((unused)); - delete[] in.buffer; - delete[] out.buffer; + delete[] in.buffer; + delete[] out.buffer; } -void Format::start(SignalList::Ptr sigs, int fl) -{ - flags &= fl; +void Format::start(SignalList::Ptr sigs, int fl) { + flags &= fl; - signals = sigs; + signals = sigs; - start(); + start(); } -void Format::start(const std::string &dtypes, int fl) -{ - flags |= fl; +void Format::start(const std::string &dtypes, int fl) { + flags |= fl; - signals = std::make_shared(dtypes.c_str()); - if (!signals) - throw MemoryAllocationError(); + signals = std::make_shared(dtypes.c_str()); + if (!signals) + throw MemoryAllocationError(); - start(); + start(); } -int Format::print(FILE *f, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - size_t wbytes; +int Format::print(FILE *f, const struct Sample *const smps[], unsigned cnt) { + int ret; + size_t wbytes; - ret = sprint(out.buffer, out.buflen, &wbytes, smps, cnt); + ret = sprint(out.buffer, out.buflen, &wbytes, smps, cnt); - fwrite(out.buffer, wbytes, 1, f); + fwrite(out.buffer, wbytes, 1, f); - return ret; + return ret; } -int Format::scan(FILE *f, struct Sample * const smps[], unsigned cnt) -{ - size_t bytes, rbytes; +int Format::scan(FILE *f, struct Sample *const smps[], unsigned cnt) { + size_t bytes, rbytes; - bytes = fread(in.buffer, 1, in.buflen, f); + bytes = fread(in.buffer, 1, in.buflen, f); - return sscan(in.buffer, bytes, &rbytes, smps, cnt); + return sscan(in.buffer, bytes, &rbytes, smps, cnt); } -void Format::parse(json_t *json) -{ - int ret; - json_error_t err; +void Format::parse(json_t *json) { + int ret; + json_error_t err; - int ts_origin = -1; - int ts_received = -1; - int sequence = -1; - int data = -1; - int offset = -1; + int ts_origin = -1; + int ts_received = -1; + int sequence = -1; + int data = -1; + int offset = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: b, s?: b, s?: b, s?: b, s?: b, s?: i }", - "ts_origin", &ts_origin, - "ts_received", &ts_received, - "sequence", &sequence, - "data", &data, - "offset", &offset, - "real_precision", &real_precision - ); - if (ret) - throw ConfigError(json, err, "node-config-format", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: b, s?: b, s?: b, s?: b, s?: b, s?: i }", + "ts_origin", &ts_origin, "ts_received", &ts_received, + "sequence", &sequence, "data", &data, "offset", &offset, + "real_precision", &real_precision); + if (ret) + throw ConfigError(json, err, "node-config-format", + "Failed to parse format configuration"); - if (real_precision < 0 || real_precision > 31) - throw ConfigError(json, err, "node-config-format-precision", "The valid range for the real_precision setting is between 0 and 31 (inclusive)"); + if (real_precision < 0 || real_precision > 31) + throw ConfigError(json, err, "node-config-format-precision", + "The valid range for the real_precision setting is " + "between 0 and 31 (inclusive)"); - if (ts_origin == 0) - flags &= ~ (int) SampleFlags::HAS_TS_ORIGIN; + if (ts_origin == 0) + flags &= ~(int)SampleFlags::HAS_TS_ORIGIN; - if (ts_received == 0) - flags &= ~ (int) SampleFlags::HAS_TS_RECEIVED; + if (ts_received == 0) + flags &= ~(int)SampleFlags::HAS_TS_RECEIVED; - if (sequence == 0) - flags &= ~ (int) SampleFlags::HAS_SEQUENCE; + if (sequence == 0) + flags &= ~(int)SampleFlags::HAS_SEQUENCE; - if (data == 0) - flags &= ~ (int) SampleFlags::HAS_DATA; + if (data == 0) + flags &= ~(int)SampleFlags::HAS_DATA; - if (offset == 0) - flags &= ~ (int) SampleFlags::HAS_OFFSET; + if (offset == 0) + flags &= ~(int)SampleFlags::HAS_OFFSET; } diff --git a/lib/formats/column.cpp b/lib/formats/column.cpp index 12cbcdf67..0aeab52f2 100644 --- a/lib/formats/column.cpp +++ b/lib/formats/column.cpp @@ -9,183 +9,196 @@ #include #include +#include #include #include #include #include -#include using namespace villas; using namespace villas::node; -size_t ColumnLineFormat::sprintLine(char *buf, size_t len, const struct Sample *smp) -{ - size_t off = 0; +size_t ColumnLineFormat::sprintLine(char *buf, size_t len, + const struct Sample *smp) { + size_t off = 0; - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) - off += snprintf(buf + off, len - off, "%lld%c%09lld", (long long) smp->ts.origin.tv_sec, separator, - (long long) smp->ts.origin.tv_nsec); - else - off += snprintf(buf + off, len - off, "nan%cnan", separator); + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) + off += snprintf(buf + off, len - off, "%lld%c%09lld", + (long long)smp->ts.origin.tv_sec, separator, + (long long)smp->ts.origin.tv_nsec); + else + off += snprintf(buf + off, len - off, "nan%cnan", separator); - if (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED) - off += snprintf(buf + off, len - off, "%c%.09f", separator, time_delta(&smp->ts.origin, &smp->ts.received)); - else - off += snprintf(buf + off, len - off, "%cnan", separator); + if (smp->flags & (int)SampleFlags::HAS_TS_RECEIVED) + off += snprintf(buf + off, len - off, "%c%.09f", separator, + time_delta(&smp->ts.origin, &smp->ts.received)); + else + off += snprintf(buf + off, len - off, "%cnan", separator); - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) - off += snprintf(buf + off, len - off, "%c%" PRIu64, separator, smp->sequence); - else - off += snprintf(buf + off, len - off, "%cnan", separator); + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) + off += + snprintf(buf + off, len - off, "%c%" PRIu64, separator, smp->sequence); + else + off += snprintf(buf + off, len - off, "%cnan", separator); - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - break; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + break; - off += snprintf(buf + off, len - off, "%c", separator); - off += smp->data[i].printString(sig->type, buf + off, len - off, real_precision); - } + off += snprintf(buf + off, len - off, "%c", separator); + off += smp->data[i].printString(sig->type, buf + off, len - off, + real_precision); + } - off += snprintf(buf + off, len - off, "%c", delimiter); + off += snprintf(buf + off, len - off, "%c", delimiter); - return off; + return off; } -size_t ColumnLineFormat::sscanLine(const char *buf, size_t len, struct Sample *smp) -{ - int ret; - unsigned i = 0; - const char *ptr = buf; - char *end; +size_t ColumnLineFormat::sscanLine(const char *buf, size_t len, + struct Sample *smp) { + int ret; + unsigned i = 0; + const char *ptr = buf; + char *end; - struct timespec offset; + struct timespec offset; - smp->flags = 0; - smp->signals = signals; + smp->flags = 0; + smp->signals = signals; - smp->ts.origin.tv_sec = strtoul(ptr, &end, 10); - if (end == ptr || *end == delimiter) - goto out; + smp->ts.origin.tv_sec = strtoul(ptr, &end, 10); + if (end == ptr || *end == delimiter) + goto out; - ptr = end + 1; + ptr = end + 1; - smp->ts.origin.tv_nsec = strtoul(ptr, &end, 10); - if (end == ptr || *end == delimiter) - goto out; + smp->ts.origin.tv_nsec = strtoul(ptr, &end, 10); + if (end == ptr || *end == delimiter) + goto out; - ptr = end + 1; + ptr = end + 1; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; - offset = time_from_double(strtof(ptr, &end)); - if (end == ptr || *end == delimiter) - goto out; + offset = time_from_double(strtof(ptr, &end)); + if (end == ptr || *end == delimiter) + goto out; - smp->ts.received = time_add(&smp->ts.origin, &offset); + smp->ts.received = time_add(&smp->ts.origin, &offset); - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; - ptr = end + 1; + ptr = end + 1; - smp->sequence = strtoul(ptr, &end, 10); - if (end == ptr || *end == delimiter) - goto out; + smp->sequence = strtoul(ptr, &end, 10); + if (end == ptr || *end == delimiter) + goto out; - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; - for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) { - if (*end == delimiter) - goto out; + for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) { + if (*end == delimiter) + goto out; - auto sig = smp->signals->getByIndex(i); - if (!sig) - goto out; + auto sig = smp->signals->getByIndex(i); + if (!sig) + goto out; - ret = smp->data[i].parseString(sig->type, ptr, &end); - if (ret || end == ptr) // There are no valid values anymore. - goto out; - } + ret = smp->data[i].parseString(sig->type, ptr, &end); + if (ret || end == ptr) // There are no valid values anymore. + goto out; + } -out: if (*end == delimiter) - end++; +out: + if (*end == delimiter) + end++; - smp->length = i; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + smp->length = i; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return end - buf; + return end - buf; } -void ColumnLineFormat::header(FILE *f, const SignalList::Ptr sigs) -{ - // Abort if we are not supposed to, or have already printed the header - if (!print_header || header_printed) - return; +void ColumnLineFormat::header(FILE *f, const SignalList::Ptr sigs) { + // Abort if we are not supposed to, or have already printed the header + if (!print_header || header_printed) + return; - if (comment) - fprintf(f, "%c", comment); + if (comment) + fprintf(f, "%c", comment); - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) - fprintf(f, "secs%cnsecs%c", separator, separator); + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) + fprintf(f, "secs%cnsecs%c", separator, separator); - if (flags & (int) SampleFlags::HAS_OFFSET) - fprintf(f, "offset%c", separator); + if (flags & (int)SampleFlags::HAS_OFFSET) + fprintf(f, "offset%c", separator); - if (flags & (int) SampleFlags::HAS_SEQUENCE) - fprintf(f, "sequence%c", separator); + if (flags & (int)SampleFlags::HAS_SEQUENCE) + fprintf(f, "sequence%c", separator); - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned i = 0; i < sigs->size(); i++) { - auto sig = sigs->getByIndex(i); - if (!sig) - break; + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned i = 0; i < sigs->size(); i++) { + auto sig = sigs->getByIndex(i); + if (!sig) + break; - if (!sig->name.empty()) - fprintf(f, "%s", sig->name.c_str()); - else - fprintf(f, "signal%u", i); + if (!sig->name.empty()) + fprintf(f, "%s", sig->name.c_str()); + else + fprintf(f, "signal%u", i); - if (!sig->unit.empty()) - fprintf(f, "[%s]", sig->unit.c_str()); + if (!sig->unit.empty()) + fprintf(f, "[%s]", sig->unit.c_str()); - if (i + 1 < sigs->size()) - fprintf(f, "%c", separator); - } - } + if (i + 1 < sigs->size()) + fprintf(f, "%c", separator); + } + } - fprintf(f, "%c", delimiter); + fprintf(f, "%c", delimiter); - LineFormat::header(f, sigs); + LineFormat::header(f, sigs); } -void ColumnLineFormat::parse(json_t *json) -{ - int ret; - json_error_t err; - const char *sep = nullptr; +void ColumnLineFormat::parse(json_t *json) { + int ret; + json_error_t err; + const char *sep = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s }", - "separator", &sep - ); - if (ret) - throw ConfigError(json, err, "node-config-format-column", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s }", "separator", &sep); + if (ret) + throw ConfigError(json, err, "node-config-format-column", + "Failed to parse format configuration"); - if (sep) { - if (strlen(sep) != 1) - throw ConfigError(json, "node-config-format-column-separator", "Column separator must be a single character!"); + if (sep) { + if (strlen(sep) != 1) + throw ConfigError(json, "node-config-format-column-separator", + "Column separator must be a single character!"); - separator = sep[0]; - } + separator = sep[0]; + } - LineFormat::parse(json); + LineFormat::parse(json); } // Register formats static char n1[] = "csv"; static char d1[] = "Comma-separated values"; -static ColumnLineFormatPlugin p1; +static ColumnLineFormatPlugin + p1; static char n2[] = "tsv"; static char d2[] = "Tabulator-separated values"; -static ColumnLineFormatPlugin p2; +static ColumnLineFormatPlugin + p2; diff --git a/lib/formats/iotagent_ul.cpp b/lib/formats/iotagent_ul.cpp index 069fa9d40..8ba278a1b 100644 --- a/lib/formats/iotagent_ul.cpp +++ b/lib/formats/iotagent_ul.cpp @@ -9,45 +9,52 @@ #include -#include -#include -#include #include -#include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; -int IotAgentUltraLightFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - size_t printed = 0; - const struct Sample *smp = smps[0]; +int IotAgentUltraLightFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], + unsigned cnt) { + size_t printed = 0; + const struct Sample *smp = smps[0]; - for (unsigned i = 0; (i < smp->length) && (printed < len); i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; (i < smp->length) && (printed < len); i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - if (!sig->name.empty()) - printed += snprintf(buf + printed, len - printed, "%s|%f|", sig->name.c_str(), smp->data[i].f); - else { - printed += snprintf(buf + printed, len - printed, "signal_%u|%f|", i, smp->data[i].f); - } - } + if (!sig->name.empty()) + printed += snprintf(buf + printed, len - printed, "%s|%f|", + sig->name.c_str(), smp->data[i].f); + else { + printed += snprintf(buf + printed, len - printed, "signal_%u|%f|", i, + smp->data[i].f); + } + } - if (wbytes) - *wbytes = printed - 1; // -1 to cut off last '|' + if (wbytes) + *wbytes = printed - 1; // -1 to cut off last '|' - return 0; + return 0; } -int IotAgentUltraLightFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - return -1; +int IotAgentUltraLightFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + return -1; } // Register format static char n[] = "iotagent_ul"; static char d[] = "FIWARE IotAgent UltraLight format"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/json.cpp b/lib/formats/json.cpp index 854255f8c..d67d0475b 100644 --- a/lib/formats/json.cpp +++ b/lib/formats/json.cpp @@ -5,369 +5,371 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include -#include #include +#include +#include +#include using namespace villas; using namespace villas::node; -enum SignalType JsonFormat::detect(const json_t *val) -{ - int type = json_typeof(val); +enum SignalType JsonFormat::detect(const json_t *val) { + int type = json_typeof(val); - switch (type) { - case JSON_REAL: - return SignalType::FLOAT; + switch (type) { + case JSON_REAL: + return SignalType::FLOAT; - case JSON_INTEGER: - return SignalType::INTEGER; + case JSON_INTEGER: + return SignalType::INTEGER; - case JSON_TRUE: - case JSON_FALSE: - return SignalType::BOOLEAN; + case JSON_TRUE: + case JSON_FALSE: + return SignalType::BOOLEAN; - case JSON_OBJECT: - return SignalType::COMPLEX; // must be a complex number + case JSON_OBJECT: + return SignalType::COMPLEX; // must be a complex number - default: - return SignalType::INVALID; - } + default: + return SignalType::INVALID; + } } -json_t * JsonFormat::packTimestamps(const struct Sample *smp) -{ - json_t *json_ts = json_object(); +json_t *JsonFormat::packTimestamps(const struct Sample *smp) { + json_t *json_ts = json_object(); #ifdef __arm__ // TODO: check - const char *fmt = "[ i, i ]"; + const char *fmt = "[ i, i ]"; #else - const char *fmt = "[ I, I ]"; + const char *fmt = "[ I, I ]"; #endif - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) - json_object_set(json_ts, "origin", json_pack(fmt, smp->ts.origin.tv_sec, smp->ts.origin.tv_nsec)); - } + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) { + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) + json_object_set( + json_ts, "origin", + json_pack(fmt, smp->ts.origin.tv_sec, smp->ts.origin.tv_nsec)); + } - if (flags & (int) SampleFlags::HAS_TS_RECEIVED) { - if (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED) - json_object_set(json_ts, "received", json_pack(fmt, smp->ts.received.tv_sec, smp->ts.received.tv_nsec)); - } + if (flags & (int)SampleFlags::HAS_TS_RECEIVED) { + if (smp->flags & (int)SampleFlags::HAS_TS_RECEIVED) + json_object_set( + json_ts, "received", + json_pack(fmt, smp->ts.received.tv_sec, smp->ts.received.tv_nsec)); + } - return json_ts; + return json_ts; } -int JsonFormat::unpackTimestamps(json_t *json_ts, struct Sample *smp) -{ - int ret; - json_error_t err; - json_t *json_ts_origin = nullptr; - json_t *json_ts_received = nullptr; +int JsonFormat::unpackTimestamps(json_t *json_ts, struct Sample *smp) { + int ret; + json_error_t err; + json_t *json_ts_origin = nullptr; + json_t *json_ts_received = nullptr; - json_unpack_ex(json_ts, &err, 0, "{ s?: o, s?: o }", - "origin", &json_ts_origin, - "received", &json_ts_received - ); + json_unpack_ex(json_ts, &err, 0, "{ s?: o, s?: o }", "origin", + &json_ts_origin, "received", &json_ts_received); - if (json_ts_origin) { - ret = json_unpack_ex(json_ts_origin, &err, 0, "[ I, I ]", &smp->ts.origin.tv_sec, &smp->ts.origin.tv_nsec); - if (ret) - return ret; + if (json_ts_origin) { + ret = json_unpack_ex(json_ts_origin, &err, 0, "[ I, I ]", + &smp->ts.origin.tv_sec, &smp->ts.origin.tv_nsec); + if (ret) + return ret; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - if (json_ts_received) { - ret = json_unpack_ex(json_ts_received, &err, 0, "[ I, I ]", &smp->ts.received.tv_sec, &smp->ts.received.tv_nsec); - if (ret) - return ret; + if (json_ts_received) { + ret = json_unpack_ex(json_ts_received, &err, 0, "[ I, I ]", + &smp->ts.received.tv_sec, &smp->ts.received.tv_nsec); + if (ret) + return ret; - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - return 0; + return 0; } -int JsonFormat::packSample(json_t **json_smp, const struct Sample *smp) -{ - json_t *json_root; - json_error_t err; +int JsonFormat::packSample(json_t **json_smp, const struct Sample *smp) { + json_t *json_root; + json_error_t err; - json_root = json_pack_ex(&err, 0, "{ s: o }", "ts", packTimestamps(smp)); + json_root = json_pack_ex(&err, 0, "{ s: o }", "ts", packTimestamps(smp)); - if (flags & (int) SampleFlags::HAS_SEQUENCE) { - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) { - json_t *json_sequence = json_integer(smp->sequence); + if (flags & (int)SampleFlags::HAS_SEQUENCE) { + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) { + json_t *json_sequence = json_integer(smp->sequence); - json_object_set_new(json_root, "sequence", json_sequence); - } - } + json_object_set_new(json_root, "sequence", json_sequence); + } + } - if (flags & (int) SampleFlags::HAS_DATA) { - json_t *json_data = json_array(); + if (flags & (int)SampleFlags::HAS_DATA) { + json_t *json_data = json_array(); - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - json_t *json_value = smp->data[i].toJson(sig->type); + json_t *json_value = smp->data[i].toJson(sig->type); - json_array_append_new(json_data, json_value); - } + json_array_append_new(json_data, json_value); + } - json_object_set_new(json_root, "data", json_data); - } + json_object_set_new(json_root, "data", json_data); + } - *json_smp = json_root; + *json_smp = json_root; - return 0; + return 0; } -int JsonFormat::packSamples(json_t **json_smps, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - json_t *json_root = json_array(); +int JsonFormat::packSamples(json_t **json_smps, + const struct Sample *const smps[], unsigned cnt) { + int ret; + json_t *json_root = json_array(); - for (unsigned i = 0; i < cnt; i++) { - json_t *json_smp; + for (unsigned i = 0; i < cnt; i++) { + json_t *json_smp; - ret = packSample(&json_smp, smps[i]); - if (ret) - break; + ret = packSample(&json_smp, smps[i]); + if (ret) + break; - json_array_append_new(json_root, json_smp); - } + json_array_append_new(json_root, json_smp); + } - *json_smps = json_root; + *json_smps = json_root; - return cnt; + return cnt; } -int JsonFormat::unpackSample(json_t *json_smp, struct Sample *smp) -{ - int ret; - json_error_t err; - json_t *json_data, *json_value, *json_ts = nullptr; - size_t i; - int64_t sequence = -1; +int JsonFormat::unpackSample(json_t *json_smp, struct Sample *smp) { + int ret; + json_error_t err; + json_t *json_data, *json_value, *json_ts = nullptr; + size_t i; + int64_t sequence = -1; - smp->signals = signals; + smp->signals = signals; - ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: I, s: o }", - "ts", &json_ts, - "sequence", &sequence, - "data", &json_data); - if (ret) - return ret; + ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: I, s: o }", "ts", + &json_ts, "sequence", &sequence, "data", &json_data); + if (ret) + return ret; - smp->flags = 0; - smp->length = 0; + smp->flags = 0; + smp->length = 0; - if (json_ts) { - ret = unpackTimestamps(json_ts, smp); - if (ret) - return ret; - } + if (json_ts) { + ret = unpackTimestamps(json_ts, smp); + if (ret) + return ret; + } - if (!json_is_array(json_data)) - return -1; + if (!json_is_array(json_data)) + return -1; - if (sequence >= 0) { - smp->sequence = sequence; - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - } + if (sequence >= 0) { + smp->sequence = sequence; + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + } - json_array_foreach(json_data, i, json_value) { - if (i >= smp->capacity) - break; + json_array_foreach(json_data, i, json_value) { + if (i >= smp->capacity) + break; - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - enum SignalType fmt = detect(json_value); - if (sig->type != fmt) - throw RuntimeError("Received invalid data type in JSON payload: Received {}, expected {} for signal {} (index {}).", - signalTypeToString(fmt), signalTypeToString(sig->type), sig->name, i); + enum SignalType fmt = detect(json_value); + if (sig->type != fmt) + throw RuntimeError("Received invalid data type in JSON payload: Received " + "{}, expected {} for signal {} (index {}).", + signalTypeToString(fmt), signalTypeToString(sig->type), + sig->name, i); - ret = smp->data[i].parseJson(sig->type, json_value); - if (ret) - return -3; + ret = smp->data[i].parseJson(sig->type, json_value); + if (ret) + return -3; - smp->length++; - } + smp->length++; + } - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return 0; + return 0; } -int JsonFormat::unpackSamples(json_t *json_smps, struct Sample * const smps[], unsigned cnt) -{ - int ret; - json_t *json_smp; - size_t i; +int JsonFormat::unpackSamples(json_t *json_smps, struct Sample *const smps[], + unsigned cnt) { + int ret; + json_t *json_smp; + size_t i; - if (!json_is_array(json_smps)) - return -1; + if (!json_is_array(json_smps)) + return -1; - json_array_foreach(json_smps, i, json_smp) { - if (i >= cnt) - break; + json_array_foreach(json_smps, i, json_smp) { + if (i >= cnt) + break; - ret = unpackSample(json_smp, smps[i]); - if (ret < 0) - break; - } + ret = unpackSample(json_smp, smps[i]); + if (ret < 0) + break; + } - return i; + return i; } -int JsonFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - json_t *json; - size_t wr; +int JsonFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + int ret; + json_t *json; + size_t wr; - ret = packSamples(&json, smps, cnt); - if (ret < 0) - return ret; + ret = packSamples(&json, smps, cnt); + if (ret < 0) + return ret; - wr = json_dumpb(json, buf, len, dump_flags); + wr = json_dumpb(json, buf, len, dump_flags); - json_decref(json); + json_decref(json); - if (wbytes) - *wbytes = wr; + if (wbytes) + *wbytes = wr; - return ret; + return ret; } -int JsonFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - int ret; - json_t *json; - json_error_t err; +int JsonFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + int ret; + json_t *json; + json_error_t err; - json = json_loadb(buf, len, 0, &err); - if (!json) - return -1; + json = json_loadb(buf, len, 0, &err); + if (!json) + return -1; - ret = unpackSamples(json, smps, cnt); + ret = unpackSamples(json, smps, cnt); - json_decref(json); + json_decref(json); - if (ret < 0) - return ret; + if (ret < 0) + return ret; - if (rbytes) - *rbytes = err.position; + if (rbytes) + *rbytes = err.position; - return ret; + return ret; } -int JsonFormat::print(FILE *f, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; - json_t *json; +int JsonFormat::print(FILE *f, const struct Sample *const smps[], + unsigned cnt) { + int ret; + unsigned i; + json_t *json; - for (i = 0; i < cnt; i++) { - ret = packSample(&json, smps[i]); - if (ret) - return ret; + for (i = 0; i < cnt; i++) { + ret = packSample(&json, smps[i]); + if (ret) + return ret; - ret = json_dumpf(json, f, dump_flags); - fputc('\n', f); + ret = json_dumpf(json, f, dump_flags); + fputc('\n', f); - json_decref(json); + json_decref(json); - if (ret) - return ret; - } + if (ret) + return ret; + } - return i; + return i; } -int JsonFormat::scan(FILE *f, struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; - json_t *json; - json_error_t err; +int JsonFormat::scan(FILE *f, struct Sample *const smps[], unsigned cnt) { + int ret; + unsigned i; + json_t *json; + json_error_t err; - for (i = 0; i < cnt; i++) { - if (feof(f)) - return -1; + for (i = 0; i < cnt; i++) { + if (feof(f)) + return -1; -skip: json = json_loadf(f, JSON_DISABLE_EOF_CHECK, &err); - if (!json) - break; + skip: + json = json_loadf(f, JSON_DISABLE_EOF_CHECK, &err); + if (!json) + break; - ret = unpackSample(json, smps[i]); - if (ret) - goto skip; + ret = unpackSample(json, smps[i]); + if (ret) + goto skip; - json_decref(json); - } + json_decref(json); + } - return i; + return i; } -void JsonFormat::parse(json_t *json) -{ - int ret; - json_error_t err; +void JsonFormat::parse(json_t *json) { + int ret; + json_error_t err; - int indent = 0; - int compact = 0; - int ensure_ascii = 0; - int escape_slash = 0; - int sort_keys = 0; + int indent = 0; + int compact = 0; + int ensure_ascii = 0; + int escape_slash = 0; + int sort_keys = 0; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b, s?: b, s?: b, s?: b }", - "indent", &indent, - "compact", &compact, - "ensure_ascii", &ensure_ascii, - "escape_slash", &escape_slash, - "sort_keys", &sort_keys + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b, s?: b, s?: b, s?: b }", + "indent", &indent, "compact", &compact, "ensure_ascii", + &ensure_ascii, "escape_slash", &escape_slash, + "sort_keys", &sort_keys - ); - if (ret) - throw ConfigError(json, err, "node-config-format-json", "Failed to parse format configuration"); + ); + if (ret) + throw ConfigError(json, err, "node-config-format-json", + "Failed to parse format configuration"); - if (indent > JSON_MAX_INDENT) - throw ConfigError(json, "node-config-format-json-indent", "The maximum indentation level is {}", JSON_MAX_INDENT); + if (indent > JSON_MAX_INDENT) + throw ConfigError(json, "node-config-format-json-indent", + "The maximum indentation level is {}", JSON_MAX_INDENT); - dump_flags = 0; + dump_flags = 0; - if (indent) - dump_flags |= JSON_INDENT(indent); + if (indent) + dump_flags |= JSON_INDENT(indent); - if (compact) - dump_flags |= JSON_COMPACT; + if (compact) + dump_flags |= JSON_COMPACT; - if (ensure_ascii) - dump_flags |= JSON_ENSURE_ASCII; + if (ensure_ascii) + dump_flags |= JSON_ENSURE_ASCII; - if (escape_slash) - dump_flags |= JSON_ESCAPE_SLASH; + if (escape_slash) + dump_flags |= JSON_ESCAPE_SLASH; - if (sort_keys) - dump_flags |= JSON_SORT_KEYS; + if (sort_keys) + dump_flags |= JSON_SORT_KEYS; - Format::parse(json); + Format::parse(json); - if (real_precision) - dump_flags |= JSON_REAL_PRECISION(real_precision); + if (real_precision) + dump_flags |= JSON_REAL_PRECISION(real_precision); } // Register format static char n[] = "json"; static char d[] = "Javascript Object Notation"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/json_edgeflex.cpp b/lib/formats/json_edgeflex.cpp index eaee6236b..861a2314c 100644 --- a/lib/formats/json_edgeflex.cpp +++ b/lib/formats/json_edgeflex.cpp @@ -7,92 +7,95 @@ #include -#include #include +#include using namespace villas::node; -int JsonEdgeflexFormat::packSample(json_t **json_smp, const struct Sample *smp) -{ - json_t *json_data, *json_value; - json_t *json_created = nullptr; +int JsonEdgeflexFormat::packSample(json_t **json_smp, + const struct Sample *smp) { + json_t *json_data, *json_value; + json_t *json_created = nullptr; - if (smp->length < 1) - return -1; + if (smp->length < 1) + return -1; - json_data = json_object(); + json_data = json_object(); - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - json_value = smp->data[i].toJson(sig->type); - json_object_set(json_data, sig->name.c_str(), json_value); - } + json_value = smp->data[i].toJson(sig->type); + json_object_set(json_data, sig->name.c_str(), json_value); + } - json_created = json_integer(time_to_double(&smp->ts.origin) * 1e3); - json_object_set(json_data, "created", json_created); + json_created = json_integer(time_to_double(&smp->ts.origin) * 1e3); + json_object_set(json_data, "created", json_created); - *json_smp = json_data; + *json_smp = json_data; - return 0; + return 0; } -int JsonEdgeflexFormat::unpackSample(json_t *json_smp, struct Sample *smp) -{ - int ret; - const char *key; - json_t *json_value, *json_created = nullptr; - json_int_t created = -1; +int JsonEdgeflexFormat::unpackSample(json_t *json_smp, struct Sample *smp) { + int ret; + const char *key; + json_t *json_value, *json_created = nullptr; + json_int_t created = -1; - if (smp->capacity < 1) - return -1; + if (smp->capacity < 1) + return -1; - if (json_typeof(json_smp) != JSON_OBJECT) - return -1; + if (json_typeof(json_smp) != JSON_OBJECT) + return -1; - json_object_foreach(json_smp, key, json_value) { - if (!strcmp(key, "created")) - json_created = json_incref(json_value); - else { - auto idx = signals->getIndexByName(key); - if (idx < 0) { - ret = sscanf(key, "signal_%d", &idx); - if (ret != 1) - continue; + json_object_foreach(json_smp, key, json_value) { + if (!strcmp(key, "created")) + json_created = json_incref(json_value); + else { + auto idx = signals->getIndexByName(key); + if (idx < 0) { + ret = sscanf(key, "signal_%d", &idx); + if (ret != 1) + continue; - if (idx < 0) - return -1; - } + if (idx < 0) + return -1; + } - auto sig = signals->getByIndex(idx); + auto sig = signals->getByIndex(idx); - if (idx < (int) smp->capacity) { - ret = smp->data[idx].parseJson(sig->type, json_value); - if (ret) - return ret; - } + if (idx < (int)smp->capacity) { + ret = smp->data[idx].parseJson(sig->type, json_value); + if (ret) + return ret; + } - if (idx >= (int) smp->length) - smp->length = idx + 1; - } - } + if (idx >= (int)smp->length) + smp->length = idx + 1; + } + } - if (!json_created || !json_is_number(json_created)) - return -1; + if (!json_created || !json_is_number(json_created)) + return -1; - created = json_number_value(json_created); - smp->ts.origin = time_from_double(created / 1e3); + created = json_number_value(json_created); + smp->ts.origin = time_from_double(created / 1e3); - smp->flags = (int) SampleFlags::HAS_TS_ORIGIN; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + smp->flags = (int)SampleFlags::HAS_TS_ORIGIN; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return 0; + return 0; } // Register format static char n[] = "json.edgeflex"; static char d[] = "EdgeFlex JSON format"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/json_kafka.cpp b/lib/formats/json_kafka.cpp index 4bae33c7b..32f1c6e25 100644 --- a/lib/formats/json_kafka.cpp +++ b/lib/formats/json_kafka.cpp @@ -5,178 +5,165 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include #include -#include -#include using namespace villas; using namespace villas::node; -const char * JsonKafkaFormat::villasToKafkaType(enum SignalType vt) -{ - switch (vt) { - case SignalType::FLOAT: - return "double"; +const char *JsonKafkaFormat::villasToKafkaType(enum SignalType vt) { + switch (vt) { + case SignalType::FLOAT: + return "double"; - case SignalType::INTEGER: - return "int64"; + case SignalType::INTEGER: + return "int64"; - case SignalType::BOOLEAN: - return "boolean"; + case SignalType::BOOLEAN: + return "boolean"; - default: - case SignalType::COMPLEX: - case SignalType::INVALID: - return "unknown"; - } + default: + case SignalType::COMPLEX: + case SignalType::INVALID: + return "unknown"; + } } -int JsonKafkaFormat::packSample(json_t **json_smp, const struct Sample *smp) -{ - json_t *json_payload, *json_fields, *json_field, *json_value; +int JsonKafkaFormat::packSample(json_t **json_smp, const struct Sample *smp) { + json_t *json_payload, *json_fields, *json_field, *json_value; - json_fields = json_array(); - json_payload = json_object(); + json_fields = json_array(); + json_payload = json_object(); - // Include sample timestamp - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) { - json_field = json_pack("{ s: s, s: b, s: s }", - "type", "int64", - "optional", false, - "field", "timestamp" - ); + // Include sample timestamp + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + json_field = json_pack("{ s: s, s: b, s: s }", "type", "int64", "optional", + false, "field", "timestamp"); - uint64_t ts_origin_ms = smp->ts.origin.tv_sec * 1e3 + smp->ts.origin.tv_nsec / 1e6; - json_array_append_new(json_fields, json_field); - json_object_set_new(json_payload, "timestamp", json_integer(ts_origin_ms)); - } + uint64_t ts_origin_ms = + smp->ts.origin.tv_sec * 1e3 + smp->ts.origin.tv_nsec / 1e6; + json_array_append_new(json_fields, json_field); + json_object_set_new(json_payload, "timestamp", json_integer(ts_origin_ms)); + } - // Include sample sequence no - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) { - json_field = json_pack("{ s: s, s: b, s: s }", - "type", "int64", - "optional", false, - "field", "sequence" - ); + // Include sample sequence no + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) { + json_field = json_pack("{ s: s, s: b, s: s }", "type", "int64", "optional", + false, "field", "sequence"); - json_array_append_new(json_fields, json_field); - json_object_set_new(json_payload, "sequence", json_integer(smp->sequence)); - } + json_array_append_new(json_fields, json_field); + json_object_set_new(json_payload, "sequence", json_integer(smp->sequence)); + } - // Include sample data - for (size_t i = 0; i < MIN(smp->length, smp->signals->size()); i++) { - const auto sig = smp->signals->getByIndex(i); - const auto *data = &smp->data[i]; + // Include sample data + for (size_t i = 0; i < MIN(smp->length, smp->signals->size()); i++) { + const auto sig = smp->signals->getByIndex(i); + const auto *data = &smp->data[i]; - json_field = json_pack("{ s: s, s: b, s: s }", - "type", villasToKafkaType(sig->type), - "optional", false, - "field", sig->name - ); + json_field = + json_pack("{ s: s, s: b, s: s }", "type", villasToKafkaType(sig->type), + "optional", false, "field", sig->name); - json_value = data->toJson(sig->type); + json_value = data->toJson(sig->type); - json_array_append_new(json_fields, json_field); - json_object_set_new(json_payload, sig->name.c_str(), json_value); - } + json_array_append_new(json_fields, json_field); + json_object_set_new(json_payload, sig->name.c_str(), json_value); + } - json_object_set_new(json_schema, "fields", json_fields); + json_object_set_new(json_schema, "fields", json_fields); - json_incref(json_schema); - *json_smp = json_pack("{ s: o, s: o }", - "schema", json_schema, - "payload", json_payload - ); - if (*json_smp == nullptr) - return -1; + json_incref(json_schema); + *json_smp = json_pack("{ s: o, s: o }", "schema", json_schema, "payload", + json_payload); + if (*json_smp == nullptr) + return -1; - return 0; + return 0; } -int JsonKafkaFormat::unpackSample(json_t *json_smp, struct Sample *smp) -{ - json_t *json_payload, *json_value; +int JsonKafkaFormat::unpackSample(json_t *json_smp, struct Sample *smp) { + json_t *json_payload, *json_value; - json_payload = json_object_get(json_smp, "payload"); - if (!json_payload) - return -1; + json_payload = json_object_get(json_smp, "payload"); + if (!json_payload) + return -1; - smp->length = 0; - smp->flags = 0; - smp->signals = signals; + smp->length = 0; + smp->flags = 0; + smp->signals = signals; - // Unpack timestamp - json_value = json_object_get(json_payload, "timestamp"); - if (json_value) { - uint64_t ts_origin_ms = json_integer_value(json_value); - smp->ts.origin = time_from_double(ts_origin_ms / 1e3); + // Unpack timestamp + json_value = json_object_get(json_payload, "timestamp"); + if (json_value) { + uint64_t ts_origin_ms = json_integer_value(json_value); + smp->ts.origin = time_from_double(ts_origin_ms / 1e3); - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - // Unpack sequence no - json_value = json_object_get(json_payload, "sequence"); - if (json_value) { - smp->sequence = json_integer_value(json_value); + // Unpack sequence no + json_value = json_object_get(json_payload, "sequence"); + if (json_value) { + smp->sequence = json_integer_value(json_value); - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - } + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + } - // Unpack signal data - for (size_t i = 0; i < signals->size(); i++) { - auto sig = signals->getByIndex(i); + // Unpack signal data + for (size_t i = 0; i < signals->size(); i++) { + auto sig = signals->getByIndex(i); - json_value = json_object_get(json_payload, sig->name.c_str()); - if (!json_value) - continue; + json_value = json_object_get(json_payload, sig->name.c_str()); + if (!json_value) + continue; - smp->data[i].parseJson(sig->type, json_value); - smp->length++; - } + smp->data[i].parseJson(sig->type, json_value); + smp->length++; + } - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return 0; + return 0; } -void JsonKafkaFormat::parse(json_t *json) -{ - int ret; +void JsonKafkaFormat::parse(json_t *json) { + int ret; - json_error_t err; - json_t *json_schema_tmp = nullptr; + json_error_t err; + json_t *json_schema_tmp = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: o }", - "schema", &json_schema_tmp - ); - if (ret) - throw ConfigError(json, err, "node-config-format-json-kafka", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o }", "schema", &json_schema_tmp); + if (ret) + throw ConfigError(json, err, "node-config-format-json-kafka", + "Failed to parse format configuration"); - if (json_schema_tmp) { - if (!json_is_object(json_schema_tmp)) - throw ConfigError(json, "node-config-format-json-kafka-schema", "Kafka schema must be configured as a dictionary"); + if (json_schema_tmp) { + if (!json_is_object(json_schema_tmp)) + throw ConfigError(json, "node-config-format-json-kafka-schema", + "Kafka schema must be configured as a dictionary"); - if (json_schema) - json_decref(json_schema); + if (json_schema) + json_decref(json_schema); - json_schema = json_schema_tmp; - } + json_schema = json_schema_tmp; + } - JsonFormat::parse(json); + JsonFormat::parse(json); } -JsonKafkaFormat::JsonKafkaFormat(int fl) : - JsonFormat(fl) -{ - json_schema = json_pack("{ s: s, s: s }", - "type", "struct", - "name", "villas-node.Value" - ); +JsonKafkaFormat::JsonKafkaFormat(int fl) : JsonFormat(fl) { + json_schema = json_pack("{ s: s, s: s }", "type", "struct", "name", + "villas-node.Value"); } // Register format static char n[] = "json.kafka"; static char d[] = "JSON Kafka schema/payload messages"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/json_reserve.cpp b/lib/formats/json_reserve.cpp index 29913a1b8..14128a261 100644 --- a/lib/formats/json_reserve.cpp +++ b/lib/formats/json_reserve.cpp @@ -7,73 +7,68 @@ #include -#include #include +#include using namespace villas::node; #define JSON_RESERVE_INTEGER_TARGET 1 -int JsonReserveFormat::packSample(json_t **json_smp, const struct Sample *smp) -{ - json_error_t err; - json_t *json_root; - json_t *json_data; - json_t *json_name; - json_t *json_unit; - json_t *json_value; - json_t *json_created = nullptr; - json_t *json_sequence = nullptr; +int JsonReserveFormat::packSample(json_t **json_smp, const struct Sample *smp) { + json_error_t err; + json_t *json_root; + json_t *json_data; + json_t *json_name; + json_t *json_unit; + json_t *json_value; + json_t *json_created = nullptr; + json_t *json_sequence = nullptr; - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) - json_created = json_integer(time_to_double(&smp->ts.origin) * 1e3); + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) + json_created = json_integer(time_to_double(&smp->ts.origin) * 1e3); - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) - json_sequence = json_integer(smp->sequence); + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) + json_sequence = json_integer(smp->sequence); - json_data = json_array(); + json_data = json_array(); - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - if (!sig->name.empty()) - json_name = json_string(sig->name.c_str()); - else { - char name[32]; - snprintf(name, 32, "signal%u", i); + if (!sig->name.empty()) + json_name = json_string(sig->name.c_str()); + else { + char name[32]; + snprintf(name, 32, "signal%u", i); - json_name = json_string(name); - } + json_name = json_string(name); + } - if (!sig->unit.empty()) - json_unit = json_string(sig->unit.c_str()); - else - json_unit = nullptr; + if (!sig->unit.empty()) + json_unit = json_string(sig->unit.c_str()); + else + json_unit = nullptr; - json_value = json_pack_ex(&err, 0, "{ s: o, s: f }", - "name", json_name, - "value", smp->data[i].f - ); - if (!json_value) - continue; + json_value = json_pack_ex(&err, 0, "{ s: o, s: f }", "name", json_name, + "value", smp->data[i].f); + if (!json_value) + continue; - if (json_unit) - json_object_set_new(json_value, "unit", json_unit); - if (json_created) - json_object_set_new(json_value, "created", json_created); - if (json_sequence) - json_object_set_new(json_value, "sequence", json_sequence); + if (json_unit) + json_object_set_new(json_value, "unit", json_unit); + if (json_created) + json_object_set_new(json_value, "created", json_created); + if (json_sequence) + json_object_set_new(json_value, "sequence", json_sequence); - json_array_append_new(json_data, json_value); - } + json_array_append_new(json_data, json_value); + } - json_root = json_pack_ex(&err, 0, "{ s: o }", - "measurements", json_data - ); - if (json_root == nullptr) - return -1; + json_root = json_pack_ex(&err, 0, "{ s: o }", "measurements", json_data); + if (json_root == nullptr) + return -1; #if 0 #ifdef JSON_RESERVE_INTEGER_TARGET if (io->out.node) { @@ -94,28 +89,24 @@ int JsonReserveFormat::packSample(json_t **json_smp, const struct Sample *smp) #endif #endif - *json_smp = json_root; + *json_smp = json_root; - return 0; + return 0; } -int JsonReserveFormat::unpackSample(json_t *json_smp, struct Sample *smp) -{ - int ret, idx; - double created = -1; - json_error_t err; - json_t *json_value, *json_data = nullptr; - json_t *json_origin = nullptr, *json_target = nullptr; - size_t i; +int JsonReserveFormat::unpackSample(json_t *json_smp, struct Sample *smp) { + int ret, idx; + double created = -1; + json_error_t err; + json_t *json_value, *json_data = nullptr; + json_t *json_origin = nullptr, *json_target = nullptr; + size_t i; - ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: o, s?: o, s?: o }", - "origin", &json_origin, - "target", &json_target, - "measurements", &json_data, - "setpoints", &json_data - ); - if (ret) - return -1; + ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: o, s?: o, s?: o }", + "origin", &json_origin, "target", &json_target, + "measurements", &json_data, "setpoints", &json_data); + if (ret) + return -1; #if 0 #ifdef JSON_RESERVE_INTEGER_TARGET @@ -146,57 +137,58 @@ int JsonReserveFormat::unpackSample(json_t *json_smp, struct Sample *smp) } #endif #endif - if (!json_data || !json_is_array(json_data)) - return -1; + if (!json_data || !json_is_array(json_data)) + return -1; - smp->flags = 0; - smp->length = 0; + smp->flags = 0; + smp->length = 0; - json_array_foreach(json_data, i, json_value) { - const char *name, *unit = nullptr; - double value; + json_array_foreach(json_data, i, json_value) { + const char *name, *unit = nullptr; + double value; - ret = json_unpack_ex(json_value, &err, 0, "{ s: s, s?: s, s: F, s?: F }", - "name", &name, - "unit", &unit, - "value", &value, - "created", &created - ); - if (ret) - return -1; + ret = json_unpack_ex(json_value, &err, 0, "{ s: s, s?: s, s: F, s?: F }", + "name", &name, "unit", &unit, "value", &value, + "created", &created); + if (ret) + return -1; - auto sig = signals->getByName(name); - if (sig) - idx = signals->getIndexByName(name); - else { - ret = sscanf(name, "signal_%d", &idx); - if (ret != 1) - continue; - } + auto sig = signals->getByName(name); + if (sig) + idx = signals->getIndexByName(name); + else { + ret = sscanf(name, "signal_%d", &idx); + if (ret != 1) + continue; + } - if (idx < 0) - return -1; + if (idx < 0) + return -1; - if (idx < (int) smp->capacity) { - smp->data[idx].f = value; + if (idx < (int)smp->capacity) { + smp->data[idx].f = value; - if (idx >= (int) smp->length) - smp->length = idx + 1; - } - } + if (idx >= (int)smp->length) + smp->length = idx + 1; + } + } - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - if (created > 0) { - smp->ts.origin = time_from_double(created * 1e-3); - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + if (created > 0) { + smp->ts.origin = time_from_double(created * 1e-3); + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - return smp->length > 0 ? 1 : 0; + return smp->length > 0 ? 1 : 0; } // Register format static char n[] = "json.reserve"; static char d[] = "RESERVE JSON format"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/line.cpp b/lib/formats/line.cpp index e5ed5ad59..07fb20115 100644 --- a/lib/formats/line.cpp +++ b/lib/formats/line.cpp @@ -5,161 +5,161 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include using namespace villas; using namespace villas::node; -int LineFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - size_t off = 0; +int LineFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + unsigned i; + size_t off = 0; - for (i = 0; i < cnt && off < len; i++) - off += sprintLine(buf + off, len - off, smps[i]); + for (i = 0; i < cnt && off < len; i++) + off += sprintLine(buf + off, len - off, smps[i]); - if (wbytes) - *wbytes = off; + if (wbytes) + *wbytes = off; - return i; + return i; } -int LineFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - size_t off = 0; +int LineFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + unsigned i; + size_t off = 0; - if (skip_first_line) { - if (!first_line_skipped) { - while (off < len) { - if (buf[off++] == delimiter) - break; - } + if (skip_first_line) { + if (!first_line_skipped) { + while (off < len) { + if (buf[off++] == delimiter) + break; + } - first_line_skipped = true; - } - } + first_line_skipped = true; + } + } - for (i = 0; i < cnt && off < len; i++) { - // Skip comment lines - if (buf[off] == comment) { - while (off < len) { - if (buf[++off] == delimiter) - break; - } + for (i = 0; i < cnt && off < len; i++) { + // Skip comment lines + if (buf[off] == comment) { + while (off < len) { + if (buf[++off] == delimiter) + break; + } - if (off == len) - break; - } + if (off == len) + break; + } - off += sscanLine(buf + off, len - off, smps[i]); - } + off += sscanLine(buf + off, len - off, smps[i]); + } - if (rbytes) - *rbytes = off; + if (rbytes) + *rbytes = off; - return i; + return i; } -int LineFormat::print(FILE *f, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; +int LineFormat::print(FILE *f, const struct Sample *const smps[], + unsigned cnt) { + int ret; + unsigned i; - if (cnt > 0 && smps[0]->signals) - header(f, smps[0]->signals); + if (cnt > 0 && smps[0]->signals) + header(f, smps[0]->signals); - for (i = 0; i < cnt; i++) { - size_t wbytes; + for (i = 0; i < cnt; i++) { + size_t wbytes; - ret = sprint(out.buffer, out.buflen, &wbytes, &smps[i], 1); - if (ret < 0) - return ret; + ret = sprint(out.buffer, out.buflen, &wbytes, &smps[i], 1); + if (ret < 0) + return ret; - fwrite(out.buffer, wbytes, 1, f); - } + fwrite(out.buffer, wbytes, 1, f); + } - return i; + return i; } -int LineFormat::scan(FILE *f, struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; - ssize_t bytes; +int LineFormat::scan(FILE *f, struct Sample *const smps[], unsigned cnt) { + int ret; + unsigned i; + ssize_t bytes; - if (skip_first_line) { - if (!first_line_skipped) { - bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); - if (bytes < 0) - return -1; // An error or eof occured + if (skip_first_line) { + if (!first_line_skipped) { + bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); + if (bytes < 0) + return -1; // An error or eof occured - first_line_skipped = true; - } - } + first_line_skipped = true; + } + } - for (i = 0; i < cnt && !feof(f); i++) { - size_t rbytes; - char *ptr; + for (i = 0; i < cnt && !feof(f); i++) { + size_t rbytes; + char *ptr; -skip: bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); - if (feof(f)) - break; - else if (bytes < 0) - return -1; // An error or eof occured + skip: + bytes = getdelim(&in.buffer, &in.buflen, delimiter, f); + if (feof(f)) + break; + else if (bytes < 0) + return -1; // An error or eof occured - // Skip whitespaces, empty and comment lines - for (ptr = in.buffer; isspace(*ptr); ptr++); + // Skip whitespaces, empty and comment lines + for (ptr = in.buffer; isspace(*ptr); ptr++) + ; - if (ptr[0] == '\0' || ptr[0] == comment) - goto skip; + if (ptr[0] == '\0' || ptr[0] == comment) + goto skip; - ret = sscan(in.buffer, bytes, &rbytes, &smps[i], 1); - if (ret < 0) - return ret; - } + ret = sscan(in.buffer, bytes, &rbytes, &smps[i], 1); + if (ret < 0) + return ret; + } - return i; + return i; } -void LineFormat::parse(json_t *json) -{ - int ret; - json_error_t err; - const char *delim = nullptr; - const char *com = nullptr; - int header = -1; - int skip = -1; +void LineFormat::parse(json_t *json) { + int ret; + json_error_t err; + const char *delim = nullptr; + const char *com = nullptr; + int header = -1; + int skip = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: b, s?: s }", - "delimiter", &delim, - "header", &header, - "skip_first_line", &skip, - "comment_prefix", &com - ); - if (ret) - throw ConfigError(json, err, "node-config-format-line", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: b, s?: s }", + "delimiter", &delim, "header", &header, + "skip_first_line", &skip, "comment_prefix", &com); + if (ret) + throw ConfigError(json, err, "node-config-format-line", + "Failed to parse format configuration"); - if (delim) { - if (strlen(delim) != 1) - throw ConfigError(json, "node-config-format-line-delimiter", "Line delimiter must be a single character!"); + if (delim) { + if (strlen(delim) != 1) + throw ConfigError(json, "node-config-format-line-delimiter", + "Line delimiter must be a single character!"); - delimiter = delim[0]; - } + delimiter = delim[0]; + } - if (com) { - if (strlen(com) != 1) - throw ConfigError(json, "node-config-format-line-comment_prefix", "Comment prefix must be a single character!"); + if (com) { + if (strlen(com) != 1) + throw ConfigError(json, "node-config-format-line-comment_prefix", + "Comment prefix must be a single character!"); - comment = com[0]; - } + comment = com[0]; + } - if (header >= 0) - print_header = header; + if (header >= 0) + print_header = header; - if (skip >= 0) - skip_first_line = skip; + if (skip >= 0) + skip_first_line = skip; - Format::parse(json); + Format::parse(json); } diff --git a/lib/formats/msg.cpp b/lib/formats/msg.cpp index 85b672b82..31818b8f2 100644 --- a/lib/formats/msg.cpp +++ b/lib/formats/msg.cpp @@ -9,127 +9,126 @@ #include #include +#include #include #include #include -#include using namespace villas; using namespace villas::node; -void villas::node::msg_ntoh(struct Message *m) -{ - msg_hdr_ntoh(m); +void villas::node::msg_ntoh(struct Message *m) { + msg_hdr_ntoh(m); - for (int i = 0; i < m->length; i++) - m->data[i].i = ntohl(m->data[i].i); + for (int i = 0; i < m->length; i++) + m->data[i].i = ntohl(m->data[i].i); } -void villas::node::msg_hton(struct Message *m) -{ - for (int i = 0; i < m->length; i++) - m->data[i].i = htonl(m->data[i].i); +void villas::node::msg_hton(struct Message *m) { + for (int i = 0; i < m->length; i++) + m->data[i].i = htonl(m->data[i].i); - msg_hdr_hton(m); + msg_hdr_hton(m); } -void villas::node::msg_hdr_hton(struct Message *m) -{ - m->length = htons(m->length); - m->sequence = htonl(m->sequence); - m->ts.sec = htonl(m->ts.sec); - m->ts.nsec = htonl(m->ts.nsec); +void villas::node::msg_hdr_hton(struct Message *m) { + m->length = htons(m->length); + m->sequence = htonl(m->sequence); + m->ts.sec = htonl(m->ts.sec); + m->ts.nsec = htonl(m->ts.nsec); } -void villas::node::msg_hdr_ntoh(struct Message *m) -{ - m->length = ntohs(m->length); - m->sequence = ntohl(m->sequence); - m->ts.sec = ntohl(m->ts.sec); - m->ts.nsec = ntohl(m->ts.nsec); +void villas::node::msg_hdr_ntoh(struct Message *m) { + m->length = ntohs(m->length); + m->sequence = ntohl(m->sequence); + m->ts.sec = ntohl(m->ts.sec); + m->ts.nsec = ntohl(m->ts.nsec); } -int villas::node::msg_verify(const struct Message *m) -{ - if (m->version != MSG_VERSION) - return -1; - else if (m->type != MSG_TYPE_DATA) - return -2; - else if (m->reserved1 != 0) - return -3; - else - return 0; +int villas::node::msg_verify(const struct Message *m) { + if (m->version != MSG_VERSION) + return -1; + else if (m->type != MSG_TYPE_DATA) + return -2; + else if (m->reserved1 != 0) + return -3; + else + return 0; } -int villas::node::msg_to_sample(const struct Message *msg, struct Sample *smp, const SignalList::Ptr sigs, uint8_t *source_index) -{ - int ret; - unsigned i; +int villas::node::msg_to_sample(const struct Message *msg, struct Sample *smp, + const SignalList::Ptr sigs, + uint8_t *source_index) { + int ret; + unsigned i; - ret = msg_verify(msg); - if (ret) - return ret; + ret = msg_verify(msg); + if (ret) + return ret; - unsigned len = MIN(msg->length, smp->capacity); - for (i = 0; i < MIN(len, sigs->size()); i++) { - auto sig = sigs->getByIndex(i); - if (!sig) - return -1; + unsigned len = MIN(msg->length, smp->capacity); + for (i = 0; i < MIN(len, sigs->size()); i++) { + auto sig = sigs->getByIndex(i); + if (!sig) + return -1; - switch (sig->type) { - case SignalType::FLOAT: - smp->data[i].f = msg->data[i].f; - break; + switch (sig->type) { + case SignalType::FLOAT: + smp->data[i].f = msg->data[i].f; + break; - case SignalType::INTEGER: - smp->data[i].i = msg->data[i].i; - break; + case SignalType::INTEGER: + smp->data[i].i = msg->data[i].i; + break; - default: - return -1; - } - } + default: + return -1; + } + } - smp->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; - smp->length = i; - smp->sequence = msg->sequence; - MSG_TS(msg, smp->ts.origin); + smp->flags = (int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA; + smp->length = i; + smp->sequence = msg->sequence; + MSG_TS(msg, smp->ts.origin); - if (source_index) - *source_index = msg->source_index; + if (source_index) + *source_index = msg->source_index; - return 0; + return 0; } -int villas::node::msg_from_sample(struct Message *msg_in, const struct Sample *smp, const SignalList::Ptr sigs, uint8_t source_index) -{ - msg_in->type = MSG_TYPE_DATA; - msg_in->version = MSG_VERSION; - msg_in->reserved1 = 0; - msg_in->source_index = source_index; - msg_in->length = (uint16_t) smp->length; - msg_in->sequence = (uint32_t) smp->sequence; - msg_in->ts.sec = smp->ts.origin.tv_sec; - msg_in->ts.nsec = smp->ts.origin.tv_nsec; +int villas::node::msg_from_sample(struct Message *msg_in, + const struct Sample *smp, + const SignalList::Ptr sigs, + uint8_t source_index) { + msg_in->type = MSG_TYPE_DATA; + msg_in->version = MSG_VERSION; + msg_in->reserved1 = 0; + msg_in->source_index = source_index; + msg_in->length = (uint16_t)smp->length; + msg_in->sequence = (uint32_t)smp->sequence; + msg_in->ts.sec = smp->ts.origin.tv_sec; + msg_in->ts.nsec = smp->ts.origin.tv_nsec; - for (unsigned i = 0; i < smp->length; i++) { - auto sig = sigs->getByIndex(i); - if (!sig) - return -1; + for (unsigned i = 0; i < smp->length; i++) { + auto sig = sigs->getByIndex(i); + if (!sig) + return -1; - switch (sig->type) { - case SignalType::FLOAT: - msg_in->data[i].f = smp->data[i].f; - break; + switch (sig->type) { + case SignalType::FLOAT: + msg_in->data[i].f = smp->data[i].f; + break; - case SignalType::INTEGER: - msg_in->data[i].i = smp->data[i].i; - break; + case SignalType::INTEGER: + msg_in->data[i].i = smp->data[i].i; + break; - default: - return -1; - } - } + default: + return -1; + } + } - return 0; + return 0; } diff --git a/lib/formats/opal_asyncip.cpp b/lib/formats/opal_asyncip.cpp index e19bc1c96..eb438329e 100644 --- a/lib/formats/opal_asyncip.cpp +++ b/lib/formats/opal_asyncip.cpp @@ -7,111 +7,110 @@ #include -#include #include +#include #include #include using namespace villas; using namespace villas::node; -int OpalAsyncIPFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - auto *ptr = buf; - ssize_t slen = len; +int OpalAsyncIPFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + unsigned i; + auto *ptr = buf; + ssize_t slen = len; - for (i = 0; i < cnt && ptr - buf < slen; i++) { - auto *pl = (struct Payload *) ptr; - auto *smp = smps[i]; + for (i = 0; i < cnt && ptr - buf < slen; i++) { + auto *pl = (struct Payload *)ptr; + auto *smp = smps[i]; - auto wlen = smp->length * sizeof(double) + sizeof(struct Payload); - if (wlen > len) - return -1; + auto wlen = smp->length * sizeof(double) + sizeof(struct Payload); + if (wlen > len) + return -1; - pl->dev_id = htole16(dev_id); - pl->msg_id = htole32(smp->sequence); - pl->msg_len = htole16(smp->length * sizeof(double)); + pl->dev_id = htole16(dev_id); + pl->msg_id = htole32(smp->sequence); + pl->msg_len = htole16(smp->length * sizeof(double)); - if (smp->length > MAXSIZE) - logger->warn("Can not sent more then {} signals via opal.asyncip format. We only send the first {}..", MAXSIZE, MAXSIZE); + if (smp->length > MAXSIZE) + logger->warn("Can not sent more then {} signals via opal.asyncip format. " + "We only send the first {}..", + MAXSIZE, MAXSIZE); - for (unsigned j = 0; j < MIN(MAXSIZE, smp->length); j++) { - auto sig = smp->signals->getByIndex(j); - auto d = smp->data[j]; + for (unsigned j = 0; j < MIN(MAXSIZE, smp->length); j++) { + auto sig = smp->signals->getByIndex(j); + auto d = smp->data[j]; - d = d.cast(sig->type, SignalType::FLOAT); - d.i = htole64(d.i); + d = d.cast(sig->type, SignalType::FLOAT); + d.i = htole64(d.i); - pl->data[j] = d.f; - } + pl->data[j] = d.f; + } - ptr += wlen; - } + ptr += wlen; + } - if (wbytes) - *wbytes = ptr - buf; + if (wbytes) + *wbytes = ptr - buf; - return i; + return i; } -int OpalAsyncIPFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - auto *ptr = buf; +int OpalAsyncIPFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + unsigned i; + auto *ptr = buf; - if (len % 8 != 0) - return -1; // Packet size is invalid: Must be multiple of 8 bytes + if (len % 8 != 0) + return -1; // Packet size is invalid: Must be multiple of 8 bytes - for (i = 0; i < cnt && ptr - buf + sizeof(struct Payload) < len; i++) { - auto *pl = (struct Payload *) ptr; - auto *smp = smps[i]; + for (i = 0; i < cnt && ptr - buf + sizeof(struct Payload) < len; i++) { + auto *pl = (struct Payload *)ptr; + auto *smp = smps[i]; - auto rlen = le16toh(pl->msg_len); - if (len < ptr - buf + rlen + sizeof(struct Payload)) - return -2; + auto rlen = le16toh(pl->msg_len); + if (len < ptr - buf + rlen + sizeof(struct Payload)) + return -2; - smp->sequence = le32toh(pl->msg_id); - smp->length = rlen / sizeof(double); - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; - smp->signals = signals; + smp->sequence = le32toh(pl->msg_id); + smp->length = rlen / sizeof(double); + smp->flags = (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA; + smp->signals = signals; - for (unsigned j = 0; j < MIN(smp->length, smp->capacity); j++) { - auto sig = signals->getByIndex(j); + for (unsigned j = 0; j < MIN(smp->length, smp->capacity); j++) { + auto sig = signals->getByIndex(j); - SignalData d; - d.f = pl->data[j]; - d.i = le64toh(d.i); + SignalData d; + d.f = pl->data[j]; + d.i = le64toh(d.i); - smp->data[j] = d.cast(SignalType::FLOAT, sig->type); - } + smp->data[j] = d.cast(SignalType::FLOAT, sig->type); + } - ptr += rlen + sizeof(struct Payload); - } + ptr += rlen + sizeof(struct Payload); + } - if (rbytes) - *rbytes = ptr - buf; + if (rbytes) + *rbytes = ptr - buf; - return i; + return i; } -void OpalAsyncIPFormat::parse(json_t *json) -{ - int ret; - json_error_t err; - int did = -1; +void OpalAsyncIPFormat::parse(json_t *json) { + int ret; + json_error_t err; + int did = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: i }", - "dev_id", &did - ); - if (ret) - throw ConfigError(json, err, "node-config-format-opal-asyncip", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i }", "dev_id", &did); + if (ret) + throw ConfigError(json, err, "node-config-format-opal-asyncip", + "Failed to parse format configuration"); - if (did >= 0) - dev_id = did; + if (did >= 0) + dev_id = did; - Format::parse(json); + Format::parse(json); } -static -OpalAsyncIPFormatPlugin p; +static OpalAsyncIPFormatPlugin p; diff --git a/lib/formats/protobuf.cpp b/lib/formats/protobuf.cpp index 41828733c..70b9796a7 100644 --- a/lib/formats/protobuf.cpp +++ b/lib/formats/protobuf.cpp @@ -5,222 +5,229 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include #include -#include -#include #include using namespace villas::node; -enum SignalType ProtobufFormat::detect(const Villas__Node__Value *val) -{ - switch (val->value_case) { - case VILLAS__NODE__VALUE__VALUE_F: - return SignalType::FLOAT; +enum SignalType ProtobufFormat::detect(const Villas__Node__Value *val) { + switch (val->value_case) { + case VILLAS__NODE__VALUE__VALUE_F: + return SignalType::FLOAT; - case VILLAS__NODE__VALUE__VALUE_I: - return SignalType::INTEGER; + case VILLAS__NODE__VALUE__VALUE_I: + return SignalType::INTEGER; - case VILLAS__NODE__VALUE__VALUE_B: - return SignalType::BOOLEAN; + case VILLAS__NODE__VALUE__VALUE_B: + return SignalType::BOOLEAN; - case VILLAS__NODE__VALUE__VALUE_Z: - return SignalType::COMPLEX; + case VILLAS__NODE__VALUE__VALUE_Z: + return SignalType::COMPLEX; - case VILLAS__NODE__VALUE__VALUE__NOT_SET: - default: - return SignalType::INVALID; - } + case VILLAS__NODE__VALUE__VALUE__NOT_SET: + default: + return SignalType::INVALID; + } } -int ProtobufFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - unsigned psz; +int ProtobufFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + unsigned psz; - auto *pb_msg = new Villas__Node__Message; - if (!pb_msg) - throw MemoryAllocationError(); + auto *pb_msg = new Villas__Node__Message; + if (!pb_msg) + throw MemoryAllocationError(); - villas__node__message__init(pb_msg); + villas__node__message__init(pb_msg); - pb_msg->n_samples = cnt; - pb_msg->samples = new Villas__Node__Sample*[pb_msg->n_samples]; - if (!pb_msg->samples) - throw MemoryAllocationError(); + pb_msg->n_samples = cnt; + pb_msg->samples = new Villas__Node__Sample *[pb_msg->n_samples]; + if (!pb_msg->samples) + throw MemoryAllocationError(); - for (unsigned i = 0; i < pb_msg->n_samples; i++) { - Villas__Node__Sample *pb_smp = pb_msg->samples[i] = new Villas__Node__Sample; - if (!pb_msg->samples[i]) - throw MemoryAllocationError(); + for (unsigned i = 0; i < pb_msg->n_samples; i++) { + Villas__Node__Sample *pb_smp = pb_msg->samples[i] = + new Villas__Node__Sample; + if (!pb_msg->samples[i]) + throw MemoryAllocationError(); - villas__node__sample__init(pb_smp); + villas__node__sample__init(pb_smp); - const struct Sample *smp = smps[i]; + const struct Sample *smp = smps[i]; - pb_smp->type = VILLAS__NODE__SAMPLE__TYPE__DATA; + pb_smp->type = VILLAS__NODE__SAMPLE__TYPE__DATA; - if (flags & smp->flags & (int) SampleFlags::HAS_SEQUENCE) { - pb_smp->has_sequence = 1; - pb_smp->sequence = smp->sequence; - } + if (flags & smp->flags & (int)SampleFlags::HAS_SEQUENCE) { + pb_smp->has_sequence = 1; + pb_smp->sequence = smp->sequence; + } - if (flags & smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) { - pb_smp->timestamp = new Villas__Node__Timestamp; - if (!pb_smp->timestamp) - throw MemoryAllocationError(); + if (flags & smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + pb_smp->timestamp = new Villas__Node__Timestamp; + if (!pb_smp->timestamp) + throw MemoryAllocationError(); - villas__node__timestamp__init(pb_smp->timestamp); + villas__node__timestamp__init(pb_smp->timestamp); - pb_smp->timestamp->sec = smp->ts.origin.tv_sec; - pb_smp->timestamp->nsec = smp->ts.origin.tv_nsec; - } + pb_smp->timestamp->sec = smp->ts.origin.tv_sec; + pb_smp->timestamp->nsec = smp->ts.origin.tv_nsec; + } - pb_smp->n_values = smp->length; - pb_smp->values = new Villas__Node__Value*[pb_smp->n_values]; - if (!pb_smp->values) - throw MemoryAllocationError(); + pb_smp->n_values = smp->length; + pb_smp->values = new Villas__Node__Value *[pb_smp->n_values]; + if (!pb_smp->values) + throw MemoryAllocationError(); - for (unsigned j = 0; j < pb_smp->n_values; j++) { - Villas__Node__Value *pb_val = pb_smp->values[j] = new Villas__Node__Value; - if (!pb_val) - throw MemoryAllocationError(); + for (unsigned j = 0; j < pb_smp->n_values; j++) { + Villas__Node__Value *pb_val = pb_smp->values[j] = new Villas__Node__Value; + if (!pb_val) + throw MemoryAllocationError(); - villas__node__value__init(pb_val); + villas__node__value__init(pb_val); - enum SignalType fmt = sample_format(smp, j); - switch (fmt) { - case SignalType::FLOAT: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE_F; - pb_val->f = smp->data[j].f; - break; + enum SignalType fmt = sample_format(smp, j); + switch (fmt) { + case SignalType::FLOAT: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE_F; + pb_val->f = smp->data[j].f; + break; - case SignalType::INTEGER: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE_I; - pb_val->i = smp->data[j].i; - break; + case SignalType::INTEGER: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE_I; + pb_val->i = smp->data[j].i; + break; - case SignalType::BOOLEAN: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE_B; - pb_val->b = smp->data[j].b; - break; + case SignalType::BOOLEAN: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE_B; + pb_val->b = smp->data[j].b; + break; - case SignalType::COMPLEX: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE_Z; - pb_val->z = new Villas__Node__Complex; - if (!pb_val->z) - throw MemoryAllocationError(); + case SignalType::COMPLEX: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE_Z; + pb_val->z = new Villas__Node__Complex; + if (!pb_val->z) + throw MemoryAllocationError(); - villas__node__complex__init(pb_val->z); + villas__node__complex__init(pb_val->z); - pb_val->z->real = std::real(smp->data[j].z); - pb_val->z->imag = std::imag(smp->data[j].z); - break; + pb_val->z->real = std::real(smp->data[j].z); + pb_val->z->imag = std::imag(smp->data[j].z); + break; - case SignalType::INVALID: - pb_val->value_case = VILLAS__NODE__VALUE__VALUE__NOT_SET; - break; - } - } - } + case SignalType::INVALID: + pb_val->value_case = VILLAS__NODE__VALUE__VALUE__NOT_SET; + break; + } + } + } - psz = villas__node__message__get_packed_size(pb_msg); + psz = villas__node__message__get_packed_size(pb_msg); - if (psz > len) - goto out; + if (psz > len) + goto out; - villas__node__message__pack(pb_msg, (uint8_t *) buf); - villas__node__message__free_unpacked(pb_msg, nullptr); + villas__node__message__pack(pb_msg, (uint8_t *)buf); + villas__node__message__free_unpacked(pb_msg, nullptr); - *wbytes = psz; + *wbytes = psz; - return cnt; + return cnt; out: - villas__node__message__free_unpacked(pb_msg, nullptr); + villas__node__message__free_unpacked(pb_msg, nullptr); - return -1; + return -1; } -int ProtobufFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - unsigned i, j; - Villas__Node__Message *pb_msg; +int ProtobufFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + unsigned i, j; + Villas__Node__Message *pb_msg; - pb_msg = villas__node__message__unpack(nullptr, len, (uint8_t *) buf); - if (!pb_msg) - return -1; + pb_msg = villas__node__message__unpack(nullptr, len, (uint8_t *)buf); + if (!pb_msg) + return -1; - for (i = 0; i < MIN(pb_msg->n_samples, cnt); i++) { - struct Sample *smp = smps[i]; - Villas__Node__Sample *pb_smp = pb_msg->samples[i]; + for (i = 0; i < MIN(pb_msg->n_samples, cnt); i++) { + struct Sample *smp = smps[i]; + Villas__Node__Sample *pb_smp = pb_msg->samples[i]; - smp->flags = 0; - smp->signals = signals; + smp->flags = 0; + smp->signals = signals; - if (pb_smp->type != VILLAS__NODE__SAMPLE__TYPE__DATA) - throw RuntimeError("Parsed non supported message type. Skipping"); + if (pb_smp->type != VILLAS__NODE__SAMPLE__TYPE__DATA) + throw RuntimeError("Parsed non supported message type. Skipping"); - if (pb_smp->has_sequence) { - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - smp->sequence = pb_smp->sequence; - } + if (pb_smp->has_sequence) { + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + smp->sequence = pb_smp->sequence; + } - if (pb_smp->timestamp) { - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - smp->ts.origin.tv_sec = pb_smp->timestamp->sec; - smp->ts.origin.tv_nsec = pb_smp->timestamp->nsec; - } + if (pb_smp->timestamp) { + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + smp->ts.origin.tv_sec = pb_smp->timestamp->sec; + smp->ts.origin.tv_nsec = pb_smp->timestamp->nsec; + } - for (j = 0; j < MIN(pb_smp->n_values, smp->capacity); j++) { - Villas__Node__Value *pb_val = pb_smp->values[j]; + for (j = 0; j < MIN(pb_smp->n_values, smp->capacity); j++) { + Villas__Node__Value *pb_val = pb_smp->values[j]; - enum SignalType fmt = detect(pb_val); + enum SignalType fmt = detect(pb_val); - auto sig = smp->signals->getByIndex(j); - if (!sig) - return -1; + auto sig = smp->signals->getByIndex(j); + if (!sig) + return -1; - if (sig->type != fmt) - throw RuntimeError("Received invalid data type in Protobuf payload: Received {}, expected {} for signal {} (index {}).", - signalTypeToString(fmt), signalTypeToString(sig->type), sig->name, i); + if (sig->type != fmt) + throw RuntimeError("Received invalid data type in Protobuf payload: " + "Received {}, expected {} for signal {} (index {}).", + signalTypeToString(fmt), + signalTypeToString(sig->type), sig->name, i); - switch (sig->type) { - case SignalType::FLOAT: - smp->data[j].f = pb_val->f; - break; + switch (sig->type) { + case SignalType::FLOAT: + smp->data[j].f = pb_val->f; + break; - case SignalType::INTEGER: - smp->data[j].i = pb_val->i; - break; + case SignalType::INTEGER: + smp->data[j].i = pb_val->i; + break; - case SignalType::BOOLEAN: - smp->data[j].b = pb_val->b; - break; + case SignalType::BOOLEAN: + smp->data[j].b = pb_val->b; + break; - case SignalType::COMPLEX: - smp->data[j].z = std::complex(pb_val->z->real, pb_val->z->imag); - break; + case SignalType::COMPLEX: + smp->data[j].z = std::complex(pb_val->z->real, pb_val->z->imag); + break; - default: { } - } - } + default: { + } + } + } - if (pb_smp->n_values > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (pb_smp->n_values > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - smp->length = j; - } + smp->length = j; + } - if (rbytes) - *rbytes = villas__node__message__get_packed_size(pb_msg); + if (rbytes) + *rbytes = villas__node__message__get_packed_size(pb_msg); - villas__node__message__free_unpacked(pb_msg, nullptr); + villas__node__message__free_unpacked(pb_msg, nullptr); - return i; + return i; } // Register format static char n[] = "protobuf"; static char d[] = "Google Protobuf"; -static FormatPlugin p; +static FormatPlugin + p; diff --git a/lib/formats/raw.cpp b/lib/formats/raw.cpp index e429c01d3..cc65fa7ce 100644 --- a/lib/formats/raw.cpp +++ b/lib/formats/raw.cpp @@ -5,11 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include #include #include +#include +#include +#include typedef float flt32_t; typedef double flt64_t; @@ -19,425 +19,520 @@ using namespace villas; using namespace villas::node; // Convert double to host byte order -#define SWAP_FLOAT_XTOH(o, b, n) ({ \ - union { flt ## b ## _t f; uint ## b ## _t i; } x = { .f = n }; \ - x.i = (o) ? be ## b ## toh(x.i) : le ## b ## toh(x.i); \ - x.f; \ -}) +#define SWAP_FLOAT_XTOH(o, b, n) \ + ({ \ + union { \ + flt##b##_t f; \ + uint##b##_t i; \ + } x = {.f = n}; \ + x.i = (o) ? be##b##toh(x.i) : le##b##toh(x.i); \ + x.f; \ + }) // Convert double to big/little endian byte order -#define SWAP_FLOAT_HTOX(o, b, n) ({ \ - union { flt ## b ## _t f; uint ## b ## _t i; } x = { .f = n }; \ - x.i = (o) ? htobe ## b (x.i) : htole ## b (x.i); \ - x.f; \ -}) +#define SWAP_FLOAT_HTOX(o, b, n) \ + ({ \ + union { \ + flt##b##_t f; \ + uint##b##_t i; \ + } x = {.f = n}; \ + x.i = (o) ? htobe##b(x.i) : htole##b(x.i); \ + x.f; \ + }) // Convert integer of varying width to host byte order -#define SWAP_INT_XTOH(o, b, n) (o ? be ## b ## toh(n) : le ## b ## toh(n)) +#define SWAP_INT_XTOH(o, b, n) (o ? be##b##toh(n) : le##b##toh(n)) // Convert integer of varying width to big/little endian byte order -#define SWAP_INT_HTOX(o, b, n) (o ? htobe ## b (n) : htole ## b (n)) +#define SWAP_INT_HTOX(o, b, n) (o ? htobe##b(n) : htole##b(n)) -int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - int o = 0; - size_t nlen; +int RawFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + int o = 0; + size_t nlen; - void *vbuf = (char *) buf; // Avoid warning about invalid pointer cast + void *vbuf = (char *)buf; // Avoid warning about invalid pointer cast - int8_t *i8 = (int8_t *) vbuf; - int16_t *i16 = (int16_t *) vbuf; - int32_t *i32 = (int32_t *) vbuf; - int64_t *i64 = (int64_t *) vbuf; - float *f32 = (float *) vbuf; - double *f64 = (double *) vbuf; + int8_t *i8 = (int8_t *)vbuf; + int16_t *i16 = (int16_t *)vbuf; + int32_t *i32 = (int32_t *)vbuf; + int64_t *i64 = (int64_t *)vbuf; + float *f32 = (float *)vbuf; + double *f64 = (double *)vbuf; #ifdef HAS_128BIT - __int128 *i128 = (__int128 *) vbuf; - __float128 *f128 = (__float128 *) vbuf; + __int128 *i128 = (__int128 *)vbuf; + __float128 *f128 = (__float128 *)vbuf; #endif - for (unsigned i = 0; i < cnt; i++) { - const struct Sample *smp = smps[i]; + for (unsigned i = 0; i < cnt; i++) { + const struct Sample *smp = smps[i]; - /* First three values are sequence, seconds and nano-seconds timestamps + /* First three values are sequence, seconds and nano-seconds timestamps * * These fields are always encoded as integers! */ - if (fake) { - // Check length - nlen = (o + 3) * (bits / 8); - if (nlen >= len) - goto out; + if (fake) { + // Check length + nlen = (o + 3) * (bits / 8); + if (nlen >= len) + goto out; - switch (bits) { - case 8: - i8[o++] = smp->sequence; - i8[o++] = smp->ts.origin.tv_sec; - i8[o++] = smp->ts.origin.tv_nsec; - break; + switch (bits) { + case 8: + i8[o++] = smp->sequence; + i8[o++] = smp->ts.origin.tv_sec; + i8[o++] = smp->ts.origin.tv_nsec; + break; - case 16: - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, smp->sequence); - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, smp->ts.origin.tv_sec); - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, smp->ts.origin.tv_nsec); - break; + case 16: + i16[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 16, smp->sequence); + i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, + smp->ts.origin.tv_sec); + i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, + smp->ts.origin.tv_nsec); + break; - case 32: - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, smp->sequence); - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, smp->ts.origin.tv_sec); - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, smp->ts.origin.tv_nsec); - break; + case 32: + i32[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 32, smp->sequence); + i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, + smp->ts.origin.tv_sec); + i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, + smp->ts.origin.tv_nsec); + break; - case 64: - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, smp->sequence); - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, smp->ts.origin.tv_sec); - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, smp->ts.origin.tv_nsec); - break; + case 64: + i64[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 64, smp->sequence); + i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, + smp->ts.origin.tv_sec); + i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, + smp->ts.origin.tv_nsec); + break; #ifdef HAS_128BIT - case 128: - i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, smp->sequence); - i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, smp->ts.origin.tv_sec); - i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, smp->ts.origin.tv_nsec); - break; + case 128: + i128[o++] = + SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, smp->sequence); + i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, + smp->ts.origin.tv_sec); + i128[o++] = SWAP_INT_TO_LE(endianess == Endianess::BIG, 128, + smp->ts.origin.tv_nsec); + break; #endif - } - } + } + } - for (unsigned j = 0; j < smp->length; j++) { - enum SignalType fmt = sample_format(smp, j); - const union SignalData *data = &smp->data[j]; + for (unsigned j = 0; j < smp->length; j++) { + enum SignalType fmt = sample_format(smp, j); + const union SignalData *data = &smp->data[j]; - // Check length - nlen = (o + (fmt == SignalType::COMPLEX ? 2 : 1)) * (bits / 8); - if (nlen >= len) - goto out; + // Check length + nlen = (o + (fmt == SignalType::COMPLEX ? 2 : 1)) * (bits / 8); + if (nlen >= len) + goto out; - switch (fmt) { - case SignalType::FLOAT: - switch (bits) { - case 8: - i8 [o++] = -1; - break; // Not supported + switch (fmt) { + case SignalType::FLOAT: + switch (bits) { + case 8: + i8[o++] = -1; + break; // Not supported - case 16: - i16[o++] = -1; - break; // Not supported + case 16: + i16[o++] = -1; + break; // Not supported - case 32: - f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, (float) data->f); - break; + case 32: + f32[o++] = + SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, (float)data->f); + break; - case 64: - f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, data->f); - break; + case 64: + f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, data->f); + break; #ifdef HAS_128BIT - case 128: f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, data->f); break; + case 128: + f128[o++] = + SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, data->f); + break; #endif - } - break; + } + break; - case SignalType::INTEGER: - switch (bits) { - case 8: - i8 [o++] = data->i; - break; + case SignalType::INTEGER: + switch (bits) { + case 8: + i8[o++] = data->i; + break; - case 16: - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, data->i); - break; + case 16: + i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, data->i); + break; - case 32: - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, data->i); - break; + case 32: + i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, data->i); + break; - case 64: - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, data->i); - break; + case 64: + i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, data->i); + break; #ifdef HAS_128BIT - case 128: - i128[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 128, data->i); - break; + case 128: + i128[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 128, data->i); + break; #endif - } - break; + } + break; - case SignalType::BOOLEAN: - switch (bits) { - case 8: - i8 [o++] = data->b ? 1 : 0; - break; + case SignalType::BOOLEAN: + switch (bits) { + case 8: + i8[o++] = data->b ? 1 : 0; + break; - case 16: - i16[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 16, data->b ? 1 : 0); - break; + case 16: + i16[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 16, data->b ? 1 : 0); + break; - case 32: - i32[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 32, data->b ? 1 : 0); - break; + case 32: + i32[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 32, data->b ? 1 : 0); + break; - case 64: - i64[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 64, data->b ? 1 : 0); - break; + case 64: + i64[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 64, data->b ? 1 : 0); + break; #ifdef HAS_128BIT - case 128: - i128[o++] = SWAP_INT_HTOX(endianess == Endianess::BIG, 128, data->b ? 1 : 0); - break; + case 128: + i128[o++] = + SWAP_INT_HTOX(endianess == Endianess::BIG, 128, data->b ? 1 : 0); + break; #endif - } - break; + } + break; - case SignalType::COMPLEX: - switch (bits) { - case 8: - i8 [o++] = -1; // Not supported - i8 [o++] = -1; - break; + case SignalType::COMPLEX: + switch (bits) { + case 8: + i8[o++] = -1; // Not supported + i8[o++] = -1; + break; - case 16: - i16[o++] = -1; // Not supported - i16[o++] = -1; - break; + case 16: + i16[o++] = -1; // Not supported + i16[o++] = -1; + break; - case 32: - f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, (float) std::real(data->z)); - f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, (float) std::imag(data->z)); - break; + case 32: + f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, + (float)std::real(data->z)); + f32[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 32, + (float)std::imag(data->z)); + break; - case 64: - f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, std::real(data->z)); - f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, std::imag(data->z)); - break; + case 64: + f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, + std::real(data->z)); + f64[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 64, + std::imag(data->z)); + break; #ifdef HAS_128BIT - case 128: - f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, std::real(data->z)); - f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, std::imag(data->z)); - break; + case 128: + f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, + std::real(data->z)); + f128[o++] = SWAP_FLOAT_HTOX(endianess == Endianess::BIG, 128, + std::imag(data->z)); + break; #endif - } - break; + } + break; - case SignalType::INVALID: - return -1; - } - } - } + case SignalType::INVALID: + return -1; + } + } + } -out: if (wbytes) - *wbytes = o * (bits / 8); +out: + if (wbytes) + *wbytes = o * (bits / 8); - return cnt; + return cnt; } -int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - void *vbuf = (void *) buf; // Avoid warning about invalid pointer cast +int RawFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + void *vbuf = (void *)buf; // Avoid warning about invalid pointer cast - int8_t *i8 = (int8_t *) vbuf; - int16_t *i16 = (int16_t *) vbuf; - int32_t *i32 = (int32_t *) vbuf; - int64_t *i64 = (int64_t *) vbuf; - float *f32 = (float *) vbuf; - double *f64 = (double *) vbuf; + int8_t *i8 = (int8_t *)vbuf; + int16_t *i16 = (int16_t *)vbuf; + int32_t *i32 = (int32_t *)vbuf; + int64_t *i64 = (int64_t *)vbuf; + float *f32 = (float *)vbuf; + double *f64 = (double *)vbuf; #ifdef HAS_128BIT - __int128 *i128 = (__int128 *) vbuf; - __float128 *f128 = (__float128 *) vbuf; + __int128 *i128 = (__int128 *)vbuf; + __float128 *f128 = (__float128 *)vbuf; #endif - /* The raw format can not encode multiple samples in one buffer + /* The raw format can not encode multiple samples in one buffer * as there is no support for framing. */ - struct Sample *smp = smps[0]; + struct Sample *smp = smps[0]; - int o = 0; - int nlen = len / (bits / 8); + int o = 0; + int nlen = len / (bits / 8); - if (cnt > 1) - return -1; + if (cnt > 1) + return -1; - if (len % (bits / 8)) - return -1; // Invalid RAW Payload length + if (len % (bits / 8)) + return -1; // Invalid RAW Payload length - if (fake) { - if (nlen < o + 3) - return -1; // Received a packet with no fake header. Skipping... + if (fake) { + if (nlen < o + 3) + return -1; // Received a packet with no fake header. Skipping... - switch (bits) { - case 8: - smp->sequence = i8[o++]; - smp->ts.origin.tv_sec = i8[o++]; - smp->ts.origin.tv_nsec = i8[o++]; - break; + switch (bits) { + case 8: + smp->sequence = i8[o++]; + smp->ts.origin.tv_sec = i8[o++]; + smp->ts.origin.tv_nsec = i8[o++]; + break; - case 16: - smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); - smp->ts.origin.tv_sec = SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); - smp->ts.origin.tv_nsec = SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); - break; + case 16: + smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + smp->ts.origin.tv_sec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + smp->ts.origin.tv_nsec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + break; - case 32: - smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); - smp->ts.origin.tv_sec = SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); - smp->ts.origin.tv_nsec = SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); - break; + case 32: + smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + smp->ts.origin.tv_sec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + smp->ts.origin.tv_nsec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + break; - case 64: - smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); - smp->ts.origin.tv_sec = SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); - smp->ts.origin.tv_nsec = SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); - break; + case 64: + smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + smp->ts.origin.tv_sec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + smp->ts.origin.tv_nsec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + break; #ifdef HAS_128BIT - case 128: - smp->sequence = SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); - smp->ts.origin.tv_sec = SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); - smp->ts.origin.tv_nsec = SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); - break; + case 128: + smp->sequence = + SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); + smp->ts.origin.tv_sec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); + smp->ts.origin.tv_nsec = + SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); + break; #endif - } + } - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN; - } - else { - smp->flags = 0; - smp->sequence = 0; - smp->ts.origin.tv_sec = 0; - smp->ts.origin.tv_nsec = 0; - } + smp->flags = + (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_TS_ORIGIN; + } else { + smp->flags = 0; + smp->sequence = 0; + smp->ts.origin.tv_sec = 0; + smp->ts.origin.tv_nsec = 0; + } - smp->signals = signals; + smp->signals = signals; - unsigned i; - for (i = 0; i < smp->capacity && o < nlen; i++) { - enum SignalType fmt = sample_format(smp, i); - union SignalData *data = &smp->data[i]; + unsigned i; + for (i = 0; i < smp->capacity && o < nlen; i++) { + enum SignalType fmt = sample_format(smp, i); + union SignalData *data = &smp->data[i]; - switch (fmt) { - case SignalType::FLOAT: - switch (bits) { - case 8: data->f = -1; o++; break; // Not supported - case 16: data->f = -1; o++; break; // Not supported + switch (fmt) { + case SignalType::FLOAT: + switch (bits) { + case 8: + data->f = -1; + o++; + break; // Not supported + case 16: + data->f = -1; + o++; + break; // Not supported - case 32: data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]); break; - case 64: data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++]); break; + case 32: + data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]); + break; + case 64: + data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++]); + break; #ifdef HAS_128BIT - case 128: data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++]); break; + case 128: + data->f = SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++]); + break; #endif - } - break; + } + break; - case SignalType::INTEGER: - switch (bits) { - case 8: data->i = (int8_t) i8[o++]; break; - case 16: data->i = (int16_t) SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); break; - case 32: data->i = (int32_t) SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); break; - case 64: data->i = (int64_t) SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); break; + case SignalType::INTEGER: + switch (bits) { + case 8: + data->i = (int8_t)i8[o++]; + break; + case 16: + data->i = + (int16_t)SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + break; + case 32: + data->i = + (int32_t)SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + break; + case 64: + data->i = + (int64_t)SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + break; #ifdef HAS_128BIT - case 128: data->i = (__int128) SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); break; + case 128: + data->i = (__int128)SWAP_INT_XTOH(endianess == Endianess::BIG, 128, + i128[o++]); + break; #endif - } - break; + } + break; - case SignalType::BOOLEAN: - switch (bits) { - case 8: data->b = (bool) i8[o++]; break; - case 16: data->b = (bool) SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); break; - case 32: data->b = (bool) SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); break; - case 64: data->b = (bool) SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); break; + case SignalType::BOOLEAN: + switch (bits) { + case 8: + data->b = (bool)i8[o++]; + break; + case 16: + data->b = + (bool)SWAP_INT_XTOH(endianess == Endianess::BIG, 16, i16[o++]); + break; + case 32: + data->b = + (bool)SWAP_INT_XTOH(endianess == Endianess::BIG, 32, i32[o++]); + break; + case 64: + data->b = + (bool)SWAP_INT_XTOH(endianess == Endianess::BIG, 64, i64[o++]); + break; #ifdef HAS_128BIT - case 128: data->b = (bool) SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); break; + case 128: + data->b = + (bool)SWAP_INT_XTOH(endianess == Endianess::BIG, 128, i128[o++]); + break; #endif - } - break; + } + break; - case SignalType::COMPLEX: - switch (bits) { - case 8: data->z = std::complex(-1, -1); o += 2; break; // Not supported - case 16: data->z = std::complex(-1, -1); o += 2; break; // Not supported + case SignalType::COMPLEX: + switch (bits) { + case 8: + data->z = std::complex(-1, -1); + o += 2; + break; // Not supported + case 16: + data->z = std::complex(-1, -1); + o += 2; + break; // Not supported - case 32: data->z = std::complex( - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]), - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++])); + case 32: + data->z = std::complex( + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++]), + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 32, f32[o++])); - break; + break; - case 64: data->z = std::complex( - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++]), - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++])); - break; + case 64: + data->z = std::complex( + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++]), + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 64, f64[o++])); + break; #if HAS_128BIT - case 128: data->z = std::complex( - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++]), - SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++])); - break; + case 128: + data->z = std::complex( + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++]), + SWAP_FLOAT_XTOH(endianess == Endianess::BIG, 128, f128[o++])); + break; #endif - } - break; + } + break; - case SignalType::INVALID: - return -1; // Unsupported format in RAW payload - } - } + case SignalType::INVALID: + return -1; // Unsupported format in RAW payload + } + } - smp->length = i; + smp->length = i; - if (smp->length > smp->capacity) - smp->length = smp->capacity; // Received more values than supported + if (smp->length > smp->capacity) + smp->length = smp->capacity; // Received more values than supported - if (rbytes) - *rbytes = o * (bits / 8); + if (rbytes) + *rbytes = o * (bits / 8); - return 1; + return 1; } -void RawFormat::parse(json_t *json) -{ - int ret; - json_error_t err; +void RawFormat::parse(json_t *json) { + int ret; + json_error_t err; - int fake_tmp = 0; - const char *end = nullptr; + int fake_tmp = 0; + const char *end = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: i }", - "endianess", &end, - "fake", &fake_tmp, - "bits", &bits - ); - if (ret) - throw ConfigError(json, err, "node-config-format-raw", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: i }", "endianess", + &end, "fake", &fake_tmp, "bits", &bits); + if (ret) + throw ConfigError(json, err, "node-config-format-raw", + "Failed to parse format configuration"); - if (bits % 8 != 0 || bits > 128 || bits <= 0) - throw ConfigError(json, "node-config-format-raw-bits", "Failed to parse format configuration"); + if (bits % 8 != 0 || bits > 128 || bits <= 0) + throw ConfigError(json, "node-config-format-raw-bits", + "Failed to parse format configuration"); - if (end) { - if (bits <= 8) - throw ConfigError(json, "node-config-format-raw-endianess", "An endianess settings must only provided for bits > 8"); + if (end) { + if (bits <= 8) + throw ConfigError( + json, "node-config-format-raw-endianess", + "An endianess settings must only provided for bits > 8"); - if (!strcmp(end, "little")) - endianess = Endianess::LITTLE; - else if (!strcmp(end, "big")) - endianess = Endianess::BIG; - else - throw ConfigError(json, "node-config-format-raw-endianess", "Endianess must be either 'big' or 'little'"); - } + if (!strcmp(end, "little")) + endianess = Endianess::LITTLE; + else if (!strcmp(end, "big")) + endianess = Endianess::BIG; + else + throw ConfigError(json, "node-config-format-raw-endianess", + "Endianess must be either 'big' or 'little'"); + } - fake = fake_tmp; - if (fake) - flags |= (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN; - else - flags &= ~((int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN); + fake = fake_tmp; + if (fake) + flags |= (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_TS_ORIGIN; + else + flags &= + ~((int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_TS_ORIGIN); - BinaryFormat::parse(json); + BinaryFormat::parse(json); } // Register formats static char n1[] = "raw"; static char d1[] = "Raw binary data"; -static FormatPlugin p1; +static FormatPlugin p1; static char n2[] = "gtnet"; static char d2[] = "RTDS GTNET"; -static FormatPlugin p2; +static FormatPlugin p2; diff --git a/lib/formats/value.cpp b/lib/formats/value.cpp index 33f3b416e..e4970006d 100644 --- a/lib/formats/value.cpp +++ b/lib/formats/value.cpp @@ -11,70 +11,71 @@ using namespace villas::node; -int ValueFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - unsigned i; - size_t off = 0; - const struct Sample *smp = smps[0]; +int ValueFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], unsigned cnt) { + unsigned i; + size_t off = 0; + const struct Sample *smp = smps[0]; - assert(cnt == 1); - assert(smp->length <= 1); + assert(cnt == 1); + assert(smp->length <= 1); - buf[0] = '\0'; + buf[0] = '\0'; - for (i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - return -1; + for (i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + return -1; - off += smp->data[i].printString(sig->type, buf, len, real_precision); - off += snprintf(buf + off, len - off, "\n"); - } + off += smp->data[i].printString(sig->type, buf, len, real_precision); + off += snprintf(buf + off, len - off, "\n"); + } - if (wbytes) - *wbytes = off; + if (wbytes) + *wbytes = off; - return i; + return i; } -int ValueFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - unsigned i = 0, ret; - struct Sample *smp = smps[0]; +int ValueFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + unsigned i = 0, ret; + struct Sample *smp = smps[0]; - const char *ptr = buf; - char *end; + const char *ptr = buf; + char *end; - assert(cnt == 1); + assert(cnt == 1); - printf("Reading: %s", buf); + printf("Reading: %s", buf); - if (smp->capacity >= 1) { - auto sig = signals->getByIndex(i); - if (!sig) - return -1; + if (smp->capacity >= 1) { + auto sig = signals->getByIndex(i); + if (!sig) + return -1; - ret = smp->data[i].parseString(sig->type, ptr, &end); - if (ret || end == ptr) // There are no valid values anymore. - goto out; + ret = smp->data[i].parseString(sig->type, ptr, &end); + if (ret || end == ptr) // There are no valid values anymore. + goto out; - i++; - ptr = end; - } + i++; + ptr = end; + } -out: smp->flags = 0; - smp->signals = signals; - smp->length = i; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; +out: + smp->flags = 0; + smp->signals = signals; + smp->length = i; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - if (rbytes) - *rbytes = ptr - buf; + if (rbytes) + *rbytes = ptr - buf; - return i; + return i; } // Register format static char n[] = "value"; static char d[] = "A bare text value without any headers"; -static FormatPlugin p; +static FormatPlugin p; diff --git a/lib/formats/villas_binary.cpp b/lib/formats/villas_binary.cpp index 87e233704..46211bafb 100644 --- a/lib/formats/villas_binary.cpp +++ b/lib/formats/villas_binary.cpp @@ -5,131 +5,125 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include +#include #include #include -#include +#include #include #include using namespace villas; using namespace villas::node; -int VillasBinaryFormat::sprint(char *buf, size_t len, size_t *wbytes, const struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i = 0; - char *ptr = buf; +int VillasBinaryFormat::sprint(char *buf, size_t len, size_t *wbytes, + const struct Sample *const smps[], + unsigned cnt) { + int ret; + unsigned i = 0; + char *ptr = buf; - for (i = 0; i < cnt; i++) { - struct Message *msg = (struct Message *) ptr; - const struct Sample *smp = smps[i]; + for (i = 0; i < cnt; i++) { + struct Message *msg = (struct Message *)ptr; + const struct Sample *smp = smps[i]; - if (ptr + MSG_LEN(smp->length) > buf + len) - break; + if (ptr + MSG_LEN(smp->length) > buf + len) + break; - ret = msg_from_sample(msg, smp, smp->signals, source_index); - if (ret) - return ret; + ret = msg_from_sample(msg, smp, smp->signals, source_index); + if (ret) + return ret; - if (web) { - // TODO: convert to little endian - } - else - msg_hton(msg); + if (web) { + // TODO: convert to little endian + } else + msg_hton(msg); - ptr += MSG_LEN(smp->length); - } + ptr += MSG_LEN(smp->length); + } - if (wbytes) - *wbytes = ptr - buf; + if (wbytes) + *wbytes = ptr - buf; - return i; + return i; } -int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, struct Sample * const smps[], unsigned cnt) -{ - int ret, values; - unsigned i, j; - const char *ptr = buf; - uint8_t sid; // source_index +int VillasBinaryFormat::sscan(const char *buf, size_t len, size_t *rbytes, + struct Sample *const smps[], unsigned cnt) { + int ret, values; + unsigned i, j; + const char *ptr = buf; + uint8_t sid; // source_index - if (len % 4 != 0) - return -1; // Packet size is invalid: Must be multiple of 4 bytes + if (len % 4 != 0) + return -1; // Packet size is invalid: Must be multiple of 4 bytes - for (i = 0, j = 0; i < cnt; i++) { - struct Message *msg = (struct Message *) ptr; - struct Sample *smp = smps[j]; + for (i = 0, j = 0; i < cnt; i++) { + struct Message *msg = (struct Message *)ptr; + struct Sample *smp = smps[j]; - smp->signals = signals; + smp->signals = signals; - // Complete buffer has been parsed - if (ptr == buf + len) - break; + // Complete buffer has been parsed + if (ptr == buf + len) + break; - // Check if header is still in buffer bounaries - if (ptr + sizeof(struct Message) > buf + len) - return -2; // Invalid msg received + // Check if header is still in buffer bounaries + if (ptr + sizeof(struct Message) > buf + len) + return -2; // Invalid msg received - values = web ? msg->length : ntohs(msg->length); + values = web ? msg->length : ntohs(msg->length); - // Check if remainder of message is in buffer boundaries - if (ptr + MSG_LEN(values) > buf + len) - return -3; // Invalid msg receive + // Check if remainder of message is in buffer boundaries + if (ptr + MSG_LEN(values) > buf + len) + return -3; // Invalid msg receive - if (web) { - // TODO: convert from little endian - } - else - msg_ntoh(msg); + if (web) { + // TODO: convert from little endian + } else + msg_ntoh(msg); - ret = msg_to_sample(msg, smp, signals, &sid); - if (ret) - return ret; // Invalid msg received + ret = msg_to_sample(msg, smp, signals, &sid); + if (ret) + return ret; // Invalid msg received - if (validate_source_index && sid != source_index) { - // source index mismatch: we skip this sample - } - else - j++; + if (validate_source_index && sid != source_index) { + // source index mismatch: we skip this sample + } else + j++; - ptr += MSG_LEN(smp->length); - } + ptr += MSG_LEN(smp->length); + } - if (rbytes) - *rbytes = ptr - buf; + if (rbytes) + *rbytes = ptr - buf; - return j; + return j; } -void VillasBinaryFormat::parse(json_t *json) -{ - int ret; - json_error_t err; - int sid = -1; - int vsi = -1; +void VillasBinaryFormat::parse(json_t *json) { + int ret; + json_error_t err; + int sid = -1; + int vsi = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b }", - "source_index", &sid, - "validate_source_index", &vsi - ); - if (ret) - throw ConfigError(json, err, "node-config-format-villas-binary", "Failed to parse format configuration"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b }", "source_index", &sid, + "validate_source_index", &vsi); + if (ret) + throw ConfigError(json, err, "node-config-format-villas-binary", + "Failed to parse format configuration"); - if (vsi >= 0) - validate_source_index = vsi != 0; + if (vsi >= 0) + validate_source_index = vsi != 0; - if (sid >= 0) - source_index = sid; + if (sid >= 0) + source_index = sid; - Format::parse(json); + Format::parse(json); } // Register formats -static -VillasBinaryFormatPlugin p1; -static -VillasBinaryFormatPlugin p2; +static VillasBinaryFormatPlugin p1; +static VillasBinaryFormatPlugin p2; diff --git a/lib/formats/villas_human.cpp b/lib/formats/villas_human.cpp index a6cb49dab..a06a2d04e 100644 --- a/lib/formats/villas_human.cpp +++ b/lib/formats/villas_human.cpp @@ -8,183 +8,190 @@ #include #include -#include -#include +#include #include #include -#include +#include +#include using namespace villas::node; -size_t VILLASHumanFormat::sprintLine(char *buf, size_t len, const struct Sample *smp) -{ - size_t off = 0; +size_t VILLASHumanFormat::sprintLine(char *buf, size_t len, + const struct Sample *smp) { + size_t off = 0; - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) { - off += snprintf(buf + off, len - off, "%llu", (unsigned long long) smp->ts.origin.tv_sec); - off += snprintf(buf + off, len - off, ".%09llu", (unsigned long long) smp->ts.origin.tv_nsec); - } - else - off += snprintf(buf + off, len - off, "0.0"); - } + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) { + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + off += snprintf(buf + off, len - off, "%llu", + (unsigned long long)smp->ts.origin.tv_sec); + off += snprintf(buf + off, len - off, ".%09llu", + (unsigned long long)smp->ts.origin.tv_nsec); + } else + off += snprintf(buf + off, len - off, "0.0"); + } - if (flags & (int) SampleFlags::HAS_OFFSET) { - if (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED) - off += snprintf(buf + off, len - off, "%+e", time_delta(&smp->ts.origin, &smp->ts.received)); - } + if (flags & (int)SampleFlags::HAS_OFFSET) { + if (smp->flags & (int)SampleFlags::HAS_TS_RECEIVED) + off += snprintf(buf + off, len - off, "%+e", + time_delta(&smp->ts.origin, &smp->ts.received)); + } - if (flags & (int) SampleFlags::HAS_SEQUENCE) { - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) - off += snprintf(buf + off, len - off, "(%" PRIu64 ")", smp->sequence); - } + if (flags & (int)SampleFlags::HAS_SEQUENCE) { + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) + off += snprintf(buf + off, len - off, "(%" PRIu64 ")", smp->sequence); + } - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned i = 0; i < smp->length; i++) { - auto sig = smp->signals->getByIndex(i); - if (!sig) - break; + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned i = 0; i < smp->length; i++) { + auto sig = smp->signals->getByIndex(i); + if (!sig) + break; - off += snprintf(buf + off, len - off, "\t"); - off += smp->data[i].printString(sig->type, buf + off, len - off, real_precision); - } - } + off += snprintf(buf + off, len - off, "\t"); + off += smp->data[i].printString(sig->type, buf + off, len - off, + real_precision); + } + } - off += snprintf(buf + off, len - off, "%c", delimiter); + off += snprintf(buf + off, len - off, "%c", delimiter); - return off; + return off; } -size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, struct Sample *smp) -{ - int ret; - char *end; - const char *ptr = buf; +size_t VILLASHumanFormat::sscanLine(const char *buf, size_t len, + struct Sample *smp) { + int ret; + char *end; + const char *ptr = buf; - double offset = 0; + double offset = 0; - smp->flags = 0; - smp->signals = signals; + smp->flags = 0; + smp->signals = signals; - /* Format: Seconds.NanoSeconds+Offset(SequenceNumber) Value1 Value2 ... + /* Format: Seconds.NanoSeconds+Offset(SequenceNumber) Value1 Value2 ... * RegEx: (\d+(?:\.\d+)?)([-+]\d+(?:\.\d+)?(?:e[+-]?\d+)?)?(?:\((\d+)\))? * * Please note that only the seconds and at least one value are mandatory */ - // Mandatory: seconds - smp->ts.origin.tv_sec = (uint32_t) strtoul(ptr, &end, 10); - if (ptr == end || *end == delimiter) - return -1; + // Mandatory: seconds + smp->ts.origin.tv_sec = (uint32_t)strtoul(ptr, &end, 10); + if (ptr == end || *end == delimiter) + return -1; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; - // Optional: nano seconds - if (*end == '.') { - ptr = end + 1; + // Optional: nano seconds + if (*end == '.') { + ptr = end + 1; - smp->ts.origin.tv_nsec = (uint32_t) strtoul(ptr, &end, 10); - if (ptr == end) - return -3; - } - else - smp->ts.origin.tv_nsec = 0; + smp->ts.origin.tv_nsec = (uint32_t)strtoul(ptr, &end, 10); + if (ptr == end) + return -3; + } else + smp->ts.origin.tv_nsec = 0; - // Optional: offset / delay - if (*end == '+' || *end == '-') { - ptr = end; + // Optional: offset / delay + if (*end == '+' || *end == '-') { + ptr = end; - offset = strtof(ptr, &end); // offset is ignored for now - if (ptr != end) - smp->flags |= (int) SampleFlags::HAS_OFFSET; - else - return -4; - } + offset = strtof(ptr, &end); // offset is ignored for now + if (ptr != end) + smp->flags |= (int)SampleFlags::HAS_OFFSET; + else + return -4; + } - // Optional: sequence - if (*end == '(') { - ptr = end + 1; + // Optional: sequence + if (*end == '(') { + ptr = end + 1; - smp->sequence = strtoul(ptr, &end, 10); - if (ptr != end) - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - else - return -5; + smp->sequence = strtoul(ptr, &end, 10); + if (ptr != end) + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + else + return -5; - if (*end == ')') - end++; - } + if (*end == ')') + end++; + } - unsigned i; - for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) { - if (*end == delimiter) - goto out; + unsigned i; + for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) { + if (*end == delimiter) + goto out; - auto sig = signals->getByIndex(i); - if (!sig) - goto out; + auto sig = signals->getByIndex(i); + if (!sig) + goto out; - ret = smp->data[i].parseString(sig->type, ptr, &end); - if (ret || end == ptr) // There are no valid values anymore. - goto out; - } + ret = smp->data[i].parseString(sig->type, ptr, &end); + if (ret || end == ptr) // There are no valid values anymore. + goto out; + } -out: if (*end == delimiter) - end++; +out: + if (*end == delimiter) + end++; - smp->length = i; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + smp->length = i; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - if (smp->flags & (int) SampleFlags::HAS_OFFSET) { - struct timespec off = time_from_double(offset); - smp->ts.received = time_add(&smp->ts.origin, &off); + if (smp->flags & (int)SampleFlags::HAS_OFFSET) { + struct timespec off = time_from_double(offset); + smp->ts.received = time_add(&smp->ts.origin, &off); - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - return end - buf; + return end - buf; } -void VILLASHumanFormat::header(FILE *f, const SignalList::Ptr sigs) -{ - // Abort if we are not supposed to, or have already printed the header - if (!print_header || header_printed) - return; +void VILLASHumanFormat::header(FILE *f, const SignalList::Ptr sigs) { + // Abort if we are not supposed to, or have already printed the header + if (!print_header || header_printed) + return; - fprintf(f, "# "); + fprintf(f, "# "); - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) - fprintf(f, "seconds.nanoseconds"); + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) + fprintf(f, "seconds.nanoseconds"); - if (flags & (int) SampleFlags::HAS_OFFSET) - fprintf(f, "+offset"); + if (flags & (int)SampleFlags::HAS_OFFSET) + fprintf(f, "+offset"); - if (flags & (int) SampleFlags::HAS_SEQUENCE) - fprintf(f, "(sequence)"); + if (flags & (int)SampleFlags::HAS_SEQUENCE) + fprintf(f, "(sequence)"); - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned i = 0; i < sigs->size(); i++) { - auto sig = sigs->getByIndex(i); - if (!sig) - break; + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned i = 0; i < sigs->size(); i++) { + auto sig = sigs->getByIndex(i); + if (!sig) + break; - if (!sig->name.empty()) - fprintf(f, "\t%s", sig->name.c_str()); - else - fprintf(f, "\tsignal%u", i); + if (!sig->name.empty()) + fprintf(f, "\t%s", sig->name.c_str()); + else + fprintf(f, "\tsignal%u", i); - if (!sig->unit.empty()) - fprintf(f, "[%s]", sig->unit.c_str()); - } - } + if (!sig->unit.empty()) + fprintf(f, "[%s]", sig->unit.c_str()); + } + } - fprintf(f, "%c", delimiter); + fprintf(f, "%c", delimiter); - LineFormat::header(f, sigs); + LineFormat::header(f, sigs); } // Register format static char n[] = "villas.human"; static char d[] = "VILLAS human readable format"; -static LineFormatPlugin p; +static LineFormatPlugin + p; diff --git a/lib/hook.cpp b/lib/hook.cpp index ed61459a1..363b74b37 100644 --- a/lib/hook.cpp +++ b/lib/hook.cpp @@ -5,172 +5,154 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include -#include #include +#include +#include #include #include +#include #include -#include -const char *hook_reasons[] = { - "ok", "error", "skip-sample", "stop-processing" -}; +const char *hook_reasons[] = {"ok", "error", "skip-sample", "stop-processing"}; using namespace villas; using namespace villas::node; -Hook::Hook(Path *p, Node *n, int fl, int prio, bool en) : - logger(logging.get("hook")), - factory(nullptr), - state(fl & (int) Hook::Flags::BUILTIN - ? State::CHECKED - : State::INITIALIZED), // We dont need to parse builtin hooks - flags(fl), - priority(prio), - enabled(en), - path(p), - node(n), - config(nullptr) -{ } +Hook::Hook(Path *p, Node *n, int fl, int prio, bool en) + : logger(logging.get("hook")), factory(nullptr), + state(fl & (int)Hook::Flags::BUILTIN + ? State::CHECKED + : State::INITIALIZED), // We dont need to parse builtin hooks + flags(fl), priority(prio), enabled(en), path(p), node(n), + config(nullptr) {} -void Hook::prepare(SignalList::Ptr sigs) -{ - assert(state == State::CHECKED); +void Hook::prepare(SignalList::Ptr sigs) { + assert(state == State::CHECKED); - signals = sigs->clone(); + signals = sigs->clone(); - prepare(); + prepare(); - state = State::PREPARED; + state = State::PREPARED; } -void Hook::parse(json_t *json) -{ - int ret; - json_error_t err; +void Hook::parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - int prio = -1; - int en = -1; + int prio = -1; + int en = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b }", - "priority", &prio, - "enabled", &en - ); - if (ret) - throw ConfigError(json, err, "node-config-hook"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: b }", "priority", &prio, + "enabled", &en); + if (ret) + throw ConfigError(json, err, "node-config-hook"); - if (prio >= 0) - priority = prio; + if (prio >= 0) + priority = prio; - if (en >= 0) - enabled = en; + if (en >= 0) + enabled = en; - config = json; + config = json; - state = State::PARSED; + state = State::PARSED; } -void SingleSignalHook::parse(json_t *json) -{ - int ret; +void SingleSignalHook::parse(json_t *json) { + int ret; - json_error_t err; - json_t *json_signal; + json_error_t err; + json_t *json_signal; - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: o }", - "signal", &json_signal - ); - if (ret) - throw ConfigError(json, err, "node-config-hook"); + ret = json_unpack_ex(json, &err, 0, "{ s: o }", "signal", &json_signal); + if (ret) + throw ConfigError(json, err, "node-config-hook"); - if (!json_is_string(json_signal)) - throw ConfigError(json_signal, "node-config-hook-signals", "Invalid value for setting 'signal'"); + if (!json_is_string(json_signal)) + throw ConfigError(json_signal, "node-config-hook-signals", + "Invalid value for setting 'signal'"); - signalName = json_string_value(json_signal); + signalName = json_string_value(json_signal); } -void SingleSignalHook::prepare() -{ - Hook::prepare(); +void SingleSignalHook::prepare() { + Hook::prepare(); - // Setup mask - int index = signals->getIndexByName(signalName.c_str()); - if (index < 0) - throw RuntimeError("Failed to find signal {}", signalName); + // Setup mask + int index = signals->getIndexByName(signalName.c_str()); + if (index < 0) + throw RuntimeError("Failed to find signal {}", signalName); - signalIndex = (unsigned) index; + signalIndex = (unsigned)index; } // Multi Signal Hook -void MultiSignalHook::parse(json_t *json) -{ - int ret; - size_t i; +void MultiSignalHook::parse(json_t *json) { + int ret; + size_t i; - json_error_t err; - json_t *json_signals = nullptr; - json_t *json_signal = nullptr; + json_error_t err; + json_t *json_signals = nullptr; + json_t *json_signal = nullptr; - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o }", - "signals", &json_signals, - "signal", &json_signal - ); - if (ret) - throw ConfigError(json, err, "node-config-hook"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o }", "signals", + &json_signals, "signal", &json_signal); + if (ret) + throw ConfigError(json, err, "node-config-hook"); - if (json_signals) { - if (!json_is_array(json_signals)) - throw ConfigError(json_signals, "node-config-hook-signals", "Setting 'signals' must be a list of signal names"); + if (json_signals) { + if (!json_is_array(json_signals)) + throw ConfigError(json_signals, "node-config-hook-signals", + "Setting 'signals' must be a list of signal names"); - json_array_foreach(json_signals, i, json_signal) { - if (!json_is_string(json_signal)) - throw ConfigError(json_signal, "node-config-hook-signals", "Invalid value for setting 'signals'"); + json_array_foreach(json_signals, i, json_signal) { + if (!json_is_string(json_signal)) + throw ConfigError(json_signal, "node-config-hook-signals", + "Invalid value for setting 'signals'"); - const char *name = json_string_value(json_signal); + const char *name = json_string_value(json_signal); - signalNames.push_back(name); - } - } - else if (json_signal) { - if (!json_is_string(json_signal)) - throw ConfigError(json_signal, "node-config-hook-signals", "Invalid value for setting 'signals'"); + signalNames.push_back(name); + } + } else if (json_signal) { + if (!json_is_string(json_signal)) + throw ConfigError(json_signal, "node-config-hook-signals", + "Invalid value for setting 'signals'"); - const char *name = json_string_value(json_signal); + const char *name = json_string_value(json_signal); - signalNames.push_back(name); - } - else - throw ConfigError(json, "node-config-hook-signals", "Missing 'signals' setting"); + signalNames.push_back(name); + } else + throw ConfigError(json, "node-config-hook-signals", + "Missing 'signals' setting"); } -void MultiSignalHook::prepare() -{ - Hook::prepare(); +void MultiSignalHook::prepare() { + Hook::prepare(); - for (const auto &signalName : signalNames) { - int index = signals->getIndexByName(signalName.c_str()); - if (index < 0) - throw RuntimeError("Failed to find signal {}", signalName); + for (const auto &signalName : signalNames) { + int index = signals->getIndexByName(signalName.c_str()); + if (index < 0) + throw RuntimeError("Failed to find signal {}", signalName); - signalIndices.push_back(index); - } + signalIndices.push_back(index); + } } -void MultiSignalHook::check() -{ - Hook::check(); +void MultiSignalHook::check() { + Hook::check(); - if (signalNames.size() == 0) - throw RuntimeError("At least a single signal must be provided"); + if (signalNames.size() == 0) + throw RuntimeError("At least a single signal must be provided"); } diff --git a/lib/hook_list.cpp b/lib/hook_list.cpp index 5e3452aac..2eadc93c9 100644 --- a/lib/hook_list.cpp +++ b/lib/hook_list.cpp @@ -5,193 +5,190 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include -#include +#include #include +#include using namespace villas; using namespace villas::node; -void HookList::parse(json_t *json, int mask, Path *o, Node *n) -{ - if (!json_is_array(json)) - throw ConfigError(json, "node-config-hook", "Hooks must be configured as a list of hook objects"); +void HookList::parse(json_t *json, int mask, Path *o, Node *n) { + if (!json_is_array(json)) + throw ConfigError(json, "node-config-hook", + "Hooks must be configured as a list of hook objects"); - size_t i; - json_t *json_hook; - json_array_foreach(json, i, json_hook) { - int ret; - const char *type; - Hook::Ptr h; - json_error_t err; - json_t *json_config; + size_t i; + json_t *json_hook; + json_array_foreach(json, i, json_hook) { + int ret; + const char *type; + Hook::Ptr h; + json_error_t err; + json_t *json_config; - switch (json_typeof(json_hook)) { - case JSON_STRING: - type = json_string_value(json_hook); - json_config = json_object(); - break; + switch (json_typeof(json_hook)) { + case JSON_STRING: + type = json_string_value(json_hook); + json_config = json_object(); + break; - case JSON_OBJECT: - ret = json_unpack_ex(json_hook, &err, 0, "{ s: s }", "type", &type); - if (ret) - throw ConfigError(json_hook, err, "node-config-hook", "Failed to parse hook"); - json_config = json_hook; - break; + case JSON_OBJECT: + ret = json_unpack_ex(json_hook, &err, 0, "{ s: s }", "type", &type); + if (ret) + throw ConfigError(json_hook, err, "node-config-hook", + "Failed to parse hook"); + json_config = json_hook; + break; - default: - throw ConfigError(json_hook, "node-config-hook", "Hook must be configured by simple string or object"); - } + default: + throw ConfigError(json_hook, "node-config-hook", + "Hook must be configured by simple string or object"); + } - auto hf = plugin::registry->lookup(type); - if (!hf) - throw ConfigError(json_hook, "node-config-hook", "Unknown hook type '{}'", type); + auto hf = plugin::registry->lookup(type); + if (!hf) + throw ConfigError(json_hook, "node-config-hook", "Unknown hook type '{}'", + type); - if (!(hf->getFlags() & mask)) - throw ConfigError(json_hook, "node-config-hook", "Hook '{}' not allowed here", type); + if (!(hf->getFlags() & mask)) + throw ConfigError(json_hook, "node-config-hook", + "Hook '{}' not allowed here", type); - h = hf->make(o, n); - h->parse(json_config); + h = hf->make(o, n); + h->parse(json_config); - push_back(h); - } + push_back(h); + } } -void HookList::check() -{ - for (auto h : *this) - h->check(); +void HookList::check() { + for (auto h : *this) + h->check(); } -void HookList::prepare(SignalList::Ptr signals, int m, Path *p, Node *n) -{ - if (!m) - goto skip_add; +void HookList::prepare(SignalList::Ptr signals, int m, Path *p, Node *n) { + if (!m) + goto skip_add; - // Add internal hooks if they are not already in the list - for (auto f : plugin::registry->lookup()) { - if ((f->getFlags() & m) == m) { - auto h = f->make(p, n); - push_back(h); - } - } + // Add internal hooks if they are not already in the list + for (auto f : plugin::registry->lookup()) { + if ((f->getFlags() & m) == m) { + auto h = f->make(p, n); + push_back(h); + } + } skip_add: - // Remove filters which are not enabled - remove_if([](Hook::Ptr h) { return !h->isEnabled(); }); + // Remove filters which are not enabled + remove_if([](Hook::Ptr h) { return !h->isEnabled(); }); - // We sort the hooks according to their priority - sort([](const value_type &a, const value_type b) { return a->getPriority() < b->getPriority(); }); + // We sort the hooks according to their priority + sort([](const value_type &a, const value_type b) { + return a->getPriority() < b->getPriority(); + }); - unsigned i = 0; - auto sigs = signals; - for (auto h : *this) { - h->prepare(sigs); + unsigned i = 0; + auto sigs = signals; + for (auto h : *this) { + h->prepare(sigs); - sigs = h->getSignals(); + sigs = h->getSignals(); - auto logger = h->getLogger(); - logger->debug("Signal list after hook #{}:", i++); - if (logger->level() <= spdlog::level::debug) - sigs->dump(logger); - } + auto logger = h->getLogger(); + logger->debug("Signal list after hook #{}:", i++); + if (logger->level() <= spdlog::level::debug) + sigs->dump(logger); + } } -int HookList::process(struct Sample * smps[], unsigned cnt) -{ - unsigned current, processed = 0; +int HookList::process(struct Sample *smps[], unsigned cnt) { + unsigned current, processed = 0; - if (size() == 0) - return cnt; + if (size() == 0) + return cnt; - for (current = 0; current < cnt; current++) { - struct Sample *smp = smps[current]; + for (current = 0; current < cnt; current++) { + struct Sample *smp = smps[current]; - for (auto h : *this) { - auto ret = h->process(smp); - smp->signals = h->getSignals(); - switch (ret) { - case Hook::Reason::ERROR: - return -1; + for (auto h : *this) { + auto ret = h->process(smp); + smp->signals = h->getSignals(); + switch (ret) { + case Hook::Reason::ERROR: + return -1; - case Hook::Reason::OK: - continue; + case Hook::Reason::OK: + continue; - case Hook::Reason::SKIP_SAMPLE: - goto skip; + case Hook::Reason::SKIP_SAMPLE: + goto skip; - case Hook::Reason::STOP_PROCESSING: - goto stop; - } - } + case Hook::Reason::STOP_PROCESSING: + goto stop; + } + } -stop: SWAP(smps[processed], smps[current]); - processed++; -skip: {} - } + stop: + SWAP(smps[processed], smps[current]); + processed++; + skip : {} + } - return processed; + return processed; } -void HookList::periodic() -{ - for (auto h : *this) - h->periodic(); +void HookList::periodic() { + for (auto h : *this) + h->periodic(); } -void HookList::start() -{ - for (auto h : *this) - h->start(); +void HookList::start() { + for (auto h : *this) + h->start(); } -void HookList::stop() -{ - for (auto h : *this) - h->stop(); +void HookList::stop() { + for (auto h : *this) + h->stop(); } -SignalList::Ptr HookList::getSignals() const -{ - auto h = back(); - if (!h) - return nullptr; +SignalList::Ptr HookList::getSignals() const { + auto h = back(); + if (!h) + return nullptr; - return h->getSignals(); + return h->getSignals(); } -unsigned HookList::getSignalsMaxCount() const -{ - unsigned max_cnt = 0; +unsigned HookList::getSignalsMaxCount() const { + unsigned max_cnt = 0; - for (auto h : *this) { - unsigned sigs_cnt = h->getSignals()->size(); + for (auto h : *this) { + unsigned sigs_cnt = h->getSignals()->size(); - if (sigs_cnt > max_cnt) - max_cnt = sigs_cnt; - } + if (sigs_cnt > max_cnt) + max_cnt = sigs_cnt; + } - return max_cnt; + return max_cnt; } -json_t * HookList::toJson() const -{ - json_t *json_hooks = json_array(); +json_t *HookList::toJson() const { + json_t *json_hooks = json_array(); - for (auto h : *this) - json_array_append(json_hooks, h->getConfig()); + for (auto h : *this) + json_array_append(json_hooks, h->getConfig()); - return json_hooks; + return json_hooks; } -void HookList::dump(Logger logger, std::string subject) const -{ - logger->debug("Hooks of {}:", subject); +void HookList::dump(Logger logger, std::string subject) const { + logger->debug("Hooks of {}:", subject); - unsigned i = 0; - for (auto h : *this) - logger->debug(" {}: {}", i++, h->getFactory()->getName()); + unsigned i = 0; + for (auto h : *this) + logger->debug(" {}: {}", i++, h->getFactory()->getName()); } diff --git a/lib/hooks/average.cpp b/lib/hooks/average.cpp index e6b77d264..895cdf9ff 100644 --- a/lib/hooks/average.cpp +++ b/lib/hooks/average.cpp @@ -10,8 +10,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -19,92 +19,85 @@ namespace node { class AverageHook : public MultiSignalHook { protected: - unsigned offset; + unsigned offset; public: - AverageHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - offset(0) - { } + AverageHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), offset(0) {} - virtual - void prepare() - { - assert(state == State::CHECKED); + virtual void prepare() { + assert(state == State::CHECKED); - MultiSignalHook::prepare(); + MultiSignalHook::prepare(); - // Add averaged signal - auto avg_sig = std::make_shared("average", "", SignalType::FLOAT); - if (!avg_sig) - throw RuntimeError("Failed to create new signal"); + // Add averaged signal + auto avg_sig = std::make_shared("average", "", SignalType::FLOAT); + if (!avg_sig) + throw RuntimeError("Failed to create new signal"); - signals->insert(signals->begin() + offset, avg_sig); + signals->insert(signals->begin() + offset, avg_sig); - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: i }", - "offset", &offset - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-average"); + ret = json_unpack_ex(json, &err, 0, "{ s: i }", "offset", &offset); + if (ret) + throw ConfigError(json, err, "node-config-hook-average"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - double avg, sum = 0; - int n = 0; + virtual Hook::Reason process(struct Sample *smp) { + double avg, sum = 0; + int n = 0; - assert(state == State::STARTED); + assert(state == State::STARTED); - for (unsigned index : signalIndices) { - switch (sample_format(smp, index)) { - case SignalType::INTEGER: - sum += smp->data[index].i; - break; + for (unsigned index : signalIndices) { + switch (sample_format(smp, index)) { + case SignalType::INTEGER: + sum += smp->data[index].i; + break; - case SignalType::FLOAT: - sum += smp->data[index].f; - break; + case SignalType::FLOAT: + sum += smp->data[index].f; + break; - case SignalType::INVALID: - case SignalType::COMPLEX: - case SignalType::BOOLEAN: - return Hook::Reason::ERROR; // not supported - } + case SignalType::INVALID: + case SignalType::COMPLEX: + case SignalType::BOOLEAN: + return Hook::Reason::ERROR; // not supported + } - n++; - } + n++; + } - avg = sum / n; + avg = sum / n; - if (offset >= smp->length) - return Reason::ERROR; + if (offset >= smp->length) + return Reason::ERROR; - sample_data_insert(smp, (union SignalData *) &avg, offset, 1); + sample_data_insert(smp, (union SignalData *)&avg, offset, 1); - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "average"; static char d[] = "Calculate average over some signals"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/cast.cpp b/lib/hooks/cast.cpp index 8fb373830..03c6a7ad3 100644 --- a/lib/hooks/cast.cpp +++ b/lib/hooks/cast.cpp @@ -16,97 +16,87 @@ namespace node { class CastHook : public MultiSignalHook { protected: - enum SignalType new_type; - std::string new_name; - std::string new_unit; + enum SignalType new_type; + std::string new_name; + std::string new_unit; public: - CastHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - new_type(SignalType::INVALID) - { } + CastHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), new_type(SignalType::INVALID) {} - virtual - void prepare() - { - assert(state == State::CHECKED); + virtual void prepare() { + assert(state == State::CHECKED); - MultiSignalHook::prepare(); + MultiSignalHook::prepare(); - for (auto index : signalIndices) { - auto orig_sig = signals->getByIndex(index); + for (auto index : signalIndices) { + auto orig_sig = signals->getByIndex(index); - auto type = new_type == SignalType::INVALID ? orig_sig->type : new_type; - auto name = new_name.empty() ? orig_sig->name : new_name; - auto unit = new_unit.empty() ? orig_sig->unit : new_unit; + auto type = new_type == SignalType::INVALID ? orig_sig->type : new_type; + auto name = new_name.empty() ? orig_sig->name : new_name; + auto unit = new_unit.empty() ? orig_sig->unit : new_unit; - (*signals)[index] = std::make_shared(name, unit, type); - } + (*signals)[index] = std::make_shared(name, unit, type); + } - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - int ret; + virtual void parse(json_t *json) { + int ret; - json_error_t err; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - const char *name = nullptr; - const char *unit = nullptr; - const char *type = nullptr; + const char *name = nullptr; + const char *unit = nullptr; + const char *type = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s }", - "new_type", &type, - "new_name", &name, - "new_unit", &unit - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-cast"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s }", "new_type", + &type, "new_name", &name, "new_unit", &unit); + if (ret) + throw ConfigError(json, err, "node-config-hook-cast"); - if (type) { - new_type = signalTypeFromString(type); - if (new_type == SignalType::INVALID) - throw RuntimeError("Invalid signal type: {}", type); - } - else - // We use this constant to indicate that we dont want to change the type. - new_type = SignalType::INVALID; + if (type) { + new_type = signalTypeFromString(type); + if (new_type == SignalType::INVALID) + throw RuntimeError("Invalid signal type: {}", type); + } else + // We use this constant to indicate that we dont want to change the type. + new_type = SignalType::INVALID; - if (name) - new_name = name; + if (name) + new_name = name; - if (unit) - new_unit = unit; + if (unit) + new_unit = unit; - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - for (auto index : signalIndices) { - auto orig_sig = smp->signals->getByIndex(index); - auto new_sig = signals->getByIndex(index); + for (auto index : signalIndices) { + auto orig_sig = smp->signals->getByIndex(index); + auto new_sig = signals->getByIndex(index); - smp->data[index] = smp->data[index].cast(orig_sig->type, new_sig->type); - } + smp->data[index] = smp->data[index].cast(orig_sig->type, new_sig->type); + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "cast"; static char d[] = "Cast signals types"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/decimate.cpp b/lib/hooks/decimate.cpp index a8124aa16..d30b7ac52 100644 --- a/lib/hooks/decimate.cpp +++ b/lib/hooks/decimate.cpp @@ -11,51 +11,49 @@ namespace villas { namespace node { -void DecimateHook::start() -{ - assert(state == State::PREPARED); +void DecimateHook::start() { + assert(state == State::PREPARED); - counter = 0; + counter = 0; - state = State::STARTED; + state = State::STARTED; } -void DecimateHook::parse(json_t *json) -{ - int ret; - json_error_t err; +void DecimateHook::parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: i, s?: b }", - "ratio", &ratio, - "renumber", &renumber - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-decimate"); + ret = json_unpack_ex(json, &err, 0, "{ s: i, s?: b }", "ratio", &ratio, + "renumber", &renumber); + if (ret) + throw ConfigError(json, err, "node-config-hook-decimate"); - state = State::PARSED; + state = State::PARSED; } -Hook::Reason DecimateHook::process(struct Sample *smp) -{ - assert(state == State::STARTED); +Hook::Reason DecimateHook::process(struct Sample *smp) { + assert(state == State::STARTED); - if (renumber) - smp->sequence /= ratio; + if (renumber) + smp->sequence /= ratio; - if (ratio && counter++ % ratio != 0) - return Hook::Reason::SKIP_SAMPLE; + if (ratio && counter++ % ratio != 0) + return Hook::Reason::SKIP_SAMPLE; - return Reason::OK; + return Reason::OK; } // Register hook static char n[] = "decimate"; static char d[] = "Downsamping by integer factor"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/dp.cpp b/lib/hooks/dp.cpp index c6a1c69fd..fd2b47687 100644 --- a/lib/hooks/dp.cpp +++ b/lib/hooks/dp.cpp @@ -10,9 +10,9 @@ #include +#include #include #include -#include #include using namespace std::complex_literals; @@ -24,36 +24,35 @@ namespace node { class DPHook : public Hook { protected: - char *signal_name; - unsigned signal_index; + char *signal_name; + unsigned signal_index; - int offset; - int inverse; + int offset; + int inverse; - double f0; - double timestep; - double time; - double steps; + double f0; + double timestep; + double time; + double steps; - std::complex *coeffs; - int *fharmonics; - int fharmonics_len; + std::complex *coeffs; + int *fharmonics; + int fharmonics_len; - dsp::Window window; + dsp::Window window; - void step(double *in, std::complex *out) - { - int N = window.size(); - __attribute__((unused)) std::complex om_k, corr; - double newest = *in; - __attribute__((unused)) double oldest = window.update(newest); + void step(double *in, std::complex *out) { + int N = window.size(); + __attribute__((unused)) std::complex om_k, corr; + double newest = *in; + __attribute__((unused)) double oldest = window.update(newest); - for (int k = 0; k < fharmonics_len; k++) { - om_k = 2.0i * M_PI * (double) fharmonics[k] / (double) N; + for (int k = 0; k < fharmonics_len; k++) { + om_k = 2.0i * M_PI * (double)fharmonics[k] / (double)N; - // Correction for stationary phasor - corr = std::exp(-om_k * (steps - (N + 1))); - //corr = 1; + // Correction for stationary phasor + corr = std::exp(-om_k * (steps - (N + 1))); + //corr = 1; #if 0 // Recursive update @@ -65,242 +64,225 @@ protected: if (fharmonics[k] == 0) out[k] /= 2.0; #else - // Full DFT - std::complex X_k = 0; + // Full DFT + std::complex X_k = 0; - for (int n = 0; n < N; n++) { - double x_n = window[n]; + for (int n = 0; n < N; n++) { + double x_n = window[n]; - X_k += x_n * std::exp(om_k * (double) n); - } + X_k += x_n * std::exp(om_k * (double)n); + } - out[k] = X_k / (corr * (double) N); + out[k] = X_k / (corr * (double)N); #endif - } - } + } + } - void istep(std::complex *in, double *out) - { - std::complex value = 0; + void istep(std::complex *in, double *out) { + std::complex value = 0; - // Reconstruct the original signal - for (int k = 0; k < fharmonics_len; k++) { - double freq = fharmonics[k]; - // cppcheck-suppress objectIndex - std::complex coeff = in[k]; - std::complex om = 2.0i * M_PI * freq * time; + // Reconstruct the original signal + for (int k = 0; k < fharmonics_len; k++) { + double freq = fharmonics[k]; + // cppcheck-suppress objectIndex + std::complex coeff = in[k]; + std::complex om = 2.0i * M_PI * freq * time; - value += coeff * std::exp(om); - } + value += coeff * std::exp(om); + } - *out = std::real(value); - } + *out = std::real(value); + } public: + DPHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), signal_name(nullptr), signal_index(0), + offset(0), inverse(0), f0(50.0), timestep(50e-6), time(), steps(0), + coeffs(), fharmonics(), fharmonics_len(0) {} - DPHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - signal_name(nullptr), - signal_index(0), - offset(0), - inverse(0), - f0(50.0), - timestep(50e-6), - time(), - steps(0), - coeffs(), - fharmonics(), - fharmonics_len(0) - { } + virtual ~DPHook() { + // Release memory + if (fharmonics) + delete fharmonics; - virtual - ~DPHook() - { - // Release memory - if (fharmonics) - delete fharmonics; + if (coeffs) + delete coeffs; - if (coeffs) - delete coeffs; + if (signal_name) + free(signal_name); + } - if (signal_name) - free(signal_name); - } + virtual void start() { + assert(state == State::PREPARED); - virtual - void start() - { - assert(state == State::PREPARED); + time = 0; + steps = 0; - time = 0; - steps = 0; + for (int i = 0; i < fharmonics_len; i++) + coeffs[i] = 0; - for (int i = 0; i < fharmonics_len; i++) - coeffs[i] = 0; + window = dsp::Window((1.0 / f0) / timestep, 0.0); - window = dsp::Window((1.0 / f0) / timestep, 0.0); + state = State::STARTED; + } - state = State::STARTED; - } + virtual void parse(json_t *json) { + int ret; + json_error_t err; + json_t *json_harmonics, *json_harmonic, *json_signal; + size_t i; - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; - json_t *json_harmonics, *json_harmonic, *json_signal; - size_t i; + Hook::parse(json); - Hook::parse(json); + double rate = -1, dt = -1; - double rate = -1, dt = -1; + ret = json_unpack_ex(json, &err, 0, + "{ s: o, s: F, s?: F, s?: F, s: o, s?: b }", "signal", + &json_signal, "f0", &f0, "dt", &dt, "rate", &rate, + "harmonics", &json_harmonics, "inverse", &inverse); + if (ret) + throw ConfigError(json, err, "node-config-hook-dp"); - ret = json_unpack_ex(json, &err, 0, "{ s: o, s: F, s?: F, s?: F, s: o, s?: b }", - "signal", &json_signal, - "f0", &f0, - "dt", &dt, - "rate", &rate, - "harmonics", &json_harmonics, - "inverse", &inverse - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-dp"); + if (rate > 0) + timestep = 1. / rate; + else if (dt > 0) + timestep = dt; + else + throw ConfigError( + json, "node-config-hook-dp", + "Either on of the settings 'dt' or 'rate' must be given"); - if (rate > 0) - timestep = 1. / rate; - else if (dt > 0) - timestep = dt; - else - throw ConfigError(json, "node-config-hook-dp", "Either on of the settings 'dt' or 'rate' must be given"); + if (!json_is_array(json_harmonics)) + throw ConfigError(json_harmonics, "node-config-hook-dp-harmonics", + "Setting 'harmonics' must be a list of integers"); - if (!json_is_array(json_harmonics)) - throw ConfigError(json_harmonics, "node-config-hook-dp-harmonics", "Setting 'harmonics' must be a list of integers"); + switch (json_typeof(json_signal)) { + case JSON_STRING: + signal_name = strdup(json_string_value(json_signal)); + break; - switch (json_typeof(json_signal)) { - case JSON_STRING: - signal_name = strdup(json_string_value(json_signal)); - break; + case JSON_INTEGER: + signal_name = nullptr; + signal_index = json_integer_value(json_signal); + break; - case JSON_INTEGER: - signal_name = nullptr; - signal_index = json_integer_value(json_signal); - break; + default: + throw ConfigError(json_signal, "node-config-hook-dp-signal", + "Invalid value for setting 'signal'"); + } - default: - throw ConfigError(json_signal, "node-config-hook-dp-signal", "Invalid value for setting 'signal'"); - } + fharmonics_len = json_array_size(json_harmonics); + fharmonics = new int[fharmonics_len]; + coeffs = new std::complex[fharmonics_len]; + if (!fharmonics || !coeffs) + throw MemoryAllocationError(); - fharmonics_len = json_array_size(json_harmonics); - fharmonics = new int[fharmonics_len]; - coeffs = new std::complex[fharmonics_len]; - if (!fharmonics || !coeffs) - throw MemoryAllocationError(); + json_array_foreach(json_harmonics, i, json_harmonic) { + if (!json_is_integer(json_harmonic)) + throw ConfigError(json_harmonic, "node-config-hook-dp-harmonics", + "Setting 'harmonics' must be a list of integers"); - json_array_foreach(json_harmonics, i, json_harmonic) { - if (!json_is_integer(json_harmonic)) - throw ConfigError(json_harmonic, "node-config-hook-dp-harmonics", "Setting 'harmonics' must be a list of integers"); + fharmonics[i] = json_integer_value(json_harmonic); + } - fharmonics[i] = json_integer_value(json_harmonic); - } + state = State::PARSED; + } - state = State::PARSED; - } + virtual void prepare() { + assert(state == State::CHECKED); - virtual - void prepare() - { - assert(state == State::CHECKED); + char *new_sig_name; - char *new_sig_name; + assert(state != State::STARTED); - assert(state != State::STARTED); + if (signal_name) { + signal_index = signals->getIndexByName(signal_name); + if (signal_index < 0) + throw RuntimeError("Failed to find signal: {}", signal_name); + } - if (signal_name) { - signal_index = signals->getIndexByName(signal_name); - if (signal_index < 0) - throw RuntimeError("Failed to find signal: {}", signal_name); - } + if (inverse) { + // Remove complex-valued coefficient signals + for (int i = 0; i < fharmonics_len; i++) { + auto orig_sig = signals->getByIndex(signal_index + i); + if (!orig_sig) + throw RuntimeError("Failed to find signal"); - if (inverse) { - // Remove complex-valued coefficient signals - for (int i = 0; i < fharmonics_len; i++) { - auto orig_sig = signals->getByIndex(signal_index + i); - if (!orig_sig) - throw RuntimeError("Failed to find signal"); + if (orig_sig->type != SignalType::COMPLEX) + throw RuntimeError("Signal is not complex"); - if (orig_sig->type != SignalType::COMPLEX) - throw RuntimeError("Signal is not complex"); + signals->erase(signals->begin() + signal_index + i); + } - signals->erase(signals->begin() + signal_index + i); - } + // Add new real-valued reconstructed signals + auto new_sig = std::make_shared("dp", "idp", SignalType::FLOAT); + if (!new_sig) + throw RuntimeError("Failed to create signal"); - // Add new real-valued reconstructed signals - auto new_sig = std::make_shared("dp", "idp", SignalType::FLOAT); - if (!new_sig) - throw RuntimeError("Failed to create signal"); + signals->insert(signals->begin() + offset, new_sig); + } else { + auto orig_sig = signals->getByIndex(signal_index); + if (!orig_sig) + throw RuntimeError("Failed to find signal"); - signals->insert(signals->begin() + offset, new_sig); - } - else { - auto orig_sig = signals->getByIndex(signal_index); - if (!orig_sig) - throw RuntimeError("Failed to find signal"); + if (orig_sig->type != SignalType::FLOAT) + throw RuntimeError("Signal is not float"); - if (orig_sig->type != SignalType::FLOAT) - throw RuntimeError("Signal is not float"); + signals->erase(signals->begin() + signal_index); - signals->erase(signals->begin() + signal_index); + for (int i = 0; i < fharmonics_len; i++) { + new_sig_name = strf("%s_harm%d", orig_sig->name, i); - for (int i = 0; i < fharmonics_len; i++) { - new_sig_name = strf("%s_harm%d", orig_sig->name, i); + auto new_sig = std::make_shared(new_sig_name, orig_sig->unit, + SignalType::COMPLEX); + if (!new_sig) + throw RuntimeError("Failed to create new signal"); - auto new_sig = std::make_shared(new_sig_name, orig_sig->unit, SignalType::COMPLEX); - if (!new_sig) - throw RuntimeError("Failed to create new signal"); + signals->insert(signals->begin() + offset, new_sig); + } + } - signals->insert(signals->begin() + offset, new_sig); - } - } + state = State::PREPARED; + } - state = State::PREPARED; - } + virtual Hook::Reason process(struct Sample *smp) { + if (signal_index >= smp->length) + return Hook::Reason::ERROR; - virtual - Hook::Reason process(struct Sample *smp) - { - if (signal_index >= smp->length) - return Hook::Reason::ERROR; + if (inverse) { + double signal; + std::complex *coeffs = + reinterpret_cast *>(&smp->data[signal_index].z); - if (inverse) { - double signal; - std::complex *coeffs = reinterpret_cast *>(&smp->data[signal_index].z); + istep(coeffs, &signal); - istep(coeffs, &signal); + sample_data_remove(smp, signal_index, fharmonics_len); + sample_data_insert(smp, (union SignalData *)&signal, offset, 1); + } else { + double signal = smp->data[signal_index].f; + std::complex coeffs[fharmonics_len]; - sample_data_remove(smp, signal_index, fharmonics_len); - sample_data_insert(smp, (union SignalData *) &signal, offset, 1); - } - else { - double signal = smp->data[signal_index].f; - std::complex coeffs[fharmonics_len]; + step(&signal, coeffs); - step(&signal, coeffs); + sample_data_remove(smp, signal_index, 1); + sample_data_insert(smp, (union SignalData *)coeffs, offset, + fharmonics_len); + } - sample_data_remove(smp, signal_index, 1); - sample_data_insert(smp, (union SignalData *) coeffs, offset, fharmonics_len); - } + time += timestep; + steps++; - time += timestep; - steps++; - - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "dp"; static char d[] = "Transform to/from dynamic phasor domain"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/drop.cpp b/lib/hooks/drop.cpp index 516e9e3f6..e4a20ad7e 100644 --- a/lib/hooks/drop.cpp +++ b/lib/hooks/drop.cpp @@ -16,73 +16,68 @@ namespace node { class DropHook : public Hook { protected: - struct Sample *prev; + struct Sample *prev; public: - using Hook::Hook; + using Hook::Hook; - virtual - void start() - { - assert(state == State::PREPARED || state == State::STOPPED); + virtual void start() { + assert(state == State::PREPARED || state == State::STOPPED); - prev = nullptr; + prev = nullptr; - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() - { - assert(state == State::STARTED); + virtual void stop() { + assert(state == State::STARTED); - if (prev) - sample_decref(prev); + if (prev) + sample_decref(prev); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - int dist; + virtual Hook::Reason process(struct Sample *smp) { + int dist; - assert(state == State::STARTED); + assert(state == State::STARTED); - if (prev) { - dist = smp->sequence - (int64_t) prev->sequence; - if (dist <= 0) { - logger->debug("Dropping reordered sample: sequence={}, distance={}", smp->sequence, dist); + if (prev) { + dist = smp->sequence - (int64_t)prev->sequence; + if (dist <= 0) { + logger->debug("Dropping reordered sample: sequence={}, distance={}", + smp->sequence, dist); - return Hook::Reason::SKIP_SAMPLE; - } - } + return Hook::Reason::SKIP_SAMPLE; + } + } - sample_incref(smp); - if (prev) - sample_decref(prev); + sample_incref(smp); + if (prev) + sample_decref(prev); - prev = smp; + prev = smp; - return Reason::OK; - } + return Reason::OK; + } - virtual - void restart() - { - assert(state == State::STARTED); + virtual void restart() { + assert(state == State::STARTED); - if (prev) { - sample_decref(prev); - prev = nullptr; - } - } + if (prev) { + sample_decref(prev); + prev = nullptr; + } + } }; // Register hook static char n[] = "drop"; static char d[] = "Drop messages with reordered sequence numbers"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/dump.cpp b/lib/hooks/dump.cpp index 5dceb1fd1..952291dbf 100644 --- a/lib/hooks/dump.cpp +++ b/lib/hooks/dump.cpp @@ -14,23 +14,25 @@ namespace node { class DumpHook : public Hook { public: - using Hook::Hook; + using Hook::Hook; - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - sample_dump(logger, smp); + sample_dump(logger, smp); - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "dump"; static char d[] = "Dump data to stdout"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/ebm.cpp b/lib/hooks/ebm.cpp index 231236efc..2b48c2146 100644 --- a/lib/hooks/ebm.cpp +++ b/lib/hooks/ebm.cpp @@ -17,101 +17,92 @@ namespace node { class EBMHook : public Hook { protected: - std::vector> phases; + std::vector> phases; - double energy; + double energy; - struct Sample *last; + struct Sample *last; public: - using Hook::Hook; + using Hook::Hook; - virtual - void parse(json_t *json) - { - int ret; + virtual void parse(json_t *json) { + int ret; - size_t i; - json_error_t err; - json_t *json_phases, *json_phase; + size_t i; + json_error_t err; + json_t *json_phases, *json_phase; - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: o }", - "phases", &json_phases - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-ebm"); + ret = json_unpack_ex(json, &err, 0, "{ s: o }", "phases", &json_phases); + if (ret) + throw ConfigError(json, err, "node-config-hook-ebm"); - if (!json_is_array(json_phases)) - throw ConfigError(json_phases, "node-config-hook-ebm-phases"); + if (!json_is_array(json_phases)) + throw ConfigError(json_phases, "node-config-hook-ebm-phases"); - json_array_foreach(json_phases, i, json_phase) { - int voltage, current; + json_array_foreach(json_phases, i, json_phase) { + int voltage, current; - ret = json_unpack_ex(json_phase, &err, 0, "[ i, i ]", - &voltage, ¤t - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-ebm-phases"); + ret = json_unpack_ex(json_phase, &err, 0, "[ i, i ]", &voltage, ¤t); + if (ret) + throw ConfigError(json, err, "node-config-hook-ebm-phases"); - phases.emplace_back(voltage, current); - } + phases.emplace_back(voltage, current); + } - state = State::PARSED; - } + state = State::PARSED; + } - virtual - void start() - { - assert(state == State::PREPARED); + virtual void start() { + assert(state == State::PREPARED); - energy = 0; - last = nullptr; + energy = 0; + last = nullptr; - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void periodic() - { - assert(state == State::STARTED); + virtual void periodic() { + assert(state == State::STARTED); - logger->info("Energy: {}", energy); - } + logger->info("Energy: {}", energy); + } - virtual - Hook::Reason process(struct Sample *smp) - { - double P, P_last, dt; + virtual Hook::Reason process(struct Sample *smp) { + double P, P_last, dt; - assert(state == State::STARTED); + assert(state == State::STARTED); - if (last) { - for (auto phase : phases) { - // Trapazoidal rule - dt = time_delta(&last->ts.origin, &smp->ts.origin); + if (last) { + for (auto phase : phases) { + // Trapazoidal rule + dt = time_delta(&last->ts.origin, &smp->ts.origin); - P = smp->data[phase.first].f * smp->data[phase.second].f; - P_last = last->data[phase.first].f * last->data[phase.second].f; + P = smp->data[phase.first].f * smp->data[phase.second].f; + P_last = last->data[phase.first].f * last->data[phase.second].f; - energy += dt * (P_last + P) / 2.0; - } + energy += dt * (P_last + P) / 2.0; + } - sample_decref(last); - } + sample_decref(last); + } - sample_incref(smp); - last = smp; + sample_incref(smp); + last = smp; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "ebm"; static char d[] = "Energy-based Metric"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/fix.cpp b/lib/hooks/fix.cpp index ea653a773..02e74afb5 100644 --- a/lib/hooks/fix.cpp +++ b/lib/hooks/fix.cpp @@ -18,38 +18,38 @@ namespace node { class FixHook : public Hook { public: - using Hook::Hook; + using Hook::Hook; - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - timespec now = time_now(); + timespec now = time_now(); - if (!(smp->flags & (int) SampleFlags::HAS_SEQUENCE) && node) { - smp->sequence = node->sequence++; - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - } + if (!(smp->flags & (int)SampleFlags::HAS_SEQUENCE) && node) { + smp->sequence = node->sequence++; + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + } - if (!(smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)) { - smp->ts.received = now; - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + if (!(smp->flags & (int)SampleFlags::HAS_TS_RECEIVED)) { + smp->ts.received = now; + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - if (!(smp->flags & (int) SampleFlags::HAS_TS_ORIGIN)) { - smp->ts.origin = smp->ts.received; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + if (!(smp->flags & (int)SampleFlags::HAS_TS_ORIGIN)) { + smp->ts.origin = smp->ts.received; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "fix"; static char d[] = "Fix received data by adding missing fields"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/gate.cpp b/lib/hooks/gate.cpp index 347d2dc30..7347ab331 100644 --- a/lib/hooks/gate.cpp +++ b/lib/hooks/gate.cpp @@ -6,8 +6,8 @@ */ #include -#include #include +#include #include #include @@ -20,143 +20,131 @@ namespace node { class GateHook : public SingleSignalHook { protected: - enum class Mode { - ABOVE, - BELOW, - RISING_EDGE, - FALLING_EDGE - } mode; + enum class Mode { ABOVE, BELOW, RISING_EDGE, FALLING_EDGE } mode; - double threshold; - double duration; - int samples; - double previousValue; + double threshold; + double duration; + int samples; + double previousValue; - bool active; - uint64_t startSequence; - timespec startTime; + bool active; + uint64_t startSequence; + timespec startTime; public: - GateHook(Path *p, Node *n, int fl, int prio, bool en = true) : - SingleSignalHook(p, n, fl, prio, en), - mode(Mode::RISING_EDGE), - threshold(0.5), - duration(-1), - samples(-1), - previousValue(std::numeric_limits::quiet_NaN()), - active(false), - startSequence(0) - { } + GateHook(Path *p, Node *n, int fl, int prio, bool en = true) + : SingleSignalHook(p, n, fl, prio, en), mode(Mode::RISING_EDGE), + threshold(0.5), duration(-1), samples(-1), + previousValue(std::numeric_limits::quiet_NaN()), active(false), + startSequence(0) {} - virtual - void parse(json_t *json) - { - int ret; + virtual void parse(json_t *json) { + int ret; - json_error_t err; + json_error_t err; - const char *mode_str; + const char *mode_str; - assert(state != State::STARTED); + assert(state != State::STARTED); - SingleSignalHook::parse(json); + SingleSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F, s?: i, s?: s }", - "threshold", &threshold, - "duration", &duration, - "samples", &samples, - "mode", &mode_str - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-gate"); + ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F, s?: i, s?: s }", + "threshold", &threshold, "duration", &duration, + "samples", &samples, "mode", &mode_str); + if (ret) + throw ConfigError(json, err, "node-config-hook-gate"); - if (mode_str) { - if (!strcmp(mode_str, "above")) - mode = Mode::ABOVE; - else if (!strcmp(mode_str, "below")) - mode = Mode::BELOW; - else if (!strcmp(mode_str, "rising_edge")) - mode = Mode::RISING_EDGE; - else if (!strcmp(mode_str, "falling_edge")) - mode = Mode::FALLING_EDGE; - } + if (mode_str) { + if (!strcmp(mode_str, "above")) + mode = Mode::ABOVE; + else if (!strcmp(mode_str, "below")) + mode = Mode::BELOW; + else if (!strcmp(mode_str, "rising_edge")) + mode = Mode::RISING_EDGE; + else if (!strcmp(mode_str, "falling_edge")) + mode = Mode::FALLING_EDGE; + } - state = State::PARSED; - } + state = State::PARSED; + } - virtual - void prepare() - { - assert(state == State::CHECKED); + virtual void prepare() { + assert(state == State::CHECKED); - SingleSignalHook::prepare(); + SingleSignalHook::prepare(); - // Check if signal type is float - auto sig = signals->getByIndex(signalIndex); - if (sig->type != SignalType::FLOAT) - throw RuntimeError("Gate signal must be of type float"); + // Check if signal type is float + auto sig = signals->getByIndex(signalIndex); + if (sig->type != SignalType::FLOAT) + throw RuntimeError("Gate signal must be of type float"); - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - Hook::Reason reason; - double value = smp->data[signalIndex].f; + Hook::Reason reason; + double value = smp->data[signalIndex].f; - if (active) { - if (duration > 0 && time_delta(&smp->ts.origin, &startTime) < duration) - reason = Reason::OK; - else if (samples > 0 && smp->sequence - startSequence < (uint64_t) samples) - reason = Reason::OK; - else { - reason = Reason::SKIP_SAMPLE; - active = false; - } - } + if (active) { + if (duration > 0 && time_delta(&smp->ts.origin, &startTime) < duration) + reason = Reason::OK; + else if (samples > 0 && smp->sequence - startSequence < (uint64_t)samples) + reason = Reason::OK; + else { + reason = Reason::SKIP_SAMPLE; + active = false; + } + } - if (!active) { - switch (mode) { - case Mode::ABOVE: - reason = value > threshold ? Reason::OK : Reason::SKIP_SAMPLE; - break; + if (!active) { + switch (mode) { + case Mode::ABOVE: + reason = value > threshold ? Reason::OK : Reason::SKIP_SAMPLE; + break; - case Mode::BELOW: - reason = value < threshold ? Reason::OK : Reason::SKIP_SAMPLE; - break; + case Mode::BELOW: + reason = value < threshold ? Reason::OK : Reason::SKIP_SAMPLE; + break; - case Mode::RISING_EDGE: - reason = (!std::isnan(previousValue) && value > previousValue) ? Reason::OK : Reason::SKIP_SAMPLE; - break; + case Mode::RISING_EDGE: + reason = (!std::isnan(previousValue) && value > previousValue) + ? Reason::OK + : Reason::SKIP_SAMPLE; + break; - case Mode::FALLING_EDGE: - reason = (!std::isnan(previousValue) && value < previousValue) ? Reason::OK : Reason::SKIP_SAMPLE; - break; + case Mode::FALLING_EDGE: + reason = (!std::isnan(previousValue) && value < previousValue) + ? Reason::OK + : Reason::SKIP_SAMPLE; + break; - default: - reason = Reason::ERROR; - } + default: + reason = Reason::ERROR; + } - if (reason == Reason::OK) { - startTime = smp->ts.origin; - startSequence = smp->sequence; - active = true; - } - } + if (reason == Reason::OK) { + startTime = smp->ts.origin; + startSequence = smp->sequence; + active = true; + } + } - previousValue = value; + previousValue = value; - return reason; - } + return reason; + } }; // Register hook static char n[] = "gate"; -static char d[] = "Skip samples only if an enable signal is under a specified threshold"; -static HookPlugin p; +static char d[] = + "Skip samples only if an enable signal is under a specified threshold"; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/jitter_calc.cpp b/lib/hooks/jitter_calc.cpp index 63c6ec1ee..628a6be40 100644 --- a/lib/hooks/jitter_calc.cpp +++ b/lib/hooks/jitter_calc.cpp @@ -5,13 +5,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include #include -#include #include +#include #include #define GPS_NTP_DELAY_WIN_SIZE 16 @@ -22,80 +22,82 @@ namespace node { class JitterCalcHook : public Hook { protected: - std::vector jitter_val; - std::vector delay_series; - std::vector moving_avg; - std::vector moving_var; + std::vector jitter_val; + std::vector delay_series; + std::vector moving_avg; + std::vector moving_var; - int64_t delay_mov_sum; - int64_t delay_mov_sum_sqrd; - int curr_count; + int64_t delay_mov_sum; + int64_t delay_mov_sum_sqrd; + int curr_count; public: + JitterCalcHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), jitter_val(GPS_NTP_DELAY_WIN_SIZE), + delay_series(GPS_NTP_DELAY_WIN_SIZE), + moving_avg(GPS_NTP_DELAY_WIN_SIZE), moving_var(GPS_NTP_DELAY_WIN_SIZE), + delay_mov_sum(0), delay_mov_sum_sqrd(0), curr_count(0) {} - JitterCalcHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - jitter_val(GPS_NTP_DELAY_WIN_SIZE), - delay_series(GPS_NTP_DELAY_WIN_SIZE), - moving_avg(GPS_NTP_DELAY_WIN_SIZE), - moving_var(GPS_NTP_DELAY_WIN_SIZE), - delay_mov_sum(0), - delay_mov_sum_sqrd(0), - curr_count(0) - { } - - /* Hook to calculate jitter between GTNET-SKT GPS timestamp and Villas node NTP timestamp. + /* Hook to calculate jitter between GTNET-SKT GPS timestamp and Villas node NTP timestamp. * * Drawbacks: No protection for out of order packets. Default positive delay assumed, * so GPS timestamp should be earlier than NTP timestamp. If difference b/w NTP and GPS ts * is high (i.e. several mins depending on GPS_NTP_DELAY_WIN_SIZE), * the variance value will overrun the 64bit value. */ - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - timespec now = time_now(); - int64_t delay_sec, delay_nsec, curr_delay_us; + timespec now = time_now(); + int64_t delay_sec, delay_nsec, curr_delay_us; - delay_sec = now.tv_sec - smp->ts.origin.tv_sec; - delay_nsec = now.tv_nsec - smp->ts.origin.tv_nsec; + delay_sec = now.tv_sec - smp->ts.origin.tv_sec; + delay_nsec = now.tv_nsec - smp->ts.origin.tv_nsec; - /* Calc on microsec instead of nenosec delay as variance formula overflows otherwise.*/ - curr_delay_us = delay_sec * 1000000 + delay_nsec / 1000; + /* Calc on microsec instead of nenosec delay as variance formula overflows otherwise.*/ + curr_delay_us = delay_sec * 1000000 + delay_nsec / 1000; - delay_mov_sum = delay_mov_sum + curr_delay_us - delay_series[curr_count]; - moving_avg[curr_count] = delay_mov_sum / GPS_NTP_DELAY_WIN_SIZE; // Will be valid after GPS_NTP_DELAY_WIN_SIZE initial values + delay_mov_sum = delay_mov_sum + curr_delay_us - delay_series[curr_count]; + moving_avg[curr_count] = + delay_mov_sum / + GPS_NTP_DELAY_WIN_SIZE; // Will be valid after GPS_NTP_DELAY_WIN_SIZE initial values - delay_mov_sum_sqrd = delay_mov_sum_sqrd + (curr_delay_us * curr_delay_us) - (delay_series[curr_count] * delay_series[curr_count]); - moving_var[curr_count] = (delay_mov_sum_sqrd - (delay_mov_sum * delay_mov_sum) / GPS_NTP_DELAY_WIN_SIZE) / (GPS_NTP_DELAY_WIN_SIZE - 1); + delay_mov_sum_sqrd = delay_mov_sum_sqrd + (curr_delay_us * curr_delay_us) - + (delay_series[curr_count] * delay_series[curr_count]); + moving_var[curr_count] = + (delay_mov_sum_sqrd - + (delay_mov_sum * delay_mov_sum) / GPS_NTP_DELAY_WIN_SIZE) / + (GPS_NTP_DELAY_WIN_SIZE - 1); - delay_series[curr_count] = curr_delay_us; // Update the last delay value + delay_series[curr_count] = curr_delay_us; // Update the last delay value - /* Jitter calc formula as used in Wireshark according to RFC3550 (RTP) + /* Jitter calc formula as used in Wireshark according to RFC3550 (RTP) D(i,j) = (Rj-Ri)-(Sj-Si) = (Rj-Sj)-(Ri-Si) J(i) = J(i-1)+(|D(i-1,i)|-J(i-1))/16 */ - jitter_val[(curr_count + 1) % GPS_NTP_DELAY_WIN_SIZE] = jitter_val[curr_count] + (labs(curr_delay_us) - jitter_val[curr_count]) / 16; + jitter_val[(curr_count + 1) % GPS_NTP_DELAY_WIN_SIZE] = + jitter_val[curr_count] + + (labs(curr_delay_us) - jitter_val[curr_count]) / 16; - logger->info("{}: jitter={} usec, moving average={} usec, moving variance={} usec", __FUNCTION__, - jitter_val[(curr_count + 1) % GPS_NTP_DELAY_WIN_SIZE], - moving_avg[curr_count], - moving_var[curr_count]); + logger->info( + "{}: jitter={} usec, moving average={} usec, moving variance={} usec", + __FUNCTION__, jitter_val[(curr_count + 1) % GPS_NTP_DELAY_WIN_SIZE], + moving_avg[curr_count], moving_var[curr_count]); - curr_count++; - if (curr_count >= GPS_NTP_DELAY_WIN_SIZE) - curr_count = 0; + curr_count++; + if (curr_count >= GPS_NTP_DELAY_WIN_SIZE) + curr_count = 0; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "jitter_calc"; static char d[] = "Calc jitter, mean and variance of GPS vs NTP TS"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/limit_rate.cpp b/lib/hooks/limit_rate.cpp index 4dd0a8527..80cf00b22 100644 --- a/lib/hooks/limit_rate.cpp +++ b/lib/hooks/limit_rate.cpp @@ -7,79 +7,79 @@ #include -#include -#include #include +#include +#include namespace villas { namespace node { -void LimitRateHook::parse(json_t *json) -{ - int ret; - json_error_t err; +void LimitRateHook::parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - double rate; - const char *m = nullptr; + double rate; + const char *m = nullptr; - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: F, s?: s }", - "rate", &rate, - "mode", &m - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-limit_rate"); + ret = json_unpack_ex(json, &err, 0, "{ s: F, s?: s }", "rate", &rate, "mode", + &m); + if (ret) + throw ConfigError(json, err, "node-config-hook-limit_rate"); - if (m) { - if (!strcmp(m, "origin")) - mode = LIMIT_RATE_ORIGIN; - else if (!strcmp(m, "received")) - mode = LIMIT_RATE_RECEIVED; - else if (!strcmp(m, "local")) - mode = LIMIT_RATE_LOCAL; - else - throw ConfigError(json, "node-config-hook-limit_rate-mode", "Invalid value '{}' for setting 'mode'", mode); - } + if (m) { + if (!strcmp(m, "origin")) + mode = LIMIT_RATE_ORIGIN; + else if (!strcmp(m, "received")) + mode = LIMIT_RATE_RECEIVED; + else if (!strcmp(m, "local")) + mode = LIMIT_RATE_LOCAL; + else + throw ConfigError(json, "node-config-hook-limit_rate-mode", + "Invalid value '{}' for setting 'mode'", mode); + } - deadtime = 1.0 / rate; + deadtime = 1.0 / rate; - state = State::PARSED; + state = State::PARSED; } -Hook::Reason LimitRateHook::process(struct Sample *smp) -{ - assert(state == State::STARTED); +Hook::Reason LimitRateHook::process(struct Sample *smp) { + assert(state == State::STARTED); - timespec next; - switch (mode) { - case LIMIT_RATE_LOCAL: - next = time_now(); - break; + timespec next; + switch (mode) { + case LIMIT_RATE_LOCAL: + next = time_now(); + break; - case LIMIT_RATE_ORIGIN: - next = smp->ts.origin; - break; + case LIMIT_RATE_ORIGIN: + next = smp->ts.origin; + break; - case LIMIT_RATE_RECEIVED: - next = smp->ts.received; - break; - } + case LIMIT_RATE_RECEIVED: + next = smp->ts.received; + break; + } - if (time_delta(&last, &next) < deadtime) - return Hook::Reason::SKIP_SAMPLE; + if (time_delta(&last, &next) < deadtime) + return Hook::Reason::SKIP_SAMPLE; - last = next; + last = next; - return Reason::OK; + return Reason::OK; } // Register hook static char n[] = "limit_rate"; static char d[] = "Limit sending rate"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/limit_value.cpp b/lib/hooks/limit_value.cpp index 9a4b0311d..0220115ef 100644 --- a/lib/hooks/limit_value.cpp +++ b/lib/hooks/limit_value.cpp @@ -11,8 +11,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -20,76 +20,69 @@ namespace node { class LimitValueHook : public MultiSignalHook { protected: - unsigned offset; + unsigned offset; - float min, max; + float min, max; public: - LimitValueHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - offset(0), - min(0), - max(0) - { } + LimitValueHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), offset(0), min(0), max(0) {} - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: f, s: f }", - "min", &min, - "max", &max - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-average"); + ret = json_unpack_ex(json, &err, 0, "{ s: f, s: f }", "min", &min, "max", + &max); + if (ret) + throw ConfigError(json, err, "node-config-hook-average"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - for (auto index : signalIndices) { - switch (sample_format(smp, index)) { - case SignalType::INTEGER: - if (smp->data[index].i > max) - smp->data[index].i = max; + for (auto index : signalIndices) { + switch (sample_format(smp, index)) { + case SignalType::INTEGER: + if (smp->data[index].i > max) + smp->data[index].i = max; - if (smp->data[index].i < min) - smp->data[index].i = min; - break; + if (smp->data[index].i < min) + smp->data[index].i = min; + break; - case SignalType::FLOAT: - if (smp->data[index].f > max) - smp->data[index].f = max; + case SignalType::FLOAT: + if (smp->data[index].f > max) + smp->data[index].f = max; - if (smp->data[index].f < min) - smp->data[index].f = min; - break; + if (smp->data[index].f < min) + smp->data[index].f = min; + break; - case SignalType::INVALID: - case SignalType::COMPLEX: - case SignalType::BOOLEAN: - return Hook::Reason::ERROR; // not supported - } - } + case SignalType::INVALID: + case SignalType::COMPLEX: + case SignalType::BOOLEAN: + return Hook::Reason::ERROR; // not supported + } + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "limit_value"; static char d[] = "Limit signal values"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/lua.cpp b/lib/hooks/lua.cpp index 4219eb061..6bf5875ae 100644 --- a/lib/hooks/lua.cpp +++ b/lib/hooks/lua.cpp @@ -5,14 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include extern "C" { - #include - #include - #include +#include +#include +#include }; #include @@ -30,749 +30,689 @@ using namespace villas::node; class LuaError : public RuntimeError { protected: - lua_State *L; - int err; + lua_State *L; + int err; public: - LuaError(lua_State *l, int e) : - RuntimeError(""), - L(l), - err(e) - { } + LuaError(lua_State *l, int e) : RuntimeError(""), L(l), err(e) {} - virtual - const char * what() const noexcept - { - const char *msg; - switch (err) { - case LUA_ERRSYNTAX: - msg = "Syntax error"; - break; + virtual const char *what() const noexcept { + const char *msg; + switch (err) { + case LUA_ERRSYNTAX: + msg = "Syntax error"; + break; - case LUA_ERRMEM: - msg = "Memory allocation error"; - break; + case LUA_ERRMEM: + msg = "Memory allocation error"; + break; - case LUA_ERRFILE: - msg = "Failed to open Lua script"; - break; + case LUA_ERRFILE: + msg = "Failed to open Lua script"; + break; - case LUA_ERRRUN: - msg = "Runtime error"; - break; + case LUA_ERRRUN: + msg = "Runtime error"; + break; - case LUA_ERRERR: - msg = "Failed to call error handler"; - break; + case LUA_ERRERR: + msg = "Failed to call error handler"; + break; - default: - msg = "Unknown error"; - break; - } + default: + msg = "Unknown error"; + break; + } - char *buf; + char *buf; - if (asprintf(&buf, "Lua: %s: %s", msg, lua_tostring(L, -1)) < 0) - return "Lua: could not format error message"; + if (asprintf(&buf, "Lua: %s: %s", msg, lua_tostring(L, -1)) < 0) + return "Lua: could not format error message"; - return buf; - } + return buf; + } }; -static -void lua_pushtimespec(lua_State *L, struct timespec *ts) -{ - lua_createtable(L, 2, 0); +static void lua_pushtimespec(lua_State *L, struct timespec *ts) { + lua_createtable(L, 2, 0); - lua_pushnumber(L, ts->tv_sec); - lua_rawseti(L, -2, 0); + lua_pushnumber(L, ts->tv_sec); + lua_rawseti(L, -2, 0); - lua_pushnumber(L, ts->tv_nsec); - lua_rawseti(L, -2, 1); + lua_pushnumber(L, ts->tv_nsec); + lua_rawseti(L, -2, 1); } -static -void lua_totimespec(lua_State *L, struct timespec *ts) -{ - lua_rawgeti(L, -1, 0); - ts->tv_sec = lua_tonumber(L, -1); +static void lua_totimespec(lua_State *L, struct timespec *ts) { + lua_rawgeti(L, -1, 0); + ts->tv_sec = lua_tonumber(L, -1); - lua_rawgeti(L, -2, 1); - ts->tv_nsec = lua_tonumber(L, -1); + lua_rawgeti(L, -2, 1); + ts->tv_nsec = lua_tonumber(L, -1); - lua_pop(L, 2); + lua_pop(L, 2); } -static -bool lua_pushsignaldata(lua_State *L, const union SignalData *data, const Signal::Ptr sig) -{ - switch (sig->type) { - case SignalType::FLOAT: - lua_pushnumber(L, data->f); - break; +static bool lua_pushsignaldata(lua_State *L, const union SignalData *data, + const Signal::Ptr sig) { + switch (sig->type) { + case SignalType::FLOAT: + lua_pushnumber(L, data->f); + break; - case SignalType::INTEGER: - lua_pushinteger(L, data->i); - break; + case SignalType::INTEGER: + lua_pushinteger(L, data->i); + break; - case SignalType::BOOLEAN: - lua_pushboolean(L, data->b); - break; + case SignalType::BOOLEAN: + lua_pushboolean(L, data->b); + break; - case SignalType::COMPLEX: - case SignalType::INVALID: - default: - return false; // we skip unknown types. Lua will see a nil value in the table - } + case SignalType::COMPLEX: + case SignalType::INVALID: + default: + return false; // we skip unknown types. Lua will see a nil value in the table + } - return true; + return true; } -static -void lua_tosignaldata(lua_State *L, union SignalData *data, enum SignalType targetType, int idx = -1) -{ - int luaType; - enum SignalType type; +static void lua_tosignaldata(lua_State *L, union SignalData *data, + enum SignalType targetType, int idx = -1) { + int luaType; + enum SignalType type; - luaType = lua_type(L, idx); - switch (luaType) { - case LUA_TBOOLEAN: - data->b = lua_toboolean(L, idx); - type = SignalType::BOOLEAN; - break; + luaType = lua_type(L, idx); + switch (luaType) { + case LUA_TBOOLEAN: + data->b = lua_toboolean(L, idx); + type = SignalType::BOOLEAN; + break; - case LUA_TNUMBER: - data->f = lua_tonumber(L, idx); - type = SignalType::FLOAT; - break; + case LUA_TNUMBER: + data->f = lua_tonumber(L, idx); + type = SignalType::FLOAT; + break; - default: - return; - } + default: + return; + } - *data = data->cast(type, targetType); + *data = data->cast(type, targetType); } -static -void lua_tosample(lua_State *L, struct Sample *smp, SignalList::Ptr signals, bool use_names = true, int idx = -1) -{ - int ret; +static void lua_tosample(lua_State *L, struct Sample *smp, + SignalList::Ptr signals, bool use_names = true, + int idx = -1) { + int ret; - smp->length = 0; - smp->flags = 0; + smp->length = 0; + smp->flags = 0; - lua_getfield(L, idx, "sequence"); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) { - smp->sequence = lua_tonumber(L, -1); - smp->flags |= (int) SampleFlags::HAS_SEQUENCE; - } - lua_pop(L, 1); + lua_getfield(L, idx, "sequence"); + ret = lua_type(L, -1); + if (ret != LUA_TNIL) { + smp->sequence = lua_tonumber(L, -1); + smp->flags |= (int)SampleFlags::HAS_SEQUENCE; + } + lua_pop(L, 1); - lua_getfield(L, idx, "ts_origin"); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) { - lua_totimespec(L, &smp->ts.origin); - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } - lua_pop(L, 1); + lua_getfield(L, idx, "ts_origin"); + ret = lua_type(L, -1); + if (ret != LUA_TNIL) { + lua_totimespec(L, &smp->ts.origin); + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } + lua_pop(L, 1); - lua_getfield(L, idx, "ts_received"); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) { - lua_totimespec(L, &smp->ts.received); - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } - lua_pop(L, 1); + lua_getfield(L, idx, "ts_received"); + ret = lua_type(L, -1); + if (ret != LUA_TNIL) { + lua_totimespec(L, &smp->ts.received); + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } + lua_pop(L, 1); - lua_getfield(L, idx, "data"); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) { - int i = 0; - for (auto sig : *signals) { - if (use_names) - lua_getfield(L, -1, sig->name.c_str()); - else - lua_rawgeti(L, -1, i); + lua_getfield(L, idx, "data"); + ret = lua_type(L, -1); + if (ret != LUA_TNIL) { + int i = 0; + for (auto sig : *signals) { + if (use_names) + lua_getfield(L, -1, sig->name.c_str()); + else + lua_rawgeti(L, -1, i); - ret = lua_type(L, -1); - if (ret != LUA_TNIL) - lua_tosignaldata(L, &smp->data[i], sig->type, -1); - else - smp->data[i] = sig->init; + ret = lua_type(L, -1); + if (ret != LUA_TNIL) + lua_tosignaldata(L, &smp->data[i], sig->type, -1); + else + smp->data[i] = sig->init; - lua_pop(L, 1); - i++; - smp->length++; - } + lua_pop(L, 1); + i++; + smp->length++; + } - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; - } - lua_pop(L, 1); + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; + } + lua_pop(L, 1); } -static -void lua_pushsample(lua_State *L, struct Sample *smp, bool use_names = true) -{ - lua_createtable(L, 0, 5); +static void lua_pushsample(lua_State *L, struct Sample *smp, + bool use_names = true) { + lua_createtable(L, 0, 5); - lua_pushnumber(L, smp->flags); - lua_setfield(L, -2, "flags"); + lua_pushnumber(L, smp->flags); + lua_setfield(L, -2, "flags"); - if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) { - lua_pushnumber(L, smp->sequence); - lua_setfield(L, -2, "sequence"); - } + if (smp->flags & (int)SampleFlags::HAS_SEQUENCE) { + lua_pushnumber(L, smp->sequence); + lua_setfield(L, -2, "sequence"); + } - if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) { - lua_pushtimespec(L, &smp->ts.origin); - lua_setfield(L, -2, "ts_origin"); - } + if (smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + lua_pushtimespec(L, &smp->ts.origin); + lua_setfield(L, -2, "ts_origin"); + } - if (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED) { - lua_pushtimespec(L, &smp->ts.received); - lua_setfield(L, -2, "ts_received"); - } + if (smp->flags & (int)SampleFlags::HAS_TS_RECEIVED) { + lua_pushtimespec(L, &smp->ts.received); + lua_setfield(L, -2, "ts_received"); + } - if (smp->flags & (int) SampleFlags::HAS_DATA) { - lua_createtable(L, smp->length, 0); + if (smp->flags & (int)SampleFlags::HAS_DATA) { + lua_createtable(L, smp->length, 0); - for (unsigned i = 0; i < smp->length; i++) { - const auto sig = smp->signals->getByIndex(i); - const auto *data = &smp->data[i]; + for (unsigned i = 0; i < smp->length; i++) { + const auto sig = smp->signals->getByIndex(i); + const auto *data = &smp->data[i]; - auto pushed = lua_pushsignaldata(L, data, sig); - if (!pushed) - continue; + auto pushed = lua_pushsignaldata(L, data, sig); + if (!pushed) + continue; - if (use_names) - lua_setfield(L, -2, sig->name.c_str()); - else - lua_rawseti(L, -2, i); - } + if (use_names) + lua_setfield(L, -2, sig->name.c_str()); + else + lua_rawseti(L, -2, i); + } - lua_setfield(L, -2, "data"); - } + lua_setfield(L, -2, "data"); + } } -static -void lua_pushjson(lua_State *L, json_t *json) -{ - size_t i; - const char *key; - json_t *json_value; +static void lua_pushjson(lua_State *L, json_t *json) { + size_t i; + const char *key; + json_t *json_value; - switch (json_typeof(json)) { - case JSON_OBJECT: - lua_newtable(L); - json_object_foreach(json, key, json_value) { - lua_pushjson(L, json_value); - lua_setfield(L, -2, key); - } - break; + switch (json_typeof(json)) { + case JSON_OBJECT: + lua_newtable(L); + json_object_foreach(json, key, json_value) { + lua_pushjson(L, json_value); + lua_setfield(L, -2, key); + } + break; - case JSON_ARRAY: - lua_newtable(L); - json_array_foreach(json, i, json_value) { - lua_pushjson(L, json_value); - lua_rawseti(L, -2, i); - } - break; + case JSON_ARRAY: + lua_newtable(L); + json_array_foreach(json, i, json_value) { + lua_pushjson(L, json_value); + lua_rawseti(L, -2, i); + } + break; - case JSON_STRING: - lua_pushstring(L, json_string_value(json)); - break; + case JSON_STRING: + lua_pushstring(L, json_string_value(json)); + break; - case JSON_REAL: - case JSON_INTEGER: - lua_pushnumber(L, json_integer_value(json)); - break; + case JSON_REAL: + case JSON_INTEGER: + lua_pushnumber(L, json_integer_value(json)); + break; - case JSON_TRUE: - case JSON_FALSE: - lua_pushboolean(L, json_boolean_value(json)); - break; + case JSON_TRUE: + case JSON_FALSE: + lua_pushboolean(L, json_boolean_value(json)); + break; - case JSON_NULL: - lua_pushnil(L); - break; - } + case JSON_NULL: + lua_pushnil(L); + break; + } } -static -json_t * lua_tojson(lua_State *L, int index = -1) -{ - double n; - const char *s; - bool b; +static json_t *lua_tojson(lua_State *L, int index = -1) { + double n; + const char *s; + bool b; - switch (lua_type(L, index)) { - case LUA_TFUNCTION: - case LUA_TUSERDATA: - case LUA_TTHREAD: - case LUA_TLIGHTUSERDATA: - case LUA_TNIL: - return json_null(); + switch (lua_type(L, index)) { + case LUA_TFUNCTION: + case LUA_TUSERDATA: + case LUA_TTHREAD: + case LUA_TLIGHTUSERDATA: + case LUA_TNIL: + return json_null(); - case LUA_TNUMBER: - n = lua_tonumber(L, index); - return n == (int) n - ? json_integer(n) - : json_real(n); + case LUA_TNUMBER: + n = lua_tonumber(L, index); + return n == (int)n ? json_integer(n) : json_real(n); - case LUA_TBOOLEAN: - b = lua_toboolean(L, index); - return json_boolean(b); + case LUA_TBOOLEAN: + b = lua_toboolean(L, index); + return json_boolean(b); - case LUA_TSTRING: - s = lua_tostring(L, index); - return json_string(s); + case LUA_TSTRING: + s = lua_tostring(L, index); + return json_string(s); - case LUA_TTABLE: { - int keys_total = 0, keys_int = 0, key_highest = -1; + case LUA_TTABLE: { + int keys_total = 0, keys_int = 0, key_highest = -1; - lua_pushnil(L); - while (lua_next(L, index) != 0) { - keys_total++; - if (lua_type(L, -2) == LUA_TNUMBER) { - int key = lua_tonumber(L, -1); + lua_pushnil(L); + while (lua_next(L, index) != 0) { + keys_total++; + if (lua_type(L, -2) == LUA_TNUMBER) { + int key = lua_tonumber(L, -1); - if (key == (int) key) { - keys_int++; - if (key > key_highest) - key_highest = key; - } - } - lua_pop(L, 1); - } + if (key == (int)key) { + keys_int++; + if (key > key_highest) + key_highest = key; + } + } + lua_pop(L, 1); + } - bool is_array = keys_total == keys_int && key_highest / keys_int > 0.5; + bool is_array = keys_total == keys_int && key_highest / keys_int > 0.5; - json_t *json = is_array - ? json_array() - : json_object(); + json_t *json = is_array ? json_array() : json_object(); - lua_pushnil(L); - while (lua_next(L, index) != 0) { - json_t *val = lua_tojson(L, -1); - if (is_array) { - int key = lua_tonumber(L, -2); - json_array_set(json, key, val); - } - else { - const char *key = lua_tostring(L, -2); - if (key) // Skip table entries whose keys are neither string or number! - json_object_set(json, key, val); - } - lua_pop(L, 1); - } + lua_pushnil(L); + while (lua_next(L, index) != 0) { + json_t *val = lua_tojson(L, -1); + if (is_array) { + int key = lua_tonumber(L, -2); + json_array_set(json, key, val); + } else { + const char *key = lua_tostring(L, -2); + if (key) // Skip table entries whose keys are neither string or number! + json_object_set(json, key, val); + } + lua_pop(L, 1); + } - return json; - } - } + return json; + } + } - return nullptr; + return nullptr; } namespace villas { namespace node { -LuaSignalExpression::LuaSignalExpression(lua_State *l, json_t *json_sig) : - cookie(0), - L(l) -{ - int ret; +LuaSignalExpression::LuaSignalExpression(lua_State *l, json_t *json_sig) + : cookie(0), L(l) { + int ret; - json_error_t err; - const char *expr; + json_error_t err; + const char *expr; - // Parse expression - ret = json_unpack_ex(json_sig, &err, 0, "{ s: s }", - "expression", &expr - ); - if (ret) - throw ConfigError(json_sig, err, "node-config-hook-lua-signals"); + // Parse expression + ret = json_unpack_ex(json_sig, &err, 0, "{ s: s }", "expression", &expr); + if (ret) + throw ConfigError(json_sig, err, "node-config-hook-lua-signals"); - cfg = json_sig; + cfg = json_sig; - expression = expr; + expression = expr; } -void LuaSignalExpression::prepare() -{ - parseExpression(expression); +void LuaSignalExpression::prepare() { parseExpression(expression); } + +void LuaSignalExpression::parseExpression(const std::string &expr) { + // Release previous expression + if (cookie) + luaL_unref(L, LUA_REGISTRYINDEX, cookie); + + auto fexpr = fmt::format("return {}", expr); + + int err = luaL_loadstring(L, fexpr.c_str()); + if (err) + throw ConfigError(cfg, "node-config-hook-lua-signals", + "Failed to load Lua expression: {}", lua_tostring(L, -1)); + + cookie = luaL_ref(L, LUA_REGISTRYINDEX); } -void LuaSignalExpression::parseExpression(const std::string &expr) -{ - // Release previous expression - if (cookie) - luaL_unref(L, LUA_REGISTRYINDEX, cookie); +void LuaSignalExpression::evaluate(union SignalData *data, + enum SignalType type) { + int err; - auto fexpr = fmt::format("return {}", expr); + lua_rawgeti(L, LUA_REGISTRYINDEX, cookie); - int err = luaL_loadstring(L, fexpr.c_str()); - if (err) - throw ConfigError(cfg, "node-config-hook-lua-signals", "Failed to load Lua expression: {}", lua_tostring(L, -1)); + err = lua_pcall(L, 0, 1, 0); + if (err) { + throw RuntimeError("Lua: Evaluation failed: {}", lua_tostring(L, -1)); + lua_pop(L, 1); + } - cookie = luaL_ref(L, LUA_REGISTRYINDEX); + lua_tosignaldata(L, data, type, -1); + + lua_pop(L, 1); } -void LuaSignalExpression::evaluate(union SignalData *data, enum SignalType type) -{ - int err; +LuaHook::LuaHook(Path *p, Node *n, int fl, int prio, bool en) + : Hook(p, n, fl, prio, en), + signalsExpressions(std::make_shared()), L(luaL_newstate()), + useNames(true), hasExpressions(false), needsLocking(false), + functions({0}) {} - lua_rawgeti(L, LUA_REGISTRYINDEX, cookie); +LuaHook::~LuaHook() { lua_close(L); } - err = lua_pcall(L, 0, 1, 0); - if (err) { - throw RuntimeError("Lua: Evaluation failed: {}", lua_tostring(L, -1)); - lua_pop(L, 1); - } +void LuaHook::parseExpressions(json_t *json_sigs) { + int ret; + size_t i; + json_t *json_sig; - lua_tosignaldata(L, data, type, -1); + signalsExpressions->clear(); + ret = signalsExpressions->parse(json_sigs); + if (ret) + throw ConfigError(json_sigs, "node-config-hook-lua-signals", + "Setting 'signals' must be a list of dicts"); - lua_pop(L, 1); + // cppcheck-suppress unknownMacro + json_array_foreach(json_sigs, i, json_sig) + expressions.emplace_back(L, json_sig); + + hasExpressions = true; } -LuaHook::LuaHook(Path *p, Node *n, int fl, int prio, bool en) : - Hook(p, n, fl, prio, en), - signalsExpressions(std::make_shared()), - L(luaL_newstate()), - useNames(true), - hasExpressions(false), - needsLocking(false), - functions({0}) -{ } +void LuaHook::parse(json_t *json) { + int ret; + const char *script_str = nullptr; + int names = 1; + json_error_t err; + json_t *json_signals = nullptr; -LuaHook::~LuaHook() -{ - lua_close(L); + assert(state != State::STARTED); + + Hook::parse(json); + + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s?: b }", "script", + &script_str, "signals", &json_signals, "use_names", + &names); + if (ret) + throw ConfigError(json, err, "node-config-hook-lua"); + + useNames = names; + + if (script_str) + script = script_str; + + if (json_signals) + parseExpressions(json_signals); + + state = State::PARSED; } -void LuaHook::parseExpressions(json_t *json_sigs) -{ - int ret; - size_t i; - json_t *json_sig; +void LuaHook::lookupFunctions() { + int ret; - signalsExpressions->clear(); - ret = signalsExpressions->parse(json_sigs); - if (ret) - throw ConfigError(json_sigs, "node-config-hook-lua-signals", "Setting 'signals' must be a list of dicts"); + std::map funcs = { + {"start", &functions.start}, {"stop", &functions.stop}, + {"restart", &functions.restart}, {"prepare", &functions.prepare}, + {"periodic", &functions.periodic}, {"process", &functions.process}}; - // cppcheck-suppress unknownMacro - json_array_foreach(json_sigs, i, json_sig) - expressions.emplace_back(L, json_sig); + for (auto it : funcs) { + lua_getglobal(L, it.first); - hasExpressions = true; + ret = lua_type(L, -1); + if (ret == LUA_TFUNCTION) { + logger->debug("Found Lua function: {}()", it.first); + *(it.second) = lua_gettop(L); + } else { + *(it.second) = 0; + lua_pop(L, 1); + } + } } -void LuaHook::parse(json_t *json) -{ - int ret; - const char *script_str = nullptr; - int names = 1; - json_error_t err; - json_t *json_signals = nullptr; +void LuaHook::loadScript() { + int ret; - assert(state != State::STARTED); + if (script.empty()) + return; // No script given - Hook::parse(json); + ret = luaL_loadfile(L, script.c_str()); + if (ret) + throw LuaError(L, ret); - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s?: b }", - "script", &script_str, - "signals", &json_signals, - "use_names", &names - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-lua"); - - useNames = names; - - if (script_str) - script = script_str; - - if (json_signals) - parseExpressions(json_signals); - - state = State::PARSED; + ret = lua_pcall(L, 0, LUA_MULTRET, 0); + if (ret) + throw LuaError(L, ret); } -void LuaHook::lookupFunctions() -{ - int ret; - - std::map funcs = { - { "start", &functions.start }, - { "stop", &functions.stop }, - { "restart", &functions.restart }, - { "prepare", &functions.prepare }, - { "periodic", &functions.periodic }, - { "process", &functions.process } - }; - - for (auto it : funcs) { - lua_getglobal(L, it.first); - - ret = lua_type(L, -1); - if (ret == LUA_TFUNCTION) { - logger->debug("Found Lua function: {}()", it.first); - *(it.second) = lua_gettop(L); - } - else { - *(it.second) = 0; - lua_pop(L, 1); - } - } +int LuaHook::luaRegisterApiHandler(lua_State *L) { + // register_api_handler(path_regex) + return 0; } -void LuaHook::loadScript() -{ - int ret; - - if (script.empty()) - return; // No script given - - ret = luaL_loadfile(L, script.c_str()); - if (ret) - throw LuaError(L, ret); - - ret = lua_pcall(L, 0, LUA_MULTRET, 0); - if (ret) - throw LuaError(L, ret); +int LuaHook::luaInfo(lua_State *L) { + logger->info(luaL_checkstring(L, 1)); + return 0; } -int LuaHook::luaRegisterApiHandler(lua_State *L) -{ - // register_api_handler(path_regex) - return 0; +int LuaHook::luaWarn(lua_State *L) { + logger->warn(luaL_checkstring(L, 1)); + return 0; } -int LuaHook::luaInfo(lua_State *L) -{ - logger->info(luaL_checkstring(L, 1)); - return 0; +int LuaHook::luaError(lua_State *L) { + logger->error(luaL_checkstring(L, 1)); + return 0; } -int LuaHook::luaWarn(lua_State *L) -{ - logger->warn(luaL_checkstring(L, 1)); - return 0; +int LuaHook::luaDebug(lua_State *L) { + logger->debug(luaL_checkstring(L, 1)); + return 0; } -int LuaHook::luaError(lua_State *L) -{ - logger->error(luaL_checkstring(L, 1)); - return 0; +void LuaHook::setupEnvironment() { + lua_pushlightuserdata(L, this); + lua_rawseti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); + + lua_register(L, "info", &dispatch<&LuaHook::luaInfo>); + lua_register(L, "warn", &dispatch<&LuaHook::luaWarn>); + lua_register(L, "error", &dispatch<&LuaHook::luaError>); + lua_register(L, "debug", &dispatch<&LuaHook::luaDebug>); + + lua_register(L, "register_api_handler", + &dispatch<&LuaHook::luaRegisterApiHandler>); } -int LuaHook::luaDebug(lua_State *L) -{ - logger->debug(luaL_checkstring(L, 1)); - return 0; -} +void LuaHook::prepare() { + // Load Lua standard libraries + luaL_openlibs(L); -void LuaHook::setupEnvironment() -{ - lua_pushlightuserdata(L, this); - lua_rawseti(L, LUA_REGISTRYINDEX, SELF_REFERENCE); + // Load our Lua script + logger->debug("Loading Lua script: {}", script); - lua_register(L, "info", &dispatch<&LuaHook::luaInfo>); - lua_register(L, "warn", &dispatch<&LuaHook::luaWarn>); - lua_register(L, "error", &dispatch<&LuaHook::luaError>); - lua_register(L, "debug", &dispatch<&LuaHook::luaDebug>); + setupEnvironment(); + loadScript(); + lookupFunctions(); - lua_register(L, "register_api_handler", &dispatch<&LuaHook::luaRegisterApiHandler>); -} - -void LuaHook::prepare() -{ - // Load Lua standard libraries - luaL_openlibs(L); - - // Load our Lua script - logger->debug("Loading Lua script: {}", script); - - setupEnvironment(); - loadScript(); - lookupFunctions(); - - /* Check if we need to protect the Lua state with a mutex + /* Check if we need to protect the Lua state with a mutex * This is the case if we have a periodic callback defined * As periodic() gets called from the main thread */ - needsLocking = functions.periodic > 0; + needsLocking = functions.periodic > 0; - // Prepare Lua process() - if (functions.process) { - /* We currently do not support the alteration of + // Prepare Lua process() + if (functions.process) { + /* We currently do not support the alteration of * signal metadata in process() */ - signalsProcessed = signals; - } + signalsProcessed = signals; + } - // Prepare Lua expressions - if (hasExpressions) { - for (auto &expr : expressions) - expr.prepare(); + // Prepare Lua expressions + if (hasExpressions) { + for (auto &expr : expressions) + expr.prepare(); - signals = signalsExpressions; - } + signals = signalsExpressions; + } - if (!functions.process && !hasExpressions) - logger->warn("The hook has neither a script or expressions defined. It is a no-op!"); + if (!functions.process && !hasExpressions) + logger->warn( + "The hook has neither a script or expressions defined. It is a no-op!"); - if (functions.prepare) { - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + if (functions.prepare) { + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - logger->debug("Executing Lua function: prepare()"); - lua_pushvalue(L, functions.prepare); - lua_pushjson(L, config); - int ret = lua_pcall(L, 1, 0, 0); - if (ret) - throw LuaError(L, ret); - } + logger->debug("Executing Lua function: prepare()"); + lua_pushvalue(L, functions.prepare); + lua_pushjson(L, config); + int ret = lua_pcall(L, 1, 0, 0); + if (ret) + throw LuaError(L, ret); + } } -void LuaHook::start() -{ - assert(state == State::PREPARED); +void LuaHook::start() { + assert(state == State::PREPARED); - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - if (functions.start) { - logger->debug("Executing Lua function: start()"); - lua_pushvalue(L, functions.start); - int ret = lua_pcall(L, 0, 0, 0); - if (ret) - throw LuaError(L, ret); - } + if (functions.start) { + logger->debug("Executing Lua function: start()"); + lua_pushvalue(L, functions.start); + int ret = lua_pcall(L, 0, 0, 0); + if (ret) + throw LuaError(L, ret); + } - state = State::STARTED; + state = State::STARTED; } -void LuaHook::stop() -{ - assert(state == State::STARTED); +void LuaHook::stop() { + assert(state == State::STARTED); - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - if (functions.stop) { - logger->debug("Executing Lua function: stop()"); - lua_pushvalue(L, functions.stop); - int ret = lua_pcall(L, 0, 0, 0); - if (ret) - throw LuaError(L, ret); - } + if (functions.stop) { + logger->debug("Executing Lua function: stop()"); + lua_pushvalue(L, functions.stop); + int ret = lua_pcall(L, 0, 0, 0); + if (ret) + throw LuaError(L, ret); + } - state = State::STOPPED; + state = State::STOPPED; } -void LuaHook::restart() -{ - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); +void LuaHook::restart() { + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - assert(state == State::STARTED); + assert(state == State::STARTED); - if (functions.restart) { - logger->debug("Executing Lua function: restart()"); - lua_pushvalue(L, functions.restart); - int ret = lua_pcall(L, 0, 0, 0); - if (ret) - throw LuaError(L, ret); - } - else - Hook::restart(); + if (functions.restart) { + logger->debug("Executing Lua function: restart()"); + lua_pushvalue(L, functions.restart); + int ret = lua_pcall(L, 0, 0, 0); + if (ret) + throw LuaError(L, ret); + } else + Hook::restart(); } -void LuaHook::periodic() -{ - assert(state == State::STARTED); +void LuaHook::periodic() { + assert(state == State::STARTED); - if (functions.periodic) { - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + if (functions.periodic) { + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - logger->debug("Executing Lua function: restart()"); - lua_pushvalue(L, functions.periodic); - int ret = lua_pcall(L, 0, 0, 0); - if (ret) - throw LuaError(L, ret); - } + logger->debug("Executing Lua function: restart()"); + lua_pushvalue(L, functions.periodic); + int ret = lua_pcall(L, 0, 0, 0); + if (ret) + throw LuaError(L, ret); + } } -Hook::Reason LuaHook::process(struct Sample *smp) -{ - if (!functions.process && !hasExpressions) - return Reason::OK; +Hook::Reason LuaHook::process(struct Sample *smp) { + if (!functions.process && !hasExpressions) + return Reason::OK; - int rtype; - enum Reason reason; - auto lockScope = needsLocking - ? std::unique_lock(mutex) - : std::unique_lock(); + int rtype; + enum Reason reason; + auto lockScope = needsLocking ? std::unique_lock(mutex) + : std::unique_lock(); - // First, run the process() function of the script - if (functions.process) { - logger->debug("Executing Lua function: process(smp)"); + // First, run the process() function of the script + if (functions.process) { + logger->debug("Executing Lua function: process(smp)"); - lua_pushsample(L, smp, useNames); + lua_pushsample(L, smp, useNames); - lua_pushvalue(L, functions.process); - lua_pushvalue(L, -2); // Push a copy since lua_pcall() will pop it - int ret = lua_pcall(L, 1, 1, 0); - if (ret) - throw LuaError(L, ret); + lua_pushvalue(L, functions.process); + lua_pushvalue(L, -2); // Push a copy since lua_pcall() will pop it + int ret = lua_pcall(L, 1, 1, 0); + if (ret) + throw LuaError(L, ret); - rtype = lua_type(L, -1); - if (rtype == LUA_TNUMBER) { - reason = (Reason) lua_tonumber(L, -1); - } - else { - logger->warn("Lua process() did not return a valid number. Assuming Reason::OK"); - reason = Reason::OK; - } + rtype = lua_type(L, -1); + if (rtype == LUA_TNUMBER) { + reason = (Reason)lua_tonumber(L, -1); + } else { + logger->warn( + "Lua process() did not return a valid number. Assuming Reason::OK"); + reason = Reason::OK; + } - lua_pop(L, 1); + lua_pop(L, 1); - lua_tosample(L, smp, signalsProcessed, useNames); - } - else - reason = Reason::OK; + lua_tosample(L, smp, signalsProcessed, useNames); + } else + reason = Reason::OK; - // After that evaluate expressions - if (hasExpressions) { - lua_pushsample(L, smp, useNames); - lua_setglobal(L, "smp"); + // After that evaluate expressions + if (hasExpressions) { + lua_pushsample(L, smp, useNames); + lua_setglobal(L, "smp"); - for (unsigned i = 0; i < expressions.size(); i++) { - auto sig = signalsExpressions->getByIndex(i); - if (!sig) - continue; + for (unsigned i = 0; i < expressions.size(); i++) { + auto sig = signalsExpressions->getByIndex(i); + if (!sig) + continue; - expressions[i].evaluate(&smp->data[i], sig->type); - } + expressions[i].evaluate(&smp->data[i], sig->type); + } - smp->length = expressions.size(); - } + smp->length = expressions.size(); + } - return reason; + return reason; } // Register hook static char n[] = "lua"; static char d[] = "Implement hook functions or expressions in Lua"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/ma.cpp b/lib/hooks/ma.cpp index 996767ab0..e2acc4f15 100644 --- a/lib/hooks/ma.cpp +++ b/lib/hooks/ma.cpp @@ -14,96 +14,90 @@ namespace node { class MovingAverageHook : public MultiSignalHook { protected: - std::vector> smpMemory; + std::vector> smpMemory; - double accumulator; - unsigned windowSize; - uint64_t smpMemoryPosition; + double accumulator; + unsigned windowSize; + uint64_t smpMemoryPosition; public: - MovingAverageHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - smpMemory(), - accumulator(0.0), - windowSize(10), - smpMemoryPosition(0) - { } + MovingAverageHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), smpMemory(), accumulator(0.0), + windowSize(10), smpMemoryPosition(0) {} - virtual - void prepare() - { - MultiSignalHook::prepare(); + virtual void prepare() { + MultiSignalHook::prepare(); - // Add signals - for (auto index : signalIndices) { - auto origSig = signals->getByIndex(index); + // Add signals + for (auto index : signalIndices) { + auto origSig = signals->getByIndex(index); - // Check that signal has float type - if (origSig->type != SignalType::FLOAT) - throw RuntimeError("The ma hook can only operate on signals of type float!"); - } + // Check that signal has float type + if (origSig->type != SignalType::FLOAT) + throw RuntimeError( + "The ma hook can only operate on signals of type float!"); + } - // Initialize sample memory - smpMemory.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) - smpMemory.emplace_back(windowSize, 0.0); + // Initialize sample memory + smpMemory.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) + smpMemory.emplace_back(windowSize, 0.0); - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: i }", - "window_size", &windowSize - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-rms"); + ret = + json_unpack_ex(json, &err, 0, "{ s?: i }", "window_size", &windowSize); + if (ret) + throw ConfigError(json, err, "node-config-hook-rms"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - unsigned i = 0; - for (auto index : signalIndices) { - // The new value - double newValue = smp->data[index].f; + unsigned i = 0; + for (auto index : signalIndices) { + // The new value + double newValue = smp->data[index].f; - // Append the new value to the history memory - smpMemory[i][smpMemoryPosition % windowSize] = newValue; + // Append the new value to the history memory + smpMemory[i][smpMemoryPosition % windowSize] = newValue; - // Get the old value from the history - double oldValue = smpMemory[i][(smpMemoryPosition + 1) % windowSize]; + // Get the old value from the history + double oldValue = smpMemory[i][(smpMemoryPosition + 1) % windowSize]; - // Update the accumulator - accumulator += newValue; - accumulator -= oldValue; + // Update the accumulator + accumulator += newValue; + accumulator -= oldValue; - smp->data[index].f = accumulator / windowSize; - i++; - } + smp->data[index].f = accumulator / windowSize; + i++; + } - smpMemoryPosition++; + smpMemoryPosition++; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "ma"; -static char d[] = "A simple moving average filter over a fixed number of past samples"; -static HookPlugin p; +static char d[] = + "A simple moving average filter over a fixed number of past samples"; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/pmu.cpp b/lib/hooks/pmu.cpp index a93ccd535..a1a2459f5 100644 --- a/lib/hooks/pmu.cpp +++ b/lib/hooks/pmu.cpp @@ -11,240 +11,243 @@ namespace villas { namespace node { -PmuHook::PmuHook(Path *p, Node *n, int fl, int prio, bool en): - MultiSignalHook(p, n, fl, prio, en), - windows(), - windowsTs(), - timeAlignType(TimeAlign::CENTER), - windowType(WindowType::NONE), - sampleRate(1), - phasorRate(1.0), - nominalFreq(1.0), - numberPlc(1.), - windowSize(1), - channelNameEnable(true), - angleUnitFactor(1.0), - lastSequence(0), - nextRun({0}), - init(false), - initSampleCount(0), - phaseOffset(0.0), - amplitudeOffset(0.0), - frequencyOffset(0.0), - rocofOffset(0.0) -{ } +PmuHook::PmuHook(Path *p, Node *n, int fl, int prio, bool en) + : MultiSignalHook(p, n, fl, prio, en), windows(), windowsTs(), + timeAlignType(TimeAlign::CENTER), windowType(WindowType::NONE), + sampleRate(1), phasorRate(1.0), nominalFreq(1.0), numberPlc(1.), + windowSize(1), channelNameEnable(true), angleUnitFactor(1.0), + lastSequence(0), nextRun({0}), init(false), initSampleCount(0), + phaseOffset(0.0), amplitudeOffset(0.0), frequencyOffset(0.0), + rocofOffset(0.0) {} -void PmuHook::prepare() -{ - MultiSignalHook::prepare(); +void PmuHook::prepare() { + MultiSignalHook::prepare(); - signals->clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - // Add signals - auto freqSig = std::make_shared("frequency", "Hz", SignalType::FLOAT); - auto amplSig = std::make_shared("amplitude", "V", SignalType::FLOAT); - auto phaseSig = std::make_shared("phase", (angleUnitFactor)?"rad":"deg", SignalType::FLOAT);//angleUnitFactor==1 means rad - auto rocofSig = std::make_shared("rocof", "Hz/s", SignalType::FLOAT); + signals->clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + // Add signals + auto freqSig = + std::make_shared("frequency", "Hz", SignalType::FLOAT); + auto amplSig = + std::make_shared("amplitude", "V", SignalType::FLOAT); + auto phaseSig = std::make_shared( + "phase", (angleUnitFactor) ? "rad" : "deg", + SignalType::FLOAT); //angleUnitFactor==1 means rad + auto rocofSig = + std::make_shared("rocof", "Hz/s", SignalType::FLOAT); - if (!freqSig || !amplSig || !phaseSig || !rocofSig) - throw RuntimeError("Failed to create new signals"); + if (!freqSig || !amplSig || !phaseSig || !rocofSig) + throw RuntimeError("Failed to create new signals"); - if (channelNameEnable) { - auto suffix = fmt::format("_{}", signalNames[i]); + if (channelNameEnable) { + auto suffix = fmt::format("_{}", signalNames[i]); - freqSig->name += suffix; - amplSig->name += suffix; - phaseSig->name += suffix; - rocofSig->name += suffix; - } + freqSig->name += suffix; + amplSig->name += suffix; + phaseSig->name += suffix; + rocofSig->name += suffix; + } - signals->push_back(freqSig); - signals->push_back(amplSig); - signals->push_back(phaseSig); - signals->push_back(rocofSig); + signals->push_back(freqSig); + signals->push_back(amplSig); + signals->push_back(phaseSig); + signals->push_back(rocofSig); - lastPhasors.push_back({0.,0.,0.,0.}); - } + lastPhasors.push_back({0., 0., 0., 0.}); + } - windowSize = ceil(sampleRate * numberPlc / nominalFreq); + windowSize = ceil(sampleRate * numberPlc / nominalFreq); - for (unsigned i = 0; i < signalIndices.size(); i++) { - if (windowType == WindowType::NONE) - windows.push_back(new dsp::RectangularWindow(windowSize, 0.0)); - else if (windowType == WindowType::FLATTOP) - windows.push_back(new dsp::FlattopWindow(windowSize, 0.0)); - else if (windowType == WindowType::HAMMING) - windows.push_back(new dsp::HammingWindow(windowSize, 0.0)); - else if (windowType == WindowType::HANN) - windows.push_back(new dsp::HannWindow(windowSize, 0.0)); - else if (windowType == WindowType::NUTTAL) - windows.push_back(new dsp::NuttallWindow(windowSize, 0.0)); - else if (windowType == WindowType::BLACKMAN) - windows.push_back(new dsp::BlackmanWindow(windowSize, 0.0)); - } + for (unsigned i = 0; i < signalIndices.size(); i++) { + if (windowType == WindowType::NONE) + windows.push_back(new dsp::RectangularWindow(windowSize, 0.0)); + else if (windowType == WindowType::FLATTOP) + windows.push_back(new dsp::FlattopWindow(windowSize, 0.0)); + else if (windowType == WindowType::HAMMING) + windows.push_back(new dsp::HammingWindow(windowSize, 0.0)); + else if (windowType == WindowType::HANN) + windows.push_back(new dsp::HannWindow(windowSize, 0.0)); + else if (windowType == WindowType::NUTTAL) + windows.push_back(new dsp::NuttallWindow(windowSize, 0.0)); + else if (windowType == WindowType::BLACKMAN) + windows.push_back(new dsp::BlackmanWindow(windowSize, 0.0)); + } - windowsTs = new dsp::Window(windowSize, timespec{0}); + windowsTs = new dsp::Window(windowSize, timespec{0}); } -void PmuHook::parse(json_t *json) -{ - MultiSignalHook::parse(json); - int ret; +void PmuHook::parse(json_t *json) { + MultiSignalHook::parse(json); + int ret; - const char *windowTypeC = nullptr; - const char *angleUnitC = nullptr; - const char *timeAlignC = nullptr; + const char *windowTypeC = nullptr; + const char *angleUnitC = nullptr; + const char *timeAlignC = nullptr; - json_error_t err; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: F, s?: F, s?: F, s?: s, s?: s, s?: b, s?: s, s?: F, s?: F, s?: F, s?: F}", - "sample_rate", &sampleRate, - "dft_rate", &phasorRate, - "nominal_freq", &nominalFreq, - "number_plc", &numberPlc, - "window_type", &windowTypeC, - "angle_unit", &angleUnitC, - "add_channel_name", &channelNameEnable, - "timestamp_align", &timeAlignC, - "phase_offset", &phaseOffset, - "amplitude_offset", &litudeOffset, - "frequency_offset", &frequencyOffset, - "rocof_offset", &rocofOffset - ); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: i, s?: F, s?: F, s?: F, s?: s, s?: s, s?: b, s?: s, s?: F, s?: F, " + "s?: F, s?: F}", + "sample_rate", &sampleRate, "dft_rate", &phasorRate, "nominal_freq", + &nominalFreq, "number_plc", &numberPlc, "window_type", &windowTypeC, + "angle_unit", &angleUnitC, "add_channel_name", &channelNameEnable, + "timestamp_align", &timeAlignC, "phase_offset", &phaseOffset, + "amplitude_offset", &litudeOffset, "frequency_offset", + &frequencyOffset, "rocof_offset", &rocofOffset); - if (ret) - throw ConfigError(json, err, "node-config-hook-pmu"); + if (ret) + throw ConfigError(json, err, "node-config-hook-pmu"); - if (sampleRate <= 0) - throw ConfigError(json, "node-config-hook-pmu-sample_rate", "Sample rate cannot be less than 0 tried to set {}", sampleRate); + if (sampleRate <= 0) + throw ConfigError(json, "node-config-hook-pmu-sample_rate", + "Sample rate cannot be less than 0 tried to set {}", + sampleRate); - if (phasorRate <= 0) - throw ConfigError(json, "node-config-hook-pmu-phasor_rate", "Phasor rate cannot be less than 0 tried to set {}", phasorRate); + if (phasorRate <= 0) + throw ConfigError(json, "node-config-hook-pmu-phasor_rate", + "Phasor rate cannot be less than 0 tried to set {}", + phasorRate); - if (nominalFreq <= 0) - throw ConfigError(json, "node-config-hook-pmu-nominal_freq", "Nominal frequency cannot be less than 0 tried to set {}", nominalFreq); + if (nominalFreq <= 0) + throw ConfigError(json, "node-config-hook-pmu-nominal_freq", + "Nominal frequency cannot be less than 0 tried to set {}", + nominalFreq); - if (numberPlc <= 0) - throw ConfigError(json, "node-config-hook-pmu-number_plc", "Number of power line cycles cannot be less than 0 tried to set {}", numberPlc); + if (numberPlc <= 0) + throw ConfigError( + json, "node-config-hook-pmu-number_plc", + "Number of power line cycles cannot be less than 0 tried to set {}", + numberPlc); - if (!windowTypeC) - logger->info("No Window type given, assume no windowing"); - else if (strcmp(windowTypeC, "flattop") == 0) - windowType = WindowType::FLATTOP; - else if (strcmp(windowTypeC, "hamming") == 0) - windowType = WindowType::HAMMING; - else if (strcmp(windowTypeC, "hann") == 0) - windowType = WindowType::HANN; - else if (strcmp(windowTypeC, "nuttal") == 0) - windowType = WindowType::NUTTAL; - else if (strcmp(windowTypeC, "blackman") == 0) - windowType = WindowType::BLACKMAN; - else - throw ConfigError(json, "node-config-hook-pmu-window-type", "Invalid window type: {}", windowTypeC); + if (!windowTypeC) + logger->info("No Window type given, assume no windowing"); + else if (strcmp(windowTypeC, "flattop") == 0) + windowType = WindowType::FLATTOP; + else if (strcmp(windowTypeC, "hamming") == 0) + windowType = WindowType::HAMMING; + else if (strcmp(windowTypeC, "hann") == 0) + windowType = WindowType::HANN; + else if (strcmp(windowTypeC, "nuttal") == 0) + windowType = WindowType::NUTTAL; + else if (strcmp(windowTypeC, "blackman") == 0) + windowType = WindowType::BLACKMAN; + else + throw ConfigError(json, "node-config-hook-pmu-window-type", + "Invalid window type: {}", windowTypeC); - if (!angleUnitC) - logger->info("No angle type given, assume rad"); - else if (strcmp(angleUnitC, "rad") == 0) - angleUnitFactor = 1; - else if (strcmp(angleUnitC, "degree") == 0) - angleUnitFactor = 180 / M_PI; - else - throw ConfigError(json, "node-config-hook-pmu-angle-unit", "Angle unit {} not recognized", angleUnitC); - - if (!timeAlignC) - logger->info("No timestamp alignment defined. Assume alignment center"); - else if (strcmp(timeAlignC, "left") == 0) - timeAlignType = TimeAlign::LEFT; - else if (strcmp(timeAlignC, "center") == 0) - timeAlignType = TimeAlign::CENTER; - else if (strcmp(timeAlignC, "right") == 0) - timeAlignType = TimeAlign::RIGHT; - else - throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", "Timestamp alignment {} not recognized", timeAlignC); + if (!angleUnitC) + logger->info("No angle type given, assume rad"); + else if (strcmp(angleUnitC, "rad") == 0) + angleUnitFactor = 1; + else if (strcmp(angleUnitC, "degree") == 0) + angleUnitFactor = 180 / M_PI; + else + throw ConfigError(json, "node-config-hook-pmu-angle-unit", + "Angle unit {} not recognized", angleUnitC); + if (!timeAlignC) + logger->info("No timestamp alignment defined. Assume alignment center"); + else if (strcmp(timeAlignC, "left") == 0) + timeAlignType = TimeAlign::LEFT; + else if (strcmp(timeAlignC, "center") == 0) + timeAlignType = TimeAlign::CENTER; + else if (strcmp(timeAlignC, "right") == 0) + timeAlignType = TimeAlign::RIGHT; + else + throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", + "Timestamp alignment {} not recognized", timeAlignC); } -Hook::Reason PmuHook::process(struct Sample *smp) -{ - assert(state == State::STARTED); +Hook::Reason PmuHook::process(struct Sample *smp) { + assert(state == State::STARTED); - initSampleCount++; + initSampleCount++; - if (smp->sequence - lastSequence > 1) - logger->warn("Calculation is not Realtime. {} sampled missed", smp->sequence - lastSequence); - lastSequence = smp->sequence; + if (smp->sequence - lastSequence > 1) + logger->warn("Calculation is not Realtime. {} sampled missed", + smp->sequence - lastSequence); + lastSequence = smp->sequence; - if (!init && initSampleCount > windowSize) - init = true; + if (!init && initSampleCount > windowSize) + init = true; - timespec timeDiff = time_diff(&nextRun, &smp->ts.origin); - double tmpTimeDiff = time_to_double(&timeDiff); - bool run = false; - if (tmpTimeDiff > 0. && init) - run = true; + timespec timeDiff = time_diff(&nextRun, &smp->ts.origin); + double tmpTimeDiff = time_to_double(&timeDiff); + bool run = false; + if (tmpTimeDiff > 0. && init) + run = true; - Status phasorStatus = Status::VALID; - timespec phasorTimestamp = {0}; - if (run) { - for (unsigned i = 0; i < signalIndices.size(); i++) { - lastPhasors[i] = estimatePhasor(windows[i], lastPhasors[i]); - if (lastPhasors[i].valid != Status::VALID) - phasorStatus = Status::INVALID; - } + Status phasorStatus = Status::VALID; + timespec phasorTimestamp = {0}; + if (run) { + for (unsigned i = 0; i < signalIndices.size(); i++) { + lastPhasors[i] = estimatePhasor(windows[i], lastPhasors[i]); + if (lastPhasors[i].valid != Status::VALID) + phasorStatus = Status::INVALID; + } - // Align time tag - double currentTimeTag = time_to_double(&smp->ts.origin); - double alignedTime = currentTimeTag - fmod(currentTimeTag, 1 / phasorRate); - nextRun = time_from_double(alignedTime + 1 / phasorRate); + // Align time tag + double currentTimeTag = time_to_double(&smp->ts.origin); + double alignedTime = currentTimeTag - fmod(currentTimeTag, 1 / phasorRate); + nextRun = time_from_double(alignedTime + 1 / phasorRate); - size_t tsPos = 0; - if (timeAlignType == TimeAlign::RIGHT) - tsPos = windowSize; - else if (timeAlignType == TimeAlign::LEFT) - tsPos = 0; - else if (timeAlignType == TimeAlign::CENTER) - tsPos = windowSize / 2; - phasorTimestamp = (*windowsTs)[tsPos]; - } + size_t tsPos = 0; + if (timeAlignType == TimeAlign::RIGHT) + tsPos = windowSize; + else if (timeAlignType == TimeAlign::LEFT) + tsPos = 0; + else if (timeAlignType == TimeAlign::CENTER) + tsPos = windowSize / 2; + phasorTimestamp = (*windowsTs)[tsPos]; + } - // Update sample memory - unsigned i = 0; - for (auto index : signalIndices) - windows[i++]->update(smp->data[index].f); - windowsTs->update(smp->ts.origin); + // Update sample memory + unsigned i = 0; + for (auto index : signalIndices) + windows[i++]->update(smp->data[index].f); + windowsTs->update(smp->ts.origin); - // Make sure to update phasors after window update but estimate them before - if(run) { - for (unsigned i = 0; i < signalIndices.size(); i++) { - smp->data[i * 4 + 0].f = lastPhasors[i].frequency + frequencyOffset; // Frequency - smp->data[i * 4 + 1].f = (lastPhasors[i].amplitude / pow(2, 0.5)) + amplitudeOffset; // Amplitude - smp->data[i * 4 + 2].f = (lastPhasors[i].phase * 180 / M_PI) + phaseOffset; // Phase - smp->data[i * 4 + 3].f = lastPhasors[i].rocof + rocofOffset; /* ROCOF */; - } - smp->ts.origin = phasorTimestamp; + // Make sure to update phasors after window update but estimate them before + if (run) { + for (unsigned i = 0; i < signalIndices.size(); i++) { + smp->data[i * 4 + 0].f = + lastPhasors[i].frequency + frequencyOffset; // Frequency + smp->data[i * 4 + 1].f = (lastPhasors[i].amplitude / pow(2, 0.5)) + + amplitudeOffset; // Amplitude + smp->data[i * 4 + 2].f = + (lastPhasors[i].phase * 180 / M_PI) + phaseOffset; // Phase + smp->data[i * 4 + 3].f = lastPhasors[i].rocof + rocofOffset; /* ROCOF */ + ; + } + smp->ts.origin = phasorTimestamp; - smp->length = signalIndices.size() * 4; - } + smp->length = signalIndices.size() * 4; + } - if (!run || phasorStatus != Status::VALID) - return Reason::SKIP_SAMPLE; + if (!run || phasorStatus != Status::VALID) + return Reason::SKIP_SAMPLE; - return Reason::OK; + return Reason::OK; } -PmuHook::Phasor PmuHook::estimatePhasor(dsp::CosineWindow *window, Phasor lastPhasor) -{ - return {0., 0., 0., 0., Status::INVALID}; +PmuHook::Phasor PmuHook::estimatePhasor(dsp::CosineWindow *window, + Phasor lastPhasor) { + return {0., 0., 0., 0., Status::INVALID}; } // Register hook static char n[] = "pmu"; static char d[] = "This hook estimates a phsor"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/pmu_dft.cpp b/lib/hooks/pmu_dft.cpp index e0687eb00..bac7e49ed 100644 --- a/lib/hooks/pmu_dft.cpp +++ b/lib/hooks/pmu_dft.cpp @@ -5,11 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include -#include +#include #include +#include #include #include @@ -25,653 +25,674 @@ namespace node { class PmuDftHook : public MultiSignalHook { protected: - enum class PaddingType { - ZERO, - SIG_REPEAT - }; + enum class PaddingType { ZERO, SIG_REPEAT }; - enum class WindowType { - NONE, - FLATTOP, - HANN, - HAMMING - }; + enum class WindowType { NONE, FLATTOP, HANN, HAMMING }; - enum class EstimationType { - NONE, - QUADRATIC, - IpDFT - }; + enum class EstimationType { NONE, QUADRATIC, IpDFT }; - enum class TimeAlign { - LEFT, - CENTER, - RIGHT, - }; + enum class TimeAlign { + LEFT, + CENTER, + RIGHT, + }; - struct Point { - double x; - std::complex y; - }; + struct Point { + double x; + std::complex y; + }; - struct DftEstimate { - double amplitude; - double frequency; - double phase; - }; + struct DftEstimate { + double amplitude; + double frequency; + double phase; + }; - struct Phasor { - double frequency; - double amplitude; - double phase; - double rocof; // Rate of change of frequency. - }; + struct Phasor { + double frequency; + double amplitude; + double phase; + double rocof; // Rate of change of frequency. + }; - enum WindowType windowType; - enum PaddingType paddingType; - enum EstimationType estType; - enum TimeAlign timeAlignType; + enum WindowType windowType; + enum PaddingType paddingType; + enum EstimationType estType; + enum TimeAlign timeAlignType; - std::vector> smpMemoryData; - std::vector smpMemoryTs; + std::vector> smpMemoryData; + std::vector smpMemoryTs; #ifdef DFT_MEM_DUMP - std::vector ppsMemory; + std::vector ppsMemory; #endif - std::vector>> matrix; - std::vector>> results; - std::vector filterWindowCoefficents; - std::vector> absResults; - std::vector absFrequencies; + std::vector>> matrix; + std::vector>> results; + std::vector filterWindowCoefficents; + std::vector> absResults; + std::vector absFrequencies; - uint64_t calcCount; - unsigned sampleRate; - double startFrequency; - double endFreqency; - double frequencyResolution; - unsigned rate; - unsigned ppsIndex; - unsigned windowSize; - unsigned windowMultiplier; // Multiplyer for the window to achieve frequency resolution - unsigned freqCount; // Number of requency bins that are calculated - bool channelNameEnable; // Rename the output values with channel name or only descriptive name + uint64_t calcCount; + unsigned sampleRate; + double startFrequency; + double endFreqency; + double frequencyResolution; + unsigned rate; + unsigned ppsIndex; + unsigned windowSize; + unsigned + windowMultiplier; // Multiplyer for the window to achieve frequency resolution + unsigned freqCount; // Number of requency bins that are calculated + bool + channelNameEnable; // Rename the output values with channel name or only descriptive name - uint64_t smpMemPos; - uint64_t lastSequence; + uint64_t smpMemPos; + uint64_t lastSequence; - std::complex omega; + std::complex omega; - double windowCorrectionFactor; - struct timespec lastCalc; - double nextCalc; + double windowCorrectionFactor; + struct timespec lastCalc; + double nextCalc; - std::vector lastResult; + std::vector lastResult; - std::string dumperPrefix; - bool dumperEnable; + std::string dumperPrefix; + bool dumperEnable; #ifdef DFT_MEM_DUMP - Dumper origSigSync; - Dumper windowdSigSync; - Dumper ppsSigSync; - Dumper phasorRocof; - Dumper phasorPhase; - Dumper phasorAmplitude; - Dumper phasorFreq; + Dumper origSigSync; + Dumper windowdSigSync; + Dumper ppsSigSync; + Dumper phasorRocof; + Dumper phasorPhase; + Dumper phasorAmplitude; + Dumper phasorFreq; #endif - double angleUnitFactor; - double phaseOffset; - double frequencyOffset; - double amplitudeOffset; - double rocofOffset; + double angleUnitFactor; + double phaseOffset; + double frequencyOffset; + double amplitudeOffset; + double rocofOffset; public: - PmuDftHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - windowType(WindowType::NONE), - paddingType(PaddingType::ZERO), - estType(EstimationType::NONE), - timeAlignType(TimeAlign::CENTER), - smpMemoryData(), - smpMemoryTs(), + PmuDftHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), windowType(WindowType::NONE), + paddingType(PaddingType::ZERO), estType(EstimationType::NONE), + timeAlignType(TimeAlign::CENTER), smpMemoryData(), smpMemoryTs(), #ifdef DFT_MEM_DUMP - ppsMemory(), + ppsMemory(), #endif - matrix(), - results(), - filterWindowCoefficents(), - absResults(), - absFrequencies(), - calcCount(0), - sampleRate(0), - startFrequency(0), - endFreqency(0), - frequencyResolution(0), - rate(0), - ppsIndex(0), - windowSize(0), - windowMultiplier(0), - freqCount(0), - channelNameEnable(1), - smpMemPos(0), - lastSequence(0), - windowCorrectionFactor(0), - lastCalc({0, 0}), - nextCalc(0.0), - lastResult(), - dumperPrefix("/tmp/plot/"), - dumperEnable(false), + matrix(), results(), filterWindowCoefficents(), absResults(), + absFrequencies(), calcCount(0), sampleRate(0), startFrequency(0), + endFreqency(0), frequencyResolution(0), rate(0), ppsIndex(0), + windowSize(0), windowMultiplier(0), freqCount(0), channelNameEnable(1), + smpMemPos(0), lastSequence(0), windowCorrectionFactor(0), + lastCalc({0, 0}), nextCalc(0.0), lastResult(), + dumperPrefix("/tmp/plot/"), dumperEnable(false), #ifdef DFT_MEM_DUMP - origSigSync(dumperPrefix + "origSigSync"), - windowdSigSync(dumperPrefix + "windowdSigSync"), - ppsSigSync(dumperPrefix + "ppsSigSync"), - phasorRocof(dumperPrefix + "phasorRocof"), - phasorPhase(dumperPrefix + "phasorPhase"), - phasorAmplitude(dumperPrefix + "phasorAmplitude"), - phasorFreq(dumperPrefix + "phasorFreq"), + origSigSync(dumperPrefix + "origSigSync"), + windowdSigSync(dumperPrefix + "windowdSigSync"), + ppsSigSync(dumperPrefix + "ppsSigSync"), + phasorRocof(dumperPrefix + "phasorRocof"), + phasorPhase(dumperPrefix + "phasorPhase"), + phasorAmplitude(dumperPrefix + "phasorAmplitude"), + phasorFreq(dumperPrefix + "phasorFreq"), #endif - angleUnitFactor(1), - phaseOffset(0.0), - frequencyOffset(0.0), - amplitudeOffset(0.0), - rocofOffset(0.0) - { } + angleUnitFactor(1), phaseOffset(0.0), frequencyOffset(0.0), + amplitudeOffset(0.0), rocofOffset(0.0) { + } - virtual - void prepare() - { - MultiSignalHook::prepare(); + virtual void prepare() { + MultiSignalHook::prepare(); - dumperEnable = logger->level() <= SPDLOG_LEVEL_DEBUG; + dumperEnable = logger->level() <= SPDLOG_LEVEL_DEBUG; - signals->clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - // Add signals - auto freqSig = std::make_shared("frequency", "Hz", SignalType::FLOAT); - auto amplSig = std::make_shared("amplitude", "V", SignalType::FLOAT); - auto phaseSig = std::make_shared("phase", (angleUnitFactor)?"rad":"deg", SignalType::FLOAT);//angleUnitFactor==1 means rad - auto rocofSig = std::make_shared("rocof", "Hz/s", SignalType::FLOAT); + signals->clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + // Add signals + auto freqSig = + std::make_shared("frequency", "Hz", SignalType::FLOAT); + auto amplSig = + std::make_shared("amplitude", "V", SignalType::FLOAT); + auto phaseSig = std::make_shared( + "phase", (angleUnitFactor) ? "rad" : "deg", + SignalType::FLOAT); //angleUnitFactor==1 means rad + auto rocofSig = + std::make_shared("rocof", "Hz/s", SignalType::FLOAT); - if (!freqSig || !amplSig || !phaseSig || !rocofSig) - throw RuntimeError("Failed to create new signals"); + if (!freqSig || !amplSig || !phaseSig || !rocofSig) + throw RuntimeError("Failed to create new signals"); - if (channelNameEnable) { - auto suffix = fmt::format("_{}", signalNames[i]); + if (channelNameEnable) { + auto suffix = fmt::format("_{}", signalNames[i]); - freqSig->name += suffix; - amplSig->name += suffix; - phaseSig->name += suffix; - rocofSig->name += suffix; - } + freqSig->name += suffix; + amplSig->name += suffix; + phaseSig->name += suffix; + rocofSig->name += suffix; + } - signals->push_back(freqSig); - signals->push_back(amplSig); - signals->push_back(phaseSig); - signals->push_back(rocofSig); - } + signals->push_back(freqSig); + signals->push_back(amplSig); + signals->push_back(phaseSig); + signals->push_back(rocofSig); + } - // Initialize sample memory - smpMemoryData.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - smpMemoryData.emplace_back(windowSize, 0.0); - } + // Initialize sample memory + smpMemoryData.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + smpMemoryData.emplace_back(windowSize, 0.0); + } - smpMemoryTs.clear(); - for (unsigned i = 0; i < windowSize; i++) { - smpMemoryTs.push_back({0}); - } + smpMemoryTs.clear(); + for (unsigned i = 0; i < windowSize; i++) { + smpMemoryTs.push_back({0}); + } - lastResult.clear(); - for (unsigned i = 0; i < windowSize; i++) { - lastResult.push_back({0,0,0,0}); - } + lastResult.clear(); + for (unsigned i = 0; i < windowSize; i++) { + lastResult.push_back({0, 0, 0, 0}); + } #ifdef DFT_MEM_DUMP - // Initialize temporary ppsMemory - ppsMemory.clear(); - ppsMemory.resize(windowSize, 0.0); + // Initialize temporary ppsMemory + ppsMemory.clear(); + ppsMemory.resize(windowSize, 0.0); #endif - // Calculate how much zero padding ist needed for a needed resolution - windowMultiplier = ceil(((double) sampleRate / windowSize) / frequencyResolution); - if (windowMultiplier > 1 && estType == EstimationType::IpDFT) - throw RuntimeError("Window multiplyer must be 1 if lpdft is used. Change resolution, window_size_factor or frequency range! Current window multiplyer factor is {}", windowMultiplier); + // Calculate how much zero padding ist needed for a needed resolution + windowMultiplier = + ceil(((double)sampleRate / windowSize) / frequencyResolution); + if (windowMultiplier > 1 && estType == EstimationType::IpDFT) + throw RuntimeError("Window multiplyer must be 1 if lpdft is used. Change " + "resolution, window_size_factor or frequency range! " + "Current window multiplyer factor is {}", + windowMultiplier); - freqCount = ceil((endFreqency - startFrequency) / frequencyResolution) + 1; + freqCount = ceil((endFreqency - startFrequency) / frequencyResolution) + 1; - // Initialize matrix of dft coeffients - matrix.clear(); - for (unsigned i = 0; i < freqCount; i++) - matrix.emplace_back(windowSize * windowMultiplier, 0.0); + // Initialize matrix of dft coeffients + matrix.clear(); + for (unsigned i = 0; i < freqCount; i++) + matrix.emplace_back(windowSize * windowMultiplier, 0.0); - // Initalize dft results matrix - results.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - results.emplace_back(freqCount, 0.0); - absResults.emplace_back(freqCount, 0.0); - } + // Initalize dft results matrix + results.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + results.emplace_back(freqCount, 0.0); + absResults.emplace_back(freqCount, 0.0); + } - filterWindowCoefficents.resize(windowSize); + filterWindowCoefficents.resize(windowSize); - for (unsigned i = 0; i < freqCount; i++) - absFrequencies.emplace_back(startFrequency + i * frequencyResolution); + for (unsigned i = 0; i < freqCount; i++) + absFrequencies.emplace_back(startFrequency + i * frequencyResolution); - generateDftMatrix(); - calculateWindow(windowType); + generateDftMatrix(); + calculateWindow(windowType); - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - MultiSignalHook::parse(json); - int ret; - int windowSizeFactor = 1; + virtual void parse(json_t *json) { + MultiSignalHook::parse(json); + int ret; + int windowSizeFactor = 1; - const char *paddingTypeC = nullptr; - const char *windowTypeC = nullptr; - const char *estimateTypeC = nullptr; - const char *angleUnitC = nullptr; - const char *timeAlignC = nullptr; + const char *paddingTypeC = nullptr; + const char *windowTypeC = nullptr; + const char *estimateTypeC = nullptr; + const char *angleUnitC = nullptr; + const char *timeAlignC = nullptr; - json_error_t err; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: F, s?: F, s?: F, s?: i, s?: i, s?: s, s?: s, s?: s, s?: i, s?: s, s?: b, s?: s, s?: F, s?: F, s?: F, s?: F}", - "sample_rate", &sampleRate, - "start_freqency", &startFrequency, - "end_freqency", &endFreqency, - "frequency_resolution", &frequencyResolution, - "dft_rate", &rate, - "window_size_factor", &windowSizeFactor, - "window_type", &windowTypeC, - "padding_type", &paddingTypeC, - "estimate_type", &estimateTypeC, - "pps_index", &ppsIndex, - "angle_unit", &angleUnitC, - "add_channel_name", &channelNameEnable, - "timestamp_align", &timeAlignC, - "phase_offset", &phaseOffset, - "amplitude_offset", &litudeOffset, - "frequency_offset", &frequencyOffset, - "rocof_offset", &rocofOffset - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-dft"); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: i, s?: F, s?: F, s?: F, s?: i, s?: i, s?: s, s?: s, s?: s, s?: " + "i, s?: s, s?: b, s?: s, s?: F, s?: F, s?: F, s?: F}", + "sample_rate", &sampleRate, "start_freqency", &startFrequency, + "end_freqency", &endFreqency, "frequency_resolution", + &frequencyResolution, "dft_rate", &rate, "window_size_factor", + &windowSizeFactor, "window_type", &windowTypeC, "padding_type", + &paddingTypeC, "estimate_type", &estimateTypeC, "pps_index", &ppsIndex, + "angle_unit", &angleUnitC, "add_channel_name", &channelNameEnable, + "timestamp_align", &timeAlignC, "phase_offset", &phaseOffset, + "amplitude_offset", &litudeOffset, "frequency_offset", + &frequencyOffset, "rocof_offset", &rocofOffset); + if (ret) + throw ConfigError(json, err, "node-config-hook-dft"); - windowSize = sampleRate * windowSizeFactor / (double) rate; - logger->info("Set windows size to {} samples which fits {} times the rate {}s", windowSize, windowSizeFactor, 1.0 / rate); + windowSize = sampleRate * windowSizeFactor / (double)rate; + logger->info( + "Set windows size to {} samples which fits {} times the rate {}s", + windowSize, windowSizeFactor, 1.0 / rate); - if (!windowTypeC) - logger->info("No Window type given, assume no windowing"); - else if (strcmp(windowTypeC, "flattop") == 0) - windowType = WindowType::FLATTOP; - else if (strcmp(windowTypeC, "hamming") == 0) - windowType = WindowType::HAMMING; - else if (strcmp(windowTypeC, "hann") == 0) - windowType = WindowType::HANN; - else - throw ConfigError(json, "node-config-hook-dft-window-type", "Invalid window type: {}", windowTypeC); + if (!windowTypeC) + logger->info("No Window type given, assume no windowing"); + else if (strcmp(windowTypeC, "flattop") == 0) + windowType = WindowType::FLATTOP; + else if (strcmp(windowTypeC, "hamming") == 0) + windowType = WindowType::HAMMING; + else if (strcmp(windowTypeC, "hann") == 0) + windowType = WindowType::HANN; + else + throw ConfigError(json, "node-config-hook-dft-window-type", + "Invalid window type: {}", windowTypeC); - if (!timeAlignC) - logger->info("No timestamp alignment defined. Assume alignment center"); - else if (strcmp(timeAlignC, "left") == 0) - timeAlignType = TimeAlign::LEFT; - else if (strcmp(timeAlignC, "center") == 0) - timeAlignType = TimeAlign::CENTER; - else if (strcmp(timeAlignC, "right") == 0) - timeAlignType = TimeAlign::RIGHT; - else - throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", "Timestamp alignment {} not recognized", timeAlignC); + if (!timeAlignC) + logger->info("No timestamp alignment defined. Assume alignment center"); + else if (strcmp(timeAlignC, "left") == 0) + timeAlignType = TimeAlign::LEFT; + else if (strcmp(timeAlignC, "center") == 0) + timeAlignType = TimeAlign::CENTER; + else if (strcmp(timeAlignC, "right") == 0) + timeAlignType = TimeAlign::RIGHT; + else + throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", + "Timestamp alignment {} not recognized", timeAlignC); - if (!angleUnitC) - logger->info("No angle type given, assume rad"); - else if (strcmp(angleUnitC, "rad") == 0) - angleUnitFactor = 1; - else if (strcmp(angleUnitC, "degree") == 0) - angleUnitFactor = 180 / M_PI; - else - throw ConfigError(json, "node-config-hook-dft-angle-unit", "Angle unit {} not recognized", angleUnitC); + if (!angleUnitC) + logger->info("No angle type given, assume rad"); + else if (strcmp(angleUnitC, "rad") == 0) + angleUnitFactor = 1; + else if (strcmp(angleUnitC, "degree") == 0) + angleUnitFactor = 180 / M_PI; + else + throw ConfigError(json, "node-config-hook-dft-angle-unit", + "Angle unit {} not recognized", angleUnitC); - if (!paddingTypeC) - logger->info("No Padding type given, assume no zeropadding"); - else if (strcmp(paddingTypeC, "zero") == 0) - paddingType = PaddingType::ZERO; - else if (strcmp(paddingTypeC, "signal_repeat") == 0) - paddingType = PaddingType::SIG_REPEAT; - else - throw ConfigError(json, "node-config-hook-dft-padding-type", "Padding type {} not recognized", paddingTypeC); + if (!paddingTypeC) + logger->info("No Padding type given, assume no zeropadding"); + else if (strcmp(paddingTypeC, "zero") == 0) + paddingType = PaddingType::ZERO; + else if (strcmp(paddingTypeC, "signal_repeat") == 0) + paddingType = PaddingType::SIG_REPEAT; + else + throw ConfigError(json, "node-config-hook-dft-padding-type", + "Padding type {} not recognized", paddingTypeC); - if (!estimateTypeC) { - logger->info("No Frequency estimation type given, assume no none"); - estType = EstimationType::NONE; - } else if (strcmp(estimateTypeC, "quadratic") == 0) - estType = EstimationType::QUADRATIC; - else if (strcmp(estimateTypeC, "ipdft") == 0) - estType = EstimationType::IpDFT; - state = State::PARSED; - } + if (!estimateTypeC) { + logger->info("No Frequency estimation type given, assume no none"); + estType = EstimationType::NONE; + } else if (strcmp(estimateTypeC, "quadratic") == 0) + estType = EstimationType::QUADRATIC; + else if (strcmp(estimateTypeC, "ipdft") == 0) + estType = EstimationType::IpDFT; + state = State::PARSED; + } - virtual - void check() - { - assert(state == State::PARSED); + virtual void check() { + assert(state == State::PARSED); - if (endFreqency < 0 || endFreqency > sampleRate) - throw RuntimeError("End frequency must be smaller than sampleRate {}", sampleRate); + if (endFreqency < 0 || endFreqency > sampleRate) + throw RuntimeError("End frequency must be smaller than sampleRate {}", + sampleRate); - if (frequencyResolution > (double) sampleRate / windowSize) - throw RuntimeError("The maximum frequency resolution with smaple_rate:{} and window_site:{} is {}", sampleRate, windowSize, ((double)sampleRate/windowSize)); + if (frequencyResolution > (double)sampleRate / windowSize) + throw RuntimeError("The maximum frequency resolution with smaple_rate:{} " + "and window_site:{} is {}", + sampleRate, windowSize, + ((double)sampleRate / windowSize)); - state = State::CHECKED; - } + state = State::CHECKED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - // Update sample memory - unsigned i = 0; - for (auto index : signalIndices) { - smpMemoryData[i++][smpMemPos % windowSize] = smp->data[index].f; - } - smpMemoryTs[smpMemPos % windowSize] = smp->ts.origin; + // Update sample memory + unsigned i = 0; + for (auto index : signalIndices) { + smpMemoryData[i++][smpMemPos % windowSize] = smp->data[index].f; + } + smpMemoryTs[smpMemPos % windowSize] = smp->ts.origin; #ifdef DFT_MEM_DUMP - ppsMemory[smpMemPos % windowSize] = smp->data[ppsIndex].f; + ppsMemory[smpMemPos % windowSize] = smp->data[ppsIndex].f; #endif - bool run = false; - double smpNsec = smp->ts.origin.tv_sec * 1e9 + smp->ts.origin.tv_nsec; + bool run = false; + double smpNsec = smp->ts.origin.tv_sec * 1e9 + smp->ts.origin.tv_nsec; - if (smpNsec > nextCalc) { - run = true; - nextCalc = (smp->ts.origin.tv_sec + (((calcCount % rate) + 1) / (double) rate)) * 1e9; - } + if (smpNsec > nextCalc) { + run = true; + nextCalc = + (smp->ts.origin.tv_sec + (((calcCount % rate) + 1) / (double)rate)) * + 1e9; + } - if (run) { - lastCalc = smp->ts.origin; + if (run) { + lastCalc = smp->ts.origin; #ifdef DFT_MEM_DUMP - double tmpPPSWindow[windowSize]; + double tmpPPSWindow[windowSize]; - for (unsigned i = 0; i< windowSize; i++) - tmpPPSWindow[i] = ppsMemory[(i + smpMemPos) % windowSize]; + for (unsigned i = 0; i < windowSize; i++) + tmpPPSWindow[i] = ppsMemory[(i + smpMemPos) % windowSize]; - if (dumperEnable) - ppsSigSync.writeDataBinary(windowSize, tmpPPSWindow); + if (dumperEnable) + ppsSigSync.writeDataBinary(windowSize, tmpPPSWindow); #endif - #pragma omp parallel for - for (unsigned i = 0; i < signalIndices.size(); i++) { - Phasor currentResult = {0,0,0,0}; +#pragma omp parallel for + for (unsigned i = 0; i < signalIndices.size(); i++) { + Phasor currentResult = {0, 0, 0, 0}; - calculateDft(PaddingType::ZERO, smpMemoryData[i], results[i], smpMemPos); + calculateDft(PaddingType::ZERO, smpMemoryData[i], results[i], + smpMemPos); - unsigned maxPos = 0; - double absAmplitude = 0; + unsigned maxPos = 0; + double absAmplitude = 0; - for(unsigned j = 0; j < freqCount; j++) { - if (absAmplitude < abs(results[i][j])) { - absAmplitude = abs(results[i][j]); - maxPos = j; - } - } - - int multiplier = paddingType == PaddingType::ZERO - ? 1 - : windowMultiplier; - - DftEstimate dftEstimate = {0}; - - if ( (maxPos < 1 || maxPos >= freqCount - 1) && estType != EstimationType::NONE) { - logger->warn("Maximum frequency bin lies on window boundary. Using non-estimated results!"); - dftEstimate = noEstimation({0}, { absFrequencies[maxPos + 0], results[i][maxPos + 0] }, {0}, maxPos, startFrequency, frequencyResolution, multiplier, windowSize, windowCorrectionFactor); - } else { - Point a = { absFrequencies[maxPos - 1], results[i][maxPos - 1] }; - Point b = { absFrequencies[maxPos + 0], results[i][maxPos + 0] }; - Point c = { absFrequencies[maxPos + 1], results[i][maxPos + 1] }; - - if( estType == EstimationType::QUADRATIC ) - dftEstimate = quadraticEstimation(a, b, c, maxPos, startFrequency, frequencyResolution, multiplier, windowSize, windowCorrectionFactor); - else if( estType == EstimationType::IpDFT ) - dftEstimate = lpdftEstimation(a, b, c, maxPos, startFrequency, frequencyResolution, multiplier, windowSize, windowCorrectionFactor); - else - dftEstimate = noEstimation({0}, b, {0}, maxPos, startFrequency, frequencyResolution, multiplier, windowSize, windowCorrectionFactor); - } - currentResult.frequency = dftEstimate.frequency; - currentResult.amplitude = dftEstimate.amplitude; - currentResult.phase = dftEstimate.phase * angleUnitFactor;//convert phase from rad to deg - - if (windowSize <= smpMemPos) { - - smp->data[i * 4 + 0].f = currentResult.frequency + frequencyOffset; // Frequency - smp->data[i * 4 + 1].f = (currentResult.amplitude / pow(2, 0.5)) + amplitudeOffset; // Amplitude - smp->data[i * 4 + 2].f = currentResult.phase + phaseOffset; // Phase - smp->data[i * 4 + 3].f = ((currentResult.frequency - lastResult[i].frequency) * (double)rate) + rocofOffset; /* ROCOF */; - lastResult[i] = currentResult; - } - } -#ifdef DFT_MEM_DUMP - // The following is a debug output and currently only for channel 0 - if (dumperEnable && windowSize * 5 < smpMemPos){ - phasorFreq.writeDataBinary(1, &(smp->data[0 * 4 + 0].f)); - phasorPhase.writeDataBinary(1, &(smp->data[0 * 4 + 2].f)); - phasorAmplitude.writeDataBinary(1, &(smp->data[0 * 4 + 1].f)); - phasorRocof.writeDataBinary(1, &(smp->data[0 * 4 + 3].f)); - } -#endif - - smp->length = windowSize < smpMemPos ? signalIndices.size() * 4 : 0; - - if(smpMemPos >= windowSize) { - unsigned tsPos = 0; - if (timeAlignType == TimeAlign::RIGHT) - tsPos = smpMemPos; - else if (timeAlignType == TimeAlign::LEFT) - tsPos = smpMemPos - windowSize; - else if (timeAlignType == TimeAlign::CENTER) { - tsPos = smpMemPos - (windowSize / 2); - } - - smp->ts.origin = smpMemoryTs[tsPos % windowSize]; - } - - calcCount++; - } - - if (smp->sequence - lastSequence > 1) - logger->warn("Calculation is not Realtime. {} sampled missed", smp->sequence - lastSequence); - - lastSequence = smp->sequence; - - if(smpMemPos >= 2 * windowSize) {//reset smpMemPos if greater than twice the window. Important to handle init - smpMemPos = windowSize; + for (unsigned j = 0; j < freqCount; j++) { + if (absAmplitude < abs(results[i][j])) { + absAmplitude = abs(results[i][j]); + maxPos = j; + } } - smpMemPos++; + int multiplier = + paddingType == PaddingType::ZERO ? 1 : windowMultiplier; - if (run && windowSize < smpMemPos) - return Reason::OK; + DftEstimate dftEstimate = {0}; - return Reason::SKIP_SAMPLE; - } + if ((maxPos < 1 || maxPos >= freqCount - 1) && + estType != EstimationType::NONE) { + logger->warn("Maximum frequency bin lies on window boundary. Using " + "non-estimated results!"); + dftEstimate = noEstimation( + {0}, {absFrequencies[maxPos + 0], results[i][maxPos + 0]}, {0}, + maxPos, startFrequency, frequencyResolution, multiplier, + windowSize, windowCorrectionFactor); + } else { + Point a = {absFrequencies[maxPos - 1], results[i][maxPos - 1]}; + Point b = {absFrequencies[maxPos + 0], results[i][maxPos + 0]}; + Point c = {absFrequencies[maxPos + 1], results[i][maxPos + 1]}; - /* - * This function generates the furie coeffients for the calculateDft function - */ - void generateDftMatrix() - { - using namespace std::complex_literals; + if (estType == EstimationType::QUADRATIC) + dftEstimate = quadraticEstimation( + a, b, c, maxPos, startFrequency, frequencyResolution, + multiplier, windowSize, windowCorrectionFactor); + else if (estType == EstimationType::IpDFT) + dftEstimate = lpdftEstimation(a, b, c, maxPos, startFrequency, + frequencyResolution, multiplier, + windowSize, windowCorrectionFactor); + else + dftEstimate = noEstimation({0}, b, {0}, maxPos, startFrequency, + frequencyResolution, multiplier, + windowSize, windowCorrectionFactor); + } + currentResult.frequency = dftEstimate.frequency; + currentResult.amplitude = dftEstimate.amplitude; + currentResult.phase = + dftEstimate.phase * angleUnitFactor; //convert phase from rad to deg - omega = exp((-2i * M_PI) / (double)(windowSize * windowMultiplier)); - unsigned startBin = floor(startFrequency / frequencyResolution); - - for (unsigned i = 0; i < freqCount ; i++) { - for (unsigned j = 0 ; j < windowSize * windowMultiplier ; j++) - matrix[i][j] = pow(omega, (i + startBin) * j); - } - } - - /* - * This function calculates the discrete furie transform of the input signal - */ - void calculateDft(enum PaddingType padding, std::vector &ringBuffer, std::vector> &results, unsigned ringBufferPos) - { - /* RingBuffer size needs to be equal to windowSize - * prepare sample window The following parts can be combined */ - double tmpSmpWindow[windowSize]; - - for (unsigned i = 0; i< windowSize; i++) - tmpSmpWindow[i] = ringBuffer[(i + ringBufferPos) % windowSize] * filterWindowCoefficents[i]; + if (windowSize <= smpMemPos) { + smp->data[i * 4 + 0].f = + currentResult.frequency + frequencyOffset; // Frequency + smp->data[i * 4 + 1].f = (currentResult.amplitude / pow(2, 0.5)) + + amplitudeOffset; // Amplitude + smp->data[i * 4 + 2].f = currentResult.phase + phaseOffset; // Phase + smp->data[i * 4 + 3].f = + ((currentResult.frequency - lastResult[i].frequency) * + (double)rate) + + rocofOffset; /* ROCOF */ + ; + lastResult[i] = currentResult; + } + } #ifdef DFT_MEM_DUMP - if (dumperEnable) - origSigSync.writeDataBinary(windowSize, tmpSmpWindow); + // The following is a debug output and currently only for channel 0 + if (dumperEnable && windowSize * 5 < smpMemPos) { + phasorFreq.writeDataBinary(1, &(smp->data[0 * 4 + 0].f)); + phasorPhase.writeDataBinary(1, &(smp->data[0 * 4 + 2].f)); + phasorAmplitude.writeDataBinary(1, &(smp->data[0 * 4 + 1].f)); + phasorRocof.writeDataBinary(1, &(smp->data[0 * 4 + 3].f)); + } #endif - for (unsigned i = 0; i < freqCount; i++) { - results[i] = 0; + smp->length = windowSize < smpMemPos ? signalIndices.size() * 4 : 0; - for (unsigned j = 0; j < windowSize * windowMultiplier; j++) { - if (padding == PaddingType::ZERO) { - if (j < windowSize) - results[i] += tmpSmpWindow[j] * matrix[i][j]; - else - results[i] += 0; - } - else if (padding == PaddingType::SIG_REPEAT) // Repeat samples - results[i] += tmpSmpWindow[j % windowSize] * matrix[i][j]; - } - } - } + if (smpMemPos >= windowSize) { + unsigned tsPos = 0; + if (timeAlignType == TimeAlign::RIGHT) + tsPos = smpMemPos; + else if (timeAlignType == TimeAlign::LEFT) + tsPos = smpMemPos - windowSize; + else if (timeAlignType == TimeAlign::CENTER) { + tsPos = smpMemPos - (windowSize / 2); + } - /* + smp->ts.origin = smpMemoryTs[tsPos % windowSize]; + } + + calcCount++; + } + + if (smp->sequence - lastSequence > 1) + logger->warn("Calculation is not Realtime. {} sampled missed", + smp->sequence - lastSequence); + + lastSequence = smp->sequence; + + if (smpMemPos >= + 2 * windowSize) { //reset smpMemPos if greater than twice the window. Important to handle init + smpMemPos = windowSize; + } + + smpMemPos++; + + if (run && windowSize < smpMemPos) + return Reason::OK; + + return Reason::SKIP_SAMPLE; + } + + /* + * This function generates the furie coeffients for the calculateDft function + */ + void generateDftMatrix() { + using namespace std::complex_literals; + + omega = exp((-2i * M_PI) / (double)(windowSize * windowMultiplier)); + unsigned startBin = floor(startFrequency / frequencyResolution); + + for (unsigned i = 0; i < freqCount; i++) { + for (unsigned j = 0; j < windowSize * windowMultiplier; j++) + matrix[i][j] = pow(omega, (i + startBin) * j); + } + } + + /* + * This function calculates the discrete furie transform of the input signal + */ + void calculateDft(enum PaddingType padding, std::vector &ringBuffer, + std::vector> &results, + unsigned ringBufferPos) { + /* RingBuffer size needs to be equal to windowSize + * prepare sample window The following parts can be combined */ + double tmpSmpWindow[windowSize]; + + for (unsigned i = 0; i < windowSize; i++) + tmpSmpWindow[i] = ringBuffer[(i + ringBufferPos) % windowSize] * + filterWindowCoefficents[i]; + +#ifdef DFT_MEM_DUMP + if (dumperEnable) + origSigSync.writeDataBinary(windowSize, tmpSmpWindow); +#endif + + for (unsigned i = 0; i < freqCount; i++) { + results[i] = 0; + + for (unsigned j = 0; j < windowSize * windowMultiplier; j++) { + if (padding == PaddingType::ZERO) { + if (j < windowSize) + results[i] += tmpSmpWindow[j] * matrix[i][j]; + else + results[i] += 0; + } else if (padding == PaddingType::SIG_REPEAT) // Repeat samples + results[i] += tmpSmpWindow[j % windowSize] * matrix[i][j]; + } + } + } + + /* * This function prepares the selected window coefficents */ - void calculateWindow(enum WindowType windowTypeIn) - { - switch (windowTypeIn) { - case WindowType::FLATTOP: - for (unsigned i = 0; i < windowSize; i++) { - filterWindowCoefficents[i] = 0.21557895 - - 0.41663158 * cos(2 * M_PI * i / (windowSize)) - + 0.277263158 * cos(4 * M_PI * i / (windowSize)) - - 0.083578947 * cos(6 * M_PI * i / (windowSize)) - + 0.006947368 * cos(8 * M_PI * i / (windowSize)); - windowCorrectionFactor += filterWindowCoefficents[i]; - } - break; + void calculateWindow(enum WindowType windowTypeIn) { + switch (windowTypeIn) { + case WindowType::FLATTOP: + for (unsigned i = 0; i < windowSize; i++) { + filterWindowCoefficents[i] = + 0.21557895 - 0.41663158 * cos(2 * M_PI * i / (windowSize)) + + 0.277263158 * cos(4 * M_PI * i / (windowSize)) - + 0.083578947 * cos(6 * M_PI * i / (windowSize)) + + 0.006947368 * cos(8 * M_PI * i / (windowSize)); + windowCorrectionFactor += filterWindowCoefficents[i]; + } + break; - case WindowType::HAMMING: - case WindowType::HANN: { - double a0 = 0.5; // This is the hann window - if (windowTypeIn == WindowType::HAMMING) - a0 = 25./46; + case WindowType::HAMMING: + case WindowType::HANN: { + double a0 = 0.5; // This is the hann window + if (windowTypeIn == WindowType::HAMMING) + a0 = 25. / 46; - for (unsigned i = 0; i < windowSize; i++) { - filterWindowCoefficents[i] = a0 - (1 - a0) * cos(2 * M_PI * i / (windowSize)); - windowCorrectionFactor += filterWindowCoefficents[i]; - } + for (unsigned i = 0; i < windowSize; i++) { + filterWindowCoefficents[i] = + a0 - (1 - a0) * cos(2 * M_PI * i / (windowSize)); + windowCorrectionFactor += filterWindowCoefficents[i]; + } - break; - } + break; + } - default: - for (unsigned i = 0; i < windowSize; i++) { - filterWindowCoefficents[i] = 1; - windowCorrectionFactor += filterWindowCoefficents[i]; - } - break; - } + default: + for (unsigned i = 0; i < windowSize; i++) { + filterWindowCoefficents[i] = 1; + windowCorrectionFactor += filterWindowCoefficents[i]; + } + break; + } - windowCorrectionFactor /= windowSize; - } + windowCorrectionFactor /= windowSize; + } - DftEstimate noEstimation(const Point &a, const Point &b, const Point &c, unsigned maxFBin, double startFrequency, double frequencyResolution, double multiplier, double windowSize, double windowCorrectionFactor) - { - // Frequency estimation - double f_est = startFrequency + maxFBin * frequencyResolution; + DftEstimate noEstimation(const Point &a, const Point &b, const Point &c, + unsigned maxFBin, double startFrequency, + double frequencyResolution, double multiplier, + double windowSize, double windowCorrectionFactor) { + // Frequency estimation + double f_est = startFrequency + maxFBin * frequencyResolution; - // Amplitude estimation - double a_est = abs(b.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); + // Amplitude estimation + double a_est = + abs(b.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); - //Phase estimation - double phase_est = atan2(b.y.imag(), b.y.real()); + //Phase estimation + double phase_est = atan2(b.y.imag(), b.y.real()); - return { a_est, f_est , phase_est}; - } + return {a_est, f_est, phase_est}; + } - /* + /* * This function is calculation the IpDFT based on the following paper: * * https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=7980868&tag=1 * */ - DftEstimate lpdftEstimation(const Point &a, const Point &b, const Point &c, unsigned maxFBin, double startFrequency, double frequencyResolution, double multiplier, double windowSize, double windowCorrectionFactor) - { - double delta = 0; + DftEstimate lpdftEstimation(const Point &a, const Point &b, const Point &c, + unsigned maxFBin, double startFrequency, + double frequencyResolution, double multiplier, + double windowSize, + double windowCorrectionFactor) { + double delta = 0; - //paper eq 8 - if (abs(c.y) > abs(a.y)) { - delta = 1. * (2. * abs(c.y) - abs(b.y)) / (abs(b.y) + abs(c.y)); - } else { - delta = -1. * (2. * abs(a.y) - abs(b.y)) / (abs(b.y) + abs(a.y)); - } + //paper eq 8 + if (abs(c.y) > abs(a.y)) { + delta = 1. * (2. * abs(c.y) - abs(b.y)) / (abs(b.y) + abs(c.y)); + } else { + delta = -1. * (2. * abs(a.y) - abs(b.y)) / (abs(b.y) + abs(a.y)); + } - // Frequency estimation (eq 4) - double f_est = startFrequency + ( (double) maxFBin + delta) * frequencyResolution; + // Frequency estimation (eq 4) + double f_est = + startFrequency + ((double)maxFBin + delta) * frequencyResolution; - // Amplitude estimation (eq 9) - double a_est = abs(b.y) * abs( (M_PI * delta) / sin( M_PI * delta) ) * abs( pow(delta, 2) - 1); - a_est *= 2 / (windowSize * windowCorrectionFactor * multiplier); + // Amplitude estimation (eq 9) + double a_est = abs(b.y) * abs((M_PI * delta) / sin(M_PI * delta)) * + abs(pow(delta, 2) - 1); + a_est *= 2 / (windowSize * windowCorrectionFactor * multiplier); - //Phase estimation (eq 10) - double phase_est = atan2(b.y.imag(), b.y.real()) - M_PI * delta; + //Phase estimation (eq 10) + double phase_est = atan2(b.y.imag(), b.y.real()) - M_PI * delta; - return { a_est, f_est , phase_est}; - } + return {a_est, f_est, phase_est}; + } - /* + /* * This function is calculating the mximum based on a quadratic interpolation * * This function is based on the following paper: * https://mgasior.web.cern.ch/pap/biw2004.pdf (equation 10) (freq estimation) * https://dspguru.com/dsp/howtos/how-to-interpolate-fft-peak/ */ - DftEstimate quadraticEstimation(const Point &a, const Point &b, const Point &c, unsigned maxFBin, double startFrequency, double frequencyResolution, double multiplier, double windowSize, double windowCorrectionFactor) - { - using namespace std::complex_literals; + DftEstimate quadraticEstimation(const Point &a, const Point &b, + const Point &c, unsigned maxFBin, + double startFrequency, + double frequencyResolution, double multiplier, + double windowSize, + double windowCorrectionFactor) { + using namespace std::complex_literals; - double ay_abs = abs(a.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); - double by_abs = abs(b.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); - double cy_abs = abs(c.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); + double ay_abs = + abs(a.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); + double by_abs = + abs(b.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); + double cy_abs = + abs(c.y) * 2 / (windowSize * windowCorrectionFactor * multiplier); - // Frequency estimation - double maxBinEst = (double) maxFBin + (cy_abs - ay_abs) / (2 * (2 * by_abs - ay_abs - cy_abs)); - double f_est = startFrequency + maxBinEst * frequencyResolution; // convert bin to frequency + // Frequency estimation + double maxBinEst = (double)maxFBin + + (cy_abs - ay_abs) / (2 * (2 * by_abs - ay_abs - cy_abs)); + double f_est = startFrequency + + maxBinEst * frequencyResolution; // convert bin to frequency - // Amplitude estimation - double f = (a.x * (by_abs - cy_abs) + b.x * (cy_abs - ay_abs) + c.x * (ay_abs - by_abs)) / ((a.x - b.x) * (a.x - c.x) * (c.x - b.x)); - double g = (pow(a.x, 2) * (by_abs - cy_abs) + pow(b.x, 2) * (cy_abs - ay_abs) + pow(c.x, 2) * (ay_abs - by_abs)) / ((a.x - b.x) * (a.x - c.x) * (b.x - c.x)); - double h = (pow(a.x, 2) * (b.x * cy_abs - c.x * by_abs) + a.x * (pow(c.x, 2) * by_abs - pow(b.x,2) * cy_abs)+ b.x * c.x * ay_abs * (b.x - c.x)) / ((a.x - b.x) * (a.x - c.x) * (b.x - c.x)); - double a_est = f * pow(f_est,2) + g * f_est + h; + // Amplitude estimation + double f = (a.x * (by_abs - cy_abs) + b.x * (cy_abs - ay_abs) + + c.x * (ay_abs - by_abs)) / + ((a.x - b.x) * (a.x - c.x) * (c.x - b.x)); + double g = + (pow(a.x, 2) * (by_abs - cy_abs) + pow(b.x, 2) * (cy_abs - ay_abs) + + pow(c.x, 2) * (ay_abs - by_abs)) / + ((a.x - b.x) * (a.x - c.x) * (b.x - c.x)); + double h = (pow(a.x, 2) * (b.x * cy_abs - c.x * by_abs) + + a.x * (pow(c.x, 2) * by_abs - pow(b.x, 2) * cy_abs) + + b.x * c.x * ay_abs * (b.x - c.x)) / + ((a.x - b.x) * (a.x - c.x) * (b.x - c.x)); + double a_est = f * pow(f_est, 2) + g * f_est + h; - //Phase estimation - double phase_est = atan2(b.y.imag(), b.y.real()); + //Phase estimation + double phase_est = atan2(b.y.imag(), b.y.real()); - return { a_est, f_est , phase_est}; - } + return {a_est, f_est, phase_est}; + } }; // Register hook static char n[] = "pmu_dft"; static char d[] = "This hook calculates the dft on a window"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/pmu_ipdft.cpp b/lib/hooks/pmu_ipdft.cpp index 3faee9649..38ec4a7e4 100644 --- a/lib/hooks/pmu_ipdft.cpp +++ b/lib/hooks/pmu_ipdft.cpp @@ -13,146 +13,152 @@ namespace node { class IpDftPmuHook : public PmuHook { protected: - std::complex omega; - std::vector>> dftMatrix; - std::vector> dftResult; + std::complex omega; + std::vector>> dftMatrix; + std::vector> dftResult; - unsigned frequencyCount; // Number of requency bins that are calculated - double estimationRange; // The range around nominalFreq used for estimation + unsigned frequencyCount; // Number of requency bins that are calculated + double estimationRange; // The range around nominalFreq used for estimation public: - IpDftPmuHook(Path *p, Node *n, int fl, int prio, bool en = true): - PmuHook(p, n, fl, prio, en), - frequencyCount(0), - estimationRange(0) + IpDftPmuHook(Path *p, Node *n, int fl, int prio, bool en = true) + : PmuHook(p, n, fl, prio, en), frequencyCount(0), estimationRange(0) - { } + {} - void prepare() - { - PmuHook::prepare(); + void prepare() { + PmuHook::prepare(); - const double startFrequency = nominalFreq - estimationRange; - const double endFrequency = nominalFreq + estimationRange; - const double frequencyResolution = (double)sampleRate / windowSize; + const double startFrequency = nominalFreq - estimationRange; + const double endFrequency = nominalFreq + estimationRange; + const double frequencyResolution = (double)sampleRate / windowSize; - frequencyCount = ceil((endFrequency - startFrequency) / frequencyResolution); + frequencyCount = + ceil((endFrequency - startFrequency) / frequencyResolution); - // Initialize matrix of dft coeffients - dftMatrix.clear(); - for (unsigned i = 0; i < frequencyCount; i++) - dftMatrix.emplace_back(windowSize, 0.0); + // Initialize matrix of dft coeffients + dftMatrix.clear(); + for (unsigned i = 0; i < frequencyCount; i++) + dftMatrix.emplace_back(windowSize, 0.0); - using namespace std::complex_literals; + using namespace std::complex_literals; - omega = exp((-2i * M_PI) / (double)(windowSize)); - unsigned startBin = floor(startFrequency / frequencyResolution); + omega = exp((-2i * M_PI) / (double)(windowSize)); + unsigned startBin = floor(startFrequency / frequencyResolution); - for (unsigned i = 0; i < frequencyCount ; i++) { - for (unsigned j = 0 ; j < windowSize; j++) - dftMatrix[i][j] = pow(omega, (i + startBin) * j); - dftResult.push_back(0.0); - } - } + for (unsigned i = 0; i < frequencyCount; i++) { + for (unsigned j = 0; j < windowSize; j++) + dftMatrix[i][j] = pow(omega, (i + startBin) * j); + dftResult.push_back(0.0); + } + } - void parse(json_t *json) - { - PmuHook::parse(json); - int ret; + void parse(json_t *json) { + PmuHook::parse(json); + int ret; - json_error_t err; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: F}", - "estimation_range", &estimationRange - ); + ret = json_unpack_ex(json, &err, 0, "{ s?: F}", "estimation_range", + &estimationRange); - if (ret) - throw ConfigError(json, err, "node-config-hook-ip-dft-pmu"); + if (ret) + throw ConfigError(json, err, "node-config-hook-ip-dft-pmu"); - if (estimationRange <= 0) - throw ConfigError(json, "node-config-hook-ip-dft-pmu-estimation_range", "Estimation range cannot be less or equal than 0 tried to set {}", estimationRange); + if (estimationRange <= 0) + throw ConfigError( + json, "node-config-hook-ip-dft-pmu-estimation_range", + "Estimation range cannot be less or equal than 0 tried to set {}", + estimationRange); + } - } + PmuHook::Phasor estimatePhasor(dsp::CosineWindow *window, + PmuHook::Phasor lastPhasor) { + PmuHook::Phasor phasor = {0}; - PmuHook::Phasor estimatePhasor(dsp::CosineWindow *window, PmuHook::Phasor lastPhasor) - { - PmuHook::Phasor phasor = {0}; + // Calculate DFT + for (unsigned i = 0; i < frequencyCount; i++) { + dftResult[i] = 0; - // Calculate DFT - for (unsigned i = 0; i < frequencyCount; i++) { - dftResult[i] = 0; + const unsigned size = (*window).size(); + for (unsigned j = 0; j < size; j++) + dftResult[i] += (*window)[j] * dftMatrix[i][j]; + } + // End calculate DFT - const unsigned size = (*window).size(); - for (unsigned j = 0; j < size; j++) - dftResult[i] += (*window)[j] * dftMatrix[i][j]; - } - // End calculate DFT + // Find max bin + unsigned maxBin = 0; + double absAmplitude = 0; - // Find max bin - unsigned maxBin = 0; - double absAmplitude = 0; + for (unsigned j = 0; j < frequencyCount; j++) { + if (absAmplitude < abs(dftResult[j])) { + absAmplitude = abs(dftResult[j]); + maxBin = j; + } + } + // End find max bin - for(unsigned j = 0; j < frequencyCount; j++) { - if (absAmplitude < abs(dftResult[j])) { - absAmplitude = abs(dftResult[j]); - maxBin = j; - } - } - // End find max bin + if (maxBin == 0 || maxBin == (frequencyCount - 1)) { + logger->warn("Maximum frequency bin lies on window boundary. Using " + "non-estimated results!"); + //TODO: add handling to not forward this phasor!! + } else { + const double startFrequency = nominalFreq - estimationRange; + const double frequencyResolution = (double)sampleRate / windowSize; - if (maxBin == 0 || maxBin == (frequencyCount - 1)) { - logger->warn("Maximum frequency bin lies on window boundary. Using non-estimated results!"); - //TODO: add handling to not forward this phasor!! - } else { - const double startFrequency = nominalFreq - estimationRange; - const double frequencyResolution = (double)sampleRate / windowSize; + double a = abs(dftResult[maxBin - 1]); + double b = abs(dftResult[maxBin + 0]); + double c = abs(dftResult[maxBin + 1]); + double bPhase = atan2(dftResult[maxBin].imag(), dftResult[maxBin].real()); - double a = abs(dftResult[ maxBin - 1 ]); - double b = abs(dftResult[ maxBin + 0 ]); - double c = abs(dftResult[ maxBin + 1 ]); - double bPhase = atan2(dftResult[maxBin].imag(), dftResult[maxBin].real()); + // Estimate phasor + // Based on https://ieeexplore.ieee.org/document/7980868 + double delta = 0; - // Estimate phasor - // Based on https://ieeexplore.ieee.org/document/7980868 - double delta = 0; + // Paper eq 8 + if (c > a) { + delta = 1. * (2. * c - b) / (b + c); + } else { + delta = -1. * (2. * a - b) / (b + a); + } - // Paper eq 8 - if (c > a) { - delta = 1. * (2. * c - b) / (b + c); - } else { - delta = -1. * (2. * a - b) / (b + a); - } + // Frequency estimation (eq 4) + phasor.frequency = + startFrequency + ((double)maxBin + delta) * frequencyResolution; - // Frequency estimation (eq 4) - phasor.frequency = startFrequency + ( (double) maxBin + delta) * frequencyResolution; + // Amplitude estimation (eq 9) + phasor.amplitude = + b * abs((M_PI * delta) / sin(M_PI * delta)) * abs(pow(delta, 2) - 1); + phasor.amplitude *= 2 / (windowSize * window->getCorrectionFactor()); - // Amplitude estimation (eq 9) - phasor.amplitude = b * abs( (M_PI * delta) / sin( M_PI * delta) ) * abs( pow(delta, 2) - 1); - phasor.amplitude *= 2 / (windowSize * window->getCorrectionFactor()); + // Phase estimation (eq 10) + phasor.phase = bPhase - M_PI * delta; - // Phase estimation (eq 10) - phasor.phase = bPhase - M_PI * delta; + // ROCOF estimation + phasor.rocof = + ((phasor.frequency - lastPhasor.frequency) * (double)phasorRate); + // End estimate phasor + } - // ROCOF estimation - phasor.rocof = ((phasor.frequency - lastPhasor.frequency) * (double)phasorRate); - // End estimate phasor - } + if (lastPhasor.frequency != + 0) // Check if we already calculated a phasor before + phasor.valid = Status::VALID; - if (lastPhasor.frequency != 0) // Check if we already calculated a phasor before - phasor.valid = Status::VALID; - - return phasor; - } + return phasor; + } }; // Register hook static char n[] = "ip-dft-pmu"; static char d[] = "This hook calculates a phasor based on ipDFT"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/power.cpp b/lib/hooks/power.cpp index 6716f8262..2862a9e5d 100644 --- a/lib/hooks/power.cpp +++ b/lib/hooks/power.cpp @@ -22,315 +22,320 @@ namespace node { class PowerHook : public MultiSignalHook { protected: - enum class TimeAlign { - LEFT, - CENTER, - RIGHT, - }; + enum class TimeAlign { + LEFT, + CENTER, + RIGHT, + }; - struct PowerPairing { - int voltageIndex; - int currentIndex; - }; + struct PowerPairing { + int voltageIndex; + int currentIndex; + }; - struct PairingsStr { - std::string voltage; - std::string current; - }; + struct PairingsStr { + std::string voltage; + std::string current; + }; - std::vector pairingsStr; - std::vector> smpMemory; - std::vector pairings; - std::vector smpMemoryTs; + std::vector pairingsStr; + std::vector> smpMemory; + std::vector pairings; + std::vector smpMemoryTs; - std::vector accumulator_u; // Integral over u - std::vector accumulator_i; // Integral over I - std::vector accumulator_ui; // Integral over U*I + std::vector accumulator_u; // Integral over u + std::vector accumulator_i; // Integral over I + std::vector accumulator_ui; // Integral over U*I - unsigned windowSize; - uint64_t smpMemoryPosition; - bool calcActivePower; - bool calcReactivePower; - bool caclApparentPower; - bool calcCosPhi; - bool channelNameEnable; // Rename the output values with channel name or only descriptive name - double angleUnitFactor; - enum TimeAlign timeAlignType; + unsigned windowSize; + uint64_t smpMemoryPosition; + bool calcActivePower; + bool calcReactivePower; + bool caclApparentPower; + bool calcCosPhi; + bool + channelNameEnable; // Rename the output values with channel name or only descriptive name + double angleUnitFactor; + enum TimeAlign timeAlignType; public: - PowerHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - smpMemory(), - pairings(), - smpMemoryTs(), - windowSize(0), - smpMemoryPosition(0), - calcActivePower(true), - calcReactivePower(true), - caclApparentPower(true), - calcCosPhi(true), - channelNameEnable(false), - angleUnitFactor(1), - timeAlignType(TimeAlign::CENTER) - { } + PowerHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), smpMemory(), pairings(), + smpMemoryTs(), windowSize(0), smpMemoryPosition(0), + calcActivePower(true), calcReactivePower(true), caclApparentPower(true), + calcCosPhi(true), channelNameEnable(false), angleUnitFactor(1), + timeAlignType(TimeAlign::CENTER) {} - virtual - void prepare() - { - MultiSignalHook::prepare(); + virtual void prepare() { + MultiSignalHook::prepare(); - for (unsigned i = 0; i < pairingsStr.size(); i++) { - PowerPairing p = {.voltageIndex = signals->getIndexByName(pairingsStr[i].voltage), .currentIndex = signals->getIndexByName(pairingsStr[i].current)}; + for (unsigned i = 0; i < pairingsStr.size(); i++) { + PowerPairing p = { + .voltageIndex = signals->getIndexByName(pairingsStr[i].voltage), + .currentIndex = signals->getIndexByName(pairingsStr[i].current)}; - if (p.currentIndex == -1) - throw RuntimeError("Pairings signal name not recognized {}", pairingsStr[i].current); - if (p.voltageIndex == -1) - throw RuntimeError("Pairings signal name not recognized {}", pairingsStr[i].voltage); + if (p.currentIndex == -1) + throw RuntimeError("Pairings signal name not recognized {}", + pairingsStr[i].current); + if (p.voltageIndex == -1) + throw RuntimeError("Pairings signal name not recognized {}", + pairingsStr[i].voltage); - pairings.push_back(p); - } + pairings.push_back(p); + } - if ((pairingsStr.size() * 2) != signalIndices.size()) - throw RuntimeError("Number of signals and parings don not match!"); + if ((pairingsStr.size() * 2) != signalIndices.size()) + throw RuntimeError("Number of signals and parings don not match!"); - // Check Signal Data Type - for (auto index : signalIndices) { - auto origSig = signals->getByIndex(index); + // Check Signal Data Type + for (auto index : signalIndices) { + auto origSig = signals->getByIndex(index); - // Check that signal has float type - if (origSig->type != SignalType::FLOAT) - throw RuntimeError("The power hook can only operate on signals of type float!"); - } + // Check that signal has float type + if (origSig->type != SignalType::FLOAT) + throw RuntimeError( + "The power hook can only operate on signals of type float!"); + } - signals->clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) { - std::string suffix = ""; - if (channelNameEnable) - suffix = fmt::format("_{}", signalNames[i]); + signals->clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + std::string suffix = ""; + if (channelNameEnable) + suffix = fmt::format("_{}", signalNames[i]); - // Add signals - if (calcActivePower) { - auto activeSig = std::make_shared("active", "W", SignalType::FLOAT); - activeSig->name += suffix; - if (!activeSig) - throw RuntimeError("Failed to create new signals"); - signals->push_back(activeSig); - } + // Add signals + if (calcActivePower) { + auto activeSig = + std::make_shared("active", "W", SignalType::FLOAT); + activeSig->name += suffix; + if (!activeSig) + throw RuntimeError("Failed to create new signals"); + signals->push_back(activeSig); + } - if (calcReactivePower) { - auto reactiveSig = std::make_shared("reactive", "Var", SignalType::FLOAT); - reactiveSig->name += suffix; - if (!reactiveSig) - throw RuntimeError("Failed to create new signals"); - signals->push_back(reactiveSig); - } + if (calcReactivePower) { + auto reactiveSig = + std::make_shared("reactive", "Var", SignalType::FLOAT); + reactiveSig->name += suffix; + if (!reactiveSig) + throw RuntimeError("Failed to create new signals"); + signals->push_back(reactiveSig); + } - if (caclApparentPower) { - auto apparentSig = std::make_shared("apparent", "VA", SignalType::FLOAT); - apparentSig->name += suffix; - if (!apparentSig) - throw RuntimeError("Failed to create new signals"); - signals->push_back(apparentSig); - } + if (caclApparentPower) { + auto apparentSig = + std::make_shared("apparent", "VA", SignalType::FLOAT); + apparentSig->name += suffix; + if (!apparentSig) + throw RuntimeError("Failed to create new signals"); + signals->push_back(apparentSig); + } - if (calcCosPhi) { - auto cosPhiSig = std::make_shared("cos_phi", "deg", SignalType::FLOAT); - cosPhiSig->name += suffix; - if (!cosPhiSig) - throw RuntimeError("Failed to create new signals"); - signals->push_back(cosPhiSig); - } - } + if (calcCosPhi) { + auto cosPhiSig = + std::make_shared("cos_phi", "deg", SignalType::FLOAT); + cosPhiSig->name += suffix; + if (!cosPhiSig) + throw RuntimeError("Failed to create new signals"); + signals->push_back(cosPhiSig); + } + } - // Initialize sampMemory to 0 - smpMemory.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++) - smpMemory.emplace_back(windowSize, 0.0); + // Initialize sampMemory to 0 + smpMemory.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) + smpMemory.emplace_back(windowSize, 0.0); - smpMemoryTs.clear(); - for (unsigned i = 0; i < windowSize; i++) - smpMemoryTs.push_back({0}); + smpMemoryTs.clear(); + for (unsigned i = 0; i < windowSize; i++) + smpMemoryTs.push_back({0}); - // Init empty accumulators for each pairing - for (size_t i = 0; i < pairings.size(); i++) { - accumulator_i.push_back(0.0); - accumulator_u.push_back(0.0); - accumulator_ui.push_back(0.0); - } + // Init empty accumulators for each pairing + for (size_t i = 0; i < pairings.size(); i++) { + accumulator_i.push_back(0.0); + accumulator_u.push_back(0.0); + accumulator_ui.push_back(0.0); + } - // Signal state prepared - state = State::PREPARED; - } + // Signal state prepared + state = State::PREPARED; + } - // Read configuration JSON and configure hook accordingly - virtual - void parse(json_t *json) - { - // Ensure hook is not yet running - assert(state != State::STARTED); + // Read configuration JSON and configure hook accordingly + virtual void parse(json_t *json) { + // Ensure hook is not yet running + assert(state != State::STARTED); - int result = 0; + int result = 0; - const char *timeAlignC = nullptr; - const char *angleUnitC = nullptr; + const char *timeAlignC = nullptr; + const char *angleUnitC = nullptr; - json_error_t json_error; + json_error_t json_error; - int windowSizeIn = 0; // Size of window in samples + int windowSizeIn = 0; // Size of window in samples - json_t *json_pairings = nullptr; + json_t *json_pairings = nullptr; - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - result = json_unpack_ex(json, &json_error, 0, "{ s: i , s: o, s?: b, s?: b, s?: b, s?: b, s?: b, s? : s, s? : s }", - "window_size", &windowSizeIn, - "pairings", &json_pairings, - "add_channel_name", &channelNameEnable, - "active_power", &calcActivePower, - "reactive_power", &calcReactivePower, - "apparent_power", &caclApparentPower, - "cos_phi", &calcCosPhi, - "timestamp_align", &timeAlignC, - "angle_unit", &angleUnitC - ); + result = json_unpack_ex( + json, &json_error, 0, + "{ s: i , s: o, s?: b, s?: b, s?: b, s?: b, s?: b, s? : s, s? : s }", + "window_size", &windowSizeIn, "pairings", &json_pairings, + "add_channel_name", &channelNameEnable, "active_power", + &calcActivePower, "reactive_power", &calcReactivePower, + "apparent_power", &caclApparentPower, "cos_phi", &calcCosPhi, + "timestamp_align", &timeAlignC, "angle_unit", &angleUnitC); - if (result) - throw ConfigError(json, json_error, "node-config-hook-power"); + if (result) + throw ConfigError(json, json_error, "node-config-hook-power"); - if (windowSizeIn < 1) - throw ConfigError(json, "node-config-hook-power", "Window size must be greater 0 but is set to {}", windowSizeIn); + if (windowSizeIn < 1) + throw ConfigError(json, "node-config-hook-power", + "Window size must be greater 0 but is set to {}", + windowSizeIn); - windowSize = (unsigned)windowSizeIn; + windowSize = (unsigned)windowSizeIn; - if (!timeAlignC) - logger->info("No timestamp alignment defined. Assume alignment center"); - else if (strcmp(timeAlignC, "left") == 0) - timeAlignType = TimeAlign::LEFT; - else if (strcmp(timeAlignC, "center") == 0) - timeAlignType = TimeAlign::CENTER; - else if (strcmp(timeAlignC, "right") == 0) - timeAlignType = TimeAlign::RIGHT; - else - throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", "Timestamp alignment {} not recognized", timeAlignC); + if (!timeAlignC) + logger->info("No timestamp alignment defined. Assume alignment center"); + else if (strcmp(timeAlignC, "left") == 0) + timeAlignType = TimeAlign::LEFT; + else if (strcmp(timeAlignC, "center") == 0) + timeAlignType = TimeAlign::CENTER; + else if (strcmp(timeAlignC, "right") == 0) + timeAlignType = TimeAlign::RIGHT; + else + throw ConfigError(json, "node-config-hook-dft-timestamp-alignment", + "Timestamp alignment {} not recognized", timeAlignC); - if (!angleUnitC) - logger->info("No angle type given, assume rad"); - else if (strcmp(angleUnitC, "rad") == 0) - angleUnitFactor = 1; - else if (strcmp(angleUnitC, "degree") == 0) - angleUnitFactor = 180 / M_PI; - else - throw ConfigError(json, "node-config-hook-dft-angle-unit", "Angle unit {} not recognized", angleUnitC); + if (!angleUnitC) + logger->info("No angle type given, assume rad"); + else if (strcmp(angleUnitC, "rad") == 0) + angleUnitFactor = 1; + else if (strcmp(angleUnitC, "degree") == 0) + angleUnitFactor = 180 / M_PI; + else + throw ConfigError(json, "node-config-hook-dft-angle-unit", + "Angle unit {} not recognized", angleUnitC); - // Pairings - if (!json_is_array(json_pairings)) - throw ConfigError(json_pairings, "node-config-hook-power", "Pairings are expected as json array"); + // Pairings + if (!json_is_array(json_pairings)) + throw ConfigError(json_pairings, "node-config-hook-power", + "Pairings are expected as json array"); - size_t i = 0; - json_t *json_pairings_value; - json_array_foreach(json_pairings, i, json_pairings_value) { - const char *voltageNameC = nullptr; - const char *currentNameC = nullptr; + size_t i = 0; + json_t *json_pairings_value; + json_array_foreach(json_pairings, i, json_pairings_value) { + const char *voltageNameC = nullptr; + const char *currentNameC = nullptr; - json_unpack_ex(json_pairings_value, &json_error, 0, "{ s: s, s: s}", - "voltage", &voltageNameC, - "current", ¤tNameC - ); - pairingsStr.push_back((PairingsStr){ .voltage = voltageNameC, .current = currentNameC}); + json_unpack_ex(json_pairings_value, &json_error, 0, "{ s: s, s: s}", + "voltage", &voltageNameC, "current", ¤tNameC); + pairingsStr.push_back( + (PairingsStr){.voltage = voltageNameC, .current = currentNameC}); + } - } + state = State::PARSED; + } - state = State::PARSED; - } + // This function does the actual processing of the hook when a new sample is passed through. + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - // This function does the actual processing of the hook when a new sample is passed through. - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + uint sigIndex = 0; //used to set the pos of value in output sampel array - uint sigIndex = 0; //used to set the pos of value in output sampel array + smpMemoryTs[smpMemoryPosition % windowSize] = smp->ts.origin; - smpMemoryTs[smpMemoryPosition % windowSize] = smp->ts.origin; + // Loop over all pairings + for (size_t i = 0; i < pairings.size(); i++) { + auto pair = pairings[i]; - // Loop over all pairings - for (size_t i = 0; i < pairings.size(); i++) { - auto pair = pairings[i]; + // Update U integral + double oldValueU = + smpMemory[pair.voltageIndex][smpMemoryPosition % windowSize]; + double newValueU = smp->data[pair.voltageIndex].f; + smpMemory[pair.voltageIndex][smpMemoryPosition % windowSize] = + newValueU; // Save for later - // Update U integral - double oldValueU = smpMemory[pair.voltageIndex][smpMemoryPosition % windowSize]; - double newValueU = smp->data[pair.voltageIndex].f; - smpMemory[pair.voltageIndex][smpMemoryPosition % windowSize] = newValueU; // Save for later + accumulator_u[i] -= oldValueU * oldValueU; + accumulator_u[i] += newValueU * newValueU; - accumulator_u[i] -= oldValueU * oldValueU; - accumulator_u[i] += newValueU * newValueU; + // Update I integral + double newValueI = smp->data[pair.currentIndex].f; + double oldValueI = + smpMemory[pair.currentIndex][smpMemoryPosition % windowSize]; + smpMemory[pair.currentIndex][smpMemoryPosition % windowSize] = + newValueI; // Save for later - // Update I integral - double newValueI = smp->data[pair.currentIndex].f; - double oldValueI = smpMemory[pair.currentIndex][smpMemoryPosition % windowSize]; - smpMemory[pair.currentIndex][smpMemoryPosition % windowSize] = newValueI; // Save for later + accumulator_i[i] -= oldValueI * oldValueI; + accumulator_i[i] += newValueI * newValueI; - accumulator_i[i] -= oldValueI * oldValueI; - accumulator_i[i] += newValueI * newValueI; + // Update UI Integral + accumulator_ui[i] -= oldValueI * oldValueU; + accumulator_ui[i] += newValueI * newValueU; - // Update UI Integral - accumulator_ui[i] -= oldValueI * oldValueU; - accumulator_ui[i] += newValueI * newValueU; + // Calc active power power + double P = (1.0 / windowSize) * accumulator_ui[i]; - // Calc active power power - double P = (1.0 / windowSize) * accumulator_ui[i]; + // Calc apparent power + double S = + (1.0 / windowSize) * pow(accumulator_i[i] * accumulator_u[i], 0.5); - // Calc apparent power - double S = (1.0 / windowSize) * pow(accumulator_i[i] * accumulator_u[i], 0.5); + // Calc reactive power + double Q = pow(S * S - P * P, 0.5); - // Calc reactive power - double Q = pow(S * S - P * P, 0.5); + // Calc cos phi + double PHI = atan2(Q, P) * angleUnitFactor; - // Calc cos phi - double PHI = atan2(Q, P) * angleUnitFactor; + if (smpMemoryPosition >= windowSize) { + // Write to samples + if (calcActivePower) + smp->data[sigIndex++].f = P; + if (calcReactivePower) + smp->data[sigIndex++].f = Q; + if (caclApparentPower) + smp->data[sigIndex++].f = S; + if (calcCosPhi) + smp->data[sigIndex++].f = PHI; + } + } - if (smpMemoryPosition >= windowSize) { - // Write to samples - if(calcActivePower) - smp->data[sigIndex++].f = P; - if(calcReactivePower) - smp->data[sigIndex++].f = Q; - if(caclApparentPower) - smp->data[sigIndex++].f = S; - if(calcCosPhi) - smp->data[sigIndex++].f = PHI; - } - } + smp->length = sigIndex; - smp->length = sigIndex; + if (smpMemoryPosition >= windowSize) { + unsigned tsPos = 0; + if (timeAlignType == TimeAlign::RIGHT) + tsPos = smpMemoryPosition; + else if (timeAlignType == TimeAlign::LEFT) + tsPos = smpMemoryPosition - windowSize; + else if (timeAlignType == TimeAlign::CENTER) + tsPos = smpMemoryPosition - (windowSize / 2); - if (smpMemoryPosition >= windowSize) { - unsigned tsPos = 0; - if (timeAlignType == TimeAlign::RIGHT) - tsPos = smpMemoryPosition; - else if (timeAlignType == TimeAlign::LEFT) - tsPos = smpMemoryPosition - windowSize; - else if (timeAlignType == TimeAlign::CENTER) - tsPos = smpMemoryPosition - (windowSize / 2); + smp->ts.origin = smpMemoryTs[tsPos % windowSize]; + } - smp->ts.origin = smpMemoryTs[tsPos % windowSize]; - } + if (smpMemoryPosition >= + 2 * windowSize) //reset smpMemPos if greater than twice the window. Important to handle init + smpMemoryPosition = windowSize; - if (smpMemoryPosition >= 2 * windowSize) //reset smpMemPos if greater than twice the window. Important to handle init - smpMemoryPosition = windowSize; + smpMemoryPosition++; // Move write head for sample history foreward by one + if (windowSize < smpMemoryPosition) + return Reason::OK; - smpMemoryPosition++; // Move write head for sample history foreward by one - if (windowSize < smpMemoryPosition) - return Reason::OK; - - return Reason::SKIP_SAMPLE; - } + return Reason::SKIP_SAMPLE; + } }; // Register hook static char n[] = "power"; -static char d[] = "This hook calculates the Active and Reactive Power for a given signal "; -static HookPlugin p; +static char d[] = + "This hook calculates the Active and Reactive Power for a given signal "; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/pps_ts.cpp b/lib/hooks/pps_ts.cpp index 33084ffa6..a43010bdf 100644 --- a/lib/hooks/pps_ts.cpp +++ b/lib/hooks/pps_ts.cpp @@ -9,8 +9,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -18,211 +18,204 @@ namespace node { class PpsTsHook : public SingleSignalHook { protected: - enum Mode { - SIMPLE, - HORIZON, - } mode; + enum Mode { + SIMPLE, + HORIZON, + } mode; - uint64_t lastSequence; + uint64_t lastSequence; - double lastValue; - double threshold; + double lastValue; + double threshold; - bool isSynced; - bool isLocked; - struct timespec tsVirt; - double timeError; // In seconds - double periodEstimate; // In seconds - double periodErrorCompensation; // In seconds - double period; // In seconds - uintmax_t cntEdges; - uintmax_t cntSmps; - uintmax_t cntSmpsTotal; - unsigned horizonCompensation; - unsigned horizonEstimation; - unsigned currentSecond; - std::vector filterWindow; + bool isSynced; + bool isLocked; + struct timespec tsVirt; + double timeError; // In seconds + double periodEstimate; // In seconds + double periodErrorCompensation; // In seconds + double period; // In seconds + uintmax_t cntEdges; + uintmax_t cntSmps; + uintmax_t cntSmpsTotal; + unsigned horizonCompensation; + unsigned horizonEstimation; + unsigned currentSecond; + std::vector filterWindow; public: - PpsTsHook(Path *p, Node *n, int fl, int prio, bool en = true) : - SingleSignalHook(p, n, fl, prio, en), - mode(Mode::SIMPLE), - lastSequence(0), - lastValue(0), - threshold(1.5), - isSynced(false), - isLocked(false), - timeError(0.0), - periodEstimate(0.0), - periodErrorCompensation(0.0), - period(0.0), - cntEdges(0), - cntSmps(0), - cntSmpsTotal(0), - horizonCompensation(10), - horizonEstimation(10), - currentSecond(0), - filterWindow(horizonEstimation + 1, 0) - { } + PpsTsHook(Path *p, Node *n, int fl, int prio, bool en = true) + : SingleSignalHook(p, n, fl, prio, en), mode(Mode::SIMPLE), + lastSequence(0), lastValue(0), threshold(1.5), isSynced(false), + isLocked(false), timeError(0.0), periodEstimate(0.0), + periodErrorCompensation(0.0), period(0.0), cntEdges(0), cntSmps(0), + cntSmpsTotal(0), horizonCompensation(10), horizonEstimation(10), + currentSecond(0), filterWindow(horizonEstimation + 1, 0) {} - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - SingleSignalHook::parse(json); + SingleSignalHook::parse(json); - const char *mode_str = nullptr; + const char *mode_str = nullptr; - double fSmps = 1.0; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: f, s?: F, s?: i, s?: i }", - "mode", &mode_str, - "threshold", &threshold, - "expected_smp_rate", &fSmps, - "horizon_estimation", &horizonEstimation, - "horizon_compensation", &horizonCompensation - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-pps_ts"); + double fSmps = 1.0; + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: f, s?: F, s?: i, s?: i }", + "mode", &mode_str, "threshold", &threshold, + "expected_smp_rate", &fSmps, "horizon_estimation", + &horizonEstimation, "horizon_compensation", + &horizonCompensation); + if (ret) + throw ConfigError(json, err, "node-config-hook-pps_ts"); - period = 1.0 / fSmps; - currentSecond = time(nullptr); + period = 1.0 / fSmps; + currentSecond = time(nullptr); - if (mode_str) { - if (!strcmp(mode_str, "simple")) - mode = Mode::SIMPLE; - else if (!strcmp(mode_str, "horizon")) - mode = Mode::HORIZON; - else - throw ConfigError(json, "node-config-hook-pps_ts-mode", "Unsupported mode: {}", mode_str); - } + if (mode_str) { + if (!strcmp(mode_str, "simple")) + mode = Mode::SIMPLE; + else if (!strcmp(mode_str, "horizon")) + mode = Mode::HORIZON; + else + throw ConfigError(json, "node-config-hook-pps_ts-mode", + "Unsupported mode: {}", mode_str); + } - state = State::PARSED; - } + state = State::PARSED; + } - virtual - villas::node::Hook::Reason process(struct Sample *smp) - { - switch (mode) { - case Mode::SIMPLE: - return processSimple(smp); + virtual villas::node::Hook::Reason process(struct Sample *smp) { + switch (mode) { + case Mode::SIMPLE: + return processSimple(smp); - case Mode::HORIZON: - return processHorizon(smp); + case Mode::HORIZON: + return processHorizon(smp); - default: - return Reason::ERROR; - } - } + default: + return Reason::ERROR; + } + } - villas::node::Hook::Reason processSimple(struct Sample *smp) - { - assert(state == State::STARTED); + villas::node::Hook::Reason processSimple(struct Sample *smp) { + assert(state == State::STARTED); - // Get value of PPS signal - float value = smp->data[signalIndex].f; // TODO check if it is really float + // Get value of PPS signal + float value = smp->data[signalIndex].f; // TODO check if it is really float - // Detect Edge - bool isEdge = lastValue < threshold && value > threshold; - if (isEdge) { - tsVirt.tv_sec = currentSecond + 1; - tsVirt.tv_nsec = 0; - period = 1.0 / cntSmps; - cntSmps = 0; - cntEdges++; - currentSecond = 0; - } else { - struct timespec tsPeriod = time_from_double(period); - tsVirt = time_add(&tsVirt, &tsPeriod); - } + // Detect Edge + bool isEdge = lastValue < threshold && value > threshold; + if (isEdge) { + tsVirt.tv_sec = currentSecond + 1; + tsVirt.tv_nsec = 0; + period = 1.0 / cntSmps; + cntSmps = 0; + cntEdges++; + currentSecond = 0; + } else { + struct timespec tsPeriod = time_from_double(period); + tsVirt = time_add(&tsVirt, &tsPeriod); + } - lastValue = value; - cntSmps++; + lastValue = value; + cntSmps++; - if (!currentSecond && tsVirt.tv_nsec > 0.5e9)//take the second somewere in the center of the last second to reduce impact of system clock error - currentSecond = time(nullptr); + if (!currentSecond && + tsVirt.tv_nsec > + 0.5e9) //take the second somewere in the center of the last second to reduce impact of system clock error + currentSecond = time(nullptr); - if (cntEdges < 5) - return Hook::Reason::SKIP_SAMPLE; + if (cntEdges < 5) + return Hook::Reason::SKIP_SAMPLE; - smp->ts.origin = tsVirt; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; + smp->ts.origin = tsVirt; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; - if ((smp->sequence - lastSequence) > 1) - logger->warn("Samples missed: {} sampled missed", smp->sequence - lastSequence); + if ((smp->sequence - lastSequence) > 1) + logger->warn("Samples missed: {} sampled missed", + smp->sequence - lastSequence); - lastSequence = smp->sequence; - return Hook::Reason::OK; - } + lastSequence = smp->sequence; + return Hook::Reason::OK; + } - villas::node::Hook::Reason processHorizon(struct Sample *smp) - { - assert(state == State::STARTED); + villas::node::Hook::Reason processHorizon(struct Sample *smp) { + assert(state == State::STARTED); - // Get value of PPS signal - float value = smp->data[signalIndex].f; // TODO check if it is really float + // Get value of PPS signal + float value = smp->data[signalIndex].f; // TODO check if it is really float - // Detect Edge - bool isEdge = lastValue < threshold && value > threshold; + // Detect Edge + bool isEdge = lastValue < threshold && value > threshold; - lastValue = value; + lastValue = value; - if (isEdge) { - if (isSynced) { - if(tsVirt.tv_nsec > 0.5e9) - timeError += 1.0 - (tsVirt.tv_nsec / 1.0e9); - else - timeError -= (tsVirt.tv_nsec / 1.0e9); + if (isEdge) { + if (isSynced) { + if (tsVirt.tv_nsec > 0.5e9) + timeError += 1.0 - (tsVirt.tv_nsec / 1.0e9); + else + timeError -= (tsVirt.tv_nsec / 1.0e9); - filterWindow[cntEdges % filterWindow.size()] = cntSmpsTotal; - // Estimated sample period over last 'horizonEstimation' seconds - unsigned int tmp = cntEdges < filterWindow.size() ? cntEdges : horizonEstimation; - double cntSmpsAvg = (cntSmpsTotal - filterWindow[(cntEdges - tmp) % filterWindow.size()]) / tmp; - periodEstimate = 1.0 / cntSmpsAvg; - periodErrorCompensation = timeError / (cntSmpsAvg * horizonCompensation); - period = periodEstimate + periodErrorCompensation; - } - else { - tsVirt.tv_sec = time(nullptr); - tsVirt.tv_nsec = 0; - isSynced = true; - cntEdges = 0; - cntSmpsTotal = 0; - } - cntSmps = 0; - cntEdges++; + filterWindow[cntEdges % filterWindow.size()] = cntSmpsTotal; + // Estimated sample period over last 'horizonEstimation' seconds + unsigned int tmp = + cntEdges < filterWindow.size() ? cntEdges : horizonEstimation; + double cntSmpsAvg = + (cntSmpsTotal - + filterWindow[(cntEdges - tmp) % filterWindow.size()]) / + tmp; + periodEstimate = 1.0 / cntSmpsAvg; + periodErrorCompensation = + timeError / (cntSmpsAvg * horizonCompensation); + period = periodEstimate + periodErrorCompensation; + } else { + tsVirt.tv_sec = time(nullptr); + tsVirt.tv_nsec = 0; + isSynced = true; + cntEdges = 0; + cntSmpsTotal = 0; + } + cntSmps = 0; + cntEdges++; - logger->debug("Time Error is: {} periodEstimate {} periodErrorCompensation {}", timeError, periodEstimate, periodErrorCompensation); - } + logger->debug( + "Time Error is: {} periodEstimate {} periodErrorCompensation {}", + timeError, periodEstimate, periodErrorCompensation); + } - cntSmps++; - cntSmpsTotal++; + cntSmps++; + cntSmpsTotal++; - if (cntEdges < 5) - return Hook::Reason::SKIP_SAMPLE; + if (cntEdges < 5) + return Hook::Reason::SKIP_SAMPLE; - smp->ts.origin = tsVirt; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; + smp->ts.origin = tsVirt; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; - struct timespec tsPeriod = time_from_double(period); - tsVirt = time_add(&tsVirt, &tsPeriod); + struct timespec tsPeriod = time_from_double(period); + tsVirt = time_add(&tsVirt, &tsPeriod); - if ((smp->sequence - lastSequence) > 1) - logger->warn("Samples missed: {} sampled missed", smp->sequence - lastSequence); + if ((smp->sequence - lastSequence) > 1) + logger->warn("Samples missed: {} sampled missed", + smp->sequence - lastSequence); - lastSequence = smp->sequence; + lastSequence = smp->sequence; - return Hook::Reason::OK; - } + return Hook::Reason::OK; + } }; // Register hook static char n[] = "pps_ts"; static char d[] = "Timestamp samples based GPS PPS signal"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/print.cpp b/lib/hooks/print.cpp index d4c10e372..29b5553c6 100644 --- a/lib/hooks/print.cpp +++ b/lib/hooks/print.cpp @@ -8,11 +8,11 @@ #include #include -#include +#include #include +#include #include #include -#include namespace villas { namespace node { @@ -20,121 +20,109 @@ namespace node { class PrintHook : public Hook { protected: - Format::Ptr formatter; + Format::Ptr formatter; - std::string prefix; - std::string output_path; + std::string prefix; + std::string output_path; - FILE *output; - std::vector output_buffer; + FILE *output; + std::vector output_buffer; public: - PrintHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - output(nullptr) - { } + PrintHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), output(nullptr) {} - virtual - void start() - { - assert(state == State::PREPARED || - state == State::STOPPED); + virtual void start() { + assert(state == State::PREPARED || state == State::STOPPED); - if (!output_path.empty()) { - output = fopen(output_path.c_str(), "w+"); - if (!output) - throw SystemError("Failed to open file"); - } - else - output_buffer = std::vector(DEFAULT_FORMAT_BUFFER_LENGTH); + if (!output_path.empty()) { + output = fopen(output_path.c_str(), "w+"); + if (!output) + throw SystemError("Failed to open file"); + } else + output_buffer = std::vector(DEFAULT_FORMAT_BUFFER_LENGTH); - formatter->start(signals); + formatter->start(signals); - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() { - if (output) - fclose(output); - } + virtual void stop() { + if (output) + fclose(output); + } - virtual - void parse(json_t *json) - { - const char *p = nullptr; - const char *o = nullptr; - int ret; - json_error_t err; - json_t *json_format = nullptr; + virtual void parse(json_t *json) { + const char *p = nullptr; + const char *o = nullptr; + int ret; + json_error_t err; + json_t *json_format = nullptr; - assert(state == State::INITIALIZED || - state == State::CHECKED || - state == State::PARSED); + assert(state == State::INITIALIZED || state == State::CHECKED || + state == State::PARSED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s?: s }", - "prefix", &p, - "format", &json_format, - "output", &o - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-print"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s?: s }", "prefix", &p, + "format", &json_format, "output", &o); + if (ret) + throw ConfigError(json, err, "node-config-hook-print"); - if (p && o) { - throw ConfigError(json, "node-config-hook-print", "Prefix and output settings are exclusive."); - } + if (p && o) { + throw ConfigError(json, "node-config-hook-print", + "Prefix and output settings are exclusive."); + } - if (p) - prefix = p; + if (p) + prefix = p; - if (o) - output_path = o; + if (o) + output_path = o; - // Format - auto *fmt = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.human"); + // Format + auto *fmt = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.human"); - formatter = Format::Ptr(fmt); - if (!formatter) - throw ConfigError(json_format, "node-config-hook-print-format", "Invalid format configuration"); + formatter = Format::Ptr(fmt); + if (!formatter) + throw ConfigError(json_format, "node-config-hook-print-format", + "Invalid format configuration"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - if (!output) { - char *buf = output_buffer.data(); - size_t buflen = output_buffer.size(); - size_t wbytes; + if (!output) { + char *buf = output_buffer.data(); + size_t buflen = output_buffer.size(); + size_t wbytes; - formatter->sprint(buf, buflen, &wbytes, smp); + formatter->sprint(buf, buflen, &wbytes, smp); - if (wbytes > 0 && buf[wbytes-1] == '\n') - buf[wbytes-1] = 0; + if (wbytes > 0 && buf[wbytes - 1] == '\n') + buf[wbytes - 1] = 0; - if (node) - logger->info("{}{} {}", prefix, node->getName(), buf); - else if (path) - logger->info("{}{} {}", prefix, path->toString(), buf); - } - else - formatter->print(output, smp); + if (node) + logger->info("{}{} {}", prefix, node->getName(), buf); + else if (path) + logger->info("{}{} {}", prefix, path->toString(), buf); + } else + formatter->print(output, smp); - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "print"; static char d[] = "Print the message to stdout or a file"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/reorder_ts.cpp b/lib/hooks/reorder_ts.cpp index 1dbbd4481..38c43c79f 100644 --- a/lib/hooks/reorder_ts.cpp +++ b/lib/hooks/reorder_ts.cpp @@ -5,11 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include #include -#include #include #include @@ -21,140 +21,124 @@ namespace node { class ReorderTsHook : public Hook { protected: - std::vector window; - std::size_t window_size; - Sample *buffer; + std::vector window; + std::size_t window_size; + Sample *buffer; - void swapSample(Sample *lhs, Sample *rhs) - { - if (buffer) { - sample_copy(buffer, lhs); - sample_copy(lhs, rhs); - sample_copy(rhs, buffer); - } else { - buffer = sample_clone(lhs); - sample_copy(lhs, rhs); - sample_copy(rhs, buffer); - } - } + void swapSample(Sample *lhs, Sample *rhs) { + if (buffer) { + sample_copy(buffer, lhs); + sample_copy(lhs, rhs); + sample_copy(rhs, buffer); + } else { + buffer = sample_clone(lhs); + sample_copy(lhs, rhs); + sample_copy(rhs, buffer); + } + } public: - ReorderTsHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - window{}, - window_size(16), - buffer(nullptr) - { } + ReorderTsHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), window{}, window_size(16), buffer(nullptr) {} - virtual - void parse(json_t *json) - { - assert(state != State::STARTED); + virtual void parse(json_t *json) { + assert(state != State::STARTED); - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s?: i }", - "window_size", &window_size - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-reorder-ts"); + json_error_t err; + int ret = + json_unpack_ex(json, &err, 0, "{ s?: i }", "window_size", &window_size); + if (ret) + throw ConfigError(json, err, "node-config-hook-reorder-ts"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - void start() - { - assert(state == State::PREPARED || state == State::STOPPED); + virtual void start() { + assert(state == State::PREPARED || state == State::STOPPED); - window.reserve(window_size); + window.reserve(window_size); - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() - { - assert(state == State::STARTED); + virtual void stop() { + assert(state == State::STARTED); - for (auto sample : window) - sample_free(sample); + for (auto sample : window) + sample_free(sample); - if (buffer) - sample_free(buffer); + if (buffer) + sample_free(buffer); - window.clear(); + window.clear(); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - Hook::Reason process(Sample *smp) - { - assert(state == State::STARTED); - assert(smp); + virtual Hook::Reason process(Sample *smp) { + assert(state == State::STARTED); + assert(smp); - if (window.empty()) { - window.push_back(sample_clone(smp)); + if (window.empty()) { + window.push_back(sample_clone(smp)); - logger->debug("window.size={}/{}", window.size(), window_size); + logger->debug("window.size={}/{}", window.size(), window_size); - return Hook::Reason::SKIP_SAMPLE; - } + return Hook::Reason::SKIP_SAMPLE; + } - for (std::size_t i = window.size() - 1;; i--) { - if (time_cmp(&smp->ts.origin, &window[i]->ts.origin) >= 0) { - if (i != window.size() - 1) - logger->warn("Fixing reordered Sample"); + for (std::size_t i = window.size() - 1;; i--) { + if (time_cmp(&smp->ts.origin, &window[i]->ts.origin) >= 0) { + if (i != window.size() - 1) + logger->warn("Fixing reordered Sample"); - if (window.size() == window_size) { - Sample *window_sample = window.front(); - std::copy( - ++std::begin(window), - std::next(std::begin(window), i + 1), - std::begin(window)); - window[i] = window_sample; - swapSample(window_sample, smp); + if (window.size() == window_size) { + Sample *window_sample = window.front(); + std::copy(++std::begin(window), std::next(std::begin(window), i + 1), + std::begin(window)); + window[i] = window_sample; + swapSample(window_sample, smp); - return Hook::Reason::OK; - } else { - window.push_back(nullptr); - std::copy_backward( - std::next(std::begin(window), i + 1), - --std::end(window), - std::end(window)); - window[i + 1] = sample_clone(smp); + return Hook::Reason::OK; + } else { + window.push_back(nullptr); + std::copy_backward(std::next(std::begin(window), i + 1), + --std::end(window), std::end(window)); + window[i + 1] = sample_clone(smp); - logger->debug("window.size={}/{}", window.size(), window_size); + logger->debug("window.size={}/{}", window.size(), window_size); - return Hook::Reason::SKIP_SAMPLE; - } - } + return Hook::Reason::SKIP_SAMPLE; + } + } - if (!i) - break; - } + if (!i) + break; + } - logger->error("Could not reorder Sample"); + logger->error("Could not reorder Sample"); - return Hook::Reason::SKIP_SAMPLE; - } + return Hook::Reason::SKIP_SAMPLE; + } - virtual - void restart() - { - assert(state == State::STARTED); + virtual void restart() { + assert(state == State::STARTED); - for (auto sample : window) - sample_free(sample); + for (auto sample : window) + sample_free(sample); - window.clear(); - } + window.clear(); + } }; // Register hook static char n[] = "reorder_ts"; static char d[] = "Reorder messages by their timestamp"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/restart.cpp b/lib/hooks/restart.cpp index d0e07d7e4..216a932b1 100644 --- a/lib/hooks/restart.cpp +++ b/lib/hooks/restart.cpp @@ -17,68 +17,66 @@ namespace node { class RestartHook : public Hook { protected: - struct Sample *prev; + struct Sample *prev; public: - using Hook::Hook; + using Hook::Hook; - virtual - void start() - { - assert(state == State::PREPARED); + virtual void start() { + assert(state == State::PREPARED); - prev = nullptr; + prev = nullptr; - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() - { - assert(state == State::STARTED); + virtual void stop() { + assert(state == State::STARTED); - if (prev) - sample_decref(prev); + if (prev) + sample_decref(prev); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - if (prev) { - // A wrap around of the sequence no should not be treated as a simulation restart - if (smp->sequence == 0 && prev->sequence != 0 && prev->sequence < UINT64_MAX - 16) { - logger->warn("Simulation from node {} restarted (previous->sequence={}, current->sequence={})", - node->getName(), prev->sequence, smp->sequence); + if (prev) { + // A wrap around of the sequence no should not be treated as a simulation restart + if (smp->sequence == 0 && prev->sequence != 0 && + prev->sequence < UINT64_MAX - 16) { + logger->warn("Simulation from node {} restarted " + "(previous->sequence={}, current->sequence={})", + node->getName(), prev->sequence, smp->sequence); - smp->flags |= (int) SampleFlags::IS_FIRST; + smp->flags |= (int)SampleFlags::IS_FIRST; - // Restart hooks - for (auto k : node->in.hooks) - k->restart(); + // Restart hooks + for (auto k : node->in.hooks) + k->restart(); - for (auto k : node->out.hooks) - k->restart(); - } - } + for (auto k : node->out.hooks) + k->restart(); + } + } - sample_incref(smp); - if (prev) - sample_decref(prev); + sample_incref(smp); + if (prev) + sample_decref(prev); - prev = smp; + prev = smp; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "restart"; static char d[] = "Call restart hooks for current node"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/rms.cpp b/lib/hooks/rms.cpp index 44689d24c..49b9310d5 100644 --- a/lib/hooks/rms.cpp +++ b/lib/hooks/rms.cpp @@ -14,105 +14,101 @@ namespace node { class RMSHook : public MultiSignalHook { protected: - std::vector> smpMemory; + std::vector> smpMemory; - std::vector accumulator; - unsigned windowSize; - uint64_t smpMemoryPosition; + std::vector accumulator; + unsigned windowSize; + uint64_t smpMemoryPosition; public: - RMSHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - smpMemory(), - windowSize(0), - smpMemoryPosition(0) - { } + RMSHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), smpMemory(), windowSize(0), + smpMemoryPosition(0) {} - virtual - void prepare() - { - MultiSignalHook::prepare(); + virtual void prepare() { + MultiSignalHook::prepare(); - // Add signals - for (auto index : signalIndices) { - auto origSig = signals->getByIndex(index); + // Add signals + for (auto index : signalIndices) { + auto origSig = signals->getByIndex(index); - // Check that signal has float type - if (origSig->type != SignalType::FLOAT) - throw RuntimeError("The rms hook can only operate on signals of type float!"); - } + // Check that signal has float type + if (origSig->type != SignalType::FLOAT) + throw RuntimeError( + "The rms hook can only operate on signals of type float!"); + } - /* Initialize memory for each channel*/ - smpMemory.clear(); - for (unsigned i = 0; i < signalIndices.size(); i++){ - accumulator.push_back(0.0); - smpMemory.emplace_back(windowSize, 0.0); - } + /* Initialize memory for each channel*/ + smpMemory.clear(); + for (unsigned i = 0; i < signalIndices.size(); i++) { + accumulator.push_back(0.0); + smpMemory.emplace_back(windowSize, 0.0); + } - state = State::PREPARED; - } + state = State::PREPARED; + } - virtual - void parse(json_t *json) - { - int ret; - int windowSizeIn; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + int windowSizeIn; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: i }", - "window_size", &windowSizeIn - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-rms"); + ret = + json_unpack_ex(json, &err, 0, "{ s: i }", "window_size", &windowSizeIn); + if (ret) + throw ConfigError(json, err, "node-config-hook-rms"); - if (windowSizeIn < 1) - throw ConfigError(json, "node-config-hook-rms", "Window size must be greater 0 but is set to {}", windowSizeIn); + if (windowSizeIn < 1) + throw ConfigError(json, "node-config-hook-rms", + "Window size must be greater 0 but is set to {}", + windowSizeIn); - windowSize = (unsigned)windowSizeIn; + windowSize = (unsigned)windowSizeIn; - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - unsigned i = 0; - for (auto index : signalIndices) { - // Square the new value - double newValue = pow(smp->data[index].f, 2); + unsigned i = 0; + for (auto index : signalIndices) { + // Square the new value + double newValue = pow(smp->data[index].f, 2); - // Get the old value from the history - double oldValue = smpMemory[i][smpMemoryPosition % windowSize]; + // Get the old value from the history + double oldValue = smpMemory[i][smpMemoryPosition % windowSize]; - // Append the new value to the history memory - smpMemory[i][smpMemoryPosition % windowSize] = newValue; + // Append the new value to the history memory + smpMemory[i][smpMemoryPosition % windowSize] = newValue; - // Update the accumulator - accumulator[index] += newValue; - accumulator[index] -= oldValue; + // Update the accumulator + accumulator[index] += newValue; + accumulator[index] -= oldValue; - auto rms = pow(accumulator[index] / windowSize, 0.5); + auto rms = pow(accumulator[index] / windowSize, 0.5); - smp->data[index].f = rms; - i++; - } + smp->data[index].f = rms; + i++; + } - smpMemoryPosition++; + smpMemoryPosition++; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "rms"; static char d[] = "This hook calculates the root-mean-square (RMS) on a window"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/round.cpp b/lib/hooks/round.cpp index 658e7ec85..5c5b36da7 100644 --- a/lib/hooks/round.cpp +++ b/lib/hooks/round.cpp @@ -16,63 +16,61 @@ namespace node { class RoundHook : public MultiSignalHook { protected: - unsigned precision; + unsigned precision; public: - RoundHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - precision(1) - { } + RoundHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), precision(1) {} - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: i}", - "precision", &precision - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-round"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i}", "precision", &precision); + if (ret) + throw ConfigError(json, err, "node-config-hook-round"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - for (auto index : signalIndices) { - assert(index < smp->length); - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + for (auto index : signalIndices) { + assert(index < smp->length); + assert(state == State::STARTED); - switch (sample_format(smp, index)) { - case SignalType::FLOAT: - smp->data[index].f = round(smp->data[index].f * pow(10, precision)) / pow(10, precision); - break; + switch (sample_format(smp, index)) { + case SignalType::FLOAT: + smp->data[index].f = + round(smp->data[index].f * pow(10, precision)) / pow(10, precision); + break; - case SignalType::COMPLEX: - smp->data[index].z = std::complex( - round(smp->data[index].z.real() * pow(10, precision)) / pow(10, precision), - round(smp->data[index].z.imag() * pow(10, precision)) / pow(10, precision) - ); - break; - default: { } - } - } + case SignalType::COMPLEX: + smp->data[index].z = std::complex( + round(smp->data[index].z.real() * pow(10, precision)) / + pow(10, precision), + round(smp->data[index].z.imag() * pow(10, precision)) / + pow(10, precision)); + break; + default: { + } + } + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "round"; static char d[] = "Round signals to a set number of digits"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/scale.cpp b/lib/hooks/scale.cpp index 956abfcf7..696ec451c 100644 --- a/lib/hooks/scale.cpp +++ b/lib/hooks/scale.cpp @@ -16,71 +16,66 @@ namespace node { class ScaleHook : public MultiSignalHook { protected: - double scale; - double offset; + double scale; + double offset; public: - ScaleHook(Path *p, Node *n, int fl, int prio, bool en = true) : - MultiSignalHook(p, n, fl, prio, en), - scale(1.0), - offset(0.0) - { } + ScaleHook(Path *p, Node *n, int fl, int prio, bool en = true) + : MultiSignalHook(p, n, fl, prio, en), scale(1.0), offset(0.0) {} - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + virtual void parse(json_t *json) { + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - MultiSignalHook::parse(json); + MultiSignalHook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }", - "scale", &scale, - "offset", &offset - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-scale"); + ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }", "scale", &scale, + "offset", &offset); + if (ret) + throw ConfigError(json, err, "node-config-hook-scale"); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - for (auto index : signalIndices) { - assert(index < smp->length); - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + for (auto index : signalIndices) { + assert(index < smp->length); + assert(state == State::STARTED); - switch (sample_format(smp, index)) { - case SignalType::INTEGER: - smp->data[index].i *= scale; - smp->data[index].i += offset; - break; + switch (sample_format(smp, index)) { + case SignalType::INTEGER: + smp->data[index].i *= scale; + smp->data[index].i += offset; + break; - case SignalType::FLOAT: - smp->data[index].f *= scale; - smp->data[index].f += offset; - break; + case SignalType::FLOAT: + smp->data[index].f *= scale; + smp->data[index].f += offset; + break; - case SignalType::COMPLEX: - smp->data[index].z *= scale; - smp->data[index].z += offset; - break; + case SignalType::COMPLEX: + smp->data[index].z *= scale; + smp->data[index].z += offset; + break; - default: { } - } - } + default: { + } + } + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "scale"; static char d[] = "Scale signals by a factor and add offset"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/shift_seq.cpp b/lib/hooks/shift_seq.cpp index 59b1fa3e9..9f242c99b 100644 --- a/lib/hooks/shift_seq.cpp +++ b/lib/hooks/shift_seq.cpp @@ -14,46 +14,41 @@ namespace node { class ShiftSequenceHook : public Hook { protected: - int offset; + int offset; public: + using Hook::Hook; - using Hook::Hook; + virtual void parse(json_t *json) { + json_error_t err; + int ret; - virtual - void parse(json_t *json) - { - json_error_t err; - int ret; + assert(state != State::STARTED); - assert(state != State::STARTED); + Hook::parse(json); - Hook::parse(json); + ret = json_unpack_ex(json, &err, 0, "{ s: i }", "offset", &offset); + if (ret) + throw ConfigError(json, err, "node-config-hook-shift_seq"); - ret = json_unpack_ex(json, &err, 0, "{ s: i }", - "offset", &offset - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-shift_seq"); + state = State::PARSED; + } - state = State::PARSED; - } + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + smp->sequence += offset; - smp->sequence += offset; - - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "shift_seq"; static char d[] = "Shift sequence number of samples"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/shift_ts.cpp b/lib/hooks/shift_ts.cpp index a06ad428d..dd8ecbacb 100644 --- a/lib/hooks/shift_ts.cpp +++ b/lib/hooks/shift_ts.cpp @@ -8,8 +8,8 @@ #include #include -#include #include +#include namespace villas { namespace node { @@ -17,81 +17,73 @@ namespace node { class ShiftTimestampHook : public Hook { protected: - timespec offset; - enum { - SHIFT_ORIGIN, - SHIFT_RECEIVED - } mode; + timespec offset; + enum { SHIFT_ORIGIN, SHIFT_RECEIVED } mode; public: - ShiftTimestampHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - mode(SHIFT_ORIGIN) - { } + ShiftTimestampHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), mode(SHIFT_ORIGIN) {} - virtual - void parse(json_t *json) - { - double o; - const char *m = nullptr; - int ret; - json_error_t err; + virtual void parse(json_t *json) { + double o; + const char *m = nullptr; + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s: F }", - "mode", &m, - "offset", &o - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-shift_ts"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s: F }", "mode", &m, "offset", + &o); + if (ret) + throw ConfigError(json, err, "node-config-hook-shift_ts"); - if (m) { - if (!strcmp(m, "origin")) - mode = SHIFT_ORIGIN; - else if (!strcmp(m, "received")) - mode = SHIFT_RECEIVED; - else - throw ConfigError(json, "node-config-hook-shift_ts-mode", "Invalid mode parameter '{}'", m); - } + if (m) { + if (!strcmp(m, "origin")) + mode = SHIFT_ORIGIN; + else if (!strcmp(m, "received")) + mode = SHIFT_RECEIVED; + else + throw ConfigError(json, "node-config-hook-shift_ts-mode", + "Invalid mode parameter '{}'", m); + } - offset = time_from_double(o); + offset = time_from_double(o); - state = State::PARSED; - } + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp) - { - timespec *ts; + virtual Hook::Reason process(struct Sample *smp) { + timespec *ts; - assert(state == State::STARTED); + assert(state == State::STARTED); - switch (mode) { - case SHIFT_ORIGIN: - ts = &smp->ts.origin; - break; + switch (mode) { + case SHIFT_ORIGIN: + ts = &smp->ts.origin; + break; - case SHIFT_RECEIVED: - ts = &smp->ts.received; - break; + case SHIFT_RECEIVED: + ts = &smp->ts.received; + break; - default: - return Hook::Reason::ERROR; - } + default: + return Hook::Reason::ERROR; + } - *ts = time_add(ts, &offset); + *ts = time_add(ts, &offset); - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "shift_ts"; static char d[] = "Shift timestamps of samples"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/skip_first.cpp b/lib/hooks/skip_first.cpp index a90fc5881..a50ef5bd7 100644 --- a/lib/hooks/skip_first.cpp +++ b/lib/hooks/skip_first.cpp @@ -6,8 +6,8 @@ */ #include -#include #include +#include namespace villas { namespace node { @@ -15,120 +15,110 @@ namespace node { class SkipFirstHook : public Hook { protected: - enum class SkipState { - STARTED, // Path just started. First sample not received yet. - SKIPPING, // First sample received. Skipping samples now. - NORMAL // All samples skipped. Normal operation. - } skip_state; + enum class SkipState { + STARTED, // Path just started. First sample not received yet. + SKIPPING, // First sample received. Skipping samples now. + NORMAL // All samples skipped. Normal operation. + } skip_state; - enum class Mode { - SECONDS, - SAMPLES - } mode; + enum class Mode { SECONDS, SAMPLES } mode; - union { - struct { - timespec until; - timespec wait; // Absolute point in time from where we accept samples. - } seconds; + union { + struct { + timespec until; + timespec wait; // Absolute point in time from where we accept samples. + } seconds; - struct { - uint64_t until; - int wait; - } samples; - }; + struct { + uint64_t until; + int wait; + } samples; + }; public: - using Hook::Hook; + using Hook::Hook; - virtual - void parse(json_t *json) - { - double s; + virtual void parse(json_t *json) { + double s; - int ret; - json_error_t err; + int ret; + json_error_t err; - assert(state != State::STARTED); + assert(state != State::STARTED); - Hook::parse(json); + Hook::parse(json); - ret = json_unpack_ex(json, &err, 0, "{ s: F }", "seconds", &s); - if (!ret) { - seconds.wait = time_from_double(s); - mode = Mode::SECONDS; + ret = json_unpack_ex(json, &err, 0, "{ s: F }", "seconds", &s); + if (!ret) { + seconds.wait = time_from_double(s); + mode = Mode::SECONDS; - state = State::PARSED; - return; - } + state = State::PARSED; + return; + } - ret = json_unpack_ex(json, &err, 0, "{ s: i }", "samples", &samples.wait); - if (!ret) { - mode = Mode::SAMPLES; + ret = json_unpack_ex(json, &err, 0, "{ s: i }", "samples", &samples.wait); + if (!ret) { + mode = Mode::SAMPLES; - state = State::PARSED; - return; - } + state = State::PARSED; + return; + } - throw ConfigError(json, err, "node-config-hook-skip_first"); - } + throw ConfigError(json, err, "node-config-hook-skip_first"); + } - virtual - void start() - { - skip_state = SkipState::STARTED; - state = State::STARTED; - } + virtual void start() { + skip_state = SkipState::STARTED; + state = State::STARTED; + } - virtual - void restart() - { - skip_state = SkipState::STARTED; - } + virtual void restart() { skip_state = SkipState::STARTED; } - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - // Remember sequence no or timestamp of first sample. - if (skip_state == SkipState::STARTED) { - switch (mode) { - case Mode::SAMPLES: - samples.until = smp->sequence + samples.wait; - break; + // Remember sequence no or timestamp of first sample. + if (skip_state == SkipState::STARTED) { + switch (mode) { + case Mode::SAMPLES: + samples.until = smp->sequence + samples.wait; + break; - case Mode::SECONDS: - seconds.until = time_add(&smp->ts.origin, &seconds.wait); - break; - } + case Mode::SECONDS: + seconds.until = time_add(&smp->ts.origin, &seconds.wait); + break; + } - skip_state = SkipState::SKIPPING; - } + skip_state = SkipState::SKIPPING; + } - switch (mode) { - case Mode::SAMPLES: - if (samples.until > smp->sequence) - return Hook::Reason::SKIP_SAMPLE; - break; + switch (mode) { + case Mode::SAMPLES: + if (samples.until > smp->sequence) + return Hook::Reason::SKIP_SAMPLE; + break; - case Mode::SECONDS: - if (time_delta(&seconds.until, &smp->ts.origin) < 0) - return Hook::Reason::SKIP_SAMPLE; - break; + case Mode::SECONDS: + if (time_delta(&seconds.until, &smp->ts.origin) < 0) + return Hook::Reason::SKIP_SAMPLE; + break; - default: - break; - } + default: + break; + } - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "skip_first"; static char d[] = "Skip the first samples"; -static HookPlugin p; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/hooks/stats.cpp b/lib/hooks/stats.cpp index df5b75ac3..14ad81a0f 100644 --- a/lib/hooks/stats.cpp +++ b/lib/hooks/stats.cpp @@ -9,9 +9,9 @@ #include #include +#include #include #include -#include #include namespace villas { @@ -22,257 +22,227 @@ class StatsHook; class StatsWriteHook : public Hook { protected: - StatsHook *parent; + StatsHook *parent; public: - StatsWriteHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - parent(pa) - { - // This hook has no config. We never call parse() for it - state = State::PARSED; - } + StatsWriteHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, + bool en = true) + : Hook(p, n, fl, prio, en), parent(pa) { + // This hook has no config. We never call parse() for it + state = State::PARSED; + } - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; class StatsReadHook : public Hook { protected: - struct Sample *last; + struct Sample *last; - StatsHook *parent; + StatsHook *parent; public: - StatsReadHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - last(nullptr), - parent(pa) - { - // This hook has no config. We never call parse() for it - state = State::PARSED; - } + StatsReadHook(StatsHook *pa, Path *p, Node *n, int fl, int prio, + bool en = true) + : Hook(p, n, fl, prio, en), last(nullptr), parent(pa) { + // This hook has no config. We never call parse() for it + state = State::PARSED; + } - virtual - void start() - { - assert(state == State::PREPARED); + virtual void start() { + assert(state == State::PREPARED); - last = nullptr; + last = nullptr; - state = State::STARTED; - } + state = State::STARTED; + } - virtual - void stop() - { - assert(state == State::STARTED); + virtual void stop() { + assert(state == State::STARTED); - if (last) - sample_decref(last); + if (last) + sample_decref(last); - state = State::STOPPED; - } + state = State::STOPPED; + } - virtual - Hook::Reason process(struct Sample *smp); + virtual Hook::Reason process(struct Sample *smp); }; class StatsHook : public Hook { - friend StatsReadHook; - friend StatsWriteHook; + friend StatsReadHook; + friend StatsWriteHook; protected: - std::shared_ptr readHook; - std::shared_ptr writeHook; + std::shared_ptr readHook; + std::shared_ptr writeHook; - enum Stats::Format format; - int verbose; - int warmup; - int buckets; + enum Stats::Format format; + int verbose; + int warmup; + int buckets; - std::shared_ptr stats; + std::shared_ptr stats; - FILE *output; - std::string uri; + FILE *output; + std::string uri; public: + StatsHook(Path *p, Node *n, int fl, int prio, bool en = true) + : Hook(p, n, fl, prio, en), format(Stats::Format::HUMAN), verbose(0), + warmup(500), buckets(20), output(nullptr), uri() { + readHook = std::make_shared(this, p, n, fl, prio, en); + writeHook = std::make_shared(this, p, n, fl, prio, en); - StatsHook(Path *p, Node *n, int fl, int prio, bool en = true) : - Hook(p, n, fl, prio, en), - format(Stats::Format::HUMAN), - verbose(0), - warmup(500), - buckets(20), - output(nullptr), - uri() - { - readHook = std::make_shared(this, p, n, fl, prio, en); - writeHook = std::make_shared(this, p, n, fl, prio, en); + if (!readHook || !writeHook) + throw MemoryAllocationError(); - if (!readHook || !writeHook) - throw MemoryAllocationError(); + // Add child hooks + if (node) { + node->in.hooks.push_back(readHook); + node->out.hooks.push_back(writeHook); + } + } - // Add child hooks - if (node) { - node->in.hooks.push_back(readHook); - node->out.hooks.push_back(writeHook); - } - } + StatsHook &operator=(const StatsHook &) = delete; + StatsHook(const StatsHook &) = delete; - StatsHook & operator=(const StatsHook&) = delete; - StatsHook(const StatsHook&) = delete; + virtual void start() { + assert(state == State::PREPARED); - virtual - void start() - { - assert(state == State::PREPARED); + if (!uri.empty()) { + output = fopen(uri.c_str(), "w+"); + if (!output) + throw RuntimeError("Failed to open file '{}' for writing", uri); + } - if (!uri.empty()) { - output = fopen(uri.c_str(), "w+"); - if (!output) - throw RuntimeError("Failed to open file '{}' for writing", uri); - } + state = State::STARTED; + } - state = State::STARTED; - } + virtual void stop() { + assert(state == State::STARTED); - virtual - void stop() - { - assert(state == State::STARTED); + stats->print(uri.empty() ? stdout : output, format, verbose); - stats->print(uri.empty() ? stdout : output, format, verbose); + if (!uri.empty()) + fclose(output); - if (!uri.empty()) - fclose(output); + state = State::STOPPED; + } - state = State::STOPPED; - } + virtual void restart() { + assert(state == State::STARTED); - virtual - void restart() - { - assert(state == State::STARTED); + stats->reset(); + } - stats->reset(); - } + virtual Hook::Reason process(struct Sample *smp) { + // Only call readHook if it hasnt been added to the node's hook list + if (!node) + return readHook->process(smp); - virtual - Hook::Reason process(struct Sample *smp) - { - // Only call readHook if it hasnt been added to the node's hook list - if (!node) - return readHook->process(smp); + return Hook::Reason::OK; + } - return Hook::Reason::OK; - } + virtual void periodic() { + assert(state == State::STARTED); - virtual - void periodic() - { - assert(state == State::STARTED); + stats->printPeriodic(uri.empty() ? stdout : output, format, node); + } - stats->printPeriodic(uri.empty() ? stdout : output, format, node); - } + virtual void parse(json_t *json) { + int ret; + json_error_t err; - virtual - void parse(json_t *json) - { - int ret; - json_error_t err; + assert(state != State::STARTED); - assert(state != State::STARTED); + Hook::parse(json); - Hook::parse(json); + const char *f = nullptr; + const char *u = nullptr; - const char *f = nullptr; - const char *u = nullptr; + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: i, s?: i, s?: s }", + "format", &f, "verbose", &verbose, "warmup", &warmup, + "buckets", &buckets, "output", &u); + if (ret) + throw ConfigError(json, err, "node-config-hook-stats"); - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b, s?: i, s?: i, s?: s }", - "format", &f, - "verbose", &verbose, - "warmup", &warmup, - "buckets", &buckets, - "output", &u - ); - if (ret) - throw ConfigError(json, err, "node-config-hook-stats"); + if (f) { + try { + format = Stats::lookupFormat(f); + } catch (const std::invalid_argument &e) { + throw ConfigError(json, "node-config-hook-stats", + "Invalid statistic output format: {}", f); + } + } - if (f) { - try { - format = Stats::lookupFormat(f); - } catch (const std::invalid_argument &e) { - throw ConfigError(json, "node-config-hook-stats", "Invalid statistic output format: {}", f); - } - } + if (u) + uri = u; - if (u) - uri = u; + state = State::PARSED; + } - state = State::PARSED; - } + virtual void prepare() { + assert(state == State::CHECKED); - virtual - void prepare() - { - assert(state == State::CHECKED); + stats = std::make_shared(buckets, warmup); - stats = std::make_shared(buckets, warmup); + if (node) + node->setStats(stats); - if (node) - node->setStats(stats); - - state = State::PREPARED; - } + state = State::PREPARED; + } }; -Hook::Reason StatsWriteHook::process(struct Sample *smp) -{ - timespec now = time_now(); +Hook::Reason StatsWriteHook::process(struct Sample *smp) { + timespec now = time_now(); - parent->stats->update(Stats::Metric::AGE, time_delta(&smp->ts.received, &now)); + parent->stats->update(Stats::Metric::AGE, + time_delta(&smp->ts.received, &now)); - return Reason::OK; + return Reason::OK; } -Hook::Reason StatsReadHook::process(struct Sample *smp) -{ - if (last) { - if (smp->flags & last->flags & (int) SampleFlags::HAS_TS_RECEIVED) - parent->stats->update(Stats::Metric::GAP_RECEIVED, time_delta(&last->ts.received, &smp->ts.received)); +Hook::Reason StatsReadHook::process(struct Sample *smp) { + if (last) { + if (smp->flags & last->flags & (int)SampleFlags::HAS_TS_RECEIVED) + parent->stats->update(Stats::Metric::GAP_RECEIVED, + time_delta(&last->ts.received, &smp->ts.received)); - if (smp->flags & last->flags & (int) SampleFlags::HAS_TS_ORIGIN) - parent->stats->update(Stats::Metric::GAP_SAMPLE, time_delta(&last->ts.origin, &smp->ts.origin)); + if (smp->flags & last->flags & (int)SampleFlags::HAS_TS_ORIGIN) + parent->stats->update(Stats::Metric::GAP_SAMPLE, + time_delta(&last->ts.origin, &smp->ts.origin)); - if ((smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) && (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)) - parent->stats->update(Stats::Metric::OWD, time_delta(&smp->ts.origin, &smp->ts.received)); + if ((smp->flags & (int)SampleFlags::HAS_TS_ORIGIN) && + (smp->flags & (int)SampleFlags::HAS_TS_RECEIVED)) + parent->stats->update(Stats::Metric::OWD, + time_delta(&smp->ts.origin, &smp->ts.received)); - if (smp->flags & last->flags & (int) SampleFlags::HAS_SEQUENCE) { - int dist = smp->sequence - (int32_t) last->sequence; - if (dist != 1) - parent->stats->update(Stats::Metric::SMPS_REORDERED, dist); - } - } + if (smp->flags & last->flags & (int)SampleFlags::HAS_SEQUENCE) { + int dist = smp->sequence - (int32_t)last->sequence; + if (dist != 1) + parent->stats->update(Stats::Metric::SMPS_REORDERED, dist); + } + } - parent->stats->update(Stats::Metric::SIGNAL_COUNT, smp->length); + parent->stats->update(Stats::Metric::SIGNAL_COUNT, smp->length); - sample_incref(smp); + sample_incref(smp); - if (last) - sample_decref(last); + if (last) + sample_decref(last); - last = smp; + last = smp; - return Reason::OK; + return Reason::OK; } // Register hook static char n[] = "stats"; static char d[] = "Collect statistics for the current node"; -static HookPlugin p; +static HookPlugin p; } // namespace node } // namespace villas diff --git a/lib/hooks/ts.cpp b/lib/hooks/ts.cpp index 85c58b28a..0cd305b42 100644 --- a/lib/hooks/ts.cpp +++ b/lib/hooks/ts.cpp @@ -6,8 +6,8 @@ */ #include -#include #include +#include namespace villas { namespace node { @@ -15,23 +15,25 @@ namespace node { class TsHook : public Hook { public: - using Hook::Hook; + using Hook::Hook; - virtual - Hook::Reason process(struct Sample *smp) - { - assert(state == State::STARTED); + virtual Hook::Reason process(struct Sample *smp) { + assert(state == State::STARTED); - smp->ts.origin = smp->ts.received; + smp->ts.origin = smp->ts.received; - return Reason::OK; - } + return Reason::OK; + } }; // Register hook static char n[] = "ts"; -static char d[] = "Overwrite origin timestamp of samples with receive timestamp"; -static HookPlugin p; +static char d[] = + "Overwrite origin timestamp of samples with receive timestamp"; +static HookPlugin + p; } // namespace node } // namespace villas diff --git a/lib/kernel/if.cpp b/lib/kernel/if.cpp index 8dd2eb549..08aca8255 100644 --- a/lib/kernel/if.cpp +++ b/lib/kernel/if.cpp @@ -11,17 +11,17 @@ #include -#include -#include -#include -#include #include +#include +#include +#include +#include #include +#include +#include #include #include -#include -#include #include @@ -30,172 +30,173 @@ using namespace villas::node; using namespace villas::utils; using namespace villas::kernel; -Interface::Interface(struct rtnl_link *link, int aff) : - nl_link(link), - tc_qdisc(nullptr), - affinity(aff) -{ - logger = logging.get(fmt::format("kernel:if:{}", getName())); +Interface::Interface(struct rtnl_link *link, int aff) + : nl_link(link), tc_qdisc(nullptr), affinity(aff) { + logger = logging.get(fmt::format("kernel:if:{}", getName())); - int n = getIRQs(); - if (n) - logger->warn("Did not found any interrupts"); + int n = getIRQs(); + if (n) + logger->warn("Did not found any interrupts"); - logger->debug("Found {} IRQs", irqs.size()); + logger->debug("Found {} IRQs", irqs.size()); } -Interface::~Interface() -{ - if (tc_qdisc) - rtnl_qdisc_put(tc_qdisc); +Interface::~Interface() { + if (tc_qdisc) + rtnl_qdisc_put(tc_qdisc); } -int Interface::start() -{ - logger->info("Starting interface which is used by {} nodes", nodes.size()); +int Interface::start() { + logger->info("Starting interface which is used by {} nodes", nodes.size()); - // Set affinity for network interfaces (skip _loopback_ dev) - if (affinity) - setAffinity(affinity); + // Set affinity for network interfaces (skip _loopback_ dev) + if (affinity) + setAffinity(affinity); - // Assign fwmark's to nodes which have netem options - int ret, fwmark = 0; - for (auto *n : nodes) { - if (n->tc_qdisc && n->fwmark < 0) - n->fwmark = 1 + fwmark++; - } + // Assign fwmark's to nodes which have netem options + int ret, fwmark = 0; + for (auto *n : nodes) { + if (n->tc_qdisc && n->fwmark < 0) + n->fwmark = 1 + fwmark++; + } - // Abort if no node is using netem - if (fwmark == 0) - return 0; + // Abort if no node is using netem + if (fwmark == 0) + return 0; - if (getuid() != 0) - throw RuntimeError("Network emulation requires super-user privileges!"); + if (getuid() != 0) + throw RuntimeError("Network emulation requires super-user privileges!"); - // Replace root qdisc - ret = tc::prio(this, &tc_qdisc, TC_HANDLE(1, 0), TC_H_ROOT, fwmark); - if (ret) - throw RuntimeError("Failed to setup priority queuing discipline: {}", nl_geterror(ret)); + // Replace root qdisc + ret = tc::prio(this, &tc_qdisc, TC_HANDLE(1, 0), TC_H_ROOT, fwmark); + if (ret) + throw RuntimeError("Failed to setup priority queuing discipline: {}", + nl_geterror(ret)); - // Create netem qdisks and appropriate filter per netem node - for (auto *n : nodes) { - if (n->tc_qdisc) { - ret = tc::mark(this, &n->tc_classifier, TC_HANDLE(1, n->fwmark), n->fwmark); - if (ret) - throw RuntimeError("Failed to setup FW mark classifier: {}", nl_geterror(ret)); + // Create netem qdisks and appropriate filter per netem node + for (auto *n : nodes) { + if (n->tc_qdisc) { + ret = + tc::mark(this, &n->tc_classifier, TC_HANDLE(1, n->fwmark), n->fwmark); + if (ret) + throw RuntimeError("Failed to setup FW mark classifier: {}", + nl_geterror(ret)); - char *buf = tc::netem_print(n->tc_qdisc); - logger->debug("Starting network emulation for FW mark {}: {}", n->fwmark, buf); - free(buf); + char *buf = tc::netem_print(n->tc_qdisc); + logger->debug("Starting network emulation for FW mark {}: {}", n->fwmark, + buf); + free(buf); - ret = tc::netem(this, &n->tc_qdisc, TC_HANDLE(0x1000+n->fwmark, 0), TC_HANDLE(1, n->fwmark)); - if (ret) - throw RuntimeError("Failed to setup netem qdisc: {}", nl_geterror(ret)); - } - } + ret = tc::netem(this, &n->tc_qdisc, TC_HANDLE(0x1000 + n->fwmark, 0), + TC_HANDLE(1, n->fwmark)); + if (ret) + throw RuntimeError("Failed to setup netem qdisc: {}", nl_geterror(ret)); + } + } - return 0; + return 0; } -int Interface::stop() -{ - logger->info("Stopping interface"); +int Interface::stop() { + logger->info("Stopping interface"); - if (affinity) - setAffinity(-1L); + if (affinity) + setAffinity(-1L); - if (tc_qdisc) - tc::reset(this); + if (tc_qdisc) + tc::reset(this); - return 0; + return 0; } -std::string Interface::getName() const -{ - auto str = rtnl_link_get_name(nl_link); +std::string Interface::getName() const { + auto str = rtnl_link_get_name(nl_link); - return std::string(str); + return std::string(str); } -Interface * Interface::getEgress(struct sockaddr *sa, SuperNode *sn) -{ - struct rtnl_link *link; +Interface *Interface::getEgress(struct sockaddr *sa, SuperNode *sn) { + struct rtnl_link *link; - Logger logger = logging.get("kernel:if"); + Logger logger = logging.get("kernel:if"); - auto & interfaces = sn->getInterfaces(); - auto affinity = sn->getAffinity(); + auto &interfaces = sn->getInterfaces(); + auto affinity = sn->getAffinity(); - // Determine outgoing interface - link = nl::get_egress_link(sa); - if (!link) - throw RuntimeError("Failed to get interface for socket address '{}'", socket_print_addr(sa)); + // Determine outgoing interface + link = nl::get_egress_link(sa); + if (!link) + throw RuntimeError("Failed to get interface for socket address '{}'", + socket_print_addr(sa)); - // Search of existing interface with correct ifindex - for (auto *i : interfaces) { - if (rtnl_link_get_ifindex(i->nl_link) == rtnl_link_get_ifindex(link)) - return i; - } + // Search of existing interface with correct ifindex + for (auto *i : interfaces) { + if (rtnl_link_get_ifindex(i->nl_link) == rtnl_link_get_ifindex(link)) + return i; + } - // If not found, create a new interface - auto *i = new Interface(link, affinity); - if (!i) - throw MemoryAllocationError(); + // If not found, create a new interface + auto *i = new Interface(link, affinity); + if (!i) + throw MemoryAllocationError(); - interfaces.push_back(i); + interfaces.push_back(i); - return i; + return i; } -int Interface::getIRQs() -{ - int irq; +int Interface::getIRQs() { + int irq; - auto dirname = fmt::format("/sys/class/net/{}/device/msi_irqs/", getName()); - DIR *dir = opendir(dirname.c_str()); - if (dir) { - irqs.clear(); + auto dirname = fmt::format("/sys/class/net/{}/device/msi_irqs/", getName()); + DIR *dir = opendir(dirname.c_str()); + if (dir) { + irqs.clear(); - struct dirent *entry; - while ((entry = readdir(dir))) { - irq = atoi(entry->d_name); - if (irq) - irqs.push_back(irq); - } + struct dirent *entry; + while ((entry = readdir(dir))) { + irq = atoi(entry->d_name); + if (irq) + irqs.push_back(irq); + } - closedir(dir); - } + closedir(dir); + } - return 0; + return 0; } -int Interface::setAffinity(int affinity) -{ - assert(affinity != 0); +int Interface::setAffinity(int affinity) { + assert(affinity != 0); - if (getuid() != 0) { - logger->warn("Failed to tune IRQ affinity. Please run as super-user"); - return 0; - } + if (getuid() != 0) { + logger->warn("Failed to tune IRQ affinity. Please run as super-user"); + return 0; + } - FILE *file; + FILE *file; - CpuSet cset_pin(affinity); + CpuSet cset_pin(affinity); - for (int irq : irqs) { - std::string filename = fmt::format("/proc/irq/{}/smp_affinity", irq); + for (int irq : irqs) { + std::string filename = fmt::format("/proc/irq/{}/smp_affinity", irq); - file = fopen(filename.c_str(), "w"); - if (file) { - if (fprintf(file, "%8lx", (unsigned long) cset_pin) < 0) - throw SystemError("Failed to set affinity for for IRQ {} on interface '{}'", irq, getName()); + file = fopen(filename.c_str(), "w"); + if (file) { + if (fprintf(file, "%8lx", (unsigned long)cset_pin) < 0) + throw SystemError( + "Failed to set affinity for for IRQ {} on interface '{}'", irq, + getName()); - fclose(file); - logger->debug("Set affinity of IRQ {} to {} {}", irq, cset_pin.count() == 1 ? "core" : "cores", (std::string) cset_pin); - } - else - throw SystemError("Failed to set affinity for for IRQ {} on interface '{}'", irq, getName()); - } + fclose(file); + logger->debug("Set affinity of IRQ {} to {} {}", irq, + cset_pin.count() == 1 ? "core" : "cores", + (std::string)cset_pin); + } else + throw SystemError( + "Failed to set affinity for for IRQ {} on interface '{}'", irq, + getName()); + } - return 0; + return 0; } diff --git a/lib/kernel/nl.cpp b/lib/kernel/nl.cpp index e84360b75..2f74dba95 100644 --- a/lib/kernel/nl.cpp +++ b/lib/kernel/nl.cpp @@ -11,145 +11,145 @@ #include -#include #include +#include -#include #include #include +#include // Singleton for global netlink socket -static -struct nl_sock *sock = nullptr; +static struct nl_sock *sock = nullptr; using namespace villas; using namespace villas::kernel::nl; -struct nl_sock * villas::kernel::nl::init() -{ - int ret; +struct nl_sock *villas::kernel::nl::init() { + int ret; - if (!sock) { - // Create connection to netlink - sock = nl_socket_alloc(); - if (!sock) - throw MemoryAllocationError(); + if (!sock) { + // Create connection to netlink + sock = nl_socket_alloc(); + if (!sock) + throw MemoryAllocationError(); - ret = nl_connect(sock, NETLINK_ROUTE); - if (ret) - throw RuntimeError("Failed to connect to kernel: {}", nl_geterror(ret)); + ret = nl_connect(sock, NETLINK_ROUTE); + if (ret) + throw RuntimeError("Failed to connect to kernel: {}", nl_geterror(ret)); - // Fill some caches - struct nl_cache *cache; - ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache); - if (ret) - throw RuntimeError("Failed to get list of interfaces: {}", nl_geterror(ret)); + // Fill some caches + struct nl_cache *cache; + ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache); + if (ret) + throw RuntimeError("Failed to get list of interfaces: {}", + nl_geterror(ret)); - nl_cache_mngt_provide(cache); - } + nl_cache_mngt_provide(cache); + } - return sock; + return sock; } -void villas::kernel::nl::shutdown() -{ - nl_close(sock); - nl_socket_free(sock); +void villas::kernel::nl::shutdown() { + nl_close(sock); + nl_socket_free(sock); - sock = nullptr; + sock = nullptr; } -static -int egress_cb(struct nl_msg *msg, void *arg) -{ - struct rtnl_route **route = (struct rtnl_route **) arg; +static int egress_cb(struct nl_msg *msg, void *arg) { + struct rtnl_route **route = (struct rtnl_route **)arg; - if (rtnl_route_parse(nlmsg_hdr(msg), route)) - return NL_SKIP; + if (rtnl_route_parse(nlmsg_hdr(msg), route)) + return NL_SKIP; - return NL_STOP; + return NL_STOP; } -int villas::kernel::nl::get_egress(struct nl_addr *addr) -{ - int ret; - struct nl_sock *sock = nl::init(); - struct nl_cb *cb; - struct nl_msg *msg = nlmsg_alloc_simple(RTM_GETROUTE, 0); - struct rtnl_route *route = nullptr; +int villas::kernel::nl::get_egress(struct nl_addr *addr) { + int ret; + struct nl_sock *sock = nl::init(); + struct nl_cb *cb; + struct nl_msg *msg = nlmsg_alloc_simple(RTM_GETROUTE, 0); + struct rtnl_route *route = nullptr; - // Build message - struct rtmsg rmsg = { - .rtm_family = (unsigned char) nl_addr_get_family(addr), - .rtm_dst_len = (unsigned char) nl_addr_get_prefixlen(addr), - }; + // Build message + struct rtmsg rmsg = { + .rtm_family = (unsigned char)nl_addr_get_family(addr), + .rtm_dst_len = (unsigned char)nl_addr_get_prefixlen(addr), + }; - ret = nlmsg_append(msg, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); - if (ret) - goto out; + ret = nlmsg_append(msg, &rmsg, sizeof(rmsg), NLMSG_ALIGNTO); + if (ret) + goto out; - ret = nla_put_addr(msg, RTA_DST, addr); - if (ret) - goto out; + ret = nla_put_addr(msg, RTA_DST, addr); + if (ret) + goto out; - // Send message - ret = nl_send_auto(sock, msg); - if (ret < 0) - goto out; + // Send message + ret = nl_send_auto(sock, msg); + if (ret < 0) + goto out; - // Hook into receive chain - cb = nl_cb_alloc(NL_CB_CUSTOM); - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, egress_cb, &route); + // Hook into receive chain + cb = nl_cb_alloc(NL_CB_CUSTOM); + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, egress_cb, &route); - // Receive message - nl_recvmsgs_report(sock, cb); - nl_wait_for_ack(sock); + // Receive message + nl_recvmsgs_report(sock, cb); + nl_wait_for_ack(sock); - // Check result - if (!route || rtnl_route_get_nnexthops(route) != 1) { - ret = -1; - goto out2; - } + // Check result + if (!route || rtnl_route_get_nnexthops(route) != 1) { + ret = -1; + goto out2; + } - ret = rtnl_route_nh_get_ifindex(rtnl_route_nexthop_n(route, 0)); + ret = rtnl_route_nh_get_ifindex(rtnl_route_nexthop_n(route, 0)); - rtnl_route_put(route); + rtnl_route_put(route); -out2: nl_cb_put(cb); -out: nlmsg_free(msg); +out2: + nl_cb_put(cb); +out: + nlmsg_free(msg); - return ret; + return ret; } -struct rtnl_link * villas::kernel::nl::get_egress_link(struct sockaddr *sa) -{ - int ifindex = -1; +struct rtnl_link *villas::kernel::nl::get_egress_link(struct sockaddr *sa) { + int ifindex = -1; - switch (sa->sa_family) { - case AF_INET: - case AF_INET6: { - struct sockaddr_in *sin = (struct sockaddr_in *) sa; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + switch (sa->sa_family) { + case AF_INET: + case AF_INET6: { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; - struct nl_addr *addr = (sa->sa_family == AF_INET) - ? nl_addr_build(sin->sin_family, &sin->sin_addr.s_addr, sizeof(sin->sin_addr.s_addr)) - : nl_addr_build(sin6->sin6_family, sin6->sin6_addr.s6_addr, sizeof(sin6->sin6_addr)); + struct nl_addr *addr = + (sa->sa_family == AF_INET) + ? nl_addr_build(sin->sin_family, &sin->sin_addr.s_addr, + sizeof(sin->sin_addr.s_addr)) + : nl_addr_build(sin6->sin6_family, sin6->sin6_addr.s6_addr, + sizeof(sin6->sin6_addr)); - ifindex = nl::get_egress(addr); nl_addr_put(addr); - if (ifindex < 0) - throw RuntimeError("Netlink error: {}", nl_geterror(ifindex)); - break; - } + ifindex = nl::get_egress(addr); + nl_addr_put(addr); + if (ifindex < 0) + throw RuntimeError("Netlink error: {}", nl_geterror(ifindex)); + break; + } - case AF_PACKET: { - struct sockaddr_ll *sll = (struct sockaddr_ll *) sa; + case AF_PACKET: { + struct sockaddr_ll *sll = (struct sockaddr_ll *)sa; - ifindex = sll->sll_ifindex; - break; - } - } + ifindex = sll->sll_ifindex; + break; + } + } - struct nl_cache *cache = nl_cache_mngt_require("route/link"); + struct nl_cache *cache = nl_cache_mngt_require("route/link"); - return rtnl_link_get(cache, ifindex); + return rtnl_link_get(cache, ifindex); } diff --git a/lib/kernel/tc.cpp b/lib/kernel/tc.cpp index 241f5d996..30f7907fe 100644 --- a/lib/kernel/tc.cpp +++ b/lib/kernel/tc.cpp @@ -12,83 +12,84 @@ #include -#include #include -#include #include -#include +#include #include +#include +#include using namespace villas; using namespace villas::kernel; -int villas::kernel::tc::prio(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t parent, int bands) -{ - int ret; - struct nl_sock *sock = nl::init(); - struct rtnl_qdisc *q = rtnl_qdisc_alloc(); +int villas::kernel::tc::prio(Interface *i, struct rtnl_qdisc **qd, + tc_hdl_t handle, tc_hdl_t parent, int bands) { + int ret; + struct nl_sock *sock = nl::init(); + struct rtnl_qdisc *q = rtnl_qdisc_alloc(); - ret = kernel::loadModule("sch_prio"); - if (ret) - throw RuntimeError("Failed to load kernel module: sch_prio ({})", ret); + ret = kernel::loadModule("sch_prio"); + if (ret) + throw RuntimeError("Failed to load kernel module: sch_prio ({})", ret); - /* This is the default priomap used by the tc-prio qdisc + /* This is the default priomap used by the tc-prio qdisc * We will use the first 'bands' bands internally */ - uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP; - for (unsigned i = 0; i < ARRAY_LEN(map); i++) - map[i] += bands; + uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP; + for (unsigned i = 0; i < ARRAY_LEN(map); i++) + map[i] += bands; - rtnl_tc_set_link(TC_CAST(q), i->nl_link); - rtnl_tc_set_parent(TC_CAST(q), parent); - rtnl_tc_set_handle(TC_CAST(q), handle); - rtnl_tc_set_kind(TC_CAST(q), "prio"); + rtnl_tc_set_link(TC_CAST(q), i->nl_link); + rtnl_tc_set_parent(TC_CAST(q), parent); + rtnl_tc_set_handle(TC_CAST(q), handle); + rtnl_tc_set_kind(TC_CAST(q), "prio"); - rtnl_qdisc_prio_set_bands(q, bands + 3); - rtnl_qdisc_prio_set_priomap(q, map, sizeof(map)); + rtnl_qdisc_prio_set_bands(q, bands + 3); + rtnl_qdisc_prio_set_priomap(q, map, sizeof(map)); - ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE | NLM_F_REPLACE); + ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE | NLM_F_REPLACE); - *qd = q; + *qd = q; - auto logger = logging.get("kernel"); - logger->debug("Added prio qdisc with {} bands to interface '{}'", bands, rtnl_link_get_name(i->nl_link)); + auto logger = logging.get("kernel"); + logger->debug("Added prio qdisc with {} bands to interface '{}'", bands, + rtnl_link_get_name(i->nl_link)); - return ret; + return ret; } -int villas::kernel::tc::mark(Interface *i, struct rtnl_cls **cls, tc_hdl_t flowid, uint32_t mark) -{ - int ret; - struct nl_sock *sock = nl::init(); - struct rtnl_cls *c = rtnl_cls_alloc(); +int villas::kernel::tc::mark(Interface *i, struct rtnl_cls **cls, + tc_hdl_t flowid, uint32_t mark) { + int ret; + struct nl_sock *sock = nl::init(); + struct rtnl_cls *c = rtnl_cls_alloc(); - ret = kernel::loadModule("cls_fw"); - if (ret) - throw RuntimeError("Failed to load kernel module: cls_fw"); + ret = kernel::loadModule("cls_fw"); + if (ret) + throw RuntimeError("Failed to load kernel module: cls_fw"); - rtnl_tc_set_link(TC_CAST(c), i->nl_link); - rtnl_tc_set_handle(TC_CAST(c), mark); - rtnl_tc_set_kind(TC_CAST(c), "fw"); + rtnl_tc_set_link(TC_CAST(c), i->nl_link); + rtnl_tc_set_handle(TC_CAST(c), mark); + rtnl_tc_set_kind(TC_CAST(c), "fw"); - rtnl_cls_set_protocol(c, ETH_P_ALL); + rtnl_cls_set_protocol(c, ETH_P_ALL); - rtnl_fw_set_classid(c, flowid); - rtnl_fw_set_mask(c, 0xFFFFFFFF); + rtnl_fw_set_classid(c, flowid); + rtnl_fw_set_mask(c, 0xFFFFFFFF); - ret = rtnl_cls_add(sock, c, NLM_F_CREATE); + ret = rtnl_cls_add(sock, c, NLM_F_CREATE); - *cls = c; + *cls = c; - auto logger = logging.get("kernel"); - logger->debug("Added fwmark classifier with mark {} to interface '{}'", mark, rtnl_link_get_name(i->nl_link)); + auto logger = logging.get("kernel"); + logger->debug("Added fwmark classifier with mark {} to interface '{}'", mark, + rtnl_link_get_name(i->nl_link)); - return ret; + return ret; } -int villas::kernel::tc::reset(Interface *i) -{ - struct nl_sock *sock = nl::init(); +int villas::kernel::tc::reset(Interface *i) { + struct nl_sock *sock = nl::init(); - // We restore the default pfifo_fast qdisc, by deleting ours - return rtnl_qdisc_delete(sock, i->tc_qdisc); + // We restore the default pfifo_fast qdisc, by deleting ours + return rtnl_qdisc_delete(sock, i->tc_qdisc); } diff --git a/lib/kernel/tc_netem.cpp b/lib/kernel/tc_netem.cpp index b62e2d667..0b9ab2625 100644 --- a/lib/kernel/tc_netem.cpp +++ b/lib/kernel/tc_netem.cpp @@ -7,275 +7,279 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::utils; using namespace villas::kernel; -static -const double max_percent_value = 0xffffffff; +static const double max_percent_value = 0xffffffff; /* * Set the delay distribution. Latency/jitter must be set before applying. * @arg qdisc Netem qdisc. * @return 0 on success, error code on failure. */ -static -int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *qdisc, short *data, size_t len) -{ - struct rtnl_netem *netem; +static int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *qdisc, + short *data, size_t len) { + struct rtnl_netem *netem; - if (!(netem = (struct rtnl_netem *) rtnl_tc_data(TC_CAST(qdisc)))) - return -1; + if (!(netem = (struct rtnl_netem *)rtnl_tc_data(TC_CAST(qdisc)))) + return -1; - if (len > MAXDIST) - return -NLE_INVAL; + if (len > MAXDIST) + return -NLE_INVAL; - netem->qnm_dist.dist_data = (int16_t *) calloc(len, sizeof(int16_t)); + netem->qnm_dist.dist_data = (int16_t *)calloc(len, sizeof(int16_t)); - size_t i; - for (i = 0; i < len; i++) - netem->qnm_dist.dist_data[i] = data[i]; + size_t i; + for (i = 0; i < len; i++) + netem->qnm_dist.dist_data[i] = data[i]; - netem->qnm_dist.dist_size = len; - netem->qnm_mask |= SCH_NETEM_ATTR_DIST; + netem->qnm_dist.dist_size = len; + netem->qnm_mask |= SCH_NETEM_ATTR_DIST; - return 0; + return 0; } // Customized version of rtnl_netem_set_delay_distribution() of libnl -static -int set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json) -{ - if (json_is_string(json)) - return rtnl_netem_set_delay_distribution(qdisc, json_string_value(json)); - else if (json_is_array(json)) { - json_t *elm; - size_t idx; - size_t len = json_array_size(json); +static int set_delay_distribution(struct rtnl_qdisc *qdisc, json_t *json) { + if (json_is_string(json)) + return rtnl_netem_set_delay_distribution(qdisc, json_string_value(json)); + else if (json_is_array(json)) { + json_t *elm; + size_t idx; + size_t len = json_array_size(json); - int16_t *data = new int16_t[len]; - if (!data) - throw MemoryAllocationError(); + int16_t *data = new int16_t[len]; + if (!data) + throw MemoryAllocationError(); - json_array_foreach(json, idx, elm) { - if (!json_is_integer(elm)) - return -1; + json_array_foreach(json, idx, elm) { + if (!json_is_integer(elm)) + return -1; - data[idx] = json_integer_value(elm); - } + data[idx] = json_integer_value(elm); + } - return rtnl_netem_set_delay_distribution_data(qdisc, data, len); - } + return rtnl_netem_set_delay_distribution_data(qdisc, data, len); + } - return 0; + return 0; } -int villas::kernel::tc::netem_parse(struct rtnl_qdisc **netem, json_t *json) -{ - int ret, val; +int villas::kernel::tc::netem_parse(struct rtnl_qdisc **netem, json_t *json) { + int ret, val; - json_t *json_limit = nullptr; - json_t *json_delay = nullptr; - json_t *json_delay_distribution = nullptr; - json_t *json_delay_correlation = nullptr; - json_t *json_jitter = nullptr; - json_t *json_loss = nullptr; - json_t *json_duplicate = nullptr; - json_t *json_corruption = nullptr; + json_t *json_limit = nullptr; + json_t *json_delay = nullptr; + json_t *json_delay_distribution = nullptr; + json_t *json_delay_correlation = nullptr; + json_t *json_jitter = nullptr; + json_t *json_loss = nullptr; + json_t *json_duplicate = nullptr; + json_t *json_corruption = nullptr; - json_error_t err; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o }", - "distribution", &json_delay_distribution, - "correlation", &json_delay_correlation, - "limit", &json_limit, - "delay", &json_delay, - "jitter", &json_jitter, - "loss", &json_loss, - "duplicate", &json_duplicate, - "corruption", &json_corruption - ); - if (ret) - throw ConfigError(json, err, "node-config-netem", "Failed to parse setting network emulation settings"); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o }", + "distribution", &json_delay_distribution, "correlation", + &json_delay_correlation, "limit", &json_limit, "delay", &json_delay, + "jitter", &json_jitter, "loss", &json_loss, "duplicate", &json_duplicate, + "corruption", &json_corruption); + if (ret) + throw ConfigError(json, err, "node-config-netem", + "Failed to parse setting network emulation settings"); - struct rtnl_qdisc *ne = rtnl_qdisc_alloc(); - if (!ne) - throw MemoryAllocationError(); + struct rtnl_qdisc *ne = rtnl_qdisc_alloc(); + if (!ne) + throw MemoryAllocationError(); - rtnl_tc_set_kind(TC_CAST(ne), "netem"); + rtnl_tc_set_kind(TC_CAST(ne), "netem"); - if (json_delay_distribution) { - if (set_delay_distribution(ne, json_delay_distribution)) - throw ConfigError(json_delay_distribution, "node-config-netem-distrobution", "Invalid delay distribution in netem config"); - } + if (json_delay_distribution) { + if (set_delay_distribution(ne, json_delay_distribution)) + throw ConfigError(json_delay_distribution, + "node-config-netem-distrobution", + "Invalid delay distribution in netem config"); + } - if (json_delay_correlation) { - double dval = json_number_value(json_delay_correlation); + if (json_delay_correlation) { + double dval = json_number_value(json_delay_correlation); - if (!json_is_number(json_delay_correlation) || dval < 0 || dval > 100) - throw ConfigError(json_delay_correlation, "Setting 'correlation' must be a positive integer within the range [ 0, 100 ]"); + if (!json_is_number(json_delay_correlation) || dval < 0 || dval > 100) + throw ConfigError(json_delay_correlation, + "Setting 'correlation' must be a positive integer " + "within the range [ 0, 100 ]"); - unsigned *pval = (unsigned *) &val; - *pval = (unsigned) rint((dval / 100.) * max_percent_value); + unsigned *pval = (unsigned *)&val; + *pval = (unsigned)rint((dval / 100.) * max_percent_value); - rtnl_netem_set_delay_correlation(ne, val); - } - else - rtnl_netem_set_delay_correlation(ne, 0); + rtnl_netem_set_delay_correlation(ne, val); + } else + rtnl_netem_set_delay_correlation(ne, 0); - if (json_limit) { - val = json_integer_value(json_limit); + if (json_limit) { + val = json_integer_value(json_limit); - if (!json_is_integer(json_limit) || val <= 0) - throw ConfigError(json_limit, "Setting 'limit' must be a positive integer"); + if (!json_is_integer(json_limit) || val <= 0) + throw ConfigError(json_limit, + "Setting 'limit' must be a positive integer"); - rtnl_netem_set_limit(ne, val); - } - else - rtnl_netem_set_limit(ne, 0); + rtnl_netem_set_limit(ne, val); + } else + rtnl_netem_set_limit(ne, 0); - if (json_delay) { - val = json_integer_value(json_delay); + if (json_delay) { + val = json_integer_value(json_delay); - if (!json_is_integer(json_delay) || val <= 0) - throw ConfigError(json_delay, "Setting 'delay' must be a positive integer"); + if (!json_is_integer(json_delay) || val <= 0) + throw ConfigError(json_delay, + "Setting 'delay' must be a positive integer"); - rtnl_netem_set_delay(ne, val); - } + rtnl_netem_set_delay(ne, val); + } - if (json_jitter) { - val = json_integer_value(json_jitter); + if (json_jitter) { + val = json_integer_value(json_jitter); - if (!json_is_integer(json_jitter) || val <= 0) - throw ConfigError(json_jitter, "Setting 'jitter' must be a positive integer"); + if (!json_is_integer(json_jitter) || val <= 0) + throw ConfigError(json_jitter, + "Setting 'jitter' must be a positive integer"); - rtnl_netem_set_jitter(ne, val); - } + rtnl_netem_set_jitter(ne, val); + } - if (json_loss) { - double dval = json_number_value(json_loss); + if (json_loss) { + double dval = json_number_value(json_loss); - if (!json_is_number(json_loss) || dval < 0 || dval > 100) - throw ConfigError(json_loss, "Setting 'loss' must be a positive integer within the range [ 0, 100 ]"); + if (!json_is_number(json_loss) || dval < 0 || dval > 100) + throw ConfigError(json_loss, "Setting 'loss' must be a positive integer " + "within the range [ 0, 100 ]"); - unsigned *pval = (unsigned *) &val; - *pval = (unsigned) rint((dval / 100.) * max_percent_value); + unsigned *pval = (unsigned *)&val; + *pval = (unsigned)rint((dval / 100.) * max_percent_value); - rtnl_netem_set_loss(ne, val); - } + rtnl_netem_set_loss(ne, val); + } - if (json_duplicate) { - double dval = json_number_value(json_duplicate); + if (json_duplicate) { + double dval = json_number_value(json_duplicate); - if (!json_is_number(json_duplicate) || dval < 0 || dval > 100) - throw ConfigError(json_duplicate, "Setting 'duplicate' must be a positive integer within the range [ 0, 100 ]"); + if (!json_is_number(json_duplicate) || dval < 0 || dval > 100) + throw ConfigError(json_duplicate, + "Setting 'duplicate' must be a positive integer within " + "the range [ 0, 100 ]"); - unsigned *pval = (unsigned *) &val; - *pval = (unsigned) rint((dval / 100.) * max_percent_value); + unsigned *pval = (unsigned *)&val; + *pval = (unsigned)rint((dval / 100.) * max_percent_value); - rtnl_netem_set_duplicate(ne, val); - } + rtnl_netem_set_duplicate(ne, val); + } - if (json_corruption) { - double dval = json_number_value(json_corruption); + if (json_corruption) { + double dval = json_number_value(json_corruption); - if (!json_is_number(json_corruption) || dval < 0 || dval > 100) - throw ConfigError(json_corruption, "Setting 'corruption' must be a positive integer within the range [ 0, 100 ]"); + if (!json_is_number(json_corruption) || dval < 0 || dval > 100) + throw ConfigError(json_corruption, + "Setting 'corruption' must be a positive integer " + "within the range [ 0, 100 ]"); - unsigned *pval = (unsigned *) &val; - *pval = (unsigned) rint((dval / 100.) * max_percent_value); + unsigned *pval = (unsigned *)&val; + *pval = (unsigned)rint((dval / 100.) * max_percent_value); - rtnl_netem_set_corruption_probability(ne, val); - } + rtnl_netem_set_corruption_probability(ne, val); + } - *netem = ne; + *netem = ne; - return 0; + return 0; } -char * villas::kernel::tc::netem_print(struct rtnl_qdisc *ne) -{ - char *buf = nullptr; +char *villas::kernel::tc::netem_print(struct rtnl_qdisc *ne) { + char *buf = nullptr; - if (rtnl_netem_get_limit(ne) > 0) - strcatf(&buf, "limit %upkts", rtnl_netem_get_limit(ne)); + if (rtnl_netem_get_limit(ne) > 0) + strcatf(&buf, "limit %upkts", rtnl_netem_get_limit(ne)); - if (rtnl_netem_get_delay(ne) > 0) { - strcatf(&buf, "delay %.2fms ", rtnl_netem_get_delay(ne) / 1000.0); + if (rtnl_netem_get_delay(ne) > 0) { + strcatf(&buf, "delay %.2fms ", rtnl_netem_get_delay(ne) / 1000.0); - if (rtnl_netem_get_jitter(ne) > 0) { - strcatf(&buf, "jitter %.2fms ", rtnl_netem_get_jitter(ne) / 1000.0); + if (rtnl_netem_get_jitter(ne) > 0) { + strcatf(&buf, "jitter %.2fms ", rtnl_netem_get_jitter(ne) / 1000.0); - if (rtnl_netem_get_delay_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_delay_correlation(ne)); - } - } + if (rtnl_netem_get_delay_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_delay_correlation(ne)); + } + } - if (rtnl_netem_get_loss(ne) > 0) { - strcatf(&buf, "loss %u%% ", rtnl_netem_get_loss(ne)); + if (rtnl_netem_get_loss(ne) > 0) { + strcatf(&buf, "loss %u%% ", rtnl_netem_get_loss(ne)); - if (rtnl_netem_get_loss_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_loss_correlation(ne)); - } + if (rtnl_netem_get_loss_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_loss_correlation(ne)); + } - if (rtnl_netem_get_reorder_probability(ne) > 0) { - strcatf(&buf, " reorder%u%% ", rtnl_netem_get_reorder_probability(ne)); + if (rtnl_netem_get_reorder_probability(ne) > 0) { + strcatf(&buf, " reorder%u%% ", rtnl_netem_get_reorder_probability(ne)); - if (rtnl_netem_get_reorder_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_reorder_correlation(ne)); - } + if (rtnl_netem_get_reorder_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_reorder_correlation(ne)); + } - if (rtnl_netem_get_corruption_probability(ne) > 0) { - strcatf(&buf, "corruption %u%% ", rtnl_netem_get_corruption_probability(ne)); + if (rtnl_netem_get_corruption_probability(ne) > 0) { + strcatf(&buf, "corruption %u%% ", + rtnl_netem_get_corruption_probability(ne)); - if (rtnl_netem_get_corruption_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_corruption_correlation(ne)); - } + if (rtnl_netem_get_corruption_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_corruption_correlation(ne)); + } - if (rtnl_netem_get_duplicate(ne) > 0) { - strcatf(&buf, "duplication %u%% ", rtnl_netem_get_duplicate(ne)); + if (rtnl_netem_get_duplicate(ne) > 0) { + strcatf(&buf, "duplication %u%% ", rtnl_netem_get_duplicate(ne)); - if (rtnl_netem_get_duplicate_correlation(ne) > 0) - strcatf(&buf, "%u%% ", rtnl_netem_get_duplicate_correlation(ne)); - } + if (rtnl_netem_get_duplicate_correlation(ne) > 0) + strcatf(&buf, "%u%% ", rtnl_netem_get_duplicate_correlation(ne)); + } - return buf; + return buf; } -int villas::kernel::tc::netem(Interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t parent) -{ - int ret; - struct nl_sock *sock = nl::init(); - struct rtnl_qdisc *q = *qd; +int villas::kernel::tc::netem(Interface *i, struct rtnl_qdisc **qd, + tc_hdl_t handle, tc_hdl_t parent) { + int ret; + struct nl_sock *sock = nl::init(); + struct rtnl_qdisc *q = *qd; - ret = kernel::loadModule("sch_netem"); - if (ret) - throw RuntimeError("Failed to load kernel module: sch_netem ({})", ret); + ret = kernel::loadModule("sch_netem"); + if (ret) + throw RuntimeError("Failed to load kernel module: sch_netem ({})", ret); - rtnl_tc_set_link(TC_CAST(q), i->nl_link); - rtnl_tc_set_parent(TC_CAST(q), parent); - rtnl_tc_set_handle(TC_CAST(q), handle); - //rtnl_tc_set_kind(TC_CAST(q), "netem"); + rtnl_tc_set_link(TC_CAST(q), i->nl_link); + rtnl_tc_set_parent(TC_CAST(q), parent); + rtnl_tc_set_handle(TC_CAST(q), handle); + //rtnl_tc_set_kind(TC_CAST(q), "netem"); - ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE); + ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE); - *qd = q; + *qd = q; - auto logger = logging.get("kernel"); - logger->debug("Added netem qdisc to interface '{}'", rtnl_link_get_name(i->nl_link)); + auto logger = logging.get("kernel"); + logger->debug("Added netem qdisc to interface '{}'", + rtnl_link_get_name(i->nl_link)); - return ret; + return ret; } diff --git a/lib/mapping.cpp b/lib/mapping.cpp index f4ad98fa3..5fec8fb31 100644 --- a/lib/mapping.cpp +++ b/lib/mapping.cpp @@ -5,351 +5,332 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include -#include -#include -#include #include +#include +#include #include +#include #include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int MappingEntry::parseString(const std::string &str) -{ - std::smatch mr; - std::regex re(RE_MAPPING); +int MappingEntry::parseString(const std::string &str) { + std::smatch mr; + std::regex re(RE_MAPPING); - if (!std::regex_match(str, mr, re)) - goto invalid_format; + if (!std::regex_match(str, mr, re)) + goto invalid_format; - if (mr[1].matched) - nodeName = mr.str(1); + if (mr[1].matched) + nodeName = mr.str(1); - if (mr[9].matched) - nodeName = mr.str(9); + if (mr[9].matched) + nodeName = mr.str(9); - if (mr[6].matched) { - data.first = strdup(mr.str(6).c_str()); - data.last = mr[7].matched - ? strdup(mr.str(7).c_str()) - : nullptr; + if (mr[6].matched) { + data.first = strdup(mr.str(6).c_str()); + data.last = mr[7].matched ? strdup(mr.str(7).c_str()) : nullptr; - type = Type::DATA; - } - else if (mr[10].matched) { - data.first = strdup(mr.str(10).c_str()); - data.last = mr[11].matched - ? strdup(mr.str(11).c_str()) - : nullptr; + type = Type::DATA; + } else if (mr[10].matched) { + data.first = strdup(mr.str(10).c_str()); + data.last = mr[11].matched ? strdup(mr.str(11).c_str()) : nullptr; - type = Type::DATA; - } - else if (mr[8].matched) { - data.first = strdup(mr.str(8).c_str()); - data.last = nullptr; + type = Type::DATA; + } else if (mr[8].matched) { + data.first = strdup(mr.str(8).c_str()); + data.last = nullptr; - type = Type::DATA; - } - else if (mr[2].matched) { - stats.type = Stats::lookupType(mr.str(3)); - stats.metric = Stats::lookupMetric(mr.str(2)); + type = Type::DATA; + } else if (mr[2].matched) { + stats.type = Stats::lookupType(mr.str(3)); + stats.metric = Stats::lookupMetric(mr.str(2)); - type = Type::STATS; - } - else if (mr[5].matched) { - if (mr.str(5) == "origin") - timestamp.type = TimestampType::ORIGIN; - else if (mr.str(5) == "received") - timestamp.type = TimestampType::RECEIVED; - else - goto invalid_format; + type = Type::STATS; + } else if (mr[5].matched) { + if (mr.str(5) == "origin") + timestamp.type = TimestampType::ORIGIN; + else if (mr.str(5) == "received") + timestamp.type = TimestampType::RECEIVED; + else + goto invalid_format; - type = Type::TIMESTAMP; - } - else if (mr[4].matched) { - if (mr.str(4) == "sequence") - header.type = HeaderType::SEQUENCE; - else if (mr.str(4) == "length") - header.type = HeaderType::LENGTH; - else - goto invalid_format; + type = Type::TIMESTAMP; + } else if (mr[4].matched) { + if (mr.str(4) == "sequence") + header.type = HeaderType::SEQUENCE; + else if (mr.str(4) == "length") + header.type = HeaderType::LENGTH; + else + goto invalid_format; - type = Type::HEADER; - } - // Only node name given.. We map all data - else if (!nodeName.empty()) { - data.first = nullptr; - data.last = nullptr; + type = Type::HEADER; + } + // Only node name given.. We map all data + else if (!nodeName.empty()) { + data.first = nullptr; + data.last = nullptr; - type = Type::DATA; - } + type = Type::DATA; + } - return 0; + return 0; invalid_format: - throw RuntimeError("Failed to parse mapping expression: {}", str); + throw RuntimeError("Failed to parse mapping expression: {}", str); } -MappingEntry::MappingEntry() : - node(nullptr), - type(Type::UNKNOWN), - length(0), - offset(0), - nodeName() -{ } +MappingEntry::MappingEntry() + : node(nullptr), type(Type::UNKNOWN), length(0), offset(0), nodeName() {} -int MappingEntry::parse(json_t *json) -{ - const char *str; +int MappingEntry::parse(json_t *json) { + const char *str; - str = json_string_value(json); - if (!str) - return -1; + str = json_string_value(json); + if (!str) + return -1; - return parseString(str); + return parseString(str); } -int MappingEntry::update(struct Sample *remapped, const struct Sample *original) const -{ - unsigned len = length; +int MappingEntry::update(struct Sample *remapped, + const struct Sample *original) const { + unsigned len = length; - if (offset + len > remapped->capacity) - return -1; + if (offset + len > remapped->capacity) + return -1; - switch (type) { - case Type::STATS: - remapped->data[offset] = node->getStats()->getValue(stats.metric, stats.type); - break; + switch (type) { + case Type::STATS: + remapped->data[offset] = + node->getStats()->getValue(stats.metric, stats.type); + break; - case Type::TIMESTAMP: { - const struct timespec *ts; + case Type::TIMESTAMP: { + const struct timespec *ts; - switch (timestamp.type) { - case TimestampType::RECEIVED: - ts = &original->ts.received; - break; - case TimestampType::ORIGIN: - ts = &original->ts.origin; - break; - default: - return -1; - } + switch (timestamp.type) { + case TimestampType::RECEIVED: + ts = &original->ts.received; + break; + case TimestampType::ORIGIN: + ts = &original->ts.origin; + break; + default: + return -1; + } - remapped->data[offset + 0].i = ts->tv_sec; - remapped->data[offset + 1].i = ts->tv_nsec; - break; - } + remapped->data[offset + 0].i = ts->tv_sec; + remapped->data[offset + 1].i = ts->tv_nsec; + break; + } - case Type::HEADER: - switch (header.type) { - case HeaderType::LENGTH: - remapped->data[offset].i = original->length; - break; + case Type::HEADER: + switch (header.type) { + case HeaderType::LENGTH: + remapped->data[offset].i = original->length; + break; - case HeaderType::SEQUENCE: - remapped->data[offset].i = original->sequence; - break; + case HeaderType::SEQUENCE: + remapped->data[offset].i = original->sequence; + break; - default: - return -1; - } - break; + default: + return -1; + } + break; - case Type::DATA: - for (unsigned j = data.offset, - i = offset; - j < MIN(original->length, (unsigned) (data.offset + length)); - j++, - i++) - { - if (j >= original->length) - remapped->data[i].f = -1; - else - remapped->data[i] = original->data[j]; - } + case Type::DATA: + for (unsigned j = data.offset, i = offset; + j < MIN(original->length, (unsigned)(data.offset + length)); + j++, i++) { + if (j >= original->length) + remapped->data[i].f = -1; + else + remapped->data[i] = original->data[j]; + } - len = MIN((unsigned) length, original->length - data.offset); - break; + len = MIN((unsigned)length, original->length - data.offset); + break; - case Type::UNKNOWN: - return -1; - } + case Type::UNKNOWN: + return -1; + } - if (offset + len > remapped->length) - remapped->length = offset + len; + if (offset + len > remapped->length) + remapped->length = offset + len; - return 0; + return 0; } -int MappingEntry::prepare(NodeList &nodes) -{ - if (!nodeName.empty() && node == nullptr) { - node = nodes.lookup(nodeName); - if (!node) - throw RuntimeError("Invalid node name in mapping: {}", nodeName); - } +int MappingEntry::prepare(NodeList &nodes) { + if (!nodeName.empty() && node == nullptr) { + node = nodes.lookup(nodeName); + if (!node) + throw RuntimeError("Invalid node name in mapping: {}", nodeName); + } - if (type == Type::DATA) { - int first = -1, last = -1; + if (type == Type::DATA) { + int first = -1, last = -1; - if (data.first) { - if (node) - first = node->getInputSignals()->getIndexByName(data.first); + if (data.first) { + if (node) + first = node->getInputSignals()->getIndexByName(data.first); - if (first < 0) { - char *endptr; - first = strtoul(data.first, &endptr, 10); - if (endptr != data.first + strlen(data.first)) - throw RuntimeError("Failed to parse data index in mapping: {}", data.first); - } - } - else { - // Map all signals - data.offset = 0; - length = -1; - goto end; - } + if (first < 0) { + char *endptr; + first = strtoul(data.first, &endptr, 10); + if (endptr != data.first + strlen(data.first)) + throw RuntimeError("Failed to parse data index in mapping: {}", + data.first); + } + } else { + // Map all signals + data.offset = 0; + length = -1; + goto end; + } - if (data.last) { - if (node) - last = node->getInputSignals()->getIndexByName(data.last); + if (data.last) { + if (node) + last = node->getInputSignals()->getIndexByName(data.last); - if (last < 0) { - char *endptr; - last = strtoul(data.last, &endptr, 10); - if (endptr != data.last + strlen(data.last)) - throw RuntimeError("Failed to parse data index in mapping: {}", data.last); - } - } - else - last = first; // single element: data[5] => data[5-5] + if (last < 0) { + char *endptr; + last = strtoul(data.last, &endptr, 10); + if (endptr != data.last + strlen(data.last)) + throw RuntimeError("Failed to parse data index in mapping: {}", + data.last); + } + } else + last = first; // single element: data[5] => data[5-5] - if (last < first) - throw RuntimeError("Invalid data range indices for mapping: {} < {}", last, first); + if (last < first) + throw RuntimeError("Invalid data range indices for mapping: {} < {}", + last, first); - data.offset = first; - length = last - first + 1; - } - else { - length = 1; - } + data.offset = first; + length = last - first + 1; + } else { + length = 1; + } end: - if (length < 0) - length = node->getInputSignals()->size(); + if (length < 0) + length = node->getInputSignals()->size(); - return 0; + return 0; } -std::string MappingEntry::toString(unsigned index) const -{ - assert(length == 0 || (int) index < length); +std::string MappingEntry::toString(unsigned index) const { + assert(length == 0 || (int)index < length); - std::stringstream ss; + std::stringstream ss; - if (node) - ss << node->getNameShort() << "."; + if (node) + ss << node->getNameShort() << "."; - switch (type) { - case Type::STATS: - ss << "stats."; - ss << Stats::metrics[stats.metric].name << "."; - ss << Stats::types[stats.type].name; - break; + switch (type) { + case Type::STATS: + ss << "stats."; + ss << Stats::metrics[stats.metric].name << "."; + ss << Stats::types[stats.type].name; + break; - case Type::HEADER: - ss << "hdr."; - switch (header.type) { - case HeaderType::LENGTH: - ss << "length"; - break; + case Type::HEADER: + ss << "hdr."; + switch (header.type) { + case HeaderType::LENGTH: + ss << "length"; + break; - case HeaderType::SEQUENCE: - ss << "sequence"; - break; + case HeaderType::SEQUENCE: + ss << "sequence"; + break; - default: {} - } - break; + default: { + } + } + break; - case Type::TIMESTAMP: - ss << "ts."; - switch (timestamp.type) { - case TimestampType::ORIGIN: - ss << "origin."; - break; + case Type::TIMESTAMP: + ss << "ts."; + switch (timestamp.type) { + case TimestampType::ORIGIN: + ss << "origin."; + break; - case TimestampType::RECEIVED: - ss << "received."; - break; + case TimestampType::RECEIVED: + ss << "received."; + break; - default: {} - } + default: { + } + } - ss << (index == 0 ? "sec" : "nsec"); - break; + ss << (index == 0 ? "sec" : "nsec"); + break; - case Type::DATA: - if (node && index < node->getInputSignals()->size()) { - auto s = node->getInputSignals()->getByIndex(index); + case Type::DATA: + if (node && index < node->getInputSignals()->size()) { + auto s = node->getInputSignals()->getByIndex(index); - ss << "data[" << s->name << "]"; - } - else - ss << "data[" << index << "]"; - break; + ss << "data[" << s->name << "]"; + } else + ss << "data[" << index << "]"; + break; - case Type::UNKNOWN: - return ""; - } + case Type::UNKNOWN: + return ""; + } - return ss.str(); + return ss.str(); } -Signal::Ptr MappingEntry::toSignal(unsigned index) const -{ - auto name = toString(index); +Signal::Ptr MappingEntry::toSignal(unsigned index) const { + auto name = toString(index); - switch (type) { - case MappingEntry::Type::STATS: - return std::make_shared(name, Stats::metrics[stats.metric].unit, - Stats::types[stats.type].signal_type); + switch (type) { + case MappingEntry::Type::STATS: + return std::make_shared(name, Stats::metrics[stats.metric].unit, + Stats::types[stats.type].signal_type); - case MappingEntry::Type::HEADER: - switch (header.type) { - case MappingEntry::HeaderType::LENGTH: - case MappingEntry::HeaderType::SEQUENCE: - return std::make_shared(name, "", SignalType::INTEGER); - } - break; + case MappingEntry::Type::HEADER: + switch (header.type) { + case MappingEntry::HeaderType::LENGTH: + case MappingEntry::HeaderType::SEQUENCE: + return std::make_shared(name, "", SignalType::INTEGER); + } + break; - case MappingEntry::Type::TIMESTAMP: - switch (index) { - case 0: - return std::make_shared(name, "s", SignalType::INTEGER); - case 1: - return std::make_shared(name, "ns", SignalType::INTEGER); - } - break; + case MappingEntry::Type::TIMESTAMP: + switch (index) { + case 0: + return std::make_shared(name, "s", SignalType::INTEGER); + case 1: + return std::make_shared(name, "ns", SignalType::INTEGER); + } + break; - case MappingEntry::Type::DATA: { - auto sig = std::make_shared(data.signal->name, data.signal->unit, data.signal->type); + case MappingEntry::Type::DATA: { + auto sig = std::make_shared(data.signal->name, data.signal->unit, + data.signal->type); - sig->init = data.signal->init; + sig->init = data.signal->init; - return sig; - } + return sig; + } - case MappingEntry::Type::UNKNOWN: - break; - } + case MappingEntry::Type::UNKNOWN: + break; + } - return std::shared_ptr(); + return std::shared_ptr(); } diff --git a/lib/mapping_list.cpp b/lib/mapping_list.cpp index 504b606fb..82a62cd35 100644 --- a/lib/mapping_list.cpp +++ b/lib/mapping_list.cpp @@ -5,74 +5,72 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include using namespace villas; using namespace villas::node; -int MappingList::parse(json_t *json) -{ - int ret; +int MappingList::parse(json_t *json) { + int ret; - size_t i; - json_t *json_entry; - json_t *json_mapping; + size_t i; + json_t *json_entry; + json_t *json_mapping; - if (json_is_string(json)) { - json_mapping = json_array(); - json_array_append(json_mapping, json); - } - else if (json_is_array(json)) - json_mapping = json_incref(json); - else - return -1; + if (json_is_string(json)) { + json_mapping = json_array(); + json_array_append(json_mapping, json); + } else if (json_is_array(json)) + json_mapping = json_incref(json); + else + return -1; - json_array_foreach(json_mapping, i, json_entry) { - auto me = std::make_shared(); - if (!me) - throw MemoryAllocationError(); + json_array_foreach(json_mapping, i, json_entry) { + auto me = std::make_shared(); + if (!me) + throw MemoryAllocationError(); - ret = me->parse(json_entry); - if (ret) - goto out; + ret = me->parse(json_entry); + if (ret) + goto out; - push_back(me); - } + push_back(me); + } - ret = 0; + ret = 0; -out: json_decref(json_mapping); +out: + json_decref(json_mapping); - return ret; + return ret; } -int MappingList::remap(struct Sample *remapped, const struct Sample *original) const -{ - int ret; +int MappingList::remap(struct Sample *remapped, + const struct Sample *original) const { + int ret; - for (auto me : *this) { - ret = me->update(remapped, original); - if (ret) - return ret; - } + for (auto me : *this) { + ret = me->update(remapped, original); + if (ret) + return ret; + } - return 0; + return 0; } -int MappingList::prepare(NodeList &nodes) -{ - int ret; +int MappingList::prepare(NodeList &nodes) { + int ret; - unsigned off = 0; - for (auto me : *this) { - ret = me->prepare(nodes); - if (ret) - return ret; + unsigned off = 0; + for (auto me : *this) { + ret = me->prepare(nodes); + if (ret) + return ret; - me->offset = off; - off += me->length; - } + me->offset = off; + off += me->length; + } - return 0; + return 0; } diff --git a/lib/memory.cpp b/lib/memory.cpp index 739ca737d..9475dc5fa 100644 --- a/lib/memory.cpp +++ b/lib/memory.cpp @@ -7,151 +7,149 @@ #include -#include -#include #include +#include #include +#include -#include -#include #include +#include +#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::node::memory; -static -std::unordered_map allocations; -static -Logger logger; +static std::unordered_map allocations; +static Logger logger; -int villas::node::memory::init(int hugepages) -{ - int ret; +int villas::node::memory::init(int hugepages) { + int ret; - logger = logging.get("memory"); + logger = logging.get("memory"); - logger->info("Initialize memory sub-system: #hugepages={}", hugepages); + logger->info("Initialize memory sub-system: #hugepages={}", hugepages); - ret = mmap_init(hugepages); - if (ret < 0) - return ret; + ret = mmap_init(hugepages); + if (ret < 0) + return ret; - size_t lock_sz = kernel::getHugePageSize() * hugepages; + size_t lock_sz = kernel::getHugePageSize() * hugepages; - ret = lock(lock_sz); - if (ret) - return ret; + ret = lock(lock_sz); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::memory::lock(size_t sz) -{ - int ret; +int villas::node::memory::lock(size_t sz) { + int ret; - if (!utils::isPrivileged()) { - logger->warn("Running in an unprivileged environment. Memory is not locked to RAM!"); - return 0; - } + if (!utils::isPrivileged()) { + logger->warn( + "Running in an unprivileged environment. Memory is not locked to RAM!"); + return 0; + } #ifdef __linux__ #ifndef __arm__ - struct rlimit l; + struct rlimit l; - // Increase ressource limit for locked memory - ret = getrlimit(RLIMIT_MEMLOCK, &l); - if (ret) - return ret; + // Increase ressource limit for locked memory + ret = getrlimit(RLIMIT_MEMLOCK, &l); + if (ret) + return ret; - if (l.rlim_cur < sz) { - if (l.rlim_max < sz) { - if (getuid() != 0) { - logger->warn("Failed to increase ressource limit of locked memory. Please increase manually by running as root:"); - logger->warn(" $ ulimit -Hl {}", sz); + if (l.rlim_cur < sz) { + if (l.rlim_max < sz) { + if (getuid() != 0) { + logger->warn("Failed to increase ressource limit of locked memory. " + "Please increase manually by running as root:"); + logger->warn(" $ ulimit -Hl {}", sz); - return 0; - } + return 0; + } - l.rlim_max = sz; - } + l.rlim_max = sz; + } - l.rlim_cur = sz; + l.rlim_cur = sz; - ret = setrlimit(RLIMIT_MEMLOCK, &l); - if (ret) - return ret; + ret = setrlimit(RLIMIT_MEMLOCK, &l); + if (ret) + return ret; - logger->debug("Increased ressource limit of locked memory to {} bytes", sz); - } + logger->debug("Increased ressource limit of locked memory to {} bytes", sz); + } #endif // __arm__ #ifdef _POSIX_MEMLOCK - // Lock all current and future memory allocations - ret = mlockall(MCL_CURRENT | MCL_FUTURE); - if (ret) - return -1; + // Lock all current and future memory allocations + ret = mlockall(MCL_CURRENT | MCL_FUTURE); + if (ret) + return -1; #endif // _POSIX_MEMLOCK #endif // __linux__ - return 0; + return 0; } -void * villas::node::memory::alloc(size_t len, struct Type *m) -{ - return alloc_aligned(len, sizeof(void *), m); +void *villas::node::memory::alloc(size_t len, struct Type *m) { + return alloc_aligned(len, sizeof(void *), m); } -void * villas::node::memory::alloc_aligned(size_t len, size_t alignment, struct Type *m) -{ - struct Allocation *ma = m->alloc(len, alignment, m); - if (ma == nullptr) { - logger->warn("Memory allocation of type {} failed. reason={}", m->name, strerror(errno)); - return nullptr; - } +void *villas::node::memory::alloc_aligned(size_t len, size_t alignment, + struct Type *m) { + struct Allocation *ma = m->alloc(len, alignment, m); + if (ma == nullptr) { + logger->warn("Memory allocation of type {} failed. reason={}", m->name, + strerror(errno)); + return nullptr; + } - allocations[ma->address] = ma; + allocations[ma->address] = ma; - logger->debug("Allocated {:#x} bytes of {:#x}-byte-aligned {} memory: {}", ma->length, ma->alignment, ma->type->name, ma->address); + logger->debug("Allocated {:#x} bytes of {:#x}-byte-aligned {} memory: {}", + ma->length, ma->alignment, ma->type->name, ma->address); - return ma->address; + return ma->address; } -int villas::node::memory::free(void *ptr) -{ - int ret; +int villas::node::memory::free(void *ptr) { + int ret; - // Find corresponding memory allocation entry - struct Allocation *ma = allocations[ptr]; - if (!ma) - return -1; + // Find corresponding memory allocation entry + struct Allocation *ma = allocations[ptr]; + if (!ma) + return -1; - logger->debug("Releasing {:#x} bytes of {} memory: {}", ma->length, ma->type->name, ma->address); + logger->debug("Releasing {:#x} bytes of {} memory: {}", ma->length, + ma->type->name, ma->address); - ret = ma->type->free(ma, ma->type); - if (ret) - return ret; + ret = ma->type->free(ma, ma->type); + if (ret) + return ret; - // Remove allocation entry - auto iter = allocations.find(ptr); - if (iter == allocations.end()) - return -1; + // Remove allocation entry + auto iter = allocations.find(ptr); + if (iter == allocations.end()) + return -1; - allocations.erase(iter); - delete ma; + allocations.erase(iter); + delete ma; - return 0; + return 0; } -struct Allocation * villas::node::memory::get_allocation(void *ptr) -{ - return allocations[ptr]; +struct Allocation *villas::node::memory::get_allocation(void *ptr) { + return allocations[ptr]; } struct Type *villas::node::memory::default_type = nullptr; diff --git a/lib/memory/heap.cpp b/lib/memory/heap.cpp index bb891324a..2b6c03bbd 100644 --- a/lib/memory/heap.cpp +++ b/lib/memory/heap.cpp @@ -7,53 +7,48 @@ #include -#include -#include #include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; using namespace villas::node::memory; -static -struct Allocation * heap_alloc(size_t len, size_t alignment, struct Type *m) -{ - int ret; +static struct Allocation *heap_alloc(size_t len, size_t alignment, + struct Type *m) { + int ret; - auto *ma = new struct Allocation; - if (!ma) - throw MemoryAllocationError(); + auto *ma = new struct Allocation; + if (!ma) + throw MemoryAllocationError(); - ma->alignment = alignment; - ma->type = m; - ma->length = len; + ma->alignment = alignment; + ma->type = m; + ma->length = len; - if (ma->alignment < sizeof(void *)) - ma->alignment = sizeof(void *); + if (ma->alignment < sizeof(void *)) + ma->alignment = sizeof(void *); - ret = posix_memalign(&ma->address, ma->alignment, ma->length); - if (ret) { - delete ma; - return nullptr; - } + ret = posix_memalign(&ma->address, ma->alignment, ma->length); + if (ret) { + delete ma; + return nullptr; + } - return ma; + return ma; } -static -int heap_free(struct Allocation *ma, struct Type *m) -{ - ::free(ma->address); +static int heap_free(struct Allocation *ma, struct Type *m) { + ::free(ma->address); - return 0; + return 0; } // List of available memory types -struct Type villas::node::memory::heap = { - .name = "heap", - .flags = (int) Flags::HEAP, - .alignment = 1, - .alloc = heap_alloc, - .free = heap_free -}; +struct Type villas::node::memory::heap = {.name = "heap", + .flags = (int)Flags::HEAP, + .alignment = 1, + .alloc = heap_alloc, + .free = heap_free}; diff --git a/lib/memory/ib.cpp b/lib/memory/ib.cpp index 6421488f5..5a2bce3c0 100644 --- a/lib/memory/ib.cpp +++ b/lib/memory/ib.cpp @@ -7,88 +7,85 @@ #include -#include -#include -#include -#include #include +#include +#include #include +#include +#include using namespace villas; using namespace villas::utils; using namespace villas::node; using namespace villas::node::memory; -struct ibv_mr * villas::node::memory::ib_get_mr(void *ptr) -{ - auto *ma = get_allocation(ptr); +struct ibv_mr *villas::node::memory::ib_get_mr(void *ptr) { + auto *ma = get_allocation(ptr); - return ma->ib.mr; + return ma->ib.mr; } -static -struct Allocation * ib_alloc(size_t len, size_t alignment, struct Type *m) -{ - auto *mi = (struct IB *) m->_vd; +static struct Allocation *ib_alloc(size_t len, size_t alignment, + struct Type *m) { + auto *mi = (struct IB *)m->_vd; - auto *ma = new struct Allocation; - if (!ma) - throw MemoryAllocationError(); + auto *ma = new struct Allocation; + if (!ma) + throw MemoryAllocationError(); - ma->type = m; - ma->length = len; - ma->alignment = alignment; + ma->type = m; + ma->length = len; + ma->alignment = alignment; - ma->parent = mi->parent->alloc(len + sizeof(struct ibv_mr *), alignment, mi->parent); - ma->address = ma->parent->address; + ma->parent = + mi->parent->alloc(len + sizeof(struct ibv_mr *), alignment, mi->parent); + ma->address = ma->parent->address; - if (!mi->pd) { - auto logger = logging.get("memory:ib"); - logger->error("Protection domain is not registered!"); - } + if (!mi->pd) { + auto logger = logging.get("memory:ib"); + logger->error("Protection domain is not registered!"); + } - ma->ib.mr = ibv_reg_mr(mi->pd, ma->address, ma->length, IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE); - if (!ma->ib.mr) { - mi->parent->free(ma->parent, mi->parent); - delete ma; - return nullptr; - } + ma->ib.mr = ibv_reg_mr(mi->pd, ma->address, ma->length, + IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE); + if (!ma->ib.mr) { + mi->parent->free(ma->parent, mi->parent); + delete ma; + return nullptr; + } - return ma; + return ma; } -static -int ib_free(struct Allocation *ma, struct Type *m) -{ - int ret; - auto *mi = (struct IB *) m->_vd; +static int ib_free(struct Allocation *ma, struct Type *m) { + int ret; + auto *mi = (struct IB *)m->_vd; - ibv_dereg_mr(ma->ib.mr); + ibv_dereg_mr(ma->ib.mr); - ret = mi->parent->free(ma->parent, mi->parent); - if (ret) - return ret; + ret = mi->parent->free(ma->parent, mi->parent); + if (ret) + return ret; - return 0; + return 0; } -struct Type * villas::node::memory::ib(NodeCompat *n, struct Type *parent) -{ - auto *i = n->getData(); - auto *mt = (struct Type *) malloc(sizeof(struct Type)); +struct Type *villas::node::memory::ib(NodeCompat *n, struct Type *parent) { + auto *i = n->getData(); + auto *mt = (struct Type *)malloc(sizeof(struct Type)); - mt->name = "ib"; - mt->flags = 0; - mt->alloc = ib_alloc; - mt->free = ib_free; - mt->alignment = 1; + mt->name = "ib"; + mt->flags = 0; + mt->alloc = ib_alloc; + mt->free = ib_free; + mt->alignment = 1; - mt->_vd = malloc(sizeof(struct IB)); + mt->_vd = malloc(sizeof(struct IB)); - auto *mi = (struct memory::IB *) mt->_vd; + auto *mi = (struct memory::IB *)mt->_vd; - mi->pd = i->ctx.pd; - mi->parent = parent; + mi->pd = i->ctx.pd; + mi->parent = parent; - return mt; + return mt; } diff --git a/lib/memory/managed.cpp b/lib/memory/managed.cpp index e977e502a..3a29bc4dc 100644 --- a/lib/memory/managed.cpp +++ b/lib/memory/managed.cpp @@ -5,181 +5,172 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include #include +#include #include -#include #include +#include #include -#include -#include #include #include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; using namespace villas::node::memory; -static -struct Allocation * managed_alloc(size_t len, size_t alignment, struct Type *m) -{ - // Simple first-fit allocation - struct Block *first = (struct Block *) m->_vd; - struct Block *block; +static struct Allocation *managed_alloc(size_t len, size_t alignment, + struct Type *m) { + // Simple first-fit allocation + struct Block *first = (struct Block *)m->_vd; + struct Block *block; - for (block = first; block != nullptr; block = block->next) { - if (block->used) - continue; + for (block = first; block != nullptr; block = block->next) { + if (block->used) + continue; - char* cptr = (char *) block + sizeof(struct Block); - size_t avail = block->length; - uintptr_t uptr = (uintptr_t) cptr; + char *cptr = (char *)block + sizeof(struct Block); + size_t avail = block->length; + uintptr_t uptr = (uintptr_t)cptr; - /* Check alignment first; leave a gap at start of block to assure + /* Check alignment first; leave a gap at start of block to assure * alignment if necessary */ - uintptr_t rem = uptr % alignment; - uintptr_t gap = 0; - if (rem != 0) { - gap = alignment - rem; - if (gap > avail) - continue; // Next aligned address isn't in this block anymore + uintptr_t rem = uptr % alignment; + uintptr_t gap = 0; + if (rem != 0) { + gap = alignment - rem; + if (gap > avail) + continue; // Next aligned address isn't in this block anymore - cptr += gap; - avail -= gap; - } + cptr += gap; + avail -= gap; + } - if (avail >= len) { - if (gap > sizeof(struct Block)) { - /* The alignment gap is big enough to fit another block. + if (avail >= len) { + if (gap > sizeof(struct Block)) { + /* The alignment gap is big enough to fit another block. * The original block descriptor is already at the correct * position, so we just change its len and create a new block * descriptor for the actual block we're handling. */ - block->length = gap - sizeof(struct Block); - struct Block *newblock = (struct Block *) (cptr - sizeof(struct Block)); - newblock->prev = block; - newblock->next = block->next; - block->next = newblock; - newblock->used = false; - newblock->length = len; - block = newblock; - } - else { - /* The gap is too small to fit another block descriptor, so we + block->length = gap - sizeof(struct Block); + struct Block *newblock = (struct Block *)(cptr - sizeof(struct Block)); + newblock->prev = block; + newblock->next = block->next; + block->next = newblock; + newblock->used = false; + newblock->length = len; + block = newblock; + } else { + /* The gap is too small to fit another block descriptor, so we * must account for the gap length in the block length. */ - block->length = len + gap; - } + block->length = len + gap; + } - if (avail > len + sizeof(struct Block)) { - // Imperfect fit, so create another block for the remaining part - struct Block *newblock = (struct Block *) (cptr + len); - newblock->prev = block; - newblock->next = block->next; - block->next = newblock; + if (avail > len + sizeof(struct Block)) { + // Imperfect fit, so create another block for the remaining part + struct Block *newblock = (struct Block *)(cptr + len); + newblock->prev = block; + newblock->next = block->next; + block->next = newblock; - if (newblock->next) - newblock->next->prev = newblock; + if (newblock->next) + newblock->next->prev = newblock; - newblock->used = false; - newblock->length = avail - len - sizeof(struct Block); - } - else { - /* If this block was larger than the requested length, but only + newblock->used = false; + newblock->length = avail - len - sizeof(struct Block); + } else { + /* If this block was larger than the requested length, but only * by less than sizeof(struct Block), we may have wasted * memory by previous assignments to block->length. */ - block->length = avail; - } + block->length = avail; + } - block->used = true; + block->used = true; - auto *ma = new struct Allocation; - if (!ma) - throw MemoryAllocationError(); + auto *ma = new struct Allocation; + if (!ma) + throw MemoryAllocationError(); - ma->address = cptr; - ma->type = m; - ma->alignment = alignment; - ma->length = len; - ma->managed.block = block; + ma->address = cptr; + ma->type = m; + ma->alignment = alignment; + ma->length = len; + ma->managed.block = block; - return ma; - } - } + return ma; + } + } - // No suitable block found - return nullptr; + // No suitable block found + return nullptr; } -static -int managed_free(struct Allocation *ma, struct Type *m) -{ - struct Block *block = ma->managed.block; +static int managed_free(struct Allocation *ma, struct Type *m) { + struct Block *block = ma->managed.block; - // Try to merge it with neighbouring free blocks - if (block->prev && !block->prev->used && - block->next && !block->next->used) { - // Special case first: both previous and next block are unused - block->prev->length += block->length + block->next->length + 2 * sizeof(struct Block); - block->prev->next = block->next->next; - if (block->next->next) - block->next->next->prev = block->prev; - } - else if (block->prev && !block->prev->used) { - block->prev->length += block->length + sizeof(struct Block); - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else if (block->next && !block->next->used) { - block->length += block->next->length + sizeof(struct Block); - block->next = block->next->next; - if (block->next) - block->next->prev = block; - } - else { - // no neighbouring free block, so just mark it as free - block->used = false; - } + // Try to merge it with neighbouring free blocks + if (block->prev && !block->prev->used && block->next && !block->next->used) { + // Special case first: both previous and next block are unused + block->prev->length += + block->length + block->next->length + 2 * sizeof(struct Block); + block->prev->next = block->next->next; + if (block->next->next) + block->next->next->prev = block->prev; + } else if (block->prev && !block->prev->used) { + block->prev->length += block->length + sizeof(struct Block); + block->prev->next = block->next; + if (block->next) + block->next->prev = block->prev; + } else if (block->next && !block->next->used) { + block->length += block->next->length + sizeof(struct Block); + block->next = block->next->next; + if (block->next) + block->next->prev = block; + } else { + // no neighbouring free block, so just mark it as free + block->used = false; + } - return 0; + return 0; } -struct Type * villas::node::memory::managed(void *ptr, size_t len) -{ - struct Type *mt = (struct Type *) ptr; - struct Block *mb; - char *cptr = (char *) ptr; +struct Type *villas::node::memory::managed(void *ptr, size_t len) { + struct Type *mt = (struct Type *)ptr; + struct Block *mb; + char *cptr = (char *)ptr; - if (len < sizeof(struct Type) + sizeof(struct Block)) { - auto logger = logging.get("memory:managed"); - logger->info("Passed region is too small"); - return nullptr; - } + if (len < sizeof(struct Type) + sizeof(struct Block)) { + auto logger = logging.get("memory:managed"); + logger->info("Passed region is too small"); + return nullptr; + } - // Initialize type - mt->name = "managed"; - mt->flags = 0; - mt->alloc = managed_alloc; - mt->free = managed_free; - mt->alignment = 1; + // Initialize type + mt->name = "managed"; + mt->flags = 0; + mt->alloc = managed_alloc; + mt->free = managed_free; + mt->alignment = 1; - cptr += ALIGN(sizeof(struct Type), sizeof(void *)); + cptr += ALIGN(sizeof(struct Type), sizeof(void *)); - // Initialize first free memory block - mb = (struct Block *) cptr; - mb->prev = nullptr; - mb->next = nullptr; - mb->used = false; + // Initialize first free memory block + mb = (struct Block *)cptr; + mb->prev = nullptr; + mb->next = nullptr; + mb->used = false; - cptr += ALIGN(sizeof(struct Block), sizeof(void *)); + cptr += ALIGN(sizeof(struct Block), sizeof(void *)); - mb->length = len - (cptr - (char *) ptr); + mb->length = len - (cptr - (char *)ptr); - mt->_vd = (void *) mb; + mt->_vd = (void *)mb; - return mt; + return mt; } diff --git a/lib/memory/mmap.cpp b/lib/memory/mmap.cpp index 5b18bb57d..3023ce374 100644 --- a/lib/memory/mmap.cpp +++ b/lib/memory/mmap.cpp @@ -5,169 +5,162 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include #include -#include #include +#include #include // Required to allocate hugepages on Apple OS X #ifdef __MACH__ - #include +#include #endif // __MACH__ +#include #include +#include #include #include -#include -#include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; using namespace villas::node::memory; -static -size_t pgsz = -1; +static size_t pgsz = -1; -static -size_t hugepgsz = -1; +static size_t hugepgsz = -1; -static -Logger logger; +static Logger logger; -int villas::node::memory::mmap_init(int hugepages) -{ - logger = logging.get("memory:mmap"); +int villas::node::memory::mmap_init(int hugepages) { + logger = logging.get("memory:mmap"); - pgsz = kernel::getPageSize(); - if (pgsz < 0) - return -1; + pgsz = kernel::getPageSize(); + if (pgsz < 0) + return -1; - if (hugepages == 0) { - logger->warn("Hugepage allocator disabled."); + if (hugepages == 0) { + logger->warn("Hugepage allocator disabled."); - default_type = &mmap; - return 0; - } + default_type = &mmap; + return 0; + } - if (!utils::isPrivileged()) { - logger->warn("Running in an unprivileged environment. Hugepages are not used!"); + if (!utils::isPrivileged()) { + logger->warn( + "Running in an unprivileged environment. Hugepages are not used!"); - default_type = &mmap; - return 0; - } + default_type = &mmap; + return 0; + } - hugepgsz = kernel::getHugePageSize(); - if (hugepgsz < 0) { - logger->warn("Failed to determine hugepage size."); + hugepgsz = kernel::getHugePageSize(); + if (hugepgsz < 0) { + logger->warn("Failed to determine hugepage size."); - return -1; - } + return -1; + } #if defined(__linux__) && defined(__x86_64__) - int ret, pagecnt; + int ret, pagecnt; - pagecnt = kernel::getNrHugepages(); - if (pagecnt < hugepages) { - ret = kernel::setNrHugepages(hugepages); - if (ret) { - logger->warn("Failed to reserved hugepages. Please reserve manually by running as root:"); - logger->warn(" $ echo {} > /proc/sys/vm/nr_hugepages", hugepages); + pagecnt = kernel::getNrHugepages(); + if (pagecnt < hugepages) { + ret = kernel::setNrHugepages(hugepages); + if (ret) { + logger->warn("Failed to reserved hugepages. Please reserve manually by " + "running as root:"); + logger->warn(" $ echo {} > /proc/sys/vm/nr_hugepages", hugepages); - return -1; - } + return -1; + } - logger->debug("Increased number of reserved hugepages from {} to {}", pagecnt, hugepages); - } + logger->debug("Increased number of reserved hugepages from {} to {}", + pagecnt, hugepages); + } - default_type = &mmap_hugetlb; + default_type = &mmap_hugetlb; #else - logger->debug("Hugepages not supported on this system. Falling back to standard mmap() allocator."); + logger->debug("Hugepages not supported on this system. Falling back to " + "standard mmap() allocator."); - default_type = &mmap; + default_type = &mmap; #endif - return 0; + return 0; } // Allocate memory backed by mmaps with malloc() like interface -static -struct Allocation * mmap_alloc(size_t len, size_t alignment, struct Type *m) -{ - int flags, fd; - size_t sz; +static struct Allocation *mmap_alloc(size_t len, size_t alignment, + struct Type *m) { + int flags, fd; + size_t sz; - auto *ma = new struct Allocation; - if (!ma) - throw MemoryAllocationError(); + auto *ma = new struct Allocation; + if (!ma) + throw MemoryAllocationError(); - if (m->flags & (int) Flags::HUGEPAGE) { + if (m->flags & (int)Flags::HUGEPAGE) { #ifdef __linux__ - flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB; + flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB; #else - flags = MAP_PRIVATE | MAP_ANONYMOUS; + flags = MAP_PRIVATE | MAP_ANONYMOUS; #endif #ifdef __MACH__ - fd = VM_FLAGS_SUPERPAGE_SIZE_2MB; + fd = VM_FLAGS_SUPERPAGE_SIZE_2MB; #else - fd = -1; + fd = -1; #endif - sz = hugepgsz; - } - else { - flags = MAP_PRIVATE | MAP_ANONYMOUS; - fd = -1; + sz = hugepgsz; + } else { + flags = MAP_PRIVATE | MAP_ANONYMOUS; + fd = -1; - sz = pgsz; - } + sz = pgsz; + } - /* We must make sure that len is a multiple of the page size + /* We must make sure that len is a multiple of the page size * * See: https://lkml.org/lkml/2014/10/22/925 */ - ma->length = ALIGN(len, sz); - ma->alignment = ALIGN(alignment, sz); - ma->type = m; + ma->length = ALIGN(len, sz); + ma->alignment = ALIGN(alignment, sz); + ma->type = m; - ma->address = ::mmap(nullptr, ma->length, PROT_READ | PROT_WRITE, flags, fd, 0); - if (ma->address == MAP_FAILED) { - delete ma; - return nullptr; - } + ma->address = + ::mmap(nullptr, ma->length, PROT_READ | PROT_WRITE, flags, fd, 0); + if (ma->address == MAP_FAILED) { + delete ma; + return nullptr; + } - return ma; + return ma; } -static -int mmap_free(struct Allocation *ma, struct Type *m) -{ - int ret; +static int mmap_free(struct Allocation *ma, struct Type *m) { + int ret; - ret = munmap(ma->address, ma->length); - if (ret) - return ret; + ret = munmap(ma->address, ma->length); + if (ret) + return ret; - return 0; + return 0; } -struct Type memory::mmap = { - .name = "mmap", - .flags = (int) Flags::MMAP, - .alignment = 12, // 4k page - .alloc = mmap_alloc, - .free = mmap_free -}; +struct Type memory::mmap = {.name = "mmap", + .flags = (int)Flags::MMAP, + .alignment = 12, // 4k page + .alloc = mmap_alloc, + .free = mmap_free}; -struct Type memory::mmap_hugetlb = { - .name = "mmap_hugetlb", - .flags = (int) Flags::MMAP | (int) Flags::HUGEPAGE, - .alignment = 21, // 2 MiB hugepage - .alloc = mmap_alloc, - .free = mmap_free -}; +struct Type memory::mmap_hugetlb = {.name = "mmap_hugetlb", + .flags = + (int)Flags::MMAP | (int)Flags::HUGEPAGE, + .alignment = 21, // 2 MiB hugepage + .alloc = mmap_alloc, + .free = mmap_free}; diff --git a/lib/node.cpp b/lib/node.cpp index 99597b5db..483573e9a 100644 --- a/lib/node.cpp +++ b/lib/node.cpp @@ -5,522 +5,478 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include #include +#include #ifdef __linux__ - #include - #include +#include +#include #endif -#include +#include #include #include -#include +#include #include +#include +#include #include #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include #ifdef WITH_NETEM - #include - #include - #include - #include +#include +#include +#include +#include #endif // WITH_NETEM using namespace villas; using namespace villas::node; using namespace villas::utils; -Node::Node(const uuid_t &id, const std::string &name) : - logger(logging.get("node")), - sequence_init(0), - sequence(0), - in(NodeDirection::Direction::IN, this), - out(NodeDirection::Direction::OUT, this), +Node::Node(const uuid_t &id, const std::string &name) + : logger(logging.get("node")), sequence_init(0), sequence(0), + in(NodeDirection::Direction::IN, this), + out(NodeDirection::Direction::OUT, this), #ifdef __linux__ - fwmark(-1), + fwmark(-1), #endif // __linux__ #ifdef WITH_NETEM - tc_qdisc(nullptr), - tc_classifier(nullptr), + tc_qdisc(nullptr), tc_classifier(nullptr), #endif // WITH_NETEM - state(State::INITIALIZED), - enabled(true), - config(nullptr), - name_short(name), - affinity(-1), // all cores - factory(nullptr) -{ - if (uuid_is_null(id)) { - uuid_generate_random(uuid); - } else { - uuid_copy(uuid, id); - } + state(State::INITIALIZED), enabled(true), config(nullptr), + name_short(name), affinity(-1), // all cores + factory(nullptr) { + if (uuid_is_null(id)) { + uuid_generate_random(uuid); + } else { + uuid_copy(uuid, id); + } - if (!name_short.empty()) { - name_long = fmt::format(CLR_RED("{}"), name_short); - } - else if (name_short.empty()) { - name_short = ""; - name_long = CLR_RED(""); - } + if (!name_short.empty()) { + name_long = fmt::format(CLR_RED("{}"), name_short); + } else if (name_short.empty()) { + name_short = ""; + name_long = CLR_RED(""); + } } -Node::~Node() -{ +Node::~Node() { #ifdef WITH_NETEM - rtnl_qdisc_put(tc_qdisc); - rtnl_cls_put(tc_classifier); + rtnl_qdisc_put(tc_qdisc); + rtnl_cls_put(tc_classifier); #endif // WITH_NETEM - factory->instances.remove(this); + factory->instances.remove(this); } -int Node::prepare() -{ - int ret; +int Node::prepare() { + int ret; - ret = in.prepare(); - if (ret) - return ret; + ret = in.prepare(); + if (ret) + return ret; - ret = out.prepare(); - if (ret) - return ret; + ret = out.prepare(); + if (ret) + return ret; - state = State::PREPARED; + state = State::PREPARED; - return 0; + return 0; } -int Node::parse(json_t *json) -{ - assert(state == State::INITIALIZED || - state == State::PARSED || - state == State::CHECKED); +int Node::parse(json_t *json) { + assert(state == State::INITIALIZED || state == State::PARSED || + state == State::CHECKED); - int ret, en = enabled, init_seq = -1; + int ret, en = enabled, init_seq = -1; - json_error_t err; - json_t *json_netem = nullptr; + json_error_t err; + json_t *json_netem = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: b, s?: i }", - "enabled", &en, - "initial_sequenceno", &init_seq - ); - if (ret) - return ret; + ret = json_unpack_ex(json, &err, 0, "{ s?: b, s?: i }", "enabled", &en, + "initial_sequenceno", &init_seq); + if (ret) + return ret; - if (init_seq >= 0) - sequence_init = init_seq; + if (init_seq >= 0) + sequence_init = init_seq; #ifdef __linux__ - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o, s?: i } }", - "out", - "netem", &json_netem, - "fwmark", &fwmark - ); - if (ret) - return ret; + ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o, s?: i } }", "out", + "netem", &json_netem, "fwmark", &fwmark); + if (ret) + return ret; #endif // __linux__ - enabled = en; + enabled = en; - if (json_netem) { + if (json_netem) { #ifdef WITH_NETEM - int enabled = 1; + int enabled = 1; - ret = json_unpack_ex(json_netem, &err, 0, "{ s?: b }", "enabled", &enabled); - if (ret) - return ret; + ret = json_unpack_ex(json_netem, &err, 0, "{ s?: b }", "enabled", &enabled); + if (ret) + return ret; - if (enabled) - kernel::tc::netem_parse(&tc_qdisc, json_netem); - else - tc_qdisc = nullptr; + if (enabled) + kernel::tc::netem_parse(&tc_qdisc, json_netem); + else + tc_qdisc = nullptr; #endif // WITH_NETEM - } + } - struct { - const char *str; - struct NodeDirection *dir; - } dirs[] = { - { "in", &in }, - { "out", &out } - }; + struct { + const char *str; + struct NodeDirection *dir; + } dirs[] = {{"in", &in}, {"out", &out}}; - const char *fields[] = { "signals", "builtin", "vectorize", "hooks" }; + const char *fields[] = {"signals", "builtin", "vectorize", "hooks"}; - for (unsigned j = 0; j < ARRAY_LEN(dirs); j++) { - json_t *json_dir = json_object_get(json, dirs[j].str); + for (unsigned j = 0; j < ARRAY_LEN(dirs); j++) { + json_t *json_dir = json_object_get(json, dirs[j].str); - // Skip if direction is unused - if (!json_dir) { - json_dir = json_pack("{ s: b }", "enabled", 0); - } + // Skip if direction is unused + if (!json_dir) { + json_dir = json_pack("{ s: b }", "enabled", 0); + } - // Copy missing fields from main node config to direction config - for (unsigned i = 0; i < ARRAY_LEN(fields); i++) { - json_t *json_field_dir = json_object_get(json_dir, fields[i]); - json_t *json_field_node = json_object_get(json, fields[i]); + // Copy missing fields from main node config to direction config + for (unsigned i = 0; i < ARRAY_LEN(fields); i++) { + json_t *json_field_dir = json_object_get(json_dir, fields[i]); + json_t *json_field_node = json_object_get(json, fields[i]); - if (json_field_node && !json_field_dir) - json_object_set(json_dir, fields[i], json_field_node); - } + if (json_field_node && !json_field_dir) + json_object_set(json_dir, fields[i], json_field_node); + } - ret = dirs[j].dir->parse(json_dir); - if (ret) - return ret; - } + ret = dirs[j].dir->parse(json_dir); + if (ret) + return ret; + } - config = json; + config = json; - return 0; + return 0; } -int Node::check() -{ - assert(state == State::CHECKED || - state == State::PARSED || - state == State::INITIALIZED); +int Node::check() { + assert(state == State::CHECKED || state == State::PARSED || + state == State::INITIALIZED); - in.check(); - out.check(); + in.check(); + out.check(); - state = State::CHECKED; + state = State::CHECKED; - return 0; + return 0; } -int Node::start() -{ - int ret; +int Node::start() { + int ret; - assert(state == State::PREPARED); + assert(state == State::PREPARED); - logger->info("Starting node {}", getNameFull()); + logger->info("Starting node {}", getNameFull()); - ret = in.start(); - if (ret) - return ret; + ret = in.start(); + if (ret) + return ret; - ret = out.start(); - if (ret) - return ret; + ret = out.start(); + if (ret) + return ret; #ifdef __linux__ - // Set fwmark for outgoing packets if netem is enabled for this node - if (fwmark >= 0) { - for (int fd : getNetemFDs()) { - ret = setsockopt(fd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)); - if (ret) - throw RuntimeError("Failed to set FW mark for outgoing packets"); - else - logger->debug("Set FW mark for socket (sd={}) to {}", fd, fwmark); - } - } + // Set fwmark for outgoing packets if netem is enabled for this node + if (fwmark >= 0) { + for (int fd : getNetemFDs()) { + ret = setsockopt(fd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)); + if (ret) + throw RuntimeError("Failed to set FW mark for outgoing packets"); + else + logger->debug("Set FW mark for socket (sd={}) to {}", fd, fwmark); + } + } #endif // __linux__ - state = State::STARTED; - sequence = sequence_init; + state = State::STARTED; + sequence = sequence_init; - return 0; + return 0; } -int Node::stop() -{ - int ret; +int Node::stop() { + int ret; - if (state != State::STOPPING && - state != State::STARTED && - state != State::CONNECTED && - state != State::PENDING_CONNECT) - return 0; + if (state != State::STOPPING && state != State::STARTED && + state != State::CONNECTED && state != State::PENDING_CONNECT) + return 0; - logger->info("Stopping node"); - setState(State::STOPPING); + logger->info("Stopping node"); + setState(State::STOPPING); - ret = in.stop(); - if (ret) - return ret; + ret = in.stop(); + if (ret) + return ret; - ret = out.stop(); - if (ret) - return ret; + ret = out.stop(); + if (ret) + return ret; - return 0; + return 0; } -int Node::restart() -{ - int ret; +int Node::restart() { + int ret; - assert(state == State::STARTED); + assert(state == State::STARTED); - logger->info("Restarting node"); + logger->info("Restarting node"); - ret = stop(); - if (ret) - return ret; + ret = stop(); + if (ret) + return ret; - ret = start(); - if (ret) - return ret; + ret = start(); + if (ret) + return ret; - return 0; + return 0; } -int Node::read(struct Sample * smps[], unsigned cnt) -{ - int toread, readd, nread = 0; - unsigned vect; +int Node::read(struct Sample *smps[], unsigned cnt) { + int toread, readd, nread = 0; + unsigned vect; - if (state == State::PAUSED || state == State::PENDING_CONNECT) - return 0; - else if (state != State::STARTED && state != State::CONNECTED) - return -1; + if (state == State::PAUSED || state == State::PENDING_CONNECT) + return 0; + else if (state != State::STARTED && state != State::CONNECTED) + return -1; - vect = factory->getVectorize(); - if (!vect) - vect = cnt; + vect = factory->getVectorize(); + if (!vect) + vect = cnt; - while (cnt - nread > 0) { - toread = MIN(cnt - nread, vect); - readd = _read(&smps[nread], toread); - if (readd < 0) - return readd; + while (cnt - nread > 0) { + toread = MIN(cnt - nread, vect); + readd = _read(&smps[nread], toread); + if (readd < 0) + return readd; - nread += readd; - } + nread += readd; + } #ifdef WITH_HOOKS - // Run read hooks - int rread = in.hooks.process(smps, nread); - if (rread < 0) - return rread; + // Run read hooks + int rread = in.hooks.process(smps, nread); + if (rread < 0) + return rread; - int skipped = nread - rread; - if (skipped > 0) { - if (stats != nullptr) - stats->update(Stats::Metric::SMPS_SKIPPED, skipped); + int skipped = nread - rread; + if (skipped > 0) { + if (stats != nullptr) + stats->update(Stats::Metric::SMPS_SKIPPED, skipped); - logger->debug("Received {} samples of which {} have been skipped", nread, skipped); - } - else - logger->debug("Received {} samples", nread); + logger->debug("Received {} samples of which {} have been skipped", nread, + skipped); + } else + logger->debug("Received {} samples", nread); - return rread; + return rread; #else - logger->debug("Received {} samples", nread); + logger->debug("Received {} samples", nread); - return nread; + return nread; #endif // WITH_HOOKS } -int Node::write(struct Sample * smps[], unsigned cnt) -{ - int tosend, sent, nsent = 0; - unsigned vect; +int Node::write(struct Sample *smps[], unsigned cnt) { + int tosend, sent, nsent = 0; + unsigned vect; - if (state == State::PAUSED || state == State::PENDING_CONNECT) - return 0; - else if (state != State::STARTED && state != State::CONNECTED) - return -1; + if (state == State::PAUSED || state == State::PENDING_CONNECT) + return 0; + else if (state != State::STARTED && state != State::CONNECTED) + return -1; #ifdef WITH_HOOKS - // Run write hooks - cnt = out.hooks.process(smps, cnt); - if (cnt <= 0) - return cnt; + // Run write hooks + cnt = out.hooks.process(smps, cnt); + if (cnt <= 0) + return cnt; #endif // WITH_HOOKS - vect = getFactory()->getVectorize(); - if (!vect) - vect = cnt; + vect = getFactory()->getVectorize(); + if (!vect) + vect = cnt; - while (cnt - nsent > 0) { - tosend = MIN(cnt - nsent, vect); - sent = _write(&smps[nsent], tosend); - if (sent < 0) - return sent; + while (cnt - nsent > 0) { + tosend = MIN(cnt - nsent, vect); + sent = _write(&smps[nsent], tosend); + if (sent < 0) + return sent; - nsent += sent; - logger->debug("Sent {} samples", sent); - } + nsent += sent; + logger->debug("Sent {} samples", sent); + } - return nsent; + return nsent; } -const std::string & Node::getNameFull() -{ - if (name_full.empty()) { - name_full = fmt::format("{}: uuid={}, #in.signals={}/{}, #in.hooks={}, #out.hooks={}, in.vectorize={}, out.vectorize={}", - getName(), uuid::toString(uuid).c_str(), - getInputSignals(false)->size(), - getInputSignals(true)->size(), - in.hooks.size(), out.hooks.size(), - in.vectorize, out.vectorize - ); +const std::string &Node::getNameFull() { + if (name_full.empty()) { + name_full = fmt::format("{}: uuid={}, #in.signals={}/{}, #in.hooks={}, " + "#out.hooks={}, in.vectorize={}, out.vectorize={}", + getName(), uuid::toString(uuid).c_str(), + getInputSignals(false)->size(), + getInputSignals(true)->size(), in.hooks.size(), + out.hooks.size(), in.vectorize, out.vectorize); #ifdef WITH_NETEM - name_full += fmt::format(", out.netem={}", tc_qdisc ? "yes" : "no"); + name_full += fmt::format(", out.netem={}", tc_qdisc ? "yes" : "no"); - if (tc_qdisc) - name_full += fmt::format(", fwmark={}", fwmark); + if (tc_qdisc) + name_full += fmt::format(", fwmark={}", fwmark); #endif // WITH_NETEM - if (out.path) { - name_full += fmt::format(", #out.signals={}/{}", - getOutputSignals(false) ? getOutputSignals(false)->size() : 0, - getOutputSignals() ? getOutputSignals()->size() : 0); + if (out.path) { + name_full += fmt::format( + ", #out.signals={}/{}", + getOutputSignals(false) ? getOutputSignals(false)->size() : 0, + getOutputSignals() ? getOutputSignals()->size() : 0); - name_full += fmt::format(", out.path={}", out.path->toString()); - } + name_full += fmt::format(", out.path={}", out.path->toString()); + } - // Append node-type specific details - auto details = getDetails(); - if (!details.empty()) - name_full += fmt::format(", {}", details); - } + // Append node-type specific details + auto details = getDetails(); + if (!details.empty()) + name_full += fmt::format(", {}", details); + } - return name_full; + return name_full; } -SignalList::Ptr Node::getInputSignals(bool after_hooks) const -{ - return in.getSignals(after_hooks); +SignalList::Ptr Node::getInputSignals(bool after_hooks) const { + return in.getSignals(after_hooks); } -SignalList::Ptr Node::getOutputSignals(bool after_hooks) const -{ - if (out.path) - return out.path->getOutputSignals(); +SignalList::Ptr Node::getOutputSignals(bool after_hooks) const { + if (out.path) + return out.path->getOutputSignals(); - return nullptr; + return nullptr; } -unsigned Node::getInputSignalsMaxCount() const -{ - return in.getSignalsMaxCount(); +unsigned Node::getInputSignalsMaxCount() const { + return in.getSignalsMaxCount(); } -unsigned Node::getOutputSignalsMaxCount() const -{ - if (out.path) - return out.path->getOutputSignalsMaxCount(); +unsigned Node::getOutputSignalsMaxCount() const { + if (out.path) + return out.path->getOutputSignalsMaxCount(); - return 0; + return 0; } -bool Node::isValidName(const std::string &name) -{ - std::regex re(RE_NODE_NAME); +bool Node::isValidName(const std::string &name) { + std::regex re(RE_NODE_NAME); - return std::regex_match(name, re); + return std::regex_match(name, re); } -json_t * Node::toJson() const -{ - json_t *json_node; - json_t *json_signals_in = nullptr; - json_t *json_signals_out = nullptr; +json_t *Node::toJson() const { + json_t *json_node; + json_t *json_signals_in = nullptr; + json_t *json_signals_out = nullptr; - json_signals_in = getInputSignals()->toJson(); + json_signals_in = getInputSignals()->toJson(); - auto output_signals = getOutputSignals(); - if (output_signals) - json_signals_out = output_signals->toJson(); + auto output_signals = getOutputSignals(); + if (output_signals) + json_signals_out = output_signals->toJson(); - json_node = json_pack("{ s: s, s: s, s: s, s: i, s: { s: i, s: o? }, s: { s: i, s: o? } }", - "name", getNameShort().c_str(), - "uuid", uuid::toString(uuid).c_str(), - "state", stateToString(state).c_str(), - "affinity", affinity, - "in", - "vectorize", in.vectorize, - "signals", json_signals_in, - "out", - "vectorize", out.vectorize, - "signals", json_signals_out - ); + json_node = json_pack( + "{ s: s, s: s, s: s, s: i, s: { s: i, s: o? }, s: { s: i, s: o? } }", + "name", getNameShort().c_str(), "uuid", uuid::toString(uuid).c_str(), + "state", stateToString(state).c_str(), "affinity", affinity, "in", + "vectorize", in.vectorize, "signals", json_signals_in, "out", "vectorize", + out.vectorize, "signals", json_signals_out); - if (stats) - json_object_set_new(json_node, "stats", stats->toJson()); + if (stats) + json_object_set_new(json_node, "stats", stats->toJson()); - auto *status = _readStatus(); - if (status) - json_object_set_new(json_node, "status", status); + auto *status = _readStatus(); + if (status) + json_object_set_new(json_node, "status", status); - /* Add all additional fields of node here. + /* Add all additional fields of node here. * This can be used for metadata */ - json_object_update(json_node, config); + json_object_update(json_node, config); - return json_node; + return json_node; } -void Node::swapSignals() { - SWAP(in.signals, out.signals); +void Node::swapSignals() { SWAP(in.signals, out.signals); } + +Node *NodeFactory::make(json_t *json, const uuid_t &id, + const std::string &name) { + int ret; + std::string type; + Node *n; + + if (json_is_object(json)) + throw ConfigError(json, "node-config-node", + "Node configuration must be an object"); + + json_t *json_type = json_object_get(json, "type"); + + type = json_string_value(json_type); + + n = NodeFactory::make(type, id, name); + if (!n) + return nullptr; + + ret = n->parse(json); + if (ret) { + delete n; + return nullptr; + } + + return n; } -Node * NodeFactory::make(json_t *json, const uuid_t &id, const std::string &name) -{ - int ret; - std::string type; - Node *n; +Node *NodeFactory::make(const std::string &type, const uuid_t &id, + const std::string &name) { + NodeFactory *nf = plugin::registry->lookup(type); + if (!nf) + throw RuntimeError("Unknown node-type: {}", type); - if (json_is_object(json)) - throw ConfigError(json, "node-config-node", "Node configuration must be an object"); - - json_t *json_type = json_object_get(json, "type"); - - type = json_string_value(json_type); - - n = NodeFactory::make(type, id, name); - if (!n) - return nullptr; - - ret = n->parse(json); - if (ret) { - delete n; - return nullptr; - } - - return n; + return nf->make(id, name); } -Node * NodeFactory::make(const std::string &type, const uuid_t &id, const std::string &name) -{ - NodeFactory *nf = plugin::registry->lookup(type); - if (!nf) - throw RuntimeError("Unknown node-type: {}", type); +int NodeFactory::start(SuperNode *sn) { + getLogger()->info("Initialized node type which is used by {} nodes", + instances.size()); - return nf->make(id, name); + state = State::STARTED; + + return 0; } -int NodeFactory::start(SuperNode *sn) -{ - getLogger()->info("Initialized node type which is used by {} nodes", instances.size()); +int NodeFactory::stop() { + getLogger()->info("De-initialized node type"); - state = State::STARTED; + state = State::STOPPED; - return 0; -} - -int NodeFactory::stop() -{ - getLogger()->info("De-initialized node type"); - - state = State::STOPPED; - - return 0; + return 0; } diff --git a/lib/node_capi.cpp b/lib/node_capi.cpp index a0fcea568..92ee338e5 100644 --- a/lib/node_capi.cpp +++ b/lib/node_capi.cpp @@ -8,216 +8,183 @@ #include extern "C" { - #include +#include } using namespace villas; using namespace villas::node; -vnode * node_new(const char *id_str, const char *json_str) -{ - json_error_t err; - uuid_t id; - uuid_parse(id_str, id); - auto *json = json_loads(json_str, 0, &err); - return (vnode *) NodeFactory::make(json, id); +vnode *node_new(const char *id_str, const char *json_str) { + json_error_t err; + uuid_t id; + uuid_parse(id_str, id); + auto *json = json_loads(json_str, 0, &err); + return (vnode *)NodeFactory::make(json, id); } -int node_prepare(vnode *n) -{ - auto *nc = (Node *) n; - return nc->prepare(); +int node_prepare(vnode *n) { + auto *nc = (Node *)n; + return nc->prepare(); } -int node_check(vnode *n) -{ - auto *nc = (Node *) n; - return nc->check(); +int node_check(vnode *n) { + auto *nc = (Node *)n; + return nc->check(); } -int node_start(vnode *n) -{ - auto *nc = (Node *) n; - return nc->start(); +int node_start(vnode *n) { + auto *nc = (Node *)n; + return nc->start(); } -int node_stop(vnode *n) -{ - auto *nc = (Node *) n; - return nc->stop(); +int node_stop(vnode *n) { + auto *nc = (Node *)n; + return nc->stop(); } -int node_pause(vnode *n) -{ - auto *nc = (Node *) n; - return nc->pause(); +int node_pause(vnode *n) { + auto *nc = (Node *)n; + return nc->pause(); } -int node_resume(vnode *n) -{ - auto *nc = (Node *) n; - return nc->resume(); +int node_resume(vnode *n) { + auto *nc = (Node *)n; + return nc->resume(); } -int node_restart(vnode *n) -{ - auto *nc = (Node *) n; - return nc->restart(); +int node_restart(vnode *n) { + auto *nc = (Node *)n; + return nc->restart(); } -int node_destroy(vnode *n) -{ - auto *nc = (Node *) n; - nc->~Node(); - return 0; +int node_destroy(vnode *n) { + auto *nc = (Node *)n; + nc->~Node(); + return 0; } -const char * node_name(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getName().c_str(); +const char *node_name(vnode *n) { + auto *nc = (Node *)n; + return nc->getName().c_str(); } -const char * node_name_short(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getNameShort().c_str(); +const char *node_name_short(vnode *n) { + auto *nc = (Node *)n; + return nc->getNameShort().c_str(); } -const char * node_name_full(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getNameFull().c_str(); +const char *node_name_full(vnode *n) { + auto *nc = (Node *)n; + return nc->getNameFull().c_str(); } -const char * node_details(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getDetails().c_str(); +const char *node_details(vnode *n) { + auto *nc = (Node *)n; + return nc->getDetails().c_str(); } -unsigned node_input_signals_max_cnt(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getInputSignalsMaxCount(); +unsigned node_input_signals_max_cnt(vnode *n) { + auto *nc = (Node *)n; + return nc->getInputSignalsMaxCount(); } -unsigned node_output_signals_max_cnt(vnode *n) -{ - auto *nc = (Node *) n; - return nc->getOutputSignalsMaxCount(); +unsigned node_output_signals_max_cnt(vnode *n) { + auto *nc = (Node *)n; + return nc->getOutputSignalsMaxCount(); } -int node_reverse(vnode *n) -{ - auto *nc = (Node *) n; - return nc->reverse(); +int node_reverse(vnode *n) { + auto *nc = (Node *)n; + return nc->reverse(); } -int node_read(vnode *n, vsample **smps, unsigned cnt) -{ - auto *nc = (Node *) n; - return nc->read((villas::node::Sample**) smps, cnt); +int node_read(vnode *n, vsample **smps, unsigned cnt) { + auto *nc = (Node *)n; + return nc->read((villas::node::Sample **)smps, cnt); } -int node_write(vnode *n, vsample **smps, unsigned cnt) -{ - auto *nc = (Node *) n; - return nc->write((villas::node::Sample**) smps, cnt); +int node_write(vnode *n, vsample **smps, unsigned cnt) { + auto *nc = (Node *)n; + return nc->write((villas::node::Sample **)smps, cnt); } -int node_poll_fds(vnode *n, int fds[]) -{ - auto *nc = (Node *) n; - auto l = nc->getPollFDs(); +int node_poll_fds(vnode *n, int fds[]) { + auto *nc = (Node *)n; + auto l = nc->getPollFDs(); - for (unsigned i = 0; i < l.size() && i < 16; i++) - fds[i] = l[i]; + for (unsigned i = 0; i < l.size() && i < 16; i++) + fds[i] = l[i]; - return l.size(); + return l.size(); } -int node_netem_fds(vnode *n, int fds[]) -{ - auto *nc = (Node *) n; - auto l = nc->getNetemFDs(); +int node_netem_fds(vnode *n, int fds[]) { + auto *nc = (Node *)n; + auto l = nc->getNetemFDs(); - for (unsigned i = 0; i < l.size() && i < 16; i++) - fds[i] = l[i]; + for (unsigned i = 0; i < l.size() && i < 16; i++) + fds[i] = l[i]; - return l.size(); + return l.size(); } -bool node_is_valid_name(const char *name) -{ - return Node::isValidName(name); +bool node_is_valid_name(const char *name) { return Node::isValidName(name); } + +bool node_is_enabled(const vnode *n) { + auto *nc = (Node *)n; + return nc->isEnabled(); } -bool node_is_enabled(const vnode *n) -{ - auto *nc = (Node *) n; - return nc->isEnabled(); +json_t *node_to_json(const vnode *n) { + auto *nc = (Node *)n; + return nc->toJson(); } -json_t * node_to_json(const vnode *n) -{ - auto *nc = (Node *) n; - return nc->toJson(); +const char *node_to_json_str(vnode *n) { + auto json = node_to_json(n); + return json_dumps(json, 0); } -const char * node_to_json_str(vnode *n) -{ - auto json = node_to_json(n); - return json_dumps(json, 0); +vsample *sample_alloc(unsigned len) { return (vsample *)sample_alloc_mem(len); } + +unsigned sample_length(vsample *s) { + auto *smp = (Sample *)s; + return smp->length; } -vsample * sample_alloc(unsigned len) -{ - return (vsample *) sample_alloc_mem(len); +vsample *sample_pack(unsigned seq, struct timespec *ts_origin, + struct timespec *ts_received, unsigned len, + double *values) { + auto *smp = sample_alloc_mem(len); + + smp->sequence = seq; + smp->ts.origin = *ts_origin; + smp->ts.received = *ts_received; + smp->length = len; + smp->flags = (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_TS_ORIGIN; + + memcpy((double *)smp->data, values, sizeof(double) * len); + + return (vsample *)smp; } -unsigned sample_length(vsample *s) -{ - auto *smp = (Sample *) s; - return smp->length; +void sample_unpack(vsample *s, unsigned *seq, struct timespec *ts_origin, + struct timespec *ts_received, int *flags, unsigned *len, + double *values) { + auto *smp = (Sample *)s; + + *seq = smp->sequence; + + *ts_origin = smp->ts.origin; + *ts_received = smp->ts.received; + + *flags = smp->flags; + *len = smp->length; + + memcpy(values, (double *)smp->data, sizeof(double) * *len); } -vsample * sample_pack(unsigned seq, struct timespec *ts_origin, struct timespec *ts_received, unsigned len, double *values) -{ - auto *smp = sample_alloc_mem(len); +void sample_decref(vsample *smp) { sample_decref((Sample *)smp); } - smp->sequence = seq; - smp->ts.origin = *ts_origin; - smp->ts.received = *ts_received; - smp->length = len; - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_TS_ORIGIN; - - memcpy((double *) smp->data, values, sizeof(double) * len); - - return (vsample *) smp; -} - -void sample_unpack(vsample *s, unsigned *seq, struct timespec *ts_origin, struct timespec *ts_received, int *flags, unsigned *len, double *values) -{ - auto *smp = (Sample *) s; - - *seq = smp->sequence; - - *ts_origin = smp->ts.origin; - *ts_received = smp->ts.received; - - *flags =smp->flags; - *len = smp->length; - - memcpy(values, (double *) smp->data, sizeof(double) * *len); -} - -void sample_decref(vsample *smp) -{ - sample_decref((Sample *) smp); -} - -int memory_init(int hugepages) -{ - return memory::init(hugepages); -} +int memory_init(int hugepages) { return memory::init(hugepages); } diff --git a/lib/node_compat.cpp b/lib/node_compat.cpp index 588ec531b..589fde594 100644 --- a/lib/node_compat.cpp +++ b/lib/node_compat.cpp @@ -5,318 +5,255 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include using namespace villas; using namespace villas::node; -NodeCompat::NodeCompat(struct NodeCompatType *vt, const uuid_t &id, const std::string &name) : - Node(id, name), - _vt(vt) -{ - _vd = new char[_vt->size]; - if (!_vd) - throw MemoryAllocationError(); +NodeCompat::NodeCompat(struct NodeCompatType *vt, const uuid_t &id, + const std::string &name) + : Node(id, name), _vt(vt) { + _vd = new char[_vt->size]; + if (!_vd) + throw MemoryAllocationError(); - memset(_vd, 0, _vt->size); + memset(_vd, 0, _vt->size); - int ret = _vt->init - ? _vt->init(this) - : 0; - if (ret) - throw RuntimeError("Failed to initialize node"); + int ret = _vt->init ? _vt->init(this) : 0; + if (ret) + throw RuntimeError("Failed to initialize node"); } -NodeCompat::NodeCompat(const NodeCompat& n) : - Node(n) -{ - _vd = new char[_vt->size]; - if (!_vd) - throw MemoryAllocationError(); +NodeCompat::NodeCompat(const NodeCompat &n) : Node(n) { + _vd = new char[_vt->size]; + if (!_vd) + throw MemoryAllocationError(); - memcpy(_vd, n._vd, _vt->size); + memcpy(_vd, n._vd, _vt->size); - int ret = _vt->init - ? _vt->init(this) - : 0; - if (ret) - throw RuntimeError("Failed to initialize node"); + int ret = _vt->init ? _vt->init(this) : 0; + if (ret) + throw RuntimeError("Failed to initialize node"); } -NodeCompat & NodeCompat::operator=(const NodeCompat& n) -{ - if (&n != this) { - *this = n; +NodeCompat &NodeCompat::operator=(const NodeCompat &n) { + if (&n != this) { + *this = n; - _vd = new char[_vt->size]; - if (!_vd) - throw MemoryAllocationError(); + _vd = new char[_vt->size]; + if (!_vd) + throw MemoryAllocationError(); - memcpy(_vd, n._vd, _vt->size); - } + memcpy(_vd, n._vd, _vt->size); + } - return *this; + return *this; } -NodeCompat::~NodeCompat() -{ - assert(state == State::STOPPED || - state == State::PREPARED || - state == State::CHECKED || - state == State::PARSED || - state == State::INITIALIZED); +NodeCompat::~NodeCompat() { + assert(state == State::STOPPED || state == State::PREPARED || + state == State::CHECKED || state == State::PARSED || + state == State::INITIALIZED); - int ret __attribute__((unused)); - ret = _vt->destroy - ? _vt->destroy(this) - : 0; + int ret __attribute__((unused)); + ret = _vt->destroy ? _vt->destroy(this) : 0; - delete[] (char *) _vd; + delete[] (char *)_vd; } -int NodeCompat::prepare() -{ - assert(state == State::CHECKED); +int NodeCompat::prepare() { + assert(state == State::CHECKED); - int ret = _vt->prepare - ? _vt->prepare(this) - : 0; - if (ret) - return ret; + int ret = _vt->prepare ? _vt->prepare(this) : 0; + if (ret) + return ret; - return Node::prepare(); + return Node::prepare(); } -int NodeCompat::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int NodeCompat::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - ret = _vt->parse - ? _vt->parse(this, json) - : 0; - if (!ret) - state = State::PARSED; + ret = _vt->parse ? _vt->parse(this, json) : 0; + if (!ret) + state = State::PARSED; - return ret; + return ret; } -int NodeCompat::check() -{ - int ret = Node::check(); - if (ret) - return ret; +int NodeCompat::check() { + int ret = Node::check(); + if (ret) + return ret; - ret = _vt->check - ? _vt->check(this) - : 0; - if (!ret) - state = State::CHECKED; + ret = _vt->check ? _vt->check(this) : 0; + if (!ret) + state = State::CHECKED; - return ret; + return ret; } -int NodeCompat::pause() -{ - int ret; +int NodeCompat::pause() { + int ret; - ret = Node::pause(); - if (ret) - return ret; + ret = Node::pause(); + if (ret) + return ret; - ret = _vt->pause - ? _vt->pause(this) - : 0; - if (!ret) - state = State::PAUSED; + ret = _vt->pause ? _vt->pause(this) : 0; + if (!ret) + state = State::PAUSED; - return ret; + return ret; } -int NodeCompat::resume() -{ - int ret; +int NodeCompat::resume() { + int ret; - ret = Node::resume(); - if (ret) - return ret; + ret = Node::resume(); + if (ret) + return ret; - ret = _vt->resume - ? _vt->resume(this) - : 0; - if (!ret) - state = State::STARTED; + ret = _vt->resume ? _vt->resume(this) : 0; + if (!ret) + state = State::STARTED; - return ret; + return ret; } -int NodeCompat::restart() -{ - return _vt->restart - ? _vt->restart(this) - : Node::restart(); +int NodeCompat::restart() { + return _vt->restart ? _vt->restart(this) : Node::restart(); } -int NodeCompat::_read(struct Sample * smps[], unsigned cnt) -{ - return _vt->read - ? _vt->read(this, smps, cnt) - : -1; +int NodeCompat::_read(struct Sample *smps[], unsigned cnt) { + return _vt->read ? _vt->read(this, smps, cnt) : -1; } -int NodeCompat::_write(struct Sample * smps[], unsigned cnt) -{ - return _vt->write - ? _vt->write(this, smps, cnt) - : -1; +int NodeCompat::_write(struct Sample *smps[], unsigned cnt) { + return _vt->write ? _vt->write(this, smps, cnt) : -1; } /* Reverse local and remote socket address. * * @see node_type::reverse */ -int NodeCompat::reverse() -{ - return _vt->reverse - ? _vt->reverse(this) - : -1; +int NodeCompat::reverse() { return _vt->reverse ? _vt->reverse(this) : -1; } + +std::vector NodeCompat::getPollFDs() { + if (_vt->poll_fds) { + int ret, fds[16]; + + ret = _vt->poll_fds(this, fds); + if (ret < 0) + return {}; + + return std::vector(fds, fds + ret); + } + + return {}; } -std::vector NodeCompat::getPollFDs() -{ - if (_vt->poll_fds) { - int ret, fds[16]; +std::vector NodeCompat::getNetemFDs() { + if (_vt->netem_fds) { + int ret, fds[16]; - ret = _vt->poll_fds(this, fds); - if (ret < 0) - return {}; + ret = _vt->netem_fds(this, fds); + if (ret < 0) + return {}; - return std::vector(fds, fds+ret); - } + return std::vector(fds, fds + ret); + } - return {}; + return {}; } -std::vector NodeCompat::getNetemFDs() -{ - if (_vt->netem_fds) { - int ret, fds[16]; - - ret = _vt->netem_fds(this, fds); - if (ret < 0) - return {}; - - return std::vector(fds, fds+ret); - } - - return {}; +struct memory::Type *NodeCompat::getMemoryType() { + return _vt->memory_type ? _vt->memory_type(this, memory::default_type) + : memory::default_type; } -struct memory::Type * NodeCompat::getMemoryType() -{ - return _vt->memory_type - ? _vt->memory_type(this, memory::default_type) - : memory::default_type; +int NodeCompat::start() { + assert(state == State::PREPARED || state == State::PAUSED); + + int ret = _vt->start ? _vt->start(this) : 0; + if (ret) + return ret; + + ret = Node::start(); + if (!ret) + state = State::STARTED; + + return ret; } -int NodeCompat::start() -{ - assert(state == State::PREPARED || - state == State::PAUSED); +int NodeCompat::stop() { + assert(state == State::STARTED || state == State::PAUSED || + state == State::STOPPING); - int ret = _vt->start - ? _vt->start(this) - : 0; - if (ret) - return ret; + int ret = Node::stop(); + if (ret) + return ret; - ret = Node::start(); - if (!ret) - state = State::STARTED; + ret = _vt->stop ? _vt->stop(this) : 0; + if (!ret) + state = State::STOPPED; - return ret; + return ret; } -int NodeCompat::stop() -{ - assert(state == State::STARTED || - state == State::PAUSED || - state == State::STOPPING); +const std::string &NodeCompat::getDetails() { + if (_vt->print && _details.empty()) { + auto *d = _vt->print(this); + _details = std::string(d); + free(d); + } - int ret = Node::stop(); - if (ret) - return ret; - - ret = _vt->stop - ? _vt->stop(this) : - 0; - if (!ret) - state = State::STOPPED; - - return ret; + return _details; } -const std::string & NodeCompat::getDetails() -{ - if (_vt->print && _details.empty()) { - auto *d = _vt->print(this); - _details = std::string(d); - free(d); - } +Node *NodeCompatFactory::make(const uuid_t &id, const std::string &name) { + auto *n = new NodeCompat(_vt, id, name); - return _details; + init(n); + + return n; } -Node * NodeCompatFactory::make(const uuid_t &id, const std::string &name) -{ - auto *n = new NodeCompat(_vt, id, name); +int NodeCompatFactory::start(SuperNode *sn) { + assert(state == State::INITIALIZED); - init(n); + int ret = _vt->type.start ? _vt->type.start(sn) : 0; + if (ret) + return ret; - return n; + return NodeFactory::start(sn); } -int NodeCompatFactory::start(SuperNode *sn) -{ - assert(state == State::INITIALIZED); +int NodeCompatFactory::stop() { + assert(state == State::STARTED); - int ret = _vt->type.start - ? _vt->type.start(sn) - : 0; - if (ret) - return ret; + int ret = _vt->type.stop ? _vt->type.stop() : 0; + if (ret) + return ret; - return NodeFactory::start(sn); + return NodeFactory::stop(); } -int NodeCompatFactory::stop() -{ - assert(state == State::STARTED); +int NodeCompatFactory::getFlags() const { + int flags = _vt->flags; - int ret = _vt->type.stop - ? _vt->type.stop() - : 0; - if (ret) - return ret; + if (_vt->read) + flags |= (int)NodeFactory::Flags::SUPPORTS_READ; - return NodeFactory::stop(); -} - -int NodeCompatFactory::getFlags() const -{ - int flags = _vt->flags; - - if (_vt->read) - flags |= (int) NodeFactory::Flags::SUPPORTS_READ; - - if (_vt->write) - flags |= (int) NodeFactory::Flags::SUPPORTS_WRITE; - - if (_vt->poll_fds) - flags |= (int) NodeFactory::Flags::SUPPORTS_POLL; - - return flags; + if (_vt->write) + flags |= (int)NodeFactory::Flags::SUPPORTS_WRITE; + + if (_vt->poll_fds) + flags |= (int)NodeFactory::Flags::SUPPORTS_POLL; + + return flags; } diff --git a/lib/node_direction.cpp b/lib/node_direction.cpp index a3c74a887..39088b014 100644 --- a/lib/node_direction.cpp +++ b/lib/node_direction.cpp @@ -6,179 +6,165 @@ */ #include -#include +#include #include #include #include -#include -#include -#include #include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -NodeDirection::NodeDirection(enum NodeDirection::Direction dir, Node *n) : - direction(dir), - path(nullptr), - node(n), - enabled(1), - builtin(1), - vectorize(1), - config(nullptr) -{ } +NodeDirection::NodeDirection(enum NodeDirection::Direction dir, Node *n) + : direction(dir), path(nullptr), node(n), enabled(1), builtin(1), + vectorize(1), config(nullptr) {} -int NodeDirection::parse(json_t *json) -{ - int ret; +int NodeDirection::parse(json_t *json) { + int ret; - json_error_t err; - json_t *json_hooks = nullptr; - json_t *json_signals = nullptr; + json_error_t err; + json_t *json_hooks = nullptr; + json_t *json_signals = nullptr; - config = json; + config = json; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: i, s?: b, s?: b }", - "hooks", &json_hooks, - "signals", &json_signals, - "vectorize", &vectorize, - "builtin", &builtin, - "enabled", &enabled - ); - if (ret) - throw ConfigError(json, err, "node-config-node-in"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: i, s?: b, s?: b }", + "hooks", &json_hooks, "signals", &json_signals, + "vectorize", &vectorize, "builtin", &builtin, "enabled", + &enabled); + if (ret) + throw ConfigError(json, err, "node-config-node-in"); - if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::PROVIDES_SIGNALS) { - // Do nothing.. Node-type will provide signals - signals = std::make_shared(); - if (!signals) - throw MemoryAllocationError(); - } - else if (json_is_object(json_signals) || json_is_array(json_signals)) { - signals = std::make_shared(); - if (!signals) - throw MemoryAllocationError(); + if (node->getFactory()->getFlags() & + (int)NodeFactory::Flags::PROVIDES_SIGNALS) { + // Do nothing.. Node-type will provide signals + signals = std::make_shared(); + if (!signals) + throw MemoryAllocationError(); + } else if (json_is_object(json_signals) || json_is_array(json_signals)) { + signals = std::make_shared(); + if (!signals) + throw MemoryAllocationError(); - if (json_is_object(json_signals)) { - json_t *json_name, *json_signal = json_signals; - int count; + if (json_is_object(json_signals)) { + json_t *json_name, *json_signal = json_signals; + int count; - ret = json_unpack_ex(json_signal, &err, 0, "{ s: i }", - "count", &count - ); - if (ret) - throw ConfigError(json_signals, "node-config-node-signals", "Invalid signal definition"); + ret = json_unpack_ex(json_signal, &err, 0, "{ s: i }", "count", &count); + if (ret) + throw ConfigError(json_signals, "node-config-node-signals", + "Invalid signal definition"); - json_signals = json_array(); - for (int i = 0; i < count; i++) { - json_t *json_signal_copy = json_copy(json_signal); + json_signals = json_array(); + for (int i = 0; i < count; i++) { + json_t *json_signal_copy = json_copy(json_signal); - json_object_del(json_signal, "count"); + json_object_del(json_signal, "count"); - // Append signal index - json_name = json_object_get(json_signal_copy, "name"); - if (json_name) { - const char *name = json_string_value(json_name); - char *name_new; + // Append signal index + json_name = json_object_get(json_signal_copy, "name"); + if (json_name) { + const char *name = json_string_value(json_name); + char *name_new; - int ret __attribute__((unused)); - ret = asprintf(&name_new, "%s%d", name, i); + int ret __attribute__((unused)); + ret = asprintf(&name_new, "%s%d", name, i); - json_string_set(json_name, name_new); - } + json_string_set(json_name, name_new); + } - json_array_append_new(json_signals, json_signal_copy); - } - json_object_set_new(json, "signals", json_signals); - } + json_array_append_new(json_signals, json_signal_copy); + } + json_object_set_new(json, "signals", json_signals); + } - ret = signals->parse(json_signals); - if (ret) - throw ConfigError(json_signals, "node-config-node-signals", "Failed to parse signal definition"); - } - else if (json_is_string(json_signals)) { - const char *dt = json_string_value(json_signals); + ret = signals->parse(json_signals); + if (ret) + throw ConfigError(json_signals, "node-config-node-signals", + "Failed to parse signal definition"); + } else if (json_is_string(json_signals)) { + const char *dt = json_string_value(json_signals); - signals = std::make_shared(dt); - if (!signals) - return -1; - } - else { - signals = std::make_shared(DEFAULT_SAMPLE_LENGTH, SignalType::FLOAT); - if (!signals) - return -1; - } + signals = std::make_shared(dt); + if (!signals) + return -1; + } else { + signals = + std::make_shared(DEFAULT_SAMPLE_LENGTH, SignalType::FLOAT); + if (!signals) + return -1; + } #ifdef WITH_HOOKS - if (json_hooks) { - int m = direction == NodeDirection::Direction::OUT - ? (int) Hook::Flags::NODE_WRITE - : (int) Hook::Flags::NODE_READ; + if (json_hooks) { + int m = direction == NodeDirection::Direction::OUT + ? (int)Hook::Flags::NODE_WRITE + : (int)Hook::Flags::NODE_READ; - hooks.parse(json_hooks, m, nullptr, node); - } + hooks.parse(json_hooks, m, nullptr, node); + } #endif // WITH_HOOKS - return 0; + return 0; } -void NodeDirection::check() -{ - if (vectorize <= 0) - throw RuntimeError("Invalid setting 'vectorize' with value {}. Must be natural number!", vectorize); +void NodeDirection::check() { + if (vectorize <= 0) + throw RuntimeError( + "Invalid setting 'vectorize' with value {}. Must be natural number!", + vectorize); #ifdef WITH_HOOKS - hooks.check(); + hooks.check(); #endif // WITH_HOOKS } -int NodeDirection::prepare() -{ +int NodeDirection::prepare() { #ifdef WITH_HOOKS - int t = direction == NodeDirection::Direction::OUT ? (int) Hook::Flags::NODE_WRITE : (int) Hook::Flags::NODE_READ; - int m = builtin ? t | (int) Hook::Flags::BUILTIN : 0; + int t = direction == NodeDirection::Direction::OUT + ? (int)Hook::Flags::NODE_WRITE + : (int)Hook::Flags::NODE_READ; + int m = builtin ? t | (int)Hook::Flags::BUILTIN : 0; - hooks.prepare(signals, m, nullptr, node); + hooks.prepare(signals, m, nullptr, node); #endif // WITH_HOOKS - return 0; + return 0; } -int NodeDirection::start() -{ +int NodeDirection::start() { #ifdef WITH_HOOKS - hooks.start(); + hooks.start(); #endif // WITH_HOOKS - return 0; + return 0; } -int NodeDirection::stop() -{ +int NodeDirection::stop() { #ifdef WITH_HOOKS - hooks.stop(); + hooks.stop(); #endif // WITH_HOOKS - return 0; + return 0; } -SignalList::Ptr NodeDirection::getSignals(int after_hooks) const -{ +SignalList::Ptr NodeDirection::getSignals(int after_hooks) const { #ifdef WITH_HOOKS - if (after_hooks && hooks.size() > 0) - return hooks.getSignals(); + if (after_hooks && hooks.size() > 0) + return hooks.getSignals(); #endif // WITH_HOOKS - return signals; + return signals; } -unsigned NodeDirection::getSignalsMaxCount() const -{ +unsigned NodeDirection::getSignalsMaxCount() const { #ifdef WITH_HOOKS - if (hooks.size() > 0) - return MAX(signals->size(), hooks.getSignalsMaxCount()); + if (hooks.size() > 0) + return MAX(signals->size(), hooks.getSignalsMaxCount()); #endif // WITH_HOOKS - return signals->size(); + return signals->size(); } diff --git a/lib/node_list.cpp b/lib/node_list.cpp index 10b40fbc1..86b8397e6 100644 --- a/lib/node_list.cpp +++ b/lib/node_list.cpp @@ -5,94 +5,91 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include using namespace villas; using namespace villas::node; -Node * NodeList::lookup(const uuid_t &uuid) -{ - for (auto *n : *this) { - if (!uuid_compare(uuid, n->getUuid())) - return n; - } +Node *NodeList::lookup(const uuid_t &uuid) { + for (auto *n : *this) { + if (!uuid_compare(uuid, n->getUuid())) + return n; + } - return nullptr; + return nullptr; } -Node * NodeList::lookup(const std::string &name) -{ - for (auto *n : *this) { - if (name == n->getNameShort()) - return n; - } +Node *NodeList::lookup(const std::string &name) { + for (auto *n : *this) { + if (name == n->getNameShort()) + return n; + } - return nullptr; + return nullptr; } -int NodeList::parse(json_t *json, NodeList &all) -{ - Node *node; - const char *str; +int NodeList::parse(json_t *json, NodeList &all) { + Node *node; + const char *str; - size_t index; - json_t *elm; + size_t index; + json_t *elm; - auto logger = logging.get("node"); + auto logger = logging.get("node"); - switch (json_typeof(json)) { - case JSON_STRING: - str = json_string_value(json); - node = all.lookup(str); - if (!node) - goto invalid2; + switch (json_typeof(json)) { + case JSON_STRING: + str = json_string_value(json); + node = all.lookup(str); + if (!node) + goto invalid2; - push_back(node); - break; + push_back(node); + break; - case JSON_ARRAY: - json_array_foreach(json, index, elm) { - if (!json_is_string(elm)) - goto invalid; + case JSON_ARRAY: + json_array_foreach(json, index, elm) { + if (!json_is_string(elm)) + goto invalid; - str = json_string_value(elm); - node = all.lookup(str); - if (!node) - goto invalid; + str = json_string_value(elm); + node = all.lookup(str); + if (!node) + goto invalid; - push_back(node); - } - break; + push_back(node); + } + break; - default: - goto invalid; - } + default: + goto invalid; + } - return 0; + return 0; invalid: - throw RuntimeError("The node list must be an a single or an array of strings referring to the keys of the 'nodes' section"); + throw RuntimeError("The node list must be an a single or an array of strings " + "referring to the keys of the 'nodes' section"); - return -1; + return -1; invalid2: - std::stringstream allss; - for (auto *n : all) - allss << " " << n->getNameShort(); + std::stringstream allss; + for (auto *n : all) + allss << " " << n->getNameShort(); - throw RuntimeError("Unknown node {}. Choose of one of:{}", str, allss.str()); + throw RuntimeError("Unknown node {}. Choose of one of:{}", str, allss.str()); - return 0; + return 0; } -json_t * NodeList::toJson() const -{ - json_t *json_nodes = json_array(); +json_t *NodeList::toJson() const { + json_t *json_nodes = json_array(); - for (const auto *n : *this) - json_array_append_new(json_nodes, n->toJson()); + for (const auto *n : *this) + json_array_append_new(json_nodes, n->toJson()); - return json_nodes; + return json_nodes; } diff --git a/lib/nodes/amqp.cpp b/lib/nodes/amqp.cpp index fc3cb1d04..07da7a5a6 100644 --- a/lib/nodes/amqp.cpp +++ b/lib/nodes/amqp.cpp @@ -17,424 +17,399 @@ #include #endif +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -void amqp_default_ssl_info(struct amqp_ssl_info *s) -{ - s->verify_peer = 1; - s->verify_hostname = 1; - s->client_key = nullptr; - s->client_cert = nullptr; - s->ca_cert = nullptr; +static void amqp_default_ssl_info(struct amqp_ssl_info *s) { + s->verify_peer = 1; + s->verify_hostname = 1; + s->client_key = nullptr; + s->client_cert = nullptr; + s->ca_cert = nullptr; } -static -amqp_bytes_t amqp_bytes_strdup(const char *str) -{ - size_t len = strlen(str) + 1; - amqp_bytes_t buf = amqp_bytes_malloc(len); +static amqp_bytes_t amqp_bytes_strdup(const char *str) { + size_t len = strlen(str) + 1; + amqp_bytes_t buf = amqp_bytes_malloc(len); - memcpy(buf.bytes, str, len); + memcpy(buf.bytes, str, len); - return buf; + return buf; } -static -amqp_connection_state_t amqp_connect(NodeCompat *n, struct amqp_connection_info *ci, struct amqp_ssl_info *ssl) -{ - int ret; - amqp_rpc_reply_t rep; - amqp_connection_state_t conn; - amqp_socket_t *sock; +static amqp_connection_state_t amqp_connect(NodeCompat *n, + struct amqp_connection_info *ci, + struct amqp_ssl_info *ssl) { + int ret; + amqp_rpc_reply_t rep; + amqp_connection_state_t conn; + amqp_socket_t *sock; - conn = amqp_new_connection(); - if (!conn) - throw MemoryAllocationError(); + conn = amqp_new_connection(); + if (!conn) + throw MemoryAllocationError(); - if (ci->ssl) { - sock = amqp_ssl_socket_new(conn); - if (!sock) - throw MemoryAllocationError(); + if (ci->ssl) { + sock = amqp_ssl_socket_new(conn); + if (!sock) + throw MemoryAllocationError(); - amqp_ssl_socket_set_verify_peer(sock, ssl->verify_peer); - amqp_ssl_socket_set_verify_hostname(sock, ssl->verify_hostname); + amqp_ssl_socket_set_verify_peer(sock, ssl->verify_peer); + amqp_ssl_socket_set_verify_hostname(sock, ssl->verify_hostname); - if (ssl->ca_cert) { - ret = amqp_ssl_socket_set_cacert(sock, ssl->ca_cert); - if (ret) { - n->logger->error("Failed to set CA cert: {}", amqp_error_string2(ret)); - return nullptr; - } - } + if (ssl->ca_cert) { + ret = amqp_ssl_socket_set_cacert(sock, ssl->ca_cert); + if (ret) { + n->logger->error("Failed to set CA cert: {}", amqp_error_string2(ret)); + return nullptr; + } + } - if (ssl->client_key && ssl->client_cert) { - ret = amqp_ssl_socket_set_key(sock, ssl->client_cert, ssl->client_key); - if (ret) { - n->logger->error("Failed to set client cert: {}", amqp_error_string2(ret)); - return nullptr; - } - } - } - else { - sock = amqp_tcp_socket_new(conn); - if (!sock) - throw MemoryAllocationError(); - } + if (ssl->client_key && ssl->client_cert) { + ret = amqp_ssl_socket_set_key(sock, ssl->client_cert, ssl->client_key); + if (ret) { + n->logger->error("Failed to set client cert: {}", + amqp_error_string2(ret)); + return nullptr; + } + } + } else { + sock = amqp_tcp_socket_new(conn); + if (!sock) + throw MemoryAllocationError(); + } - ret = amqp_socket_open(sock, ci->host, ci->port); - if (ret != AMQP_STATUS_OK) { - n->logger->error("Failed to open socket: {}", amqp_error_string2(ret)); - return nullptr; - } + ret = amqp_socket_open(sock, ci->host, ci->port); + if (ret != AMQP_STATUS_OK) { + n->logger->error("Failed to open socket: {}", amqp_error_string2(ret)); + return nullptr; + } - rep = amqp_login(conn, ci->vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, ci->user, ci->password); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) { - n->logger->error("Failed to login"); - return nullptr; - } + rep = amqp_login(conn, ci->vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, + ci->user, ci->password); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to login"); + return nullptr; + } - amqp_channel_open(conn, 1); - rep = amqp_get_rpc_reply(conn); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) { - n->logger->error("Failed to open channel"); - return nullptr; - } + amqp_channel_open(conn, 1); + rep = amqp_get_rpc_reply(conn); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to open channel"); + return nullptr; + } - return conn; + return conn; } -static -int amqp_close(NodeCompat *n, amqp_connection_state_t conn) -{ - amqp_rpc_reply_t rep; +static int amqp_close(NodeCompat *n, amqp_connection_state_t conn) { + amqp_rpc_reply_t rep; - rep = amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) { - n->logger->error("Failed to close channel"); - return -1; - } + rep = amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to close channel"); + return -1; + } - rep = amqp_connection_close(conn, AMQP_REPLY_SUCCESS); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) { - n->logger->error("Failed to close connection"); - return -1; - }; + rep = amqp_connection_close(conn, AMQP_REPLY_SUCCESS); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) { + n->logger->error("Failed to close connection"); + return -1; + }; - return 0; + return 0; } -int villas::node::amqp_init(NodeCompat *n) -{ - auto *a = n->getData(); +int villas::node::amqp_init(NodeCompat *n) { + auto *a = n->getData(); - // Default values - amqp_default_ssl_info(&a->ssl_info); - amqp_default_connection_info(&a->connection_info); + // Default values + amqp_default_ssl_info(&a->ssl_info); + amqp_default_connection_info(&a->connection_info); - a->formatter = nullptr; + a->formatter = nullptr; - return 0; + return 0; } -int villas::node::amqp_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *a = n->getData(); +int villas::node::amqp_parse(NodeCompat *n, json_t *json) { + int ret; + auto *a = n->getData(); - int port = 5672; - const char *uri = nullptr; - const char *host = "localhost"; - const char *vhost = "/"; - const char *username = "guest"; - const char *password = "guest"; - const char *exchange, *routing_key; + int port = 5672; + const char *uri = nullptr; + const char *host = "localhost"; + const char *vhost = "/"; + const char *username = "guest"; + const char *password = "guest"; + const char *exchange, *routing_key; - json_error_t err; + json_error_t err; - json_t *json_ssl = nullptr; - json_t *json_format = nullptr; + json_t *json_ssl = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: s, s?: s, s?: i, s: s, s: s, s?: o, s?: o }", - "uri", &uri, - "host", &host, - "vhost", &vhost, - "username", &username, - "password", &password, - "port", &port, - "exchange", &exchange, - "routing_key", &routing_key, - "format", &json_format, - "ssl", &json_ssl - ); - if (ret) - throw ConfigError(json, err, "node-config-node-amqp"); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: s, s?: s, s?: s, s?: s, s?: s, s?: i, s: s, s: s, s?: o, s?: o }", + "uri", &uri, "host", &host, "vhost", &vhost, "username", &username, + "password", &password, "port", &port, "exchange", &exchange, + "routing_key", &routing_key, "format", &json_format, "ssl", &json_ssl); + if (ret) + throw ConfigError(json, err, "node-config-node-amqp"); - a->exchange = amqp_bytes_strdup(exchange); - a->routing_key = amqp_bytes_strdup(routing_key); + a->exchange = amqp_bytes_strdup(exchange); + a->routing_key = amqp_bytes_strdup(routing_key); - if (uri) - a->uri = strdup(uri); - else - a->uri = strf("%s://%s:%s@%s:%d/%s", json_ssl ? "amqps" : "amqp", username, password, host, port, vhost); + if (uri) + a->uri = strdup(uri); + else + a->uri = strf("%s://%s:%s@%s:%d/%s", json_ssl ? "amqps" : "amqp", username, + password, host, port, vhost); - ret = amqp_parse_url(a->uri, &a->connection_info); - if (ret != AMQP_STATUS_OK) - throw ConfigError(json, "node-config-node-uri", "Failed to parse URI '{}'", uri); + ret = amqp_parse_url(a->uri, &a->connection_info); + if (ret != AMQP_STATUS_OK) + throw ConfigError(json, "node-config-node-uri", "Failed to parse URI '{}'", + uri); - if (json_ssl) { - const char *ca_cert = nullptr; - const char *client_cert = nullptr; - const char *client_key = nullptr; + if (json_ssl) { + const char *ca_cert = nullptr; + const char *client_cert = nullptr; + const char *client_key = nullptr; - ret = json_unpack_ex(json_ssl, &err, 0, "{ s?: b, s?: b, s?: s, s?: s, s?: s }", - "verify_peer", &a->ssl_info.verify_peer, - "verify_hostname", &a->ssl_info.verify_hostname, - "ca_cert", &ca_cert, - "client_key", &client_key, - "client_cert", &client_cert - ); - if (ret) - throw ConfigError(json_ssl, err, "node-config-node-amqp-ssl", "Failed to parse SSL configuration"); + ret = json_unpack_ex( + json_ssl, &err, 0, "{ s?: b, s?: b, s?: s, s?: s, s?: s }", + "verify_peer", &a->ssl_info.verify_peer, "verify_hostname", + &a->ssl_info.verify_hostname, "ca_cert", &ca_cert, "client_key", + &client_key, "client_cert", &client_cert); + if (ret) + throw ConfigError(json_ssl, err, "node-config-node-amqp-ssl", + "Failed to parse SSL configuration"); - if (ca_cert) - a->ssl_info.ca_cert = strdup(ca_cert); + if (ca_cert) + a->ssl_info.ca_cert = strdup(ca_cert); - if (client_cert) - a->ssl_info.client_cert = strdup(client_cert); + if (client_cert) + a->ssl_info.client_cert = strdup(client_cert); - if (client_key) - a->ssl_info.client_key = strdup(client_key); - } + if (client_key) + a->ssl_info.client_key = strdup(client_key); + } - // Format - if (a->formatter) - delete a->formatter; - a->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("json"); - if (!a->formatter) - throw ConfigError(json_format, "node-config-node-amqp-format", "Invalid format configuration"); + // Format + if (a->formatter) + delete a->formatter; + a->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("json"); + if (!a->formatter) + throw ConfigError(json_format, "node-config-node-amqp-format", + "Invalid format configuration"); - return 0; + return 0; } -char * villas::node::amqp_print(NodeCompat *n) -{ - auto *a = n->getData(); +char *villas::node::amqp_print(NodeCompat *n) { + auto *a = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - strcatf(&buf, "uri=%s://%s:%s@%s:%d%s, exchange=%s, routing_key=%s", - a->connection_info.ssl ? "amqps" : "amqp", - a->connection_info.user, - a->connection_info.password, - a->connection_info.host, - a->connection_info.port, - a->connection_info.vhost, - (char *) a->exchange.bytes, - (char *) a->routing_key.bytes - ); + strcatf(&buf, "uri=%s://%s:%s@%s:%d%s, exchange=%s, routing_key=%s", + a->connection_info.ssl ? "amqps" : "amqp", a->connection_info.user, + a->connection_info.password, a->connection_info.host, + a->connection_info.port, a->connection_info.vhost, + (char *)a->exchange.bytes, (char *)a->routing_key.bytes); - if (a->connection_info.ssl) { - strcatf(&buf, ", ssl_info.verify_peer=%s, ssl_info.verify_hostname=%s", - a->ssl_info.verify_peer ? "true" : "false", - a->ssl_info.verify_hostname ? "true" : "false" - ); + if (a->connection_info.ssl) { + strcatf(&buf, ", ssl_info.verify_peer=%s, ssl_info.verify_hostname=%s", + a->ssl_info.verify_peer ? "true" : "false", + a->ssl_info.verify_hostname ? "true" : "false"); - if (a->ssl_info.ca_cert) - strcatf(&buf, ", ssl_info.ca_cert=%s", a->ssl_info.ca_cert); + if (a->ssl_info.ca_cert) + strcatf(&buf, ", ssl_info.ca_cert=%s", a->ssl_info.ca_cert); - if (a->ssl_info.client_cert) - strcatf(&buf, ", ssl_info.client_cert=%s", a->ssl_info.client_cert); + if (a->ssl_info.client_cert) + strcatf(&buf, ", ssl_info.client_cert=%s", a->ssl_info.client_cert); - if (a->ssl_info.client_key) - strcatf(&buf, ", ssl_info.client_key=%s", a->ssl_info.client_key); - } + if (a->ssl_info.client_key) + strcatf(&buf, ", ssl_info.client_key=%s", a->ssl_info.client_key); + } - return buf; + return buf; } -int villas::node::amqp_start(NodeCompat *n) -{ - auto *a = n->getData(); +int villas::node::amqp_start(NodeCompat *n) { + auto *a = n->getData(); - amqp_bytes_t queue; - amqp_rpc_reply_t rep; - amqp_queue_declare_ok_t *r; + amqp_bytes_t queue; + amqp_rpc_reply_t rep; + amqp_queue_declare_ok_t *r; - a->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + a->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - // Connect producer - a->producer = amqp_connect(n, &a->connection_info, &a->ssl_info); - if (!a->producer) - return -1; + // Connect producer + a->producer = amqp_connect(n, &a->connection_info, &a->ssl_info); + if (!a->producer) + return -1; - // Connect consumer - a->consumer = amqp_connect(n, &a->connection_info, &a->ssl_info); - if (!a->consumer) - return -1; + // Connect consumer + a->consumer = amqp_connect(n, &a->connection_info, &a->ssl_info); + if (!a->consumer) + return -1; - // Declare exchange - amqp_exchange_declare(a->producer, 1, a->exchange, amqp_cstring_bytes("direct"), 0, 0, 0, 0, amqp_empty_table); - rep = amqp_get_rpc_reply(a->consumer); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + // Declare exchange + amqp_exchange_declare(a->producer, 1, a->exchange, + amqp_cstring_bytes("direct"), 0, 0, 0, 0, + amqp_empty_table); + rep = amqp_get_rpc_reply(a->consumer); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - // Declare private queue - r = amqp_queue_declare(a->consumer, 1, amqp_empty_bytes, 0, 0, 0, 1, amqp_empty_table); - rep = amqp_get_rpc_reply(a->consumer); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + // Declare private queue + r = amqp_queue_declare(a->consumer, 1, amqp_empty_bytes, 0, 0, 0, 1, + amqp_empty_table); + rep = amqp_get_rpc_reply(a->consumer); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - queue = amqp_bytes_malloc_dup(r->queue); - if (queue.bytes == nullptr) - return -1; + queue = amqp_bytes_malloc_dup(r->queue); + if (queue.bytes == nullptr) + return -1; - // Bind queue to exchange - amqp_queue_bind(a->consumer, 1, queue, a->exchange, a->routing_key, amqp_empty_table); - rep = amqp_get_rpc_reply(a->consumer); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + // Bind queue to exchange + amqp_queue_bind(a->consumer, 1, queue, a->exchange, a->routing_key, + amqp_empty_table); + rep = amqp_get_rpc_reply(a->consumer); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - // Start consumer - amqp_basic_consume(a->consumer, 1, queue, amqp_empty_bytes, 0, 1, 0, amqp_empty_table); - rep = amqp_get_rpc_reply(a->consumer); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + // Start consumer + amqp_basic_consume(a->consumer, 1, queue, amqp_empty_bytes, 0, 1, 0, + amqp_empty_table); + rep = amqp_get_rpc_reply(a->consumer); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - amqp_bytes_free(queue); + amqp_bytes_free(queue); - return 0; + return 0; } -int villas::node::amqp_stop(NodeCompat *n) -{ - int ret; - auto *a = n->getData(); +int villas::node::amqp_stop(NodeCompat *n) { + int ret; + auto *a = n->getData(); - ret = amqp_close(n, a->consumer); - if (ret) - return ret; + ret = amqp_close(n, a->consumer); + if (ret) + return ret; - ret = amqp_close(n, a->producer); - if (ret) - return ret; + ret = amqp_close(n, a->producer); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::amqp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *a = n->getData(); - amqp_envelope_t env; - amqp_rpc_reply_t rep; +int villas::node::amqp_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *a = n->getData(); + amqp_envelope_t env; + amqp_rpc_reply_t rep; - rep = amqp_consume_message(a->consumer, &env, nullptr, 0); - if (rep.reply_type != AMQP_RESPONSE_NORMAL) - return -1; + rep = amqp_consume_message(a->consumer, &env, nullptr, 0); + if (rep.reply_type != AMQP_RESPONSE_NORMAL) + return -1; - ret = a->formatter->sscan(static_cast(env.message.body.bytes), env.message.body.len, nullptr, smps, cnt); + ret = a->formatter->sscan(static_cast(env.message.body.bytes), + env.message.body.len, nullptr, smps, cnt); - amqp_destroy_envelope(&env); + amqp_destroy_envelope(&env); - return ret; + return ret; } -int villas::node::amqp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *a = n->getData(); - char data[1500]; - size_t wbytes; +int villas::node::amqp_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *a = n->getData(); + char data[1500]; + size_t wbytes; - ret = a->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret <= 0) - return -1; + ret = a->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret <= 0) + return -1; - amqp_bytes_t message = { - .len = wbytes, - .bytes = data - }; + amqp_bytes_t message = {.len = wbytes, .bytes = data}; - // Send message - ret = amqp_basic_publish(a->producer, 1, - a->exchange, - a->routing_key, - 0, 0, nullptr, message); + // Send message + ret = amqp_basic_publish(a->producer, 1, a->exchange, a->routing_key, 0, 0, + nullptr, message); - if (ret != AMQP_STATUS_OK) - return -1; + if (ret != AMQP_STATUS_OK) + return -1; - return cnt; + return cnt; } -int villas::node::amqp_poll_fds(NodeCompat *n, int fds[]) -{ - auto *a = n->getData(); +int villas::node::amqp_poll_fds(NodeCompat *n, int fds[]) { + auto *a = n->getData(); - amqp_socket_t *sock = amqp_get_socket(a->consumer); + amqp_socket_t *sock = amqp_get_socket(a->consumer); - fds[0] = amqp_socket_get_sockfd(sock); + fds[0] = amqp_socket_get_sockfd(sock); - return 1; + return 1; } -int villas::node::amqp_destroy(NodeCompat *n) -{ - auto *a = n->getData(); +int villas::node::amqp_destroy(NodeCompat *n) { + auto *a = n->getData(); - if (a->uri) - free(a->uri); + if (a->uri) + free(a->uri); - if (a->ssl_info.client_cert) - free(a->ssl_info.client_cert); + if (a->ssl_info.client_cert) + free(a->ssl_info.client_cert); - if (a->ssl_info.client_key) - free(a->ssl_info.client_key); + if (a->ssl_info.client_key) + free(a->ssl_info.client_key); - if (a->ssl_info.ca_cert) - free(a->ssl_info.ca_cert); + if (a->ssl_info.ca_cert) + free(a->ssl_info.ca_cert); - if (a->producer) - amqp_destroy_connection(a->producer); + if (a->producer) + amqp_destroy_connection(a->producer); - if (a->consumer) - amqp_destroy_connection(a->consumer); + if (a->consumer) + amqp_destroy_connection(a->consumer); - if (a->formatter) - delete a->formatter; + if (a->formatter) + delete a->formatter; - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "amqp"; - p.description = "Advanced Message Queueing Protoocl (rabbitmq-c)"; - p.vectorize = 0; - p.size = sizeof(struct amqp); - p.init = amqp_init; - p.destroy = amqp_destroy; - p.parse = amqp_parse; - p.print = amqp_print; - p.start = amqp_start; - p.stop = amqp_stop; - p.read = amqp_read; - p.write = amqp_write; - p.poll_fds = amqp_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "amqp"; + p.description = "Advanced Message Queueing Protoocl (rabbitmq-c)"; + p.vectorize = 0; + p.size = sizeof(struct amqp); + p.init = amqp_init; + p.destroy = amqp_destroy; + p.parse = amqp_parse; + p.print = amqp_print; + p.start = amqp_start; + p.stop = amqp_stop; + p.read = amqp_read; + p.write = amqp_write; + p.poll_fds = amqp_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/api.cpp b/lib/nodes/api.cpp index 68c3b48cb..63c7cace5 100644 --- a/lib/nodes/api.cpp +++ b/lib/nodes/api.cpp @@ -8,121 +8,114 @@ #include -#include #include +#include #include using namespace villas; using namespace villas::node; using namespace villas::node::api::universal; -APINode::APINode(const uuid_t &id, const std::string &name) : - Node(id, name), - read(), - write() -{ - int ret; - auto dirs = std::vector{&read, &write}; +APINode::APINode(const uuid_t &id, const std::string &name) + : Node(id, name), read(), write() { + int ret; + auto dirs = std::vector{&read, &write}; - for (auto dir : dirs) { - ret = pthread_mutex_init(&dir->mutex, nullptr); - if (ret) - throw RuntimeError("failed to initialize mutex"); + for (auto dir : dirs) { + ret = pthread_mutex_init(&dir->mutex, nullptr); + if (ret) + throw RuntimeError("failed to initialize mutex"); - ret = pthread_cond_init(&dir->cv, nullptr); - if (ret) - throw RuntimeError("failed to initialize mutex"); - } + ret = pthread_cond_init(&dir->cv, nullptr); + if (ret) + throw RuntimeError("failed to initialize mutex"); + } } -int APINode::prepare() -{ - auto signals_in = getInputSignals(false); +int APINode::prepare() { + auto signals_in = getInputSignals(false); - read.sample = sample_alloc_mem(signals_in->size()); - if (!read.sample) - throw MemoryAllocationError(); + read.sample = sample_alloc_mem(signals_in->size()); + if (!read.sample) + throw MemoryAllocationError(); - write.sample = sample_alloc_mem(64); - if (!write.sample) - throw MemoryAllocationError(); + write.sample = sample_alloc_mem(64); + if (!write.sample) + throw MemoryAllocationError(); - unsigned j = 0; - for (auto sig : *signals_in) - read.sample->data[j++] = sig->init; + unsigned j = 0; + for (auto sig : *signals_in) + read.sample->data[j++] = sig->init; - read.sample->length = j; - read.sample->signals = signals_in; + read.sample->length = j; + read.sample->signals = signals_in; - return Node::prepare(); + return Node::prepare(); } -int APINode::check() -{ - for (auto &ch : read.channels) { - if (ch->payload != PayloadType::SAMPLES) - return -1; - } +int APINode::check() { + for (auto &ch : read.channels) { + if (ch->payload != PayloadType::SAMPLES) + return -1; + } - for (auto &ch : write.channels) { - if (ch->payload != PayloadType::SAMPLES) - return -1; - } + for (auto &ch : write.channels) { + if (ch->payload != PayloadType::SAMPLES) + return -1; + } - return 0; + return 0; } -int APINode::_read(struct Sample *smps[], unsigned cnt) -{ - assert(cnt == 1); +int APINode::_read(struct Sample *smps[], unsigned cnt) { + assert(cnt == 1); - pthread_cond_wait(&read.cv, &read.mutex); + pthread_cond_wait(&read.cv, &read.mutex); - sample_copy(smps[0], read.sample); + sample_copy(smps[0], read.sample); - return 1; + return 1; } -int APINode::_write(struct Sample *smps[], unsigned cnt) -{ - assert(cnt == 1); +int APINode::_write(struct Sample *smps[], unsigned cnt) { + assert(cnt == 1); - sample_copy(write.sample, smps[0]); + sample_copy(write.sample, smps[0]); - pthread_cond_signal(&write.cv); + pthread_cond_signal(&write.cv); - return 1; + return 1; } -int APINode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int APINode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - json_t *json_signals_in = nullptr; - json_t *json_signals_out = nullptr; + json_t *json_signals_in = nullptr; + json_t *json_signals_out = nullptr; - json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o }, s?: { s?: o } }", - "in", - "signals", &json_signals_in, - "out", - "signals", &json_signals_out - ); - if (ret) - throw ConfigError(json, err, "node-config-node-api"); + json_error_t err; + ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o }, s?: { s?: o } }", "in", + "signals", &json_signals_in, "out", "signals", + &json_signals_out); + if (ret) + throw ConfigError(json, err, "node-config-node-api"); - if (json_signals_in) - read.channels.parse(json_signals_in, false, true); + if (json_signals_in) + read.channels.parse(json_signals_in, false, true); - if (json_signals_out) - write.channels.parse(json_signals_out, true, false); + if (json_signals_out) + write.channels.parse(json_signals_out, true, false); - return 0; + return 0; } // Register node static char n[] = "api"; static char d[] = "A node providing a HTTP REST interface"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/can.cpp b/lib/nodes/can.cpp index 2b313f04f..e4544c139 100644 --- a/lib/nodes/can.cpp +++ b/lib/nodes/can.cpp @@ -11,520 +11,506 @@ #include #include -#include -#include #include +#include +#include #include #include #include +#include #include #include -#include #include #include -#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; // Forward declarations -static -NodeCompatType p; +static NodeCompatType p; -int villas::node::can_init(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_init(NodeCompat *n) { + auto *c = n->getData(); - c->interface_name = nullptr; - c->socket = 0; - c->sample_buf = nullptr; - c->sample_buf_num = 0; - c->in = nullptr; - c->out = nullptr; + c->interface_name = nullptr; + c->socket = 0; + c->sample_buf = nullptr; + c->sample_buf_num = 0; + c->in = nullptr; + c->out = nullptr; - return 0; + return 0; } -int villas::node::can_destroy(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_destroy(NodeCompat *n) { + auto *c = n->getData(); - if (c->socket != 0) - close(c->socket); + if (c->socket != 0) + close(c->socket); - free(c->sample_buf); + free(c->sample_buf); - if (c->in) - free(c->in); + if (c->in) + free(c->in); - if (c->out) - free(c->out); + if (c->out) + free(c->out); - return 0; + return 0; } -static -int can_parse_signal(json_t *json, SignalList::Ptr node_signals, struct can_signal *can_signals, size_t signal_index) -{ - const char *name = nullptr; - uint64_t can_id = 0; - int can_size = 8; - int can_offset = 0; - int ret = 1; - json_error_t err; +static int can_parse_signal(json_t *json, SignalList::Ptr node_signals, + struct can_signal *can_signals, + size_t signal_index) { + const char *name = nullptr; + uint64_t can_id = 0; + int can_size = 8; + int can_offset = 0; + int ret = 1; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: i, s?: i, s?: i }", - "name", &name, - "can_id", &can_id, - "can_size", &can_size, - "can_offset", &can_offset - ); - if (ret) - throw ConfigError(json, err, "node-config-node-can-signals"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: i, s?: i, s?: i }", "name", + &name, "can_id", &can_id, "can_size", &can_size, + "can_offset", &can_offset); + if (ret) + throw ConfigError(json, err, "node-config-node-can-signals"); - if (can_size > 8 || can_size <= 0) - throw ConfigError(json, "node-config-node-can-can-size", "can_size of {} for signal '{}' is invalid. You must satisfy 0 < can_size <= 8.", can_size, name); + if (can_size > 8 || can_size <= 0) + throw ConfigError(json, "node-config-node-can-can-size", + "can_size of {} for signal '{}' is invalid. You must " + "satisfy 0 < can_size <= 8.", + can_size, name); - if (can_offset > 8 || can_offset < 0) - throw ConfigError(json, "node-config-node-can-can-offset", "can_offset of {} for signal '{}' is invalid. You must satisfy 0 <= can_offset <= 8.", can_offset, name); + if (can_offset > 8 || can_offset < 0) + throw ConfigError(json, "node-config-node-can-can-offset", + "can_offset of {} for signal '{}' is invalid. You must " + "satisfy 0 <= can_offset <= 8.", + can_offset, name); - auto sig = node_signals->getByIndex(signal_index); - if ((!name && sig->name.empty()) || (name && sig->name == name)) { - can_signals[signal_index].id = can_id; - can_signals[signal_index].size = can_size; - can_signals[signal_index].offset = can_offset; - ret = 0; - goto out; - } - else - throw ConfigError(json, "node-config-node-can-signa;s", "Signal configuration inconsistency detected: Signal with index {} '{}' does not match can_signal '{}'", signal_index, sig->name, name); + auto sig = node_signals->getByIndex(signal_index); + if ((!name && sig->name.empty()) || (name && sig->name == name)) { + can_signals[signal_index].id = can_id; + can_signals[signal_index].size = can_size; + can_signals[signal_index].offset = can_offset; + ret = 0; + goto out; + } else + throw ConfigError(json, "node-config-node-can-signa;s", + "Signal configuration inconsistency detected: Signal " + "with index {} '{}' does not match can_signal '{}'", + signal_index, sig->name, name); -out: return ret; +out: + return ret; } -int villas::node::can_parse(NodeCompat *n, json_t *json) -{ - int ret = 1; - auto *c = n->getData(); - size_t i; - json_t *json_in_signals; - json_t *json_out_signals; - json_t *json_signal; - json_error_t err; +int villas::node::can_parse(NodeCompat *n, json_t *json) { + int ret = 1; + auto *c = n->getData(); + size_t i; + json_t *json_in_signals; + json_t *json_out_signals; + json_t *json_signal; + json_error_t err; - c->in = nullptr; - c->out = nullptr; + c->in = nullptr; + c->out = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: { s?: o }, s?: { s?: o } }", - "interface_name", &c->interface_name, - "in", - "signals", &json_in_signals, - "out", - "signals", &json_out_signals - ); - if (ret) - throw ConfigError(json, err, "node-config-node-can"); + ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: { s?: o }, s?: { s?: o } }", + "interface_name", &c->interface_name, "in", "signals", + &json_in_signals, "out", "signals", &json_out_signals); + if (ret) + throw ConfigError(json, err, "node-config-node-can"); - c->in = (struct can_signal*) calloc( - json_array_size(json_in_signals), - sizeof(struct can_signal)); - if (!c->in) - throw MemoryAllocationError(); + c->in = (struct can_signal *)calloc(json_array_size(json_in_signals), + sizeof(struct can_signal)); + if (!c->in) + throw MemoryAllocationError(); - c->out = (struct can_signal*) calloc( - json_array_size(json_out_signals), - sizeof(struct can_signal)); - if (!c->out) - throw MemoryAllocationError(); + c->out = (struct can_signal *)calloc(json_array_size(json_out_signals), + sizeof(struct can_signal)); + if (!c->out) + throw MemoryAllocationError(); - json_array_foreach(json_in_signals, i, json_signal) { - ret = can_parse_signal(json_signal, n->in.signals, c->in, i); - if (ret) - throw RuntimeError("at signal {}.",i); - } + json_array_foreach(json_in_signals, i, json_signal) { + ret = can_parse_signal(json_signal, n->in.signals, c->in, i); + if (ret) + throw RuntimeError("at signal {}.", i); + } - json_array_foreach(json_out_signals, i, json_signal) { - ret = can_parse_signal(json_signal, n->out.signals, c->out, i); - if (ret) - throw RuntimeError("at signal {}.", i); - } + json_array_foreach(json_out_signals, i, json_signal) { + ret = can_parse_signal(json_signal, n->out.signals, c->out, i); + if (ret) + throw RuntimeError("at signal {}.", i); + } - ret = 0; + ret = 0; - return ret; + return ret; } -char * villas::node::can_print(NodeCompat *n) -{ - auto *c = n->getData(); +char *villas::node::can_print(NodeCompat *n) { + auto *c = n->getData(); - return strf("interface_name={}", c->interface_name); + return strf("interface_name={}", c->interface_name); } -int villas::node::can_check(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_check(NodeCompat *n) { + auto *c = n->getData(); - if (c->interface_name == nullptr || strlen(c->interface_name) == 0) - throw RuntimeError("Empty interface_name. Please specify the name of the CAN interface!"); + if (c->interface_name == nullptr || strlen(c->interface_name) == 0) + throw RuntimeError( + "Empty interface_name. Please specify the name of the CAN interface!"); - return 0; + return 0; } -int villas::node::can_prepare(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_prepare(NodeCompat *n) { + auto *c = n->getData(); - c->sample_buf = (union SignalData*) calloc(n->getInputSignals(false)->size(), sizeof(union SignalData)); + c->sample_buf = (union SignalData *)calloc(n->getInputSignals(false)->size(), + sizeof(union SignalData)); - return (c->sample_buf != 0 ? 0 : 1); + return (c->sample_buf != 0 ? 0 : 1); } -int villas::node::can_start(NodeCompat *n) -{ - int ret = 1; - struct sockaddr_can addr = {0}; - struct ifreq ifr; +int villas::node::can_start(NodeCompat *n) { + int ret = 1; + struct sockaddr_can addr = {0}; + struct ifreq ifr; - auto *c = n->getData(); - c->start_time = time_now(); + auto *c = n->getData(); + c->start_time = time_now(); - c->socket = socket(PF_CAN, SOCK_RAW, CAN_RAW); - if (c->socket < 0) - throw SystemError("Error while opening CAN socket"); + c->socket = socket(PF_CAN, SOCK_RAW, CAN_RAW); + if (c->socket < 0) + throw SystemError("Error while opening CAN socket"); - strcpy(ifr.ifr_name, c->interface_name); + strcpy(ifr.ifr_name, c->interface_name); - ret = ioctl(c->socket, SIOCGIFINDEX, &ifr); - if (ret != 0) - throw SystemError("Could not find interface with name '{}'.", c->interface_name); + ret = ioctl(c->socket, SIOCGIFINDEX, &ifr); + if (ret != 0) + throw SystemError("Could not find interface with name '{}'.", + c->interface_name); - addr.can_family = AF_CAN; - addr.can_ifindex = ifr.ifr_ifindex; + addr.can_family = AF_CAN; + addr.can_ifindex = ifr.ifr_ifindex; - ret = bind(c->socket, (struct sockaddr *)&addr, sizeof(addr)); - if (ret < 0) - throw SystemError("Could not bind to interface with name '{}' ({}).", c->interface_name, ifr.ifr_ifindex); + ret = bind(c->socket, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) + throw SystemError("Could not bind to interface with name '{}' ({}).", + c->interface_name, ifr.ifr_ifindex); - return 0; + return 0; } -int villas::node::can_stop(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::can_stop(NodeCompat *n) { + auto *c = n->getData(); - if (c->socket != 0) { - close(c->socket); - c->socket = 0; - } + if (c->socket != 0) { + close(c->socket); + c->socket = 0; + } - return 0; + return 0; } -static -int can_convert_to_raw(const union SignalData *sig, const Signal::Ptr from, void *to, int size) -{ - if (size <= 0 || size > 8) - throw RuntimeError("Signal size cannot be larger than 8!"); +static int can_convert_to_raw(const union SignalData *sig, + const Signal::Ptr from, void *to, int size) { + if (size <= 0 || size > 8) + throw RuntimeError("Signal size cannot be larger than 8!"); - switch(from->type) { - case SignalType::BOOLEAN: - *(uint8_t*)to = sig->b; - return 0; + switch (from->type) { + case SignalType::BOOLEAN: + *(uint8_t *)to = sig->b; + return 0; - case SignalType::INTEGER: - switch(size) { - case 1: - *(int8_t*)to = (int8_t)sig->i; - return 0; + case SignalType::INTEGER: + switch (size) { + case 1: + *(int8_t *)to = (int8_t)sig->i; + return 0; - case 2: - *(int16_t*)to = (int16_t)sig->i; - return 0; + case 2: + *(int16_t *)to = (int16_t)sig->i; + return 0; - case 3: - *(int16_t*)to = (int16_t)sig->i; - *((int8_t*)to+2) = (int8_t)(sig->i >> 16); - return 0; + case 3: + *(int16_t *)to = (int16_t)sig->i; + *((int8_t *)to + 2) = (int8_t)(sig->i >> 16); + return 0; - case 4: - *(int32_t*)to = (int32_t)sig->i; - return 0; + case 4: + *(int32_t *)to = (int32_t)sig->i; + return 0; - case 8: - *(int64_t*)to = sig->i; - return 0; + case 8: + *(int64_t *)to = sig->i; + return 0; - default: - goto fail; - } - case SignalType::FLOAT: - switch(size) { - case 4: - assert(sizeof(float) == 4); - *(float*)to = (float)sig->f; - return 0; + default: + goto fail; + } + case SignalType::FLOAT: + switch (size) { + case 4: + assert(sizeof(float) == 4); + *(float *)to = (float)sig->f; + return 0; - case 8: - *(double*)to = sig->f; - return 0; + case 8: + *(double *)to = sig->f; + return 0; - default: - goto fail; - } - case SignalType::COMPLEX: - if (size != 8) - goto fail; + default: + goto fail; + } + case SignalType::COMPLEX: + if (size != 8) + goto fail; - *(float*)to = sig->z.real(); - *((float*)to+1) = sig->z.imag(); - return 0; + *(float *)to = sig->z.real(); + *((float *)to + 1) = sig->z.imag(); + return 0; - default: - goto fail; - } + default: + goto fail; + } fail: - throw RuntimeError("Unsupported conversion to {} from raw ({}, {})", signalTypeToString(from->type), to, size); + throw RuntimeError("Unsupported conversion to {} from raw ({}, {})", + signalTypeToString(from->type), to, size); - return 1; + return 1; } -static -int can_conv_from_raw(union SignalData *sig, void *from, int size, Signal::Ptr to) -{ - if (size <= 0 || size > 8) - throw RuntimeError("Signal size cannot be larger than 8!"); +static int can_conv_from_raw(union SignalData *sig, void *from, int size, + Signal::Ptr to) { + if (size <= 0 || size > 8) + throw RuntimeError("Signal size cannot be larger than 8!"); - switch(to->type) { - case SignalType::BOOLEAN: - sig->b = (bool)*(uint8_t*)from; - return 0; - case SignalType::INTEGER: - switch(size) { - case 1: - sig->i = (int64_t)*(int8_t*)from; - return 0; + switch (to->type) { + case SignalType::BOOLEAN: + sig->b = (bool)*(uint8_t *)from; + return 0; + case SignalType::INTEGER: + switch (size) { + case 1: + sig->i = (int64_t) * (int8_t *)from; + return 0; - case 2: - sig->i = (int64_t)*(int16_t*)from; - return 0; + case 2: + sig->i = (int64_t) * (int16_t *)from; + return 0; - case 3: - sig->i = (int64_t)*(int16_t*)from; - sig->i += ((int64_t)*((int8_t*)(from)+2)) << 16; - return 0; + case 3: + sig->i = (int64_t) * (int16_t *)from; + sig->i += ((int64_t) * ((int8_t *)(from) + 2)) << 16; + return 0; - case 4: - sig->i = (int64_t)*(int32_t*)from; - return 0; + case 4: + sig->i = (int64_t) * (int32_t *)from; + return 0; - case 8: - sig->i = *(uint64_t*)from; - return 0; + case 8: + sig->i = *(uint64_t *)from; + return 0; - default: - goto fail; - } - case SignalType::FLOAT: - switch(size) { - case 4: - assert(sizeof(float) == 4); - sig->f = (double)*(float*)from; - return 0; + default: + goto fail; + } + case SignalType::FLOAT: + switch (size) { + case 4: + assert(sizeof(float) == 4); + sig->f = (double)*(float *)from; + return 0; - case 8: - sig->f = *(double*)from; - return 0; + case 8: + sig->f = *(double *)from; + return 0; - default: - goto fail; - } - case SignalType::COMPLEX: - if (size != 8) - goto fail; + default: + goto fail; + } + case SignalType::COMPLEX: + if (size != 8) + goto fail; - sig->z = std::complex(*(float*)from, *((float*)from+1)); - return 0; + sig->z = std::complex(*(float *)from, *((float *)from + 1)); + return 0; - default: - goto fail; - } + default: + goto fail; + } fail: - throw RuntimeError("Unsupported conversion from {} to raw ({}, {})", signalTypeToString(to->type), from, size); + throw RuntimeError("Unsupported conversion from {} to raw ({}, {})", + signalTypeToString(to->type), from, size); - return 1; + return 1; } -int villas::node::can_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret = 0; - int nbytes; - unsigned nread = 0; - struct can_frame frame; - struct timeval tv; - bool found_id = false; +int villas::node::can_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret = 0; + int nbytes; + unsigned nread = 0; + struct can_frame frame; + struct timeval tv; + bool found_id = false; - auto *c = n->getData(); + auto *c = n->getData(); - assert(cnt >= 1 && smps[0]->capacity >= 1); + assert(cnt >= 1 && smps[0]->capacity >= 1); - nbytes = read(c->socket, &frame, sizeof(struct can_frame)); - if (nbytes == -1) - throw RuntimeError("CAN read() returned -1. Is the CAN interface up?"); + nbytes = read(c->socket, &frame, sizeof(struct can_frame)); + if (nbytes == -1) + throw RuntimeError("CAN read() returned -1. Is the CAN interface up?"); - if ((unsigned)nbytes != sizeof(struct can_frame)) - throw RuntimeError("CAN read() error. Returned {} bytes but expected {}", nbytes, sizeof(struct can_frame)); + if ((unsigned)nbytes != sizeof(struct can_frame)) + throw RuntimeError("CAN read() error. Returned {} bytes but expected {}", + nbytes, sizeof(struct can_frame)); - n->logger->debug("Received can message: (id={}, len={}, data={:#x}:{:#x})", - frame.can_id, - frame.can_dlc, - ((uint32_t*)&frame.data)[0], - ((uint32_t*)&frame.data)[1]); + n->logger->debug("Received can message: (id={}, len={}, data={:#x}:{:#x})", + frame.can_id, frame.can_dlc, ((uint32_t *)&frame.data)[0], + ((uint32_t *)&frame.data)[1]); - if (ioctl(c->socket, SIOCGSTAMP, &tv) == 0) { - TIMEVAL_TO_TIMESPEC(&tv, &smps[nread]->ts.received); - smps[nread]->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + if (ioctl(c->socket, SIOCGSTAMP, &tv) == 0) { + TIMEVAL_TO_TIMESPEC(&tv, &smps[nread]->ts.received); + smps[nread]->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - for (size_t i=0; i < n->getInputSignals(false)->size(); i++) { - if (c->in[i].id == frame.can_id) { - if (can_conv_from_raw(&c->sample_buf[i], - ((uint8_t*)&frame.data) + c->in[i].offset, - c->in[i].size, - n->getInputSignals(false)->getByIndex(i)) != 0) { - goto out; - } + for (size_t i = 0; i < n->getInputSignals(false)->size(); i++) { + if (c->in[i].id == frame.can_id) { + if (can_conv_from_raw( + &c->sample_buf[i], ((uint8_t *)&frame.data) + c->in[i].offset, + c->in[i].size, n->getInputSignals(false)->getByIndex(i)) != 0) { + goto out; + } - c->sample_buf_num++; - found_id = true; - } - } + c->sample_buf_num++; + found_id = true; + } + } - if (!found_id) - throw RuntimeError("Did not find signal for can id {}", frame.can_id); + if (!found_id) + throw RuntimeError("Did not find signal for can id {}", frame.can_id); - n->logger->debug("Received {} signals", c->sample_buf_num); + n->logger->debug("Received {} signals", c->sample_buf_num); - // Copy signal data to sample only when all signals have been received - if (c->sample_buf_num == n->getInputSignals(false)->size()) { - smps[nread]->length = c->sample_buf_num; - memcpy(smps[nread]->data, c->sample_buf, c->sample_buf_num*sizeof(union SignalData)); - c->sample_buf_num = 0; - smps[nread]->flags |= (int) SampleFlags::HAS_DATA; - ret = 1; - } - else { - smps[nread]->length = 0; - ret = 0; - } + // Copy signal data to sample only when all signals have been received + if (c->sample_buf_num == n->getInputSignals(false)->size()) { + smps[nread]->length = c->sample_buf_num; + memcpy(smps[nread]->data, c->sample_buf, + c->sample_buf_num * sizeof(union SignalData)); + c->sample_buf_num = 0; + smps[nread]->flags |= (int)SampleFlags::HAS_DATA; + ret = 1; + } else { + smps[nread]->length = 0; + ret = 0; + } - out: // Set signals, because other VILLASnode parts expect us to - smps[nread]->signals = n->getInputSignals(false); +out: // Set signals, because other VILLASnode parts expect us to + smps[nread]->signals = n->getInputSignals(false); - return ret; + return ret; } -int villas::node::can_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int nbytes; - unsigned nwrite; - struct can_frame *frame; - size_t fsize = 0; // number of frames in use +int villas::node::can_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int nbytes; + unsigned nwrite; + struct can_frame *frame; + size_t fsize = 0; // number of frames in use - auto *c = n->getData(); + auto *c = n->getData(); - assert(cnt >= 1 && smps[0]->capacity >= 1); + assert(cnt >= 1 && smps[0]->capacity >= 1); - frame = (struct can_frame*) calloc(sizeof(struct can_frame), n->getOutputSignals()->size()); + frame = (struct can_frame *)calloc(sizeof(struct can_frame), + n->getOutputSignals()->size()); - for (nwrite=0; nwrite < cnt; nwrite++) { - for (size_t i=0; i < n->getOutputSignals()->size(); i++) { - if (c->out[i].offset != 0) // frame is shared - continue; + for (nwrite = 0; nwrite < cnt; nwrite++) { + for (size_t i = 0; i < n->getOutputSignals()->size(); i++) { + if (c->out[i].offset != 0) // frame is shared + continue; - frame[fsize].can_dlc = c->out[i].size; - frame[fsize].can_id = c->out[i].id; + frame[fsize].can_dlc = c->out[i].size; + frame[fsize].can_id = c->out[i].id; - can_convert_to_raw( - &smps[nwrite]->data[i], - n->getOutputSignals()->getByIndex(i), - &frame[fsize].data, - c->out[i].size); + can_convert_to_raw(&smps[nwrite]->data[i], + n->getOutputSignals()->getByIndex(i), + &frame[fsize].data, c->out[i].size); - fsize++; - } + fsize++; + } - for (size_t i=0; i < n->getOutputSignals(false)->size(); i++) { - if (c->out[i].offset == 0) { // frame already stored - continue; - } + for (size_t i = 0; i < n->getOutputSignals(false)->size(); i++) { + if (c->out[i].offset == 0) { // frame already stored + continue; + } - for (size_t j=0; j < fsize; j++) { - if (c->out[i].id != frame[j].can_id) - continue; + for (size_t j = 0; j < fsize; j++) { + if (c->out[i].id != frame[j].can_id) + continue; - frame[j].can_dlc += c->out[i].size; - can_convert_to_raw( - &smps[nwrite]->data[i], - n->getOutputSignals(false)->getByIndex(i), - (uint8_t*)&frame[j].data + c->out[i].offset, - c->out[i].size); - break; - } - } + frame[j].can_dlc += c->out[i].size; + can_convert_to_raw( + &smps[nwrite]->data[i], n->getOutputSignals(false)->getByIndex(i), + (uint8_t *)&frame[j].data + c->out[i].offset, c->out[i].size); + break; + } + } - for (size_t j=0; j < fsize; j++) { - n->logger->debug("Writing CAN message: (id={}, dlc={}, data={:#x}:{:#x})", - frame[j].can_id, - frame[j].can_dlc, - ((uint32_t*)&frame[j].data)[0], - ((uint32_t*)&frame[j].data)[1] - ); + for (size_t j = 0; j < fsize; j++) { + n->logger->debug("Writing CAN message: (id={}, dlc={}, data={:#x}:{:#x})", + frame[j].can_id, frame[j].can_dlc, + ((uint32_t *)&frame[j].data)[0], + ((uint32_t *)&frame[j].data)[1]); - if ((nbytes = write(c->socket, &frame[j], sizeof(struct can_frame))) == -1) - throw RuntimeError("CAN write() returned -1. Is the CAN interface up?"); + if ((nbytes = write(c->socket, &frame[j], sizeof(struct can_frame))) == + -1) + throw RuntimeError("CAN write() returned -1. Is the CAN interface up?"); - if ((unsigned)nbytes != sizeof(struct can_frame)) - throw RuntimeError("CAN write() returned {} bytes but expected {}", - nbytes, sizeof(struct can_frame)); - } - } + if ((unsigned)nbytes != sizeof(struct can_frame)) + throw RuntimeError("CAN write() returned {} bytes but expected {}", + nbytes, sizeof(struct can_frame)); + } + } - return nwrite; + return nwrite; } -int villas::node::can_poll_fds(NodeCompat *n, int fds[]) -{ - auto *c = n->getData(); +int villas::node::can_poll_fds(NodeCompat *n, int fds[]) { + auto *c = n->getData(); - fds[0] = c->socket; + fds[0] = c->socket; - return 1; // The number of file descriptors which have been set in fds + return 1; // The number of file descriptors which have been set in fds } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "can"; - p.description = "Receive CAN messages using the socketCAN driver"; - p.vectorize = 0; - p.flags = 0; - p.size = sizeof(struct can); - p.init = can_init; - p.destroy = can_destroy; - p.prepare = can_prepare; - p.parse = can_parse; - p.print = can_print; - p.check = can_check; - p.start = can_start; - p.stop = can_stop; - p.read = can_read; - p.write = can_write; - p.poll_fds = can_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "can"; + p.description = "Receive CAN messages using the socketCAN driver"; + p.vectorize = 0; + p.flags = 0; + p.size = sizeof(struct can); + p.init = can_init; + p.destroy = can_destroy; + p.prepare = can_prepare; + p.parse = can_parse; + p.print = can_print; + p.check = can_check; + p.start = can_start; + p.stop = can_stop; + p.read = can_read; + p.write = can_write; + p.poll_fds = can_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/comedi.cpp b/lib/nodes/comedi.cpp index 5932a4d17..803d8ce09 100644 --- a/lib/nodes/comedi.cpp +++ b/lib/nodes/comedi.cpp @@ -6,627 +6,625 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include -#include #include +#include +#include +#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; // Utility functions to dump a comedi_cmd graciously taken from comedilib demo -static -char* comedi_cmd_trigger_src(unsigned int src, char *buf); -static -void comedi_dump_cmd(Logger logger, comedi_cmd *cmd); +static char *comedi_cmd_trigger_src(unsigned int src, char *buf); +static void comedi_dump_cmd(Logger logger, comedi_cmd *cmd); -static -int comedi_parse_direction(struct comedi *c, struct comedi_direction *d, json_t *json) -{ - int ret; +static int comedi_parse_direction(struct comedi *c, struct comedi_direction *d, + json_t *json) { + int ret; - json_t *json_chans; - json_error_t err; + json_t *json_chans; + json_error_t err; - // Default values - d->subdevice = -1; - d->buffer_size = 16; + // Default values + d->subdevice = -1; + d->buffer_size = 16; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: i, s: o, s: i }", - "subdevice", &d->subdevice, - "bufsize", &d->buffer_size, - "signals", &json_chans, - "rate", &d->sample_rate_hz - ); - if (ret) - throw ConfigError(json, err, "node-config-node-comedi"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: i, s: o, s: i }", + "subdevice", &d->subdevice, "bufsize", &d->buffer_size, + "signals", &json_chans, "rate", &d->sample_rate_hz); + if (ret) + throw ConfigError(json, err, "node-config-node-comedi"); - if (!json_is_array(json_chans)) - return -1; + if (!json_is_array(json_chans)) + return -1; - // Convert kilobytes to bytes - d->buffer_size = d->buffer_size << 10; + // Convert kilobytes to bytes + d->buffer_size = d->buffer_size << 10; - size_t i; - json_t *json_chan; + size_t i; + json_t *json_chan; - d->chanlist_len = json_array_size(json_chans); - if (d->chanlist_len == 0) - throw ConfigError(json_chans, "node-config-node-channels", "No channels configured"); + d->chanlist_len = json_array_size(json_chans); + if (d->chanlist_len == 0) + throw ConfigError(json_chans, "node-config-node-channels", + "No channels configured"); - d->chanlist = new unsigned int[d->chanlist_len]; - if (!d->chanlist) - throw MemoryAllocationError(); + d->chanlist = new unsigned int[d->chanlist_len]; + if (!d->chanlist) + throw MemoryAllocationError(); - d->chanspecs = new comedi_chanspec[d->chanlist_len]; - if (!d->chanspecs) - throw MemoryAllocationError(); + d->chanspecs = new comedi_chanspec[d->chanlist_len]; + if (!d->chanspecs) + throw MemoryAllocationError(); - json_array_foreach(json_chans, i, json_chan) { - int num, range, aref; - ret = json_unpack_ex(json_chan, &err, 0, "{ s: i, s: i, s: i }", - "channel", &num, - "range", &range, - "aref", &aref - ); - if (ret) - throw ConfigError(json_chan, err, "node-config-node-comedi"); + json_array_foreach(json_chans, i, json_chan) { + int num, range, aref; + ret = json_unpack_ex(json_chan, &err, 0, "{ s: i, s: i, s: i }", "channel", + &num, "range", &range, "aref", &aref); + if (ret) + throw ConfigError(json_chan, err, "node-config-node-comedi"); - if (aref < AREF_GROUND || aref > AREF_OTHER) - throw ConfigError(json_chan, "node-config-node-comedi-aref", "Invalid value for analog reference: aref={}", aref); + if (aref < AREF_GROUND || aref > AREF_OTHER) + throw ConfigError(json_chan, "node-config-node-comedi-aref", + "Invalid value for analog reference: aref={}", aref); - d->chanlist[i] = CR_PACK(num, range, aref); - } + d->chanlist[i] = CR_PACK(num, range, aref); + } - return 0; + return 0; } -static -int comedi_start_common(NodeCompat *n) -{ - auto *c = n->getData(); - struct comedi_direction* directions[2] = { &c->in, &c->out }; +static int comedi_start_common(NodeCompat *n) { + auto *c = n->getData(); + struct comedi_direction *directions[2] = {&c->in, &c->out}; - comedi_set_global_oor_behavior(COMEDI_OOR_NAN); + comedi_set_global_oor_behavior(COMEDI_OOR_NAN); - for (int dirIdx = 0; dirIdx < 2; dirIdx++) { - struct comedi_direction* d = directions[dirIdx]; - int ret; + for (int dirIdx = 0; dirIdx < 2; dirIdx++) { + struct comedi_direction *d = directions[dirIdx]; + int ret; - if (!d->present) - continue; + if (!d->present) + continue; - // Sanity-check channel config and populate chanspec for later - for (unsigned i = 0; i < d->chanlist_len; i++) { - const unsigned int channel = CR_CHAN(d->chanlist[i]); - const int range = CR_RANGE(d->chanlist[i]); + // Sanity-check channel config and populate chanspec for later + for (unsigned i = 0; i < d->chanlist_len; i++) { + const unsigned int channel = CR_CHAN(d->chanlist[i]); + const int range = CR_RANGE(d->chanlist[i]); - ret = comedi_get_n_ranges(c->dev, d->subdevice, channel); - if (ret < 0) - throw RuntimeError("Failed to get ranges for channel {} on subdevice {}", channel, d->subdevice); + ret = comedi_get_n_ranges(c->dev, d->subdevice, channel); + if (ret < 0) + throw RuntimeError( + "Failed to get ranges for channel {} on subdevice {}", channel, + d->subdevice); - if (range >= ret) - throw RuntimeError("Invalid range for channel {} on subdevice {}: range={}", channel, d->subdevice, range); + if (range >= ret) + throw RuntimeError( + "Invalid range for channel {} on subdevice {}: range={}", channel, + d->subdevice, range); - ret = comedi_get_maxdata(c->dev, d->subdevice, channel); - if (ret <= 0) - throw RuntimeError("Failed to get max. data value for channel {} on subdevice {}", channel, d->subdevice); + ret = comedi_get_maxdata(c->dev, d->subdevice, channel); + if (ret <= 0) + throw RuntimeError( + "Failed to get max. data value for channel {} on subdevice {}", + channel, d->subdevice); - d->chanspecs[i].maxdata = ret; - d->chanspecs[i].range = comedi_get_range(c->dev, d->subdevice, - channel, range); + d->chanspecs[i].maxdata = ret; + d->chanspecs[i].range = + comedi_get_range(c->dev, d->subdevice, channel, range); - n->logger->info("{} channel: {} aref={} range={} maxdata={}", - (d == &c->in ? "Input" : "Output"), channel, - CR_AREF(d->chanlist[i]), range, d->chanspecs[i].maxdata); - } + n->logger->info("{} channel: {} aref={} range={} maxdata={}", + (d == &c->in ? "Input" : "Output"), channel, + CR_AREF(d->chanlist[i]), range, d->chanspecs[i].maxdata); + } - const int flags = comedi_get_subdevice_flags(c->dev, d->subdevice); - d->sample_size = (flags & SDF_LSAMPL) ? sizeof(lsampl_t) : sizeof(sampl_t); + const int flags = comedi_get_subdevice_flags(c->dev, d->subdevice); + d->sample_size = (flags & SDF_LSAMPL) ? sizeof(lsampl_t) : sizeof(sampl_t); - // Set buffer size - comedi_set_buffer_size(c->dev, d->subdevice, d->buffer_size); - comedi_set_max_buffer_size(c->dev, d->subdevice, d->buffer_size); - ret = comedi_get_buffer_size(c->dev, d->subdevice); - if (ret != d->buffer_size) - throw RuntimeError("Failed to set buffer size for subdevice {}", d->subdevice); + // Set buffer size + comedi_set_buffer_size(c->dev, d->subdevice, d->buffer_size); + comedi_set_max_buffer_size(c->dev, d->subdevice, d->buffer_size); + ret = comedi_get_buffer_size(c->dev, d->subdevice); + if (ret != d->buffer_size) + throw RuntimeError("Failed to set buffer size for subdevice {}", + d->subdevice); - n->logger->info("Set buffer size for subdevice {} to {} bytes", d->subdevice, d->buffer_size); + n->logger->info("Set buffer size for subdevice {} to {} bytes", + d->subdevice, d->buffer_size); - ret = comedi_lock(c->dev, d->subdevice); - if (ret) - throw RuntimeError("Failed to lock subdevice {}", d->subdevice); - } + ret = comedi_lock(c->dev, d->subdevice); + if (ret) + throw RuntimeError("Failed to lock subdevice {}", d->subdevice); + } - return 0; + return 0; } -static -int comedi_start_in(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->in; +static int comedi_start_in(NodeCompat *n) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->in; - // Try to find first analog input subdevice if not specified in config - if (d->subdevice < 0) { - d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AI, 0); - if (d->subdevice < 0) - throw RuntimeError("Cannot find analog input device for node '{}'"); - } - else { - // Check if subdevice is usable - ret = comedi_get_subdevice_type(c->dev, d->subdevice); - if (ret != COMEDI_SUBD_AI) - throw RuntimeError("Input subdevice is not an analog input"); - } + // Try to find first analog input subdevice if not specified in config + if (d->subdevice < 0) { + d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AI, 0); + if (d->subdevice < 0) + throw RuntimeError("Cannot find analog input device for node '{}'"); + } else { + // Check if subdevice is usable + ret = comedi_get_subdevice_type(c->dev, d->subdevice); + if (ret != COMEDI_SUBD_AI) + throw RuntimeError("Input subdevice is not an analog input"); + } - ret = comedi_get_subdevice_flags(c->dev, d->subdevice); - if (ret < 0 || !(ret & SDF_CMD_READ)) - throw RuntimeError("Input subdevice does not support 'read' commands"); + ret = comedi_get_subdevice_flags(c->dev, d->subdevice); + if (ret < 0 || !(ret & SDF_CMD_READ)) + throw RuntimeError("Input subdevice does not support 'read' commands"); - comedi_set_read_subdevice(c->dev, d->subdevice); - ret = comedi_get_read_subdevice(c->dev); - if (ret < 0 || ret != d->subdevice) - throw RuntimeError("Failed to change 'read' subdevice from {} to {}", ret, d->subdevice); + comedi_set_read_subdevice(c->dev, d->subdevice); + ret = comedi_get_read_subdevice(c->dev); + if (ret < 0 || ret != d->subdevice) + throw RuntimeError("Failed to change 'read' subdevice from {} to {}", ret, + d->subdevice); - comedi_cmd cmd; - memset(&cmd, 0, sizeof(cmd)); + comedi_cmd cmd; + memset(&cmd, 0, sizeof(cmd)); - cmd.subdev = d->subdevice; + cmd.subdev = d->subdevice; - /* Make card send interrupts after every sample, not only when fifo is half + /* Make card send interrupts after every sample, not only when fifo is half * full (TODO: evaluate if this makes sense, leave as reminder) */ - //cmd.flags = TRIG_WAKE_EOS; + //cmd.flags = TRIG_WAKE_EOS; - // Start right now - cmd.start_src = TRIG_NOW; + // Start right now + cmd.start_src = TRIG_NOW; - // Trigger scans periodically - cmd.scan_begin_src = TRIG_TIMER; - cmd.scan_begin_arg = 1e9 / d->sample_rate_hz; + // Trigger scans periodically + cmd.scan_begin_src = TRIG_TIMER; + cmd.scan_begin_arg = 1e9 / d->sample_rate_hz; - // Do conversions in serial with 1ns inter-conversion delay - cmd.convert_src = TRIG_TIMER; - cmd.convert_arg = 1; // Inter-conversion delay in nanoseconds + // Do conversions in serial with 1ns inter-conversion delay + cmd.convert_src = TRIG_TIMER; + cmd.convert_arg = 1; // Inter-conversion delay in nanoseconds - // Terminate scan after each channel has been converted - cmd.scan_end_src = TRIG_COUNT; - cmd.scan_end_arg = d->chanlist_len; + // Terminate scan after each channel has been converted + cmd.scan_end_src = TRIG_COUNT; + cmd.scan_end_arg = d->chanlist_len; - // Contionous sampling - cmd.stop_src = TRIG_NONE; + // Contionous sampling + cmd.stop_src = TRIG_NONE; - cmd.chanlist = d->chanlist; - cmd.chanlist_len = d->chanlist_len; + cmd.chanlist = d->chanlist; + cmd.chanlist_len = d->chanlist_len; - // First run might change command, second should return successfully - ret = comedi_command_test(c->dev, &cmd); - ret = comedi_command_test(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Invalid command for input subdevice"); + // First run might change command, second should return successfully + ret = comedi_command_test(c->dev, &cmd); + ret = comedi_command_test(c->dev, &cmd); + if (ret < 0) + throw RuntimeError("Invalid command for input subdevice"); - n->logger->info("Input command:"); - comedi_dump_cmd(n->logger, &cmd); + n->logger->info("Input command:"); + comedi_dump_cmd(n->logger, &cmd); - ret = comedi_command(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Failed to issue command to input subdevice"); + ret = comedi_command(c->dev, &cmd); + if (ret < 0) + throw RuntimeError("Failed to issue command to input subdevice"); - d->started = time_now(); - d->counter = 0; - d->running = true; + d->started = time_now(); + d->counter = 0; + d->running = true; #if COMEDI_USE_READ - // Be prepared to consume one entire buffer - c->buf = new char[c->in.buffer_size]; - c->bufptr = c->buf; - if (!c->buf) - throw MemoryAllocationError(); + // Be prepared to consume one entire buffer + c->buf = new char[c->in.buffer_size]; + c->bufptr = c->buf; + if (!c->buf) + throw MemoryAllocationError(); - n->logger->info("Compiled for kernel read() interface"); + n->logger->info("Compiled for kernel read() interface"); #else - n->logger->info("Compiled for kernel mmap() interface"); + n->logger->info("Compiled for kernel mmap() interface"); #endif - return 0; + return 0; } -static -int comedi_start_out(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->out; +static int comedi_start_out(NodeCompat *n) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->out; - // Try to find first analog output subdevice if not specified in config - if (d->subdevice < 0) { - d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AO, 0); - if (d->subdevice < 0) - throw RuntimeError("Cannot find analog output device"); - } - else { - ret = comedi_get_subdevice_type(c->dev, d->subdevice); - if (ret != COMEDI_SUBD_AO) - throw RuntimeError("Output subdevice is not an analog output"); - } + // Try to find first analog output subdevice if not specified in config + if (d->subdevice < 0) { + d->subdevice = comedi_find_subdevice_by_type(c->dev, COMEDI_SUBD_AO, 0); + if (d->subdevice < 0) + throw RuntimeError("Cannot find analog output device"); + } else { + ret = comedi_get_subdevice_type(c->dev, d->subdevice); + if (ret != COMEDI_SUBD_AO) + throw RuntimeError("Output subdevice is not an analog output"); + } - ret = comedi_get_subdevice_flags(c->dev, d->subdevice); - if (ret < 0 || !(ret & SDF_CMD_WRITE)) - throw RuntimeError("Output subdevice does not support 'write' commands"); + ret = comedi_get_subdevice_flags(c->dev, d->subdevice); + if (ret < 0 || !(ret & SDF_CMD_WRITE)) + throw RuntimeError("Output subdevice does not support 'write' commands"); - comedi_set_write_subdevice(c->dev, d->subdevice); - ret = comedi_get_write_subdevice(c->dev); - if (ret < 0 || ret != d->subdevice) - throw RuntimeError("Failed to change 'write' subdevice from {} to {}", ret, d->subdevice); + comedi_set_write_subdevice(c->dev, d->subdevice); + ret = comedi_get_write_subdevice(c->dev); + if (ret < 0 || ret != d->subdevice) + throw RuntimeError("Failed to change 'write' subdevice from {} to {}", ret, + d->subdevice); - comedi_cmd cmd; - memset(&cmd, 0, sizeof(cmd)); + comedi_cmd cmd; + memset(&cmd, 0, sizeof(cmd)); - cmd.subdev = d->subdevice; + cmd.subdev = d->subdevice; - cmd.flags = CMDF_WRITE; + cmd.flags = CMDF_WRITE; - // Wait for internal trigger, we will have to fill the buffer first - cmd.start_src = TRIG_INT; - cmd.start_arg = 0; + // Wait for internal trigger, we will have to fill the buffer first + cmd.start_src = TRIG_INT; + cmd.start_arg = 0; - cmd.scan_begin_src = TRIG_TIMER; - cmd.scan_begin_arg = 1e9 / d->sample_rate_hz; + cmd.scan_begin_src = TRIG_TIMER; + cmd.scan_begin_arg = 1e9 / d->sample_rate_hz; - cmd.convert_src = TRIG_NOW; - cmd.convert_arg = 0; + cmd.convert_src = TRIG_NOW; + cmd.convert_arg = 0; - cmd.scan_end_src = TRIG_COUNT; - cmd.scan_end_arg = d->chanlist_len; + cmd.scan_end_src = TRIG_COUNT; + cmd.scan_end_arg = d->chanlist_len; - // Continous sampling - cmd.stop_src = TRIG_NONE; - cmd.stop_arg = 0; + // Continous sampling + cmd.stop_src = TRIG_NONE; + cmd.stop_arg = 0; - cmd.chanlist = d->chanlist; - cmd.chanlist_len = d->chanlist_len; + cmd.chanlist = d->chanlist; + cmd.chanlist_len = d->chanlist_len; - // First run might change command, second should return successfully - ret = comedi_command_test(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Invalid command for input subdevice"); + // First run might change command, second should return successfully + ret = comedi_command_test(c->dev, &cmd); + if (ret < 0) + throw RuntimeError("Invalid command for input subdevice"); - ret = comedi_command_test(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Invalid command for input subdevice"); + ret = comedi_command_test(c->dev, &cmd); + if (ret < 0) + throw RuntimeError("Invalid command for input subdevice"); - n->logger->info("Output command:"); - comedi_dump_cmd(n->logger, &cmd); + n->logger->info("Output command:"); + comedi_dump_cmd(n->logger, &cmd); - ret = comedi_command(c->dev, &cmd); - if (ret < 0) - throw RuntimeError("Failed to issue command to input subdevice of node '{}'"); + ret = comedi_command(c->dev, &cmd); + if (ret < 0) + throw RuntimeError( + "Failed to issue command to input subdevice of node '{}'"); - // Output will only start after the internal trigger - d->running = false; - d->last_debug = time_now(); + // Output will only start after the internal trigger + d->running = false; + d->last_debug = time_now(); - // Allocate buffer for one complete VILLAS sample - // TODO: maybe increase buffer size according to c->vectorize - const size_t local_buffer_size = d->sample_size * d->chanlist_len; - d->buffer = new char[local_buffer_size]; - d->bufptr = d->buffer; - if (!d->buffer) - throw MemoryAllocationError(); + // Allocate buffer for one complete VILLAS sample + // TODO: maybe increase buffer size according to c->vectorize + const size_t local_buffer_size = d->sample_size * d->chanlist_len; + d->buffer = new char[local_buffer_size]; + d->bufptr = d->buffer; + if (!d->buffer) + throw MemoryAllocationError(); - // Initialize local buffer used for write() syscalls - for (unsigned channel = 0; channel < d->chanlist_len; channel++) { - const unsigned raw = comedi_from_phys(0.0f, d->chanspecs[channel].range, d->chanspecs[channel].maxdata); + // Initialize local buffer used for write() syscalls + for (unsigned channel = 0; channel < d->chanlist_len; channel++) { + const unsigned raw = comedi_from_phys(0.0f, d->chanspecs[channel].range, + d->chanspecs[channel].maxdata); - if (d->sample_size == sizeof(sampl_t)) - *((sampl_t *)d->bufptr) = raw; - else - *((lsampl_t *)d->bufptr) = raw; + if (d->sample_size == sizeof(sampl_t)) + *((sampl_t *)d->bufptr) = raw; + else + *((lsampl_t *)d->bufptr) = raw; - d->bufptr += d->sample_size; - } + d->bufptr += d->sample_size; + } - // Preload comedi output buffer - for (unsigned i = 0; i < d->buffer_size / local_buffer_size; i++) { - size_t written = write(comedi_fileno(c->dev), d->buffer, local_buffer_size); - if (written != local_buffer_size) { - throw RuntimeError("Cannot preload Comedi buffer"); - } - } + // Preload comedi output buffer + for (unsigned i = 0; i < d->buffer_size / local_buffer_size; i++) { + size_t written = write(comedi_fileno(c->dev), d->buffer, local_buffer_size); + if (written != local_buffer_size) { + throw RuntimeError("Cannot preload Comedi buffer"); + } + } - const size_t villas_samples_in_kernel_buf = d->buffer_size / (d->sample_size * d->chanlist_len); - const double latencyMs = (double) villas_samples_in_kernel_buf / d->sample_rate_hz * 1e3; - n->logger->info("Added latency due to buffering: {:4.1f} ms", latencyMs); + const size_t villas_samples_in_kernel_buf = + d->buffer_size / (d->sample_size * d->chanlist_len); + const double latencyMs = + (double)villas_samples_in_kernel_buf / d->sample_rate_hz * 1e3; + n->logger->info("Added latency due to buffering: {:4.1f} ms", latencyMs); - return 0; + return 0; } -static -int comedi_stop_in(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->in; +static int comedi_stop_in(NodeCompat *n) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->in; - comedi_cancel(c->dev, d->subdevice); + comedi_cancel(c->dev, d->subdevice); - ret = comedi_unlock(c->dev, d->subdevice); - if (ret) - throw RuntimeError("Failed to lock subdevice {}", d->subdevice); + ret = comedi_unlock(c->dev, d->subdevice); + if (ret) + throw RuntimeError("Failed to lock subdevice {}", d->subdevice); - return 0; + return 0; } -static -int comedi_stop_out(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->out; +static int comedi_stop_out(NodeCompat *n) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->out; - comedi_cancel(c->dev, d->subdevice); + comedi_cancel(c->dev, d->subdevice); - ret = comedi_unlock(c->dev, d->subdevice); - if (ret) - throw RuntimeError("Failed to lock subdevice {}", d->subdevice); + ret = comedi_unlock(c->dev, d->subdevice); + if (ret) + throw RuntimeError("Failed to lock subdevice {}", d->subdevice); - return 0; + return 0; } -int villas::node::comedi_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *c = n->getData(); +int villas::node::comedi_parse(NodeCompat *n, json_t *json) { + int ret; + auto *c = n->getData(); - const char *device; + const char *device; - json_t *json_in = nullptr; - json_t *json_out = nullptr; - json_error_t err; + json_t *json_in = nullptr; + json_t *json_out = nullptr; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: o, s?: o }", - "device", &device, - "in", &json_in, - "out", &json_out); + ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: o, s?: o }", "device", + &device, "in", &json_in, "out", &json_out); - if (ret) - throw ConfigError(json, err, "node-config-node-comedi"); + if (ret) + throw ConfigError(json, err, "node-config-node-comedi"); - c->in.present = json_in != nullptr; - c->in.enabled = false; - c->in.running = false; + c->in.present = json_in != nullptr; + c->in.enabled = false; + c->in.running = false; - c->out.present = json_out != nullptr; - c->out.enabled = false; - c->out.running = false; + c->out.present = json_out != nullptr; + c->out.enabled = false; + c->out.running = false; - if (c->in.present) { - ret = comedi_parse_direction(c, &c->in, json_in); - if (ret) - return ret; - } + if (c->in.present) { + ret = comedi_parse_direction(c, &c->in, json_in); + if (ret) + return ret; + } - if (c->out.present) { - ret = comedi_parse_direction(c, &c->out, json_out); - if (ret) - return ret; - } + if (c->out.present) { + ret = comedi_parse_direction(c, &c->out, json_out); + if (ret) + return ret; + } - c->device = strdup(device); + c->device = strdup(device); - return 0; + return 0; } -char * villas::node::comedi_print(NodeCompat *n) -{ - auto *c = n->getData(); +char *villas::node::comedi_print(NodeCompat *n) { + auto *c = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - const char *board = comedi_get_board_name(c->dev); - const char *driver = comedi_get_driver_name(c->dev); + const char *board = comedi_get_board_name(c->dev); + const char *driver = comedi_get_driver_name(c->dev); - strcatf(&buf, "board=%s, driver=%s, device=%s", board, driver, c->device); + strcatf(&buf, "board=%s, driver=%s, device=%s", board, driver, c->device); - return buf; + return buf; } -int villas::node::comedi_start(NodeCompat *n) -{ - auto *c = n->getData(); +int villas::node::comedi_start(NodeCompat *n) { + auto *c = n->getData(); - c->dev = comedi_open(c->device); - if (!c->dev) - throw RuntimeError("Failed to open device: {}", comedi_strerror(comedi_errno())); + c->dev = comedi_open(c->device); + if (!c->dev) + throw RuntimeError("Failed to open device: {}", + comedi_strerror(comedi_errno())); - // Enable non-blocking syscalls - // TODO: verify if this works with both input and output, so comment out - //if (fcntl(comedi_fileno(c->dev), F_SETFL, O_NONBLOCK)) - // throw RuntimeError("Failed to set non-blocking flag in Comedi FD"); + // Enable non-blocking syscalls + // TODO: verify if this works with both input and output, so comment out + //if (fcntl(comedi_fileno(c->dev), F_SETFL, O_NONBLOCK)) + // throw RuntimeError("Failed to set non-blocking flag in Comedi FD"); - comedi_start_common(n); + comedi_start_common(n); - if (c->in.present) { - int ret = comedi_start_in(n); - if (ret) - return ret; + if (c->in.present) { + int ret = comedi_start_in(n); + if (ret) + return ret; - c->in.enabled = true; - } + c->in.enabled = true; + } - if (c->out.present) { - int ret = comedi_start_out(n); - if (ret) - return ret; + if (c->out.present) { + int ret = comedi_start_out(n); + if (ret) + return ret; - c->out.enabled = true; - } + c->out.enabled = true; + } #if !COMEDI_USE_READ - n->logger->info("Mapping Comedi buffer of {} bytes", c->in.buffer_size); - c->map = mmap(nullptr, c->in.buffer_size, PROT_READ, MAP_SHARED, comedi_fileno(c->dev), 0); - if (c->map == MAP_FAILED) - throw RuntimeError("Failed to map Comedi buffer"); + n->logger->info("Mapping Comedi buffer of {} bytes", c->in.buffer_size); + c->map = mmap(nullptr, c->in.buffer_size, PROT_READ, MAP_SHARED, + comedi_fileno(c->dev), 0); + if (c->map == MAP_FAILED) + throw RuntimeError("Failed to map Comedi buffer"); - c->front = 0; - c->back = 0; - c->bufpos = 0; + c->front = 0; + c->back = 0; + c->bufpos = 0; #endif - return 0; + return 0; } -int villas::node::comedi_stop(NodeCompat *n) -{ - int ret; - auto *c = n->getData(); +int villas::node::comedi_stop(NodeCompat *n) { + int ret; + auto *c = n->getData(); - if (c->in.enabled) - comedi_stop_in(n); + if (c->in.enabled) + comedi_stop_in(n); - if (c->out.enabled) - comedi_stop_out(n); + if (c->out.enabled) + comedi_stop_out(n); - ret = comedi_close(c->dev); - if (ret) - return ret; + ret = comedi_close(c->dev); + if (ret) + return ret; - return 0; + return 0; } #if COMEDI_USE_READ -int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->in; - const size_t villas_sample_size = d->chanlist_len * d->sample_size; +int villas::node::comedi_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->in; + const size_t villas_sample_size = d->chanlist_len * d->sample_size; - ret = comedi_get_buffer_contents(c->dev, d->subdevice); - if (ret < 0) { - if (comedi_errno() == EBUF_OVR) - throw RuntimeError("Comedi buffer overflow"); - else - throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); - } + ret = comedi_get_buffer_contents(c->dev, d->subdevice); + if (ret < 0) { + if (comedi_errno() == EBUF_OVR) + throw RuntimeError("Comedi buffer overflow"); + else + throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); + } - fd_set rdset; - FD_ZERO(&rdset); - FD_SET(comedi_fileno(c->dev), &rdset); + fd_set rdset; + FD_ZERO(&rdset); + FD_SET(comedi_fileno(c->dev), &rdset); - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 5000; + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 5000; - ret = select(comedi_fileno(c->dev) + 1, &rdset, nullptr, nullptr, &timeout); - if (ret < 0) - throw RuntimeError("Failed select()"); - else if (ret == 0) // hit timeout - return 0; - else if (FD_ISSET(comedi_fileno(c->dev), &rdset)) { // comedi file descriptor became ready - const size_t buffer_bytes_free = d->buffer_size - (c->bufptr - c->buf); - const size_t bytes_requested = cnt * villas_sample_size; + ret = select(comedi_fileno(c->dev) + 1, &rdset, nullptr, nullptr, &timeout); + if (ret < 0) + throw RuntimeError("Failed select()"); + else if (ret == 0) // hit timeout + return 0; + else if (FD_ISSET(comedi_fileno(c->dev), + &rdset)) { // comedi file descriptor became ready + const size_t buffer_bytes_free = d->buffer_size - (c->bufptr - c->buf); + const size_t bytes_requested = cnt * villas_sample_size; - ret = read(comedi_fileno(c->dev), c->bufptr, MIN(bytes_requested, buffer_bytes_free)); - if (ret < 0) { - if (errno == EAGAIN) - throw RuntimeError("Failed read()"); - else - return 0; - } - else if (ret == 0) { - n->logger->warn("Timeout in select(), no samples available"); - return 0; - } - else { - // Sample handling here - const size_t bytes_available = ret; - const size_t raw_samples_available = bytes_available / d->sample_size; - const size_t villas_samples_available = raw_samples_available / d->chanlist_len; + ret = read(comedi_fileno(c->dev), c->bufptr, + MIN(bytes_requested, buffer_bytes_free)); + if (ret < 0) { + if (errno == EAGAIN) + throw RuntimeError("Failed read()"); + else + return 0; + } else if (ret == 0) { + n->logger->warn("Timeout in select(), no samples available"); + return 0; + } else { + // Sample handling here + const size_t bytes_available = ret; + const size_t raw_samples_available = bytes_available / d->sample_size; + const size_t villas_samples_available = + raw_samples_available / d->chanlist_len; - n->logger->info("There are {} bytes available ({} requested) => {} VILLAS samples", - bytes_available, bytes_requested, villas_samples_available); + n->logger->info( + "There are {} bytes available ({} requested) => {} VILLAS samples", + bytes_available, bytes_requested, villas_samples_available); - if (cnt > villas_samples_available) - cnt = villas_samples_available; + if (cnt > villas_samples_available) + cnt = villas_samples_available; - for (size_t i = 0; i < cnt; i++) { - d->counter++; + for (size_t i = 0; i < cnt; i++) { + d->counter++; - smps[i]->signals = n->getInputSignals(false); - smps[i]->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE; - smps[i]->sequence = d->counter / d->chanlist_len; + smps[i]->signals = n->getInputSignals(false); + smps[i]->flags = (int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE; + smps[i]->sequence = d->counter / d->chanlist_len; - struct timespec offset = time_from_double(d->counter * 1.0 / d->sample_rate_hz); - smps[i]->ts.origin = time_add(&d->started, &offset); + struct timespec offset = + time_from_double(d->counter * 1.0 / d->sample_rate_hz); + smps[i]->ts.origin = time_add(&d->started, &offset); - smps[i]->length = d->chanlist_len; + smps[i]->length = d->chanlist_len; - if (smps[i]->capacity < d->chanlist_len) - throw RuntimeError("Sample has insufficient capacity: {} < {}", smps[i]->capacity, d->chanlist_len); + if (smps[i]->capacity < d->chanlist_len) + throw RuntimeError("Sample has insufficient capacity: {} < {}", + smps[i]->capacity, d->chanlist_len); - for (unsigned si = 0; si < d->chanlist_len; si++) { - unsigned int raw; + for (unsigned si = 0; si < d->chanlist_len; si++) { + unsigned int raw; - if (d->sample_size == sizeof(sampl_t)) - raw = *((sampl_t *)(c->bufptr)); - else - raw = *((lsampl_t *)(c->bufptr)); + if (d->sample_size == sizeof(sampl_t)) + raw = *((sampl_t *)(c->bufptr)); + else + raw = *((lsampl_t *)(c->bufptr)); - c->bufptr += d->sample_size; + c->bufptr += d->sample_size; - smps[i]->data[si].f = comedi_to_phys(raw, d->chanspecs[si].range, d->chanspecs[si].maxdata); + smps[i]->data[si].f = comedi_to_phys(raw, d->chanspecs[si].range, + d->chanspecs[si].maxdata); - if (std::isnan(smps[i]->data[si].f)) - n->logger->warn("Input: channel {} clipped", CR_CHAN(d->chanlist[si])); - } - } + if (std::isnan(smps[i]->data[si].f)) + n->logger->warn("Input: channel {} clipped", + CR_CHAN(d->chanlist[si])); + } + } - const size_t bytes_consumed = cnt * villas_sample_size; - const size_t bytes_left = bytes_available - bytes_consumed; - if (bytes_left > 0) { - // Move leftover bytes to the beginning of buffer - // TODO: optimize? - memmove(c->buf, c->bufptr, bytes_left); - } + const size_t bytes_consumed = cnt * villas_sample_size; + const size_t bytes_left = bytes_available - bytes_consumed; + if (bytes_left > 0) { + // Move leftover bytes to the beginning of buffer + // TODO: optimize? + memmove(c->buf, c->bufptr, bytes_left); + } - n->logger->info("Consumed {} bytes", bytes_consumed); + n->logger->info("Consumed {} bytes", bytes_consumed); - // Start at the beginning again - c->bufptr = c->buf; + // Start at the beginning again + c->bufptr = c->buf; - return cnt; - } - } - else - // unknown file descriptor became ready - n->logger->warn("Unknown file descriptor ready"); + return cnt; + } + } else + // unknown file descriptor became ready + n->logger->warn("Unknown file descriptor ready"); - return -1; + return -1; } #else -int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->in; +int villas::node::comedi_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->in; - const size_t villas_sample_size = d->chanlist_len * d->sample_size; + const size_t villas_sample_size = d->chanlist_len * d->sample_size; - comedi_set_read_subdevice(c->dev, d->subdevice); + comedi_set_read_subdevice(c->dev, d->subdevice); - n->logger->info("Current bufpos={}", c->bufpos); + n->logger->info("Current bufpos={}", c->bufpos); #if 0 if (c->bufpos > (d->buffer_size - villas_sample_size)) { @@ -639,23 +637,24 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig } #endif - ret = comedi_get_buffer_contents(c->dev, d->subdevice); - if (ret == 0) - return 0; - else if (ret < 0) { - if (comedi_errno() == EBUF_OVR) - throw RuntimeError("Comedi buffer overflow"); - else - throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); - } + ret = comedi_get_buffer_contents(c->dev, d->subdevice); + if (ret == 0) + return 0; + else if (ret < 0) { + if (comedi_errno() == EBUF_OVR) + throw RuntimeError("Comedi buffer overflow"); + else + throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); + } - const size_t bytes_available = ret; - const size_t raw_sample_count = bytes_available / d->sample_size; - size_t villas_sample_count = raw_sample_count / d->chanlist_len; - if (villas_sample_count == 0) - return 0; + const size_t bytes_available = ret; + const size_t raw_sample_count = bytes_available / d->sample_size; + size_t villas_sample_count = raw_sample_count / d->chanlist_len; + if (villas_sample_count == 0) + return 0; - n->logger->info("There are {} VILLAS samples ({} raw bytes, {} channels)", villas_sample_count, bytes_available, d->chanlist_len); + n->logger->info("There are {} VILLAS samples ({} raw bytes, {} channels)", + villas_sample_count, bytes_available, d->chanlist_len); #if 0 if (villas_sample_count == 1) @@ -669,8 +668,8 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig } #endif - if (cnt > villas_sample_count) - cnt = villas_sample_count; + if (cnt > villas_sample_count) + cnt = villas_sample_count; #if 0 if (bytes_available != 0 && bytes_available < villas_sample_size) { @@ -684,74 +683,81 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig } #endif - const size_t samples_total_bytes = cnt * villas_sample_size; + const size_t samples_total_bytes = cnt * villas_sample_size; - ret = comedi_mark_buffer_read(c->dev, d->subdevice, samples_total_bytes); - if (ret == 0) { - n->logger->warn("Marking read buffer ({} bytes) not working, try again later", samples_total_bytes); - return 0; - } - else if (ret != samples_total_bytes) { - n->logger->warn("Can only mark {} bytes as read, reducing samples", ret); - return 0; - } - else - n->logger->info("Consume {} bytes", ret); + ret = comedi_mark_buffer_read(c->dev, d->subdevice, samples_total_bytes); + if (ret == 0) { + n->logger->warn( + "Marking read buffer ({} bytes) not working, try again later", + samples_total_bytes); + return 0; + } else if (ret != samples_total_bytes) { + n->logger->warn("Can only mark {} bytes as read, reducing samples", ret); + return 0; + } else + n->logger->info("Consume {} bytes", ret); - // Align front to whole samples - c->front = c->back + samples_total_bytes; + // Align front to whole samples + c->front = c->back + samples_total_bytes; - for (size_t i = 0; i < cnt; i++) { - d->counter++; + for (size_t i = 0; i < cnt; i++) { + d->counter++; - smps[i]->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE; - smps[i]->sequence = d->counter / d->chanlist_len; + smps[i]->flags = (int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE; + smps[i]->sequence = d->counter / d->chanlist_len; - struct timespec offset = time_from_double(d->counter * 1.0 / d->sample_rate_hz); - smps[i]->ts.origin = time_add(&d->started, &offset); + struct timespec offset = + time_from_double(d->counter * 1.0 / d->sample_rate_hz); + smps[i]->ts.origin = time_add(&d->started, &offset); - smps[i]->length = d->chanlist_len; + smps[i]->length = d->chanlist_len; - if (smps[i]->capacity < d->chanlist_len) - throw RuntimeError("Sample has insufficient capacity: {} < {}", smps[i]->capacity, d->chanlist_len); + if (smps[i]->capacity < d->chanlist_len) + throw RuntimeError("Sample has insufficient capacity: {} < {}", + smps[i]->capacity, d->chanlist_len); - for (int si = 0; si < d->chanlist_len; si++) { - unsigned int raw; + for (int si = 0; si < d->chanlist_len; si++) { + unsigned int raw; - if (d->sample_size == sizeof(sampl_t)) - raw = *((sampl_t *)(c->map + c->bufpos)); - else - raw = *((lsampl_t *)(c->map + c->bufpos)); + if (d->sample_size == sizeof(sampl_t)) + raw = *((sampl_t *)(c->map + c->bufpos)); + else + raw = *((lsampl_t *)(c->map + c->bufpos)); - smps[i]->data[si].f = comedi_to_phys(raw, d->chanspecs[si].range, d->chanspecs[si].maxdata); + smps[i]->data[si].f = + comedi_to_phys(raw, d->chanspecs[si].range, d->chanspecs[si].maxdata); - if (isnan(smps[i]->data[si].f)) - throw RuntimeError("Got nan"); + if (isnan(smps[i]->data[si].f)) + throw RuntimeError("Got nan"); -// smps[i]->data[si].i = raw; + // smps[i]->data[si].i = raw; - c->bufpos += d->sample_size; - if (c->bufpos >= d->buffer_size) { - n->logger->warn("Read buffer wraparound"); -// c->bufpos = 0; - } - } - } + c->bufpos += d->sample_size; + if (c->bufpos >= d->buffer_size) { + n->logger->warn("Read buffer wraparound"); + // c->bufpos = 0; + } + } + } -// const size_t bytes_consumed = c->front - c->back; + // const size_t bytes_consumed = c->front - c->back; -// n->logger->info("Advance Comedi buffer by {} bytes", bytes_consumed); + // n->logger->info("Advance Comedi buffer by {} bytes", bytes_consumed); - ret = comedi_get_buffer_read_offset(c->dev, d->subdevice); - if (ret < 0) { - if (comedi_errno() != EPIPE) - throw RuntimeError("Failed to get read buffer offset: {}, Comedi error {}", ret, comedi_strerror(comedi_errno())); - else - ret = c->bufpos; - } + ret = comedi_get_buffer_read_offset(c->dev, d->subdevice); + if (ret < 0) { + if (comedi_errno() != EPIPE) + throw RuntimeError( + "Failed to get read buffer offset: {}, Comedi error {}", ret, + comedi_strerror(comedi_errno())); + else + ret = c->bufpos; + } - n->logger->warn("Change bufpos: {} to {}", c->bufpos, ret); - c->bufpos = ret; + n->logger->warn("Change bufpos: {} to {}", c->bufpos, ret); + c->bufpos = ret; #if 0 ret = comedi_mark_buffer_read(c->dev, d->subdevice, bytes_consumed); @@ -785,207 +791,217 @@ int villas::node::comedi_read(NodeCompat *n, struct Sample * const smps[], unsig } #endif -// n->logger->info("New bufpos: {}", c->bufpos); + // n->logger->info("New bufpos: {}", c->bufpos); - c->back = c->front; + c->back = c->front; - return cnt; + return cnt; } #endif -int villas::node::comedi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *c = n->getData(); - struct comedi_direction *d = &c->out; +int villas::node::comedi_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *c = n->getData(); + struct comedi_direction *d = &c->out; - if (!d->enabled) { - n->logger->warn("Attempting to write, but output is not enabled"); - return 0; - } + if (!d->enabled) { + n->logger->warn("Attempting to write, but output is not enabled"); + return 0; + } - if (!d->running) { - // Output was not yet running, so start now - ret = comedi_internal_trigger(c->dev, d->subdevice, 0); - if (ret < 0) - throw RuntimeError("Failed to trigger-start output"); + if (!d->running) { + // Output was not yet running, so start now + ret = comedi_internal_trigger(c->dev, d->subdevice, 0); + if (ret < 0) + throw RuntimeError("Failed to trigger-start output"); - d->started = time_now(); - d->counter = 0; - d->running = true; + d->started = time_now(); + d->counter = 0; + d->running = true; - n->logger->info("Starting output"); - } + n->logger->info("Starting output"); + } - const size_t buffer_capacity_raw = d->buffer_size / d->sample_size; - const size_t buffer_capacity_villas = buffer_capacity_raw / d->chanlist_len; - const size_t villas_sample_size = d->sample_size * d->chanlist_len; + const size_t buffer_capacity_raw = d->buffer_size / d->sample_size; + const size_t buffer_capacity_villas = buffer_capacity_raw / d->chanlist_len; + const size_t villas_sample_size = d->sample_size * d->chanlist_len; - ret = comedi_get_buffer_contents(c->dev, d->subdevice); - if (ret < 0) { - if (comedi_errno() == EBUF_OVR) - throw RuntimeError("Comedi buffer overflow"); - else - throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); - } + ret = comedi_get_buffer_contents(c->dev, d->subdevice); + if (ret < 0) { + if (comedi_errno() == EBUF_OVR) + throw RuntimeError("Comedi buffer overflow"); + else + throw RuntimeError("Comedi error: {}", comedi_strerror(comedi_errno())); + } - const size_t bytes_in_buffer = ret; - const size_t raw_samples_in_buffer = bytes_in_buffer / d->sample_size; - const size_t villas_samples_in_buffer = raw_samples_in_buffer / d->chanlist_len; + const size_t bytes_in_buffer = ret; + const size_t raw_samples_in_buffer = bytes_in_buffer / d->sample_size; + const size_t villas_samples_in_buffer = + raw_samples_in_buffer / d->chanlist_len; - if (villas_samples_in_buffer == buffer_capacity_villas) { - n->logger->warn("Comedi buffer is full"); - return 0; - } - else { - struct timespec now = time_now(); - if (time_delta(&d->last_debug, &now) >= 1) { - n->logger->debug("Comedi write buffer: {} VILLAS samples ({}% of buffer)", - villas_samples_in_buffer, - (100.0f * villas_samples_in_buffer / buffer_capacity_villas)); + if (villas_samples_in_buffer == buffer_capacity_villas) { + n->logger->warn("Comedi buffer is full"); + return 0; + } else { + struct timespec now = time_now(); + if (time_delta(&d->last_debug, &now) >= 1) { + n->logger->debug( + "Comedi write buffer: {} VILLAS samples ({}% of buffer)", + villas_samples_in_buffer, + (100.0f * villas_samples_in_buffer / buffer_capacity_villas)); - d->last_debug = time_now(); - } - } + d->last_debug = time_now(); + } + } - size_t villas_samples_written = 0; + size_t villas_samples_written = 0; - while (villas_samples_written < cnt) { - const struct Sample *sample = smps[villas_samples_written]; - if (sample->length != d->chanlist_len) - throw RuntimeError("Value count in sample ({}) != configured output channels ({})", sample->length, d->chanlist_len); + while (villas_samples_written < cnt) { + const struct Sample *sample = smps[villas_samples_written]; + if (sample->length != d->chanlist_len) + throw RuntimeError( + "Value count in sample ({}) != configured output channels ({})", + sample->length, d->chanlist_len); - d->bufptr = d->buffer; + d->bufptr = d->buffer; - // Move samples from villas into local buffer for comedi - for (unsigned si = 0; si < sample->length; si++) { - unsigned raw_value = 0; + // Move samples from villas into local buffer for comedi + for (unsigned si = 0; si < sample->length; si++) { + unsigned raw_value = 0; - switch (sample_format(sample, si)) { - case SignalType::FLOAT: - raw_value = comedi_from_phys(sample->data[si].f, d->chanspecs[si].range, d->chanspecs[si].maxdata); - break; + switch (sample_format(sample, si)) { + case SignalType::FLOAT: + raw_value = comedi_from_phys(sample->data[si].f, d->chanspecs[si].range, + d->chanspecs[si].maxdata); + break; - case SignalType::INTEGER: - // Treat sample as already raw DAC value - raw_value = sample->data[si].i; - break; + case SignalType::INTEGER: + // Treat sample as already raw DAC value + raw_value = sample->data[si].i; + break; - case SignalType::BOOLEAN: - raw_value = comedi_from_phys(sample->data[si].b ? 1 : 0, d->chanspecs[si].range, d->chanspecs[si].maxdata); - break; + case SignalType::BOOLEAN: + raw_value = + comedi_from_phys(sample->data[si].b ? 1 : 0, d->chanspecs[si].range, + d->chanspecs[si].maxdata); + break; - case SignalType::COMPLEX: - // We only output the real part - raw_value = comedi_from_phys(std::real(sample->data[si].z), d->chanspecs[si].range, d->chanspecs[si].maxdata); - break; + case SignalType::COMPLEX: + // We only output the real part + raw_value = + comedi_from_phys(std::real(sample->data[si].z), + d->chanspecs[si].range, d->chanspecs[si].maxdata); + break; - case SignalType::INVALID: - raw_value = 0; - break; - } + case SignalType::INVALID: + raw_value = 0; + break; + } - if (d->sample_size == sizeof(sampl_t)) - *((sampl_t *)d->bufptr) = raw_value; - else - *((lsampl_t *)d->bufptr) = raw_value; + if (d->sample_size == sizeof(sampl_t)) + *((sampl_t *)d->bufptr) = raw_value; + else + *((lsampl_t *)d->bufptr) = raw_value; - d->bufptr += d->sample_size; - } + d->bufptr += d->sample_size; + } - // Try to write one complete villas sample to comedi - size_t written = write(comedi_fileno(c->dev), d->buffer, villas_sample_size); - if (written < 0) - throw RuntimeError("write() failed"); - else if (written == 0) - break; // Comedi doesn't accept any more samples at the moment - else if (written == villas_sample_size) - villas_samples_written++; - else - throw RuntimeError("Only partial sample written ({} bytes), oops", written); - } + // Try to write one complete villas sample to comedi + size_t written = + write(comedi_fileno(c->dev), d->buffer, villas_sample_size); + if (written < 0) + throw RuntimeError("write() failed"); + else if (written == 0) + break; // Comedi doesn't accept any more samples at the moment + else if (written == villas_sample_size) + villas_samples_written++; + else + throw RuntimeError("Only partial sample written ({} bytes), oops", + written); + } - if (villas_samples_written == 0) - n->logger->warn("Nothing done"); + if (villas_samples_written == 0) + n->logger->warn("Nothing done"); - d->counter += villas_samples_written; + d->counter += villas_samples_written; - return villas_samples_written; + return villas_samples_written; } -static -char* comedi_cmd_trigger_src(unsigned int src, char *buf) -{ - buf[0] = 0; +static char *comedi_cmd_trigger_src(unsigned int src, char *buf) { + buf[0] = 0; - if (src & TRIG_NONE) strcat(buf, "none|"); - if (src & TRIG_NOW) strcat(buf, "now|"); - if (src & TRIG_FOLLOW) strcat(buf, "follow|"); - if (src & TRIG_TIME) strcat(buf, "time|"); - if (src & TRIG_TIMER) strcat(buf, "timer|"); - if (src & TRIG_COUNT) strcat(buf, "count|"); - if (src & TRIG_EXT) strcat(buf, "ext|"); - if (src & TRIG_INT) strcat(buf, "int|"); + if (src & TRIG_NONE) + strcat(buf, "none|"); + if (src & TRIG_NOW) + strcat(buf, "now|"); + if (src & TRIG_FOLLOW) + strcat(buf, "follow|"); + if (src & TRIG_TIME) + strcat(buf, "time|"); + if (src & TRIG_TIMER) + strcat(buf, "timer|"); + if (src & TRIG_COUNT) + strcat(buf, "count|"); + if (src & TRIG_EXT) + strcat(buf, "ext|"); + if (src & TRIG_INT) + strcat(buf, "int|"); - if (strlen(buf) == 0) - sprintf(buf, "unknown(0x%08x)", src); - else - buf[strlen(buf) - 1] = 0; + if (strlen(buf) == 0) + sprintf(buf, "unknown(0x%08x)", src); + else + buf[strlen(buf) - 1] = 0; - return buf; + return buf; } -static -void comedi_dump_cmd(Logger logger, comedi_cmd *cmd) -{ - char buf[256]; - char* src; +static void comedi_dump_cmd(Logger logger, comedi_cmd *cmd) { + char buf[256]; + char *src; - logger->debug("subdevice: {}", cmd->subdev); + logger->debug("subdevice: {}", cmd->subdev); - src = comedi_cmd_trigger_src(cmd->start_src, buf); - logger->debug("start: {:-8s} {}", src, cmd->start_arg); + src = comedi_cmd_trigger_src(cmd->start_src, buf); + logger->debug("start: {:-8s} {}", src, cmd->start_arg); - src = comedi_cmd_trigger_src(cmd->scan_begin_src, buf); - logger->debug("scan_begin: {:-8s} {}", src, cmd->scan_begin_arg); + src = comedi_cmd_trigger_src(cmd->scan_begin_src, buf); + logger->debug("scan_begin: {:-8s} {}", src, cmd->scan_begin_arg); - src = comedi_cmd_trigger_src(cmd->convert_src, buf); - logger->debug("convert: {:-8s} {}", src, cmd->convert_arg); + src = comedi_cmd_trigger_src(cmd->convert_src, buf); + logger->debug("convert: {:-8s} {}", src, cmd->convert_arg); - src = comedi_cmd_trigger_src(cmd->scan_end_src, buf); - logger->debug("scan_end: {:-8s} {}", src, cmd->scan_end_arg); + src = comedi_cmd_trigger_src(cmd->scan_end_src, buf); + logger->debug("scan_end: {:-8s} {}", src, cmd->scan_end_arg); - src = comedi_cmd_trigger_src(cmd->stop_src,buf); - logger->debug("stop: {:-8s} {}", src, cmd->stop_arg); + src = comedi_cmd_trigger_src(cmd->stop_src, buf); + logger->debug("stop: {:-8s} {}", src, cmd->stop_arg); } -int villas::node::comedi_poll_fds(NodeCompat *n, int fds[]) -{ - auto *c = n->getData(); +int villas::node::comedi_poll_fds(NodeCompat *n, int fds[]) { + auto *c = n->getData(); - fds[0] = comedi_fileno(c->dev); + fds[0] = comedi_fileno(c->dev); - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "comedi"; - p.description = "Comedi-compatible DAQ/ADC cards"; - p.vectorize = 0; - p.size = sizeof(struct comedi); - p.parse = comedi_parse; - p.print = comedi_print; - p.start = comedi_start; - p.stop = comedi_stop; - p.read = comedi_read; - p.write = comedi_write; - p.poll_fds = comedi_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "comedi"; + p.description = "Comedi-compatible DAQ/ADC cards"; + p.vectorize = 0; + p.size = sizeof(struct comedi); + p.parse = comedi_parse; + p.print = comedi_print; + p.start = comedi_start; + p.stop = comedi_stop; + p.read = comedi_read; + p.write = comedi_write; + p.poll_fds = comedi_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/ethercat.cpp b/lib/nodes/ethercat.cpp index 5c8df874d..3b2944637 100644 --- a/lib/nodes/ethercat.cpp +++ b/lib/nodes/ethercat.cpp @@ -9,18 +9,17 @@ #include -#include -#include #include #include #include +#include +#include using namespace villas; using namespace villas::node; // Forward declartions -static -NodeCompatType p; +static NodeCompatType p; // Constants #define NSEC_PER_SEC (1000000000) @@ -30,430 +29,411 @@ NodeCompatType p; int master_id = 0; int alias = 0; -static -ec_master_t *master = nullptr; +static ec_master_t *master = nullptr; struct coupler { - int position; - int vendor_id; - int product_code; + int position; + int vendor_id; + int product_code; - ec_slave_config_t *sc; -} coupler = { - .position = 0, - .vendor_id = ETHERCAT_VID_BECKHOFF, - .product_code = ETHERCAT_PID_EK1100, - .sc = nullptr -}; + ec_slave_config_t *sc; +} coupler = {.position = 0, + .vendor_id = ETHERCAT_VID_BECKHOFF, + .product_code = ETHERCAT_PID_EK1100, + .sc = nullptr}; -static -void ethercat_cyclic_task(NodeCompat *n) -{ - int ret; - struct Sample *smp; - auto *w = n->getData(); +static void ethercat_cyclic_task(NodeCompat *n) { + int ret; + struct Sample *smp; + auto *w = n->getData(); - while (true) { - w->task.wait(); + while (true) { + w->task.wait(); - // Receive process data - ecrt_master_receive(master); - ecrt_domain_process(w->domain); + // Receive process data + ecrt_master_receive(master); + ecrt_domain_process(w->domain); - // Receive process data - smp = sample_alloc(&w->pool); - if (!smp) { - n->logger->warn("Pool underrun"); - continue; - } + // Receive process data + smp = sample_alloc(&w->pool); + if (!smp) { + n->logger->warn("Pool underrun"); + continue; + } - smp->length = MIN(w->in.num_channels, smp->capacity); - smp->flags = (int) SampleFlags::HAS_DATA; - smp->signals = n->getInputSignals(false); + smp->length = MIN(w->in.num_channels, smp->capacity); + smp->flags = (int)SampleFlags::HAS_DATA; + smp->signals = n->getInputSignals(false); - // Read process data - for (unsigned i = 0; i < smp->length; i++) { - int16_t ain_value = EC_READ_S16(w->domain_pd + w->in.offsets[i]); + // Read process data + for (unsigned i = 0; i < smp->length; i++) { + int16_t ain_value = EC_READ_S16(w->domain_pd + w->in.offsets[i]); - smp->data[i].f = w->in.range * (float) ain_value / INT16_MAX; - } + smp->data[i].f = w->in.range * (float)ain_value / INT16_MAX; + } - ret = queue_signalled_push(&w->queue, smp); - if (ret) - n->logger->warn("Failed to enqueue samples"); + ret = queue_signalled_push(&w->queue, smp); + if (ret) + n->logger->warn("Failed to enqueue samples"); - // Write process data - smp = w->send.exchange(nullptr); + // Write process data + smp = w->send.exchange(nullptr); - for (unsigned i = 0; i < w->out.num_channels; i++) { - int16_t aout_value = (smp->data[i].f / w->out.range) * INT16_MAX; + for (unsigned i = 0; i < w->out.num_channels; i++) { + int16_t aout_value = (smp->data[i].f / w->out.range) * INT16_MAX; - EC_WRITE_S16(w->domain_pd + w->out.offsets[i], aout_value); - } + EC_WRITE_S16(w->domain_pd + w->out.offsets[i], aout_value); + } - sample_decref(smp); + sample_decref(smp); - // send process data - ecrt_domain_queue(w->domain); - ecrt_master_send(master); - } + // send process data + ecrt_domain_queue(w->domain); + ecrt_master_send(master); + } } -int villas::node::ethercat_type_start(villas::node::SuperNode *sn) -{ - int ret; - json_error_t err; +int villas::node::ethercat_type_start(villas::node::SuperNode *sn) { + int ret; + json_error_t err; - if (sn == nullptr) - throw RuntimeError("EtherCAT node-type requires super-node"); + if (sn == nullptr) + throw RuntimeError("EtherCAT node-type requires super-node"); - json_t *json = sn->getConfig(); - if (json) { - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?:i, s?: { s?: { s?: i, s?: i, s?: i } } }", - "ethernet", - "master", &master_id, - "alias", &alias, - "coupler", - "position", &coupler.position, - "product_code", &coupler.product_code, - "vendor_id", &coupler.vendor_id - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ethercat"); - } + json_t *json = sn->getConfig(); + if (json) { + ret = json_unpack_ex( + json, &err, 0, "{ s?: i, s?:i, s?: { s?: { s?: i, s?: i, s?: i } } }", + "ethernet", "master", &master_id, "alias", &alias, "coupler", + "position", &coupler.position, "product_code", &coupler.product_code, + "vendor_id", &coupler.vendor_id); + if (ret) + throw ConfigError(json, err, "node-config-node-ethercat"); + } - master = ecrt_request_master(master_id); - if (!master) - return -1; + master = ecrt_request_master(master_id); + if (!master) + return -1; - // Create configuration for bus coupler - coupler.sc = ecrt_master_slave_config(master, alias, coupler.position, coupler.vendor_id, coupler.product_code); - if (!coupler.sc) - return -1; + // Create configuration for bus coupler + coupler.sc = ecrt_master_slave_config( + master, alias, coupler.position, coupler.vendor_id, coupler.product_code); + if (!coupler.sc) + return -1; - return 0; + return 0; } -int villas::node::ethercat_type_stop() -{ - auto logger = logging.get("node:ethercat"); +int villas::node::ethercat_type_stop() { + auto logger = logging.get("node:ethercat"); - logger->info("Releasing EtherCAT master"); + logger->info("Releasing EtherCAT master"); - ecrt_release_master(master); + ecrt_release_master(master); - return 0; + return 0; } -int villas::node::ethercat_parse(NodeCompat *n, json_t *json) -{ - auto *w = n->getData(); +int villas::node::ethercat_parse(NodeCompat *n, json_t *json) { + auto *w = n->getData(); - int ret; - json_error_t err; + int ret; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: { s: i, s?: F, s?: i, s?: i, s?: i }, s?: { s: i, s?: F, s?: i, s?: i, s?: i } }", - "rate", &w->rate, - "out", - "num_channels", &w->out.num_channels, - "range", &w->out.range, - "position", &w->out.position, - "product_code", &w->out.product_code, - "vendor_id", &w->out.vendor_id, - "in", - "num_channels", &w->in.num_channels, - "range", &w->in.range, - "position", &w->in.position, - "product_code", &w->in.product_code, - "vendor_id", &w->in.vendor_id - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ethercat"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: F, s?: { s: i, s?: F, s?: i, s?: i, s?: i }, s?: " + "{ s: i, s?: F, s?: i, s?: i, s?: i } }", + "rate", &w->rate, "out", "num_channels", + &w->out.num_channels, "range", &w->out.range, "position", + &w->out.position, "product_code", &w->out.product_code, + "vendor_id", &w->out.vendor_id, "in", "num_channels", + &w->in.num_channels, "range", &w->in.range, "position", + &w->in.position, "product_code", &w->in.product_code, + "vendor_id", &w->in.vendor_id); + if (ret) + throw ConfigError(json, err, "node-config-node-ethercat"); - return 0; + return 0; } -char * villas::node::ethercat_print(NodeCompat *n) -{ - auto *w = n->getData(); - std::stringstream ss; +char *villas::node::ethercat_print(NodeCompat *n) { + auto *w = n->getData(); + std::stringstream ss; - ss << "alias=" << alias; - ss << ", in.range=" << w->in.range << ", in.num_channels=" << w->in.num_channels; - ss << ", out.range=" << w->out.range << ", out.num_channels=" << w->out.num_channels; + ss << "alias=" << alias; + ss << ", in.range=" << w->in.range + << ", in.num_channels=" << w->in.num_channels; + ss << ", out.range=" << w->out.range + << ", out.num_channels=" << w->out.num_channels; - return strdup(ss.str().c_str()); + return strdup(ss.str().c_str()); } -int villas::node::ethercat_check(NodeCompat *n) -{ - auto *w = n->getData(); +int villas::node::ethercat_check(NodeCompat *n) { + auto *w = n->getData(); - // Some parts of the configuration are still hard-coded for this specific setup - if (w->in.product_code != ETHERCAT_PID_EL3008 || - w->in.vendor_id != ETHERCAT_VID_BECKHOFF || - w->out.product_code != ETHERCAT_PID_EL4038 || - w->out.vendor_id != ETHERCAT_VID_BECKHOFF || - coupler.product_code != ETHERCAT_PID_EK1100 || - coupler.vendor_id != ETHERCAT_VID_BECKHOFF - ) - return -1; + // Some parts of the configuration are still hard-coded for this specific setup + if (w->in.product_code != ETHERCAT_PID_EL3008 || + w->in.vendor_id != ETHERCAT_VID_BECKHOFF || + w->out.product_code != ETHERCAT_PID_EL4038 || + w->out.vendor_id != ETHERCAT_VID_BECKHOFF || + coupler.product_code != ETHERCAT_PID_EK1100 || + coupler.vendor_id != ETHERCAT_VID_BECKHOFF) + return -1; - return 0; + return 0; } -int villas::node::ethercat_prepare(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::ethercat_prepare(NodeCompat *n) { + int ret; + auto *w = n->getData(); - ret = pool_init(&w->pool, DEFAULT_ETHERCAT_QUEUE_LENGTH, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + ret = pool_init(&w->pool, DEFAULT_ETHERCAT_QUEUE_LENGTH, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&w->queue, DEFAULT_ETHERCAT_QUEUE_LENGTH); - if (ret) - return ret; + ret = queue_signalled_init(&w->queue, DEFAULT_ETHERCAT_QUEUE_LENGTH); + if (ret) + return ret; - w->in.offsets = new unsigned[w->in.num_channels]; - if (!w->in.offsets) - throw MemoryAllocationError(); + w->in.offsets = new unsigned[w->in.num_channels]; + if (!w->in.offsets) + throw MemoryAllocationError(); - w->out.offsets = new unsigned[w->out.num_channels]; - if (!w->out.offsets) - throw MemoryAllocationError(); + w->out.offsets = new unsigned[w->out.num_channels]; + if (!w->out.offsets) + throw MemoryAllocationError(); - w->domain_regs = new ec_pdo_entry_reg_t[w->in.num_channels + w->out.num_channels + 1]; - if (!w->domain_regs) - throw MemoryAllocationError(); + w->domain_regs = + new ec_pdo_entry_reg_t[w->in.num_channels + w->out.num_channels + 1]; + if (!w->domain_regs) + throw MemoryAllocationError(); - memset(w->domain_regs, 0, (w->in.num_channels + w->out.num_channels + 1) * sizeof(ec_pdo_entry_reg_t)); + memset(w->domain_regs, 0, + (w->in.num_channels + w->out.num_channels + 1) * + sizeof(ec_pdo_entry_reg_t)); - // Prepare list of domain registers - int o = 0; - for (unsigned i = 0; i < w->out.num_channels; i++) { - w->out.offsets[i] = 0; + // Prepare list of domain registers + int o = 0; + for (unsigned i = 0; i < w->out.num_channels; i++) { + w->out.offsets[i] = 0; - w->domain_regs[o].alias = alias; - w->domain_regs[o].position = w->out.position; - w->domain_regs[o].vendor_id = w->out.vendor_id; - w->domain_regs[o].product_code = w->out.product_code; - w->domain_regs[o].index = 0x7000 + i * 0x10; - w->domain_regs[o].subindex = 0x1; - w->domain_regs[o].offset = w->out.offsets + i; + w->domain_regs[o].alias = alias; + w->domain_regs[o].position = w->out.position; + w->domain_regs[o].vendor_id = w->out.vendor_id; + w->domain_regs[o].product_code = w->out.product_code; + w->domain_regs[o].index = 0x7000 + i * 0x10; + w->domain_regs[o].subindex = 0x1; + w->domain_regs[o].offset = w->out.offsets + i; - o++; - }; + o++; + }; - // Prepare list of domain registers - for (unsigned i = 0; i < w->in.num_channels; i++) { - w->in.offsets[i] = 0; + // Prepare list of domain registers + for (unsigned i = 0; i < w->in.num_channels; i++) { + w->in.offsets[i] = 0; - w->domain_regs[o].alias = alias; - w->domain_regs[o].position = w->in.position; - w->domain_regs[o].vendor_id = w->in.vendor_id; - w->domain_regs[o].product_code = w->in.product_code; - w->domain_regs[o].index = 0x6000 + i * 0x10; - w->domain_regs[o].subindex = 0x11; - w->domain_regs[o].offset = w->in.offsets + i; + w->domain_regs[o].alias = alias; + w->domain_regs[o].position = w->in.position; + w->domain_regs[o].vendor_id = w->in.vendor_id; + w->domain_regs[o].product_code = w->in.product_code; + w->domain_regs[o].index = 0x6000 + i * 0x10; + w->domain_regs[o].subindex = 0x11; + w->domain_regs[o].offset = w->in.offsets + i; - o++; - }; + o++; + }; - w->domain = ecrt_master_create_domain(master); - if (!w->domain) - return -1; + w->domain = ecrt_master_create_domain(master); + if (!w->domain) + return -1; - return 0; + return 0; } -int villas::node::ethercat_start(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::ethercat_start(NodeCompat *n) { + int ret; + auto *w = n->getData(); - // Configure analog in - w->in.sc = ecrt_master_slave_config(master, alias, w->in.position, w->in.vendor_id, w->in.product_code); - if (!w->in.sc) - throw RuntimeError("Failed to get slave configuration."); + // Configure analog in + w->in.sc = ecrt_master_slave_config(master, alias, w->in.position, + w->in.vendor_id, w->in.product_code); + if (!w->in.sc) + throw RuntimeError("Failed to get slave configuration."); - ret = ecrt_slave_config_pdos(w->in.sc, EC_END, slave_4_syncs); - if (ret) - throw RuntimeError("Failed to configure PDOs."); + ret = ecrt_slave_config_pdos(w->in.sc, EC_END, slave_4_syncs); + if (ret) + throw RuntimeError("Failed to configure PDOs."); - // Configure analog out - w->out.sc = ecrt_master_slave_config(master, alias, w->out.position, w->out.vendor_id, w->out.product_code); - if (!w->out.sc) - throw RuntimeError("Failed to get slave configuration."); + // Configure analog out + w->out.sc = ecrt_master_slave_config(master, alias, w->out.position, + w->out.vendor_id, w->out.product_code); + if (!w->out.sc) + throw RuntimeError("Failed to get slave configuration."); - ret = ecrt_slave_config_pdos(w->out.sc, EC_END, slave_3_syncs); - if (ret) - throw RuntimeError("Failed to configure PDOs."); + ret = ecrt_slave_config_pdos(w->out.sc, EC_END, slave_3_syncs); + if (ret) + throw RuntimeError("Failed to configure PDOs."); - ret = ecrt_domain_reg_pdo_entry_list(w->domain, w->domain_regs); - if (ret) - throw RuntimeError("PDO entry registration failed!"); + ret = ecrt_domain_reg_pdo_entry_list(w->domain, w->domain_regs); + if (ret) + throw RuntimeError("PDO entry registration failed!"); - // TODO: Check that master is not already active... - ret = ecrt_master_activate(master); - if (ret) - return -1; + // TODO: Check that master is not already active... + ret = ecrt_master_activate(master); + if (ret) + return -1; - w->domain_pd = ecrt_domain_data(w->domain); - if (!w->domain_pd) - return -1; + w->domain_pd = ecrt_domain_data(w->domain); + if (!w->domain_pd) + return -1; - // Start cyclic timer - w->task.setRate(w->rate); + // Start cyclic timer + w->task.setRate(w->rate); - // Start cyclic task - w->thread = std::thread(ethercat_cyclic_task, n); + // Start cyclic task + w->thread = std::thread(ethercat_cyclic_task, n); - return 0; + return 0; } -int villas::node::ethercat_stop(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::ethercat_stop(NodeCompat *n) { + int ret; + auto *w = n->getData(); - w->thread.join(); + w->thread.join(); - ret = queue_signalled_close(&w->queue); - if (ret) - return ret; + ret = queue_signalled_close(&w->queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::ethercat_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *w = n->getData(); +int villas::node::ethercat_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *w = n->getData(); - int avail; - struct Sample *cpys[cnt]; + int avail; + struct Sample *cpys[cnt]; - avail = queue_signalled_pull_many(&w->queue, (void **) cpys, cnt); - if (avail < 0) - n->logger->warn("Pool underrun: avail={}", avail); + avail = queue_signalled_pull_many(&w->queue, (void **)cpys, cnt); + if (avail < 0) + n->logger->warn("Pool underrun: avail={}", avail); - sample_copy_many(smps, cpys, avail); - sample_decref_many(cpys, avail); + sample_copy_many(smps, cpys, avail); + sample_decref_many(cpys, avail); - return avail; + return avail; } -int villas::node::ethercat_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *w = n->getData(); +int villas::node::ethercat_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *w = n->getData(); - if (cnt < 1) - return cnt; + if (cnt < 1) + return cnt; - struct Sample *smp = smps[0]; + struct Sample *smp = smps[0]; - sample_incref(smp); + sample_incref(smp); - struct Sample *old = w->send.exchange(smp); - if (old) - sample_decref(old); + struct Sample *old = w->send.exchange(smp); + if (old) + sample_decref(old); - return 1; + return 1; } -int villas::node::ethercat_init(NodeCompat *n) -{ - auto *w = n->getData(); +int villas::node::ethercat_init(NodeCompat *n) { + auto *w = n->getData(); - // Default values - w->rate = 1000; + // Default values + w->rate = 1000; - w->in.num_channels = 8; - w->in.range = 10.0; - w->in.position = 2; - w->in.product_code = ETHERCAT_PID_EL3008; - w->in.vendor_id = ETHERCAT_VID_BECKHOFF; - w->in.sc = nullptr; - w->in.offsets = nullptr; + w->in.num_channels = 8; + w->in.range = 10.0; + w->in.position = 2; + w->in.product_code = ETHERCAT_PID_EL3008; + w->in.vendor_id = ETHERCAT_VID_BECKHOFF; + w->in.sc = nullptr; + w->in.offsets = nullptr; - w->out.num_channels = 8; - w->out.range = 10.0; - w->out.position = 1; - w->out.product_code = ETHERCAT_PID_EL4038; - w->out.vendor_id = ETHERCAT_VID_BECKHOFF; - w->out.sc = nullptr; - w->out.offsets = nullptr; + w->out.num_channels = 8; + w->out.range = 10.0; + w->out.position = 1; + w->out.product_code = ETHERCAT_PID_EL4038; + w->out.vendor_id = ETHERCAT_VID_BECKHOFF; + w->out.sc = nullptr; + w->out.offsets = nullptr; - w->domain = nullptr; - w->domain_pd = nullptr; - w->domain_regs = nullptr; + w->domain = nullptr; + w->domain_pd = nullptr; + w->domain_regs = nullptr; - // Placement new for C++ objects - new (&w->send) std::atomic(); - new (&w->thread) std::thread(); - new (&w->task) Task(CLOCK_REALTIME); + // Placement new for C++ objects + new (&w->send) std::atomic(); + new (&w->thread) std::thread(); + new (&w->task) Task(CLOCK_REALTIME); - return 0; + return 0; } -int villas::node::ethercat_destroy(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::ethercat_destroy(NodeCompat *n) { + int ret; + auto *w = n->getData(); - if (w->domain_regs) - delete[] w->domain_regs; + if (w->domain_regs) + delete[] w->domain_regs; - if (w->in.offsets) - delete[] w->in.offsets; + if (w->in.offsets) + delete[] w->in.offsets; - if (w->out.offsets) - delete[] w->out.offsets; + if (w->out.offsets) + delete[] w->out.offsets; - ret = queue_signalled_destroy(&w->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&w->queue); + if (ret) + return ret; - ret = pool_destroy(&w->pool); - if (ret) - return ret; + ret = pool_destroy(&w->pool); + if (ret) + return ret; - w->task.~Task(); + w->task.~Task(); - // TODO: Destroy domain? + // TODO: Destroy domain? - return 0; + return 0; } -int villas::node::ethercat_poll_fds(NodeCompat *n, int *fds) -{ - auto *w = n->getData(); +int villas::node::ethercat_poll_fds(NodeCompat *n, int *fds) { + auto *w = n->getData(); - fds[0] = queue_signalled_fd(&w->queue); + fds[0] = queue_signalled_fd(&w->queue); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "ethercat"; - p.description = "Send and receive samples of an ethercat connection"; - p.vectorize = 1; // we only process a single sample per call - p.size = sizeof(struct ethercat); - p.type.start = ethercat_type_start; - p.type.stop = ethercat_type_stop; - p.parse = ethercat_parse; - p.print = ethercat_print; - p.check = ethercat_check; - p.init = ethercat_init; - p.destroy = ethercat_destroy; - p.prepare = ethercat_prepare; - p.start = ethercat_start; - p.stop = ethercat_stop; - p.read = ethercat_read; - p.write = ethercat_write; - p.poll_fds = ethercat_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "ethercat"; + p.description = "Send and receive samples of an ethercat connection"; + p.vectorize = 1; // we only process a single sample per call + p.size = sizeof(struct ethercat); + p.type.start = ethercat_type_start; + p.type.stop = ethercat_type_stop; + p.parse = ethercat_parse; + p.print = ethercat_print; + p.check = ethercat_check; + p.init = ethercat_init; + p.destroy = ethercat_destroy; + p.prepare = ethercat_prepare; + p.start = ethercat_start; + p.stop = ethercat_stop; + p.read = ethercat_read; + p.write = ethercat_write; + p.poll_fds = ethercat_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/example.cpp b/lib/nodes/example.cpp index b71cc0715..1914d3dec 100644 --- a/lib/nodes/example.cpp +++ b/lib/nodes/example.cpp @@ -8,76 +8,64 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include #include -#include #include -#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -ExampleNode::ExampleNode(const uuid_t &id, const std::string &name) : - Node(id, name), - setting1(72), - setting2("something"), - state1(0) -{ } +ExampleNode::ExampleNode(const uuid_t &id, const std::string &name) + : Node(id, name), setting1(72), setting2("something"), state1(0) {} -ExampleNode::~ExampleNode() -{ } +ExampleNode::~ExampleNode() {} -int ExampleNode::prepare() -{ - state1 = setting1; +int ExampleNode::prepare() { + state1 = setting1; - if (setting2 == "double") - state1 *= 2; + if (setting2 == "double") + state1 *= 2; - return 0; + return 0; } -int ExampleNode::parse(json_t *json) -{ - // TODO: Add implementation here. The following is just an example +int ExampleNode::parse(json_t *json) { + // TODO: Add implementation here. The following is just an example - const char *setting2_str = nullptr; + const char *setting2_str = nullptr; - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", - "setting1", &setting1, - "setting2", &setting2_str - ); - if (ret) - throw ConfigError(json, err, "node-config-node-example"); + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", "setting1", + &setting1, "setting2", &setting2_str); + if (ret) + throw ConfigError(json, err, "node-config-node-example"); - if (setting2_str) - setting2 = setting2_str; + if (setting2_str) + setting2 = setting2_str; - return 0; + return 0; } -int ExampleNode::check() -{ - if (setting1 > 100 || setting1 < 0) - return -1; +int ExampleNode::check() { + if (setting1 > 100 || setting1 < 0) + return -1; - if (setting2.empty() || setting2.size() > 10) - return -1; + if (setting2.empty() || setting2.size() > 10) + return -1; - return 0; + return 0; } -int ExampleNode::start() -{ - // TODO add implementation here +int ExampleNode::start() { + // TODO add implementation here - start_time = time_now(); + start_time = time_now(); - return 0; + return 0; } // int ExampleNode::stop() @@ -127,47 +115,49 @@ int ExampleNode::start() // // TODO add implementation here // } -const std::string & ExampleNode::getDetails() -{ - details = fmt::format("setting1={}, setting2={}", setting1, setting2); - return details; +const std::string &ExampleNode::getDetails() { + details = fmt::format("setting1={}, setting2={}", setting1, setting2); + return details; } -int ExampleNode::_read(struct Sample *smps[], unsigned cnt) -{ - int read; - struct timespec now; +int ExampleNode::_read(struct Sample *smps[], unsigned cnt) { + int read; + struct timespec now; - // TODO: Add implementation here. The following is just an example + // TODO: Add implementation here. The following is just an example - assert(cnt >= 1 && smps[0]->capacity >= 1); + assert(cnt >= 1 && smps[0]->capacity >= 1); - now = time_now(); + now = time_now(); - smps[0]->data[0].f = time_delta(&now, &start_time); + smps[0]->data[0].f = time_delta(&now, &start_time); - /* Dont forget to set other flags in struct Sample::flags + /* Dont forget to set other flags in struct Sample::flags * E.g. for sequence no, timestamps... */ - smps[0]->flags = (int) SampleFlags::HAS_DATA; - smps[0]->signals = getInputSignals(false); + smps[0]->flags = (int)SampleFlags::HAS_DATA; + smps[0]->signals = getInputSignals(false); - read = 1; // The number of samples read + read = 1; // The number of samples read - return read; + return read; } -int ExampleNode::_write(struct Sample *smps[], unsigned cnt) -{ - int written; +int ExampleNode::_write(struct Sample *smps[], unsigned cnt) { + int written; - // TODO: Add implementation here. + // TODO: Add implementation here. - written = 0; // The number of samples written + written = 0; // The number of samples written - return written; + return written; } // Register node static char n[] = "example"; static char d[] = "An example for staring new node-type implementations"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/exec.cpp b/lib/nodes/exec.cpp index 3bfa36007..0d33a76e7 100644 --- a/lib/nodes/exec.cpp +++ b/lib/nodes/exec.cpp @@ -8,205 +8,198 @@ #include #include +#include #include +#include #include #include -#include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -ExecNode::~ExecNode() -{ - if (stream_in) - fclose(stream_in); +ExecNode::~ExecNode() { + if (stream_in) + fclose(stream_in); - if (stream_out) - fclose(stream_out); + if (stream_out) + fclose(stream_out); } -int ExecNode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int ExecNode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - json_error_t err; - int f = 1, s = -1; + json_error_t err; + int f = 1, s = -1; - json_t *json_exec; - json_t *json_env = nullptr; - json_t *json_format = nullptr; + json_t *json_exec; + json_t *json_env = nullptr; + json_t *json_format = nullptr; - const char *wd = nullptr; + const char *wd = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s?: o, s?: b, s?: o, s?: b, s?: s }", - "exec", &json_exec, - "format", &json_format, - "flush", &f, - "environment", &json_env, - "shell", &s, - "working_directory", &wd - ); - if (ret) - throw ConfigError(json, err, "node-config-node-exec"); + ret = json_unpack_ex( + json, &err, 0, "{ s: o, s?: o, s?: b, s?: o, s?: b, s?: s }", "exec", + &json_exec, "format", &json_format, "flush", &f, "environment", &json_env, + "shell", &s, "working_directory", &wd); + if (ret) + throw ConfigError(json, err, "node-config-node-exec"); - flush = f != 0; - shell = s < 0 ? json_is_string(json_exec) : s != 0; + flush = f != 0; + shell = s < 0 ? json_is_string(json_exec) : s != 0; - arguments.clear(); - environment.clear(); + arguments.clear(); + environment.clear(); - if (json_is_string(json_exec)) { - if (!shell) - throw ConfigError(json_exec, "node-config-node-exec-shell", "The exec setting must be an array if shell mode is disabled."); + if (json_is_string(json_exec)) { + if (!shell) + throw ConfigError( + json_exec, "node-config-node-exec-shell", + "The exec setting must be an array if shell mode is disabled."); - command = json_string_value(json_exec); - } - else if (json_is_array(json_exec)) { - if (shell) - throw ConfigError(json_exec, "node-config-node-exec-shell", "The exec setting must be a string if shell mode is enabled."); + command = json_string_value(json_exec); + } else if (json_is_array(json_exec)) { + if (shell) + throw ConfigError( + json_exec, "node-config-node-exec-shell", + "The exec setting must be a string if shell mode is enabled."); - if (json_array_size(json_exec) < 1) - throw ConfigError(json_exec, "node-config-node-exec-exec", "At least one argument must be given"); + if (json_array_size(json_exec) < 1) + throw ConfigError(json_exec, "node-config-node-exec-exec", + "At least one argument must be given"); - size_t i; - json_t *json_arg; - json_array_foreach(json_exec, i, json_arg) { - if (!json_is_string(json_arg)) - throw ConfigError(json_arg, "node-config-node-exec-exec", "All arguments must be of string type"); + size_t i; + json_t *json_arg; + json_array_foreach(json_exec, i, json_arg) { + if (!json_is_string(json_arg)) + throw ConfigError(json_arg, "node-config-node-exec-exec", + "All arguments must be of string type"); - if (i == 0) - command = json_string_value(json_arg); + if (i == 0) + command = json_string_value(json_arg); - arguments.push_back(json_string_value(json_arg)); - } - } + arguments.push_back(json_string_value(json_arg)); + } + } - if (json_env) { - // obj is a JSON object - const char *key; - json_t *json_value; + if (json_env) { + // obj is a JSON object + const char *key; + json_t *json_value; - json_object_foreach(json_env, key, json_value) { - if (!json_is_string(json_value)) - throw ConfigError(json_value, "node-config-node-exec-environment", "Environment variables must be of string type"); + json_object_foreach(json_env, key, json_value) { + if (!json_is_string(json_value)) + throw ConfigError(json_value, "node-config-node-exec-environment", + "Environment variables must be of string type"); - environment[key] = json_string_value(json_value); - } - } + environment[key] = json_string_value(json_value); + } + } - // Format - auto *fmt = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.human"); + // Format + auto *fmt = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.human"); - formatter = Format::Ptr(fmt); - if (!formatter) - throw ConfigError(json_format, "node-config-node-exec-format", "Invalid format configuration"); + formatter = Format::Ptr(fmt); + if (!formatter) + throw ConfigError(json_format, "node-config-node-exec-format", + "Invalid format configuration"); - state = State::PARSED; + state = State::PARSED; - return 0; + return 0; } -int ExecNode::prepare() -{ - assert(state == State::CHECKED); +int ExecNode::prepare() { + assert(state == State::CHECKED); - // Initialize IO - formatter->start(getInputSignals(false)); + // Initialize IO + formatter->start(getInputSignals(false)); - return Node::prepare(); + return Node::prepare(); } -int ExecNode::start() -{ - // Start subprocess - proc = std::make_unique(command, arguments, environment, working_dir, shell); - logger->debug("Started sub-process with pid={}", proc->getPid()); +int ExecNode::start() { + // Start subprocess + proc = std::make_unique(command, arguments, environment, working_dir, + shell); + logger->debug("Started sub-process with pid={}", proc->getPid()); - stream_in = fdopen(proc->getFdIn(), "r"); - if (!stream_in) - return -1; + stream_in = fdopen(proc->getFdIn(), "r"); + if (!stream_in) + return -1; - stream_out = fdopen(proc->getFdOut(), "w"); - if (!stream_out) - return -1; + stream_out = fdopen(proc->getFdOut(), "w"); + if (!stream_out) + return -1; - int ret = Node::start(); - if (!ret) - state = State::STARTED; + int ret = Node::start(); + if (!ret) + state = State::STARTED; - return 0; + return 0; } -int ExecNode::stop() -{ - int ret = Node::stop(); - if (ret) - return ret; +int ExecNode::stop() { + int ret = Node::stop(); + if (ret) + return ret; - // Stop subprocess - logger->debug("Killing sub-process with pid={}", proc->getPid()); - proc->kill(SIGINT); + // Stop subprocess + logger->debug("Killing sub-process with pid={}", proc->getPid()); + proc->kill(SIGINT); - logger->debug("Waiting for sub-process with pid={} to terminate", proc->getPid()); - proc->close(); + logger->debug("Waiting for sub-process with pid={} to terminate", + proc->getPid()); + proc->close(); - // TODO: Check exit code of subprocess? - return 0; + // TODO: Check exit code of subprocess? + return 0; } -int ExecNode::_read(struct Sample * smps[], unsigned cnt) -{ - return formatter->scan(stream_in, smps, cnt); +int ExecNode::_read(struct Sample *smps[], unsigned cnt) { + return formatter->scan(stream_in, smps, cnt); } -int ExecNode::_write(struct Sample * smps[], unsigned cnt) -{ - int ret; +int ExecNode::_write(struct Sample *smps[], unsigned cnt) { + int ret; - ret = formatter->print(stream_out, smps, cnt); - if (ret < 0) - return ret; + ret = formatter->print(stream_out, smps, cnt); + if (ret < 0) + return ret; - if (flush) - fflush(stream_out); + if (flush) + fflush(stream_out); - return cnt; + return cnt; } -const std::string & ExecNode::getDetails() -{ - if (details.empty()) { - std::string wd = working_dir; - if (wd.empty()) { - char buf[128]; - wd = getcwd(buf, sizeof(buf)); - } +const std::string &ExecNode::getDetails() { + if (details.empty()) { + std::string wd = working_dir; + if (wd.empty()) { + char buf[128]; + wd = getcwd(buf, sizeof(buf)); + } - details = fmt::format("exec={}, shell={}, flush={}, #environment={}, #arguments={}, working_dir={}", - command, - shell ? "yes" : "no", - flush ? "yes" : "no", - environment.size(), - arguments.size(), - wd - ); - } + details = fmt::format("exec={}, shell={}, flush={}, #environment={}, " + "#arguments={}, working_dir={}", + command, shell ? "yes" : "no", flush ? "yes" : "no", + environment.size(), arguments.size(), wd); + } - return details; + return details; } -std::vector ExecNode::getPollFDs() -{ - return { proc->getFdIn() }; -} +std::vector ExecNode::getPollFDs() { return {proc->getFdIn()}; } // Register node static char n[] = "exec"; static char d[] = "run subprocesses with stdin/stdout communication"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/file.cpp b/lib/nodes/file.cpp index 5ae0ea762..3fd6692e3 100644 --- a/lib/nodes/file.cpp +++ b/lib/nodes/file.cpp @@ -5,489 +5,463 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include #include +#include #include #include -#include +#include +#include +#include #include #include -#include -#include #include -#include -#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -char * file_format_name(const char *format, struct timespec *ts) -{ - struct tm tm; - char *buf = new char[FILE_MAX_PATHLEN]; - if (!buf) - throw MemoryAllocationError(); +static char *file_format_name(const char *format, struct timespec *ts) { + struct tm tm; + char *buf = new char[FILE_MAX_PATHLEN]; + if (!buf) + throw MemoryAllocationError(); - // Convert time - gmtime_r(&ts->tv_sec, &tm); + // Convert time + gmtime_r(&ts->tv_sec, &tm); - strftime(buf, FILE_MAX_PATHLEN, format, &tm); + strftime(buf, FILE_MAX_PATHLEN, format, &tm); - return buf; + return buf; } -static -struct timespec file_calc_offset(const struct timespec *first, const struct timespec *epoch, enum file::EpochMode mode) -{ - // Get current time - struct timespec now = time_now(); - struct timespec offset; +static struct timespec file_calc_offset(const struct timespec *first, + const struct timespec *epoch, + enum file::EpochMode mode) { + // Get current time + struct timespec now = time_now(); + struct timespec offset; - // Set offset depending on epoch - switch (mode) { - case file::EpochMode::DIRECT: // read first value at now + epoch - offset = time_diff(first, &now); - return time_add(&offset, epoch); + // Set offset depending on epoch + switch (mode) { + case file::EpochMode::DIRECT: // read first value at now + epoch + offset = time_diff(first, &now); + return time_add(&offset, epoch); - case file::EpochMode::WAIT: // read first value at now + first + epoch - offset = now; - return time_add(&now, epoch); + case file::EpochMode::WAIT: // read first value at now + first + epoch + offset = now; + return time_add(&now, epoch); - case file::EpochMode::RELATIVE: // read first value at first + epoch - return *epoch; + case file::EpochMode::RELATIVE: // read first value at first + epoch + return *epoch; - case file::EpochMode::ABSOLUTE: // read first value at f->epoch - return time_diff(first, epoch); + case file::EpochMode::ABSOLUTE: // read first value at f->epoch + return time_diff(first, epoch); - default: - return (struct timespec) { 0 }; - } + default: + return (struct timespec){0}; + } } -int villas::node::file_parse(NodeCompat *n, json_t *json) -{ - auto *f = n->getData(); +int villas::node::file_parse(NodeCompat *n, json_t *json) { + auto *f = n->getData(); - int ret; - json_error_t err; - json_t *json_format = nullptr; + int ret; + json_error_t err; + json_t *json_format = nullptr; - const char *uri_tmpl = nullptr; - const char *eof = nullptr; - const char *epoch = nullptr; - double epoch_flt = 0; + const char *uri_tmpl = nullptr; + const char *eof = nullptr; + const char *epoch = nullptr; + double epoch_flt = 0; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: o, s?: { s?: s, s?: F, s?: s, s?: F, s?: i, s?: i }, s?: { s?: b, s?: i } }", - "uri", &uri_tmpl, - "format", &json_format, - "in", - "eof", &eof, - "rate", &f->rate, - "epoch_mode", &epoch, - "epoch", &epoch_flt, - "buffer_size", &f->buffer_size_in, - "skip", &f->skip_lines, - "out", - "flush", &f->flush, - "buffer_size", &f->buffer_size_out - ); - if (ret) - throw ConfigError(json, err, "node-config-node-file"); + ret = json_unpack_ex(json, &err, 0, + "{ s: s, s?: o, s?: { s?: s, s?: F, s?: s, s?: F, s?: " + "i, s?: i }, s?: { s?: b, s?: i } }", + "uri", &uri_tmpl, "format", &json_format, "in", "eof", + &eof, "rate", &f->rate, "epoch_mode", &epoch, "epoch", + &epoch_flt, "buffer_size", &f->buffer_size_in, "skip", + &f->skip_lines, "out", "flush", &f->flush, "buffer_size", + &f->buffer_size_out); + if (ret) + throw ConfigError(json, err, "node-config-node-file"); - f->epoch = time_from_double(epoch_flt); - f->uri_tmpl = uri_tmpl ? strdup(uri_tmpl) : nullptr; + f->epoch = time_from_double(epoch_flt); + f->uri_tmpl = uri_tmpl ? strdup(uri_tmpl) : nullptr; - // Format - if (f->formatter) - delete f->formatter; - f->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.human"); - if (!f->formatter) - throw ConfigError(json_format, "node-config-node-file-format", "Invalid format configuration"); + // Format + if (f->formatter) + delete f->formatter; + f->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.human"); + if (!f->formatter) + throw ConfigError(json_format, "node-config-node-file-format", + "Invalid format configuration"); - if (eof) { - if (!strcmp(eof, "exit") || !strcmp(eof, "stop")) - f->eof_mode = file::EOFBehaviour::STOP; - else if (!strcmp(eof, "rewind")) - f->eof_mode = file::EOFBehaviour::REWIND; - else if (!strcmp(eof, "wait")) - f->eof_mode = file::EOFBehaviour::SUSPEND; - else - throw RuntimeError("Invalid mode '{}' for 'eof' setting", eof); - } + if (eof) { + if (!strcmp(eof, "exit") || !strcmp(eof, "stop")) + f->eof_mode = file::EOFBehaviour::STOP; + else if (!strcmp(eof, "rewind")) + f->eof_mode = file::EOFBehaviour::REWIND; + else if (!strcmp(eof, "wait")) + f->eof_mode = file::EOFBehaviour::SUSPEND; + else + throw RuntimeError("Invalid mode '{}' for 'eof' setting", eof); + } - if (epoch) { - if (!strcmp(epoch, "direct")) - f->epoch_mode = file::EpochMode::DIRECT; - else if (!strcmp(epoch, "wait")) - f->epoch_mode = file::EpochMode::WAIT; - else if (!strcmp(epoch, "relative")) - f->epoch_mode = file::EpochMode::RELATIVE; - else if (!strcmp(epoch, "absolute")) - f->epoch_mode = file::EpochMode::ABSOLUTE; - else if (!strcmp(epoch, "original")) - f->epoch_mode = file::EpochMode::ORIGINAL; - else - throw RuntimeError("Invalid value '{}' for setting 'epoch'", epoch); - } + if (epoch) { + if (!strcmp(epoch, "direct")) + f->epoch_mode = file::EpochMode::DIRECT; + else if (!strcmp(epoch, "wait")) + f->epoch_mode = file::EpochMode::WAIT; + else if (!strcmp(epoch, "relative")) + f->epoch_mode = file::EpochMode::RELATIVE; + else if (!strcmp(epoch, "absolute")) + f->epoch_mode = file::EpochMode::ABSOLUTE; + else if (!strcmp(epoch, "original")) + f->epoch_mode = file::EpochMode::ORIGINAL; + else + throw RuntimeError("Invalid value '{}' for setting 'epoch'", epoch); + } - return 0; + return 0; } -char * villas::node::file_print(NodeCompat *n) -{ - auto *f = n->getData(); - char *buf = nullptr; +char *villas::node::file_print(NodeCompat *n) { + auto *f = n->getData(); + char *buf = nullptr; - const char *epoch_str = nullptr; - const char *eof_str = nullptr; + const char *epoch_str = nullptr; + const char *eof_str = nullptr; - switch (f->epoch_mode) { - case file::EpochMode::DIRECT: - epoch_str = "direct"; - break; + switch (f->epoch_mode) { + case file::EpochMode::DIRECT: + epoch_str = "direct"; + break; - case file::EpochMode::WAIT: - epoch_str = "wait"; - break; + case file::EpochMode::WAIT: + epoch_str = "wait"; + break; - case file::EpochMode::RELATIVE: - epoch_str = "relative"; - break; + case file::EpochMode::RELATIVE: + epoch_str = "relative"; + break; - case file::EpochMode::ABSOLUTE: - epoch_str = "absolute"; - break; + case file::EpochMode::ABSOLUTE: + epoch_str = "absolute"; + break; - case file::EpochMode::ORIGINAL: - epoch_str = "original"; - break; + case file::EpochMode::ORIGINAL: + epoch_str = "original"; + break; - default: - epoch_str = ""; - break; - } + default: + epoch_str = ""; + break; + } - switch (f->eof_mode) { - case file::EOFBehaviour::STOP: - eof_str = "stop"; - break; + switch (f->eof_mode) { + case file::EOFBehaviour::STOP: + eof_str = "stop"; + break; - case file::EOFBehaviour::SUSPEND: - eof_str = "wait"; - break; + case file::EOFBehaviour::SUSPEND: + eof_str = "wait"; + break; - case file::EOFBehaviour::REWIND: - eof_str = "rewind"; - break; + case file::EOFBehaviour::REWIND: + eof_str = "rewind"; + break; - default: - eof_str = ""; - break; - } + default: + eof_str = ""; + break; + } - strcatf(&buf, "uri=%s, out.flush=%s, in.skip=%d, in.eof=%s, in.epoch=%s, in.epoch=%.2f", - f->uri ? f->uri : f->uri_tmpl, - f->flush ? "yes" : "no", - f->skip_lines, - eof_str, - epoch_str, - time_to_double(&f->epoch) - ); + strcatf( + &buf, + "uri=%s, out.flush=%s, in.skip=%d, in.eof=%s, in.epoch=%s, in.epoch=%.2f", + f->uri ? f->uri : f->uri_tmpl, f->flush ? "yes" : "no", f->skip_lines, + eof_str, epoch_str, time_to_double(&f->epoch)); - if (f->rate) - strcatf(&buf, ", in.rate=%.1f", f->rate); + if (f->rate) + strcatf(&buf, ", in.rate=%.1f", f->rate); - if (f->first.tv_sec || f->first.tv_nsec) - strcatf(&buf, ", first=%.2f", time_to_double(&f->first)); + if (f->first.tv_sec || f->first.tv_nsec) + strcatf(&buf, ", first=%.2f", time_to_double(&f->first)); - if (f->offset.tv_sec || f->offset.tv_nsec) - strcatf(&buf, ", offset=%.2f", time_to_double(&f->offset)); + if (f->offset.tv_sec || f->offset.tv_nsec) + strcatf(&buf, ", offset=%.2f", time_to_double(&f->offset)); - if ((f->first.tv_sec || f->first.tv_nsec) && - (f->offset.tv_sec || f->offset.tv_nsec)) { - struct timespec eta, now = time_now(); + if ((f->first.tv_sec || f->first.tv_nsec) && + (f->offset.tv_sec || f->offset.tv_nsec)) { + struct timespec eta, now = time_now(); - eta = time_add(&f->first, &f->offset); - eta = time_diff(&now, &eta); + eta = time_add(&f->first, &f->offset); + eta = time_diff(&now, &eta); - if (eta.tv_sec || eta.tv_nsec) - strcatf(&buf, ", eta=%.2f sec", time_to_double(&eta)); - } + if (eta.tv_sec || eta.tv_nsec) + strcatf(&buf, ", eta=%.2f sec", time_to_double(&eta)); + } - return buf; + return buf; } -int villas::node::file_start(NodeCompat *n) -{ - auto *f = n->getData(); +int villas::node::file_start(NodeCompat *n) { + auto *f = n->getData(); - struct timespec now = time_now(); - int ret; + struct timespec now = time_now(); + int ret; - // Prepare file name - if (f->uri) - delete[] f->uri; + // Prepare file name + if (f->uri) + delete[] f->uri; - f->uri = file_format_name(f->uri_tmpl, &now); + f->uri = file_format_name(f->uri_tmpl, &now); - // Check if directory exists - struct stat sb; - char *cpy = strdup(f->uri); - char *dir = dirname(cpy); + // Check if directory exists + struct stat sb; + char *cpy = strdup(f->uri); + char *dir = dirname(cpy); - ret = stat(dir, &sb); - if (ret) { - if (errno == ENOENT || errno == ENOTDIR) { - ret = mkdir(dir, 0644); - if (ret) - throw SystemError("Failed to create directory"); - } - else if (errno != EISDIR) - throw SystemError("Failed to stat"); - } - else if (!S_ISDIR(sb.st_mode)) { - ret = mkdir(dir, 0644); - if (ret) - throw SystemError("Failed to create directory"); - } + ret = stat(dir, &sb); + if (ret) { + if (errno == ENOENT || errno == ENOTDIR) { + ret = mkdir(dir, 0644); + if (ret) + throw SystemError("Failed to create directory"); + } else if (errno != EISDIR) + throw SystemError("Failed to stat"); + } else if (!S_ISDIR(sb.st_mode)) { + ret = mkdir(dir, 0644); + if (ret) + throw SystemError("Failed to create directory"); + } - free(cpy); + free(cpy); - f->formatter->start(n->getInputSignals(false)); + f->formatter->start(n->getInputSignals(false)); - // Open file - f->stream_out = fopen(f->uri, "a+"); - if (!f->stream_out) - return -1; + // Open file + f->stream_out = fopen(f->uri, "a+"); + if (!f->stream_out) + return -1; - f->stream_in = fopen(f->uri, "r"); - if (!f->stream_in) - return -1; + f->stream_in = fopen(f->uri, "r"); + if (!f->stream_in) + return -1; - if (f->buffer_size_in) { - ret = setvbuf(f->stream_in, nullptr, _IOFBF, f->buffer_size_in); - if (ret) - return ret; - } + if (f->buffer_size_in) { + ret = setvbuf(f->stream_in, nullptr, _IOFBF, f->buffer_size_in); + if (ret) + return ret; + } - if (f->buffer_size_out) { - ret = setvbuf(f->stream_out, nullptr, _IOFBF, f->buffer_size_out); - if (ret) - return ret; - } + if (f->buffer_size_out) { + ret = setvbuf(f->stream_out, nullptr, _IOFBF, f->buffer_size_out); + if (ret) + return ret; + } - // Create timer - f->task.setRate(f->rate); + // Create timer + f->task.setRate(f->rate); - // Get timestamp of first line - if (f->epoch_mode != file::EpochMode::ORIGINAL) { - rewind(f->stream_in); + // Get timestamp of first line + if (f->epoch_mode != file::EpochMode::ORIGINAL) { + rewind(f->stream_in); - if (feof(f->stream_in)) { - n->logger->warn("Empty file"); - } - else { - struct Sample smp; + if (feof(f->stream_in)) { + n->logger->warn("Empty file"); + } else { + struct Sample smp; - smp.capacity = 0; + smp.capacity = 0; - ret = f->formatter->scan(f->stream_in, &smp); - if (ret == 1) { - f->first = smp.ts.origin; - f->offset = file_calc_offset(&f->first, &f->epoch, f->epoch_mode); - } - else - n->logger->warn("Failed to read first timestamp"); - } - } + ret = f->formatter->scan(f->stream_in, &smp); + if (ret == 1) { + f->first = smp.ts.origin; + f->offset = file_calc_offset(&f->first, &f->epoch, f->epoch_mode); + } else + n->logger->warn("Failed to read first timestamp"); + } + } - rewind(f->stream_in); + rewind(f->stream_in); - // Fast-forward - struct Sample *smp = sample_alloc_mem(n->getInputSignals(false)->size()); - for (unsigned i = 0; i < f->skip_lines; i++) - f->formatter->scan(f->stream_in, smp); + // Fast-forward + struct Sample *smp = sample_alloc_mem(n->getInputSignals(false)->size()); + for (unsigned i = 0; i < f->skip_lines; i++) + f->formatter->scan(f->stream_in, smp); - sample_free(smp); + sample_free(smp); - return 0; + return 0; } -int villas::node::file_stop(NodeCompat *n) -{ - auto *f = n->getData(); +int villas::node::file_stop(NodeCompat *n) { + auto *f = n->getData(); - f->task.stop(); + f->task.stop(); - fclose(f->stream_in); - fclose(f->stream_out); + fclose(f->stream_in); + fclose(f->stream_out); - return 0; + return 0; } -int villas::node::file_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *f = n->getData(); - int ret; - uint64_t steps; +int villas::node::file_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *f = n->getData(); + int ret; + uint64_t steps; - assert(cnt == 1); + assert(cnt == 1); -retry: ret = f->formatter->scan(f->stream_in, smps, cnt); - if (ret <= 0) { - if (feof(f->stream_in)) { - switch (f->eof_mode) { - case file::EOFBehaviour::REWIND: - n->logger->info("Rewind input file"); +retry: + ret = f->formatter->scan(f->stream_in, smps, cnt); + if (ret <= 0) { + if (feof(f->stream_in)) { + switch (f->eof_mode) { + case file::EOFBehaviour::REWIND: + n->logger->info("Rewind input file"); - f->offset = file_calc_offset(&f->first, &f->epoch, f->epoch_mode); - rewind(f->stream_in); - goto retry; + f->offset = file_calc_offset(&f->first, &f->epoch, f->epoch_mode); + rewind(f->stream_in); + goto retry; - case file::EOFBehaviour::SUSPEND: - // We wait 10ms before fetching again. - usleep(100000); + case file::EOFBehaviour::SUSPEND: + // We wait 10ms before fetching again. + usleep(100000); - // Try to download more data if this is a remote file. - clearerr(f->stream_in); - goto retry; + // Try to download more data if this is a remote file. + clearerr(f->stream_in); + goto retry; - case file::EOFBehaviour::STOP: - n->logger->info("Reached end-of-file."); + case file::EOFBehaviour::STOP: + n->logger->info("Reached end-of-file."); - n->setState(State::STOPPING); + n->setState(State::STOPPING); - return -1; + return -1; - default: { } - } - } - else - n->logger->warn("Failed to read messages: reason={}", ret); + default: { + } + } + } else + n->logger->warn("Failed to read messages: reason={}", ret); - return 0; - } + return 0; + } - // We dont wait in FILE_EPOCH_ORIGINAL mode - if (f->epoch_mode == file::EpochMode::ORIGINAL) - return cnt; + // We dont wait in FILE_EPOCH_ORIGINAL mode + if (f->epoch_mode == file::EpochMode::ORIGINAL) + return cnt; - if (f->rate) { - steps = f->task.wait(); + if (f->rate) { + steps = f->task.wait(); - smps[0]->ts.origin = time_now(); - } - else { - smps[0]->ts.origin = time_add(&smps[0]->ts.origin, &f->offset); + smps[0]->ts.origin = time_now(); + } else { + smps[0]->ts.origin = time_add(&smps[0]->ts.origin, &f->offset); - f->task.setNext(&smps[0]->ts.origin); - steps = f->task.wait(); - } + f->task.setNext(&smps[0]->ts.origin); + steps = f->task.wait(); + } - // Check for overruns - if (steps == 0) - throw SystemError("Failed to wait for timer"); - else if (steps != 1) - n->logger->warn("Missed steps: {}", steps - 1); + // Check for overruns + if (steps == 0) + throw SystemError("Failed to wait for timer"); + else if (steps != 1) + n->logger->warn("Missed steps: {}", steps - 1); - return cnt; + return cnt; } -int villas::node::file_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *f = n->getData(); +int villas::node::file_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *f = n->getData(); - assert(cnt == 1); + assert(cnt == 1); - ret = f->formatter->print(f->stream_out, smps, cnt); - if (ret < 0) - return ret; + ret = f->formatter->print(f->stream_out, smps, cnt); + if (ret < 0) + return ret; - if (f->flush) - fflush(f->stream_out); + if (f->flush) + fflush(f->stream_out); - return cnt; + return cnt; } -int villas::node::file_poll_fds(NodeCompat *n, int fds[]) -{ - auto *f = n->getData(); +int villas::node::file_poll_fds(NodeCompat *n, int fds[]) { + auto *f = n->getData(); - if (f->rate) { - fds[0] = f->task.getFD(); + if (f->rate) { + fds[0] = f->task.getFD(); - return 1; - } - else if (f->epoch_mode == file::EpochMode::ORIGINAL) { - fds[0] = fileno(f->stream_in); + return 1; + } else if (f->epoch_mode == file::EpochMode::ORIGINAL) { + fds[0] = fileno(f->stream_in); - return 1; - } + return 1; + } - return -1; // TODO: not supported yet + return -1; // TODO: not supported yet } -int villas::node::file_init(NodeCompat *n) -{ - auto *f = n->getData(); +int villas::node::file_init(NodeCompat *n) { + auto *f = n->getData(); - new (&f->task) Task(CLOCK_REALTIME); + new (&f->task) Task(CLOCK_REALTIME); - // Default values - f->rate = 0; - f->eof_mode = file::EOFBehaviour::STOP; - f->epoch_mode = file::EpochMode::DIRECT; - f->flush = 0; - f->buffer_size_in = 0; - f->buffer_size_out = 0; - f->skip_lines = 0; + // Default values + f->rate = 0; + f->eof_mode = file::EOFBehaviour::STOP; + f->epoch_mode = file::EpochMode::DIRECT; + f->flush = 0; + f->buffer_size_in = 0; + f->buffer_size_out = 0; + f->skip_lines = 0; - f->formatter = nullptr; + f->formatter = nullptr; - return 0; + return 0; } -int villas::node::file_destroy(NodeCompat *n) -{ - auto *f = n->getData(); +int villas::node::file_destroy(NodeCompat *n) { + auto *f = n->getData(); - f->task.~Task(); + f->task.~Task(); - if (f->uri) - delete[] f->uri; + if (f->uri) + delete[] f->uri; - if (f->formatter) - delete f->formatter; + if (f->formatter) + delete f->formatter; - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "file"; - p.description = "support for file log / replay node type"; - p.vectorize = 1; - p.size = sizeof(struct file); - p.init = file_init; - p.destroy = file_destroy; - p.parse = file_parse; - p.print = file_print; - p.start = file_start; - p.stop = file_stop; - p.read = file_read; - p.write = file_write; - p.poll_fds = file_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "file"; + p.description = "support for file log / replay node type"; + p.vectorize = 1; + p.size = sizeof(struct file); + p.init = file_init; + p.destroy = file_destroy; + p.parse = file_parse; + p.print = file_print; + p.start = file_start; + p.stop = file_stop; + p.read = file_read; + p.write = file_write; + p.poll_fds = file_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/fpga.cpp b/lib/nodes/fpga.cpp index 461e97e09..7f12d1382 100644 --- a/lib/nodes/fpga.cpp +++ b/lib/nodes/fpga.cpp @@ -5,27 +5,27 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include -#include -#include #include +#include +#include #include +#include +#include #include #include -#include -#include -#include #include #include +#include #include #include -#include #include +#include using namespace villas; using namespace villas::node; @@ -33,217 +33,200 @@ using namespace villas::fpga; using namespace villas::utils; // Global state -static -std::list> cards; -static -std::map dmaMap; +static std::list> cards; +static std::map dmaMap; -static -std::shared_ptr pciDevices; -static -std::shared_ptr vfioContainer; +static std::shared_ptr pciDevices; +static std::shared_ptr vfioContainer; using namespace villas; using namespace villas::node; -FpgaNode::FpgaNode(const uuid_t &id, const std::string &name) : - Node(id, name), - irqFd(-1), - coalesce(0), - polling(true) -{ } +FpgaNode::FpgaNode(const uuid_t &id, const std::string &name) + : Node(id, name), irqFd(-1), coalesce(0), polling(true) {} -FpgaNode::~FpgaNode() -{ } +FpgaNode::~FpgaNode() {} -int FpgaNode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int FpgaNode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - json_error_t err; + json_error_t err; - const char *card = nullptr; - const char *intf = nullptr; - const char *dma = nullptr; - int poll = polling; + const char *card = nullptr; + const char *intf = nullptr; + const char *dma = nullptr; + int poll = polling; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: i, s?: b }", - "card", &card, - "interface", &intf, - "dma", &dma, - "coalesce", &coalesce, - "polling", &polling - ); - if (ret) - throw ConfigError(json, err, "node-config-fpga", "Failed to parse configuration of node {}", this->getName()); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: i, s?: b }", + "card", &card, "interface", &intf, "dma", &dma, + "coalesce", &coalesce, "polling", &polling); + if (ret) + throw ConfigError(json, err, "node-config-fpga", + "Failed to parse configuration of node {}", + this->getName()); - if (card) - cardName = card; + if (card) + cardName = card; - if (intf) - intfName = intf; + if (intf) + intfName = intf; - if (dma) - dmaName = dma; + if (dma) + dmaName = dma; - polling = poll; // cast int to bool + polling = poll; // cast int to bool - return 0; + return 0; } -const std::string & FpgaNode::getDetails() -{ - if (details.empty()) { - auto &name = card ? card->name : cardName; +const std::string &FpgaNode::getDetails() { + if (details.empty()) { + auto &name = card ? card->name : cardName; - details = fmt::format("fpga={}, dma={}, if={}, polling={}, coalesce={}", - name, - dma->getInstanceName(), - polling ? "yes" : "no", - coalesce - ); - } + details = + fmt::format("fpga={}, dma={}, if={}, polling={}, coalesce={}", name, + dma->getInstanceName(), polling ? "yes" : "no", coalesce); + } - return details; + return details; } -int FpgaNode::check() -{ - return 0; +int FpgaNode::check() { return 0; } + +int FpgaNode::prepare() { + auto it = cardName.empty() + ? cards.begin() + : std::find_if(cards.begin(), cards.end(), + [this](std::shared_ptr c) { + return c->name == cardName; + }); + + if (it == cards.end()) + throw ConfigError(json_object_get(config, "fpga"), "node-config-fpga-card", + "Invalid FPGA card name: {}", cardName); + + card = *it; + + auto intfCore = intfName.empty() + ? card->lookupIp(fpga::Vlnv(FPGA_AURORA_VLNV)) + : card->lookupIp(intfName); + if (!intfCore) + throw ConfigError(config, "node-config-fpga-interface", + "There is no interface IP with the name: {}", intfName); + + intf = std::dynamic_pointer_cast(intfCore); + if (!intf) + throw RuntimeError("The IP {} is not a interface", *intfCore); + + auto dmaCore = dmaName.empty() ? card->lookupIp(fpga::Vlnv(FPGA_DMA_VLNV)) + : card->lookupIp(dmaName); + if (!dmaCore) + throw ConfigError(config, "node-config-fpga-dma", + "There is no DMA IP with the name: {}", dmaName); + + dma = std::dynamic_pointer_cast(dmaCore); + if (!dma) + throw RuntimeError("The IP {} is not a DMA controller", *dmaCore); + + int ret = intf->connect(*(dma), true); + if (ret) + throw RuntimeError("Failed to connect: {} -> {}", *(intf), *(dma)); + + auto &alloc = HostDmaRam::getAllocator(); + + const std::shared_ptr blockRx = + alloc.allocateBlock(0x100 * sizeof(float)); + const std::shared_ptr blockTx = + alloc.allocateBlock(0x100 * sizeof(float)); + villas::MemoryAccessor memRx = *blockRx; + villas::MemoryAccessor memTx = *blockTx; + + dma->makeAccesibleFromVA(blockRx); + dma->makeAccesibleFromVA(blockTx); + + // Show some debugging infos + auto &mm = MemoryManager::get(); + + dma->dump(); + intf->dump(); + mm.getGraph().dump(); + + return Node::prepare(); } -int FpgaNode::prepare() -{ - auto it = cardName.empty() - ? cards.begin() - : std::find_if(cards.begin(), cards.end(), [this](std::shared_ptr c) { - return c->name == cardName; - }); +int FpgaNode::_read(Sample *smps[], unsigned cnt) { + unsigned read; + Sample *smp = smps[0]; - if (it == cards.end()) - throw ConfigError(json_object_get(config, "fpga"), "node-config-fpga-card", "Invalid FPGA card name: {}", cardName); + assert(cnt == 1); - card = *it; + dma->read(*blockRx, blockRx->getSize()); // TODO: calc size + const size_t bytesRead = dma->readComplete().bytes; + read = bytesRead / sizeof(int32_t); - auto intfCore = intfName.empty() - ? card->lookupIp(fpga::Vlnv(FPGA_AURORA_VLNV)) - : card->lookupIp(intfName); - if (!intfCore) - throw ConfigError(config, "node-config-fpga-interface", "There is no interface IP with the name: {}", intfName); + auto mem = MemoryAccessor(*blockRx); - intf = std::dynamic_pointer_cast(intfCore); - if (!intf) - throw RuntimeError("The IP {} is not a interface", *intfCore); + for (unsigned i = 0; i < MIN(read, smp->capacity); i++) + smp->data[i].i = mem[i]; - auto dmaCore = dmaName.empty() - ? card->lookupIp(fpga::Vlnv(FPGA_DMA_VLNV)) - : card->lookupIp(dmaName); - if (!dmaCore) - throw ConfigError(config, "node-config-fpga-dma", "There is no DMA IP with the name: {}", dmaName); + smp->signals = in.signals; - dma = std::dynamic_pointer_cast(dmaCore); - if (!dma) - throw RuntimeError("The IP {} is not a DMA controller", *dmaCore); - - int ret = intf->connect(*(dma), true); - if (ret) - throw RuntimeError("Failed to connect: {} -> {}", *(intf), *(dma)); - - auto &alloc = HostDmaRam::getAllocator(); - - const std::shared_ptr blockRx = alloc.allocateBlock(0x100 * sizeof(float)); - const std::shared_ptr blockTx = alloc.allocateBlock(0x100 * sizeof(float)); - villas::MemoryAccessor memRx = *blockRx; - villas::MemoryAccessor memTx = *blockTx; - - dma->makeAccesibleFromVA(blockRx); - dma->makeAccesibleFromVA(blockTx); - - // Show some debugging infos - auto &mm = MemoryManager::get(); - - dma->dump(); - intf->dump(); - mm.getGraph().dump(); - - return Node::prepare(); + return read; } -int FpgaNode::_read(Sample *smps[], unsigned cnt) -{ - unsigned read; - Sample *smp = smps[0]; +int FpgaNode::_write(Sample *smps[], unsigned cnt) { + int written; + Sample *smp = smps[0]; - assert(cnt == 1); + assert(cnt == 1); - dma->read(*blockRx, blockRx->getSize()); // TODO: calc size - const size_t bytesRead = dma->readComplete().bytes; - read = bytesRead / sizeof(int32_t); + auto mem = MemoryAccessor(*blockTx); - auto mem = MemoryAccessor(*blockRx); + for (unsigned i = 0; i < smps[0]->length; i++) + mem[i] = smps[0]->data[i].i; - for (unsigned i = 0; i < MIN(read, smp->capacity); i++) - smp->data[i].i = mem[i]; + bool state = dma->write(*blockTx, smp->length * sizeof(int32_t)); + if (!state) + return -1; - smp->signals = in.signals; + written = 0; // The number of samples written - return read; + return written; } -int FpgaNode::_write(Sample *smps[], unsigned cnt) -{ - int written; - Sample *smp = smps[0]; +std::vector FpgaNode::getPollFDs() { + std::vector fds; - assert(cnt == 1); + if (!polling) + fds.push_back(irqFd); - auto mem = MemoryAccessor(*blockTx); - - for (unsigned i = 0; i < smps[0]->length; i++) - mem[i] = smps[0]->data[i].i; - - bool state = dma->write(*blockTx, smp->length * sizeof(int32_t)); - if (!state) - return -1; - - written = 0; // The number of samples written - - return written; + return fds; } -std::vector FpgaNode::getPollFDs() -{ - std::vector fds; +int FpgaNodeFactory::start(SuperNode *sn) { + vfioContainer = std::make_shared(); + pciDevices = std::make_shared(); - if (!polling) - fds.push_back(irqFd); + // Get the FPGA card plugin + auto pcieCardPlugin = plugin::registry->lookup("pcie"); + if (!pcieCardPlugin) + throw RuntimeError("No FPGA PCIe plugin found"); - return fds; -} + json_t *json_cfg = sn->getConfig(); + json_t *json_fpgas = json_object_get(json_cfg, "fpgas"); + if (!json_fpgas) + throw ConfigError(json_cfg, "node-config-fpgas", + "No section 'fpgas' found in config"); -int FpgaNodeFactory::start(SuperNode *sn) -{ - vfioContainer = std::make_shared(); - pciDevices = std::make_shared(); + // Create all FPGA card instances using the corresponding plugin + auto piceCards = + fpga::PCIeCardFactory::make(json_fpgas, pciDevices, vfioContainer); - // Get the FPGA card plugin - auto pcieCardPlugin = plugin::registry->lookup("pcie"); - if (!pcieCardPlugin) - throw RuntimeError("No FPGA PCIe plugin found"); + cards.splice(cards.end(), piceCards); - json_t *json_cfg = sn->getConfig(); - json_t *json_fpgas = json_object_get(json_cfg, "fpgas"); - if (!json_fpgas) - throw ConfigError(json_cfg, "node-config-fpgas", "No section 'fpgas' found in config"); - - // Create all FPGA card instances using the corresponding plugin - auto piceCards = fpga::PCIeCardFactory::make(json_fpgas, pciDevices, vfioContainer); - - cards.splice(cards.end(), piceCards); - - return NodeFactory::start(sn); + return NodeFactory::start(sn); } static FpgaNodeFactory p; diff --git a/lib/nodes/iec60870.cpp b/lib/nodes/iec60870.cpp index e3b213b2a..a05ee4890 100644 --- a/lib/nodes/iec60870.cpp +++ b/lib/nodes/iec60870.cpp @@ -7,12 +7,12 @@ #include +#include #include #include -#include #include #include -#include +#include using namespace villas; using namespace villas::node; @@ -20,787 +20,793 @@ using namespace villas::utils; using namespace villas::node::iec60870; using namespace std::literals::chrono_literals; -static -CP56Time2a timespec_to_cp56time2a(timespec time) { - time_t time_ms = - static_cast(time.tv_sec) * 1000 - + static_cast(time.tv_nsec) / 1000000; - return CP56Time2a_createFromMsTimestamp(NULL, time_ms); +static CP56Time2a timespec_to_cp56time2a(timespec time) { + time_t time_ms = static_cast(time.tv_sec) * 1000 + + static_cast(time.tv_nsec) / 1000000; + return CP56Time2a_createFromMsTimestamp(NULL, time_ms); } -static -timespec cp56time2a_to_timespec(CP56Time2a cp56time2a) { - auto time_ms = CP56Time2a_toMsTimestamp(cp56time2a); - timespec time {}; - time.tv_nsec = time_ms % 1000 * 1000; - time.tv_sec = time_ms / 1000; - return time; +static timespec cp56time2a_to_timespec(CP56Time2a cp56time2a) { + auto time_ms = CP56Time2a_toMsTimestamp(cp56time2a); + timespec time{}; + time.tv_nsec = time_ms % 1000 * 1000; + time.tv_sec = time_ms / 1000; + return time; } -ASDUData ASDUData::parse(json_t *json_signal, std::optional last_data, bool duplicate_ioa_is_sequence) { - json_error_t err; - char const *asdu_type_name = nullptr; - int with_timestamp = -1; - char const *asdu_type_id = nullptr; - std::optional ioa_sequence_start = std::nullopt; - int ioa = -1; +ASDUData ASDUData::parse(json_t *json_signal, std::optional last_data, + bool duplicate_ioa_is_sequence) { + json_error_t err; + char const *asdu_type_name = nullptr; + int with_timestamp = -1; + char const *asdu_type_id = nullptr; + std::optional ioa_sequence_start = std::nullopt; + int ioa = -1; - if (json_unpack_ex(json_signal, &err, 0, "{ s?: s, s?: b, s?: s, s: i }", - "asdu_type", &asdu_type_name, - "with_timestamp", &with_timestamp, - "asdu_type_id", &asdu_type_id, - "ioa", &ioa - )) - throw ConfigError(json_signal, err, "node-config-node-iec60870-5-104"); + if (json_unpack_ex(json_signal, &err, 0, "{ s?: s, s?: b, s?: s, s: i }", + "asdu_type", &asdu_type_name, "with_timestamp", + &with_timestamp, "asdu_type_id", &asdu_type_id, "ioa", + &ioa)) + throw ConfigError(json_signal, err, "node-config-node-iec60870-5-104"); - // Increase the ioa if it is found twice to make it a sequence - if ( duplicate_ioa_is_sequence && - last_data && - ioa == last_data->ioa_sequence_start) { - ioa = last_data->ioa + 1; - ioa_sequence_start = last_data->ioa_sequence_start; - } + // Increase the ioa if it is found twice to make it a sequence + if (duplicate_ioa_is_sequence && last_data && + ioa == last_data->ioa_sequence_start) { + ioa = last_data->ioa + 1; + ioa_sequence_start = last_data->ioa_sequence_start; + } - if ( (asdu_type_name && asdu_type_id) || - (!asdu_type_name && !asdu_type_id)) - throw RuntimeError("Please specify one of asdu_type or asdu_type_id", ioa); + if ((asdu_type_name && asdu_type_id) || (!asdu_type_name && !asdu_type_id)) + throw RuntimeError("Please specify one of asdu_type or asdu_type_id", ioa); - auto asdu_data = asdu_type_name - ? ASDUData::lookupName(asdu_type_name, - with_timestamp != -1 ? with_timestamp != 0 : false, - ioa, ioa_sequence_start.value_or(ioa)) - : ASDUData::lookupTypeId(asdu_type_id, ioa, ioa_sequence_start.value_or(ioa)); + auto asdu_data = + asdu_type_name ? ASDUData::lookupName( + asdu_type_name, + with_timestamp != -1 ? with_timestamp != 0 : false, + ioa, ioa_sequence_start.value_or(ioa)) + : ASDUData::lookupTypeId(asdu_type_id, ioa, + ioa_sequence_start.value_or(ioa)); - if (!asdu_data.has_value()) - throw RuntimeError("Found invalid asdu_type or asdu_type_id"); + if (!asdu_data.has_value()) + throw RuntimeError("Found invalid asdu_type or asdu_type_id"); - if (asdu_type_id && with_timestamp != -1 && asdu_data->hasTimestamp() != with_timestamp) - throw RuntimeError("Found mismatch between asdu_type_id {} and with_timestamp {}", asdu_type_id, with_timestamp != 0); + if (asdu_type_id && with_timestamp != -1 && + asdu_data->hasTimestamp() != with_timestamp) + throw RuntimeError( + "Found mismatch between asdu_type_id {} and with_timestamp {}", + asdu_type_id, with_timestamp != 0); - return *asdu_data; + return *asdu_data; }; -std::optional ASDUData::lookupTypeId(char const *type_id, int ioa, int ioa_sequence_start) -{ - auto check = [type_id] (Descriptor descriptor) { - return !strcmp(descriptor.type_id, type_id); - }; +std::optional ASDUData::lookupTypeId(char const *type_id, int ioa, + int ioa_sequence_start) { + auto check = [type_id](Descriptor descriptor) { + return !strcmp(descriptor.type_id, type_id); + }; - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return ASDUData { &*descriptor, ioa, ioa_sequence_start }; - else - return std::nullopt; + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return ASDUData{&*descriptor, ioa, ioa_sequence_start}; + else + return std::nullopt; } -std::optional ASDUData::lookupName(char const *name, bool with_timestamp, int ioa, int ioa_sequence_start) -{ - auto check = [name, with_timestamp] (Descriptor descriptor) { - return !strcmp(descriptor.name, name) && descriptor.has_timestamp == with_timestamp; - }; +std::optional ASDUData::lookupName(char const *name, + bool with_timestamp, int ioa, + int ioa_sequence_start) { + auto check = [name, with_timestamp](Descriptor descriptor) { + return !strcmp(descriptor.name, name) && + descriptor.has_timestamp == with_timestamp; + }; - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return ASDUData { &*descriptor, ioa, ioa_sequence_start }; - else - return std::nullopt; + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return ASDUData{&*descriptor, ioa, ioa_sequence_start}; + else + return std::nullopt; } -std::optional ASDUData::lookupType(int type, int ioa, int ioa_sequence_start) -{ - auto check = [type] (Descriptor descriptor) { - return descriptor.type == type; - }; +std::optional ASDUData::lookupType(int type, int ioa, + int ioa_sequence_start) { + auto check = [type](Descriptor descriptor) { + return descriptor.type == type; + }; - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return ASDUData { &*descriptor, ioa, ioa_sequence_start }; - else - return std::nullopt; + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return ASDUData{&*descriptor, ioa, ioa_sequence_start}; + else + return std::nullopt; } -bool ASDUData::hasTimestamp() const -{ - return descriptor->has_timestamp; +bool ASDUData::hasTimestamp() const { return descriptor->has_timestamp; } + +ASDUData::Type ASDUData::type() const { return descriptor->type; } + +char const *ASDUData::name() const { return descriptor->name; } + +ASDUData::Type ASDUData::typeWithoutTimestamp() const { + return descriptor->type_without_timestamp; } -ASDUData::Type ASDUData::type() const -{ - return descriptor->type; +ASDUData ASDUData::withoutTimestamp() const { + return ASDUData::lookupType(typeWithoutTimestamp(), ioa, ioa_sequence_start) + .value(); } -char const * ASDUData::name() const { - return descriptor->name; +SignalType ASDUData::signalType() const { return descriptor->signal_type; } + +std::optional +ASDUData::checkASDU(CS101_ASDU const &asdu) const { + if (CS101_ASDU_getTypeID(asdu) != static_cast(descriptor->type)) + return std::nullopt; + + for (int i = 0; i < CS101_ASDU_getNumberOfElements(asdu); i++) { + InformationObject io = CS101_ASDU_getElement(asdu, i); + + if (ioa != InformationObject_getObjectAddress(io)) { + InformationObject_destroy(io); + continue; + } + + SignalData signal_data; + QualityDescriptor quality; + switch (typeWithoutTimestamp()) { + case ASDUData::SCALED_INT: { + auto scaled_int = reinterpret_cast(io); + int scaled_int_value = MeasuredValueScaled_getValue(scaled_int); + signal_data.i = static_cast(scaled_int_value); + quality = MeasuredValueScaled_getQuality(scaled_int); + break; + } + + case ASDUData::NORMALIZED_FLOAT: { + auto normalized_float = reinterpret_cast(io); + float normalized_float_value = + MeasuredValueNormalized_getValue(normalized_float); + signal_data.f = static_cast(normalized_float_value); + quality = MeasuredValueNormalized_getQuality(normalized_float); + break; + } + + case ASDUData::DOUBLE_POINT: { + auto double_point = reinterpret_cast(io); + DoublePointValue double_point_value = + DoublePointInformation_getValue(double_point); + signal_data.i = static_cast(double_point_value); + quality = DoublePointInformation_getQuality(double_point); + break; + } + + case ASDUData::SINGLE_POINT: { + auto single_point = reinterpret_cast(io); + bool single_point_value = SinglePointInformation_getValue(single_point); + signal_data.b = static_cast(single_point_value); + quality = SinglePointInformation_getQuality(single_point); + break; + } + + case ASDUData::SHORT_FLOAT: { + auto short_float = reinterpret_cast(io); + float short_float_value = MeasuredValueShort_getValue(short_float); + signal_data.f = static_cast(short_float_value); + quality = MeasuredValueShort_getQuality(short_float); + break; + } + + default: + throw RuntimeError{"unsupported asdu type"}; + } + + std::optional time_cp56; + switch (type()) { + case ASDUData::SCALED_INT_WITH_TIMESTAMP: { + auto scaled_int = reinterpret_cast(io); + time_cp56 = MeasuredValueScaledWithCP56Time2a_getTimestamp(scaled_int); + break; + } + + case ASDUData::NORMALIZED_FLOAT_WITH_TIMESTAMP: { + auto normalized_float = + reinterpret_cast(io); + time_cp56 = + MeasuredValueNormalizedWithCP56Time2a_getTimestamp(normalized_float); + break; + } + + case ASDUData::DOUBLE_POINT_WITH_TIMESTAMP: { + auto double_point = reinterpret_cast(io); + time_cp56 = DoublePointWithCP56Time2a_getTimestamp(double_point); + break; + } + + case ASDUData::SINGLE_POINT_WITH_TIMESTAMP: { + auto single_point = reinterpret_cast(io); + time_cp56 = SinglePointWithCP56Time2a_getTimestamp(single_point); + break; + } + + case ASDUData::SHORT_FLOAT_WITH_TIMESTAMP: { + auto short_float = reinterpret_cast(io); + time_cp56 = MeasuredValueShortWithCP56Time2a_getTimestamp(short_float); + break; + } + + default: + time_cp56 = std::nullopt; + } + + InformationObject_destroy(io); + + std::optional timestamp = + time_cp56.has_value() + ? std::optional{cp56time2a_to_timespec(*time_cp56)} + : std::nullopt; + + return ASDUData::Sample{signal_data, quality, timestamp}; + } + + return std::nullopt; } -ASDUData::Type ASDUData::typeWithoutTimestamp() const -{ - return descriptor->type_without_timestamp; -} - -ASDUData ASDUData::withoutTimestamp() const -{ - return ASDUData::lookupType(typeWithoutTimestamp(), ioa, ioa_sequence_start).value(); -} - -SignalType ASDUData::signalType() const -{ - return descriptor->signal_type; -} - -std::optional ASDUData::checkASDU(CS101_ASDU const &asdu) const -{ - if (CS101_ASDU_getTypeID(asdu) != static_cast(descriptor->type)) - return std::nullopt; - - for (int i = 0; i < CS101_ASDU_getNumberOfElements(asdu); i++) { - InformationObject io = CS101_ASDU_getElement(asdu, i); - - if (ioa != InformationObject_getObjectAddress(io)) { - InformationObject_destroy(io); - continue; - } - - SignalData signal_data; - QualityDescriptor quality; - switch (typeWithoutTimestamp()) { - case ASDUData::SCALED_INT: { - auto scaled_int = reinterpret_cast(io); - int scaled_int_value = MeasuredValueScaled_getValue(scaled_int); - signal_data.i = static_cast(scaled_int_value); - quality = MeasuredValueScaled_getQuality(scaled_int); - break; - } - - case ASDUData::NORMALIZED_FLOAT: { - auto normalized_float = reinterpret_cast(io); - float normalized_float_value = MeasuredValueNormalized_getValue(normalized_float); - signal_data.f = static_cast(normalized_float_value); - quality = MeasuredValueNormalized_getQuality(normalized_float); - break; - } - - case ASDUData::DOUBLE_POINT: { - auto double_point = reinterpret_cast(io); - DoublePointValue double_point_value = DoublePointInformation_getValue(double_point); - signal_data.i = static_cast(double_point_value); - quality = DoublePointInformation_getQuality(double_point); - break; - } - - case ASDUData::SINGLE_POINT: { - auto single_point = reinterpret_cast(io); - bool single_point_value = SinglePointInformation_getValue(single_point); - signal_data.b = static_cast(single_point_value); - quality = SinglePointInformation_getQuality(single_point); - break; - } - - case ASDUData::SHORT_FLOAT: { - auto short_float = reinterpret_cast(io); - float short_float_value = MeasuredValueShort_getValue(short_float); - signal_data.f = static_cast(short_float_value); - quality = MeasuredValueShort_getQuality(short_float); - break; - } - - default: - throw RuntimeError { "unsupported asdu type" }; - } - - std::optional time_cp56; - switch (type()) { - case ASDUData::SCALED_INT_WITH_TIMESTAMP: { - auto scaled_int = reinterpret_cast(io); - time_cp56 = MeasuredValueScaledWithCP56Time2a_getTimestamp(scaled_int); - break; - } - - case ASDUData::NORMALIZED_FLOAT_WITH_TIMESTAMP: { - auto normalized_float = reinterpret_cast(io); - time_cp56 = MeasuredValueNormalizedWithCP56Time2a_getTimestamp(normalized_float); - break; - } - - case ASDUData::DOUBLE_POINT_WITH_TIMESTAMP: { - auto double_point = reinterpret_cast(io); - time_cp56 = DoublePointWithCP56Time2a_getTimestamp(double_point); - break; - } - - case ASDUData::SINGLE_POINT_WITH_TIMESTAMP: { - auto single_point = reinterpret_cast(io); - time_cp56 = SinglePointWithCP56Time2a_getTimestamp(single_point); - break; - } - - case ASDUData::SHORT_FLOAT_WITH_TIMESTAMP: { - auto short_float = reinterpret_cast(io); - time_cp56 = MeasuredValueShortWithCP56Time2a_getTimestamp(short_float); - break; - } - - default: - time_cp56 = std::nullopt; - } - - InformationObject_destroy(io); - - std::optional timestamp = time_cp56.has_value() - ? std::optional { cp56time2a_to_timespec(*time_cp56) } - : std::nullopt; - - return ASDUData::Sample { signal_data, quality, timestamp }; - } - - return std::nullopt; -} - -bool ASDUData::addSampleToASDU(CS101_ASDU &asdu, ASDUData::Sample sample) const -{ +bool ASDUData::addSampleToASDU(CS101_ASDU &asdu, + ASDUData::Sample sample) const { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" - std::optional timestamp = sample.timestamp.has_value() - ? std::optional { timespec_to_cp56time2a(*sample.timestamp) } - : std::nullopt; + std::optional timestamp = + sample.timestamp.has_value() + ? std::optional{timespec_to_cp56time2a(*sample.timestamp)} + : std::nullopt; - InformationObject io = nullptr; - switch (descriptor->type) { - case ASDUData::SCALED_INT: { - auto scaled_int_value = static_cast(sample.signal_data.i & 0xFFFF); - auto scaled_int = MeasuredValueScaled_create(NULL, ioa, scaled_int_value, sample.quality); - io = reinterpret_cast(scaled_int); - break; - } + InformationObject io = nullptr; + switch (descriptor->type) { + case ASDUData::SCALED_INT: { + auto scaled_int_value = static_cast(sample.signal_data.i & 0xFFFF); + auto scaled_int = + MeasuredValueScaled_create(NULL, ioa, scaled_int_value, sample.quality); + io = reinterpret_cast(scaled_int); + break; + } - case ASDUData::NORMALIZED_FLOAT: { - auto normalized_float_value = static_cast(sample.signal_data.f); - auto normalized_float = MeasuredValueNormalized_create(NULL, ioa, normalized_float_value, sample.quality); - io = reinterpret_cast(normalized_float); - break; - } + case ASDUData::NORMALIZED_FLOAT: { + auto normalized_float_value = static_cast(sample.signal_data.f); + auto normalized_float = MeasuredValueNormalized_create( + NULL, ioa, normalized_float_value, sample.quality); + io = reinterpret_cast(normalized_float); + break; + } - case ASDUData::DOUBLE_POINT: { - auto double_point_value = static_cast(sample.signal_data.i & 0x3); - auto double_point = DoublePointInformation_create(NULL, ioa, double_point_value, sample.quality); - io = reinterpret_cast(double_point); - break; - } + case ASDUData::DOUBLE_POINT: { + auto double_point_value = + static_cast(sample.signal_data.i & 0x3); + auto double_point = DoublePointInformation_create( + NULL, ioa, double_point_value, sample.quality); + io = reinterpret_cast(double_point); + break; + } - case ASDUData::SINGLE_POINT: { - auto single_point_value = sample.signal_data.b; - auto single_point = SinglePointInformation_create(NULL, ioa, single_point_value, sample.quality); - io = reinterpret_cast(single_point); - break; - } + case ASDUData::SINGLE_POINT: { + auto single_point_value = sample.signal_data.b; + auto single_point = SinglePointInformation_create( + NULL, ioa, single_point_value, sample.quality); + io = reinterpret_cast(single_point); + break; + } - case ASDUData::SHORT_FLOAT: { - auto short_float_value = static_cast(sample.signal_data.f); - auto short_float = MeasuredValueShort_create(NULL, ioa, short_float_value, sample.quality); - io = reinterpret_cast(short_float); - break; - } + case ASDUData::SHORT_FLOAT: { + auto short_float_value = static_cast(sample.signal_data.f); + auto short_float = + MeasuredValueShort_create(NULL, ioa, short_float_value, sample.quality); + io = reinterpret_cast(short_float); + break; + } - case ASDUData::SCALED_INT_WITH_TIMESTAMP: { - auto scaled_int_value = static_cast(sample.signal_data.i & 0xFFFF); - auto scaled_int = MeasuredValueScaledWithCP56Time2a_create(NULL, ioa, scaled_int_value, sample.quality, timestamp.value()); - io = reinterpret_cast(scaled_int); - break; - } + case ASDUData::SCALED_INT_WITH_TIMESTAMP: { + auto scaled_int_value = static_cast(sample.signal_data.i & 0xFFFF); + auto scaled_int = MeasuredValueScaledWithCP56Time2a_create( + NULL, ioa, scaled_int_value, sample.quality, timestamp.value()); + io = reinterpret_cast(scaled_int); + break; + } - case ASDUData::NORMALIZED_FLOAT_WITH_TIMESTAMP: { - auto normalized_float_value = static_cast(sample.signal_data.f); - auto normalized_float = MeasuredValueNormalizedWithCP56Time2a_create(NULL, ioa, normalized_float_value, sample.quality, timestamp.value()); - io = reinterpret_cast(normalized_float); - break; - } + case ASDUData::NORMALIZED_FLOAT_WITH_TIMESTAMP: { + auto normalized_float_value = static_cast(sample.signal_data.f); + auto normalized_float = MeasuredValueNormalizedWithCP56Time2a_create( + NULL, ioa, normalized_float_value, sample.quality, timestamp.value()); + io = reinterpret_cast(normalized_float); + break; + } - case ASDUData::DOUBLE_POINT_WITH_TIMESTAMP: { - auto double_point_value = static_cast(sample.signal_data.i & 0x3); - auto double_point = DoublePointWithCP56Time2a_create(NULL, ioa, double_point_value, sample.quality, timestamp.value()); - io = reinterpret_cast(double_point); - break; - } + case ASDUData::DOUBLE_POINT_WITH_TIMESTAMP: { + auto double_point_value = + static_cast(sample.signal_data.i & 0x3); + auto double_point = DoublePointWithCP56Time2a_create( + NULL, ioa, double_point_value, sample.quality, timestamp.value()); + io = reinterpret_cast(double_point); + break; + } - case ASDUData::SINGLE_POINT_WITH_TIMESTAMP: { - auto single_point_value = sample.signal_data.b; - auto single_point = SinglePointWithCP56Time2a_create(NULL, ioa, single_point_value, sample.quality, timestamp.value()); - io = reinterpret_cast(single_point); - break; - } + case ASDUData::SINGLE_POINT_WITH_TIMESTAMP: { + auto single_point_value = sample.signal_data.b; + auto single_point = SinglePointWithCP56Time2a_create( + NULL, ioa, single_point_value, sample.quality, timestamp.value()); + io = reinterpret_cast(single_point); + break; + } - case ASDUData::SHORT_FLOAT_WITH_TIMESTAMP: { - auto short_float_value = static_cast(sample.signal_data.f); - auto short_float = MeasuredValueShortWithCP56Time2a_create(NULL, ioa, short_float_value, sample.quality, timestamp.value()); - io = reinterpret_cast(short_float); - break; - } + case ASDUData::SHORT_FLOAT_WITH_TIMESTAMP: { + auto short_float_value = static_cast(sample.signal_data.f); + auto short_float = MeasuredValueShortWithCP56Time2a_create( + NULL, ioa, short_float_value, sample.quality, timestamp.value()); + io = reinterpret_cast(short_float); + break; + } - default: - throw RuntimeError { "invalid asdu data type" }; - } + default: + throw RuntimeError{"invalid asdu data type"}; + } - bool successfully_added = CS101_ASDU_addInformationObject(asdu, io); + bool successfully_added = CS101_ASDU_addInformationObject(asdu, io); - InformationObject_destroy(io); + InformationObject_destroy(io); - return successfully_added; + return successfully_added; #pragma GCC diagnostic pop } -ASDUData::ASDUData(ASDUData::Descriptor const *descriptor, int ioa, int ioa_sequence_start) : ioa(ioa), ioa_sequence_start(ioa_sequence_start), descriptor(descriptor) -{ +ASDUData::ASDUData(ASDUData::Descriptor const *descriptor, int ioa, + int ioa_sequence_start) + : ioa(ioa), ioa_sequence_start(ioa_sequence_start), descriptor(descriptor) { } -void SlaveNode::createSlave() noexcept -{ - // Destroy slave id it was already created - destroySlave(); +void SlaveNode::createSlave() noexcept { + // Destroy slave id it was already created + destroySlave(); - // Create the slave object - server.slave = CS104_Slave_create(server.low_priority_queue, server.high_priority_queue); - CS104_Slave_setServerMode(server.slave, CS104_MODE_SINGLE_REDUNDANCY_GROUP); - CS104_Slave_setMaxOpenConnections(server.slave, 1); + // Create the slave object + server.slave = + CS104_Slave_create(server.low_priority_queue, server.high_priority_queue); + CS104_Slave_setServerMode(server.slave, CS104_MODE_SINGLE_REDUNDANCY_GROUP); + CS104_Slave_setMaxOpenConnections(server.slave, 1); - // Configure the slave according to config - server.asdu_app_layer_parameters = CS104_Slave_getAppLayerParameters(server.slave); - CS104_APCIParameters apci_parameters = CS104_Slave_getConnectionParameters(server.slave); + // Configure the slave according to config + server.asdu_app_layer_parameters = + CS104_Slave_getAppLayerParameters(server.slave); + CS104_APCIParameters apci_parameters = + CS104_Slave_getConnectionParameters(server.slave); - if (server.apci_t0) - apci_parameters->t0 = *server.apci_t0; + if (server.apci_t0) + apci_parameters->t0 = *server.apci_t0; - if (server.apci_t1) - apci_parameters->t1 = *server.apci_t1; + if (server.apci_t1) + apci_parameters->t1 = *server.apci_t1; - if (server.apci_t2) - apci_parameters->t2 = *server.apci_t2; + if (server.apci_t2) + apci_parameters->t2 = *server.apci_t2; - if (server.apci_t3) - apci_parameters->t3 = *server.apci_t3; + if (server.apci_t3) + apci_parameters->t3 = *server.apci_t3; - if (server.apci_k) - apci_parameters->k = *server.apci_k; + if (server.apci_k) + apci_parameters->k = *server.apci_k; - if (server.apci_w) - apci_parameters->w = *server.apci_w; + if (server.apci_w) + apci_parameters->w = *server.apci_w; - CS104_Slave_setLocalAddress(server.slave, server.local_address.c_str()); - CS104_Slave_setLocalPort(server.slave, server.local_port); + CS104_Slave_setLocalAddress(server.slave, server.local_address.c_str()); + CS104_Slave_setLocalPort(server.slave, server.local_port); - // Setup callbacks into the class - CS104_Slave_setClockSyncHandler(server.slave, [] (void *tcp_node, IMasterConnection connection, CS101_ASDU asdu, CP56Time2a new_time) { - auto self = static_cast(tcp_node); - return self->onClockSync(connection, asdu, new_time); - }, this); + // Setup callbacks into the class + CS104_Slave_setClockSyncHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, CS101_ASDU asdu, + CP56Time2a new_time) { + auto self = static_cast(tcp_node); + return self->onClockSync(connection, asdu, new_time); + }, + this); - CS104_Slave_setInterrogationHandler(server.slave, [] (void *tcp_node, IMasterConnection connection, CS101_ASDU asdu, QualifierOfInterrogation qoi) { - auto self = static_cast(tcp_node); - return self->onInterrogation(connection, asdu, qoi); - }, this); + CS104_Slave_setInterrogationHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, CS101_ASDU asdu, + QualifierOfInterrogation qoi) { + auto self = static_cast(tcp_node); + return self->onInterrogation(connection, asdu, qoi); + }, + this); - CS104_Slave_setASDUHandler(server.slave, [] (void *tcp_node, IMasterConnection connection, CS101_ASDU asdu) { - auto self = static_cast(tcp_node); - return self->onASDU(connection, asdu); - }, this); + CS104_Slave_setASDUHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, CS101_ASDU asdu) { + auto self = static_cast(tcp_node); + return self->onASDU(connection, asdu); + }, + this); - CS104_Slave_setConnectionEventHandler(server.slave, [](void *tcp_node, IMasterConnection connection, CS104_PeerConnectionEvent event){ - auto self = static_cast(tcp_node); - self->debugPrintConnection(connection, event); - }, this); + CS104_Slave_setConnectionEventHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, + CS104_PeerConnectionEvent event) { + auto self = static_cast(tcp_node); + self->debugPrintConnection(connection, event); + }, + this); - CS104_Slave_setRawMessageHandler(server.slave, [](void *tcp_node, IMasterConnection connection, uint8_t *message, int message_size, bool sent){ - auto self = static_cast(tcp_node); - self->debugPrintMessage(connection, message, message_size, sent); - }, this); + CS104_Slave_setRawMessageHandler( + server.slave, + [](void *tcp_node, IMasterConnection connection, uint8_t *message, + int message_size, bool sent) { + auto self = static_cast(tcp_node); + self->debugPrintMessage(connection, message, message_size, sent); + }, + this); - server.state = SlaveNode::Server::READY; + server.state = SlaveNode::Server::READY; } -void SlaveNode::destroySlave() noexcept -{ - if (server.state == SlaveNode::Server::NONE) - return; +void SlaveNode::destroySlave() noexcept { + if (server.state == SlaveNode::Server::NONE) + return; - stopSlave(); + stopSlave(); - CS104_Slave_destroy(server.slave); - server.state = SlaveNode::Server::NONE; + CS104_Slave_destroy(server.slave); + server.state = SlaveNode::Server::NONE; } -void SlaveNode::startSlave() noexcept(false) -{ - if (server.state == SlaveNode::Server::NONE) - createSlave(); - else - stopSlave(); +void SlaveNode::startSlave() noexcept(false) { + if (server.state == SlaveNode::Server::NONE) + createSlave(); + else + stopSlave(); - server.state = SlaveNode::Server::READY; + server.state = SlaveNode::Server::READY; - CS104_Slave_start(server.slave); + CS104_Slave_start(server.slave); - if (!CS104_Slave_isRunning(server.slave)) - throw std::runtime_error{"iec60870-5-104 server could not be started"}; + if (!CS104_Slave_isRunning(server.slave)) + throw std::runtime_error{"iec60870-5-104 server could not be started"}; } -void SlaveNode::stopSlave() noexcept -{ - if (server.state != SlaveNode::Server::READY || !CS104_Slave_isRunning(server.slave)) - return; +void SlaveNode::stopSlave() noexcept { + if (server.state != SlaveNode::Server::READY || + !CS104_Slave_isRunning(server.slave)) + return; - server.state = SlaveNode::Server::STOPPED; + server.state = SlaveNode::Server::STOPPED; - if (CS104_Slave_getNumberOfQueueEntries(server.slave, NULL) != 0) - logger->info("Waiting for last messages in queue"); + if (CS104_Slave_getNumberOfQueueEntries(server.slave, NULL) != 0) + logger->info("Waiting for last messages in queue"); - // Wait for all messages to be send before really stopping - while ( (CS104_Slave_getNumberOfQueueEntries(server.slave, NULL) != 0) && - (CS104_Slave_getOpenConnections(server.slave) != 0)) - std::this_thread::sleep_for(100ms); + // Wait for all messages to be send before really stopping + while ((CS104_Slave_getNumberOfQueueEntries(server.slave, NULL) != 0) && + (CS104_Slave_getOpenConnections(server.slave) != 0)) + std::this_thread::sleep_for(100ms); - CS104_Slave_stop(server.slave); + CS104_Slave_stop(server.slave); } -void SlaveNode::debugPrintMessage(IMasterConnection connection, uint8_t* message, int message_size, bool sent) const noexcept -{ - /// TODO: debug print the message bytes as trace +void SlaveNode::debugPrintMessage(IMasterConnection connection, + uint8_t *message, int message_size, + bool sent) const noexcept { + /// TODO: debug print the message bytes as trace } -void SlaveNode::debugPrintConnection(IMasterConnection connection, CS104_PeerConnectionEvent event) const noexcept -{ - switch (event) { - case CS104_CON_EVENT_CONNECTION_OPENED: - logger->info("Client connected"); - break; +void SlaveNode::debugPrintConnection( + IMasterConnection connection, + CS104_PeerConnectionEvent event) const noexcept { + switch (event) { + case CS104_CON_EVENT_CONNECTION_OPENED: + logger->info("Client connected"); + break; - case CS104_CON_EVENT_CONNECTION_CLOSED: - logger->info("Client disconnected"); - break; + case CS104_CON_EVENT_CONNECTION_CLOSED: + logger->info("Client disconnected"); + break; - case CS104_CON_EVENT_ACTIVATED: - logger->info("Connection activated"); - break; + case CS104_CON_EVENT_ACTIVATED: + logger->info("Connection activated"); + break; - case CS104_CON_EVENT_DEACTIVATED: - logger->info("Connection closed"); - break; - } + case CS104_CON_EVENT_DEACTIVATED: + logger->info("Connection closed"); + break; + } } -bool SlaveNode::onClockSync(IMasterConnection connection, CS101_ASDU asdu, CP56Time2a new_time) const noexcept -{ - logger->warn("Received clock sync command (unimplemented)"); - return true; +bool SlaveNode::onClockSync(IMasterConnection connection, CS101_ASDU asdu, + CP56Time2a new_time) const noexcept { + logger->warn("Received clock sync command (unimplemented)"); + return true; } -bool SlaveNode::onInterrogation(IMasterConnection connection, CS101_ASDU asdu, QualifierOfInterrogation qoi) const noexcept -{ - switch (qoi) { - // Send last values without timestamps - case IEC60870_QOI_STATION: { - IMasterConnection_sendACT_CON(connection, asdu, false); +bool SlaveNode::onInterrogation(IMasterConnection connection, CS101_ASDU asdu, + QualifierOfInterrogation qoi) const noexcept { + switch (qoi) { + // Send last values without timestamps + case IEC60870_QOI_STATION: { + IMasterConnection_sendACT_CON(connection, asdu, false); - logger->debug("Received general interrogation"); + logger->debug("Received general interrogation"); - auto guard = std::lock_guard { output.last_values_mutex }; + auto guard = std::lock_guard{output.last_values_mutex}; - for (auto const &asdu_type : output.asdu_types) { - for (unsigned i = 0; i < output.mapping.size();) { - auto signal_asdu = CS101_ASDU_create( - IMasterConnection_getApplicationLayerParameters(connection), - false, - CS101_COT_INTERROGATED_BY_STATION, - 0, - server.common_address, - false, - false - ); + for (auto const &asdu_type : output.asdu_types) { + for (unsigned i = 0; i < output.mapping.size();) { + auto signal_asdu = CS101_ASDU_create( + IMasterConnection_getApplicationLayerParameters(connection), false, + CS101_COT_INTERROGATED_BY_STATION, 0, server.common_address, false, + false); - do { - auto asdu_data = output.mapping[i]; - auto last_value = output.last_values[i]; + do { + auto asdu_data = output.mapping[i]; + auto last_value = output.last_values[i]; - if (asdu_data.type() != asdu_type) - continue; + if (asdu_data.type() != asdu_type) + continue; - if (!asdu_data.withoutTimestamp().addSampleToASDU(signal_asdu, - ASDUData::Sample { - last_value, - IEC60870_QUALITY_GOOD, - std::nullopt - })) - break; - } while (++i < output.mapping.size()); + if (!asdu_data.withoutTimestamp().addSampleToASDU( + signal_asdu, + ASDUData::Sample{last_value, IEC60870_QUALITY_GOOD, + std::nullopt})) + break; + } while (++i < output.mapping.size()); - if (CS101_ASDU_getNumberOfElements(asdu) != 0) - IMasterConnection_sendASDU(connection, signal_asdu); + if (CS101_ASDU_getNumberOfElements(asdu) != 0) + IMasterConnection_sendASDU(connection, signal_asdu); - CS101_ASDU_destroy(signal_asdu); - } - } + CS101_ASDU_destroy(signal_asdu); + } + } - IMasterConnection_sendACT_TERM(connection, asdu); - break; - } + IMasterConnection_sendACT_TERM(connection, asdu); + break; + } - // Negative acknowledgement - default: - IMasterConnection_sendACT_CON(connection, asdu, true); - logger->warn("Ignoring interrogation type {}", qoi); - } + // Negative acknowledgement + default: + IMasterConnection_sendACT_CON(connection, asdu, true); + logger->warn("Ignoring interrogation type {}", qoi); + } - return true; + return true; } -bool SlaveNode::onASDU(IMasterConnection connection, CS101_ASDU asdu) const noexcept -{ - logger->warn("Ignoring ASDU type {}", CS101_ASDU_getTypeID(asdu)); - return true; +bool SlaveNode::onASDU(IMasterConnection connection, + CS101_ASDU asdu) const noexcept { + logger->warn("Ignoring ASDU type {}", CS101_ASDU_getTypeID(asdu)); + return true; } -void SlaveNode::sendPeriodicASDUsForSample(Sample const *sample) const noexcept(false) -{ - // ASDUs may only carry one type of ASDU - for (auto const &type : output.asdu_types) { - // Search all occurrences of this ASDU type - for (unsigned signal = 0; signal < MIN(sample->length, output.mapping.size());) { - // Create an ASDU for periodic transmission - CS101_ASDU asdu = CS101_ASDU_create( - server.asdu_app_layer_parameters, - 0, - CS101_COT_PERIODIC, - 0, - server.common_address, - false, - false - ); +void SlaveNode::sendPeriodicASDUsForSample(Sample const *sample) const + noexcept(false) { + // ASDUs may only carry one type of ASDU + for (auto const &type : output.asdu_types) { + // Search all occurrences of this ASDU type + for (unsigned signal = 0; + signal < MIN(sample->length, output.mapping.size());) { + // Create an ASDU for periodic transmission + CS101_ASDU asdu = CS101_ASDU_create(server.asdu_app_layer_parameters, 0, + CS101_COT_PERIODIC, 0, + server.common_address, false, false); - do { - auto &asdu_data = output.mapping[signal]; + do { + auto &asdu_data = output.mapping[signal]; - // This signal_data does not belong in this ASDU - if (asdu_data.type() != type) - continue; + // This signal_data does not belong in this ASDU + if (asdu_data.type() != type) + continue; - auto timestamp = (sample->flags & (int) SampleFlags::HAS_TS_ORIGIN) - ? std::optional{ sample->ts.origin } - : std::nullopt; + auto timestamp = (sample->flags & (int)SampleFlags::HAS_TS_ORIGIN) + ? std::optional{sample->ts.origin} + : std::nullopt; - if (asdu_data.hasTimestamp() && !timestamp.has_value()) - throw RuntimeError("Received sample without timestamp for ASDU type with mandatory timestamp"); + if (asdu_data.hasTimestamp() && !timestamp.has_value()) + throw RuntimeError("Received sample without timestamp for ASDU type " + "with mandatory timestamp"); - if (asdu_data.signalType() != sample_format(sample, signal)) - throw RuntimeError("Expected signal type {}, but received {}", - signalTypeToString(asdu_data.signalType()), - signalTypeToString(sample_format(sample, signal)) - ); + if (asdu_data.signalType() != sample_format(sample, signal)) + throw RuntimeError("Expected signal type {}, but received {}", + signalTypeToString(asdu_data.signalType()), + signalTypeToString(sample_format(sample, signal))); - if (asdu_data.addSampleToASDU(asdu, ASDUData::Sample { - sample->data[signal], - IEC60870_QUALITY_GOOD, - timestamp - }) == false) - // ASDU is full -> dispatch -> create a new one - break; - } while (++signal < MIN(sample->length, output.mapping.size())); + if (asdu_data.addSampleToASDU(asdu, + ASDUData::Sample{sample->data[signal], + IEC60870_QUALITY_GOOD, + timestamp}) == false) + // ASDU is full -> dispatch -> create a new one + break; + } while (++signal < MIN(sample->length, output.mapping.size())); - if (CS101_ASDU_getNumberOfElements(asdu) != 0) - CS104_Slave_enqueueASDU(server.slave, asdu); + if (CS101_ASDU_getNumberOfElements(asdu) != 0) + CS104_Slave_enqueueASDU(server.slave, asdu); - CS101_ASDU_destroy(asdu); - } - } + CS101_ASDU_destroy(asdu); + } + } } -int SlaveNode::_write(Sample *samples[], unsigned sample_count) -{ - if (server.state != SlaveNode::Server::READY) - return -1; +int SlaveNode::_write(Sample *samples[], unsigned sample_count) { + if (server.state != SlaveNode::Server::READY) + return -1; - for (unsigned sample_index = 0; sample_index < sample_count; sample_index++) { - Sample const *sample = samples[sample_index]; + for (unsigned sample_index = 0; sample_index < sample_count; sample_index++) { + Sample const *sample = samples[sample_index]; - // Update last_values - output.last_values_mutex.lock(); - for (unsigned i = 0; i < MIN(sample->length, output.last_values.size()); i++) - output.last_values[i] = sample->data[i]; + // Update last_values + output.last_values_mutex.lock(); + for (unsigned i = 0; i < MIN(sample->length, output.last_values.size()); + i++) + output.last_values[i] = sample->data[i]; - output.last_values_mutex.unlock(); - sendPeriodicASDUsForSample(sample); - } + output.last_values_mutex.unlock(); + sendPeriodicASDUsForSample(sample); + } - return sample_count; + return sample_count; } -SlaveNode::SlaveNode(const uuid_t &id, const std::string &name) : - Node(id, name) -{ - server.state = SlaveNode::Server::NONE; +SlaveNode::SlaveNode(const uuid_t &id, const std::string &name) + : Node(id, name) { + server.state = SlaveNode::Server::NONE; - // Server config (use explicit defaults) - server.local_address = "0.0.0.0"; - server.local_port = 2404; - server.common_address = 1; - server.low_priority_queue = 100; - server.high_priority_queue = 100; + // Server config (use explicit defaults) + server.local_address = "0.0.0.0"; + server.local_port = 2404; + server.common_address = 1; + server.low_priority_queue = 100; + server.high_priority_queue = 100; - // Config (use lib60870 defaults if std::nullopt) - server.apci_t0 = std::nullopt; - server.apci_t1 = std::nullopt; - server.apci_t2 = std::nullopt; - server.apci_t3 = std::nullopt; - server.apci_k = std::nullopt; - server.apci_w = std::nullopt; + // Config (use lib60870 defaults if std::nullopt) + server.apci_t0 = std::nullopt; + server.apci_t1 = std::nullopt; + server.apci_t2 = std::nullopt; + server.apci_t3 = std::nullopt; + server.apci_k = std::nullopt; + server.apci_w = std::nullopt; - // Output config - output.enabled = false; - output.mapping = {}; - output.asdu_types = {}; - output.last_values = {}; + // Output config + output.enabled = false; + output.mapping = {}; + output.asdu_types = {}; + output.last_values = {}; } -SlaveNode::~SlaveNode() -{ - destroySlave(); +SlaveNode::~SlaveNode() { destroySlave(); } + +int SlaveNode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; + + json_error_t err; + auto signals = getOutputSignals(); + + json_t *json_out = nullptr; + char const *address = nullptr; + int apci_t0 = -1; + int apci_t1 = -1; + int apci_t2 = -1; + int apci_t3 = -1; + int apci_k = -1; + int apci_w = -1; + + ret = json_unpack_ex( + json, &err, 0, + "{ s?: o, s?: s, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, " + "s?: i, s?: i }", + "out", &json_out, "address", &address, "port", &server.local_port, "ca", + &server.common_address, "low_priority_queue", &server.low_priority_queue, + "high_priority_queue", &server.high_priority_queue, "apci_t0", &apci_t0, + "apci_t1", &apci_t1, "apci_t2", &apci_t2, "apci_t3", &apci_t3, "apci_k", + &apci_k, "apci_w", &apci_w); + if (ret) + throw ConfigError(json, err, "node-config-node-iec60870-5-104"); + + if (apci_t0 != -1) + server.apci_t0 = apci_t0; + + if (apci_t1 != -1) + server.apci_t1 = apci_t1; + + if (apci_t2 != -1) + server.apci_t2 = apci_t2; + + if (apci_t3 != -1) + server.apci_t3 = apci_t3; + + if (apci_k != -1) + server.apci_k = apci_k; + + if (apci_w != -1) + server.apci_w = apci_w; + + if (address) + server.local_address = address; + + json_t *json_signals = nullptr; + int duplicate_ioa_is_sequence = false; + + if (json_out) { + output.enabled = true; + + ret = json_unpack_ex(json_out, &err, 0, "{ s: o, s?: b }", "signals", + &json_signals, "duplicate_ioa_is_sequence", + &duplicate_ioa_is_sequence); + if (ret) + throw ConfigError(json_out, err, "node-config-node-iec60870-5-104"); + } + + if (json_signals) { + json_t *json_signal; + size_t i; + std::optional last_data = std::nullopt; + + json_array_foreach(json_signals, i, json_signal) { + auto signal = signals ? signals->getByIndex(i) : Signal::Ptr{}; + auto asdu_data = + ASDUData::parse(json_signal, last_data, duplicate_ioa_is_sequence); + last_data = asdu_data; + SignalData initial_value; + + if (signal) { + if (signal->type != asdu_data.signalType()) { + throw RuntimeError( + "Type mismatch! Expected type {} for signal {}, but found {}", + signalTypeToString(asdu_data.signalType()), signal->name, + signalTypeToString(signal->type)); + } + + switch (signal->type) { + case SignalType::BOOLEAN: + initial_value.b = false; + break; + + case SignalType::INTEGER: + initial_value.i = 0; + break; + + case SignalType::FLOAT: + initial_value.f = 0; + break; + + default: + throw RuntimeError{"unsupported signal type"}; + } + } else + initial_value.f = 0.0; + + output.mapping.push_back(asdu_data); + output.last_values.push_back(initial_value); + } + } + + for (auto const &asdu_data : output.mapping) { + if (std::find(begin(output.asdu_types), end(output.asdu_types), + asdu_data.type()) == end(output.asdu_types)) + output.asdu_types.push_back(asdu_data.type()); + } + + return 0; } -int SlaveNode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int SlaveNode::start() { + startSlave(); - json_error_t err; - auto signals = getOutputSignals(); - - json_t *json_out = nullptr; - char const *address = nullptr; - int apci_t0 = -1; - int apci_t1 = -1; - int apci_t2 = -1; - int apci_t3 = -1; - int apci_k = -1; - int apci_w = -1; - - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: s, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i, s?: i }", - "out", &json_out, - "address", &address, - "port", &server.local_port, - "ca", &server.common_address, - "low_priority_queue", &server.low_priority_queue, - "high_priority_queue", &server.high_priority_queue, - "apci_t0", &apci_t0, - "apci_t1", &apci_t1, - "apci_t2", &apci_t2, - "apci_t3", &apci_t3, - "apci_k", &apci_k, - "apci_w", &apci_w - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec60870-5-104"); - - if (apci_t0 != -1) - server.apci_t0 = apci_t0; - - if (apci_t1 != -1) - server.apci_t1 = apci_t1; - - if (apci_t2 != -1) - server.apci_t2 = apci_t2; - - if (apci_t3 != -1) - server.apci_t3 = apci_t3; - - if (apci_k != -1) - server.apci_k = apci_k; - - if (apci_w != -1) - server.apci_w = apci_w; - - if (address) - server.local_address = address; - - json_t *json_signals = nullptr; - int duplicate_ioa_is_sequence = false; - - if (json_out) { - output.enabled = true; - - ret = json_unpack_ex(json_out, &err, 0, "{ s: o, s?: b }", - "signals", &json_signals, - "duplicate_ioa_is_sequence", &duplicate_ioa_is_sequence - ); - if (ret) - throw ConfigError(json_out, err, "node-config-node-iec60870-5-104"); - } - - if (json_signals) { - json_t *json_signal; - size_t i; - std::optional last_data = std::nullopt; - - json_array_foreach(json_signals, i, json_signal) { - auto signal = signals ? signals->getByIndex(i) : Signal::Ptr{}; - auto asdu_data = ASDUData::parse(json_signal, last_data, duplicate_ioa_is_sequence); - last_data = asdu_data; - SignalData initial_value; - - if (signal) { - if (signal->type != asdu_data.signalType()) { - throw RuntimeError("Type mismatch! Expected type {} for signal {}, but found {}", - signalTypeToString(asdu_data.signalType()), - signal->name, - signalTypeToString(signal->type) - ); - } - - switch (signal->type) { - case SignalType::BOOLEAN: - initial_value.b = false; - break; - - case SignalType::INTEGER: - initial_value.i = 0; - break; - - case SignalType::FLOAT: - initial_value.f = 0; - break; - - default: - throw RuntimeError { "unsupported signal type" }; - } - } else - initial_value.f = 0.0; - - output.mapping.push_back(asdu_data); - output.last_values.push_back(initial_value); - } - } - - for (auto const &asdu_data : output.mapping) { - if (std::find(begin(output.asdu_types), end(output.asdu_types), asdu_data.type()) == end(output.asdu_types)) - output.asdu_types.push_back(asdu_data.type()); - } - - return 0; + return Node::start(); } -int SlaveNode::start() -{ - startSlave(); +int SlaveNode::stop() { + stopSlave(); - return Node::start(); -} - -int SlaveNode::stop() -{ - stopSlave(); - - return Node::stop(); + return Node::stop(); } // Register node static char name[] = "iec60870-5-104"; static char description[] = "Provide values as protocol slave"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/iec61850.cpp b/lib/nodes/iec61850.cpp index 33771ad48..2ac58e9b3 100644 --- a/lib/nodes/iec61850.cpp +++ b/lib/nodes/iec61850.cpp @@ -9,11 +9,11 @@ #include #include +#include #include #include #include #include -#include #define CONFIG_SV_DEFAULT_APPID 0x4000 #define CONFIG_SV_DEFAULT_DST_ADDRESS CONFIG_GOOSE_DEFAULT_DST_ADDRESS @@ -25,290 +25,295 @@ using namespace villas::node; using namespace villas::utils; const struct iec61850_type_descriptor type_descriptors[] = { - // name, iec_type, type, size, supported - { "boolean", IEC61850Type::BOOLEAN, SignalType::BOOLEAN, 1, false, false }, - { "int8", IEC61850Type::INT8, SignalType::INTEGER, 1, false, false }, - { "int16", IEC61850Type::INT16, SignalType::INTEGER, 2, false, false }, - { "int32", IEC61850Type::INT32, SignalType::INTEGER, 4, false, false }, - { "int64", IEC61850Type::INT64, SignalType::INTEGER, 8, false, false }, - { "int8u", IEC61850Type::INT8U, SignalType::INTEGER, 1, false, false }, - { "int16u", IEC61850Type::INT16U, SignalType::INTEGER, 2, false, false }, - { "int32u", IEC61850Type::INT32U, SignalType::INTEGER, 4, false, false }, - { "int64u", IEC61850Type::INT64U, SignalType::INTEGER, 8, false, false }, - { "float32", IEC61850Type::FLOAT32, SignalType::FLOAT, 4, false, false }, - { "float64", IEC61850Type::FLOAT64, SignalType::FLOAT, 8, false, false }, - { "enumerated", IEC61850Type::ENUMERATED, SignalType::INVALID, 4, false, false }, - { "coded_enum", IEC61850Type::CODED_ENUM, SignalType::INVALID, 4, false, false }, - { "octet_string", IEC61850Type::OCTET_STRING, SignalType::INVALID, 20, false, false }, - { "visible_string", IEC61850Type::VISIBLE_STRING, SignalType::INVALID, 35, false, false }, - { "objectname", IEC61850Type::OBJECTNAME, SignalType::INVALID, 20, false, false }, - { "objectreference", IEC61850Type::OBJECTREFERENCE, SignalType::INVALID, 20, false, false }, - { "timestamp", IEC61850Type::TIMESTAMP, SignalType::INVALID, 8, false, false }, - { "entrytime", IEC61850Type::ENTRYTIME, SignalType::INVALID, 6, false, false }, - { "bitstring", IEC61850Type::BITSTRING, SignalType::INVALID, 4, false, false } -}; + // name, iec_type, type, size, supported + {"boolean", IEC61850Type::BOOLEAN, SignalType::BOOLEAN, 1, false, false}, + {"int8", IEC61850Type::INT8, SignalType::INTEGER, 1, false, false}, + {"int16", IEC61850Type::INT16, SignalType::INTEGER, 2, false, false}, + {"int32", IEC61850Type::INT32, SignalType::INTEGER, 4, false, false}, + {"int64", IEC61850Type::INT64, SignalType::INTEGER, 8, false, false}, + {"int8u", IEC61850Type::INT8U, SignalType::INTEGER, 1, false, false}, + {"int16u", IEC61850Type::INT16U, SignalType::INTEGER, 2, false, false}, + {"int32u", IEC61850Type::INT32U, SignalType::INTEGER, 4, false, false}, + {"int64u", IEC61850Type::INT64U, SignalType::INTEGER, 8, false, false}, + {"float32", IEC61850Type::FLOAT32, SignalType::FLOAT, 4, false, false}, + {"float64", IEC61850Type::FLOAT64, SignalType::FLOAT, 8, false, false}, + {"enumerated", IEC61850Type::ENUMERATED, SignalType::INVALID, 4, false, + false}, + {"coded_enum", IEC61850Type::CODED_ENUM, SignalType::INVALID, 4, false, + false}, + {"octet_string", IEC61850Type::OCTET_STRING, SignalType::INVALID, 20, false, + false}, + {"visible_string", IEC61850Type::VISIBLE_STRING, SignalType::INVALID, 35, + false, false}, + {"objectname", IEC61850Type::OBJECTNAME, SignalType::INVALID, 20, false, + false}, + {"objectreference", IEC61850Type::OBJECTREFERENCE, SignalType::INVALID, 20, + false, false}, + {"timestamp", IEC61850Type::TIMESTAMP, SignalType::INVALID, 8, false, + false}, + {"entrytime", IEC61850Type::ENTRYTIME, SignalType::INVALID, 6, false, + false}, + {"bitstring", IEC61850Type::BITSTRING, SignalType::INVALID, 4, false, + false}}; // Each network interface needs a separate receiver -static -struct List receivers; -static -pthread_t thread; -static -EthernetHandleSet hset; -static -int users = 0; +static struct List receivers; +static pthread_t thread; +static EthernetHandleSet hset; +static int users = 0; -static -void * iec61850_thread(void *ctx) -{ - int ret; +static void *iec61850_thread(void *ctx) { + int ret; - while (1) { - ret = EthernetHandleSet_waitReady(hset, 1000); - if (ret < 0) - continue; + while (1) { + ret = EthernetHandleSet_waitReady(hset, 1000); + if (ret < 0) + continue; - for (unsigned i = 0; i < list_length(&receivers); i++) { - struct iec61850_receiver *r = (struct iec61850_receiver *) list_at(&receivers, i); + for (unsigned i = 0; i < list_length(&receivers); i++) { + struct iec61850_receiver *r = + (struct iec61850_receiver *)list_at(&receivers, i); - switch (r->type) { - case iec61850_receiver::Type::GOOSE: GooseReceiver_tick(r->goose); break; - case iec61850_receiver::Type::SAMPLED_VALUES: SVReceiver_tick(r->sv); break; - } - } - } + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + GooseReceiver_tick(r->goose); + break; + case iec61850_receiver::Type::SAMPLED_VALUES: + SVReceiver_tick(r->sv); + break; + } + } + } - return nullptr; + return nullptr; } -const struct iec61850_type_descriptor * villas::node::iec61850_lookup_type(const char *name) -{ - for (unsigned i = 0; i < ARRAY_LEN(type_descriptors); i++) { - if (!strcmp(name, type_descriptors[i].name)) - return &type_descriptors[i]; - } +const struct iec61850_type_descriptor * +villas::node::iec61850_lookup_type(const char *name) { + for (unsigned i = 0; i < ARRAY_LEN(type_descriptors); i++) { + if (!strcmp(name, type_descriptors[i].name)) + return &type_descriptors[i]; + } - return nullptr; + return nullptr; } -int villas::node::iec61850_parse_signals(json_t *json_signals, struct List *signals, SignalList::Ptr node_signals) -{ - int ret, total_size = 0; - const char *iec_type; - const struct iec61850_type_descriptor *td; - json_error_t err; +int villas::node::iec61850_parse_signals(json_t *json_signals, + struct List *signals, + SignalList::Ptr node_signals) { + int ret, total_size = 0; + const char *iec_type; + const struct iec61850_type_descriptor *td; + json_error_t err; - ret = list_init(signals); - if (ret) - return ret; + ret = list_init(signals); + if (ret) + return ret; - if (json_is_array(json_signals)) { - json_t *json_signal; - size_t i; - json_array_foreach(json_signals, i, json_signal) { - json_unpack_ex(json_signal, &err, 0, "{ s?: s }", - "iec_type", &iec_type - ); + if (json_is_array(json_signals)) { + json_t *json_signal; + size_t i; + json_array_foreach(json_signals, i, json_signal) { + json_unpack_ex(json_signal, &err, 0, "{ s?: s }", "iec_type", &iec_type); - // Try to deduct the IEC 61850 data type from VILLAS signal format - if (!iec_type) { - if (!node_signals) - return -1; + // Try to deduct the IEC 61850 data type from VILLAS signal format + if (!iec_type) { + if (!node_signals) + return -1; - auto sig = node_signals->getByIndex(i); - if (!sig) - return -1; + auto sig = node_signals->getByIndex(i); + if (!sig) + return -1; - switch (sig->type) { - case SignalType::BOOLEAN: - iec_type = "boolean"; - break; + switch (sig->type) { + case SignalType::BOOLEAN: + iec_type = "boolean"; + break; - case SignalType::FLOAT: - iec_type = "float64"; - break; + case SignalType::FLOAT: + iec_type = "float64"; + break; - case SignalType::INTEGER: - iec_type = "int64"; - break; + case SignalType::INTEGER: + iec_type = "int64"; + break; - default: - return -1; - } - } + default: + return -1; + } + } - td = iec61850_lookup_type(iec_type); - if (!td) - return -1; + td = iec61850_lookup_type(iec_type); + if (!td) + return -1; - list_push(signals, (void *) td); + list_push(signals, (void *)td); - total_size += td->size; - } - } - else { - ret = json_unpack_ex(json_signals, &err, 0, "{ s: s }", "iec_type", &iec_type); - if (ret) - return ret; + total_size += td->size; + } + } else { + ret = json_unpack_ex(json_signals, &err, 0, "{ s: s }", "iec_type", + &iec_type); + if (ret) + return ret; - td = iec61850_lookup_type(iec_type); - if (!td) - return -1; + td = iec61850_lookup_type(iec_type); + if (!td) + return -1; - for (unsigned i = 0; i < node_signals->size(); i++) { - list_push(signals, (void *) td); + for (unsigned i = 0; i < node_signals->size(); i++) { + list_push(signals, (void *)td); - total_size += td->size; - } - } + total_size += td->size; + } + } - return total_size; + return total_size; } -int villas::node::iec61850_type_start(villas::node::SuperNode *sn) -{ - int ret; +int villas::node::iec61850_type_start(villas::node::SuperNode *sn) { + int ret; - // Check if already initialized - if (users > 0) - return 0; + // Check if already initialized + if (users > 0) + return 0; - ret = list_init(&receivers); - if (ret) - return ret; + ret = list_init(&receivers); + if (ret) + return ret; - hset = EthernetHandleSet_new(); + hset = EthernetHandleSet_new(); - ret = pthread_create(&thread, nullptr, iec61850_thread, nullptr); - if (ret) - return ret; + ret = pthread_create(&thread, nullptr, iec61850_thread, nullptr); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::iec61850_type_stop() -{ - int ret; +int villas::node::iec61850_type_stop() { + int ret; - if (--users > 0) - return 0; + if (--users > 0) + return 0; - for (unsigned i = 0; i < list_length(&receivers); i++) { - struct iec61850_receiver *r = (struct iec61850_receiver *) list_at(&receivers, i); + for (unsigned i = 0; i < list_length(&receivers); i++) { + struct iec61850_receiver *r = + (struct iec61850_receiver *)list_at(&receivers, i); - iec61850_receiver_stop(r); - } + iec61850_receiver_stop(r); + } - ret = pthread_cancel(thread); - if (ret) - return ret; + ret = pthread_cancel(thread); + if (ret) + return ret; - ret = pthread_join(thread, nullptr); - if (ret) - return ret; + ret = pthread_join(thread, nullptr); + if (ret) + return ret; - EthernetHandleSet_destroy(hset); + EthernetHandleSet_destroy(hset); - ret = list_destroy(&receivers, (dtor_cb_t) iec61850_receiver_destroy, true); - if (ret) - return ret; + ret = list_destroy(&receivers, (dtor_cb_t)iec61850_receiver_destroy, true); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::iec61850_receiver_start(struct iec61850_receiver *r) -{ - switch (r->type) { - case iec61850_receiver::Type::GOOSE: - r->socket = GooseReceiver_startThreadless(r->goose); - break; +int villas::node::iec61850_receiver_start(struct iec61850_receiver *r) { + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + r->socket = GooseReceiver_startThreadless(r->goose); + break; - case iec61850_receiver::Type::SAMPLED_VALUES: - r->socket = SVReceiver_startThreadless(r->sv); - break; - } + case iec61850_receiver::Type::SAMPLED_VALUES: + r->socket = SVReceiver_startThreadless(r->sv); + break; + } - EthernetHandleSet_addSocket(hset, r->socket); + EthernetHandleSet_addSocket(hset, r->socket); - return 0; + return 0; } -int villas::node::iec61850_receiver_stop(struct iec61850_receiver *r) -{ - EthernetHandleSet_removeSocket(hset, r->socket); +int villas::node::iec61850_receiver_stop(struct iec61850_receiver *r) { + EthernetHandleSet_removeSocket(hset, r->socket); - switch (r->type) { - case iec61850_receiver::Type::GOOSE: - GooseReceiver_stopThreadless(r->goose); - break; + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + GooseReceiver_stopThreadless(r->goose); + break; - case iec61850_receiver::Type::SAMPLED_VALUES: - SVReceiver_stopThreadless(r->sv); - break; - } + case iec61850_receiver::Type::SAMPLED_VALUES: + SVReceiver_stopThreadless(r->sv); + break; + } - return 0; + return 0; } -int villas::node::iec61850_receiver_destroy(struct iec61850_receiver *r) -{ - switch (r->type) { - case iec61850_receiver::Type::GOOSE: - GooseReceiver_destroy(r->goose); - break; +int villas::node::iec61850_receiver_destroy(struct iec61850_receiver *r) { + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + GooseReceiver_destroy(r->goose); + break; - case iec61850_receiver::Type::SAMPLED_VALUES: - SVReceiver_destroy(r->sv); - break; - } + case iec61850_receiver::Type::SAMPLED_VALUES: + SVReceiver_destroy(r->sv); + break; + } - free(r->interface); + free(r->interface); - return 0; + return 0; } -struct iec61850_receiver * villas::node::iec61850_receiver_lookup(enum iec61850_receiver::Type t, const char *intf) -{ - for (unsigned i = 0; i < list_length(&receivers); i++) { - struct iec61850_receiver *r = (struct iec61850_receiver *) list_at(&receivers, i); +struct iec61850_receiver * +villas::node::iec61850_receiver_lookup(enum iec61850_receiver::Type t, + const char *intf) { + for (unsigned i = 0; i < list_length(&receivers); i++) { + struct iec61850_receiver *r = + (struct iec61850_receiver *)list_at(&receivers, i); - if (r->type == t && strcmp(r->interface, intf) == 0) - return r; - } + if (r->type == t && strcmp(r->interface, intf) == 0) + return r; + } - return nullptr; + return nullptr; } -struct iec61850_receiver * villas::node::iec61850_receiver_create(enum iec61850_receiver::Type t, const char *intf) -{ - struct iec61850_receiver *r; +struct iec61850_receiver * +villas::node::iec61850_receiver_create(enum iec61850_receiver::Type t, + const char *intf) { + struct iec61850_receiver *r; - // Check if there is already a SVReceiver for this interface - r = iec61850_receiver_lookup(t, intf); - if (!r) { - r = new struct iec61850_receiver; - if (!r) - throw MemoryAllocationError(); + // Check if there is already a SVReceiver for this interface + r = iec61850_receiver_lookup(t, intf); + if (!r) { + r = new struct iec61850_receiver; + if (!r) + throw MemoryAllocationError(); - r->interface = strdup(intf); - r->type = t; + r->interface = strdup(intf); + r->type = t; - switch (r->type) { - case iec61850_receiver::Type::GOOSE: - r->goose = GooseReceiver_create(); - GooseReceiver_setInterfaceId(r->goose, r->interface); - break; + switch (r->type) { + case iec61850_receiver::Type::GOOSE: + r->goose = GooseReceiver_create(); + GooseReceiver_setInterfaceId(r->goose, r->interface); + break; - case iec61850_receiver::Type::SAMPLED_VALUES: - r->sv = SVReceiver_create(); - SVReceiver_setInterfaceId(r->sv, r->interface); - break; - } + case iec61850_receiver::Type::SAMPLED_VALUES: + r->sv = SVReceiver_create(); + SVReceiver_setInterfaceId(r->sv, r->interface); + break; + } - iec61850_receiver_start(r); + iec61850_receiver_start(r); - list_push(&receivers, r); - } + list_push(&receivers, r); + } - return r; + return r; } diff --git a/lib/nodes/iec61850_goose.cpp b/lib/nodes/iec61850_goose.cpp index 0bed4b5da..c7477c237 100644 --- a/lib/nodes/iec61850_goose.cpp +++ b/lib/nodes/iec61850_goose.cpp @@ -8,12 +8,12 @@ #include #include +#include #include #include -#include #include #include -#include +#include using namespace std::literals::chrono_literals; using namespace std::literals::string_literals; @@ -23,893 +23,853 @@ using namespace villas::node; using namespace villas::utils; using namespace villas::node::iec61850; -static -std::optional> stringToMac(char *mac_string) -{ - std::array mac; - char *save; - char *token = strtok_r(mac_string, ":", &save); +static std::optional> stringToMac(char *mac_string) { + std::array mac; + char *save; + char *token = strtok_r(mac_string, ":", &save); - for (auto &i : mac) { - if (!token) return std::nullopt; + for (auto &i : mac) { + if (!token) + return std::nullopt; - i = static_cast(strtol(token, NULL, 16)); + i = static_cast(strtol(token, NULL, 16)); - token = strtok_r(NULL, ":", &save); - } + token = strtok_r(NULL, ":", &save); + } - return std::optional { mac }; + return std::optional{mac}; } -MmsType GooseSignal::mmsType() const -{ - return descriptor->mms_type; +MmsType GooseSignal::mmsType() const { return descriptor->mms_type; } + +std::string const &GooseSignal::name() const { return descriptor->name; } + +SignalType GooseSignal::signalType() const { return descriptor->signal_type; } + +std::optional GooseSignal::fromMmsValue(MmsValue *mms_value) { + auto mms_type = MmsValue_getType(mms_value); + auto descriptor = lookupMmsType(mms_type); + SignalData data; + + if (!descriptor) + return std::nullopt; + + switch (mms_type) { + case MmsType::MMS_BOOLEAN: + data.b = MmsValue_getBoolean(mms_value); + break; + case MmsType::MMS_INTEGER: + data.i = MmsValue_toInt64(mms_value); + break; + case MmsType::MMS_UNSIGNED: + data.i = static_cast(MmsValue_toUint32(mms_value)); + break; + case MmsType::MMS_BIT_STRING: + data.i = static_cast(MmsValue_getBitStringAsInteger(mms_value)); + break; + case MmsType::MMS_FLOAT: + data.f = MmsValue_toDouble(mms_value); + break; + default: + return std::nullopt; + } + + return GooseSignal{descriptor.value(), data}; } -std::string const & GooseSignal::name() const -{ - return descriptor->name; +std::optional +GooseSignal::fromNameAndValue(char const *name, SignalData value, + std::optional meta) { + auto descriptor = lookupMmsTypeName(name); + + if (!descriptor) + return std::nullopt; + + return GooseSignal{descriptor.value(), value, meta}; } -SignalType GooseSignal::signalType() const -{ - return descriptor->signal_type; +MmsValue *GooseSignal::toMmsValue() const { + switch (descriptor->mms_type) { + case MmsType::MMS_BOOLEAN: + return MmsValue_newBoolean(signal_data.b); + case MmsType::MMS_INTEGER: + return newMmsInteger(signal_data.i, meta.size); + case MmsType::MMS_UNSIGNED: + return newMmsUnsigned(static_cast(signal_data.i), meta.size); + case MmsType::MMS_BIT_STRING: + return newMmsBitString(static_cast(signal_data.i), meta.size); + case MmsType::MMS_FLOAT: + return newMmsFloat(signal_data.f, meta.size); + default: + throw RuntimeError{"invalid mms type"}; + } } -std::optional GooseSignal::fromMmsValue(MmsValue *mms_value) -{ - auto mms_type = MmsValue_getType(mms_value); - auto descriptor = lookupMmsType(mms_type); - SignalData data; +MmsValue *GooseSignal::newMmsBitString(uint32_t i, int size) { + auto mms_bitstring = MmsValue_newBitString(size); - if (!descriptor) return std::nullopt; + MmsValue_setBitStringFromInteger(mms_bitstring, i); - switch (mms_type) { - case MmsType::MMS_BOOLEAN: - data.b = MmsValue_getBoolean(mms_value); - break; - case MmsType::MMS_INTEGER: - data.i = MmsValue_toInt64(mms_value); - break; - case MmsType::MMS_UNSIGNED: - data.i = static_cast(MmsValue_toUint32(mms_value)); - break; - case MmsType::MMS_BIT_STRING: - data.i = static_cast(MmsValue_getBitStringAsInteger(mms_value)); - break; - case MmsType::MMS_FLOAT: - data.f = MmsValue_toDouble(mms_value); - break; - default: - return std::nullopt; - } - - return GooseSignal { descriptor.value(), data }; + return mms_bitstring; } -std::optional GooseSignal::fromNameAndValue(char const *name, SignalData value, std::optional meta) -{ - auto descriptor = lookupMmsTypeName(name); +MmsValue *GooseSignal::newMmsInteger(int64_t i, int size) { + auto mms_integer = MmsValue_newInteger(size); - if (!descriptor) return std::nullopt; - - return GooseSignal { descriptor.value(), value, meta }; + switch (size) { + case 8: + MmsValue_setInt8(mms_integer, static_cast(i)); + return mms_integer; + case 16: + MmsValue_setInt16(mms_integer, static_cast(i)); + return mms_integer; + case 32: + MmsValue_setInt32(mms_integer, static_cast(i)); + return mms_integer; + case 64: + MmsValue_setInt64(mms_integer, static_cast(i)); + return mms_integer; + default: + throw RuntimeError{"invalid mms integer size"}; + } } -MmsValue * GooseSignal::toMmsValue() const -{ - switch (descriptor->mms_type) { - case MmsType::MMS_BOOLEAN: - return MmsValue_newBoolean(signal_data.b); - case MmsType::MMS_INTEGER: - return newMmsInteger(signal_data.i, meta.size); - case MmsType::MMS_UNSIGNED: - return newMmsUnsigned(static_cast(signal_data.i), meta.size); - case MmsType::MMS_BIT_STRING: - return newMmsBitString(static_cast(signal_data.i), meta.size); - case MmsType::MMS_FLOAT: - return newMmsFloat(signal_data.f, meta.size); - default: - throw RuntimeError { "invalid mms type" }; - } +MmsValue *GooseSignal::newMmsUnsigned(uint64_t u, int size) { + auto mms_unsigned = MmsValue_newUnsigned(size); + + switch (size) { + case 8: + MmsValue_setUint8(mms_unsigned, static_cast(u)); + return mms_unsigned; + case 16: + MmsValue_setUint16(mms_unsigned, static_cast(u)); + return mms_unsigned; + case 32: + MmsValue_setUint32(mms_unsigned, static_cast(u)); + return mms_unsigned; + default: + throw RuntimeError{"invalid mms integer size"}; + } } -MmsValue * GooseSignal::newMmsBitString(uint32_t i, int size) -{ - auto mms_bitstring = MmsValue_newBitString(size); - - MmsValue_setBitStringFromInteger(mms_bitstring, i); - - return mms_bitstring; +MmsValue *GooseSignal::newMmsFloat(double d, int size) { + switch (size) { + case 32: + return MmsValue_newFloat(static_cast(d)); + case 64: + return MmsValue_newDouble(d); + default: + throw RuntimeError{"invalid mms float size"}; + } } -MmsValue * GooseSignal::newMmsInteger(int64_t i, int size) -{ - auto mms_integer = MmsValue_newInteger(size); +std::optional GooseSignal::lookupMmsType(int mms_type) { + auto check = [mms_type](Descriptor descriptor) { + return descriptor.mms_type == mms_type; + }; - switch (size) { - case 8: - MmsValue_setInt8(mms_integer, static_cast(i)); - return mms_integer; - case 16: - MmsValue_setInt16(mms_integer, static_cast(i)); - return mms_integer; - case 32: - MmsValue_setInt32(mms_integer, static_cast(i)); - return mms_integer; - case 64: - MmsValue_setInt64(mms_integer, static_cast(i)); - return mms_integer; - default: - throw RuntimeError { "invalid mms integer size" }; - } + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return &*descriptor; + else + return std::nullopt; } -MmsValue * GooseSignal::newMmsUnsigned(uint64_t u, int size) -{ - auto mms_unsigned = MmsValue_newUnsigned(size); +std::optional +GooseSignal::lookupMmsTypeName(char const *name) { + auto check = [name](Descriptor descriptor) { + return descriptor.name == name; + }; - switch (size) { - case 8: - MmsValue_setUint8(mms_unsigned, static_cast(u)); - return mms_unsigned; - case 16: - MmsValue_setUint16(mms_unsigned, static_cast(u)); - return mms_unsigned; - case 32: - MmsValue_setUint32(mms_unsigned, static_cast(u)); - return mms_unsigned; - default: - throw RuntimeError { "invalid mms integer size" }; - } + auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); + if (descriptor != end(descriptors)) + return &*descriptor; + else + return std::nullopt; } -MmsValue * GooseSignal::newMmsFloat(double d, int size) -{ - switch (size) { - case 32: - return MmsValue_newFloat(static_cast(d)); - case 64: - return MmsValue_newDouble(d); - default: - throw RuntimeError { "invalid mms float size" }; - } -} - -std::optional GooseSignal::lookupMmsType(int mms_type) -{ - auto check = [mms_type] (Descriptor descriptor) { - return descriptor.mms_type == mms_type; - }; - - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return &*descriptor; - else - return std::nullopt; -} - -std::optional GooseSignal::lookupMmsTypeName(char const *name) -{ - auto check = [name] (Descriptor descriptor) { - return descriptor.name == name; - }; - - auto descriptor = std::find_if(begin(descriptors), end(descriptors), check); - if (descriptor != end(descriptors)) - return &*descriptor; - else - return std::nullopt; -} - -GooseSignal::GooseSignal(GooseSignal::Descriptor const *descriptor, SignalData data, std::optional meta) : - signal_data(data), - meta(meta.value_or(descriptor->default_meta)), - descriptor(descriptor) -{ -} +GooseSignal::GooseSignal(GooseSignal::Descriptor const *descriptor, + SignalData data, std::optional meta) + : signal_data(data), meta(meta.value_or(descriptor->default_meta)), + descriptor(descriptor) {} bool iec61850::operator==(GooseSignal &lhs, GooseSignal &rhs) { - if (lhs.mmsType() != rhs.mmsType()) - return false; + if (lhs.mmsType() != rhs.mmsType()) + return false; - switch (lhs.mmsType()) { - case MmsType::MMS_INTEGER: - case MmsType::MMS_UNSIGNED: - case MmsType::MMS_BIT_STRING: - case MmsType::MMS_FLOAT: - if (lhs.meta.size != rhs.meta.size) - return false; - break; - default: break; - } + switch (lhs.mmsType()) { + case MmsType::MMS_INTEGER: + case MmsType::MMS_UNSIGNED: + case MmsType::MMS_BIT_STRING: + case MmsType::MMS_FLOAT: + if (lhs.meta.size != rhs.meta.size) + return false; + break; + default: + break; + } - switch (lhs.signalType()) { - case SignalType::BOOLEAN: - return lhs.signal_data.b == rhs.signal_data.b; - case SignalType::INTEGER: - return lhs.signal_data.i == rhs.signal_data.i; - case SignalType::FLOAT: - return lhs.signal_data.f == rhs.signal_data.f; - default: - return false; - } + switch (lhs.signalType()) { + case SignalType::BOOLEAN: + return lhs.signal_data.b == rhs.signal_data.b; + case SignalType::INTEGER: + return lhs.signal_data.i == rhs.signal_data.i; + case SignalType::FLOAT: + return lhs.signal_data.f == rhs.signal_data.f; + default: + return false; + } } bool iec61850::operator!=(GooseSignal &lhs, GooseSignal &rhs) { - return !(lhs == rhs); + return !(lhs == rhs); } -void GooseNode::onEvent(GooseSubscriber subscriber, GooseNode::InputEventContext &ctx) noexcept -{ - if (!GooseSubscriber_isValid(subscriber) || GooseSubscriber_needsCommission(subscriber)) - return; +void GooseNode::onEvent(GooseSubscriber subscriber, + GooseNode::InputEventContext &ctx) noexcept { + if (!GooseSubscriber_isValid(subscriber) || + GooseSubscriber_needsCommission(subscriber)) + return; - int last_state_num = ctx.last_state_num; - int state_num = GooseSubscriber_getStNum(subscriber); - ctx.last_state_num = state_num; + int last_state_num = ctx.last_state_num; + int state_num = GooseSubscriber_getStNum(subscriber); + ctx.last_state_num = state_num; - if (ctx.subscriber_config.trigger == InputTrigger::CHANGE - && !ctx.values.empty() - && state_num == last_state_num) - return; + if (ctx.subscriber_config.trigger == InputTrigger::CHANGE && + !ctx.values.empty() && state_num == last_state_num) + return; - auto mms_values = GooseSubscriber_getDataSetValues(subscriber); + auto mms_values = GooseSubscriber_getDataSetValues(subscriber); - if (MmsValue_getType(mms_values) != MmsType::MMS_ARRAY) { - ctx.node->logger->warn("DataSet is not an array"); - return; - } + if (MmsValue_getType(mms_values) != MmsType::MMS_ARRAY) { + ctx.node->logger->warn("DataSet is not an array"); + return; + } - ctx.values.clear(); + ctx.values.clear(); - for (unsigned int i = 0; i < MmsValue_getArraySize(mms_values); i++) { - auto mms_value = MmsValue_getElement(mms_values, i); - auto goose_value = GooseSignal::fromMmsValue(mms_value); - ctx.values.push_back(goose_value); - } + for (unsigned int i = 0; i < MmsValue_getArraySize(mms_values); i++) { + auto mms_value = MmsValue_getElement(mms_values, i); + auto goose_value = GooseSignal::fromMmsValue(mms_value); + ctx.values.push_back(goose_value); + } - uint64_t timestamp = GooseSubscriber_getTimestamp(subscriber); + uint64_t timestamp = GooseSubscriber_getTimestamp(subscriber); - ctx.node->pushSample(timestamp); + ctx.node->pushSample(timestamp); } -void GooseNode::pushSample(uint64_t timestamp) noexcept -{ - Sample *sample = sample_alloc(&input.pool); - if (!sample) { - logger->warn("Pool underrun"); - return; - } +void GooseNode::pushSample(uint64_t timestamp) noexcept { + Sample *sample = sample_alloc(&input.pool); + if (!sample) { + logger->warn("Pool underrun"); + return; + } - sample->length = input.mappings.size(); - sample->flags = (int) SampleFlags::HAS_DATA; - sample->signals = getInputSignals(false); + sample->length = input.mappings.size(); + sample->flags = (int)SampleFlags::HAS_DATA; + sample->signals = getInputSignals(false); - if (input.with_timestamp) { - sample->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - sample->ts.origin.tv_sec = timestamp / 1000; - sample->ts.origin.tv_nsec = 1000 * (timestamp % 1000); - } + if (input.with_timestamp) { + sample->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + sample->ts.origin.tv_sec = timestamp / 1000; + sample->ts.origin.tv_nsec = 1000 * (timestamp % 1000); + } - for (unsigned int signal = 0; signal < sample->length; signal++) { - auto& mapping = input.mappings[signal]; - auto& values = input.contexts[mapping.subscriber].values; + for (unsigned int signal = 0; signal < sample->length; signal++) { + auto &mapping = input.mappings[signal]; + auto &values = input.contexts[mapping.subscriber].values; - if (mapping.index >= values.size() || !values[mapping.index]) { - auto signal_str = sample->signals->getByIndex(signal)->toString(); - logger->error("tried to access unavailable goose value for signal {}", signal_str); - continue; - } + if (mapping.index >= values.size() || !values[mapping.index]) { + auto signal_str = sample->signals->getByIndex(signal)->toString(); + logger->error("tried to access unavailable goose value for signal {}", + signal_str); + continue; + } - if (mapping.type->mms_type != values[mapping.index]->mmsType()) { - auto signal_str = sample->signals->getByIndex(signal)->toString(); - logger->error("received unexpected mms_type for signal {}", signal_str); - continue; - } + if (mapping.type->mms_type != values[mapping.index]->mmsType()) { + auto signal_str = sample->signals->getByIndex(signal)->toString(); + logger->error("received unexpected mms_type for signal {}", signal_str); + continue; + } - sample->data[signal] = values[mapping.index]->signal_data; - } + sample->data[signal] = values[mapping.index]->signal_data; + } - if (queue_signalled_push(&input.queue, sample) != 1) - logger->warn("Failed to enqueue samples"); + if (queue_signalled_push(&input.queue, sample) != 1) + logger->warn("Failed to enqueue samples"); } -void GooseNode::addSubscriber(GooseNode::InputEventContext &ctx) noexcept -{ - GooseSubscriber subscriber; - SubscriberConfig &sc = ctx.subscriber_config; +void GooseNode::addSubscriber(GooseNode::InputEventContext &ctx) noexcept { + GooseSubscriber subscriber; + SubscriberConfig &sc = ctx.subscriber_config; - ctx.node = this; + ctx.node = this; - subscriber = GooseSubscriber_create(sc.go_cb_ref.data(), NULL); + subscriber = GooseSubscriber_create(sc.go_cb_ref.data(), NULL); - if (sc.dst_address) - GooseSubscriber_setDstMac(subscriber, sc.dst_address->data()); + if (sc.dst_address) + GooseSubscriber_setDstMac(subscriber, sc.dst_address->data()); - if (sc.app_id) - GooseSubscriber_setAppId(subscriber, *sc.app_id); + if (sc.app_id) + GooseSubscriber_setAppId(subscriber, *sc.app_id); - GooseSubscriber_setListener(subscriber, [] (GooseSubscriber goose_subscriber, void* event_context) { - auto context = static_cast (event_context); - onEvent(goose_subscriber, *context); - }, &ctx); + GooseSubscriber_setListener( + subscriber, + [](GooseSubscriber goose_subscriber, void *event_context) { + auto context = static_cast(event_context); + onEvent(goose_subscriber, *context); + }, + &ctx); - GooseReceiver_addSubscriber(input.receiver, subscriber); + GooseReceiver_addSubscriber(input.receiver, subscriber); } -void GooseNode::createReceiver() noexcept -{ - destroyReceiver(); +void GooseNode::createReceiver() noexcept { + destroyReceiver(); - input.receiver = GooseReceiver_create(); + input.receiver = GooseReceiver_create(); - GooseReceiver_setInterfaceId(input.receiver, input.interface_id.c_str()); + GooseReceiver_setInterfaceId(input.receiver, input.interface_id.c_str()); - for (auto& pair_key_context : input.contexts) - addSubscriber(pair_key_context.second); + for (auto &pair_key_context : input.contexts) + addSubscriber(pair_key_context.second); - input.state = Input::READY; + input.state = Input::READY; } -void GooseNode::destroyReceiver() noexcept -{ - int err __attribute__((unused)); +void GooseNode::destroyReceiver() noexcept { + int err __attribute__((unused)); - if (input.state == Input::NONE) - return; + if (input.state == Input::NONE) + return; - stopReceiver(); + stopReceiver(); - GooseReceiver_destroy(input.receiver); + GooseReceiver_destroy(input.receiver); - err = queue_signalled_destroy(&input.queue); + err = queue_signalled_destroy(&input.queue); - input.state = Input::NONE; + input.state = Input::NONE; } -void GooseNode::startReceiver() noexcept(false) -{ - if (input.state == Input::NONE) - createReceiver(); - else - stopReceiver(); +void GooseNode::startReceiver() noexcept(false) { + if (input.state == Input::NONE) + createReceiver(); + else + stopReceiver(); - GooseReceiver_start(input.receiver); + GooseReceiver_start(input.receiver); - if (!GooseReceiver_isRunning(input.receiver)) - throw RuntimeError{"iec61850-GOOSE receiver could not be started"}; + if (!GooseReceiver_isRunning(input.receiver)) + throw RuntimeError{"iec61850-GOOSE receiver could not be started"}; - input.state = Input::READY; + input.state = Input::READY; } -void GooseNode::stopReceiver() noexcept -{ - if (input.state == Input::NONE) - return; +void GooseNode::stopReceiver() noexcept { + if (input.state == Input::NONE) + return; - input.state = Input::STOPPED; + input.state = Input::STOPPED; - if (!GooseReceiver_isRunning(input.receiver)) - return; + if (!GooseReceiver_isRunning(input.receiver)) + return; - GooseReceiver_stop(input.receiver); + GooseReceiver_stop(input.receiver); } -void GooseNode::createPublishers() noexcept -{ - destroyPublishers(); +void GooseNode::createPublishers() noexcept { + destroyPublishers(); - for (auto &ctx : output.contexts) { - auto dst_address = ctx.config.dst_address; - auto comm = CommParameters { - /* vlanPriority */ 0, - /* vlanId */ 0, - ctx.config.app_id, - {} - }; + for (auto &ctx : output.contexts) { + auto dst_address = ctx.config.dst_address; + auto comm = CommParameters{/* vlanPriority */ 0, + /* vlanId */ 0, + ctx.config.app_id, + {}}; - memcpy(comm.dstAddress, dst_address.data(), dst_address.size()); + memcpy(comm.dstAddress, dst_address.data(), dst_address.size()); - ctx.publisher = GoosePublisher_createEx(&comm, output.interface_id.c_str(), false); + ctx.publisher = + GoosePublisher_createEx(&comm, output.interface_id.c_str(), false); - GoosePublisher_setGoID(ctx.publisher, ctx.config.go_id.data()); - GoosePublisher_setGoCbRef(ctx.publisher, ctx.config.go_cb_ref.data()); - GoosePublisher_setDataSetRef(ctx.publisher, ctx.config.data_set_ref.data()); - GoosePublisher_setConfRev(ctx.publisher, ctx.config.conf_rev); - GoosePublisher_setTimeAllowedToLive(ctx.publisher, ctx.config.time_allowed_to_live); - } + GoosePublisher_setGoID(ctx.publisher, ctx.config.go_id.data()); + GoosePublisher_setGoCbRef(ctx.publisher, ctx.config.go_cb_ref.data()); + GoosePublisher_setDataSetRef(ctx.publisher, ctx.config.data_set_ref.data()); + GoosePublisher_setConfRev(ctx.publisher, ctx.config.conf_rev); + GoosePublisher_setTimeAllowedToLive(ctx.publisher, + ctx.config.time_allowed_to_live); + } - output.state = Output::READY; + output.state = Output::READY; } -void GooseNode::destroyPublishers() noexcept -{ - int err __attribute__((unused)); +void GooseNode::destroyPublishers() noexcept { + int err __attribute__((unused)); - if (output.state == Output::NONE) - return; + if (output.state == Output::NONE) + return; - stopPublishers(); + stopPublishers(); - for (auto &ctx : output.contexts) - GoosePublisher_destroy(ctx.publisher); + for (auto &ctx : output.contexts) + GoosePublisher_destroy(ctx.publisher); - output.state = Output::NONE; + output.state = Output::NONE; } -void GooseNode::startPublishers() noexcept(false) -{ - if (output.state == Output::NONE) - createPublishers(); - else - stopPublishers(); +void GooseNode::startPublishers() noexcept(false) { + if (output.state == Output::NONE) + createPublishers(); + else + stopPublishers(); - output.resend_thread_stop = false; - output.resend_thread = std::thread(resend_thread, &output); + output.resend_thread_stop = false; + output.resend_thread = std::thread(resend_thread, &output); - output.state = Output::READY; + output.state = Output::READY; } -void GooseNode::stopPublishers() noexcept -{ - if (output.state == Output::NONE) - return; +void GooseNode::stopPublishers() noexcept { + if (output.state == Output::NONE) + return; - if (output.resend_thread) { - auto lock = std::unique_lock { output.send_mutex }; - output.resend_thread_stop = true; - lock.unlock(); + if (output.resend_thread) { + auto lock = std::unique_lock{output.send_mutex}; + output.resend_thread_stop = true; + lock.unlock(); - output.resend_thread_cv.notify_all(); - output.resend_thread->join(); - output.resend_thread = std::nullopt; - } + output.resend_thread_cv.notify_all(); + output.resend_thread->join(); + output.resend_thread = std::nullopt; + } - output.state = Output::STOPPED; + output.state = Output::STOPPED; } -int GooseNode::_read(Sample *samples[], unsigned sample_count) -{ - int available_samples; - struct Sample *copies[sample_count]; +int GooseNode::_read(Sample *samples[], unsigned sample_count) { + int available_samples; + struct Sample *copies[sample_count]; - if (input.state != Input::READY) - return 0; + if (input.state != Input::READY) + return 0; - available_samples = queue_signalled_pull_many(&input.queue, (void **) copies, sample_count); - sample_copy_many(samples, copies, available_samples); - sample_decref_many(copies, available_samples); + available_samples = + queue_signalled_pull_many(&input.queue, (void **)copies, sample_count); + sample_copy_many(samples, copies, available_samples); + sample_decref_many(copies, available_samples); - return available_samples; + return available_samples; } -void GooseNode::publish_values(GoosePublisher publisher, std::vector &values, bool changed, int burst) noexcept -{ - auto data_set = LinkedList_create(); +void GooseNode::publish_values(GoosePublisher publisher, + std::vector &values, bool changed, + int burst) noexcept { + auto data_set = LinkedList_create(); - for (auto &value : values) { - LinkedList_add(data_set, value.toMmsValue()); - } + for (auto &value : values) { + LinkedList_add(data_set, value.toMmsValue()); + } - if (changed) - GoosePublisher_increaseStNum(publisher); + if (changed) + GoosePublisher_increaseStNum(publisher); - do { - GoosePublisher_publish(publisher, data_set); - } while (changed && --burst > 0); + do { + GoosePublisher_publish(publisher, data_set); + } while (changed && --burst > 0); - LinkedList_destroyDeep(data_set, (LinkedListValueDeleteFunction) MmsValue_delete); + LinkedList_destroyDeep(data_set, + (LinkedListValueDeleteFunction)MmsValue_delete); } -void GooseNode::resend_thread(GooseNode::Output *output) noexcept -{ - using namespace std::chrono; +void GooseNode::resend_thread(GooseNode::Output *output) noexcept { + using namespace std::chrono; - auto interval = duration_cast(duration(output->resend_interval)); - auto lock = std::unique_lock { output->send_mutex }; - time_point next_sample_time; + auto interval = duration_cast( + duration(output->resend_interval)); + auto lock = std::unique_lock{output->send_mutex}; + time_point next_sample_time; - // wait for the first GooseNode::_write call - output->resend_thread_cv.wait(lock); + // wait for the first GooseNode::_write call + output->resend_thread_cv.wait(lock); - while (!output->resend_thread_stop) { - if (output->changed) { - output->changed = false; - next_sample_time = steady_clock::now() + interval; - } + while (!output->resend_thread_stop) { + if (output->changed) { + output->changed = false; + next_sample_time = steady_clock::now() + interval; + } - auto status = output->resend_thread_cv.wait_until(lock, next_sample_time); + auto status = output->resend_thread_cv.wait_until(lock, next_sample_time); - if (status == std::cv_status::no_timeout || output->changed) - continue; + if (status == std::cv_status::no_timeout || output->changed) + continue; - for (auto &ctx : output->contexts) - publish_values(ctx.publisher, ctx.values, false); + for (auto &ctx : output->contexts) + publish_values(ctx.publisher, ctx.values, false); - next_sample_time = next_sample_time + interval; - } + next_sample_time = next_sample_time + interval; + } } -int GooseNode::_write(Sample *samples[], unsigned sample_count) -{ - auto lock = std::unique_lock { output.send_mutex }; +int GooseNode::_write(Sample *samples[], unsigned sample_count) { + auto lock = std::unique_lock{output.send_mutex}; - for (unsigned int i = 0; i < sample_count; i++) { - auto sample = samples[i]; + for (unsigned int i = 0; i < sample_count; i++) { + auto sample = samples[i]; - for (auto &ctx : output.contexts) { - bool changed = false; + for (auto &ctx : output.contexts) { + bool changed = false; - for (unsigned int data_index = 0; data_index < ctx.config.data.size(); data_index++) { - auto data = ctx.config.data[data_index]; - auto goose_value = data.default_value; - auto signal = data.signal; - if (signal && *signal < sample->length) - goose_value.signal_data = sample->data[*signal]; + for (unsigned int data_index = 0; data_index < ctx.config.data.size(); + data_index++) { + auto data = ctx.config.data[data_index]; + auto goose_value = data.default_value; + auto signal = data.signal; + if (signal && *signal < sample->length) + goose_value.signal_data = sample->data[*signal]; - if (ctx.values.size() <= data_index) { - changed = true; - ctx.values.push_back(goose_value); - } else if (ctx.values[data_index] != goose_value) { - changed = true; - ctx.values[data_index] = goose_value; - } - } + if (ctx.values.size() <= data_index) { + changed = true; + ctx.values.push_back(goose_value); + } else if (ctx.values[data_index] != goose_value) { + changed = true; + ctx.values[data_index] = goose_value; + } + } - if (changed) { - output.changed = true; - publish_values(ctx.publisher, ctx.values, changed, ctx.config.burst); - } - } - } + if (changed) { + output.changed = true; + publish_values(ctx.publisher, ctx.values, changed, ctx.config.burst); + } + } + } - if (output.changed) { - lock.unlock(); - output.resend_thread_cv.notify_all(); - } + if (output.changed) { + lock.unlock(); + output.resend_thread_cv.notify_all(); + } - return sample_count; + return sample_count; } -GooseNode::GooseNode(const uuid_t &id, const std::string &name) : - Node(id, name) -{ - input.state = Input::NONE; +GooseNode::GooseNode(const uuid_t &id, const std::string &name) + : Node(id, name) { + input.state = Input::NONE; - input.contexts = {}; - input.mappings = {}; - input.interface_id = "lo"; - input.queue_length = 1024; + input.contexts = {}; + input.mappings = {}; + input.interface_id = "lo"; + input.queue_length = 1024; - output.state = Output::NONE; - output.interface_id = "lo"; - output.changed = false; - output.resend_interval = 1.; - output.resend_thread = std::nullopt; + output.state = Output::NONE; + output.interface_id = "lo"; + output.changed = false; + output.resend_interval = 1.; + output.resend_thread = std::nullopt; } -GooseNode::~GooseNode() -{ - int err __attribute__((unused)); +GooseNode::~GooseNode() { + int err __attribute__((unused)); - destroyReceiver(); - destroyPublishers(); + destroyReceiver(); + destroyPublishers(); - err = queue_signalled_destroy(&input.queue); + err = queue_signalled_destroy(&input.queue); - err = pool_destroy(&input.pool); + err = pool_destroy(&input.pool); } -int GooseNode::parse(json_t *json) -{ - int ret; - json_error_t err; +int GooseNode::parse(json_t *json) { + int ret; + json_error_t err; - ret = Node::parse(json); - if (ret) - return ret; + ret = Node::parse(json); + if (ret) + return ret; - json_t *json_in = nullptr; - json_t *json_out = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o }", - "in", &json_in, - "out", &json_out - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_t *json_in = nullptr; + json_t *json_out = nullptr; + ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o }", "in", &json_in, "out", + &json_out); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - parseInput(json_in); - parseOutput(json_out); + parseInput(json_in); + parseOutput(json_out); - return 0; + return 0; } -void GooseNode::parseInput(json_t *json) -{ - int ret; - json_error_t err; +void GooseNode::parseInput(json_t *json) { + int ret; + json_error_t err; - json_t *json_subscribers = nullptr; - json_t *json_signals = nullptr; - char const *interface_id = input.interface_id.c_str(); - int with_timestamp = true; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o, s?: s, s: b }", - "subscribers", &json_subscribers, - "signals", &json_signals, - "interface", &interface_id, - "with_timestamp", &with_timestamp - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_t *json_subscribers = nullptr; + json_t *json_signals = nullptr; + char const *interface_id = input.interface_id.c_str(); + int with_timestamp = true; + ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o, s?: s, s: b }", + "subscribers", &json_subscribers, "signals", + &json_signals, "interface", &interface_id, + "with_timestamp", &with_timestamp); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - parseSubscribers(json_subscribers, input.contexts); - parseInputSignals(json_signals, input.mappings); + parseSubscribers(json_subscribers, input.contexts); + parseInputSignals(json_signals, input.mappings); - input.interface_id = interface_id; - input.with_timestamp = with_timestamp; + input.interface_id = interface_id; + input.with_timestamp = with_timestamp; } -void GooseNode::parseSubscriber(json_t *json, GooseNode::SubscriberConfig &sc) -{ - int ret; - json_error_t err; +void GooseNode::parseSubscriber(json_t *json, GooseNode::SubscriberConfig &sc) { + int ret; + json_error_t err; - char *go_cb_ref = nullptr; - char *dst_address_str = nullptr; - char *trigger = nullptr; - int app_id = 0; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: s, s?: s, s?: i }", - "go_cb_ref", &go_cb_ref, - "trigger", &trigger, - "dst_address", &dst_address_str, - "app_id", &app_id - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + char *go_cb_ref = nullptr; + char *dst_address_str = nullptr; + char *trigger = nullptr; + int app_id = 0; + ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: s, s?: s, s?: i }", + "go_cb_ref", &go_cb_ref, "trigger", &trigger, + "dst_address", &dst_address_str, "app_id", &app_id); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - sc.go_cb_ref = std::string { go_cb_ref }; + sc.go_cb_ref = std::string{go_cb_ref}; - if (!trigger || !strcmp(trigger, "always")) - sc.trigger = InputTrigger::ALWAYS; - else if (!strcmp(trigger, "change")) - sc.trigger = InputTrigger::CHANGE; - else - throw RuntimeError("Unknown trigger type"); + if (!trigger || !strcmp(trigger, "always")) + sc.trigger = InputTrigger::ALWAYS; + else if (!strcmp(trigger, "change")) + sc.trigger = InputTrigger::CHANGE; + else + throw RuntimeError("Unknown trigger type"); - if (dst_address_str) { - std::optional dst_address = stringToMac(dst_address_str); - if (!dst_address) - throw RuntimeError("Invalid dst_address"); - sc.dst_address = *dst_address; - } + if (dst_address_str) { + std::optional dst_address = stringToMac(dst_address_str); + if (!dst_address) + throw RuntimeError("Invalid dst_address"); + sc.dst_address = *dst_address; + } - if (app_id != 0) - sc.app_id = static_cast(app_id); + if (app_id != 0) + sc.app_id = static_cast(app_id); } -void GooseNode::parseSubscribers(json_t *json, std::map &ctx) -{ - char const* key; - json_t* json_subscriber; +void GooseNode::parseSubscribers( + json_t *json, std::map &ctx) { + char const *key; + json_t *json_subscriber; - if (!json_is_object(json)) - throw RuntimeError("subscribers is not an object"); + if (!json_is_object(json)) + throw RuntimeError("subscribers is not an object"); - json_object_foreach(json, key, json_subscriber) { - SubscriberConfig sc; + json_object_foreach(json, key, json_subscriber) { + SubscriberConfig sc; - parseSubscriber(json_subscriber, sc); + parseSubscriber(json_subscriber, sc); - ctx[key] = InputEventContext { sc }; - } + ctx[key] = InputEventContext{sc}; + } } -void GooseNode::parseInputSignals(json_t *json, std::vector &mappings) -{ - int ret; - json_error_t err; - int index; - json_t *value; +void GooseNode::parseInputSignals( + json_t *json, std::vector &mappings) { + int ret; + json_error_t err; + int index; + json_t *value; - mappings.clear(); + mappings.clear(); - json_array_foreach(json, index, value) { - char *mapping_subscriber; - unsigned int mapping_index; - char *mapping_type_name; - ret = json_unpack_ex(value, &err, 0, "{ s: s, s: i, s: s }", - "subscriber", &mapping_subscriber, - "index", &mapping_index, - "mms_type", &mapping_type_name - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_array_foreach(json, index, value) { + char *mapping_subscriber; + unsigned int mapping_index; + char *mapping_type_name; + ret = json_unpack_ex(value, &err, 0, "{ s: s, s: i, s: s }", "subscriber", + &mapping_subscriber, "index", &mapping_index, + "mms_type", &mapping_type_name); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - auto mapping_type = GooseSignal::lookupMmsTypeName(mapping_type_name).value(); + auto mapping_type = + GooseSignal::lookupMmsTypeName(mapping_type_name).value(); - mappings.push_back(InputMapping { - mapping_subscriber, - mapping_index, - mapping_type, - }); - } + mappings.push_back(InputMapping{ + mapping_subscriber, + mapping_index, + mapping_type, + }); + } } -void GooseNode::parseOutput(json_t *json) -{ - int ret; - json_error_t err; +void GooseNode::parseOutput(json_t *json) { + int ret; + json_error_t err; - json_t *json_publishers = nullptr; - json_t *json_signals = nullptr; - char const *interface_id = output.interface_id.c_str(); - ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o, s?: s, s?: f }", - "publishers", &json_publishers, - "signals", &json_signals, - "interface", &interface_id, - "resend_interval", &output.resend_interval - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_t *json_publishers = nullptr; + json_t *json_signals = nullptr; + char const *interface_id = output.interface_id.c_str(); + ret = json_unpack_ex(json, &err, 0, "{ s: o, s: o, s?: s, s?: f }", + "publishers", &json_publishers, "signals", &json_signals, + "interface", &interface_id, "resend_interval", + &output.resend_interval); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - parsePublishers(json_publishers, output.contexts); + parsePublishers(json_publishers, output.contexts); - output.interface_id = interface_id; + output.interface_id = interface_id; } -void GooseNode::parsePublisherData(json_t *json, std::vector &data) -{ - int ret; - json_error_t err; - int index; - json_t* json_signal_or_value; +void GooseNode::parsePublisherData(json_t *json, + std::vector &data) { + int ret; + json_error_t err; + int index; + json_t *json_signal_or_value; - if (!json_is_array(json)) - throw RuntimeError("publisher data is not an array"); + if (!json_is_array(json)) + throw RuntimeError("publisher data is not an array"); - json_array_foreach(json, index, json_signal_or_value) { - char const *mms_type = nullptr; - char const *signal_str = nullptr; - json_t *json_value = nullptr; - int bitstring_size = -1; - ret = json_unpack_ex(json_signal_or_value, &err, 0, "{ s: s, s?: s, s?: o, s?: i }", - "mms_type", &mms_type, - "signal", &signal_str, - "value", &json_value, - "mms_bitstring_size", &bitstring_size - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + json_array_foreach(json, index, json_signal_or_value) { + char const *mms_type = nullptr; + char const *signal_str = nullptr; + json_t *json_value = nullptr; + int bitstring_size = -1; + ret = json_unpack_ex(json_signal_or_value, &err, 0, + "{ s: s, s?: s, s?: o, s?: i }", "mms_type", &mms_type, + "signal", &signal_str, "value", &json_value, + "mms_bitstring_size", &bitstring_size); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - auto goose_type = GooseSignal::lookupMmsTypeName(mms_type).value(); - std::optional meta = std::nullopt; + auto goose_type = GooseSignal::lookupMmsTypeName(mms_type).value(); + std::optional meta = std::nullopt; - if (goose_type->mms_type == MmsType::MMS_BIT_STRING && bitstring_size != -1) - meta = {.size = bitstring_size}; + if (goose_type->mms_type == MmsType::MMS_BIT_STRING && bitstring_size != -1) + meta = {.size = bitstring_size}; - auto signal_data = SignalData {}; + auto signal_data = SignalData{}; - if (json_value) { - ret = signal_data.parseJson(goose_type->signal_type, json_value); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - } + if (json_value) { + ret = signal_data.parseJson(goose_type->signal_type, json_value); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + } - auto signal = std::optional {}; + auto signal = std::optional{}; - if (signal_str) - signal = out.signals->getIndexByName(signal_str); + if (signal_str) + signal = out.signals->getIndexByName(signal_str); - OutputData value = { - .signal = signal, - .default_value = GooseSignal { goose_type, signal_data, meta } - }; + OutputData value = {.signal = signal, + .default_value = + GooseSignal{goose_type, signal_data, meta}}; - data.push_back(value); - }; + data.push_back(value); + }; } -void GooseNode::parsePublisher(json_t *json, PublisherConfig &pc) -{ - int ret; - json_error_t err; +void GooseNode::parsePublisher(json_t *json, PublisherConfig &pc) { + int ret; + json_error_t err; - char *go_id = nullptr; - char *go_cb_ref = nullptr; - char *data_set_ref = nullptr; - char *dst_address_str = nullptr; - int app_id = 0; - int conf_rev = 0; - int time_allowed_to_live = 0; - int burst = 1; - json_t *json_data = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: s, s: s, s: i, s: i, s: i, s?: i, s: o }", - "go_id", &go_id, - "go_cb_ref", &go_cb_ref, - "data_set_ref", &data_set_ref, - "dst_address", &dst_address_str, - "app_id", &app_id, - "conf_rev", &conf_rev, - "time_allowed_to_live", &time_allowed_to_live, - "burst", &burst, - "data", &json_data - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-8-1"); + char *go_id = nullptr; + char *go_cb_ref = nullptr; + char *data_set_ref = nullptr; + char *dst_address_str = nullptr; + int app_id = 0; + int conf_rev = 0; + int time_allowed_to_live = 0; + int burst = 1; + json_t *json_data = nullptr; + ret = json_unpack_ex( + json, &err, 0, + "{ s: s, s: s, s: s, s: s, s: i, s: i, s: i, s?: i, s: o }", "go_id", + &go_id, "go_cb_ref", &go_cb_ref, "data_set_ref", &data_set_ref, + "dst_address", &dst_address_str, "app_id", &app_id, "conf_rev", &conf_rev, + "time_allowed_to_live", &time_allowed_to_live, "burst", &burst, "data", + &json_data); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-8-1"); - std::optional dst_address = stringToMac(dst_address_str); - if (!dst_address) - throw RuntimeError("Invalid dst_address"); + std::optional dst_address = stringToMac(dst_address_str); + if (!dst_address) + throw RuntimeError("Invalid dst_address"); - pc.go_id = std::string { go_id }; - pc.go_cb_ref = std::string { go_cb_ref }; - pc.data_set_ref = std::string { data_set_ref }; - pc.dst_address = *dst_address; - pc.app_id = app_id; - pc.conf_rev = conf_rev; - pc.time_allowed_to_live = time_allowed_to_live; - pc.burst = burst; + pc.go_id = std::string{go_id}; + pc.go_cb_ref = std::string{go_cb_ref}; + pc.data_set_ref = std::string{data_set_ref}; + pc.dst_address = *dst_address; + pc.app_id = app_id; + pc.conf_rev = conf_rev; + pc.time_allowed_to_live = time_allowed_to_live; + pc.burst = burst; - parsePublisherData(json_data, pc.data); + parsePublisherData(json_data, pc.data); } -void GooseNode::parsePublishers(json_t *json, std::vector &ctx) -{ - int index; - json_t* json_publisher; +void GooseNode::parsePublishers(json_t *json, std::vector &ctx) { + int index; + json_t *json_publisher; - json_array_foreach(json, index, json_publisher) { - PublisherConfig pc; + json_array_foreach(json, index, json_publisher) { + PublisherConfig pc; - parsePublisher(json_publisher, pc); + parsePublisher(json_publisher, pc); - ctx.push_back(OutputContext { pc }); - } + ctx.push_back(OutputContext{pc}); + } } -std::vector GooseNode::getPollFDs() -{ - return { queue_signalled_fd(&input.queue) }; +std::vector GooseNode::getPollFDs() { + return {queue_signalled_fd(&input.queue)}; } -int GooseNode::prepare() -{ - int ret; +int GooseNode::prepare() { + int ret; - ret = pool_init(&input.pool, input.queue_length, SAMPLE_LENGTH(getInputSignals(false)->size())); - if (ret) return ret; + ret = pool_init(&input.pool, input.queue_length, + SAMPLE_LENGTH(getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&input.queue, input.queue_length); - if (ret) return ret; + ret = queue_signalled_init(&input.queue, input.queue_length); + if (ret) + return ret; - return Node::prepare(); + return Node::prepare(); } -int GooseNode::start() -{ - if (in.enabled) - startReceiver(); +int GooseNode::start() { + if (in.enabled) + startReceiver(); - if (out.enabled) - startPublishers(); + if (out.enabled) + startPublishers(); - return Node::start(); + return Node::start(); } -int GooseNode::stop() -{ - int err __attribute__((unused)); +int GooseNode::stop() { + int err __attribute__((unused)); - stopReceiver(); - stopPublishers(); + stopReceiver(); + stopPublishers(); - err = queue_signalled_close(&input.queue); + err = queue_signalled_close(&input.queue); - return Node::stop(); + return Node::stop(); } // Register node static char name[] = "iec61850-8-1"; static char description[] = "IEC 61850-8-1 (GOOSE)"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/iec61850_sv.cpp b/lib/nodes/iec61850_sv.cpp index 6b531aef4..64a1c8465 100644 --- a/lib/nodes/iec61850_sv.cpp +++ b/lib/nodes/iec61850_sv.cpp @@ -9,10 +9,10 @@ #include #include -#include -#include #include +#include #include +#include #define CONFIG_SV_DEFAULT_APPID 0x4000 #define CONFIG_SV_DEFAULT_DST_ADDRESS CONFIG_GOOSE_DEFAULT_DST_ADDRESS @@ -23,27 +23,28 @@ using namespace villas; using namespace villas::utils; using namespace villas::node; -static -void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, SVSubscriber_ASDU asdu) -{ - auto *n = (NodeCompat *) ctx; - auto *i = n->getData(); - struct Sample *smp; +static void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, + SVSubscriber_ASDU asdu) { + auto *n = (NodeCompat *)ctx; + auto *i = n->getData(); + struct Sample *smp; - const char* svid = SVSubscriber_ASDU_getSvId(asdu); - int smpcnt = SVSubscriber_ASDU_getSmpCnt(asdu); - int confrev = SVSubscriber_ASDU_getConfRev(asdu); - int sz; + const char *svid = SVSubscriber_ASDU_getSvId(asdu); + int smpcnt = SVSubscriber_ASDU_getSmpCnt(asdu); + int confrev = SVSubscriber_ASDU_getConfRev(asdu); + int sz; - n->logger->debug("Received SV: svid={}, smpcnt={}, confrev={}", svid, smpcnt, confrev); + n->logger->debug("Received SV: svid={}, smpcnt={}, confrev={}", svid, smpcnt, + confrev); - sz = SVSubscriber_ASDU_getDataSize(asdu); - if (sz < i->in.total_size) { - n->logger->warn("Received truncated ASDU: size={}, expected={}", SVSubscriber_ASDU_getDataSize(asdu), i->in.total_size); - return; - } + sz = SVSubscriber_ASDU_getDataSize(asdu); + if (sz < i->in.total_size) { + n->logger->warn("Received truncated ASDU: size={}, expected={}", + SVSubscriber_ASDU_getDataSize(asdu), i->in.total_size); + return; + } - /* Access to the data requires a priori knowledge of the data set. + /* Access to the data requires a priori knowledge of the data set. * For this example we assume a data set consisting of FLOAT32 values. * A FLOAT32 value is encoded as 4 bytes. You can find the first FLOAT32 * value at byte position 0, the second value at byte position 4, the third @@ -53,434 +54,438 @@ void iec61850_sv_listener(SVSubscriber subscriber, void *ctx, SVSubscriber_ASDU * data block of the SV message before accessing the data. */ - smp = sample_alloc(&i->in.pool); - if (!smp) { - n->logger->warn("Pool underrun in subscriber"); - return; - } + smp = sample_alloc(&i->in.pool); + if (!smp) { + n->logger->warn("Pool underrun in subscriber"); + return; + } - smp->sequence = smpcnt; - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; - smp->length = 0; - smp->signals = n->getInputSignals(false); + smp->sequence = smpcnt; + smp->flags = (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA; + smp->length = 0; + smp->signals = n->getInputSignals(false); - if (SVSubscriber_ASDU_hasRefrTm(asdu)) { - uint64_t refrtm = SVSubscriber_ASDU_getRefrTmAsMs(asdu); + if (SVSubscriber_ASDU_hasRefrTm(asdu)) { + uint64_t refrtm = SVSubscriber_ASDU_getRefrTmAsMs(asdu); - smp->ts.origin.tv_sec = refrtm / 1000; - smp->ts.origin.tv_nsec = (refrtm % 1000) * 1000000; - smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN; - } + smp->ts.origin.tv_sec = refrtm / 1000; + smp->ts.origin.tv_nsec = (refrtm % 1000) * 1000000; + smp->flags |= (int)SampleFlags::HAS_TS_ORIGIN; + } - unsigned offset = 0; - for (size_t j = 0; j < list_length(&i->in.signals); j++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) list_at(&i->in.signals, j); - auto sig = smp->signals->getByIndex(j); - if (!sig) - continue; + unsigned offset = 0; + for (size_t j = 0; j < list_length(&i->in.signals); j++) { + struct iec61850_type_descriptor *td = + (struct iec61850_type_descriptor *)list_at(&i->in.signals, j); + auto sig = smp->signals->getByIndex(j); + if (!sig) + continue; - switch (td->iec_type) { - case IEC61850Type::INT8: - smp->data[j].i = SVSubscriber_ASDU_getINT8(asdu, offset); - break; + switch (td->iec_type) { + case IEC61850Type::INT8: + smp->data[j].i = SVSubscriber_ASDU_getINT8(asdu, offset); + break; - case IEC61850Type::INT16: - smp->data[j].i = SVSubscriber_ASDU_getINT16(asdu, offset); - break; + case IEC61850Type::INT16: + smp->data[j].i = SVSubscriber_ASDU_getINT16(asdu, offset); + break; - case IEC61850Type::INT32: - smp->data[j].i = SVSubscriber_ASDU_getINT32(asdu, offset); - break; + case IEC61850Type::INT32: + smp->data[j].i = SVSubscriber_ASDU_getINT32(asdu, offset); + break; - case IEC61850Type::INT8U: - smp->data[j].i = SVSubscriber_ASDU_getINT8U(asdu, offset); - break; + case IEC61850Type::INT8U: + smp->data[j].i = SVSubscriber_ASDU_getINT8U(asdu, offset); + break; - case IEC61850Type::INT16U: - smp->data[j].i = SVSubscriber_ASDU_getINT16U(asdu, offset); - break; + case IEC61850Type::INT16U: + smp->data[j].i = SVSubscriber_ASDU_getINT16U(asdu, offset); + break; - case IEC61850Type::INT32U: - smp->data[j].i = SVSubscriber_ASDU_getINT32U(asdu, offset); - break; + case IEC61850Type::INT32U: + smp->data[j].i = SVSubscriber_ASDU_getINT32U(asdu, offset); + break; - case IEC61850Type::FLOAT32: - smp->data[j].f = SVSubscriber_ASDU_getFLOAT32(asdu, offset); - break; + case IEC61850Type::FLOAT32: + smp->data[j].f = SVSubscriber_ASDU_getFLOAT32(asdu, offset); + break; - case IEC61850Type::FLOAT64: - smp->data[j].f = SVSubscriber_ASDU_getFLOAT64(asdu, offset); - break; + case IEC61850Type::FLOAT64: + smp->data[j].f = SVSubscriber_ASDU_getFLOAT64(asdu, offset); + break; - default: { } - } + default: { + } + } - offset += td->size; + offset += td->size; - smp->length++; - } + smp->length++; + } - int pushed __attribute__((unused)); - pushed = queue_signalled_push(&i->in.queue, smp); + int pushed __attribute__((unused)); + pushed = queue_signalled_push(&i->in.queue, smp); } -int villas::node::iec61850_sv_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *i = n->getData(); +int villas::node::iec61850_sv_parse(NodeCompat *n, json_t *json) { + int ret; + auto *i = n->getData(); - const char *dst_address = nullptr; - const char *interface = nullptr; - const char *svid = nullptr; - const char *smpmod = nullptr; + const char *dst_address = nullptr; + const char *interface = nullptr; + const char *svid = nullptr; + const char *smpmod = nullptr; - json_t *json_in = nullptr; - json_t *json_out = nullptr; - json_t *json_signals = nullptr; - json_error_t err; + json_t *json_in = nullptr; + json_t *json_out = nullptr; + json_t *json_signals = nullptr; + json_error_t err; - // Default values - i->out.enabled = false; - i->in.enabled = false; - i->out.smpmod = -1; // do not set smpmod - i->out.smprate = -1; // do not set smpmod - i->out.confrev = 1; - i->out.vlan_priority = CONFIG_SV_DEFAULT_PRIORITY; - i->out.vlan_id = CONFIG_SV_DEFAULT_VLAN_ID; + // Default values + i->out.enabled = false; + i->in.enabled = false; + i->out.smpmod = -1; // do not set smpmod + i->out.smprate = -1; // do not set smpmod + i->out.confrev = 1; + i->out.vlan_priority = CONFIG_SV_DEFAULT_PRIORITY; + i->out.vlan_id = CONFIG_SV_DEFAULT_VLAN_ID; - i->app_id = CONFIG_SV_DEFAULT_APPID; + i->app_id = CONFIG_SV_DEFAULT_APPID; - uint8_t tmp[] = CONFIG_SV_DEFAULT_DST_ADDRESS; - memcpy(i->dst_address.ether_addr_octet, tmp, sizeof(i->dst_address.ether_addr_octet)); + uint8_t tmp[] = CONFIG_SV_DEFAULT_DST_ADDRESS; + memcpy(i->dst_address.ether_addr_octet, tmp, + sizeof(i->dst_address.ether_addr_octet)); - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s: s, s?: i, s?: s }", - "out", &json_out, - "in", &json_in, - "interface", &interface, - "app_id", &i->app_id, - "dst_address", &dst_address - ); - if (ret) - throw ConfigError(json, err, "node-config-node-iec61850-sv"); + ret = + json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s: s, s?: i, s?: s }", + "out", &json_out, "in", &json_in, "interface", &interface, + "app_id", &i->app_id, "dst_address", &dst_address); + if (ret) + throw ConfigError(json, err, "node-config-node-iec61850-sv"); - if (interface) - i->interface = strdup(interface); + if (interface) + i->interface = strdup(interface); - if (dst_address) - ether_aton_r(dst_address, &i->dst_address); + if (dst_address) + ether_aton_r(dst_address, &i->dst_address); - if (json_out) { - i->out.enabled = true; + if (json_out) { + i->out.enabled = true; - ret = json_unpack_ex(json_out, &err, 0, "{ s: o, s: s, s?: i, s?: s, s?: i, s?: i, s?: i }", - "signals", &json_signals, - "svid", &svid, - "confrev", &i->out.confrev, - "smpmod", &smpmod, - "smprate", &i->out.smprate, - "vlan_id", &i->out.vlan_id, - "vlan_priority", &i->out.vlan_priority - ); - if (ret) - throw ConfigError(json_out, err, "node-config-node-iec61850-sv-out"); + ret = json_unpack_ex( + json_out, &err, 0, "{ s: o, s: s, s?: i, s?: s, s?: i, s?: i, s?: i }", + "signals", &json_signals, "svid", &svid, "confrev", &i->out.confrev, + "smpmod", &smpmod, "smprate", &i->out.smprate, "vlan_id", + &i->out.vlan_id, "vlan_priority", &i->out.vlan_priority); + if (ret) + throw ConfigError(json_out, err, "node-config-node-iec61850-sv-out"); - if (smpmod) { - if (!strcmp(smpmod, "per_nominal_period")) - i->out.smpmod = IEC61850_SV_SMPMOD_PER_NOMINAL_PERIOD; - else if (!strcmp(smpmod, "samples_per_second")) - i->out.smpmod = IEC61850_SV_SMPMOD_SAMPLES_PER_SECOND; - else if (!strcmp(smpmod, "seconds_per_sample")) - i->out.smpmod = IEC61850_SV_SMPMOD_SECONDS_PER_SAMPLE; - else - throw RuntimeError("Invalid value '{}' for setting 'smpmod'", smpmod); - } + if (smpmod) { + if (!strcmp(smpmod, "per_nominal_period")) + i->out.smpmod = IEC61850_SV_SMPMOD_PER_NOMINAL_PERIOD; + else if (!strcmp(smpmod, "samples_per_second")) + i->out.smpmod = IEC61850_SV_SMPMOD_SAMPLES_PER_SECOND; + else if (!strcmp(smpmod, "seconds_per_sample")) + i->out.smpmod = IEC61850_SV_SMPMOD_SECONDS_PER_SAMPLE; + else + throw RuntimeError("Invalid value '{}' for setting 'smpmod'", smpmod); + } - i->out.svid = svid ? strdup(svid) : nullptr; + i->out.svid = svid ? strdup(svid) : nullptr; - ret = iec61850_parse_signals(json_signals, &i->out.signals, n->getOutputSignals()); - if (ret <= 0) - throw RuntimeError("Failed to parse setting 'signals'"); + ret = iec61850_parse_signals(json_signals, &i->out.signals, + n->getOutputSignals()); + if (ret <= 0) + throw RuntimeError("Failed to parse setting 'signals'"); - i->out.total_size = ret; - } + i->out.total_size = ret; + } - if (json_in) { - i->in.enabled = true; + if (json_in) { + i->in.enabled = true; - json_signals = nullptr; - ret = json_unpack_ex(json_in, &err, 0, "{ s: o }", - "signals", &json_signals - ); - if (ret) - throw ConfigError(json_in, err, "node-config-node-iec61850-in"); + json_signals = nullptr; + ret = + json_unpack_ex(json_in, &err, 0, "{ s: o }", "signals", &json_signals); + if (ret) + throw ConfigError(json_in, err, "node-config-node-iec61850-in"); - ret = iec61850_parse_signals(json_signals, &i->in.signals, n->getInputSignals(false)); - if (ret <= 0) - throw RuntimeError("Failed to parse setting 'signals'"); + ret = iec61850_parse_signals(json_signals, &i->in.signals, + n->getInputSignals(false)); + if (ret <= 0) + throw RuntimeError("Failed to parse setting 'signals'"); - i->in.total_size = ret; - } + i->in.total_size = ret; + } - return 0; + return 0; } -char * villas::node::iec61850_sv_print(NodeCompat *n) -{ - char *buf; - auto *i = n->getData(); +char *villas::node::iec61850_sv_print(NodeCompat *n) { + char *buf; + auto *i = n->getData(); - buf = strf("interface=%s, app_id=%#x, dst_address=%s", i->interface, i->app_id, ether_ntoa(&i->dst_address)); + buf = strf("interface=%s, app_id=%#x, dst_address=%s", i->interface, + i->app_id, ether_ntoa(&i->dst_address)); - // Publisher part - if (i->out.enabled) { - strcatf(&buf, ", pub.svid=%s, pub.vlan_prio=%d, pub.vlan_id=%#x, pub.confrev=%d, pub.#fields=%zu", - i->out.svid, - i->out.vlan_priority, - i->out.vlan_id, - i->out.confrev, - n->getOutputSignals()->size() - ); - } + // Publisher part + if (i->out.enabled) { + strcatf(&buf, + ", pub.svid=%s, pub.vlan_prio=%d, pub.vlan_id=%#x, pub.confrev=%d, " + "pub.#fields=%zu", + i->out.svid, i->out.vlan_priority, i->out.vlan_id, i->out.confrev, + n->getOutputSignals()->size()); + } - // Subscriber part - if (i->in.enabled) - strcatf(&buf, ", sub.#fields=%zu", list_length(&i->in.signals)); + // Subscriber part + if (i->in.enabled) + strcatf(&buf, ", sub.#fields=%zu", list_length(&i->in.signals)); - return buf; + return buf; } -int villas::node::iec61850_sv_start(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::iec61850_sv_start(NodeCompat *n) { + int ret; + auto *i = n->getData(); - // Initialize publisher - if (i->out.enabled) { - i->out.publisher = SVPublisher_create(nullptr, i->interface); - i->out.asdu = SVPublisher_addASDU(i->out.publisher, i->out.svid, n->getNameShort().c_str(), i->out.confrev); + // Initialize publisher + if (i->out.enabled) { + i->out.publisher = SVPublisher_create(nullptr, i->interface); + i->out.asdu = + SVPublisher_addASDU(i->out.publisher, i->out.svid, + n->getNameShort().c_str(), i->out.confrev); - for (unsigned k = 0; k < list_length(&i->out.signals); k++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) list_at(&i->out.signals, k); + for (unsigned k = 0; k < list_length(&i->out.signals); k++) { + struct iec61850_type_descriptor *td = + (struct iec61850_type_descriptor *)list_at(&i->out.signals, k); - switch (td->iec_type) { - case IEC61850Type::INT8: - SVPublisher_ASDU_addINT8(i->out.asdu); - break; + switch (td->iec_type) { + case IEC61850Type::INT8: + SVPublisher_ASDU_addINT8(i->out.asdu); + break; - case IEC61850Type::INT32: - SVPublisher_ASDU_addINT32(i->out.asdu); - break; + case IEC61850Type::INT32: + SVPublisher_ASDU_addINT32(i->out.asdu); + break; - case IEC61850Type::FLOAT32: - SVPublisher_ASDU_addFLOAT(i->out.asdu); - break; + case IEC61850Type::FLOAT32: + SVPublisher_ASDU_addFLOAT(i->out.asdu); + break; - case IEC61850Type::FLOAT64: - SVPublisher_ASDU_addFLOAT64(i->out.asdu); - break; + case IEC61850Type::FLOAT64: + SVPublisher_ASDU_addFLOAT64(i->out.asdu); + break; - default: { } - } - } + default: { + } + } + } - if (i->out.smpmod >= 0) - SVPublisher_ASDU_setSmpMod(i->out.asdu, i->out.smpmod); + if (i->out.smpmod >= 0) + SVPublisher_ASDU_setSmpMod(i->out.asdu, i->out.smpmod); - SVPublisher_ASDU_enableRefrTm(i->out.asdu); + SVPublisher_ASDU_enableRefrTm(i->out.asdu); -// if (s->out.smprate >= 0) -// SV_ASDU_setSmpRate(i->out.asdu, i->out.smprate); + // if (s->out.smprate >= 0) + // SV_ASDU_setSmpRate(i->out.asdu, i->out.smprate); - // Start publisher - SVPublisher_setupComplete(i->out.publisher); - } + // Start publisher + SVPublisher_setupComplete(i->out.publisher); + } - // Start subscriber - if (i->in.enabled) { - struct iec61850_receiver *r = iec61850_receiver_create(iec61850_receiver::Type::SAMPLED_VALUES, i->interface); + // Start subscriber + if (i->in.enabled) { + struct iec61850_receiver *r = iec61850_receiver_create( + iec61850_receiver::Type::SAMPLED_VALUES, i->interface); - i->in.receiver = r->sv; - i->in.subscriber = SVSubscriber_create(i->dst_address.ether_addr_octet, i->app_id); + i->in.receiver = r->sv; + i->in.subscriber = + SVSubscriber_create(i->dst_address.ether_addr_octet, i->app_id); - // Install a callback handler for the subscriber - SVSubscriber_setListener(i->in.subscriber, iec61850_sv_listener, n); + // Install a callback handler for the subscriber + SVSubscriber_setListener(i->in.subscriber, iec61850_sv_listener, n); - // Connect the subscriber to the receiver - SVReceiver_addSubscriber(i->in.receiver, i->in.subscriber); + // Connect the subscriber to the receiver + SVReceiver_addSubscriber(i->in.receiver, i->in.subscriber); - // Initialize pool and queue to pass samples between threads - ret = pool_init(&i->in.pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + // Initialize pool and queue to pass samples between threads + ret = pool_init(&i->in.pool, 1024, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&i->in.queue, 1024); - if (ret) - return ret; + ret = queue_signalled_init(&i->in.queue, 1024); + if (ret) + return ret; - for (unsigned k = 0; k < list_length(&i->in.signals); k++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) list_at(&i->in.signals, k); - auto sig = n->getInputSignals(false)->getByIndex(k); + for (unsigned k = 0; k < list_length(&i->in.signals); k++) { + struct iec61850_type_descriptor *td = + (struct iec61850_type_descriptor *)list_at(&i->in.signals, k); + auto sig = n->getInputSignals(false)->getByIndex(k); - if (sig->type == SignalType::INVALID) - sig->type = td->type; - else if (sig->type != td->type) - return -1; - } - } + if (sig->type == SignalType::INVALID) + sig->type = td->type; + else if (sig->type != td->type) + return -1; + } + } - return 0; + return 0; } -int villas::node::iec61850_sv_stop(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::iec61850_sv_stop(NodeCompat *n) { + int ret; + auto *i = n->getData(); - if (i->in.enabled) - SVReceiver_removeSubscriber(i->in.receiver, i->in.subscriber); + if (i->in.enabled) + SVReceiver_removeSubscriber(i->in.receiver, i->in.subscriber); - ret = queue_signalled_close(&i->in.queue); - if (ret) - return ret; + ret = queue_signalled_close(&i->in.queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::iec61850_sv_destroy(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::iec61850_sv_destroy(NodeCompat *n) { + int ret; + auto *i = n->getData(); - // Deinitialize publisher - if (i->out.enabled && i->out.publisher) - SVPublisher_destroy(i->out.publisher); + // Deinitialize publisher + if (i->out.enabled && i->out.publisher) + SVPublisher_destroy(i->out.publisher); - // Deinitialise subscriber - if (i->in.enabled) { - ret = queue_signalled_destroy(&i->in.queue); - if (ret) - return ret; + // Deinitialise subscriber + if (i->in.enabled) { + ret = queue_signalled_destroy(&i->in.queue); + if (ret) + return ret; - ret = pool_destroy(&i->in.pool); - if (ret) - return ret; - } + ret = pool_destroy(&i->in.pool); + if (ret) + return ret; + } - return 0; + return 0; } -int villas::node::iec61850_sv_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int pulled; - auto *i = n->getData(); - struct Sample *smpt[cnt]; +int villas::node::iec61850_sv_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int pulled; + auto *i = n->getData(); + struct Sample *smpt[cnt]; - if (!i->in.enabled) - return -1; + if (!i->in.enabled) + return -1; - pulled = queue_signalled_pull_many(&i->in.queue, (void **) smpt, cnt); + pulled = queue_signalled_pull_many(&i->in.queue, (void **)smpt, cnt); - sample_copy_many(smps, smpt, pulled); - sample_decref_many(smpt, pulled); + sample_copy_many(smps, smpt, pulled); + sample_decref_many(smpt, pulled); - return pulled; + return pulled; } -int villas::node::iec61850_sv_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *i = n->getData(); +int villas::node::iec61850_sv_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *i = n->getData(); - if (!i->out.enabled) - return -1; + if (!i->out.enabled) + return -1; - for (unsigned j = 0; j < cnt; j++) { - unsigned offset = 0; - for (unsigned k = 0; k < MIN(smps[j]->length, list_length(&i->out.signals)); k++) { - struct iec61850_type_descriptor *td = (struct iec61850_type_descriptor *) list_at(&i->out.signals, k); + for (unsigned j = 0; j < cnt; j++) { + unsigned offset = 0; + for (unsigned k = 0; k < MIN(smps[j]->length, list_length(&i->out.signals)); + k++) { + struct iec61850_type_descriptor *td = + (struct iec61850_type_descriptor *)list_at(&i->out.signals, k); - int ival = 0; - double fval = 0; + int ival = 0; + double fval = 0; - switch (td->iec_type) { - case IEC61850Type::INT8: - case IEC61850Type::INT32: - ival = sample_format(smps[j], k) == SignalType::FLOAT ? smps[j]->data[k].f : smps[j]->data[k].i; - break; + switch (td->iec_type) { + case IEC61850Type::INT8: + case IEC61850Type::INT32: + ival = sample_format(smps[j], k) == SignalType::FLOAT + ? smps[j]->data[k].f + : smps[j]->data[k].i; + break; - case IEC61850Type::FLOAT32: - case IEC61850Type::FLOAT64: - fval = sample_format(smps[j], k) == SignalType::FLOAT ? smps[j]->data[k].f : smps[j]->data[k].i; - break; + case IEC61850Type::FLOAT32: + case IEC61850Type::FLOAT64: + fval = sample_format(smps[j], k) == SignalType::FLOAT + ? smps[j]->data[k].f + : smps[j]->data[k].i; + break; - default: { } - } + default: { + } + } - switch (td->iec_type) { - case IEC61850Type::INT8: - SVPublisher_ASDU_setINT8(i->out.asdu, offset, ival); - break; + switch (td->iec_type) { + case IEC61850Type::INT8: + SVPublisher_ASDU_setINT8(i->out.asdu, offset, ival); + break; - case IEC61850Type::INT32: - SVPublisher_ASDU_setINT32(i->out.asdu, offset, ival); - break; + case IEC61850Type::INT32: + SVPublisher_ASDU_setINT32(i->out.asdu, offset, ival); + break; - case IEC61850Type::FLOAT32: - SVPublisher_ASDU_setFLOAT(i->out.asdu, offset, fval); - break; + case IEC61850Type::FLOAT32: + SVPublisher_ASDU_setFLOAT(i->out.asdu, offset, fval); + break; - case IEC61850Type::FLOAT64: - SVPublisher_ASDU_setFLOAT64(i->out.asdu, offset, fval); - break; + case IEC61850Type::FLOAT64: + SVPublisher_ASDU_setFLOAT64(i->out.asdu, offset, fval); + break; - default: { } - } + default: { + } + } - offset += td->size; - } + offset += td->size; + } - SVPublisher_ASDU_setSmpCnt(i->out.asdu, smps[j]->sequence); + SVPublisher_ASDU_setSmpCnt(i->out.asdu, smps[j]->sequence); - if (smps[j]->flags & (int) SampleFlags::HAS_TS_ORIGIN) { - uint64_t refrtm = smps[j]->ts.origin.tv_sec * 1000 + smps[j]->ts.origin.tv_nsec / 1000000; + if (smps[j]->flags & (int)SampleFlags::HAS_TS_ORIGIN) { + uint64_t refrtm = smps[j]->ts.origin.tv_sec * 1000 + + smps[j]->ts.origin.tv_nsec / 1000000; - SVPublisher_ASDU_setRefrTm(i->out.asdu, refrtm); - } + SVPublisher_ASDU_setRefrTm(i->out.asdu, refrtm); + } - SVPublisher_publish(i->out.publisher); - } + SVPublisher_publish(i->out.publisher); + } - return cnt; + return cnt; } -int villas::node::iec61850_sv_poll_fds(NodeCompat *n, int fds[]) -{ - auto *i = n->getData(); +int villas::node::iec61850_sv_poll_fds(NodeCompat *n, int fds[]) { + auto *i = n->getData(); - fds[0] = queue_signalled_fd(&i->in.queue); + fds[0] = queue_signalled_fd(&i->in.queue); - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "iec61850-9-2"; - p.description = "IEC 61850-9-2 (Sampled Values)"; - p.vectorize = 0; - p.size = sizeof(struct iec61850_sv); - p.type.start = iec61850_type_start; - p.type.stop = iec61850_type_stop; - p.destroy = iec61850_sv_destroy; - p.parse = iec61850_sv_parse; - p.print = iec61850_sv_print; - p.start = iec61850_sv_start; - p.stop = iec61850_sv_stop; - p.read = iec61850_sv_read; - p.write = iec61850_sv_write; - p.poll_fds = iec61850_sv_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "iec61850-9-2"; + p.description = "IEC 61850-9-2 (Sampled Values)"; + p.vectorize = 0; + p.size = sizeof(struct iec61850_sv); + p.type.start = iec61850_type_start; + p.type.stop = iec61850_type_stop; + p.destroy = iec61850_sv_destroy; + p.parse = iec61850_sv_parse; + p.print = iec61850_sv_print; + p.start = iec61850_sv_start; + p.stop = iec61850_sv_stop; + p.read = iec61850_sv_read; + p.write = iec61850_sv_write; + p.poll_fds = iec61850_sv_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/infiniband.cpp b/lib/nodes/infiniband.cpp index 48c161567..032d7f864 100644 --- a/lib/nodes/infiniband.cpp +++ b/lib/nodes/infiniband.cpp @@ -5,403 +5,386 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include #include +#include +#include #include +#include #include #include -#include -#include -#include #include -#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -int ib_disconnect(NodeCompat *n) -{ - auto *ib = n->getData(); - struct ibv_wc wc[MAX(ib->recv_cq_size, ib->send_cq_size)]; - int wcs; +static int ib_disconnect(NodeCompat *n) { + auto *ib = n->getData(); + struct ibv_wc wc[MAX(ib->recv_cq_size, ib->send_cq_size)]; + int wcs; - n->logger->debug("Starting to clean up"); + n->logger->debug("Starting to clean up"); - rdma_disconnect(ib->ctx.id); + rdma_disconnect(ib->ctx.id); - // If there is anything in the Completion Queue, it should be given back to the framework Receive Queue. - while (ib->conn.available_recv_wrs) { - wcs = ibv_poll_cq(ib->ctx.recv_cq, ib->recv_cq_size, wc); + // If there is anything in the Completion Queue, it should be given back to the framework Receive Queue. + while (ib->conn.available_recv_wrs) { + wcs = ibv_poll_cq(ib->ctx.recv_cq, ib->recv_cq_size, wc); - ib->conn.available_recv_wrs -= wcs; + ib->conn.available_recv_wrs -= wcs; - for (int j = 0; j < wcs; j++) - sample_decref((struct Sample *) (intptr_t) (wc[j].wr_id)); - } + for (int j = 0; j < wcs; j++) + sample_decref((struct Sample *)(intptr_t)(wc[j].wr_id)); + } - // Send Queue - while ((wcs = ibv_poll_cq(ib->ctx.send_cq, ib->send_cq_size, wc))) - for (int j = 0; j < wcs; j++) - if (wc[j].wr_id > 0) - sample_decref((struct Sample *) (intptr_t) (wc[j].wr_id)); + // Send Queue + while ((wcs = ibv_poll_cq(ib->ctx.send_cq, ib->send_cq_size, wc))) + for (int j = 0; j < wcs; j++) + if (wc[j].wr_id > 0) + sample_decref((struct Sample *)(intptr_t)(wc[j].wr_id)); - // Destroy QP - rdma_destroy_qp(ib->ctx.id); + // Destroy QP + rdma_destroy_qp(ib->ctx.id); - n->logger->debug("Destroyed QP"); + n->logger->debug("Destroyed QP"); - return ib->stopThreads; + return ib->stopThreads; } -static -void ib_build_ibv(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +static void ib_build_ibv(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Starting to build IBV components"); + n->logger->debug("Starting to build IBV components"); - // Create completion queues (No completion channel!) - ib->ctx.recv_cq = ibv_create_cq(ib->ctx.id->verbs, ib->recv_cq_size, nullptr, nullptr, 0); - if (!ib->ctx.recv_cq) - throw RuntimeError("Could not create receive completion queue"); + // Create completion queues (No completion channel!) + ib->ctx.recv_cq = + ibv_create_cq(ib->ctx.id->verbs, ib->recv_cq_size, nullptr, nullptr, 0); + if (!ib->ctx.recv_cq) + throw RuntimeError("Could not create receive completion queue"); - n->logger->debug("Created receive Completion Queue"); + n->logger->debug("Created receive Completion Queue"); - ib->ctx.send_cq = ibv_create_cq(ib->ctx.id->verbs, ib->send_cq_size, nullptr, nullptr, 0); - if (!ib->ctx.send_cq) - throw RuntimeError("Could not create send completion queue"); + ib->ctx.send_cq = + ibv_create_cq(ib->ctx.id->verbs, ib->send_cq_size, nullptr, nullptr, 0); + if (!ib->ctx.send_cq) + throw RuntimeError("Could not create send completion queue"); - n->logger->debug("Created send Completion Queue"); + n->logger->debug("Created send Completion Queue"); - // Prepare remaining Queue Pair (QP) attributes - ib->qp_init.send_cq = ib->ctx.send_cq; - ib->qp_init.recv_cq = ib->ctx.recv_cq; + // Prepare remaining Queue Pair (QP) attributes + ib->qp_init.send_cq = ib->ctx.send_cq; + ib->qp_init.recv_cq = ib->ctx.recv_cq; - // Create the actual QP - ret = rdma_create_qp(ib->ctx.id, ib->ctx.pd, &ib->qp_init); - if (ret) - throw RuntimeError("Failed to create Queue Pair"); + // Create the actual QP + ret = rdma_create_qp(ib->ctx.id, ib->ctx.pd, &ib->qp_init); + if (ret) + throw RuntimeError("Failed to create Queue Pair"); - n->logger->debug("Created Queue Pair with {} receive and {} send elements", - ib->qp_init.cap.max_recv_wr, ib->qp_init.cap.max_send_wr); + n->logger->debug("Created Queue Pair with {} receive and {} send elements", + ib->qp_init.cap.max_recv_wr, ib->qp_init.cap.max_send_wr); - if (ib->conn.send_inline) - n->logger->info("Maximum inline size is set to {} byte", ib->qp_init.cap.max_inline_data); + if (ib->conn.send_inline) + n->logger->info("Maximum inline size is set to {} byte", + ib->qp_init.cap.max_inline_data); } -static -int ib_addr_resolved(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +static int ib_addr_resolved(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Successfully resolved address"); + n->logger->debug("Successfully resolved address"); - // Build all components from IB Verbs - ib_build_ibv(n); + // Build all components from IB Verbs + ib_build_ibv(n); - // Resolve address - ret = rdma_resolve_route(ib->ctx.id, ib->conn.timeout); - if (ret) - throw RuntimeError("Failed to resolve route"); + // Resolve address + ret = rdma_resolve_route(ib->ctx.id, ib->conn.timeout); + if (ret) + throw RuntimeError("Failed to resolve route"); - return 0; + return 0; } -static -int ib_route_resolved(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +static int ib_route_resolved(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - struct rdma_conn_param cm_params; - memset(&cm_params, 0, sizeof(cm_params)); + struct rdma_conn_param cm_params; + memset(&cm_params, 0, sizeof(cm_params)); - // Send connection request - ret = rdma_connect(ib->ctx.id, &cm_params); - if (ret) - throw RuntimeError("Failed to connect"); + // Send connection request + ret = rdma_connect(ib->ctx.id, &cm_params); + if (ret) + throw RuntimeError("Failed to connect"); - n->logger->debug("Called rdma_connect"); + n->logger->debug("Called rdma_connect"); - return 0; + return 0; } -static -int ib_connect_request(NodeCompat *n, struct rdma_cm_id *id) -{ - auto *ib = n->getData(); - int ret; +static int ib_connect_request(NodeCompat *n, struct rdma_cm_id *id) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Received a connection request!"); + n->logger->debug("Received a connection request!"); - ib->ctx.id = id; - ib_build_ibv(n); + ib->ctx.id = id; + ib_build_ibv(n); - struct rdma_conn_param cm_params; - memset(&cm_params, 0, sizeof(cm_params)); + struct rdma_conn_param cm_params; + memset(&cm_params, 0, sizeof(cm_params)); - // Accept connection request - ret = rdma_accept(ib->ctx.id, &cm_params); - if (ret) - throw RuntimeError("Failed to connect"); + // Accept connection request + ret = rdma_accept(ib->ctx.id, &cm_params); + if (ret) + throw RuntimeError("Failed to connect"); - n->logger->info("Successfully accepted connection request"); + n->logger->info("Successfully accepted connection request"); - return 0; + return 0; } -int villas::node::ib_reverse(NodeCompat *n) -{ - auto *ib = n->getData(); +int villas::node::ib_reverse(NodeCompat *n) { + auto *ib = n->getData(); - SWAP(ib->conn.src_addr, ib->conn.dst_addr); + SWAP(ib->conn.src_addr, ib->conn.dst_addr); - return 0; + return 0; } -int villas::node::ib_parse(NodeCompat *n, json_t *json) -{ - auto *ib = n->getData(); +int villas::node::ib_parse(NodeCompat *n, json_t *json) { + auto *ib = n->getData(); - throw ConfigError(json, "The infiniband node-type is currently broken!"); + throw ConfigError(json, "The infiniband node-type is currently broken!"); - int ret; - char *local = nullptr, *remote = nullptr, *lasts; - const char *transport_mode = "RC"; - int timeout = 1000; - int recv_cq_size = 128; - int send_cq_size = 128; - int max_send_wr = 128; - int max_recv_wr = 128; - int max_inline_data = 0; - int send_inline = 1; - int vectorize_in = 1; - int vectorize_out = 1; - int buffer_subtraction = 16; - int use_fallback = 1; + int ret; + char *local = nullptr, *remote = nullptr, *lasts; + const char *transport_mode = "RC"; + int timeout = 1000; + int recv_cq_size = 128; + int send_cq_size = 128; + int max_send_wr = 128; + int max_recv_wr = 128; + int max_inline_data = 0; + int send_inline = 1; + int vectorize_in = 1; + int vectorize_out = 1; + int buffer_subtraction = 16; + int use_fallback = 1; - // Parse JSON files and copy to local variables - json_t *json_in = nullptr; - json_t *json_out = nullptr; - json_error_t err; + // Parse JSON files and copy to local variables + json_t *json_in = nullptr; + json_t *json_out = nullptr; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: s }", - "in", &json_in, - "out", &json_out, - "rdma_transport_mode", &transport_mode - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ib"); + ret = + json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: s }", "in", &json_in, + "out", &json_out, "rdma_transport_mode", &transport_mode); + if (ret) + throw ConfigError(json, err, "node-config-node-ib"); - if (json_in) { - ret = json_unpack_ex(json_in, &err, 0, "{ s?: s, s?: i, s?: i, s?: i, s?: i}", - "address", &local, - "cq_size", &recv_cq_size, - "max_wrs", &max_recv_wr, - "vectorize", &vectorize_in, - "buffer_subtraction", &buffer_subtraction - ); - if (ret) - throw ConfigError(json_in, err, "node-config-node-ib-in"); - } + if (json_in) { + ret = json_unpack_ex( + json_in, &err, 0, "{ s?: s, s?: i, s?: i, s?: i, s?: i}", "address", + &local, "cq_size", &recv_cq_size, "max_wrs", &max_recv_wr, "vectorize", + &vectorize_in, "buffer_subtraction", &buffer_subtraction); + if (ret) + throw ConfigError(json_in, err, "node-config-node-ib-in"); + } - if (json_out) { - ret = json_unpack_ex(json_out, &err, 0, "{ s?: s, s?: i, s?: i, s?: i, s?: i, s?: b, s?: i, s?: b, s?: i}", - "address", &remote, - "resolution_timeout", &timeout, - "cq_size", &send_cq_size, - "max_wrs", &max_send_wr, - "max_inline_data", &max_inline_data, - "send_inline", &send_inline, - "vectorize", &vectorize_out, - "use_fallback", &use_fallback, - "periodic_signaling", &ib->periodic_signaling - ); - if (ret) - throw ConfigError(json_out, err, "node-config-node-ib-out"); + if (json_out) { + ret = json_unpack_ex( + json_out, &err, 0, + "{ s?: s, s?: i, s?: i, s?: i, s?: i, s?: b, s?: i, s?: b, s?: i}", + "address", &remote, "resolution_timeout", &timeout, "cq_size", + &send_cq_size, "max_wrs", &max_send_wr, "max_inline_data", + &max_inline_data, "send_inline", &send_inline, "vectorize", + &vectorize_out, "use_fallback", &use_fallback, "periodic_signaling", + &ib->periodic_signaling); + if (ret) + throw ConfigError(json_out, err, "node-config-node-ib-out"); - if (remote) { - ib->is_source = 1; + if (remote) { + ib->is_source = 1; - n->logger->debug("Setup as source and target"); - } - } - else { - ib->is_source = 0; + n->logger->debug("Setup as source and target"); + } + } else { + ib->is_source = 0; - n->logger->debug("Setup as target"); - } + n->logger->debug("Setup as target"); + } - // Set fallback mode - ib->conn.use_fallback = use_fallback; + // Set fallback mode + ib->conn.use_fallback = use_fallback; - // Set vectorize mode. Do not print, since framework will print this information - n->in.vectorize = vectorize_in; - n->out.vectorize = vectorize_out; + // Set vectorize mode. Do not print, since framework will print this information + n->in.vectorize = vectorize_in; + n->out.vectorize = vectorize_out; - // Set buffer subtraction - ib->conn.buffer_subtraction = buffer_subtraction; + // Set buffer subtraction + ib->conn.buffer_subtraction = buffer_subtraction; - n->logger->debug("Set buffer subtraction to {}", buffer_subtraction); + n->logger->debug("Set buffer subtraction to {}", buffer_subtraction); - // Translate IP:PORT to a struct addrinfo - char *ip_adr = strtok_r(local, ":", &lasts); - char *port = strtok_r(nullptr, ":", &lasts); + // Translate IP:PORT to a struct addrinfo + char *ip_adr = strtok_r(local, ":", &lasts); + char *port = strtok_r(nullptr, ":", &lasts); - ret = getaddrinfo(ip_adr, port, nullptr, &ib->conn.src_addr); - if (ret) - throw RuntimeError("Failed to resolve local address '{}': {}", local, gai_strerror(ret)); + ret = getaddrinfo(ip_adr, port, nullptr, &ib->conn.src_addr); + if (ret) + throw RuntimeError("Failed to resolve local address '{}': {}", local, + gai_strerror(ret)); - n->logger->debug("Translated {}:{} to a struct addrinfo", ip_adr, port); + n->logger->debug("Translated {}:{} to a struct addrinfo", ip_adr, port); - // Translate port space - if (strcmp(transport_mode, "RC") == 0) { - ib->conn.port_space = RDMA_PS_TCP; - ib->qp_init.qp_type = IBV_QPT_RC; - } - else if (strcmp(transport_mode, "UC") == 0) { + // Translate port space + if (strcmp(transport_mode, "RC") == 0) { + ib->conn.port_space = RDMA_PS_TCP; + ib->qp_init.qp_type = IBV_QPT_RC; + } else if (strcmp(transport_mode, "UC") == 0) { #ifdef RDMA_CMA_H_CUSTOM - ib->conn.port_space = RDMA_PS_IB; - ib->qp_init.qp_type = IBV_QPT_UC; + ib->conn.port_space = RDMA_PS_IB; + ib->qp_init.qp_type = IBV_QPT_UC; #else - throw RuntimeError("Unreliable Connected (UC) mode is only available with an adapted version of librdma. " - "Please read the Infiniband node type Documentation for more information on UC!"); + throw RuntimeError("Unreliable Connected (UC) mode is only available with " + "an adapted version of librdma. " + "Please read the Infiniband node type Documentation for " + "more information on UC!"); #endif - } - else if (strcmp(transport_mode, "UD") == 0) { - ib->conn.port_space = RDMA_PS_UDP; - ib->qp_init.qp_type = IBV_QPT_UD; - } - else - throw RuntimeError("Invalid transport_mode = '{}'!", transport_mode); + } else if (strcmp(transport_mode, "UD") == 0) { + ib->conn.port_space = RDMA_PS_UDP; + ib->qp_init.qp_type = IBV_QPT_UD; + } else + throw RuntimeError("Invalid transport_mode = '{}'!", transport_mode); - n->logger->debug("Set transport mode to {}", transport_mode); + n->logger->debug("Set transport mode to {}", transport_mode); - // Set timeout - ib->conn.timeout = timeout; + // Set timeout + ib->conn.timeout = timeout; - n->logger->debug("Set timeout to {}", timeout); + n->logger->debug("Set timeout to {}", timeout); - // Set completion queue size - ib->recv_cq_size = recv_cq_size; - ib->send_cq_size = send_cq_size; + // Set completion queue size + ib->recv_cq_size = recv_cq_size; + ib->send_cq_size = send_cq_size; - n->logger->debug("Set Completion Queue size to {} & {} (in & out)", - recv_cq_size, send_cq_size); + n->logger->debug("Set Completion Queue size to {} & {} (in & out)", + recv_cq_size, send_cq_size); - // Translate inline mode - ib->conn.send_inline = send_inline; + // Translate inline mode + ib->conn.send_inline = send_inline; - n->logger->debug("Set send_inline to {}", send_inline); + n->logger->debug("Set send_inline to {}", send_inline); - // Set max. send and receive Work Requests - ib->qp_init.cap.max_send_wr = max_send_wr; - ib->qp_init.cap.max_recv_wr = max_recv_wr; + // Set max. send and receive Work Requests + ib->qp_init.cap.max_send_wr = max_send_wr; + ib->qp_init.cap.max_recv_wr = max_recv_wr; - n->logger->debug("Set max_send_wr and max_recv_wr to {} and {}, respectively", - max_send_wr, max_recv_wr); + n->logger->debug("Set max_send_wr and max_recv_wr to {} and {}, respectively", + max_send_wr, max_recv_wr); - // Set available receive Work Requests to 0 - ib->conn.available_recv_wrs = 0; + // Set available receive Work Requests to 0 + ib->conn.available_recv_wrs = 0; - // Set remaining QP attributes - ib->qp_init.cap.max_send_sge = 4; - ib->qp_init.cap.max_recv_sge = (ib->conn.port_space == RDMA_PS_UDP) ? 5 : 4; + // Set remaining QP attributes + ib->qp_init.cap.max_send_sge = 4; + ib->qp_init.cap.max_recv_sge = (ib->conn.port_space == RDMA_PS_UDP) ? 5 : 4; - // Set number of bytes to be send inline - ib->qp_init.cap.max_inline_data = max_inline_data; + // Set number of bytes to be send inline + ib->qp_init.cap.max_inline_data = max_inline_data; - // If node will send data, set remote address - if (ib->is_source) { - // Translate address info - char *ip_adr = strtok_r(remote, ":", &lasts); - char *port = strtok_r(nullptr, ":", &lasts); + // If node will send data, set remote address + if (ib->is_source) { + // Translate address info + char *ip_adr = strtok_r(remote, ":", &lasts); + char *port = strtok_r(nullptr, ":", &lasts); - ret = getaddrinfo(ip_adr, port, nullptr, &ib->conn.dst_addr); - if (ret) - throw RuntimeError("Failed to resolve remote address '{}': {}", remote, gai_strerror(ret)); + ret = getaddrinfo(ip_adr, port, nullptr, &ib->conn.dst_addr); + if (ret) + throw RuntimeError("Failed to resolve remote address '{}': {}", remote, + gai_strerror(ret)); - n->logger->debug("Translated {}:{} to a struct addrinfo", ip_adr, port); - } + n->logger->debug("Translated {}:{} to a struct addrinfo", ip_adr, port); + } - return 0; + return 0; } -int villas::node::ib_check(NodeCompat *n) -{ - auto *ib = n->getData(); +int villas::node::ib_check(NodeCompat *n) { + auto *ib = n->getData(); - // Check if read substraction makes sense - if (ib->conn.buffer_subtraction < 2 * n->in.vectorize) - throw RuntimeError("The buffer substraction value must be bigger than 2 * in.vectorize"); + // Check if read substraction makes sense + if (ib->conn.buffer_subtraction < 2 * n->in.vectorize) + throw RuntimeError( + "The buffer substraction value must be bigger than 2 * in.vectorize"); - if (ib->conn.buffer_subtraction >= ib->qp_init.cap.max_recv_wr - n->in.vectorize) - throw RuntimeError("The buffer substraction value cannot be bigger than in.max_wrs - in.vectorize"); + if (ib->conn.buffer_subtraction >= + ib->qp_init.cap.max_recv_wr - n->in.vectorize) + throw RuntimeError("The buffer substraction value cannot be bigger than " + "in.max_wrs - in.vectorize"); - // Check if the set value is a power of 2, and warn the user if this is not the case - unsigned max_send_pow = (int) pow(2, ceil(log2(ib->qp_init.cap.max_send_wr))); - unsigned max_recv_pow = (int) pow(2, ceil(log2(ib->qp_init.cap.max_recv_wr))); + // Check if the set value is a power of 2, and warn the user if this is not the case + unsigned max_send_pow = (int)pow(2, ceil(log2(ib->qp_init.cap.max_send_wr))); + unsigned max_recv_pow = (int)pow(2, ceil(log2(ib->qp_init.cap.max_recv_wr))); - if (ib->qp_init.cap.max_send_wr != max_send_pow) { - n->logger->warn("Max nr. of send WRs ({}) is not a power of 2! It will be changed to a power of 2: {}", - ib->qp_init.cap.max_send_wr, max_send_pow); + if (ib->qp_init.cap.max_send_wr != max_send_pow) { + n->logger->warn("Max nr. of send WRs ({}) is not a power of 2! It will be " + "changed to a power of 2: {}", + ib->qp_init.cap.max_send_wr, max_send_pow); - // Change it now, because otherwise errors are possible in ib_start(). - ib->qp_init.cap.max_send_wr = max_send_pow; - } + // Change it now, because otherwise errors are possible in ib_start(). + ib->qp_init.cap.max_send_wr = max_send_pow; + } - if (ib->qp_init.cap.max_recv_wr != max_recv_pow) { - n->logger->warn("Max nr. of recv WRs ({}) is not a power of 2! It will be changed to a power of 2: {}", - ib->qp_init.cap.max_recv_wr, max_recv_pow); + if (ib->qp_init.cap.max_recv_wr != max_recv_pow) { + n->logger->warn("Max nr. of recv WRs ({}) is not a power of 2! It will be " + "changed to a power of 2: {}", + ib->qp_init.cap.max_recv_wr, max_recv_pow); - // Change it now, because otherwise errors are possible in ib_start(). - ib->qp_init.cap.max_recv_wr = max_recv_pow; - } + // Change it now, because otherwise errors are possible in ib_start(). + ib->qp_init.cap.max_recv_wr = max_recv_pow; + } - // Check maximum size of max_recv_wr and max_send_wr - if (ib->qp_init.cap.max_send_wr > 8192) - n->logger->warn("Max number of send WRs ({}) is bigger than send queue!", ib->qp_init.cap.max_send_wr); + // Check maximum size of max_recv_wr and max_send_wr + if (ib->qp_init.cap.max_send_wr > 8192) + n->logger->warn("Max number of send WRs ({}) is bigger than send queue!", + ib->qp_init.cap.max_send_wr); - if (ib->qp_init.cap.max_recv_wr > 8192) - n->logger->warn("Max number of receive WRs ({}) is bigger than send queue!", ib->qp_init.cap.max_recv_wr); + if (ib->qp_init.cap.max_recv_wr > 8192) + n->logger->warn("Max number of receive WRs ({}) is bigger than send queue!", + ib->qp_init.cap.max_recv_wr); - /* Set periodic signaling + /* Set periodic signaling * This is done here, so that it uses the checked max_send_wr value */ - if (ib->periodic_signaling == 0) - ib->periodic_signaling = ib->qp_init.cap.max_send_wr / 2; + if (ib->periodic_signaling == 0) + ib->periodic_signaling = ib->qp_init.cap.max_send_wr / 2; - // Warn user if he changed the default inline value - if (ib->qp_init.cap.max_inline_data != 0) - n->logger->warn("You changed the default value of max_inline_data. This might influence the maximum number " - "of outstanding Work Requests in the Queue Pair and can be a reason for the Queue Pair creation to fail"); + // Warn user if he changed the default inline value + if (ib->qp_init.cap.max_inline_data != 0) + n->logger->warn("You changed the default value of max_inline_data. This " + "might influence the maximum number " + "of outstanding Work Requests in the Queue Pair and can be " + "a reason for the Queue Pair creation to fail"); - return 0; + return 0; } -char * villas::node::ib_print(NodeCompat *n) -{ - return 0; -} +char *villas::node::ib_print(NodeCompat *n) { return 0; } -int villas::node::ib_destroy(NodeCompat *n) -{ - return 0; -} +int villas::node::ib_destroy(NodeCompat *n) { return 0; } -static -void ib_create_bind_id(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +static void ib_create_bind_id(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - /* Create rdma_cm_id + /* Create rdma_cm_id * * The unreliable connected mode is officially not supported by the rdma_cm library. Only the Reliable * Connected mode (RDMA_PS_TCP) and the Unreliable Datagram mode (RDMA_PS_UDP). Although it is not officially @@ -433,595 +416,610 @@ void ib_create_bind_id(NodeCompat *n) * */ #ifdef RDMA_CMA_H_CUSTOM - ret = rdma_create_id2(ib->ctx.ec, &ib->ctx.id, nullptr, ib->conn.port_space, ib->qp_init.qp_type); + ret = rdma_create_id2(ib->ctx.ec, &ib->ctx.id, nullptr, ib->conn.port_space, + ib->qp_init.qp_type); #else - ret = rdma_create_id(ib->ctx.ec, &ib->ctx.id, nullptr, ib->conn.port_space); + ret = rdma_create_id(ib->ctx.ec, &ib->ctx.id, nullptr, ib->conn.port_space); #endif - if (ret) - throw RuntimeError("Failed to create rdma_cm_id: {}", gai_strerror(ret)); + if (ret) + throw RuntimeError("Failed to create rdma_cm_id: {}", gai_strerror(ret)); - n->logger->debug("Created rdma_cm_id"); + n->logger->debug("Created rdma_cm_id"); - // Bind rdma_cm_id to the HCA - ret = rdma_bind_addr(ib->ctx.id, ib->conn.src_addr->ai_addr); - if (ret) - throw RuntimeError("Failed to bind to local device: {}", gai_strerror(ret)); + // Bind rdma_cm_id to the HCA + ret = rdma_bind_addr(ib->ctx.id, ib->conn.src_addr->ai_addr); + if (ret) + throw RuntimeError("Failed to bind to local device: {}", gai_strerror(ret)); - n->logger->debug("Bound rdma_cm_id to Infiniband device"); + n->logger->debug("Bound rdma_cm_id to Infiniband device"); - /* The ID will be overwritten for the target. If the event type is + /* The ID will be overwritten for the target. If the event type is * RDMA_CM_EVENT_CONNECT_REQUEST, >then this references a new id for * that communication. */ - ib->ctx.listen_id = ib->ctx.id; + ib->ctx.listen_id = ib->ctx.id; } -static -void ib_continue_as_listen(NodeCompat *n, struct rdma_cm_event *event) -{ - auto *ib = n->getData(); - int ret; +static void ib_continue_as_listen(NodeCompat *n, struct rdma_cm_event *event) { + auto *ib = n->getData(); + int ret; - if (ib->conn.use_fallback) - n->logger->warn("Trying to continue as listening node"); - else - throw RuntimeError("Cannot establish a connection with remote host! If you want that {} tries to " - "continue as listening node in such cases, set use_fallback = true in the configuration"); + if (ib->conn.use_fallback) + n->logger->warn("Trying to continue as listening node"); + else + throw RuntimeError("Cannot establish a connection with remote host! If you " + "want that {} tries to " + "continue as listening node in such cases, set " + "use_fallback = true in the configuration"); - n->setState(State::STARTED); + n->setState(State::STARTED); - // Acknowledge event - rdma_ack_cm_event(event); + // Acknowledge event + rdma_ack_cm_event(event); - // Destroy ID - rdma_destroy_id(ib->ctx.listen_id); + // Destroy ID + rdma_destroy_id(ib->ctx.listen_id); - // Create rdma_cm_id and bind to device - ib_create_bind_id(n); + // Create rdma_cm_id and bind to device + ib_create_bind_id(n); - // Listen to id for events - ret = rdma_listen(ib->ctx.listen_id, 10); - if (ret) - throw RuntimeError("Failed to listen to rdma_cm_id"); + // Listen to id for events + ret = rdma_listen(ib->ctx.listen_id, 10); + if (ret) + throw RuntimeError("Failed to listen to rdma_cm_id"); - // Node is not a source (and will not send data - ib->is_source = 0; + // Node is not a source (and will not send data + ib->is_source = 0; - n->logger->info("Use listening mode"); + n->logger->info("Use listening mode"); } -static -void * ib_rdma_cm_event_thread(void *ctx) -{ - auto *n = (NodeCompat *) ctx; - auto *ib = n->getData(); - struct rdma_cm_event *event; - int ret = 0; +static void *ib_rdma_cm_event_thread(void *ctx) { + auto *n = (NodeCompat *)ctx; + auto *ib = n->getData(); + struct rdma_cm_event *event; + int ret = 0; - n->logger->debug("Started rdma_cm_event thread"); + n->logger->debug("Started rdma_cm_event thread"); - // Wait until node is completely started - while (n->getState() != State::STARTED); + // Wait until node is completely started + while (n->getState() != State::STARTED) + ; - // Monitor event channel - while (rdma_get_cm_event(ib->ctx.ec, &event) == 0) { - n->logger->debug("Received communication event: {}", rdma_event_str(event->event)); + // Monitor event channel + while (rdma_get_cm_event(ib->ctx.ec, &event) == 0) { + n->logger->debug("Received communication event: {}", + rdma_event_str(event->event)); - switch(event->event) { - case RDMA_CM_EVENT_ADDR_RESOLVED: - ret = ib_addr_resolved(n); - break; + switch (event->event) { + case RDMA_CM_EVENT_ADDR_RESOLVED: + ret = ib_addr_resolved(n); + break; - case RDMA_CM_EVENT_ADDR_ERROR: - n->logger->warn("Address resolution (rdma_resolve_addr) failed!"); + case RDMA_CM_EVENT_ADDR_ERROR: + n->logger->warn("Address resolution (rdma_resolve_addr) failed!"); - ib_continue_as_listen(n, event); + ib_continue_as_listen(n, event); - break; + break; - case RDMA_CM_EVENT_ROUTE_RESOLVED: - ret = ib_route_resolved(n); - break; + case RDMA_CM_EVENT_ROUTE_RESOLVED: + ret = ib_route_resolved(n); + break; - case RDMA_CM_EVENT_ROUTE_ERROR: - n->logger->warn("Route resolution (rdma_resovle_route) failed!"); + case RDMA_CM_EVENT_ROUTE_ERROR: + n->logger->warn("Route resolution (rdma_resovle_route) failed!"); - ib_continue_as_listen(n, event); + ib_continue_as_listen(n, event); - break; + break; - case RDMA_CM_EVENT_UNREACHABLE: - n->logger->warn("Remote server unreachable!"); + case RDMA_CM_EVENT_UNREACHABLE: + n->logger->warn("Remote server unreachable!"); - ib_continue_as_listen(n, event); - break; + ib_continue_as_listen(n, event); + break; - case RDMA_CM_EVENT_CONNECT_REQUEST: - ret = ib_connect_request(n, event->id); + case RDMA_CM_EVENT_CONNECT_REQUEST: + ret = ib_connect_request(n, event->id); - /* A target UDP node will never really connect. In order to receive data, + /* A target UDP node will never really connect. In order to receive data, * we set it to connected after it answered the connection request * with rdma_connect. */ - if (ib->conn.port_space == RDMA_PS_UDP && !ib->is_source) - n->setState(State::CONNECTED); - else - n->setState(State::PENDING_CONNECT); + if (ib->conn.port_space == RDMA_PS_UDP && !ib->is_source) + n->setState(State::CONNECTED); + else + n->setState(State::PENDING_CONNECT); - break; + break; - case RDMA_CM_EVENT_CONNECT_ERROR: - n->logger->warn("An error has occurred trying to establish a connection!"); + case RDMA_CM_EVENT_CONNECT_ERROR: + n->logger->warn( + "An error has occurred trying to establish a connection!"); - ib_continue_as_listen(n, event); + ib_continue_as_listen(n, event); - break; + break; - case RDMA_CM_EVENT_REJECTED: - n->logger->warn("Connection request or response was rejected by the remote end point!"); + case RDMA_CM_EVENT_REJECTED: + n->logger->warn("Connection request or response was rejected by the " + "remote end point!"); - ib_continue_as_listen(n, event); + ib_continue_as_listen(n, event); - break; + break; - case RDMA_CM_EVENT_ESTABLISHED: - // If the connection is unreliable connectionless, set appropriate variables - if (ib->conn.port_space == RDMA_PS_UDP) { - ib->conn.ud.ud = event->param.ud; - ib->conn.ud.ah = ibv_create_ah(ib->ctx.pd, &ib->conn.ud.ud.ah_attr); - } + case RDMA_CM_EVENT_ESTABLISHED: + // If the connection is unreliable connectionless, set appropriate variables + if (ib->conn.port_space == RDMA_PS_UDP) { + ib->conn.ud.ud = event->param.ud; + ib->conn.ud.ah = ibv_create_ah(ib->ctx.pd, &ib->conn.ud.ud.ah_attr); + } - n->setState(State::CONNECTED); + n->setState(State::CONNECTED); - n->logger->info("Connection established"); + n->logger->info("Connection established"); - break; + break; - case RDMA_CM_EVENT_DISCONNECTED: - n->setState(State::STARTED); + case RDMA_CM_EVENT_DISCONNECTED: + n->setState(State::STARTED); - ret = ib_disconnect(n); + ret = ib_disconnect(n); - if (!ret) - n->logger->info("Host disconnected. Ready to accept new connections."); + if (!ret) + n->logger->info("Host disconnected. Ready to accept new connections."); - break; + break; - case RDMA_CM_EVENT_TIMEWAIT_EXIT: - break; + case RDMA_CM_EVENT_TIMEWAIT_EXIT: + break; - default: - throw RuntimeError("Unknown event occurred: {}", event->event); - } + default: + throw RuntimeError("Unknown event occurred: {}", event->event); + } - rdma_ack_cm_event(event); + rdma_ack_cm_event(event); - if (ret) - break; - } + if (ret) + break; + } - return nullptr; + return nullptr; } -int villas::node::ib_start(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +int villas::node::ib_start(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Started ib_start"); + n->logger->debug("Started ib_start"); - // Create event channel - ib->ctx.ec = rdma_create_event_channel(); - if (!ib->ctx.ec) - throw RuntimeError("Failed to create event channel!"); + // Create event channel + ib->ctx.ec = rdma_create_event_channel(); + if (!ib->ctx.ec) + throw RuntimeError("Failed to create event channel!"); - n->logger->debug("Created event channel"); + n->logger->debug("Created event channel"); - // Create rdma_cm_id and bind to device - ib_create_bind_id(n); + // Create rdma_cm_id and bind to device + ib_create_bind_id(n); - n->logger->debug("Initialized Work Completion Buffer"); + n->logger->debug("Initialized Work Completion Buffer"); - // Resolve address or listen to rdma_cm_id - if (ib->is_source) { - // Resolve address - ret = rdma_resolve_addr(ib->ctx.id, nullptr, ib->conn.dst_addr->ai_addr, ib->conn.timeout); - if (ret) - throw RuntimeError("Failed to resolve remote address after {}ms: {}", ib->conn.timeout, gai_strerror(ret)); - } - else { - // Listen on rdma_cm_id for events - ret = rdma_listen(ib->ctx.listen_id, 10); - if (ret) - throw RuntimeError("Failed to listen to rdma_cm_id"); + // Resolve address or listen to rdma_cm_id + if (ib->is_source) { + // Resolve address + ret = rdma_resolve_addr(ib->ctx.id, nullptr, ib->conn.dst_addr->ai_addr, + ib->conn.timeout); + if (ret) + throw RuntimeError("Failed to resolve remote address after {}ms: {}", + ib->conn.timeout, gai_strerror(ret)); + } else { + // Listen on rdma_cm_id for events + ret = rdma_listen(ib->ctx.listen_id, 10); + if (ret) + throw RuntimeError("Failed to listen to rdma_cm_id"); - n->logger->debug("Started to listen to rdma_cm_id"); - } + n->logger->debug("Started to listen to rdma_cm_id"); + } - // Allocate protection domain - ib->ctx.pd = ibv_alloc_pd(ib->ctx.id->verbs); - if (!ib->ctx.pd) - throw RuntimeError("Could not allocate protection domain"); + // Allocate protection domain + ib->ctx.pd = ibv_alloc_pd(ib->ctx.id->verbs); + if (!ib->ctx.pd) + throw RuntimeError("Could not allocate protection domain"); - n->logger->debug("Allocated Protection Domain"); + n->logger->debug("Allocated Protection Domain"); - // Allocate space for 40 Byte GHR. We don't use this. - if (ib->conn.port_space == RDMA_PS_UDP) { - ib->conn.ud.grh_ptr = new char[GRH_SIZE]; - if (!ib->conn.ud.grh_ptr) - throw MemoryAllocationError(); + // Allocate space for 40 Byte GHR. We don't use this. + if (ib->conn.port_space == RDMA_PS_UDP) { + ib->conn.ud.grh_ptr = new char[GRH_SIZE]; + if (!ib->conn.ud.grh_ptr) + throw MemoryAllocationError(); - ib->conn.ud.grh_mr = ibv_reg_mr(ib->ctx.pd, ib->conn.ud.grh_ptr, GRH_SIZE, IBV_ACCESS_LOCAL_WRITE); - } + ib->conn.ud.grh_mr = ibv_reg_mr(ib->ctx.pd, ib->conn.ud.grh_ptr, GRH_SIZE, + IBV_ACCESS_LOCAL_WRITE); + } - /* Several events should occur on the event channel, to make + /* Several events should occur on the event channel, to make * sure the nodes are succesfully connected. */ - n->logger->debug("Starting to monitor events on rdma_cm_id"); + n->logger->debug("Starting to monitor events on rdma_cm_id"); - // Create thread to monitor rdma_cm_event channel - ret = pthread_create(&ib->conn.rdma_cm_event_thread, nullptr, ib_rdma_cm_event_thread, n); - if (ret) - throw RuntimeError("Failed to create thread to monitor rdma_cm events: {}", gai_strerror(ret)); + // Create thread to monitor rdma_cm_event channel + ret = pthread_create(&ib->conn.rdma_cm_event_thread, nullptr, + ib_rdma_cm_event_thread, n); + if (ret) + throw RuntimeError("Failed to create thread to monitor rdma_cm events: {}", + gai_strerror(ret)); - return 0; + return 0; } -int villas::node::ib_stop(NodeCompat *n) -{ - auto *ib = n->getData(); - int ret; +int villas::node::ib_stop(NodeCompat *n) { + auto *ib = n->getData(); + int ret; - n->logger->debug("Called ib_stop"); + n->logger->debug("Called ib_stop"); - ib->stopThreads = 1; + ib->stopThreads = 1; - /* Call RDMA disconnect function + /* Call RDMA disconnect function * Will flush all outstanding WRs to the Completion Queue and * will call RDMA_CM_EVENT_DISCONNECTED if that is done. */ - if (n->getState() == State::CONNECTED && ib->conn.port_space != RDMA_PS_UDP) { - ret = rdma_disconnect(ib->ctx.id); + if (n->getState() == State::CONNECTED && ib->conn.port_space != RDMA_PS_UDP) { + ret = rdma_disconnect(ib->ctx.id); - if (ret) - throw RuntimeError("Error while calling rdma_disconnect: {}", gai_strerror(ret)); + if (ret) + throw RuntimeError("Error while calling rdma_disconnect: {}", + gai_strerror(ret)); - n->logger->debug("Called rdma_disconnect"); - } - else { - pthread_cancel(ib->conn.rdma_cm_event_thread); + n->logger->debug("Called rdma_disconnect"); + } else { + pthread_cancel(ib->conn.rdma_cm_event_thread); - n->logger->debug("Called pthread_cancel() on communication management thread."); - } + n->logger->debug( + "Called pthread_cancel() on communication management thread."); + } - n->logger->info("Disconnecting... Waiting for threads to join."); + n->logger->info("Disconnecting... Waiting for threads to join."); - // Wait for event thread to join - ret = pthread_join(ib->conn.rdma_cm_event_thread, nullptr); - if (ret) - throw RuntimeError("Error while joining rdma_cm_event_thread: {}", ret); + // Wait for event thread to join + ret = pthread_join(ib->conn.rdma_cm_event_thread, nullptr); + if (ret) + throw RuntimeError("Error while joining rdma_cm_event_thread: {}", ret); - n->logger->debug("Joined rdma_cm_event_thread"); + n->logger->debug("Joined rdma_cm_event_thread"); - // Destroy RDMA CM ID - rdma_destroy_id(ib->ctx.id); - n->logger->debug("Destroyed rdma_cm_id"); + // Destroy RDMA CM ID + rdma_destroy_id(ib->ctx.id); + n->logger->debug("Destroyed rdma_cm_id"); - // Dealloc Protection Domain - ibv_dealloc_pd(ib->ctx.pd); - n->logger->debug("Destroyed protection domain"); + // Dealloc Protection Domain + ibv_dealloc_pd(ib->ctx.pd); + n->logger->debug("Destroyed protection domain"); - // Destroy event channel - rdma_destroy_event_channel(ib->ctx.ec); - n->logger->debug("Destroyed event channel"); + // Destroy event channel + rdma_destroy_event_channel(ib->ctx.ec); + n->logger->debug("Destroyed event channel"); - n->logger->info("Successfully stopped node"); + n->logger->info("Successfully stopped node"); - return 0; + return 0; } -int villas::node::ib_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *ib = n->getData(); - struct ibv_wc wc[cnt]; - struct ibv_recv_wr wr[cnt], *bad_wr = nullptr; - struct ibv_sge sge[cnt][ib->qp_init.cap.max_recv_sge]; - struct ibv_mr *mr; - struct timespec ts_receive; - int ret = 0, wcs = 0, read_values = 0, max_wr_post; +int villas::node::ib_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *ib = n->getData(); + struct ibv_wc wc[cnt]; + struct ibv_recv_wr wr[cnt], *bad_wr = nullptr; + struct ibv_sge sge[cnt][ib->qp_init.cap.max_recv_sge]; + struct ibv_mr *mr; + struct timespec ts_receive; + int ret = 0, wcs = 0, read_values = 0, max_wr_post; - n->logger->debug("ib_read is called"); + n->logger->debug("ib_read is called"); - if (n->getState() == State::CONNECTED || n->getState() == State::PENDING_CONNECT) { + if (n->getState() == State::CONNECTED || + n->getState() == State::PENDING_CONNECT) { - max_wr_post = cnt; + max_wr_post = cnt; - /* Poll Completion Queue + /* Poll Completion Queue * If we've already posted enough receive WRs, try to pull cnt */ - if (ib->conn.available_recv_wrs >= (ib->qp_init.cap.max_recv_wr - ib->conn.buffer_subtraction) ) { - for (int i = 0; ; i++) { - if (i % CHK_PER_ITER == CHK_PER_ITER - 1) pthread_testcancel(); + if (ib->conn.available_recv_wrs >= + (ib->qp_init.cap.max_recv_wr - ib->conn.buffer_subtraction)) { + for (int i = 0;; i++) { + if (i % CHK_PER_ITER == CHK_PER_ITER - 1) + pthread_testcancel(); - /* If IB node disconnects or if it is still in State::PENDING_CONNECT, ib_read + /* If IB node disconnects or if it is still in State::PENDING_CONNECT, ib_read * should return immediately if this condition holds */ - if (n->getState() != State::CONNECTED) return 0; + if (n->getState() != State::CONNECTED) + return 0; - wcs = ibv_poll_cq(ib->ctx.recv_cq, cnt, wc); - if (wcs) { - // Get time directly after something arrived in Completion Queue - ts_receive = time_now(); + wcs = ibv_poll_cq(ib->ctx.recv_cq, cnt, wc); + if (wcs) { + // Get time directly after something arrived in Completion Queue + ts_receive = time_now(); - n->logger->debug("Received {} Work Completions", wcs); + n->logger->debug("Received {} Work Completions", wcs); - read_values = wcs; // Value to return - max_wr_post = wcs; // Make space free in smps[] + read_values = wcs; // Value to return + max_wr_post = wcs; // Make space free in smps[] - break; - } - } + break; + } + } - /* All samples (wcs * received + unposted) should be released. Let + /* All samples (wcs * received + unposted) should be released. Let * *release be equal to allocated. * * This is set in the framework, before this function was called. */ - } - else { - ib->conn.available_recv_wrs += max_wr_post; + } else { + ib->conn.available_recv_wrs += max_wr_post; - // TODO: fix release logic - // *release = 0; // While we fill the receive queue, we always use all samples - } + // TODO: fix release logic + // *release = 0; // While we fill the receive queue, we always use all samples + } - // Get Memory Region - mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); + // Get Memory Region + mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); - for (int i = 0; i < max_wr_post; i++) { - int j = 0; + for (int i = 0; i < max_wr_post; i++) { + int j = 0; - // Prepare receive Scatter/Gather element + // Prepare receive Scatter/Gather element - // First 40 byte of UD data are GRH and unused in our case - if (ib->conn.port_space == RDMA_PS_UDP) { - sge[i][j].addr = (uint64_t) ib->conn.ud.grh_ptr; - sge[i][j].length = GRH_SIZE; - sge[i][j].lkey = ib->conn.ud.grh_mr->lkey; + // First 40 byte of UD data are GRH and unused in our case + if (ib->conn.port_space == RDMA_PS_UDP) { + sge[i][j].addr = (uint64_t)ib->conn.ud.grh_ptr; + sge[i][j].length = GRH_SIZE; + sge[i][j].lkey = ib->conn.ud.grh_mr->lkey; - j++; - } + j++; + } - // Sequence - sge[i][j].addr = (uint64_t) &smps[i]->sequence; - sge[i][j].length = sizeof(smps[i]->sequence); - sge[i][j].lkey = mr->lkey; + // Sequence + sge[i][j].addr = (uint64_t)&smps[i]->sequence; + sge[i][j].length = sizeof(smps[i]->sequence); + sge[i][j].lkey = mr->lkey; - j++; + j++; - // Timespec origin - sge[i][j].addr = (uint64_t) &smps[i]->ts.origin; - sge[i][j].length = sizeof(smps[i]->ts.origin); - sge[i][j].lkey = mr->lkey; + // Timespec origin + sge[i][j].addr = (uint64_t)&smps[i]->ts.origin; + sge[i][j].length = sizeof(smps[i]->ts.origin); + sge[i][j].lkey = mr->lkey; - j++; + j++; - sge[i][j].addr = (uint64_t) &smps[i]->data; - sge[i][j].length = SAMPLE_DATA_LENGTH(DEFAULT_SAMPLE_LENGTH); - sge[i][j].lkey = mr->lkey; + sge[i][j].addr = (uint64_t)&smps[i]->data; + sge[i][j].length = SAMPLE_DATA_LENGTH(DEFAULT_SAMPLE_LENGTH); + sge[i][j].lkey = mr->lkey; - j++; + j++; - // Prepare a receive Work Request - wr[i].wr_id = (uintptr_t) smps[i]; - wr[i].next = &wr[i+1]; - wr[i].sg_list = sge[i]; - wr[i].num_sge = j; - } + // Prepare a receive Work Request + wr[i].wr_id = (uintptr_t)smps[i]; + wr[i].next = &wr[i + 1]; + wr[i].sg_list = sge[i]; + wr[i].num_sge = j; + } - wr[max_wr_post-1].next = nullptr; + wr[max_wr_post - 1].next = nullptr; - n->logger->debug("Prepared {} new receive Work Requests", max_wr_post); - n->logger->debug("{} receive Work Requests in Receive Queue", ib->conn.available_recv_wrs); + n->logger->debug("Prepared {} new receive Work Requests", max_wr_post); + n->logger->debug("{} receive Work Requests in Receive Queue", + ib->conn.available_recv_wrs); - // Post list of Work Requests - ret = ibv_post_recv(ib->ctx.id->qp, &wr[0], &bad_wr); - if (ret) - throw RuntimeError("Was unable to post receive WR: {}, bad WR ID: {:#x}", ret, bad_wr->wr_id); + // Post list of Work Requests + ret = ibv_post_recv(ib->ctx.id->qp, &wr[0], &bad_wr); + if (ret) + throw RuntimeError("Was unable to post receive WR: {}, bad WR ID: {:#x}", + ret, bad_wr->wr_id); - n->logger->debug("Succesfully posted receive Work Requests"); + n->logger->debug("Succesfully posted receive Work Requests"); - // Doesn't start if wcs == 0 - for (int j = 0; j < wcs; j++) { - if ( !( (wc[j].opcode & IBV_WC_RECV) && wc[j].status == IBV_WC_SUCCESS) ) { - // Drop all values, we don't know where the error occured - read_values = 0; - } + // Doesn't start if wcs == 0 + for (int j = 0; j < wcs; j++) { + if (!((wc[j].opcode & IBV_WC_RECV) && wc[j].status == IBV_WC_SUCCESS)) { + // Drop all values, we don't know where the error occured + read_values = 0; + } - if (wc[j].status == IBV_WC_WR_FLUSH_ERR) - n->logger->debug("Received IBV_WC_WR_FLUSH_ERR (ib_read). Ignore it."); - else if (wc[j].status != IBV_WC_SUCCESS) - n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", - wc[j].status); + if (wc[j].status == IBV_WC_WR_FLUSH_ERR) + n->logger->debug("Received IBV_WC_WR_FLUSH_ERR (ib_read). Ignore it."); + else if (wc[j].status != IBV_WC_SUCCESS) + n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", + wc[j].status); - /* 32 byte of meta data is always transferred. We should substract it. + /* 32 byte of meta data is always transferred. We should substract it. * Furthermore, in case of an unreliable connection, a 40 byte * global routing header is transferred. This should be substracted as well. */ - int correction = (ib->conn.port_space == RDMA_PS_UDP) ? META_GRH_SIZE : META_SIZE; + int correction = + (ib->conn.port_space == RDMA_PS_UDP) ? META_GRH_SIZE : META_SIZE; - // TODO: fix release logic - // smps[j] = (struct Sample *) (wc[j].wr_id); + // TODO: fix release logic + // smps[j] = (struct Sample *) (wc[j].wr_id); - smps[j]->length = SAMPLE_NUMBER_OF_VALUES(wc[j].byte_len - correction); - smps[j]->ts.received = ts_receive; - smps[j]->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_TS_RECEIVED | (int) SampleFlags::HAS_SEQUENCE; - smps[j]->signals = n->getInputSignals(false); - } - - } - return read_values; + smps[j]->length = SAMPLE_NUMBER_OF_VALUES(wc[j].byte_len - correction); + smps[j]->ts.received = ts_receive; + smps[j]->flags = (int)SampleFlags::HAS_TS_ORIGIN | + (int)SampleFlags::HAS_TS_RECEIVED | + (int)SampleFlags::HAS_SEQUENCE; + smps[j]->signals = n->getInputSignals(false); + } + } + return read_values; } -int villas::node::ib_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *ib = n->getData(); - struct ibv_send_wr wr[cnt], *bad_wr = nullptr; - struct ibv_sge sge[cnt][ib->qp_init.cap.max_recv_sge]; - struct ibv_wc wc[cnt]; - struct ibv_mr *mr; +int villas::node::ib_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *ib = n->getData(); + struct ibv_send_wr wr[cnt], *bad_wr = nullptr; + struct ibv_sge sge[cnt][ib->qp_init.cap.max_recv_sge]; + struct ibv_wc wc[cnt]; + struct ibv_mr *mr; - int ret; - unsigned sent = 0; // Used for first loop: prepare work requests to post to send queue + int ret; + unsigned sent = + 0; // Used for first loop: prepare work requests to post to send queue - n->logger->debug("ib_write is called"); + n->logger->debug("ib_write is called"); - if (n->getState() == State::CONNECTED) { - // TODO: fix release logic - // *release = 0; + if (n->getState() == State::CONNECTED) { + // TODO: fix release logic + // *release = 0; - // First, write + // First, write - // Get Memory Region - mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); + // Get Memory Region + mr = memory::ib_get_mr(pool_buffer(sample_pool(smps[0]))); - for (sent = 0; sent < cnt; sent++) { - int j = 0; + for (sent = 0; sent < cnt; sent++) { + int j = 0; - // Set Scatter/Gather element to data of sample + // Set Scatter/Gather element to data of sample - // Sequence - sge[sent][j].addr = (uint64_t) &smps[sent]->sequence; - sge[sent][j].length = sizeof(smps[sent]->sequence); - sge[sent][j].lkey = mr->lkey; + // Sequence + sge[sent][j].addr = (uint64_t)&smps[sent]->sequence; + sge[sent][j].length = sizeof(smps[sent]->sequence); + sge[sent][j].lkey = mr->lkey; - j++; + j++; - // Timespec origin - sge[sent][j].addr = (uint64_t) &smps[sent]->ts.origin; - sge[sent][j].length = sizeof(smps[sent]->ts.origin); - sge[sent][j].lkey = mr->lkey; + // Timespec origin + sge[sent][j].addr = (uint64_t)&smps[sent]->ts.origin; + sge[sent][j].length = sizeof(smps[sent]->ts.origin); + sge[sent][j].lkey = mr->lkey; - j++; + j++; - // Actual Payload - sge[sent][j].addr = (uint64_t) &smps[sent]->data; - sge[sent][j].length = SAMPLE_DATA_LENGTH(smps[sent]->length); - sge[sent][j].lkey = mr->lkey; + // Actual Payload + sge[sent][j].addr = (uint64_t)&smps[sent]->data; + sge[sent][j].length = SAMPLE_DATA_LENGTH(smps[sent]->length); + sge[sent][j].lkey = mr->lkey; - j++; + j++; - // Check if connection is connected or unconnected and set appropriate values - if (ib->conn.port_space == RDMA_PS_UDP) { - wr[sent].wr.ud.ah = ib->conn.ud.ah; - wr[sent].wr.ud.remote_qkey = ib->conn.ud.ud.qkey; - wr[sent].wr.ud.remote_qpn = ib->conn.ud.ud.qp_num; - } + // Check if connection is connected or unconnected and set appropriate values + if (ib->conn.port_space == RDMA_PS_UDP) { + wr[sent].wr.ud.ah = ib->conn.ud.ah; + wr[sent].wr.ud.remote_qkey = ib->conn.ud.ud.qkey; + wr[sent].wr.ud.remote_qpn = ib->conn.ud.ud.qp_num; + } - /* Check if data can be send inline + /* Check if data can be send inline * 32 byte meta data is always send. * Once every max_send_wr iterations a signal must be generated. Since we would need * an additional buffer if we were sending inlines with IBV_SEND_SIGNALED, we prefer * to send one samples every max_send_wr NOT inline (which thus generates a signal). */ - int send_inline = ((sge[sent][j-1].length + META_SIZE) < ib->qp_init.cap.max_inline_data) - && ((++ib->signaling_counter % ib->periodic_signaling) != 0) ? - ib->conn.send_inline : 0; + int send_inline = + ((sge[sent][j - 1].length + META_SIZE) < + ib->qp_init.cap.max_inline_data) && + ((++ib->signaling_counter % ib->periodic_signaling) != 0) + ? ib->conn.send_inline + : 0; - n->logger->debug("Sample will be send inline [0/1]: {}", send_inline); + n->logger->debug("Sample will be send inline [0/1]: {}", send_inline); - // Set Send Work Request - wr[sent].wr_id = (uintptr_t) smps[sent]; - wr[sent].sg_list = sge[sent]; - wr[sent].num_sge = j; - wr[sent].next = &wr[sent+1]; + // Set Send Work Request + wr[sent].wr_id = (uintptr_t)smps[sent]; + wr[sent].sg_list = sge[sent]; + wr[sent].num_sge = j; + wr[sent].next = &wr[sent + 1]; - wr[sent].send_flags = send_inline ? IBV_SEND_INLINE : IBV_SEND_SIGNALED; - wr[sent].opcode = IBV_WR_SEND; - } + wr[sent].send_flags = send_inline ? IBV_SEND_INLINE : IBV_SEND_SIGNALED; + wr[sent].opcode = IBV_WR_SEND; + } - n->logger->debug("Prepared {} send Work Requests", cnt); - wr[cnt-1].next = nullptr; + n->logger->debug("Prepared {} send Work Requests", cnt); + wr[cnt - 1].next = nullptr; - // Send linked list of Work Requests - ret = ibv_post_send(ib->ctx.id->qp, wr, &bad_wr); - n->logger->debug("Posted send Work Requests"); + // Send linked list of Work Requests + ret = ibv_post_send(ib->ctx.id->qp, wr, &bad_wr); + n->logger->debug("Posted send Work Requests"); - /* Reorder list. Place inline and unposted samples to the top + /* Reorder list. Place inline and unposted samples to the top * m will always be equal or smaller than *release */ - for (unsigned m = 0; m < cnt; m++) { - /* We can't use wr_id as identifier, since it is 0 for inline + for (unsigned m = 0; m < cnt; m++) { + /* We can't use wr_id as identifier, since it is 0 for inline * elements */ - if (ret && (wr[m].sg_list == bad_wr->sg_list)) { - /* The remaining work requests will be bad. Ripple through list + if (ret && (wr[m].sg_list == bad_wr->sg_list)) { + /* The remaining work requests will be bad. Ripple through list * and prepare them to be released */ - n->logger->debug("Bad WR occured with ID: {:#x} and S/G address: {:#x}: {}", - bad_wr->wr_id, (void *) bad_wr->sg_list, ret); + n->logger->debug( + "Bad WR occured with ID: {:#x} and S/G address: {:#x}: {}", + bad_wr->wr_id, (void *)bad_wr->sg_list, ret); - while (1) { - // TODO: fix release logic - // smps[*release] = smps[m]; - // (*release)++; // Increment number of samples to be released - sent--; // Decrement the number of successfully posted elements + while (1) { + // TODO: fix release logic + // smps[*release] = smps[m]; + // (*release)++; // Increment number of samples to be released + sent--; // Decrement the number of successfully posted elements - if (++m == cnt) break; - } - } - else if (wr[m].send_flags & IBV_SEND_INLINE) { - // TODO: fix release logic - // smps[*release] = smps[m]; - // (*release)++; - } - } + if (++m == cnt) + break; + } + } else if (wr[m].send_flags & IBV_SEND_INLINE) { + // TODO: fix release logic + // smps[*release] = smps[m]; + // (*release)++; + } + } - // TODO: fix release logic - // n->logger->debug("{} samples will be released (before WC)", *release); + // TODO: fix release logic + // n->logger->debug("{} samples will be released (before WC)", *release); - // Try to grab as many CQEs from CQ as there is space in *smps[] - // ret = ibv_poll_cq(ib->ctx.send_cq, cnt - *release, wc); + // Try to grab as many CQEs from CQ as there is space in *smps[] + // ret = ibv_poll_cq(ib->ctx.send_cq, cnt - *release, wc); - for (int i = 0; i < ret; i++) { - if (wc[i].status != IBV_WC_SUCCESS && wc[i].status != IBV_WC_WR_FLUSH_ERR) - n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", - wc[i].status); + for (int i = 0; i < ret; i++) { + if (wc[i].status != IBV_WC_SUCCESS && wc[i].status != IBV_WC_WR_FLUSH_ERR) + n->logger->warn("Work Completion status was not IBV_WC_SUCCESS: {}", + wc[i].status); - // TODO: fix release logic - // smps[*release] = (struct Sample *) (wc[i].wr_id); - // (*release)++; - } + // TODO: fix release logic + // smps[*release] = (struct Sample *) (wc[i].wr_id); + // (*release)++; + } - // TODO: fix release logic - // n->logger->debug("{} samples will be released (after WC)", *release); - } + // TODO: fix release logic + // n->logger->debug("{} samples will be released (after WC)", *release); + } - return sent; + return sent; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "infiniband"; - p.description = "Infiniband interface (libibverbs, librdmacm)"; - p.vectorize = 0; - p.size = sizeof(struct infiniband); - // TODO: fix - // p.pool_size = 8192; - p.destroy = ib_destroy; - p.parse = ib_parse; - p.check = ib_check; - p.print = ib_print; - p.start = ib_start; - p.stop = ib_stop; - p.read = ib_read; - p.write = ib_write; - p.reverse = ib_reverse; - p.memory_type = memory::ib; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "infiniband"; + p.description = "Infiniband interface (libibverbs, librdmacm)"; + p.vectorize = 0; + p.size = sizeof(struct infiniband); + // TODO: fix + // p.pool_size = 8192; + p.destroy = ib_destroy; + p.parse = ib_parse; + p.check = ib_check; + p.print = ib_print; + p.start = ib_start; + p.stop = ib_stop; + p.read = ib_read; + p.write = ib_write; + p.reverse = ib_reverse; + p.memory_type = memory::ib; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/influxdb.cpp b/lib/nodes/influxdb.cpp index 7080f56bb..8e357df9d 100644 --- a/lib/nodes/influxdb.cpp +++ b/lib/nodes/influxdb.cpp @@ -5,207 +5,193 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include -#include +#include #include +#include +#include -#include -#include +#include #include +#include #include #include -#include +#include +#include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int villas::node::influxdb_parse(NodeCompat *n, json_t *json) -{ - auto *i = n->getData(); +int villas::node::influxdb_parse(NodeCompat *n, json_t *json) { + auto *i = n->getData(); - json_error_t err; - int ret; + json_error_t err; + int ret; - char *tmp, *host, *port, *lasts; - const char *server, *key; + char *tmp, *host, *port, *lasts; + const char *server, *key; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s }", - "server", &server, - "key", &key - ); - if (ret) - throw ConfigError(json, err, "node-config-node-influx"); + ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s }", "server", &server, + "key", &key); + if (ret) + throw ConfigError(json, err, "node-config-node-influx"); - tmp = strdup(server); + tmp = strdup(server); - host = strtok_r(tmp, ":", &lasts); - port = strtok_r(nullptr, "", &lasts); + host = strtok_r(tmp, ":", &lasts); + port = strtok_r(nullptr, "", &lasts); - i->key = strdup(key); - i->host = strdup(host); - i->port = strdup(port ? port : "8089"); + i->key = strdup(key); + i->host = strdup(host); + i->port = strdup(port ? port : "8089"); - free(tmp); + free(tmp); - return 0; + return 0; } -int villas::node::influxdb_open(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::influxdb_open(NodeCompat *n) { + int ret; + auto *i = n->getData(); - struct addrinfo hints, *servinfo, *p; + struct addrinfo hints, *servinfo, *p; - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; - ret = getaddrinfo(i->host, i->port, &hints, &servinfo); - if (ret) - throw RuntimeError("Failed to lookup server: {}", gai_strerror(ret)); + ret = getaddrinfo(i->host, i->port, &hints, &servinfo); + if (ret) + throw RuntimeError("Failed to lookup server: {}", gai_strerror(ret)); - // Loop through all the results and connect to the first we can - for (p = servinfo; p != nullptr; p = p->ai_next) { - i->sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if (i->sd == -1) - throw SystemError("Failed to create socket"); + // Loop through all the results and connect to the first we can + for (p = servinfo; p != nullptr; p = p->ai_next) { + i->sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (i->sd == -1) + throw SystemError("Failed to create socket"); - ret = connect(i->sd, p->ai_addr, p->ai_addrlen); - if (ret == -1) { - n->logger->warn("Connect failed: {}", strerror(errno)); - close(i->sd); - continue; - } + ret = connect(i->sd, p->ai_addr, p->ai_addrlen); + if (ret == -1) { + n->logger->warn("Connect failed: {}", strerror(errno)); + close(i->sd); + continue; + } - // If we get here, we must have connected successfully - break; - } + // If we get here, we must have connected successfully + break; + } - return p ? 0 : -1; + return p ? 0 : -1; } -int villas::node::influxdb_close(NodeCompat *n) -{ - auto *i = n->getData(); +int villas::node::influxdb_close(NodeCompat *n) { + auto *i = n->getData(); - close(i->sd); + close(i->sd); - if (i->host) - free(i->host); - if (i->port) - free(i->port); - if (i->key) - free(i->key); + if (i->host) + free(i->host); + if (i->port) + free(i->port); + if (i->key) + free(i->key); - return 0; + return 0; } -int villas::node::influxdb_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *i = n->getData(); +int villas::node::influxdb_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *i = n->getData(); - char *buf = strf(""); - ssize_t sentlen, buflen; + char *buf = strf(""); + ssize_t sentlen, buflen; - for (unsigned k = 0; k < cnt; k++) { - const struct Sample *smp = smps[k]; + for (unsigned k = 0; k < cnt; k++) { + const struct Sample *smp = smps[k]; - // Key - strcatf(&buf, "%s", i->key); + // Key + strcatf(&buf, "%s", i->key); - // Fields - for (unsigned j = 0; j < smp->length; j++) { - const auto *data = &smp->data[j]; - auto sig = smp->signals->getByIndex(j); - if (!sig) - return -1; + // Fields + for (unsigned j = 0; j < smp->length; j++) { + const auto *data = &smp->data[j]; + auto sig = smp->signals->getByIndex(j); + if (!sig) + return -1; - if ( - sig->type != SignalType::BOOLEAN && - sig->type != SignalType::FLOAT && - sig->type != SignalType::INTEGER && - sig->type != SignalType::COMPLEX - ) { - n->logger->warn("Unsupported signal format. Skipping"); - continue; - } + if (sig->type != SignalType::BOOLEAN && sig->type != SignalType::FLOAT && + sig->type != SignalType::INTEGER && + sig->type != SignalType::COMPLEX) { + n->logger->warn("Unsupported signal format. Skipping"); + continue; + } - strcatf(&buf, "%c", j == 0 ? ' ' : ','); - if (sig->type == SignalType::COMPLEX) { - strcatf(&buf, "%s_re=%f, %s_im=%f", - sig->name.c_str(), std::real(data->z), - sig->name.c_str(), std::imag(data->z) - ); - } - else { - strcatf(&buf, "%s=", sig->name.c_str()); + strcatf(&buf, "%c", j == 0 ? ' ' : ','); + if (sig->type == SignalType::COMPLEX) { + strcatf(&buf, "%s_re=%f, %s_im=%f", sig->name.c_str(), + std::real(data->z), sig->name.c_str(), std::imag(data->z)); + } else { + strcatf(&buf, "%s=", sig->name.c_str()); - switch (sig->type) { - case SignalType::BOOLEAN: - strcatf(&buf, "%s", data->b ? "true" : "false"); - break; + switch (sig->type) { + case SignalType::BOOLEAN: + strcatf(&buf, "%s", data->b ? "true" : "false"); + break; - case SignalType::FLOAT: - strcatf(&buf, "%f", data->f); - break; + case SignalType::FLOAT: + strcatf(&buf, "%f", data->f); + break; - case SignalType::INTEGER: - strcatf(&buf, "%" PRIi64, data->i); - break; + case SignalType::INTEGER: + strcatf(&buf, "%" PRIi64, data->i); + break; - default: { } - } - } - } + default: { + } + } + } + } - // Timestamp - strcatf(&buf, " %lld%09lld\n", (long long) smp->ts.origin.tv_sec, - (long long) smp->ts.origin.tv_nsec); - } + // Timestamp + strcatf(&buf, " %lld%09lld\n", (long long)smp->ts.origin.tv_sec, + (long long)smp->ts.origin.tv_nsec); + } - buflen = strlen(buf) + 1; - sentlen = send(i->sd, buf, buflen, 0); - if (sentlen < 0) - return -1; - else if (sentlen < buflen) - n->logger->warn("Partial sent"); + buflen = strlen(buf) + 1; + sentlen = send(i->sd, buf, buflen, 0); + if (sentlen < 0) + return -1; + else if (sentlen < buflen) + n->logger->warn("Partial sent"); - free(buf); + free(buf); - return cnt; + return cnt; } -char * villas::node::influxdb_print(NodeCompat *n) -{ - auto *i = n->getData(); - char *buf = nullptr; +char *villas::node::influxdb_print(NodeCompat *n) { + auto *i = n->getData(); + char *buf = nullptr; - strcatf(&buf, "host=%s, port=%s, key=%s", i->host, i->port, i->key); + strcatf(&buf, "host=%s, port=%s, key=%s", i->host, i->port, i->key); - return buf; + return buf; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "influxdb"; - p.description = "Write results to InfluxDB"; - p.vectorize = 0; - p.size = sizeof(struct influxdb); - p.parse = influxdb_parse; - p.print = influxdb_print; - p.start = influxdb_open; - p.stop = influxdb_close; - p.write = influxdb_write; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "influxdb"; + p.description = "Write results to InfluxDB"; + p.vectorize = 0; + p.size = sizeof(struct influxdb); + p.parse = influxdb_parse; + p.print = influxdb_print; + p.start = influxdb_open; + p.stop = influxdb_close; + p.write = influxdb_write; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/kafka.cpp b/lib/nodes/kafka.cpp index 710de5fec..5eaccfaab 100644 --- a/lib/nodes/kafka.cpp +++ b/lib/nodes/kafka.cpp @@ -6,599 +6,594 @@ */ #include -#include #include +#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; // Each process has a list of clients for which a thread invokes the kafka loop -static -struct List clients; -static -pthread_t thread; -static -Logger logger; +static struct List clients; +static pthread_t thread; +static Logger logger; -static -void kafka_logger_cb(const rd_kafka_t *rk, int level, const char *fac, const char *buf) -{ +static void kafka_logger_cb(const rd_kafka_t *rk, int level, const char *fac, + const char *buf) { - switch (level) { - case LOG_EMERG: - case LOG_CRIT: - case LOG_ERR: - logger->error("{}: {}", fac, buf); - break; + switch (level) { + case LOG_EMERG: + case LOG_CRIT: + case LOG_ERR: + logger->error("{}: {}", fac, buf); + break; - case LOG_ALERT: - case LOG_WARNING: - logger->warn("{}: {}", fac, buf); - break; + case LOG_ALERT: + case LOG_WARNING: + logger->warn("{}: {}", fac, buf); + break; - case LOG_DEBUG: - logger->debug("{}: {}", fac, buf); - break; + case LOG_DEBUG: + logger->debug("{}: {}", fac, buf); + break; - case LOG_NOTICE: - case LOG_INFO: - default: - logger->info("{}: {}", fac, buf); - break; - } + case LOG_NOTICE: + case LOG_INFO: + default: + logger->info("{}: {}", fac, buf); + break; + } } -static -void kafka_message_cb(void *ctx, const rd_kafka_message_t *msg) -{ - int ret; - auto *n = (NodeCompat *) ctx; - auto *k = n->getData(); - struct Sample *smps[n->in.vectorize]; +static void kafka_message_cb(void *ctx, const rd_kafka_message_t *msg) { + int ret; + auto *n = (NodeCompat *)ctx; + auto *k = n->getData(); + struct Sample *smps[n->in.vectorize]; - n->logger->debug("Received a message of {} bytes from broker {}", msg->len, k->server); + n->logger->debug("Received a message of {} bytes from broker {}", msg->len, + k->server); - ret = sample_alloc_many(&k->pool, smps, n->in.vectorize); - if (ret <= 0) { - n->logger->warn("Pool underrun in consumer"); - return; - } + ret = sample_alloc_many(&k->pool, smps, n->in.vectorize); + if (ret <= 0) { + n->logger->warn("Pool underrun in consumer"); + return; + } - ret = k->formatter->sscan((char *) msg->payload, msg->len, nullptr, smps, n->in.vectorize); - if (ret < 0) { - n->logger->warn("Received an invalid message"); - n->logger->warn(" Payload: {}", (char *) msg->payload); - return; - } + ret = k->formatter->sscan((char *)msg->payload, msg->len, nullptr, smps, + n->in.vectorize); + if (ret < 0) { + n->logger->warn("Received an invalid message"); + n->logger->warn(" Payload: {}", (char *)msg->payload); + return; + } - if (ret == 0) { - n->logger->debug("Skip empty message"); - sample_decref_many(smps, n->in.vectorize); - return; - } + if (ret == 0) { + n->logger->debug("Skip empty message"); + sample_decref_many(smps, n->in.vectorize); + return; + } - ret = queue_signalled_push_many(&k->queue, (void **) smps, n->in.vectorize); - if (ret < (int) n->in.vectorize) - n->logger->warn("Failed to enqueue samples"); + ret = queue_signalled_push_many(&k->queue, (void **)smps, n->in.vectorize); + if (ret < (int)n->in.vectorize) + n->logger->warn("Failed to enqueue samples"); } -static -void * kafka_loop_thread(void *ctx) -{ - int ret; +static void *kafka_loop_thread(void *ctx) { + int ret; - // Set the cancel type of this thread to async - ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr); - if (ret != 0) - throw RuntimeError("Unable to set cancel type of Kafka communication thread to asynchronous."); + // Set the cancel type of this thread to async + ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr); + if (ret != 0) + throw RuntimeError("Unable to set cancel type of Kafka communication " + "thread to asynchronous."); - while (true) { - for (unsigned i = 0; i < list_length(&clients); i++) { - auto *n = (NodeCompat *) list_at(&clients, i); - auto *k = n->getData(); + while (true) { + for (unsigned i = 0; i < list_length(&clients); i++) { + auto *n = (NodeCompat *)list_at(&clients, i); + auto *k = n->getData(); - // Execute kafka loop for this client - if (k->consumer.client) { - rd_kafka_message_t *msg = rd_kafka_consumer_poll(k->consumer.client, k->timeout * 1000); - if (msg) { - kafka_message_cb((void *) n, msg); - rd_kafka_message_destroy(msg); - } - } - } - } + // Execute kafka loop for this client + if (k->consumer.client) { + rd_kafka_message_t *msg = + rd_kafka_consumer_poll(k->consumer.client, k->timeout * 1000); + if (msg) { + kafka_message_cb((void *)n, msg); + rd_kafka_message_destroy(msg); + } + } + } + } - return nullptr; + return nullptr; } -int villas::node::kafka_reverse(NodeCompat *n) -{ - auto *k = n->getData(); +int villas::node::kafka_reverse(NodeCompat *n) { + auto *k = n->getData(); - SWAP(k->produce, k->consume); + SWAP(k->produce, k->consume); - return 0; + return 0; } -int villas::node::kafka_init(NodeCompat *n) -{ - auto *k = n->getData(); +int villas::node::kafka_init(NodeCompat *n) { + auto *k = n->getData(); - // Default values - k->server = nullptr; - k->protocol = nullptr; - k->produce = nullptr; - k->consume = nullptr; - k->client_id = nullptr; - k->timeout = 1.0; + // Default values + k->server = nullptr; + k->protocol = nullptr; + k->produce = nullptr; + k->consume = nullptr; + k->client_id = nullptr; + k->timeout = 1.0; - k->consumer.client = nullptr; - k->consumer.group_id = nullptr; - k->producer.client = nullptr; - k->producer.topic = nullptr; + k->consumer.client = nullptr; + k->consumer.group_id = nullptr; + k->producer.client = nullptr; + k->producer.topic = nullptr; - k->sasl.mechanisms = nullptr; - k->sasl.username = nullptr; - k->sasl.password = nullptr; + k->sasl.mechanisms = nullptr; + k->sasl.username = nullptr; + k->sasl.password = nullptr; - k->ssl.ca = nullptr; + k->ssl.ca = nullptr; - k->formatter = nullptr; + k->formatter = nullptr; - return 0; + return 0; } -int villas::node::kafka_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_parse(NodeCompat *n, json_t *json) { + int ret; + auto *k = n->getData(); - const char *server; - const char *produce = nullptr; - const char *consume = nullptr; - const char *protocol; - const char *client_id = "villas-node"; - const char *group_id = nullptr; + const char *server; + const char *produce = nullptr; + const char *consume = nullptr; + const char *protocol; + const char *client_id = "villas-node"; + const char *group_id = nullptr; - json_error_t err; - json_t *json_ssl = nullptr; - json_t *json_sasl = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_ssl = nullptr; + json_t *json_sasl = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: s }, s?: { s?: s, s?: s }, s?: o, s: s, s?: F, s: s, s?: s, s?: o, s?: o }", - "out", - "produce", &produce, - "in", - "consume", &consume, - "group_id", &group_id, - "format", &json_format, - "server", &server, - "timeout", &k->timeout, - "protocol", &protocol, - "client_id", &client_id, - "ssl", &json_ssl, - "sasl", &json_sasl - ); - if (ret) - throw ConfigError(json, err, "node-config-node-kafka"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: { s?: s }, s?: { s?: s, s?: s }, s?: o, s: s, " + "s?: F, s: s, s?: s, s?: o, s?: o }", + "out", "produce", &produce, "in", "consume", &consume, + "group_id", &group_id, "format", &json_format, "server", + &server, "timeout", &k->timeout, "protocol", &protocol, + "client_id", &client_id, "ssl", &json_ssl, "sasl", + &json_sasl); + if (ret) + throw ConfigError(json, err, "node-config-node-kafka"); - k->server = strdup(server); - k->produce = produce ? strdup(produce) : nullptr; - k->consume = consume ? strdup(consume) : nullptr; - k->protocol = strdup(protocol); - k->client_id = strdup(client_id); - k->consumer.group_id = group_id ? strdup(group_id) : nullptr; + k->server = strdup(server); + k->produce = produce ? strdup(produce) : nullptr; + k->consume = consume ? strdup(consume) : nullptr; + k->protocol = strdup(protocol); + k->client_id = strdup(client_id); + k->consumer.group_id = group_id ? strdup(group_id) : nullptr; - if (strcmp(protocol, "SSL") && - strcmp(protocol, "PLAINTEXT") && - strcmp(protocol, "SASL_SSL") && - strcmp(protocol, "SASL_PLAINTEXT")) - throw ConfigError(json, "node-config-node-kafka-protocol", "Invalid security protocol: {}", protocol); + if (strcmp(protocol, "SSL") && strcmp(protocol, "PLAINTEXT") && + strcmp(protocol, "SASL_SSL") && strcmp(protocol, "SASL_PLAINTEXT")) + throw ConfigError(json, "node-config-node-kafka-protocol", + "Invalid security protocol: {}", protocol); - if (!k->produce && !k->consume) - throw ConfigError(json, "node-config-node-kafka", "At least one topic has to be specified for node {}", n->getName()); + if (!k->produce && !k->consume) + throw ConfigError(json, "node-config-node-kafka", + "At least one topic has to be specified for node {}", + n->getName()); - if (json_ssl) { - const char *ca; + if (json_ssl) { + const char *ca; - ret = json_unpack_ex(json_ssl, &err, 0, "{ s: s }", - "ca", &ca - ); - if (ret) - throw ConfigError(json_ssl, err, "node-config-node-kafka-ssl", "Failed to parse SSL configuration of node {}", n->getName()); + ret = json_unpack_ex(json_ssl, &err, 0, "{ s: s }", "ca", &ca); + if (ret) + throw ConfigError(json_ssl, err, "node-config-node-kafka-ssl", + "Failed to parse SSL configuration of node {}", + n->getName()); - k->ssl.ca = strdup(ca); - } + k->ssl.ca = strdup(ca); + } - if (json_sasl) { - const char *mechanisms; - const char *username; - const char *password; + if (json_sasl) { + const char *mechanisms; + const char *username; + const char *password; - ret = json_unpack_ex(json_sasl, &err, 0, "{ s: s, s: s, s: s }", - "mechanisms", &mechanisms, - "username", &username, - "password", &password - ); - if (ret) - throw ConfigError(json_sasl, err, "node-config-node-kafka-sasl", "Failed to parse SASL configuration"); + ret = json_unpack_ex(json_sasl, &err, 0, "{ s: s, s: s, s: s }", + "mechanisms", &mechanisms, "username", &username, + "password", &password); + if (ret) + throw ConfigError(json_sasl, err, "node-config-node-kafka-sasl", + "Failed to parse SASL configuration"); - k->sasl.mechanisms = strdup(mechanisms); - k->sasl.username = strdup(username); - k->sasl.password = strdup(password); - } + k->sasl.mechanisms = strdup(mechanisms); + k->sasl.username = strdup(username); + k->sasl.password = strdup(password); + } - // Format - if (k->formatter) - delete k->formatter; - k->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); - if (!k->formatter) - throw ConfigError(json_format, "node-config-node-kafka-format", "Invalid format configuration"); + // Format + if (k->formatter) + delete k->formatter; + k->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); + if (!k->formatter) + throw ConfigError(json_format, "node-config-node-kafka-format", + "Invalid format configuration"); - return 0; + return 0; } -int villas::node::kafka_prepare(NodeCompat *n) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_prepare(NodeCompat *n) { + int ret; + auto *k = n->getData(); - k->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + k->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - ret = pool_init(&k->pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + ret = pool_init(&k->pool, 1024, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&k->queue, 1024); - if (ret) - return ret; + ret = queue_signalled_init(&k->queue, 1024); + if (ret) + return ret; - return 0; + return 0; } -char * villas::node::kafka_print(NodeCompat *n) -{ - auto *k = n->getData(); +char *villas::node::kafka_print(NodeCompat *n) { + auto *k = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - strcatf(&buf, "bootstrap.server=%s, client.id=%s, security.protocol=%s", - k->server, - k->client_id, - k->protocol - ); + strcatf(&buf, "bootstrap.server=%s, client.id=%s, security.protocol=%s", + k->server, k->client_id, k->protocol); - // Only show if not default - if (k->produce) - strcatf(&buf, ", out.produce=%s", k->produce); + // Only show if not default + if (k->produce) + strcatf(&buf, ", out.produce=%s", k->produce); - if (k->consume) - strcatf(&buf, ", in.consume=%s", k->consume); + if (k->consume) + strcatf(&buf, ", in.consume=%s", k->consume); - return buf; + return buf; } -int villas::node::kafka_destroy(NodeCompat *n) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_destroy(NodeCompat *n) { + int ret; + auto *k = n->getData(); - if (k->producer.client) - rd_kafka_destroy(k->producer.client); + if (k->producer.client) + rd_kafka_destroy(k->producer.client); - if (k->consumer.client) - rd_kafka_destroy(k->consumer.client); + if (k->consumer.client) + rd_kafka_destroy(k->consumer.client); - if (k->formatter) - delete k->formatter; + if (k->formatter) + delete k->formatter; - ret = pool_destroy(&k->pool); - if (ret) - return ret; + ret = pool_destroy(&k->pool); + if (ret) + return ret; - ret = queue_signalled_destroy(&k->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&k->queue); + if (ret) + return ret; - if (k->produce) - free(k->produce); + if (k->produce) + free(k->produce); - if (k->consume) - free(k->consume); + if (k->consume) + free(k->consume); - if (k->protocol) - free(k->protocol); + if (k->protocol) + free(k->protocol); - if (k->client_id) - free(k->client_id); + if (k->client_id) + free(k->client_id); - free(k->server); + free(k->server); - return 0; + return 0; } -int villas::node::kafka_start(NodeCompat *n) -{ - int ret; - char errstr[1024]; - auto *k = n->getData(); +int villas::node::kafka_start(NodeCompat *n) { + int ret; + char errstr[1024]; + auto *k = n->getData(); - rd_kafka_conf_t *rdkconf = rd_kafka_conf_new(); - if (!rdkconf) - throw MemoryAllocationError(); + rd_kafka_conf_t *rdkconf = rd_kafka_conf_new(); + if (!rdkconf) + throw MemoryAllocationError(); - rd_kafka_conf_set_log_cb(rdkconf, kafka_logger_cb); + rd_kafka_conf_set_log_cb(rdkconf, kafka_logger_cb); - ret = rd_kafka_conf_set(rdkconf, "client.id", k->client_id, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf, "client.id", k->client_id, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - ret = rd_kafka_conf_set(rdkconf, "bootstrap.servers", k->server, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf, "bootstrap.servers", k->server, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - ret = rd_kafka_conf_set(rdkconf, "security.protocol", k->protocol, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf, "security.protocol", k->protocol, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - if (!strcmp(k->protocol, "SASL_SSL") || !strcmp(k->protocol, "SSL")) { - ret = rd_kafka_conf_set(rdkconf, "ssl.ca.location", k->ssl.ca, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; - } + if (!strcmp(k->protocol, "SASL_SSL") || !strcmp(k->protocol, "SSL")) { + ret = rd_kafka_conf_set(rdkconf, "ssl.ca.location", k->ssl.ca, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; + } - if (!strcmp(k->protocol, "SASL_PLAINTEXT") || !strcmp(k->protocol, "SASL_SSL")) { - ret = rd_kafka_conf_set(rdkconf, "sasl.mechanisms", k->sasl.mechanisms, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + if (!strcmp(k->protocol, "SASL_PLAINTEXT") || + !strcmp(k->protocol, "SASL_SSL")) { + ret = rd_kafka_conf_set(rdkconf, "sasl.mechanisms", k->sasl.mechanisms, + errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - ret = rd_kafka_conf_set(rdkconf, "sasl.username", k->sasl.username, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf, "sasl.username", k->sasl.username, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - ret = rd_kafka_conf_set(rdkconf, "sasl.password", k->sasl.password, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; - } + ret = rd_kafka_conf_set(rdkconf, "sasl.password", k->sasl.password, errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; + } - if (k->produce) { - // rd_kafka_new() will take ownership and free the passed rd_kafka_conf_t object, - // so we will need to create a copy first - rd_kafka_conf_t *rdkconf_prod = rd_kafka_conf_dup(rdkconf); - if (!rdkconf_prod) - throw MemoryAllocationError(); + if (k->produce) { + // rd_kafka_new() will take ownership and free the passed rd_kafka_conf_t object, + // so we will need to create a copy first + rd_kafka_conf_t *rdkconf_prod = rd_kafka_conf_dup(rdkconf); + if (!rdkconf_prod) + throw MemoryAllocationError(); - k->producer.client = rd_kafka_new(RD_KAFKA_PRODUCER, rdkconf_prod, errstr, sizeof(errstr)); - if (!k->producer.client) - goto kafka_config_error; + k->producer.client = + rd_kafka_new(RD_KAFKA_PRODUCER, rdkconf_prod, errstr, sizeof(errstr)); + if (!k->producer.client) + goto kafka_config_error; - rd_kafka_topic_conf_t *topic_conf = rd_kafka_topic_conf_new(); - if (!topic_conf) - throw MemoryAllocationError(); + rd_kafka_topic_conf_t *topic_conf = rd_kafka_topic_conf_new(); + if (!topic_conf) + throw MemoryAllocationError(); - ret = rd_kafka_topic_conf_set(topic_conf, "acks", "all", errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_topic_conf_set(topic_conf, "acks", "all", errstr, + sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - k->producer.topic = rd_kafka_topic_new(k->producer.client, k->produce, topic_conf); - if (!k->producer.topic) - throw MemoryAllocationError(); + k->producer.topic = + rd_kafka_topic_new(k->producer.client, k->produce, topic_conf); + if (!k->producer.topic) + throw MemoryAllocationError(); - n->logger->info("Connected producer to bootstrap server {}", k->server); - } + n->logger->info("Connected producer to bootstrap server {}", k->server); + } - if (k->consume) { - // rd_kafka_new() will take ownership and free the passed rd_kafka_conf_t object, - // so we will need to create a copy first - rd_kafka_conf_t *rdkconf_cons = rd_kafka_conf_dup(rdkconf); - if (!rdkconf_cons) - throw MemoryAllocationError(); + if (k->consume) { + // rd_kafka_new() will take ownership and free the passed rd_kafka_conf_t object, + // so we will need to create a copy first + rd_kafka_conf_t *rdkconf_cons = rd_kafka_conf_dup(rdkconf); + if (!rdkconf_cons) + throw MemoryAllocationError(); - rd_kafka_topic_partition_list_t *partitions = rd_kafka_topic_partition_list_new(1); - if (!partitions) - throw MemoryAllocationError(); + rd_kafka_topic_partition_list_t *partitions = + rd_kafka_topic_partition_list_new(1); + if (!partitions) + throw MemoryAllocationError(); - rd_kafka_topic_partition_t *partition = rd_kafka_topic_partition_list_add(partitions, k->consume, 0); - if (!partition) - throw RuntimeError("Failed to add new partition"); + rd_kafka_topic_partition_t *partition = + rd_kafka_topic_partition_list_add(partitions, k->consume, 0); + if (!partition) + throw RuntimeError("Failed to add new partition"); - ret = rd_kafka_conf_set(rdkconf_cons, "group.id", k->consumer.group_id, errstr, sizeof(errstr)); - if (ret != RD_KAFKA_CONF_OK) - goto kafka_config_error; + ret = rd_kafka_conf_set(rdkconf_cons, "group.id", k->consumer.group_id, + errstr, sizeof(errstr)); + if (ret != RD_KAFKA_CONF_OK) + goto kafka_config_error; - k->consumer.client = rd_kafka_new(RD_KAFKA_CONSUMER, rdkconf_cons, errstr, sizeof(errstr)); - if (!k->consumer.client) - throw MemoryAllocationError(); + k->consumer.client = + rd_kafka_new(RD_KAFKA_CONSUMER, rdkconf_cons, errstr, sizeof(errstr)); + if (!k->consumer.client) + throw MemoryAllocationError(); - ret = rd_kafka_subscribe(k->consumer.client, partitions); - if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) - throw RuntimeError("Error subscribing to {} at {}: {}", k->consume, k->server, rd_kafka_err2str((rd_kafka_resp_err_t) ret)); + ret = rd_kafka_subscribe(k->consumer.client, partitions); + if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) + throw RuntimeError("Error subscribing to {} at {}: {}", k->consume, + k->server, rd_kafka_err2str((rd_kafka_resp_err_t)ret)); - n->logger->info("Subscribed consumer from bootstrap server {}", k->server); - } + n->logger->info("Subscribed consumer from bootstrap server {}", k->server); + } - // Add client to global list of kafka clients - // so that thread can call kafka loop for this client - list_push(&clients, n); + // Add client to global list of kafka clients + // so that thread can call kafka loop for this client + list_push(&clients, n); - rd_kafka_conf_destroy(rdkconf); + rd_kafka_conf_destroy(rdkconf); - return 0; + return 0; kafka_config_error: - rd_kafka_conf_destroy(rdkconf); + rd_kafka_conf_destroy(rdkconf); - throw RuntimeError(errstr); + throw RuntimeError(errstr); - return -1; + return -1; } -int villas::node::kafka_stop(NodeCompat *n) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_stop(NodeCompat *n) { + int ret; + auto *k = n->getData(); - if (k->producer.client) { - ret = rd_kafka_flush(k->producer.client, k->timeout * 1000); - if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) - n->logger->error("Failed to flush messages: {}", rd_kafka_err2str((rd_kafka_resp_err_t) ret)); + if (k->producer.client) { + ret = rd_kafka_flush(k->producer.client, k->timeout * 1000); + if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) + n->logger->error("Failed to flush messages: {}", + rd_kafka_err2str((rd_kafka_resp_err_t)ret)); - /* If the output queue is still not empty there is an issue + /* If the output queue is still not empty there is an issue * with producing messages to the clusters. */ - if (rd_kafka_outq_len(k->producer.client) > 0) - n->logger->warn("{} message(s) were not delivered", rd_kafka_outq_len(k->producer.client)); - } + if (rd_kafka_outq_len(k->producer.client) > 0) + n->logger->warn("{} message(s) were not delivered", + rd_kafka_outq_len(k->producer.client)); + } - // Unregister client from global kafka client list - // so that kafka loop is no longer invoked for this client - // important to do that before disconnecting from broker, otherwise, kafka thread will attempt to reconnect - list_remove_all(&clients, n); + // Unregister client from global kafka client list + // so that kafka loop is no longer invoked for this client + // important to do that before disconnecting from broker, otherwise, kafka thread will attempt to reconnect + list_remove_all(&clients, n); - ret = queue_signalled_close(&k->queue); - if (ret) - return ret; + ret = queue_signalled_close(&k->queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::kafka_type_start(villas::node::SuperNode *sn) -{ - int ret; +int villas::node::kafka_type_start(villas::node::SuperNode *sn) { + int ret; - logger = logging.get("node:kafka"); + logger = logging.get("node:kafka"); - ret = list_init(&clients); - if (ret) - goto kafka_error; + ret = list_init(&clients); + if (ret) + goto kafka_error; - // Start thread here to run kafka loop for registered clients - ret = pthread_create(&thread, nullptr, kafka_loop_thread, nullptr); - if (ret) - goto kafka_error; + // Start thread here to run kafka loop for registered clients + ret = pthread_create(&thread, nullptr, kafka_loop_thread, nullptr); + if (ret) + goto kafka_error; - return 0; + return 0; kafka_error: - logger->warn("Error initialazing node type kafka"); + logger->warn("Error initialazing node type kafka"); - return ret; + return ret; } -int villas::node::kafka_type_stop() -{ - int ret; +int villas::node::kafka_type_stop() { + int ret; - // Stop thread here that executes kafka loop - ret = pthread_cancel(thread); - if (ret) - return ret; + // Stop thread here that executes kafka loop + ret = pthread_cancel(thread); + if (ret) + return ret; - logger->debug("Called pthread_cancel() on kafka communication management thread."); + logger->debug( + "Called pthread_cancel() on kafka communication management thread."); - ret = pthread_join(thread, nullptr); - if (ret) - goto kafka_error; + ret = pthread_join(thread, nullptr); + if (ret) + goto kafka_error; - // When this is called the list of clients should be empty - if (list_length(&clients) > 0) - throw RuntimeError("List of kafka clients contains elements at time of destruction. Call node_stop for each kafka node before stopping node type!"); + // When this is called the list of clients should be empty + if (list_length(&clients) > 0) + throw RuntimeError( + "List of kafka clients contains elements at time of destruction. Call " + "node_stop for each kafka node before stopping node type!"); - ret = list_destroy(&clients, nullptr, false); - if (ret) - goto kafka_error; + ret = list_destroy(&clients, nullptr, false); + if (ret) + goto kafka_error; - return 0; + return 0; kafka_error: - logger->warn("Error stoping node type kafka"); + logger->warn("Error stoping node type kafka"); - return ret; + return ret; } -int villas::node::kafka_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int pulled; - auto *k = n->getData(); - struct Sample *smpt[cnt]; +int villas::node::kafka_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int pulled; + auto *k = n->getData(); + struct Sample *smpt[cnt]; - pulled = queue_signalled_pull_many(&k->queue, (void **) smpt, cnt); + pulled = queue_signalled_pull_many(&k->queue, (void **)smpt, cnt); - sample_copy_many(smps, smpt, pulled); - sample_decref_many(smpt, pulled); + sample_copy_many(smps, smpt, pulled); + sample_decref_many(smpt, pulled); - return pulled; + return pulled; } -int villas::node::kafka_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *k = n->getData(); +int villas::node::kafka_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *k = n->getData(); - size_t wbytes; + size_t wbytes; - char data[DEFAULT_FORMAT_BUFFER_LENGTH]; + char data[DEFAULT_FORMAT_BUFFER_LENGTH]; - ret = k->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret < 0) - return ret; + ret = k->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret < 0) + return ret; - if (k->produce) { - ret = rd_kafka_produce(k->producer.topic, RD_KAFKA_PARTITION_UA, RD_KAFKA_MSG_F_COPY, - data, wbytes, NULL, 0, NULL); + if (k->produce) { + ret = rd_kafka_produce(k->producer.topic, RD_KAFKA_PARTITION_UA, + RD_KAFKA_MSG_F_COPY, data, wbytes, NULL, 0, NULL); - if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) { - n->logger->warn("Publish failed"); - return -abs(ret); - } - } - else - n->logger->warn("No produce possible because no produce topic is configured"); + if (ret != RD_KAFKA_RESP_ERR_NO_ERROR) { + n->logger->warn("Publish failed"); + return -abs(ret); + } + } else + n->logger->warn( + "No produce possible because no produce topic is configured"); - return cnt; + return cnt; } -int villas::node::kafka_poll_fds(NodeCompat *n, int fds[]) -{ - auto *k = n->getData(); +int villas::node::kafka_poll_fds(NodeCompat *n, int fds[]) { + auto *k = n->getData(); - fds[0] = queue_signalled_fd(&k->queue); + fds[0] = queue_signalled_fd(&k->queue); - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "kafka"; - p.description = "Kafka event message streaming (rdkafka)"; - p.vectorize = 0; - p.size = sizeof(struct kafka); - p.type.start = kafka_type_start; - p.type.stop = kafka_type_stop; - p.destroy = kafka_destroy; - p.prepare = kafka_prepare; - p.parse = kafka_parse; - p.prepare = kafka_prepare; - p.print = kafka_print; - p.init = kafka_init; - p.destroy = kafka_destroy; - p.start = kafka_start; - p.stop = kafka_stop; - p.read = kafka_read; - p.write = kafka_write; - p.reverse = kafka_reverse; - p.poll_fds = kafka_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "kafka"; + p.description = "Kafka event message streaming (rdkafka)"; + p.vectorize = 0; + p.size = sizeof(struct kafka); + p.type.start = kafka_type_start; + p.type.stop = kafka_type_stop; + p.destroy = kafka_destroy; + p.prepare = kafka_prepare; + p.parse = kafka_parse; + p.prepare = kafka_prepare; + p.print = kafka_print; + p.init = kafka_init; + p.destroy = kafka_destroy; + p.start = kafka_start; + p.stop = kafka_stop; + p.read = kafka_read; + p.write = kafka_write; + p.reverse = kafka_reverse; + p.poll_fds = kafka_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/loopback.cpp b/lib/nodes/loopback.cpp index 55cd70d91..a82385342 100644 --- a/lib/nodes/loopback.cpp +++ b/lib/nodes/loopback.cpp @@ -7,136 +7,127 @@ #include +#include #include +#include #include #include -#include -#include #include using namespace villas; using namespace villas::node; using namespace villas::utils; -LoopbackNode::LoopbackNode(const uuid_t &id, const std::string &name) : - Node(id, name), - queuelen(DEFAULT_QUEUE_LENGTH), - mode(QueueSignalledMode::AUTO) -{ - queue.queue.state = State::DESTROYED; +LoopbackNode::LoopbackNode(const uuid_t &id, const std::string &name) + : Node(id, name), queuelen(DEFAULT_QUEUE_LENGTH), + mode(QueueSignalledMode::AUTO) { + queue.queue.state = State::DESTROYED; } -LoopbackNode::~LoopbackNode() -{ - int ret __attribute__((unused)); +LoopbackNode::~LoopbackNode() { + int ret __attribute__((unused)); - ret = queue_signalled_destroy(&queue); + ret = queue_signalled_destroy(&queue); } -int LoopbackNode::prepare() -{ - assert(state == State::CHECKED); +int LoopbackNode::prepare() { + assert(state == State::CHECKED); - int ret = queue_signalled_init(&queue, queuelen, &memory::mmap, mode); - if (ret) - throw RuntimeError("Failed to initialize queue"); + int ret = queue_signalled_init(&queue, queuelen, &memory::mmap, mode); + if (ret) + throw RuntimeError("Failed to initialize queue"); - return Node::prepare(); + return Node::prepare(); } -int LoopbackNode::stop() -{ - int ret; +int LoopbackNode::stop() { + int ret; - ret = queue_signalled_close(&queue); - if (ret) - return ret; + ret = queue_signalled_close(&queue); + if (ret) + return ret; - return 0; + return 0; } -int LoopbackNode::_read(struct Sample * smps[], unsigned cnt) -{ - int avail; +int LoopbackNode::_read(struct Sample *smps[], unsigned cnt) { + int avail; - struct Sample *cpys[cnt]; + struct Sample *cpys[cnt]; - avail = queue_signalled_pull_many(&queue, (void **) cpys, cnt); + avail = queue_signalled_pull_many(&queue, (void **)cpys, cnt); - sample_copy_many(smps, cpys, avail); - sample_decref_many(cpys, avail); + sample_copy_many(smps, cpys, avail); + sample_decref_many(cpys, avail); - return avail; + return avail; } -int LoopbackNode::_write(struct Sample * smps[], unsigned cnt) -{ - sample_incref_many(smps, cnt); +int LoopbackNode::_write(struct Sample *smps[], unsigned cnt) { + sample_incref_many(smps, cnt); - int pushed = queue_signalled_push_many(&queue, (void **) smps, cnt); - if (pushed < 0) { - sample_decref_many(smps, cnt); - return pushed; - } + int pushed = queue_signalled_push_many(&queue, (void **)smps, cnt); + if (pushed < 0) { + sample_decref_many(smps, cnt); + return pushed; + } - // Released unpushed samples - if ((unsigned) pushed < cnt) { - sample_decref_many(smps + pushed, cnt - pushed); - logger->warn("Queue overrun"); - } + // Released unpushed samples + if ((unsigned)pushed < cnt) { + sample_decref_many(smps + pushed, cnt - pushed); + logger->warn("Queue overrun"); + } - return pushed; + return pushed; } -std::vector LoopbackNode::getPollFDs() -{ - return { queue_signalled_fd(&queue) }; +std::vector LoopbackNode::getPollFDs() { + return {queue_signalled_fd(&queue)}; } -const std::string & LoopbackNode::getDetails() -{ - if (details.empty()) { - details = fmt::format("queuelen={}", queuelen); - } +const std::string &LoopbackNode::getDetails() { + if (details.empty()) { + details = fmt::format("queuelen={}", queuelen); + } - return details; + return details; } -int LoopbackNode::parse(json_t *json) -{ - const char *mode_str = nullptr; +int LoopbackNode::parse(json_t *json) { + const char *mode_str = nullptr; - json_error_t err; - int ret; + json_error_t err; + int ret; - ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", - "queuelen", &queuelen, - "mode", &mode_str - ); - if (ret) - throw ConfigError(json, err, "node-config-node-loopback"); + ret = json_unpack_ex(json, &err, 0, "{ s?: i, s?: s }", "queuelen", &queuelen, + "mode", &mode_str); + if (ret) + throw ConfigError(json, err, "node-config-node-loopback"); - if (mode_str) { - if (!strcmp(mode_str, "auto")) - mode = QueueSignalledMode::AUTO; + if (mode_str) { + if (!strcmp(mode_str, "auto")) + mode = QueueSignalledMode::AUTO; #ifdef HAVE_EVENTFD - else if (!strcmp(mode_str, "eventfd")) - mode = QueueSignalledMode::EVENTFD; + else if (!strcmp(mode_str, "eventfd")) + mode = QueueSignalledMode::EVENTFD; #endif - else if (!strcmp(mode_str, "pthread")) - mode = QueueSignalledMode::PTHREAD; - else if (!strcmp(mode_str, "polling")) - mode = QueueSignalledMode::POLLING; - else - throw ConfigError(json, "node-config-node-loopback-mode", "Unknown mode '{}'", mode_str); - } + else if (!strcmp(mode_str, "pthread")) + mode = QueueSignalledMode::PTHREAD; + else if (!strcmp(mode_str, "polling")) + mode = QueueSignalledMode::POLLING; + else + throw ConfigError(json, "node-config-node-loopback-mode", + "Unknown mode '{}'", mode_str); + } - return Node::parse(json); + return Node::parse(json); } // Register node static char n[] = "loopback"; static char d[] = "loopback node-type"; -static NodePlugin nf; +static NodePlugin + nf; diff --git a/lib/nodes/loopback_internal.cpp b/lib/nodes/loopback_internal.cpp index e2f87d547..ed18875ba 100644 --- a/lib/nodes/loopback_internal.cpp +++ b/lib/nodes/loopback_internal.cpp @@ -7,100 +7,94 @@ #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::node; -static -InternalLoopbackNodeFactory nf; +static InternalLoopbackNodeFactory nf; -InternalLoopbackNode::InternalLoopbackNode(Node *src, unsigned id, unsigned ql) : - queuelen(ql), - source(src) -{ - auto name = fmt::format("{}.lo{}", src->getNameShort(), id); +InternalLoopbackNode::InternalLoopbackNode(Node *src, unsigned id, unsigned ql) + : queuelen(ql), source(src) { + auto name = fmt::format("{}.lo{}", src->getNameShort(), id); - uuid_t uuid; - int ret = uuid::generateFromString(uuid, fmt::format("lo{}", id), src->getUuid()); - if (ret) - throw RuntimeError("Failed to initialize UUID"); + uuid_t uuid; + int ret = + uuid::generateFromString(uuid, fmt::format("lo{}", id), src->getUuid()); + if (ret) + throw RuntimeError("Failed to initialize UUID"); - Node(uuid, name); + Node(uuid, name); - factory = &nf; - name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", name_short, nf.getName()); + factory = &nf; + name_long = fmt::format(CLR_RED("{}") "(" CLR_YEL("{}") ")", name_short, + nf.getName()); - auto logger_name = fmt::format("node:{}", getNameShort()); + auto logger_name = fmt::format("node:{}", getNameShort()); - logger = logging.get(logger_name); + logger = logging.get(logger_name); - in.signals = source->getInputSignals(false); + in.signals = source->getInputSignals(false); - ret = queue_signalled_init(&queue, queuelen); - if (ret) - throw RuntimeError("Failed to initialize queue"); + ret = queue_signalled_init(&queue, queuelen); + if (ret) + throw RuntimeError("Failed to initialize queue"); - state = State::PREPARED; + state = State::PREPARED; } -InternalLoopbackNode::~InternalLoopbackNode() -{ - int ret __attribute__((unused)); +InternalLoopbackNode::~InternalLoopbackNode() { + int ret __attribute__((unused)); - ret = queue_signalled_destroy(&queue); + ret = queue_signalled_destroy(&queue); } -int InternalLoopbackNode::stop() -{ - int ret; +int InternalLoopbackNode::stop() { + int ret; - ret = queue_signalled_close(&queue); - if (ret) - return ret; + ret = queue_signalled_close(&queue); + if (ret) + return ret; - return 0; + return 0; } -int InternalLoopbackNode::_read(struct Sample * smps[], unsigned cnt) -{ - int avail; +int InternalLoopbackNode::_read(struct Sample *smps[], unsigned cnt) { + int avail; - struct Sample *cpys[cnt]; + struct Sample *cpys[cnt]; - avail = queue_signalled_pull_many(&queue, (void **) cpys, cnt); + avail = queue_signalled_pull_many(&queue, (void **)cpys, cnt); - sample_copy_many(smps, cpys, avail); - sample_decref_many(cpys, avail); + sample_copy_many(smps, cpys, avail); + sample_decref_many(cpys, avail); - return avail; + return avail; } -int InternalLoopbackNode::_write(struct Sample * smps[], unsigned cnt) -{ - sample_incref_many(smps, cnt); +int InternalLoopbackNode::_write(struct Sample *smps[], unsigned cnt) { + sample_incref_many(smps, cnt); - int pushed = queue_signalled_push_many(&queue, (void **) smps, cnt); - if (pushed < 0) { - sample_decref_many(smps, cnt); - return pushed; - } + int pushed = queue_signalled_push_many(&queue, (void **)smps, cnt); + if (pushed < 0) { + sample_decref_many(smps, cnt); + return pushed; + } - // Released unpushed samples - if ((unsigned) pushed < cnt) { - sample_decref_many(smps + pushed, cnt - pushed); - logger->warn("Queue overrun"); - } + // Released unpushed samples + if ((unsigned)pushed < cnt) { + sample_decref_many(smps + pushed, cnt - pushed); + logger->warn("Queue overrun"); + } - return pushed; + return pushed; } -std::vector InternalLoopbackNode::getPollFDs() -{ - return { queue_signalled_fd(&queue) }; +std::vector InternalLoopbackNode::getPollFDs() { + return {queue_signalled_fd(&queue)}; } diff --git a/lib/nodes/modbus.cpp b/lib/nodes/modbus.cpp index 13bd07beb..ee751a1c2 100644 --- a/lib/nodes/modbus.cpp +++ b/lib/nodes/modbus.cpp @@ -40,908 +40,875 @@ #include +#include #include #include -#include #include -#include #include -#include - +#include using namespace villas; using namespace villas::node; using namespace villas::node::modbus; using namespace villas::utils; -int64_t RegisterMappingSingle::IntegerToInteger::read(uint16_t const *registers) const -{ - int64_t integer = 0; - auto ptr = word_endianess == Endianess::Big ? registers + num_registers - 1 : registers; +int64_t +RegisterMappingSingle::IntegerToInteger::read(uint16_t const *registers) const { + int64_t integer = 0; + auto ptr = word_endianess == Endianess::Big ? registers + num_registers - 1 + : registers; - for (size_t i = 0; i < num_registers; ++i) { - integer <<= sizeof(uint16_t) * 8; + for (size_t i = 0; i < num_registers; ++i) { + integer <<= sizeof(uint16_t) * 8; - if (byte_endianess == Endianess::Big) - integer |= (int64_t) *ptr; - else - integer |= (int64_t) byteswap(*ptr); + if (byte_endianess == Endianess::Big) + integer |= (int64_t)*ptr; + else + integer |= (int64_t)byteswap(*ptr); - if (word_endianess == Endianess::Big) - --ptr; - else - ++ptr; - } + if (word_endianess == Endianess::Big) + --ptr; + else + ++ptr; + } - return integer; + return integer; } -void RegisterMappingSingle::IntegerToInteger::write(int64_t integer, uint16_t *registers) const -{ - auto ptr = word_endianess == Endianess::Big ? registers : registers + num_registers - 1; +void RegisterMappingSingle::IntegerToInteger::write(int64_t integer, + uint16_t *registers) const { + auto ptr = word_endianess == Endianess::Big ? registers + : registers + num_registers - 1; - for (size_t i = 0; i < num_registers; ++i) { - if (byte_endianess == Endianess::Big) - *ptr = (uint16_t) integer; - else - *ptr = byteswap((uint16_t) integer); + for (size_t i = 0; i < num_registers; ++i) { + if (byte_endianess == Endianess::Big) + *ptr = (uint16_t)integer; + else + *ptr = byteswap((uint16_t)integer); - if (word_endianess == Endianess::Big) - ++ptr; - else - --ptr; + if (word_endianess == Endianess::Big) + ++ptr; + else + --ptr; - integer >>= sizeof(uint16_t) * 8; - } + integer >>= sizeof(uint16_t) * 8; + } } -double RegisterMappingSingle::IntegerToFloat::read(uint16_t const *registers) const -{ - int64_t integer = integer_conversion.read(registers); +double +RegisterMappingSingle::IntegerToFloat::read(uint16_t const *registers) const { + int64_t integer = integer_conversion.read(registers); - return integer * scale + offset; + return integer * scale + offset; } -void RegisterMappingSingle::IntegerToFloat::write(double d, uint16_t *registers) const -{ - int64_t integer = (d - offset) / scale; +void RegisterMappingSingle::IntegerToFloat::write(double d, + uint16_t *registers) const { + int64_t integer = (d - offset) / scale; - integer_conversion.write(integer, registers); + integer_conversion.write(integer, registers); } -double RegisterMappingSingle::FloatToFloat::read(uint16_t const *registers) const -{ - static_assert(sizeof(float) == sizeof(uint32_t)); +double +RegisterMappingSingle::FloatToFloat::read(uint16_t const *registers) const { + static_assert(sizeof(float) == sizeof(uint32_t)); - auto const conversion = IntegerToInteger { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .num_registers = 2, - }; + auto const conversion = IntegerToInteger{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = 2, + }; - union { - uint32_t i; - float f; - } value; + union { + uint32_t i; + float f; + } value; - value.i = (uint32_t) conversion.read(registers); + value.i = (uint32_t)conversion.read(registers); - return value.f * scale + offset; + return value.f * scale + offset; } -void RegisterMappingSingle::FloatToFloat::write(double d, uint16_t *registers) const -{ - static_assert(sizeof(float) == sizeof(uint32_t)); +void RegisterMappingSingle::FloatToFloat::write(double d, + uint16_t *registers) const { + static_assert(sizeof(float) == sizeof(uint32_t)); - auto const conversion = IntegerToInteger { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .num_registers = 2, - }; + auto const conversion = IntegerToInteger{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = 2, + }; - union { - uint32_t i; - float f; - } value; + union { + uint32_t i; + float f; + } value; - value.f = (d - offset) / scale; + value.f = (d - offset) / scale; - conversion.write((int64_t) value.i, registers); + conversion.write((int64_t)value.i, registers); } -bool RegisterMappingSingle::BitToBool::read(uint16_t reg) const -{ - return (reg >> bit) & 1; +bool RegisterMappingSingle::BitToBool::read(uint16_t reg) const { + return (reg >> bit) & 1; } -RegisterMappingSingle::RegisterMappingSingle(unsigned int signal_index, modbus_addr_t address) : - conversion(IntegerToInteger { - .word_endianess = Endianess::Big, - .byte_endianess = Endianess::Big, - .num_registers = 1, - }), - signal_index(signal_index), - address(address) -{ } +RegisterMappingSingle::RegisterMappingSingle(unsigned int signal_index, + modbus_addr_t address) + : conversion(IntegerToInteger{ + .word_endianess = Endianess::Big, + .byte_endianess = Endianess::Big, + .num_registers = 1, + }), + signal_index(signal_index), address(address) {} -SignalData RegisterMappingSingle::read(uint16_t const *registers, modbus_addr_t length) const -{ - SignalData data; +SignalData RegisterMappingSingle::read(uint16_t const *registers, + modbus_addr_t length) const { + SignalData data; - if (num_registers() != length) - throw RuntimeError { "reading from invalid register range" }; + if (num_registers() != length) + throw RuntimeError{"reading from invalid register range"}; - if (auto i2i = std::get_if(&conversion)) - data.i = i2i->read(registers); - else if (auto i2f = std::get_if(&conversion)) - data.f = i2f->read(registers); - else if (auto f2f = std::get_if(&conversion)) - data.f = f2f->read(registers); - else if (auto b2b = std::get_if(&conversion)) - data.b = b2b->read(*registers); - else - throw RuntimeError { "read unsupported" }; + if (auto i2i = std::get_if(&conversion)) + data.i = i2i->read(registers); + else if (auto i2f = std::get_if(&conversion)) + data.f = i2f->read(registers); + else if (auto f2f = std::get_if(&conversion)) + data.f = f2f->read(registers); + else if (auto b2b = std::get_if(&conversion)) + data.b = b2b->read(*registers); + else + throw RuntimeError{"read unsupported"}; - return data; + return data; } -void RegisterMappingSingle::write(SignalData data, uint16_t *registers, modbus_addr_t length) const -{ - if (num_registers() != length) - throw RuntimeError { "writing to invalid register range" }; +void RegisterMappingSingle::write(SignalData data, uint16_t *registers, + modbus_addr_t length) const { + if (num_registers() != length) + throw RuntimeError{"writing to invalid register range"}; - if (auto i2i = std::get_if(&conversion)) - i2i->write(data.i, registers); - else if (auto i2f = std::get_if(&conversion)) - i2f->write(data.f, registers); - else if (auto f2f = std::get_if(&conversion)) - f2f->write(data.f, registers); - else - throw RuntimeError { "write unsupported" }; + if (auto i2i = std::get_if(&conversion)) + i2i->write(data.i, registers); + else if (auto i2f = std::get_if(&conversion)) + i2f->write(data.f, registers); + else if (auto f2f = std::get_if(&conversion)) + f2f->write(data.f, registers); + else + throw RuntimeError{"write unsupported"}; } -modbus_addr_t RegisterMappingSingle::num_registers() const -{ - if (auto i2i = std::get_if(&conversion)) - return i2i->num_registers; +modbus_addr_t RegisterMappingSingle::num_registers() const { + if (auto i2i = std::get_if(&conversion)) + return i2i->num_registers; - if (auto i2f = std::get_if(&conversion)) - return i2f->integer_conversion.num_registers; + if (auto i2f = std::get_if(&conversion)) + return i2f->integer_conversion.num_registers; - if (std::holds_alternative(conversion)) - return 2; + if (std::holds_alternative(conversion)) + return 2; - if (std::holds_alternative(conversion)) - return 1; + if (std::holds_alternative(conversion)) + return 1; - throw RuntimeError { "unreachable" }; + throw RuntimeError{"unreachable"}; } -uint16_t modbus::byteswap(uint16_t i) -{ - uint8_t low = (i & 0x00FF); - uint8_t high = (i & 0xFF00) >> 8; - return (low << 8) | high; +uint16_t modbus::byteswap(uint16_t i) { + uint8_t low = (i & 0x00FF); + uint8_t high = (i & 0xFF00) >> 8; + return (low << 8) | high; } -modbus_addr_t modbus::blockBegin(RegisterMappingSingle const &single) -{ - return single.address; +modbus_addr_t modbus::blockBegin(RegisterMappingSingle const &single) { + return single.address; } -modbus_addr_t modbus::blockBegin(RegisterMappingBlock const &block) -{ - assert(!block.empty()); - return blockBegin(block.front()); +modbus_addr_t modbus::blockBegin(RegisterMappingBlock const &block) { + assert(!block.empty()); + return blockBegin(block.front()); } -modbus_addr_t modbus::blockBegin(RegisterMapping const &mapping) -{ - return std::visit([](auto &v){ - return blockBegin(v); - }, mapping); +modbus_addr_t modbus::blockBegin(RegisterMapping const &mapping) { + return std::visit([](auto &v) { return blockBegin(v); }, mapping); } -modbus_addr_t modbus::blockEnd(RegisterMappingSingle const &single) -{ - return single.address + single.num_registers(); +modbus_addr_t modbus::blockEnd(RegisterMappingSingle const &single) { + return single.address + single.num_registers(); } -modbus_addr_t modbus::blockEnd(RegisterMappingBlock const &block) -{ - assert(!block.empty()); - return blockEnd(block.back()); +modbus_addr_t modbus::blockEnd(RegisterMappingBlock const &block) { + assert(!block.empty()); + return blockEnd(block.back()); } -modbus_addr_t modbus::blockEnd(RegisterMapping const &mapping) -{ - return std::visit([](auto &v){ - return blockEnd(v); - }, mapping); +modbus_addr_t modbus::blockEnd(RegisterMapping const &mapping) { + return std::visit([](auto &v) { return blockEnd(v); }, mapping); } -modbus_addr_t modbus::mappedRegisters(RegisterMappingSingle const &single) -{ - return single.num_registers(); +modbus_addr_t modbus::mappedRegisters(RegisterMappingSingle const &single) { + return single.num_registers(); } -modbus_addr_t modbus::mappedRegisters(RegisterMappingBlock const &block) -{ - auto mapped = 0; +modbus_addr_t modbus::mappedRegisters(RegisterMappingBlock const &block) { + auto mapped = 0; - modbus_addr_t last_address = -1; - for (auto &single : block) { - if (single.address != last_address) - mapped += single.num_registers(); + modbus_addr_t last_address = -1; + for (auto &single : block) { + if (single.address != last_address) + mapped += single.num_registers(); - last_address = single.address; - } + last_address = single.address; + } - return mapped; + return mapped; } -modbus_addr_t modbus::mappedRegisters(RegisterMapping const &mapping) -{ - return std::visit([](auto &v){ - return mappedRegisters(v); - }, mapping); +modbus_addr_t modbus::mappedRegisters(RegisterMapping const &mapping) { + return std::visit([](auto &v) { return mappedRegisters(v); }, mapping); } -modbus_addrdiff_t modbus::blockDistance(RegisterMapping const &lhs, RegisterMapping const &rhs) -{ - if (blockBegin(rhs) >= blockEnd(lhs)) - return (modbus_addrdiff_t) blockBegin(rhs) - blockEnd(lhs); +modbus_addrdiff_t modbus::blockDistance(RegisterMapping const &lhs, + RegisterMapping const &rhs) { + if (blockBegin(rhs) >= blockEnd(lhs)) + return (modbus_addrdiff_t)blockBegin(rhs) - blockEnd(lhs); - if (blockBegin(lhs) >= blockEnd(rhs)) - return (modbus_addrdiff_t) blockBegin(lhs) - blockEnd(rhs); + if (blockBegin(lhs) >= blockEnd(rhs)) + return (modbus_addrdiff_t)blockBegin(lhs) - blockEnd(rhs); - if (hasOverlappingBitMapping(lhs, rhs)) - return -1; + if (hasOverlappingBitMapping(lhs, rhs)) + return -1; - throw RuntimeError { "overlapping mappings" }; + throw RuntimeError{"overlapping mappings"}; } -bool modbus::hasOverlappingBitMapping(RegisterMapping const &lhs, RegisterMapping const &rhs) -{ - // Only check if there is exactly 1 register of overlap. - if (blockEnd(lhs) - blockBegin(rhs) != 1 && blockEnd(rhs) - blockBegin(lhs) != 1) - return false; +bool modbus::hasOverlappingBitMapping(RegisterMapping const &lhs, + RegisterMapping const &rhs) { + // Only check if there is exactly 1 register of overlap. + if (blockEnd(lhs) - blockBegin(rhs) != 1 && + blockEnd(rhs) - blockBegin(lhs) != 1) + return false; - // Assume that lhs is at a lower address than rhs. - if (blockBegin(rhs) < blockBegin(lhs) || blockEnd(rhs) < blockEnd(lhs)) - return hasOverlappingBitMapping(rhs, lhs); + // Assume that lhs is at a lower address than rhs. + if (blockBegin(rhs) < blockBegin(lhs) || blockEnd(rhs) < blockEnd(lhs)) + return hasOverlappingBitMapping(rhs, lhs); - // Get the last mapping from the lhs block. - RegisterMappingSingle const *lhs_back = nullptr; - if (auto single = std::get_if(&lhs)) - lhs_back = single; - else if (auto block = std::get_if(&lhs)) - lhs_back = &block->back(); - else - return false; + // Get the last mapping from the lhs block. + RegisterMappingSingle const *lhs_back = nullptr; + if (auto single = std::get_if(&lhs)) + lhs_back = single; + else if (auto block = std::get_if(&lhs)) + lhs_back = &block->back(); + else + return false; - // We are only interested in bit mappings. - if (!std::holds_alternative(lhs_back->conversion)) - return false; + // We are only interested in bit mappings. + if (!std::holds_alternative( + lhs_back->conversion)) + return false; - // Get the first mapping from the rhs block. - RegisterMappingSingle const *rhs_front = nullptr; - if (auto single = std::get_if(&rhs)) - rhs_front = single; - else if (auto block = std::get_if(&rhs)) - rhs_front = &block->front(); - else - return false; + // Get the first mapping from the rhs block. + RegisterMappingSingle const *rhs_front = nullptr; + if (auto single = std::get_if(&rhs)) + rhs_front = single; + else if (auto block = std::get_if(&rhs)) + rhs_front = &block->front(); + else + return false; - // We are only interested in bit mappings. - if (!std::holds_alternative(rhs_front->conversion)) - return false; + // We are only interested in bit mappings. + if (!std::holds_alternative( + rhs_front->conversion)) + return false; - // The last register of lhs and the first register of rhs overlap and are both bit mappings. - return true; + // The last register of lhs and the first register of rhs overlap and are both bit mappings. + return true; } -bool modbus::compareBlockAddress(RegisterMapping const &lhs, RegisterMapping const &rhs) -{ - if (blockBegin(rhs) >= blockEnd(lhs)) - return true; +bool modbus::compareBlockAddress(RegisterMapping const &lhs, + RegisterMapping const &rhs) { + if (blockBegin(rhs) >= blockEnd(lhs)) + return true; - if (blockBegin(lhs) >= blockEnd(rhs)) - return false; + if (blockBegin(lhs) >= blockEnd(rhs)) + return false; - if (hasOverlappingBitMapping(lhs, rhs)) - return false; + if (hasOverlappingBitMapping(lhs, rhs)) + return false; - throw RuntimeError { "overlapping mappings" }; + throw RuntimeError{"overlapping mappings"}; } -bool ModbusNode::isReconnecting() -{ - return reconnecting.load(); +bool ModbusNode::isReconnecting() { return reconnecting.load(); } + +void ModbusNode::reconnect() { + if (reconnecting.exchange(true)) + return; + + logger->error("No connection to the Modbus server. Reconnecting..."); + + std::thread([this]() { + auto start = std::chrono::steady_clock::now(); + + if (modbus_connect(modbus_context) == -1) { + logger->error("reconnect failure: ", modbus_strerror(errno)); + std::this_thread::sleep_until( + start + std::chrono::duration(reconnect_interval)); + } + + reconnecting.store(false); + }).detach(); } -void ModbusNode::reconnect() -{ - if (reconnecting.exchange(true)) - return; +void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, + RegisterMappingBlock const &rhs) { + if (auto lhs_single = std::get_if(&lhs)) + lhs = RegisterMappingBlock{*lhs_single}; - logger->error("No connection to the Modbus server. Reconnecting..."); - - std::thread([this](){ - auto start = std::chrono::steady_clock::now(); - - if (modbus_connect(modbus_context) == -1) { - logger->error("reconnect failure: ", modbus_strerror(errno)); - std::this_thread::sleep_until(start + std::chrono::duration(reconnect_interval)); - } - - reconnecting.store(false); - }).detach(); + auto &block = std::get(lhs); + block.reserve(blockEnd(rhs) - blockBegin(lhs)); + std::copy(std::begin(rhs), std::end(rhs), std::back_inserter(block)); } -void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, RegisterMappingBlock const &rhs) -{ - if (auto lhs_single = std::get_if(&lhs)) - lhs = RegisterMappingBlock { *lhs_single }; +void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, + RegisterMappingSingle const &rhs) { + if (auto lhs_single = std::get_if(&lhs)) + lhs = RegisterMappingBlock{*lhs_single}; - auto &block = std::get(lhs); - block.reserve(blockEnd(rhs) - blockBegin(lhs)); - std::copy(std::begin(rhs), std::end(rhs), std::back_inserter(block)); + auto &block = std::get(lhs); + block.push_back(rhs); } -void ModbusNode::mergeMappingInplace(RegisterMapping &lhs, RegisterMappingSingle const &rhs) -{ - if (auto lhs_single = std::get_if(&lhs)) - lhs = RegisterMappingBlock { *lhs_single }; +bool ModbusNode::tryMergeMappingInplace(RegisterMapping &lhs, + RegisterMapping const &rhs) { + auto block_size = blockEnd(rhs) - blockBegin(lhs); - auto &block = std::get(lhs); - block.push_back(rhs); + if (block_size >= max_block_size) + return false; + + auto block_usage = + (mappedRegisters(lhs) + mappedRegisters(rhs)) / (float)block_size; + + if (block_usage < min_block_usage) + return false; + + std::visit([&lhs](auto const &rhs) { mergeMappingInplace(lhs, rhs); }, rhs); + + return true; } -bool ModbusNode::tryMergeMappingInplace(RegisterMapping &lhs, RegisterMapping const &rhs) -{ - auto block_size = blockEnd(rhs) - blockBegin(lhs); +void ModbusNode::mergeMappings(std::vector &mappings, + modbus_addrdiff_t max_block_distance) { + if (std::size(mappings) < 2) + return; - if (block_size >= max_block_size) - return false; + // Sort all mappings by their block address. + std::sort(std::begin(mappings), std::end(mappings), compareBlockAddress); - auto block_usage = (mappedRegisters(lhs) + mappedRegisters(rhs)) / (float) block_size; + // Calculate the distances. (number of unused registers inbetween mappings) + auto distances = std::vector(); + distances.reserve(std::size(mappings)); + for (size_t i = 1; i < std::size(mappings); i++) + distances.push_back(blockDistance(mappings[i - 1], mappings[i])); - if (block_usage < min_block_usage) - return false; + for (;;) { + // Try to group the mappings closest to each other first. + auto min_distance = + std::min_element(std::begin(distances), std::end(distances)); - std::visit([&lhs](auto const &rhs){ - mergeMappingInplace(lhs, rhs); - }, rhs); + // The closest distance is too far to merge, abort the merging process. + if (min_distance == std::end(distances) || + *min_distance >= max_block_distance) + break; - return true; + // Find the mappings to the left and right of the minimum distance. + auto i = std::distance(std::begin(distances), min_distance); + auto left_mapping = std::next(std::begin(mappings), i); + auto right_mapping = std::next(std::begin(mappings), i + 1); + + if (tryMergeMappingInplace(*left_mapping, *right_mapping)) { + // Remove the right mapping and the distance + // if it could be merged into the left mapping. + mappings.erase(right_mapping); + distances.erase(min_distance); + } else { + // Set the distance to a value, so that it won't be retried. + *min_distance = max_block_distance; + } + } } -void ModbusNode::mergeMappings(std::vector &mappings, modbus_addrdiff_t max_block_distance) -{ - if (std::size(mappings) < 2) - return; +int ModbusNode::readBlock(RegisterMapping const &mapping, SignalData *data, + size_t size) { + if (isReconnecting()) + return -1; - // Sort all mappings by their block address. - std::sort(std::begin(mappings), std::end(mappings), compareBlockAddress); + auto address = blockBegin(mapping); + auto block_size = blockEnd(mapping) - address; - // Calculate the distances. (number of unused registers inbetween mappings) - auto distances = std::vector(); - distances.reserve(std::size(mappings)); - for (size_t i = 1; i < std::size(mappings); i++) - distances.push_back(blockDistance(mappings[i-1], mappings[i])); + read_buffer.resize(block_size); - for (;;) { - // Try to group the mappings closest to each other first. - auto min_distance = std::min_element(std::begin(distances), std::end(distances)); + if (modbus_read_registers(modbus_context, address, block_size, + read_buffer.data()) == -1) { + logger->error("read registers failure: ", modbus_strerror(errno)); - // The closest distance is too far to merge, abort the merging process. - if (min_distance == std::end(distances) || *min_distance >= max_block_distance) - break; + reconnect(); - // Find the mappings to the left and right of the minimum distance. - auto i = std::distance(std::begin(distances), min_distance); - auto left_mapping = std::next(std::begin(mappings), i); - auto right_mapping = std::next(std::begin(mappings), i+1); + return -1; + } - if (tryMergeMappingInplace(*left_mapping, *right_mapping)) { - // Remove the right mapping and the distance - // if it could be merged into the left mapping. - mappings.erase(right_mapping); - distances.erase(min_distance); - } else { - // Set the distance to a value, so that it won't be retried. - *min_distance = max_block_distance; - } - } + return readMapping(mapping, read_buffer.data(), read_buffer.size(), data, + size); } -int ModbusNode::readBlock(RegisterMapping const &mapping, SignalData *data, size_t size) -{ - if (isReconnecting()) - return -1; - - auto address = blockBegin(mapping); - auto block_size = blockEnd(mapping) - address; - - read_buffer.resize(block_size); - - if (modbus_read_registers(modbus_context, address, block_size, read_buffer.data()) == -1) { - logger->error("read registers failure: ", modbus_strerror(errno)); - - reconnect(); - - return -1; - } - - return readMapping(mapping, read_buffer.data(), read_buffer.size(), data, size); +int ModbusNode::readMapping(RegisterMapping const &mapping, + uint16_t const *registers, + modbus_addr_t num_registers, SignalData *signals, + unsigned int num_signals) { + return std::visit( + [this, registers, num_registers, signals, num_signals](auto mapping) { + return readMapping(mapping, registers, num_registers, signals, + num_signals); + }, + mapping); } -int ModbusNode::readMapping(RegisterMapping const &mapping, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals) -{ - return std::visit([this, registers, num_registers, signals, num_signals](auto mapping){ - return readMapping(mapping, registers, num_registers, signals, num_signals); - }, mapping); +int ModbusNode::readMapping(RegisterMappingSingle const &single, + uint16_t const *registers, + modbus_addr_t num_registers, SignalData *signals, + unsigned int num_signals) { + auto signal_data = single.read(registers, num_registers); + + assert(single.signal_index < num_signals); + signals[single.signal_index] = signal_data; + + return 0; } -int ModbusNode::readMapping(RegisterMappingSingle const &single, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals) -{ - auto signal_data = single.read(registers, num_registers); +int ModbusNode::readMapping(RegisterMappingBlock const &block, + uint16_t const *registers, + modbus_addr_t num_registers, SignalData *signals, + unsigned int num_signals) { + auto begin_block = blockBegin(block); - assert(single.signal_index < num_signals); - signals[single.signal_index] = signal_data; + for (auto &single : block) { + auto begin_single = blockBegin(single); + auto end_single = blockEnd(single); - return 0; + assert(end_single - begin_block <= num_registers); + if (auto ret = readMapping(single, ®isters[begin_single - begin_block], + end_single - begin_single, signals, num_signals)) + return ret; + } + + return 0; } -int ModbusNode::readMapping(RegisterMappingBlock const &block, uint16_t const *registers, modbus_addr_t num_registers, SignalData *signals, unsigned int num_signals) -{ - auto begin_block = blockBegin(block); +int ModbusNode::_read(struct Sample *smps[], unsigned cnt) { + read_task.wait(); - for (auto &single : block) { - auto begin_single = blockBegin(single); - auto end_single = blockEnd(single); + for (unsigned int i = 0; i < cnt; ++i) { + auto smp = smps[i]; + smp->length = num_in_signals; + smp->flags |= (int)SampleFlags::HAS_DATA; - assert(end_single - begin_block <= num_registers); - if (auto ret = readMapping(single, ®isters[begin_single - begin_block], end_single - begin_single, signals, num_signals)) - return ret; - } + assert(smp->length <= smp->capacity); - return 0; + for (auto &mapping : in_mappings) { + if (auto ret = readBlock(mapping, smp->data, smp->length)) + return ret; + } + } + + return cnt; } -int ModbusNode::_read(struct Sample *smps[], unsigned cnt) -{ - read_task.wait(); +int ModbusNode::writeBlock(RegisterMapping const &mapping, + SignalData const *data, size_t size) { + if (isReconnecting()) + return -1; - for (unsigned int i = 0; i < cnt; ++i) { - auto smp = smps[i]; - smp->length = num_in_signals; - smp->flags |= (int) SampleFlags::HAS_DATA; + auto address = blockBegin(mapping); + auto block_size = blockEnd(mapping) - address; - assert(smp->length <= smp->capacity); + write_buffer.resize(block_size); - for (auto &mapping : in_mappings) { - if (auto ret = readBlock(mapping, smp->data, smp->length)) - return ret; - } - } + if (auto ret = writeMapping(mapping, write_buffer.data(), write_buffer.size(), + data, size)) + return ret; - return cnt; + if (modbus_write_registers(modbus_context, address, block_size, + write_buffer.data()) == -1) { + logger->error("write registers failure: ", modbus_strerror(errno)); + + reconnect(); + + return -1; + } + + return 0; } -int ModbusNode::writeBlock(RegisterMapping const &mapping, SignalData const *data, size_t size) -{ - if (isReconnecting()) - return -1; - - auto address = blockBegin(mapping); - auto block_size = blockEnd(mapping) - address; - - write_buffer.resize(block_size); - - if (auto ret = writeMapping(mapping, write_buffer.data(), write_buffer.size(), data, size)) - return ret; - - if (modbus_write_registers(modbus_context, address, block_size, write_buffer.data()) == -1) { - logger->error("write registers failure: ", modbus_strerror(errno)); - - reconnect(); - - return -1; - } - - return 0; +int ModbusNode::writeMapping(RegisterMapping const &mapping, + uint16_t *registers, modbus_addr_t num_registers, + SignalData const *signals, + unsigned int num_signals) { + return std::visit( + [this, registers, num_registers, signals, num_signals](auto mapping) { + return writeMapping(mapping, registers, num_registers, signals, + num_signals); + }, + mapping); } -int ModbusNode::writeMapping(RegisterMapping const &mapping, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals) -{ - return std::visit([this, registers, num_registers, signals, num_signals](auto mapping){ - return writeMapping(mapping, registers, num_registers, signals, num_signals); - }, mapping); +int ModbusNode::writeMapping(RegisterMappingSingle const &single, + uint16_t *registers, modbus_addr_t num_registers, + SignalData const *signals, + unsigned int num_signals) { + assert(single.signal_index < num_signals); + single.write(signals[single.signal_index], registers, num_registers); + + return 0; } -int ModbusNode::writeMapping(RegisterMappingSingle const &single, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals) -{ - assert(single.signal_index < num_signals); - single.write(signals[single.signal_index], registers, num_registers); +int ModbusNode::writeMapping(RegisterMappingBlock const &block, + uint16_t *registers, modbus_addr_t num_registers, + SignalData const *signals, + unsigned int num_signals) { + auto begin_block = blockBegin(block); - return 0; + for (auto &single : block) { + auto begin_single = blockBegin(single); + auto end_single = blockEnd(single); + + assert(end_single - begin_block <= num_registers); + if (auto ret = + writeMapping(single, ®isters[begin_single - begin_block], + end_single - begin_single, signals, num_signals)) + return ret; + } + + return 0; } -int ModbusNode::writeMapping(RegisterMappingBlock const &block, uint16_t *registers, modbus_addr_t num_registers, SignalData const *signals, unsigned int num_signals) -{ - auto begin_block = blockBegin(block); +int ModbusNode::_write(struct Sample *smps[], unsigned cnt) { + for (unsigned int i = 0; i < cnt; ++i) { + auto smp = smps[i]; - for (auto &single : block) { - auto begin_single = blockBegin(single); - auto end_single = blockEnd(single); + assert(smp->length == num_out_signals); - assert(end_single - begin_block <= num_registers); - if (auto ret = writeMapping(single, ®isters[begin_single - begin_block], end_single - begin_single, signals, num_signals)) - return ret; - } + for (auto &mapping : out_mappings) { + if (auto ret = writeBlock(mapping, smp->data, smp->length)) + return ret; + } + } - return 0; + return cnt; } -int ModbusNode::_write(struct Sample *smps[], unsigned cnt) -{ - for (unsigned int i = 0; i < cnt; ++i) { - auto smp = smps[i]; +ModbusNode::ModbusNode(const uuid_t &id, const std::string &name) + : Node(id, name), max_block_size(32), min_block_usage(0.25), + connection_settings(), rate(-1), response_timeout(1), in_mappings{}, + num_in_signals(0), out_mappings{}, num_out_signals(0), + reconnect_interval(10), read_buffer{}, write_buffer{}, + modbus_context(nullptr), read_task(), reconnecting(false) {} - assert(smp->length == num_out_signals); - - for (auto &mapping : out_mappings) { - if (auto ret = writeBlock(mapping, smp->data, smp->length)) - return ret; - } - } - - return cnt; +ModbusNode::~ModbusNode() { + if (modbus_context) + modbus_free(modbus_context); } -ModbusNode::ModbusNode(const uuid_t &id, const std::string &name) : - Node(id, name), - max_block_size(32), - min_block_usage(0.25), - connection_settings(), - rate(-1), - response_timeout(1), - in_mappings{}, - num_in_signals(0), - out_mappings{}, - num_out_signals(0), - reconnect_interval(10), - read_buffer{}, - write_buffer{}, - modbus_context(nullptr), - read_task(), - reconnecting(false) -{ } +int ModbusNode::prepare() { + mergeMappings(in_mappings, max_block_size - 2); + mergeMappings(out_mappings, 0); -ModbusNode::~ModbusNode() -{ - if (modbus_context) - modbus_free(modbus_context); + if (in.enabled) { + read_task.setRate(rate); + + logger->info("Making {} Modbus calls for each read", in_mappings.size()); + } + + if (out.enabled) + logger->info("Making {} Modbus calls for each write", out_mappings.size()); + + assert(!std::holds_alternative(connection_settings)); + + if (auto tcp = std::get_if(&connection_settings)) { + modbus_context = modbus_new_tcp(tcp->remote.c_str(), tcp->port); + + if (tcp->unit) + modbus_set_slave(modbus_context, *tcp->unit); + } + + if (auto rtu = std::get_if(&connection_settings)) { + modbus_context = modbus_new_rtu(rtu->device.c_str(), rtu->baudrate, + static_cast(rtu->parity), + rtu->data_bits, rtu->stop_bits); + + modbus_set_slave(modbus_context, rtu->unit); + } + + auto response_timeout_secs = (uint32_t)response_timeout; + auto response_timeout_usecs = + (uint32_t)(response_timeout - (double)response_timeout_secs); + modbus_set_response_timeout(modbus_context, response_timeout_secs, + response_timeout_usecs); + + return Node::prepare(); } -int ModbusNode::prepare() -{ - mergeMappings(in_mappings, max_block_size - 2); - mergeMappings(out_mappings, 0); +Endianess modbus::parseEndianess(char const *str) { + if (!strcmp(str, "little")) + return Endianess::Little; - if (in.enabled) { - read_task.setRate(rate); + if (!strcmp(str, "big")) + return Endianess::Big; - logger->info("Making {} Modbus calls for each read", in_mappings.size()); - } - - if (out.enabled) - logger->info("Making {} Modbus calls for each write", out_mappings.size()); - - assert(!std::holds_alternative(connection_settings)); - - if (auto tcp = std::get_if(&connection_settings)) { - modbus_context = modbus_new_tcp(tcp->remote.c_str(), tcp->port); - - if (tcp->unit) - modbus_set_slave(modbus_context, *tcp->unit); - } - - if (auto rtu = std::get_if(&connection_settings)) { - modbus_context = modbus_new_rtu( - rtu->device.c_str(), - rtu->baudrate, - static_cast(rtu->parity), - rtu->data_bits, - rtu->stop_bits); - - modbus_set_slave(modbus_context, rtu->unit); - } - - auto response_timeout_secs = (uint32_t) response_timeout; - auto response_timeout_usecs = (uint32_t) (response_timeout - (double) response_timeout_secs); - modbus_set_response_timeout(modbus_context, response_timeout_secs, response_timeout_usecs); - - return Node::prepare(); + throw RuntimeError{"invalid endianess"}; } -Endianess modbus::parseEndianess(char const *str) -{ - if (!strcmp(str, "little")) - return Endianess::Little; +Parity modbus::parseParity(char const *str) { + if (!strcmp(str, "none")) + return Parity::None; - if (!strcmp(str, "big")) - return Endianess::Big; + if (!strcmp(str, "even")) + return Parity::Even; - throw RuntimeError { "invalid endianess" }; + if (!strcmp(str, "odd")) + return Parity::Odd; + + throw RuntimeError{"invalid parity"}; } -Parity modbus::parseParity(char const *str) -{ - if (!strcmp(str, "none")) - return Parity::None; +Rtu Rtu::parse(json_t *json) { + char const *device = nullptr; + char const *parity_str = nullptr; + int baudrate = -1; + int data_bits = -1; + int stop_bits = -1; - if (!strcmp(str, "even")) - return Parity::Even; + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: i, s: i, s: i }", + "device", &device, "parity", &parity_str, "baudrate", + &baudrate, "data_bits", &data_bits, "stop_bits", + &stop_bits); + if (ret) + throw ConfigError(json, err, "node-config-node-modbus-rtu"); - if (!strcmp(str, "odd")) - return Parity::Odd; + Parity parity = parseParity(parity_str); - throw RuntimeError { "invalid parity" }; + return Rtu{device, parity, baudrate, data_bits, stop_bits}; } -Rtu Rtu::parse(json_t* json) -{ - char const *device = nullptr; - char const *parity_str = nullptr; - int baudrate = -1; - int data_bits = -1; - int stop_bits = -1; +Tcp Tcp::parse(json_t *json) { + char const *remote = nullptr; + int port = 502; + int unit_int = -1; - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: i, s: i, s: i }", - "device", &device, - "parity", &parity_str, - "baudrate", &baudrate, - "data_bits", &data_bits, - "stop_bits", &stop_bits - ); - if (ret) - throw ConfigError(json, err, "node-config-node-modbus-rtu"); + json_error_t err; + int ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: i, s?: i }", "remote", + &remote, "port", &port, "unit", &unit_int); + if (ret) + throw ConfigError(json, err, "node-config-node-modbus-tcp"); - Parity parity = parseParity(parity_str); + std::optional unit = unit_int >= 0 ? std::optional(unit_int) : std::nullopt; - return Rtu { device, parity, baudrate, data_bits, stop_bits }; + return Tcp{ + .remote = remote, + .port = (uint16_t)port, + .unit = unit, + }; } -Tcp Tcp::parse(json_t* json) -{ - char const *remote = nullptr; - int port = 502; - int unit_int = -1; +RegisterMappingSingle RegisterMappingSingle::parse(unsigned int index, + Signal::Ptr signal, + json_t *json) { + int address = -1; + int bit = -1; + int integer_registers = -1; + char const *word_endianess_str = nullptr; + char const *byte_endianess_str = nullptr; + double offset = 0.0; + double scale = 1.0; - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: i, s?: i }", - "remote", &remote, - "port", &port, - "unit", &unit_int - ); - if (ret) - throw ConfigError(json, err, "node-config-node-modbus-tcp"); + json_error_t err; + int ret = json_unpack_ex( + json, &err, 0, "{ s: i, s?: i, s?: i, s?: s, s?: s, s?: F, s?: F }", + "address", &address, "bit", &bit, "integer_registers", &integer_registers, + "word_endianess", &word_endianess_str, "byte_endianess", + &byte_endianess_str, "offset", &offset, "scale", &scale); + if (ret) + throw ConfigError(json, err, "node-config-node-modbus-signal"); - std::optional unit = unit_int >= 0 ? std::optional(unit_int) : std::nullopt; + if (integer_registers != -1 && + (integer_registers <= 0 || (size_t)integer_registers > MAX_REGISTERS)) + throw RuntimeError{"unsupported register block size"}; - return Tcp { - .remote = remote, - .port = (uint16_t) port, - .unit = unit, - }; + Endianess word_endianess = Endianess::Big; + if (word_endianess_str) + word_endianess = parseEndianess(word_endianess_str); + + Endianess byte_endianess = Endianess::Big; + if (byte_endianess_str) + byte_endianess = parseEndianess(byte_endianess_str); + + auto mapping = RegisterMappingSingle{index, (modbus_addr_t)address}; + if (signal->type == SignalType::FLOAT) { + if (integer_registers == -1) { + mapping.conversion = FloatToFloat{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .offset = offset, + .scale = scale, + }; + } else { + auto integer_conversion = IntegerToInteger{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = (modbus_addr_t)integer_registers, + }; + + mapping.conversion = IntegerToFloat{ + .integer_conversion = integer_conversion, + .offset = offset, + .scale = scale, + }; + } + + return mapping; + } else if (signal->type == SignalType::INTEGER) { + if (integer_registers == -1) + integer_registers = 1; + + mapping.conversion = IntegerToInteger{ + .word_endianess = word_endianess, + .byte_endianess = byte_endianess, + .num_registers = (modbus_addr_t)integer_registers, + }; + } else if (signal->type == SignalType::BOOLEAN) { + if (bit < 0 || bit > 15) + throw RuntimeError{ + "mappings from bit to bool must be in the range 0 to 16"}; + + mapping.conversion = BitToBool{ + .bit = (uint8_t)bit, + }; + } else { + throw RuntimeError{"unsupported signal type"}; + } + + return mapping; } -RegisterMappingSingle RegisterMappingSingle::parse(unsigned int index, Signal::Ptr signal, json_t *json) -{ - int address = -1; - int bit = -1; - int integer_registers = -1; - char const *word_endianess_str = nullptr; - char const *byte_endianess_str = nullptr; - double offset = 0.0; - double scale = 1.0; +unsigned int ModbusNode::parseMappings(std::vector &mappings, + json_t *json) { + assert(json_is_array(json)); - json_error_t err; - int ret = json_unpack_ex(json, &err, 0, "{ s: i, s?: i, s?: i, s?: s, s?: s, s?: F, s?: F }", - "address", &address, - "bit", &bit, - "integer_registers", &integer_registers, - "word_endianess", &word_endianess_str, - "byte_endianess", &byte_endianess_str, - "offset", &offset, - "scale", &scale - ); - if (ret) - throw ConfigError(json, err, "node-config-node-modbus-signal"); + size_t i; + json_t *signal_json; + auto signals = getInputSignals(false); - if (integer_registers != -1 && (integer_registers <= 0 || (size_t) integer_registers > MAX_REGISTERS)) - throw RuntimeError { "unsupported register block size" }; + json_array_foreach(json, i, signal_json) { + auto signal = signals->getByIndex(i); - Endianess word_endianess = Endianess::Big; - if (word_endianess_str) - word_endianess = parseEndianess(word_endianess_str); + mappings.push_back(RegisterMappingSingle::parse(i, signal, signal_json)); + } - Endianess byte_endianess = Endianess::Big; - if (byte_endianess_str) - byte_endianess = parseEndianess(byte_endianess_str); - - auto mapping = RegisterMappingSingle { index, (modbus_addr_t) address }; - if (signal->type == SignalType::FLOAT) { - if (integer_registers == -1) { - mapping.conversion = FloatToFloat { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .offset = offset, - .scale = scale, - }; - } else { - auto integer_conversion = IntegerToInteger { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .num_registers = (modbus_addr_t) integer_registers, - }; - - mapping.conversion = IntegerToFloat { - .integer_conversion = integer_conversion, - .offset = offset, - .scale = scale, - }; - } - - return mapping; - } else if (signal->type == SignalType::INTEGER) { - if (integer_registers == -1) - integer_registers = 1; - - mapping.conversion = IntegerToInteger { - .word_endianess = word_endianess, - .byte_endianess = byte_endianess, - .num_registers = (modbus_addr_t) integer_registers, - }; - } else if (signal->type == SignalType::BOOLEAN) { - if (bit < 0 || bit > 15) - throw RuntimeError { "mappings from bit to bool must be in the range 0 to 16" }; - - mapping.conversion = BitToBool { - .bit = (uint8_t) bit, - }; - } else { - throw RuntimeError { "unsupported signal type" }; - } - - return mapping; + return json_array_size(json); } -unsigned int ModbusNode::parseMappings(std::vector &mappings, json_t *json) -{ - assert(json_is_array(json)); +int ModbusNode::parse(json_t *json) { + if (auto ret = Node::parse(json)) + return ret; - size_t i; - json_t *signal_json; - auto signals = getInputSignals(false); + json_error_t err; + char const *transport = nullptr; + json_t *in_json = nullptr; + json_t *out_json = nullptr; - json_array_foreach (json, i, signal_json) { - auto signal = signals->getByIndex(i); + if (json_unpack_ex( + json, &err, 0, + "{ s: s, s?: F, s?: F, s?: i, s?: i, s?: F, s?: o, s?: o }", + "transport", &transport, "response_timeout", &response_timeout, + "reconnect_interval", &reconnect_interval, "min_block_usage", + &min_block_usage, "max_block_size", &max_block_size, "rate", &rate, + "in", &in_json, "out", &out_json)) + throw ConfigError(json, err, "node-config-node-modbus"); - mappings.push_back(RegisterMappingSingle::parse(i, signal, signal_json)); - } + if (in.enabled && rate < 0) + throw RuntimeError{"missing polling rate for Modbus reads"}; - return json_array_size(json); + if (!strcmp(transport, "rtu")) + connection_settings = Rtu::parse(json); + else if (!strcmp(transport, "tcp")) + connection_settings = Tcp::parse(json); + else + throw ConfigError(json, err, "node-config-node-modbus-transport"); + + json_t *signals_json; + + if (in_json && (signals_json = json_object_get(in_json, "signals"))) + num_in_signals = parseMappings(in_mappings, signals_json); + + if (out_json && (signals_json = json_object_get(out_json, "signals"))) + num_out_signals = parseMappings(out_mappings, signals_json); + + return 0; } -int ModbusNode::parse(json_t *json) -{ - if (auto ret = Node::parse(json)) - return ret; +int ModbusNode::check() { return Node::check(); } - json_error_t err; - char const * transport = nullptr; - json_t *in_json = nullptr; - json_t *out_json = nullptr; +int ModbusNode::start() { + if (modbus_connect(modbus_context) == -1) + throw RuntimeError{"connection failure: {}", modbus_strerror(errno)}; - if (json_unpack_ex(json, &err, 0, "{ s: s, s?: F, s?: F, s?: i, s?: i, s?: F, s?: o, s?: o }", - "transport", &transport, - "response_timeout", &response_timeout, - "reconnect_interval", &reconnect_interval, - "min_block_usage", &min_block_usage, - "max_block_size", &max_block_size, - "rate", &rate, - "in", &in_json, - "out", &out_json - )) - throw ConfigError(json, err, "node-config-node-modbus"); - - if (in.enabled && rate < 0) - throw RuntimeError { "missing polling rate for Modbus reads" }; - - if (!strcmp(transport, "rtu")) - connection_settings = Rtu::parse(json); - else if (!strcmp(transport, "tcp")) - connection_settings = Tcp::parse(json); - else - throw ConfigError(json, err, "node-config-node-modbus-transport"); - - json_t *signals_json; - - if (in_json && (signals_json = json_object_get(in_json, "signals"))) - num_in_signals = parseMappings(in_mappings, signals_json); - - if (out_json && (signals_json = json_object_get(out_json, "signals"))) - num_out_signals = parseMappings(out_mappings, signals_json); - - return 0; + return Node::start(); } -int ModbusNode::check() -{ - return Node::check(); +int ModbusNode::stop() { + modbus_close(modbus_context); + + return Node::stop(); } -int ModbusNode::start() -{ - if (modbus_connect(modbus_context) == -1) - throw RuntimeError { "connection failure: {}", modbus_strerror(errno) }; +std::vector ModbusNode::getPollFDs() { return {read_task.getFD()}; } - return Node::start(); +std::vector ModbusNode::getNetemFDs() { + if (modbus_context != nullptr && + std::holds_alternative(connection_settings)) { + return {modbus_get_socket(modbus_context)}; + } + + return {}; } -int ModbusNode::stop() -{ - modbus_close(modbus_context); +const std::string &ModbusNode::getDetails() { + if (details.empty()) { + if (auto tcp = std::get_if(&connection_settings)) { + details = fmt::format("transport=tcp, remote={}, port={}", tcp->remote, + tcp->port); - return Node::stop(); -} + if (tcp->unit) + details.append(fmt::format(", unit={}", *tcp->unit)); + } -std::vector ModbusNode::getPollFDs() -{ - return { read_task.getFD() }; -} + if (auto rtu = std::get_if(&connection_settings)) { + details = fmt::format("transport=rtu, device={}, baudrate={}, parity={}, " + "data_bits={}, stop_bits={}, unit={}", + rtu->device.c_str(), rtu->baudrate, + static_cast(rtu->parity), rtu->data_bits, + rtu->stop_bits, rtu->unit); + } + } -std::vector ModbusNode::getNetemFDs() -{ - if (modbus_context != nullptr && std::holds_alternative(connection_settings)) { - return { - modbus_get_socket(modbus_context) - }; - } - - return { }; -} - -const std::string & ModbusNode::getDetails() -{ - if (details.empty()) { - if (auto tcp = std::get_if(&connection_settings)) { - details = fmt::format("transport=tcp, remote={}, port={}", tcp->remote, tcp->port); - - if (tcp->unit) - details.append(fmt::format(", unit={}", *tcp->unit)); - } - - if (auto rtu = std::get_if(&connection_settings)) { - details = fmt::format("transport=rtu, device={}, baudrate={}, parity={}, data_bits={}, stop_bits={}, unit={}", - rtu->device.c_str(), - rtu->baudrate, - static_cast(rtu->parity), - rtu->data_bits, - rtu->stop_bits, - rtu->unit); - } - } - - return details; + return details; } // Register node static char name[] = "modbus"; static char description[] = "Read and write Modbus registers"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/mqtt.cpp b/lib/nodes/mqtt.cpp index a20e815bf..851b36a66 100644 --- a/lib/nodes/mqtt.cpp +++ b/lib/nodes/mqtt.cpp @@ -5,526 +5,504 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include +#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -void mqtt_log_cb(struct mosquitto *mosq, void *ctx, int level, const char *str) -{ - auto *n = (NodeCompat *) ctx; +static void mqtt_log_cb(struct mosquitto *mosq, void *ctx, int level, + const char *str) { + auto *n = (NodeCompat *)ctx; - switch (level) { - case MOSQ_LOG_NONE: - case MOSQ_LOG_INFO: - case MOSQ_LOG_NOTICE: - n->logger->info("{}", str); - break; + switch (level) { + case MOSQ_LOG_NONE: + case MOSQ_LOG_INFO: + case MOSQ_LOG_NOTICE: + n->logger->info("{}", str); + break; - case MOSQ_LOG_WARNING: - n->logger->warn("{}", str); - break; + case MOSQ_LOG_WARNING: + n->logger->warn("{}", str); + break; - case MOSQ_LOG_ERR: - n->logger->error("{}", str); - break; + case MOSQ_LOG_ERR: + n->logger->error("{}", str); + break; - case MOSQ_LOG_DEBUG: - n->logger->debug("{}", str); - break; - } + case MOSQ_LOG_DEBUG: + n->logger->debug("{}", str); + break; + } } -static -void mqtt_connect_cb(struct mosquitto *mosq, void *ctx, int result) -{ - auto *n = (NodeCompat *) ctx; - auto *m = n->getData(); +static void mqtt_connect_cb(struct mosquitto *mosq, void *ctx, int result) { + auto *n = (NodeCompat *)ctx; + auto *m = n->getData(); - int ret; + int ret; - n->logger->info("Connected to broker {}", m->host); + n->logger->info("Connected to broker {}", m->host); - if (m->subscribe) { - ret = mosquitto_subscribe(m->client, nullptr, m->subscribe, m->qos); - if (ret) - n->logger->warn("Failed to subscribe to topic '{}': {}", m->subscribe, mosquitto_strerror(ret)); - } - else - n->logger->warn("No subscription as no topic is configured"); + if (m->subscribe) { + ret = mosquitto_subscribe(m->client, nullptr, m->subscribe, m->qos); + if (ret) + n->logger->warn("Failed to subscribe to topic '{}': {}", m->subscribe, + mosquitto_strerror(ret)); + } else + n->logger->warn("No subscription as no topic is configured"); } -static -void mqtt_disconnect_cb(struct mosquitto *mosq, void *ctx, int result) -{ - auto *n = (NodeCompat *) ctx; - auto *m = n->getData(); +static void mqtt_disconnect_cb(struct mosquitto *mosq, void *ctx, int result) { + auto *n = (NodeCompat *)ctx; + auto *m = n->getData(); - n->logger->info("Disconnected from broker {}", m->host); + n->logger->info("Disconnected from broker {}", m->host); } -static -void mqtt_message_cb(struct mosquitto *mosq, void *ctx, const struct mosquitto_message *msg) -{ - int ret; - auto *n = (NodeCompat *) ctx; - auto *m = n->getData(); - struct Sample *smps[n->in.vectorize]; +static void mqtt_message_cb(struct mosquitto *mosq, void *ctx, + const struct mosquitto_message *msg) { + int ret; + auto *n = (NodeCompat *)ctx; + auto *m = n->getData(); + struct Sample *smps[n->in.vectorize]; - n->logger->debug("Received a message of {} bytes from broker {}", msg->payloadlen, m->host); + n->logger->debug("Received a message of {} bytes from broker {}", + msg->payloadlen, m->host); - ret = sample_alloc_many(&m->pool, smps, n->in.vectorize); - if (ret <= 0) { - n->logger->warn("Pool underrun in subscriber"); - return; - } + ret = sample_alloc_many(&m->pool, smps, n->in.vectorize); + if (ret <= 0) { + n->logger->warn("Pool underrun in subscriber"); + return; + } - ret = m->formatter->sscan((char *) msg->payload, msg->payloadlen, nullptr, smps, n->in.vectorize); - if (ret < 0) { - n->logger->warn("Received an invalid message"); - n->logger->warn(" Payload: {}", (char *) msg->payload); - return; - } + ret = m->formatter->sscan((char *)msg->payload, msg->payloadlen, nullptr, + smps, n->in.vectorize); + if (ret < 0) { + n->logger->warn("Received an invalid message"); + n->logger->warn(" Payload: {}", (char *)msg->payload); + return; + } - if (ret == 0) { - n->logger->debug("Skip empty message"); - sample_decref_many(smps, n->in.vectorize); - return; - } + if (ret == 0) { + n->logger->debug("Skip empty message"); + sample_decref_many(smps, n->in.vectorize); + return; + } - ret = queue_signalled_push_many(&m->queue, (void **) smps, n->in.vectorize); - if (ret < (int) n->in.vectorize) - n->logger->warn("Failed to enqueue samples"); + ret = queue_signalled_push_many(&m->queue, (void **)smps, n->in.vectorize); + if (ret < (int)n->in.vectorize) + n->logger->warn("Failed to enqueue samples"); } -static -void mqtt_subscribe_cb(struct mosquitto *mosq, void *ctx, int mid, int qos_count, const int *granted_qos) -{ - auto *n = (NodeCompat *) ctx; - auto *m = n->getData(); +static void mqtt_subscribe_cb(struct mosquitto *mosq, void *ctx, int mid, + int qos_count, const int *granted_qos) { + auto *n = (NodeCompat *)ctx; + auto *m = n->getData(); - n->logger->info("Subscribed to broker {}", m->host); + n->logger->info("Subscribed to broker {}", m->host); } -int villas::node::mqtt_reverse(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::mqtt_reverse(NodeCompat *n) { + auto *m = n->getData(); - SWAP(m->publish, m->subscribe); + SWAP(m->publish, m->subscribe); - return 0; + return 0; } -int villas::node::mqtt_init(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::mqtt_init(NodeCompat *n) { + auto *m = n->getData(); - m->client = mosquitto_new(nullptr, true, (void *) n); - if (!m->client) - return -1; + m->client = mosquitto_new(nullptr, true, (void *)n); + if (!m->client) + return -1; - mosquitto_log_callback_set(m->client, mqtt_log_cb); - mosquitto_connect_callback_set(m->client, mqtt_connect_cb); - mosquitto_disconnect_callback_set(m->client, mqtt_disconnect_cb); - mosquitto_message_callback_set(m->client, mqtt_message_cb); - mosquitto_subscribe_callback_set(m->client, mqtt_subscribe_cb); + mosquitto_log_callback_set(m->client, mqtt_log_cb); + mosquitto_connect_callback_set(m->client, mqtt_connect_cb); + mosquitto_disconnect_callback_set(m->client, mqtt_disconnect_cb); + mosquitto_message_callback_set(m->client, mqtt_message_cb); + mosquitto_subscribe_callback_set(m->client, mqtt_subscribe_cb); - m->formatter = nullptr; + m->formatter = nullptr; - // Default values - m->port = 1883; - m->qos = 0; - m->retain = 0; - m->keepalive = 5; // 5 second, minimum required for libmosquitto + // Default values + m->port = 1883; + m->qos = 0; + m->retain = 0; + m->keepalive = 5; // 5 second, minimum required for libmosquitto - m->host = nullptr; - m->username = nullptr; - m->password = nullptr; - m->publish = nullptr; - m->subscribe = nullptr; + m->host = nullptr; + m->username = nullptr; + m->password = nullptr; + m->publish = nullptr; + m->subscribe = nullptr; - m->ssl.enabled = 0; - m->ssl.insecure = 0; - m->ssl.cafile = nullptr; - m->ssl.capath = nullptr; - m->ssl.certfile = nullptr; - m->ssl.keyfile = nullptr; - m->ssl.cert_reqs = SSL_VERIFY_PEER; - m->ssl.tls_version = nullptr; - m->ssl.ciphers = nullptr; + m->ssl.enabled = 0; + m->ssl.insecure = 0; + m->ssl.cafile = nullptr; + m->ssl.capath = nullptr; + m->ssl.certfile = nullptr; + m->ssl.keyfile = nullptr; + m->ssl.cert_reqs = SSL_VERIFY_PEER; + m->ssl.tls_version = nullptr; + m->ssl.ciphers = nullptr; - return 0; + return 0; } -int villas::node::mqtt_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_parse(NodeCompat *n, json_t *json) { + int ret; + auto *m = n->getData(); - const char *host; - const char *publish = nullptr; - const char *subscribe = nullptr; - const char *username = nullptr; - const char *password = nullptr; + const char *host; + const char *publish = nullptr; + const char *subscribe = nullptr; + const char *username = nullptr; + const char *password = nullptr; - json_error_t err; - json_t *json_ssl = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_ssl = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: s }, s?: { s?: s }, s?: o, s: s, s?: i, s?: i, s?: i, s?: b, s?: s, s?: s, s?: o }", - "out", - "publish", &publish, - "in", - "subscribe", &subscribe, - "format", &json_format, - "host", &host, - "port", &m->port, - "qos", &m->qos, - "keepalive", &m->keepalive, - "retain", &m->retain, - "username", &username, - "password", &password, - "ssl", &json_ssl - ); - if (ret) - throw ConfigError(json, err, "node-config-node-mqtt"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: { s?: s }, s?: { s?: s }, s?: o, s: s, s?: i, " + "s?: i, s?: i, s?: b, s?: s, s?: s, s?: o }", + "out", "publish", &publish, "in", "subscribe", + &subscribe, "format", &json_format, "host", &host, + "port", &m->port, "qos", &m->qos, "keepalive", + &m->keepalive, "retain", &m->retain, "username", + &username, "password", &password, "ssl", &json_ssl); + if (ret) + throw ConfigError(json, err, "node-config-node-mqtt"); - m->host = strdup(host); - m->publish = publish ? strdup(publish) : nullptr; - m->subscribe = subscribe ? strdup(subscribe) : nullptr; - m->username = username ? strdup(username) : nullptr; - m->password = password ? strdup(password) : nullptr; + m->host = strdup(host); + m->publish = publish ? strdup(publish) : nullptr; + m->subscribe = subscribe ? strdup(subscribe) : nullptr; + m->username = username ? strdup(username) : nullptr; + m->password = password ? strdup(password) : nullptr; - if (!m->publish && !m->subscribe) - throw ConfigError(json, "node-config-node-mqtt", "At least one topic has to be specified for node {}", n->getName()); + if (!m->publish && !m->subscribe) + throw ConfigError(json, "node-config-node-mqtt", + "At least one topic has to be specified for node {}", + n->getName()); - if (json_ssl) { - m->ssl.enabled = 1; + if (json_ssl) { + m->ssl.enabled = 1; - const char *cafile = nullptr; - const char *capath = nullptr; - const char *certfile = nullptr; - const char *keyfile = nullptr; - const char *tls_version = nullptr; - const char *ciphers = nullptr; + const char *cafile = nullptr; + const char *capath = nullptr; + const char *certfile = nullptr; + const char *keyfile = nullptr; + const char *tls_version = nullptr; + const char *ciphers = nullptr; - ret = json_unpack_ex(json_ssl, &err, 0, "{ s?: b, s?: b, s?: s, s?: s, s?: s, s?: s, s?: s, s?: b, s?: s }", - "enabled", &m->ssl.enabled, - "insecure", &m->ssl.insecure, - "cafile", &cafile, - "capath", &capath, - "certfile", &certfile, - "keyfile", &keyfile, - "cipher", &ciphers, - "verify", &m->ssl.cert_reqs, - "tls_version", &tls_version - ); - if (ret) - throw ConfigError(json_ssl, err, "node-config-node-mqtt-ssl", "Failed to parse SSL configuration of node {}", n->getName()); + ret = json_unpack_ex( + json_ssl, &err, 0, + "{ s?: b, s?: b, s?: s, s?: s, s?: s, s?: s, s?: s, s?: b, s?: s }", + "enabled", &m->ssl.enabled, "insecure", &m->ssl.insecure, "cafile", + &cafile, "capath", &capath, "certfile", &certfile, "keyfile", &keyfile, + "cipher", &ciphers, "verify", &m->ssl.cert_reqs, "tls_version", + &tls_version); + if (ret) + throw ConfigError(json_ssl, err, "node-config-node-mqtt-ssl", + "Failed to parse SSL configuration of node {}", + n->getName()); - if (m->ssl.enabled && !cafile && !capath) - throw ConfigError(json_ssl, "node-config-node-mqtt-ssl", "Either 'ssl.cafile' or 'ssl.capath' settings must be set for node {}.", n->getName()); + if (m->ssl.enabled && !cafile && !capath) + throw ConfigError(json_ssl, "node-config-node-mqtt-ssl", + "Either 'ssl.cafile' or 'ssl.capath' settings must be " + "set for node {}.", + n->getName()); - m->ssl.cafile = cafile ? strdup(cafile) : nullptr; - m->ssl.capath = capath ? strdup(capath) : nullptr; - m->ssl.certfile = certfile ? strdup(certfile) : nullptr; - m->ssl.keyfile = keyfile ? strdup(keyfile) : nullptr; - m->ssl.ciphers = ciphers ? strdup(ciphers) : nullptr; - } + m->ssl.cafile = cafile ? strdup(cafile) : nullptr; + m->ssl.capath = capath ? strdup(capath) : nullptr; + m->ssl.certfile = certfile ? strdup(certfile) : nullptr; + m->ssl.keyfile = keyfile ? strdup(keyfile) : nullptr; + m->ssl.ciphers = ciphers ? strdup(ciphers) : nullptr; + } - // Format - if (m->formatter) - delete m->formatter; - m->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("json"); - if (!m->formatter) - throw ConfigError(json_format, "node-config-node-mqtt-format", "Invalid format configuration"); + // Format + if (m->formatter) + delete m->formatter; + m->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("json"); + if (!m->formatter) + throw ConfigError(json_format, "node-config-node-mqtt-format", + "Invalid format configuration"); - return 0; + return 0; } -int villas::node::mqtt_check(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_check(NodeCompat *n) { + int ret; + auto *m = n->getData(); - ret = mosquitto_sub_topic_check(m->subscribe); - if (ret != MOSQ_ERR_SUCCESS) - throw RuntimeError("Invalid subscribe topic: '{}': {}", m->subscribe, mosquitto_strerror(ret)); + ret = mosquitto_sub_topic_check(m->subscribe); + if (ret != MOSQ_ERR_SUCCESS) + throw RuntimeError("Invalid subscribe topic: '{}': {}", m->subscribe, + mosquitto_strerror(ret)); - ret = mosquitto_pub_topic_check(m->publish); - if (ret != MOSQ_ERR_SUCCESS) - throw RuntimeError("Invalid publish topic: '{}': {}", m->publish, mosquitto_strerror(ret)); + ret = mosquitto_pub_topic_check(m->publish); + if (ret != MOSQ_ERR_SUCCESS) + throw RuntimeError("Invalid publish topic: '{}': {}", m->publish, + mosquitto_strerror(ret)); - return 0; + return 0; } -int villas::node::mqtt_prepare(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_prepare(NodeCompat *n) { + int ret; + auto *m = n->getData(); - m->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + m->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - ret = pool_init(&m->pool, 1024, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + ret = pool_init(&m->pool, 1024, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&m->queue, 1024); - if (ret) - return ret; + ret = queue_signalled_init(&m->queue, 1024); + if (ret) + return ret; - return 0; + return 0; } -char * villas::node::mqtt_print(NodeCompat *n) -{ - auto *m = n->getData(); +char *villas::node::mqtt_print(NodeCompat *n) { + auto *m = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - strcatf(&buf, "host=%s, port=%d, keepalive=%d, ssl=%s", - m->host, - m->port, - m->keepalive, - m->ssl.enabled ? "yes" : "no" - ); + strcatf(&buf, "host=%s, port=%d, keepalive=%d, ssl=%s", m->host, m->port, + m->keepalive, m->ssl.enabled ? "yes" : "no"); - // Only show if not default - if (m->username) - strcatf(&buf, ", username=%s", m->username); + // Only show if not default + if (m->username) + strcatf(&buf, ", username=%s", m->username); - if (m->publish) - strcatf(&buf, ", out.publish=%s", m->publish); + if (m->publish) + strcatf(&buf, ", out.publish=%s", m->publish); - if (m->subscribe) - strcatf(&buf, ", in.subscribe=%s", m->subscribe); + if (m->subscribe) + strcatf(&buf, ", in.subscribe=%s", m->subscribe); - return buf; + return buf; } -int villas::node::mqtt_destroy(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_destroy(NodeCompat *n) { + int ret; + auto *m = n->getData(); - mosquitto_destroy(m->client); + mosquitto_destroy(m->client); - ret = pool_destroy(&m->pool); - if (ret) - return ret; + ret = pool_destroy(&m->pool); + if (ret) + return ret; - ret = queue_signalled_destroy(&m->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&m->queue); + if (ret) + return ret; - if (m->publish) - free(m->publish); + if (m->publish) + free(m->publish); - if (m->subscribe) - free(m->subscribe); + if (m->subscribe) + free(m->subscribe); - if (m->password) - free(m->password); + if (m->password) + free(m->password); - if (m->username) - free(m->username); + if (m->username) + free(m->username); - if (m->host) - free(m->host); + if (m->host) + free(m->host); - if (m->formatter) - delete m->formatter; + if (m->formatter) + delete m->formatter; - return 0; + return 0; } -int villas::node::mqtt_start(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_start(NodeCompat *n) { + int ret; + auto *m = n->getData(); - if (m->username && m->password) { - ret = mosquitto_username_pw_set(m->client, m->username, m->password); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; - } + if (m->username && m->password) { + ret = mosquitto_username_pw_set(m->client, m->username, m->password); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; + } - if (m->ssl.enabled) { - ret = mosquitto_tls_set(m->client, m->ssl.cafile, m->ssl.capath, m->ssl.certfile, m->ssl.keyfile, nullptr); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + if (m->ssl.enabled) { + ret = mosquitto_tls_set(m->client, m->ssl.cafile, m->ssl.capath, + m->ssl.certfile, m->ssl.keyfile, nullptr); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = mosquitto_tls_insecure_set(m->client, m->ssl.insecure); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_tls_insecure_set(m->client, m->ssl.insecure); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = mosquitto_tls_opts_set(m->client, m->ssl.cert_reqs, m->ssl.tls_version, m->ssl.ciphers); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; - } + ret = mosquitto_tls_opts_set(m->client, m->ssl.cert_reqs, + m->ssl.tls_version, m->ssl.ciphers); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; + } - ret = mosquitto_connect(m->client, m->host, m->port, m->keepalive); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_connect(m->client, m->host, m->port, m->keepalive); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = mosquitto_loop_start(m->client); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_loop_start(m->client); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - return 0; + return 0; mosquitto_error: - n->logger->warn("{}", mosquitto_strerror(ret)); + n->logger->warn("{}", mosquitto_strerror(ret)); - return ret; + return ret; } -int villas::node::mqtt_stop(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_stop(NodeCompat *n) { + int ret; + auto *m = n->getData(); - ret = mosquitto_disconnect(m->client); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_disconnect(m->client); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = mosquitto_loop_stop(m->client, false); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_loop_stop(m->client, false); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - ret = queue_signalled_close(&m->queue); - if (ret) - return ret; + ret = queue_signalled_close(&m->queue); + if (ret) + return ret; - return 0; + return 0; mosquitto_error: - n->logger->warn("{}", mosquitto_strerror(ret)); + n->logger->warn("{}", mosquitto_strerror(ret)); - return ret; + return ret; } -int villas::node::mqtt_type_start(villas::node::SuperNode *sn) -{ - int ret; +int villas::node::mqtt_type_start(villas::node::SuperNode *sn) { + int ret; - ret = mosquitto_lib_init(); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_lib_init(); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - return 0; + return 0; mosquitto_error: - auto logger = logging.get("node:mqtt"); - logger->warn("{}", mosquitto_strerror(ret)); + auto logger = logging.get("node:mqtt"); + logger->warn("{}", mosquitto_strerror(ret)); - return ret; + return ret; } -int villas::node::mqtt_type_stop() -{ - int ret; +int villas::node::mqtt_type_stop() { + int ret; - ret = mosquitto_lib_cleanup(); - if (ret != MOSQ_ERR_SUCCESS) - goto mosquitto_error; + ret = mosquitto_lib_cleanup(); + if (ret != MOSQ_ERR_SUCCESS) + goto mosquitto_error; - return 0; + return 0; mosquitto_error: - auto logger = logging.get("node:mqtt"); - logger->warn("{}", mosquitto_strerror(ret)); + auto logger = logging.get("node:mqtt"); + logger->warn("{}", mosquitto_strerror(ret)); - return ret; + return ret; } -int villas::node::mqtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int pulled; - auto *m = n->getData(); - struct Sample *smpt[cnt]; +int villas::node::mqtt_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int pulled; + auto *m = n->getData(); + struct Sample *smpt[cnt]; - pulled = queue_signalled_pull_many(&m->queue, (void **) smpt, cnt); + pulled = queue_signalled_pull_many(&m->queue, (void **)smpt, cnt); - sample_copy_many(smps, smpt, pulled); - sample_decref_many(smpt, pulled); + sample_copy_many(smps, smpt, pulled); + sample_decref_many(smpt, pulled); - return pulled; + return pulled; } -int villas::node::mqtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *m = n->getData(); +int villas::node::mqtt_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *m = n->getData(); - size_t wbytes; + size_t wbytes; - char data[1500]; + char data[1500]; - ret = m->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret < 0) - return ret; + ret = m->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret < 0) + return ret; - if (m->publish) { - ret = mosquitto_publish(m->client, nullptr /* mid */, m->publish, wbytes, data, m->qos, m->retain); - if (ret != MOSQ_ERR_SUCCESS) { - n->logger->warn("Publish failed: {}", mosquitto_strerror(ret)); - return -abs(ret); - } - } - else - n->logger->warn("No publish possible because no publish topic is configured"); + if (m->publish) { + ret = mosquitto_publish(m->client, nullptr /* mid */, m->publish, wbytes, + data, m->qos, m->retain); + if (ret != MOSQ_ERR_SUCCESS) { + n->logger->warn("Publish failed: {}", mosquitto_strerror(ret)); + return -abs(ret); + } + } else + n->logger->warn( + "No publish possible because no publish topic is configured"); - return cnt; + return cnt; } -int villas::node::mqtt_poll_fds(NodeCompat *n, int fds[]) -{ - auto *m = n->getData(); +int villas::node::mqtt_poll_fds(NodeCompat *n, int fds[]) { + auto *m = n->getData(); - fds[0] = queue_signalled_fd(&m->queue); + fds[0] = queue_signalled_fd(&m->queue); - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "mqtt"; - p.description = "Message Queuing Telemetry Transport (libmosquitto)"; - p.vectorize = 0; - p.size = sizeof(struct mqtt); - p.type.start = mqtt_type_start; - p.type.stop = mqtt_type_stop; - p.destroy = mqtt_destroy; - p.prepare = mqtt_prepare; - p.parse = mqtt_parse; - p.check = mqtt_check; - p.prepare = mqtt_prepare; - p.print = mqtt_print; - p.init = mqtt_init; - p.destroy = mqtt_destroy; - p.start = mqtt_start; - p.stop = mqtt_stop; - p.read = mqtt_read; - p.write = mqtt_write; - p.reverse = mqtt_reverse; - p.poll_fds = mqtt_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "mqtt"; + p.description = "Message Queuing Telemetry Transport (libmosquitto)"; + p.vectorize = 0; + p.size = sizeof(struct mqtt); + p.type.start = mqtt_type_start; + p.type.stop = mqtt_type_stop; + p.destroy = mqtt_destroy; + p.prepare = mqtt_prepare; + p.parse = mqtt_parse; + p.check = mqtt_check; + p.prepare = mqtt_prepare; + p.print = mqtt_print; + p.init = mqtt_init; + p.destroy = mqtt_destroy; + p.start = mqtt_start; + p.stop = mqtt_stop; + p.read = mqtt_read; + p.write = mqtt_write; + p.reverse = mqtt_reverse; + p.poll_fds = mqtt_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/nanomsg.cpp b/lib/nodes/nanomsg.cpp index 61acc74a5..55a113b8b 100644 --- a/lib/nodes/nanomsg.cpp +++ b/lib/nodes/nanomsg.cpp @@ -5,312 +5,297 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include +#include #include #include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int villas::node::nanomsg_init(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::nanomsg_init(NodeCompat *n) { + auto *m = n->getData(); - m->formatter = nullptr; + m->formatter = nullptr; - return 0; + return 0; } -int villas::node::nanomsg_destroy(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::nanomsg_destroy(NodeCompat *n) { + auto *m = n->getData(); - if (m->formatter) - delete m->formatter; + if (m->formatter) + delete m->formatter; - return 0; + return 0; } -int villas::node::nanomsg_reverse(NodeCompat *n) -{ - auto *m = n->getData(); +int villas::node::nanomsg_reverse(NodeCompat *n) { + auto *m = n->getData(); - if (list_length(&m->out.endpoints) != 1 || - list_length(&m->in.endpoints) != 1) - return -1; + if (list_length(&m->out.endpoints) != 1 || list_length(&m->in.endpoints) != 1) + return -1; - char *subscriber = (char *) list_first(&m->in.endpoints); - char *publisher = (char *) list_first(&m->out.endpoints); + char *subscriber = (char *)list_first(&m->in.endpoints); + char *publisher = (char *)list_first(&m->out.endpoints); - list_set(&m->in.endpoints, 0, publisher); - list_set(&m->out.endpoints, 0, subscriber); + list_set(&m->in.endpoints, 0, publisher); + list_set(&m->out.endpoints, 0, subscriber); - return 0; + return 0; } -static -int nanomsg_parse_endpoints(struct List *l, json_t *json) -{ - const char *ep; +static int nanomsg_parse_endpoints(struct List *l, json_t *json) { + const char *ep; - size_t i; - json_t *json_val; + size_t i; + json_t *json_val; - switch (json_typeof(json)) { - case JSON_ARRAY: - json_array_foreach(json, i, json_val) { - ep = json_string_value(json_val); - if (!ep) - return -1; + switch (json_typeof(json)) { + case JSON_ARRAY: + json_array_foreach(json, i, json_val) { + ep = json_string_value(json_val); + if (!ep) + return -1; - list_push(l, strdup(ep)); - } - break; + list_push(l, strdup(ep)); + } + break; - case JSON_STRING: - ep = json_string_value(json); + case JSON_STRING: + ep = json_string_value(json); - list_push(l, strdup(ep)); - break; + list_push(l, strdup(ep)); + break; - default: - return -1; - } + default: + return -1; + } - return 0; + return 0; } -int villas::node::nanomsg_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_parse(NodeCompat *n, json_t *json) { + int ret; + auto *m = n->getData(); - json_error_t err; - json_t *json_format = nullptr; - json_t *json_out_endpoints = nullptr; - json_t *json_in_endpoints = nullptr; + json_error_t err; + json_t *json_format = nullptr; + json_t *json_out_endpoints = nullptr; + json_t *json_in_endpoints = nullptr; - ret = list_init(&m->out.endpoints); - if (ret) - return ret; + ret = list_init(&m->out.endpoints); + if (ret) + return ret; - ret = list_init(&m->in.endpoints); - if (ret) - return ret; + ret = list_init(&m->in.endpoints); + if (ret) + return ret; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: { s?: o }, s?: { s?: o } }", - "format", &json_format, - "out", - "endpoints", &json_out_endpoints, - "in", - "endpoints", &json_in_endpoints - ); - if (ret) - throw ConfigError(json, err, "node-config-node-nanomsg"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: { s?: o }, s?: { s?: o } }", + "format", &json_format, "out", "endpoints", + &json_out_endpoints, "in", "endpoints", + &json_in_endpoints); + if (ret) + throw ConfigError(json, err, "node-config-node-nanomsg"); - if (json_out_endpoints) { - ret = nanomsg_parse_endpoints(&m->out.endpoints, json_out_endpoints); - if (ret < 0) - throw RuntimeError("Invalid type for 'publish' setting"); - } + if (json_out_endpoints) { + ret = nanomsg_parse_endpoints(&m->out.endpoints, json_out_endpoints); + if (ret < 0) + throw RuntimeError("Invalid type for 'publish' setting"); + } - if (json_in_endpoints) { - ret = nanomsg_parse_endpoints(&m->in.endpoints, json_in_endpoints); - if (ret < 0) - throw RuntimeError("Invalid type for 'subscribe' setting"); - } + if (json_in_endpoints) { + ret = nanomsg_parse_endpoints(&m->in.endpoints, json_in_endpoints); + if (ret < 0) + throw RuntimeError("Invalid type for 'subscribe' setting"); + } - // Format - if (m->formatter) - delete m->formatter; - m->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("json"); - if (!m->formatter) - throw ConfigError(json_format, "node-config-node-nanomsg-format", "Invalid format configuration"); + // Format + if (m->formatter) + delete m->formatter; + m->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("json"); + if (!m->formatter) + throw ConfigError(json_format, "node-config-node-nanomsg-format", + "Invalid format configuration"); - return 0; + return 0; } -char * villas::node::nanomsg_print(NodeCompat *n) -{ - auto *m = n->getData(); +char *villas::node::nanomsg_print(NodeCompat *n) { + auto *m = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - strcatf(&buf, "in.endpoints=[ "); + strcatf(&buf, "in.endpoints=[ "); - for (size_t i = 0; i < list_length(&m->in.endpoints); i++) { - char *ep = (char *) list_at(&m->in.endpoints, i); + for (size_t i = 0; i < list_length(&m->in.endpoints); i++) { + char *ep = (char *)list_at(&m->in.endpoints, i); - strcatf(&buf, "%s ", ep); - } + strcatf(&buf, "%s ", ep); + } - strcatf(&buf, "], out.endpoints=[ "); + strcatf(&buf, "], out.endpoints=[ "); - for (size_t i = 0; i < list_length(&m->out.endpoints); i++) { - char *ep = (char *) list_at(&m->out.endpoints, i); + for (size_t i = 0; i < list_length(&m->out.endpoints); i++) { + char *ep = (char *)list_at(&m->out.endpoints, i); - strcatf(&buf, "%s ", ep); - } + strcatf(&buf, "%s ", ep); + } - strcatf(&buf, "]"); + strcatf(&buf, "]"); - return buf; + return buf; } -int villas::node::nanomsg_start(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_start(NodeCompat *n) { + int ret; + auto *m = n->getData(); - m->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + m->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - ret = m->in.socket = nn_socket(AF_SP, NN_SUB); - if (ret < 0) - throw RuntimeError("Failed to create nanomsg socket: {}", nn_strerror(errno)); + ret = m->in.socket = nn_socket(AF_SP, NN_SUB); + if (ret < 0) + throw RuntimeError("Failed to create nanomsg socket: {}", + nn_strerror(errno)); - ret = m->out.socket = nn_socket(AF_SP, NN_PUB); - if (ret < 0) - throw RuntimeError("Failed to create nanomsg socket: {}", nn_strerror(errno)); + ret = m->out.socket = nn_socket(AF_SP, NN_PUB); + if (ret < 0) + throw RuntimeError("Failed to create nanomsg socket: {}", + nn_strerror(errno)); - // Subscribe to all topics - ret = nn_setsockopt(ret = m->in.socket, NN_SUB, NN_SUB_SUBSCRIBE, "", 0); - if (ret < 0) - return ret; + // Subscribe to all topics + ret = nn_setsockopt(ret = m->in.socket, NN_SUB, NN_SUB_SUBSCRIBE, "", 0); + if (ret < 0) + return ret; - // Bind publisher to socket - for (size_t i = 0; i < list_length(&m->out.endpoints); i++) { - char *ep = (char *) list_at(&m->out.endpoints, i); + // Bind publisher to socket + for (size_t i = 0; i < list_length(&m->out.endpoints); i++) { + char *ep = (char *)list_at(&m->out.endpoints, i); - ret = nn_bind(m->out.socket, ep); - if (ret < 0) - throw RuntimeError("Failed to connect nanomsg socket to endpoint {}: {}", ep, nn_strerror(errno)); - } + ret = nn_bind(m->out.socket, ep); + if (ret < 0) + throw RuntimeError("Failed to connect nanomsg socket to endpoint {}: {}", + ep, nn_strerror(errno)); + } - // Connect subscribers socket - for (size_t i = 0; i < list_length(&m->in.endpoints); i++) { - char *ep = (char *) list_at(&m->in.endpoints, i); + // Connect subscribers socket + for (size_t i = 0; i < list_length(&m->in.endpoints); i++) { + char *ep = (char *)list_at(&m->in.endpoints, i); - ret = nn_connect(m->in.socket, ep); - if (ret < 0) - throw RuntimeError("Failed to connect nanomsg socket to endpoint {}: {}", ep, nn_strerror(errno)); - } + ret = nn_connect(m->in.socket, ep); + if (ret < 0) + throw RuntimeError("Failed to connect nanomsg socket to endpoint {}: {}", + ep, nn_strerror(errno)); + } - return 0; + return 0; } -int villas::node::nanomsg_stop(NodeCompat *n) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_stop(NodeCompat *n) { + int ret; + auto *m = n->getData(); - ret = nn_close(m->in.socket); - if (ret < 0) - return ret; + ret = nn_close(m->in.socket); + if (ret < 0) + return ret; - ret = nn_close(m->out.socket); - if (ret < 0) - return ret; + ret = nn_close(m->out.socket); + if (ret < 0) + return ret; - return 0; + return 0; } -int villas::node::nanomsg_type_stop() -{ - nn_term(); +int villas::node::nanomsg_type_stop() { + nn_term(); - return 0; + return 0; } -int villas::node::nanomsg_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *m = n->getData(); - int bytes; - char data[NANOMSG_MAX_PACKET_LEN]; +int villas::node::nanomsg_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *m = n->getData(); + int bytes; + char data[NANOMSG_MAX_PACKET_LEN]; - // Receive payload - bytes = nn_recv(m->in.socket, data, sizeof(data), 0); - if (bytes < 0) - return -1; + // Receive payload + bytes = nn_recv(m->in.socket, data, sizeof(data), 0); + if (bytes < 0) + return -1; - return m->formatter->sscan(data, bytes, nullptr, smps, cnt); + return m->formatter->sscan(data, bytes, nullptr, smps, cnt); } -int villas::node::nanomsg_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *m = n->getData(); - size_t wbytes; + size_t wbytes; - char data[NANOMSG_MAX_PACKET_LEN]; + char data[NANOMSG_MAX_PACKET_LEN]; - ret = m->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret <= 0) - return -1; + ret = m->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret <= 0) + return -1; - ret = nn_send(m->out.socket, data, wbytes, 0); - if (ret < 0) - return ret; + ret = nn_send(m->out.socket, data, wbytes, 0); + if (ret < 0) + return ret; - return cnt; + return cnt; } -int villas::node::nanomsg_poll_fds(NodeCompat *n, int fds[]) -{ - int ret; - auto *m = n->getData(); +int villas::node::nanomsg_poll_fds(NodeCompat *n, int fds[]) { + int ret; + auto *m = n->getData(); - int fd; - size_t len = sizeof(fd); + int fd; + size_t len = sizeof(fd); - ret = nn_getsockopt(m->in.socket, NN_SOL_SOCKET, NN_RCVFD, &fd, &len); - if (ret) - return ret; + ret = nn_getsockopt(m->in.socket, NN_SOL_SOCKET, NN_RCVFD, &fd, &len); + if (ret) + return ret; - fds[0] = fd; + fds[0] = fd; - return 1; + return 1; } -int villas::node::nanomsg_netem_fds(NodeCompat *n, int fds[]) -{ - auto *m = n->getData(); +int villas::node::nanomsg_netem_fds(NodeCompat *n, int fds[]) { + auto *m = n->getData(); - fds[0] = m->out.socket; + fds[0] = m->out.socket; - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "nanomsg"; - p.description = "scalability protocols library (libnanomsg)"; - p.vectorize = 0; - p.size = sizeof(struct nanomsg); - p.type.stop = nanomsg_type_stop; - p.init = nanomsg_init; - p.destroy = nanomsg_destroy; - p.parse = nanomsg_parse; - p.print = nanomsg_print; - p.start = nanomsg_start; - p.stop = nanomsg_stop; - p.read = nanomsg_read; - p.write = nanomsg_write; - p.reverse = nanomsg_reverse; - p.poll_fds = nanomsg_poll_fds; - p.netem_fds = nanomsg_netem_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "nanomsg"; + p.description = "scalability protocols library (libnanomsg)"; + p.vectorize = 0; + p.size = sizeof(struct nanomsg); + p.type.stop = nanomsg_type_stop; + p.init = nanomsg_init; + p.destroy = nanomsg_destroy; + p.parse = nanomsg_parse; + p.print = nanomsg_print; + p.start = nanomsg_start; + p.stop = nanomsg_stop; + p.read = nanomsg_read; + p.write = nanomsg_write; + p.reverse = nanomsg_reverse; + p.poll_fds = nanomsg_poll_fds; + p.netem_fds = nanomsg_netem_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/ngsi.cpp b/lib/nodes/ngsi.cpp index 5088ab86f..aeb00d7f0 100644 --- a/lib/nodes/ngsi.cpp +++ b/lib/nodes/ngsi.cpp @@ -5,24 +5,24 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include +#include #include -#include -#include #include #include -#include +#include +#include +#include +#include +#include #include #include -#include #include -#include #include -#include +#include using namespace villas; using namespace villas::node; @@ -31,843 +31,808 @@ using namespace villas::utils; // Some global settings #if OPENSSL_VERSION_NUMBER < 0x010003000L - // See: https://curl.haxx.se/libcurl/c/opensslthreadlock.html - #define CURL_SSL_REQUIRES_LOCKING +// See: https://curl.haxx.se/libcurl/c/opensslthreadlock.html +#define CURL_SSL_REQUIRES_LOCKING #endif #ifdef CURL_SSL_REQUIRES_LOCKING // This array will store all of the mutexes available to OpenSSL. -static -pthread_mutex_t *mutex_buf = NULL; +static pthread_mutex_t *mutex_buf = NULL; -static -void handle_error(const char *file, int lineno, const char *msg) -{ - auto logger = logging.get("curl"); +static void handle_error(const char *file, int lineno, const char *msg) { + auto logger = logging.get("curl"); - logger->error("** {}:{} {}", file, lineno, msg); + logger->error("** {}:{} {}", file, lineno, msg); - ERR_print_errors_fp(stderr); + ERR_print_errors_fp(stderr); - // exit(-1); + // exit(-1); } -static -void curl_ssl_locking_function(int mode, int n, const char *file, int line) -{ - if (mode & CRYPTO_LOCK) - pthread_mutex_lock(&mutex_buf[n]); - else - pthread_mutex_unlock(&mutex_buf[n]); +static void curl_ssl_locking_function(int mode, int n, const char *file, + int line) { + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(&mutex_buf[n]); + else + pthread_mutex_unlock(&mutex_buf[n]); } -static -unsigned long curl_ssl_thread_id_function(void) -{ - return ((unsigned long) pthread_self()); +static unsigned long curl_ssl_thread_id_function(void) { + return ((unsigned long)pthread_self()); } #endif // CURL_SSL_REQUIRES_LOCKING enum NgsiFlags { - NGSI_ENTITY_ATTRIBUTES_IN = (1 << 0), - NGSI_ENTITY_ATTRIBUTES_OUT = (1 << 1), - NGSI_ENTITY_ATTRIBUTES = NGSI_ENTITY_ATTRIBUTES_IN | NGSI_ENTITY_ATTRIBUTES_OUT, - NGSI_ENTITY_VALUES = (1 << 2), - NGSI_ENTITY_METADATA = (1 << 3), + NGSI_ENTITY_ATTRIBUTES_IN = (1 << 0), + NGSI_ENTITY_ATTRIBUTES_OUT = (1 << 1), + NGSI_ENTITY_ATTRIBUTES = + NGSI_ENTITY_ATTRIBUTES_IN | NGSI_ENTITY_ATTRIBUTES_OUT, + NGSI_ENTITY_VALUES = (1 << 2), + NGSI_ENTITY_METADATA = (1 << 3), }; class NgsiMetadata { public: - NgsiMetadata(json_t *json) - { - parse(json); - } + NgsiMetadata(json_t *json) { parse(json); } - NgsiMetadata(const std::string &nam, const std::string &typ, const std::string &val) : - name(nam), - type(typ), - value(val) - { } + NgsiMetadata(const std::string &nam, const std::string &typ, + const std::string &val) + : name(nam), type(typ), value(val) {} - void parse(json_t *json) - { - int ret; + void parse(json_t *json) { + int ret; - json_error_t err; - const char *nam, *typ, *val; + json_error_t err; + const char *nam, *typ, *val; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: s }", - "name", &nam, - "type", &typ, - "value", &val - ); - if (ret) - throw ConfigError(json, "node-config-node-ngsi-metadata", "Failed to parse NGSI metadata"); + ret = json_unpack_ex(json, &err, 0, "{ s: s, s: s, s: s }", "name", &nam, + "type", &typ, "value", &val); + if (ret) + throw ConfigError(json, "node-config-node-ngsi-metadata", + "Failed to parse NGSI metadata"); - name = nam; - type = typ; - value = val; - } + name = nam; + type = typ; + value = val; + } - std::string name; - std::string type; - std::string value; + std::string name; + std::string type; + std::string value; }; class NgsiAttribute { public: - std::string name; - std::string type; + std::string name; + std::string type; - size_t index; - std::list metadata; + size_t index; + std::list metadata; - NgsiAttribute(json_t *json, size_t j, Signal::Ptr s) - { - parse(json, j, s); - } + NgsiAttribute(json_t *json, size_t j, Signal::Ptr s) { parse(json, j, s); } - void parse(json_t *json, size_t j, Signal::Ptr s) - { - int ret; + void parse(json_t *json, size_t j, Signal::Ptr s) { + int ret; - json_error_t err; - json_t *json_metadatas = nullptr; + json_error_t err; + json_t *json_metadatas = nullptr; - const char *nam = nullptr; - const char *typ = nullptr; + const char *nam = nullptr; + const char *typ = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o }", - "ngsi_attribute_name", &nam, - "ngsi_attribute_type", &typ, - "ngsi_metadatas", &json_metadatas - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ngsi", "Failed to parse NGSI attribute"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o }", + "ngsi_attribute_name", &nam, "ngsi_attribute_type", + &typ, "ngsi_metadatas", &json_metadatas); + if (ret) + throw ConfigError(json, err, "node-config-node-ngsi", + "Failed to parse NGSI attribute"); - // Copy values from node signal, if 'ngsi_attribute' settings not provided - if (s && !nam) - nam = !s->name.empty() ? s->name.c_str() : ""; + // Copy values from node signal, if 'ngsi_attribute' settings not provided + if (s && !nam) + nam = !s->name.empty() ? s->name.c_str() : ""; - if (s && !typ) - typ = !s->unit.empty() ? s->unit.c_str() : ""; + if (s && !typ) + typ = !s->unit.empty() ? s->unit.c_str() : ""; - name = nam; - type = typ; - index = j; + name = nam; + type = typ; + index = j; - if (json_metadatas) { - if (!json_is_array(json_metadatas)) - throw ConfigError(json_metadatas, "node-config-node-ngsi-metadata", "ngsi_metadata must be a list of objects"); + if (json_metadatas) { + if (!json_is_array(json_metadatas)) + throw ConfigError(json_metadatas, "node-config-node-ngsi-metadata", + "ngsi_metadata must be a list of objects"); - json_t *json_metadata; + json_t *json_metadata; - // cppcheck-suppress unknownMacro - json_array_foreach(json_metadatas, j, json_metadata) - metadata.emplace_back(json_metadata); - } + // cppcheck-suppress unknownMacro + json_array_foreach(json_metadatas, j, json_metadata) + metadata.emplace_back(json_metadata); + } - // Metadata: index(integer)=j - metadata.emplace_back("index", "integer", fmt::format("{}", j)); - } + // Metadata: index(integer)=j + metadata.emplace_back("index", "integer", fmt::format("{}", j)); + } - json_t * build(const struct Sample * const smps[], unsigned cnt, int flags) - { - json_t *json_attribute = json_pack("{ s: s, s: s }", - "name", name.c_str(), - "type", type.c_str() - ); + json_t *build(const struct Sample *const smps[], unsigned cnt, int flags) { + json_t *json_attribute = + json_pack("{ s: s, s: s }", "name", name.c_str(), "type", type.c_str()); - if (flags & NGSI_ENTITY_VALUES) { + if (flags & NGSI_ENTITY_VALUES) { #if NGSI_VECTORS - // Build value vector - json_t *json_value = json_array(); + // Build value vector + json_t *json_value = json_array(); - for (unsigned k = 0; k < cnt; k++) { - const auto *smp = &smps[k]; - const auto *data = &smp->data[index]; - auto sig = smp->signals->getByIndex(index); + for (unsigned k = 0; k < cnt; k++) { + const auto *smp = &smps[k]; + const auto *data = &smp->data[index]; + auto sig = smp->signals->getByIndex(index); - json_array_append_new(json_value, json_pack("[ f, o, i ]", - time_to_double(smp->ts.origin), - data->toJson(sig->type), - smp->sequence - )); - } + json_array_append_new( + json_value, json_pack("[ f, o, i ]", time_to_double(smp->ts.origin), + data->toJson(sig->type), smp->sequence)); + } #else - const auto *smp = smps[0]; - const auto sig = smp->signals->getByIndex(index); - const auto *data = &smp->data[index]; + const auto *smp = smps[0]; + const auto sig = smp->signals->getByIndex(index); + const auto *data = &smp->data[index]; - json_t *json_value = data->toJson(sig->type); + json_t *json_value = data->toJson(sig->type); #endif - json_object_set(json_attribute, "value", json_value); - } + json_object_set(json_attribute, "value", json_value); + } - if (flags & NGSI_ENTITY_METADATA) { // Create Metadata for attribute - json_t *json_metadatas = json_array(); + if (flags & NGSI_ENTITY_METADATA) { // Create Metadata for attribute + json_t *json_metadatas = json_array(); - for (auto &meta : metadata) { - json_array_append_new(json_metadatas, json_pack("{ s: s, s: s, s: s }", - "name", meta.name.c_str(), - "type", meta.type.c_str(), - "value", meta.value.c_str() - )); - } + for (auto &meta : metadata) { + json_array_append_new( + json_metadatas, + json_pack("{ s: s, s: s, s: s }", "name", meta.name.c_str(), "type", + meta.type.c_str(), "value", meta.value.c_str())); + } - json_object_set(json_attribute, "metadatas", json_metadatas); - } + json_object_set(json_attribute, "metadatas", json_metadatas); + } - return json_attribute; - } + return json_attribute; + } }; struct ngsi_response { - char *data; - size_t len; + char *data; + size_t len; }; -static -json_t* ngsi_build_entity(NodeCompat *n, const struct Sample * const smps[], unsigned cnt, int flags) -{ - auto *i = n->getData(); +static json_t *ngsi_build_entity(NodeCompat *n, + const struct Sample *const smps[], + unsigned cnt, int flags) { + auto *i = n->getData(); - json_t *json_entity = json_pack("{ s: s, s: s, s: b }", - "id", i->entity_id, - "type", i->entity_type, - "isPattern", 0 - ); + json_t *json_entity = json_pack("{ s: s, s: s, s: b }", "id", i->entity_id, + "type", i->entity_type, "isPattern", 0); - if (flags & NGSI_ENTITY_ATTRIBUTES) { - json_t *json_attrs = json_array(); + if (flags & NGSI_ENTITY_ATTRIBUTES) { + json_t *json_attrs = json_array(); - if (flags & NGSI_ENTITY_ATTRIBUTES_IN) { - for (size_t j = 0; j < list_length(&i->in.signals); j++) { - auto *attr = (NgsiAttribute *) list_at(&i->in.signals, j); + if (flags & NGSI_ENTITY_ATTRIBUTES_IN) { + for (size_t j = 0; j < list_length(&i->in.signals); j++) { + auto *attr = (NgsiAttribute *)list_at(&i->in.signals, j); - auto *json_attr = attr->build(smps, cnt, flags); + auto *json_attr = attr->build(smps, cnt, flags); - json_array_append_new(json_attrs, json_attr); - } - } + json_array_append_new(json_attrs, json_attr); + } + } - if (flags & NGSI_ENTITY_ATTRIBUTES_OUT) { - for (size_t j = 0; j < list_length(&i->out.signals); j++) { - auto *attr = (NgsiAttribute *) list_at(&i->out.signals, j); + if (flags & NGSI_ENTITY_ATTRIBUTES_OUT) { + for (size_t j = 0; j < list_length(&i->out.signals); j++) { + auto *attr = (NgsiAttribute *)list_at(&i->out.signals, j); - auto *json_attr = attr->build(smps, cnt, flags); + auto *json_attr = attr->build(smps, cnt, flags); - json_array_append_new(json_attrs, json_attr); - } - } + json_array_append_new(json_attrs, json_attr); + } + } - json_object_set(json_entity, "attributes", json_attrs); - } + json_object_set(json_entity, "attributes", json_attrs); + } - return json_entity; + return json_entity; } -static -int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, struct Sample * const smps[], unsigned cnt) -{ - int ret, length = 0; - const char *id, *name, *type; +static int ngsi_parse_entity(NodeCompat *n, json_t *json_entity, + struct Sample *const smps[], unsigned cnt) { + int ret, length = 0; + const char *id, *name, *type; - auto *i = n->getData(); + auto *i = n->getData(); - size_t l; - json_error_t err; - json_t *json_attr, *json_attrs; + size_t l; + json_error_t err; + json_t *json_attr, *json_attrs; - ret = json_unpack_ex(json_entity, &err, 0, "{ s: s, s: s, s: o }", - "id", &id, - "type", &type, - "attributes", &json_attrs - ); - if (ret || !json_is_array(json_attrs)) - return -1; + ret = json_unpack_ex(json_entity, &err, 0, "{ s: s, s: s, s: o }", "id", &id, + "type", &type, "attributes", &json_attrs); + if (ret || !json_is_array(json_attrs)) + return -1; - if (strcmp(id, i->entity_id) || strcmp(type, i->entity_type)) - return -2; + if (strcmp(id, i->entity_id) || strcmp(type, i->entity_type)) + return -2; - json_array_foreach(json_attrs, l, json_attr) { - NgsiAttribute *attr; - json_error_t err; - json_t *json_metadata, *json_value; + json_array_foreach(json_attrs, l, json_attr) { + NgsiAttribute *attr; + json_error_t err; + json_t *json_metadata, *json_value; - char *end; - const char *value; + char *end; + const char *value; - // Parse JSON - ret = json_unpack_ex(json_attr, &err, 0, "{ s: s, s: s, s: o, s?: o }", - "name", &name, - "type", &type, - "value", &json_value, - "metadatas", &json_metadata - ); - if (ret) - return -3; + // Parse JSON + ret = json_unpack_ex(json_attr, &err, 0, "{ s: s, s: s, s: o, s?: o }", + "name", &name, "type", &type, "value", &json_value, + "metadatas", &json_metadata); + if (ret) + return -3; - // Check attribute name and type - attr = list_lookup_name(&i->in.signals, name); - if (!attr || attr->type != type) - continue; // skip unknown attributes + // Check attribute name and type + attr = list_lookup_name(&i->in.signals, name); + if (!attr || attr->type != type) + continue; // skip unknown attributes - length++; + length++; - // Check metadata - if (!json_is_array(json_metadata)) - return -5; + // Check metadata + if (!json_is_array(json_metadata)) + return -5; #ifdef NGSI_VECTORS - json_t *json_tuple; - const char *ts, *seq; + json_t *json_tuple; + const char *ts, *seq; - // Check number of values - if (!json_is_array(json_value) || json_array_size(json_value) != cnt) - return -6; + // Check number of values + if (!json_is_array(json_value) || json_array_size(json_value) != cnt) + return -6; - size_t k; - json_array_foreach(json_value, k, json_tuple) { - struct Sample *smp = smps[k]; + size_t k; + json_array_foreach(json_value, k, json_tuple) { + struct Sample *smp = smps[k]; - // Check sample format - if (!json_is_array(json_tuple) || json_array_size(json_tuple) != 3) - return -7; + // Check sample format + if (!json_is_array(json_tuple) || json_array_size(json_tuple) != 3) + return -7; - ret = json_unpack_ex(json_tuple, &err, 0, "[ s, s, s ]", &ts, &value, &seq); - if (ret) - return -8; + ret = + json_unpack_ex(json_tuple, &err, 0, "[ s, s, s ]", &ts, &value, &seq); + if (ret) + return -8; - smp->sequence = atoi(seq); + smp->sequence = atoi(seq); - struct timespec tss = time_from_double(strtod(ts, &end)); - if (ts == end) - return -9; + struct timespec tss = time_from_double(strtod(ts, &end)); + if (ts == end) + return -9; - smp->ts.origin = tss; + smp->ts.origin = tss; - auto *sd = &smp->data[attr->index]; - auto sig = n->getInputSignals(false)->getByIndex(attr->index); - if (!sig) - return -11; + auto *sd = &smp->data[attr->index]; + auto sig = n->getInputSignals(false)->getByIndex(attr->index); + if (!sig) + return -11; - if (value[0] == '\0') // No data on Orion CB? -> Use init value - *sd = sig->init; - else { - signal_data_parse_str(sd, sig->type, value, &end); - if (value == end) - return -10; - } - } + if (value[0] == '\0') // No data on Orion CB? -> Use init value + *sd = sig->init; + else { + signal_data_parse_str(sd, sig->type, value, &end); + if (value == end) + return -10; + } + } #else - struct Sample *smp = smps[0]; + struct Sample *smp = smps[0]; - // Check number of values - if (!json_is_string(json_value)) - return -6; + // Check number of values + if (!json_is_string(json_value)) + return -6; - value = json_string_value(json_value); + value = json_string_value(json_value); - auto *data = &smp->data[attr->index]; - auto sig = n->getInputSignals(false)->getByIndex(attr->index); - if (!sig) - return -11; + auto *data = &smp->data[attr->index]; + auto sig = n->getInputSignals(false)->getByIndex(attr->index); + if (!sig) + return -11; - if (value[0] == '\0') // No data on Orion CB? -> Use init value - *data = sig->init; - else { - data->parseString(sig->type, value, &end); - if (value == end) - return -10; - } + if (value[0] == '\0') // No data on Orion CB? -> Use init value + *data = sig->init; + else { + data->parseString(sig->type, value, &end); + if (value == end) + return -10; + } #endif - } + } - for (unsigned k = 0; k < cnt; k++) { - struct Sample *smp = smps[k]; + for (unsigned k = 0; k < cnt; k++) { + struct Sample *smp = smps[k]; - smp->length = length; - smp->signals = n->getInputSignals(false); - smp->flags = (int) SampleFlags::HAS_DATA; + smp->length = length; + smp->signals = n->getInputSignals(false); + smp->flags = (int)SampleFlags::HAS_DATA; #ifdef NGSI_VECTORS - smp->flags |= (int) (SampleFlags::HAS_SEQUENCE | - SampleFlags::HAS_TS_ORIGIN); + smp->flags |= (int)(SampleFlags::HAS_SEQUENCE | SampleFlags::HAS_TS_ORIGIN); #endif - } + } - return cnt; + return cnt; } -static -int ngsi_parse_signals(json_t *json_signals, struct List *ngsi_signals, SignalList::Ptr node_signals) -{ - size_t j; - json_t *json_signal; +static int ngsi_parse_signals(json_t *json_signals, struct List *ngsi_signals, + SignalList::Ptr node_signals) { + size_t j; + json_t *json_signal; - if (!json_is_array(json_signals)) - return -1; + if (!json_is_array(json_signals)) + return -1; - json_array_foreach(json_signals, j, json_signal) { - auto s = node_signals->getByIndex(j); - auto *a = new NgsiAttribute(json_signal, j, s); - if (!a) - throw MemoryAllocationError(); + json_array_foreach(json_signals, j, json_signal) { + auto s = node_signals->getByIndex(j); + auto *a = new NgsiAttribute(json_signal, j, s); + if (!a) + throw MemoryAllocationError(); - list_push(ngsi_signals, a); - } + list_push(ngsi_signals, a); + } - return 0; + return 0; } -static -int ngsi_parse_context_response(json_t *json_response, int *code, char **reason, json_t **json_rentity, Logger logger) { - int ret; - char *codestr; +static int ngsi_parse_context_response(json_t *json_response, int *code, + char **reason, json_t **json_rentity, + Logger logger) { + int ret; + char *codestr; - json_error_t err; + json_error_t err; - ret = json_unpack_ex(json_response, &err, 0, "{ s: [ { s: O, s: { s: s, s: s } } ] }", - "contextResponses", - "contextElement", json_rentity, - "statusCode", - "code", &codestr, - "reasonPhrase", reason - ); - if (ret) { - logger->warn("Failed to find NGSI response code"); - return ret; - } + ret = json_unpack_ex(json_response, &err, 0, + "{ s: [ { s: O, s: { s: s, s: s } } ] }", + "contextResponses", "contextElement", json_rentity, + "statusCode", "code", &codestr, "reasonPhrase", reason); + if (ret) { + logger->warn("Failed to find NGSI response code"); + return ret; + } - *code = atoi(codestr); + *code = atoi(codestr); - if (*code != 200) - logger->warn("NGSI response: {} {}", codestr, *reason); + if (*code != 200) + logger->warn("NGSI response: {} {}", codestr, *reason); - return ret; + return ret; } -static -size_t ngsi_request_writer(void *contents, size_t size, size_t nmemb, void *userp) -{ - size_t realsize = size * nmemb; - struct ngsi_response *mem = (struct ngsi_response *) userp; +static size_t ngsi_request_writer(void *contents, size_t size, size_t nmemb, + void *userp) { + size_t realsize = size * nmemb; + struct ngsi_response *mem = (struct ngsi_response *)userp; - mem->data = (char *) realloc(mem->data, mem->len + realsize + 1); - if (mem->data == nullptr) // out of memory! - throw MemoryAllocationError(); + mem->data = (char *)realloc(mem->data, mem->len + realsize + 1); + if (mem->data == nullptr) // out of memory! + throw MemoryAllocationError(); - memcpy(&(mem->data[mem->len]), contents, realsize); - mem->len += realsize; - mem->data[mem->len] = 0; + memcpy(&(mem->data[mem->len]), contents, realsize); + mem->len += realsize; + mem->data[mem->len] = 0; - return realsize; + return realsize; } -static -int ngsi_request(CURL *handle, const char *endpoint, const char *operation, json_t *json_request, json_t **json_response, Logger logger) -{ - struct ngsi_response chunk = { 0 }; - char *post = json_dumps(json_request, JSON_INDENT(4)); - int old; - double time; - char url[128]; - json_error_t err; +static int ngsi_request(CURL *handle, const char *endpoint, + const char *operation, json_t *json_request, + json_t **json_response, Logger logger) { + struct ngsi_response chunk = {0}; + char *post = json_dumps(json_request, JSON_INDENT(4)); + int old; + double time; + char url[128]; + json_error_t err; - snprintf(url, sizeof(url), "%s/v1/%s", endpoint, operation); + snprintf(url, sizeof(url), "%s/v1/%s", endpoint, operation); - curl_easy_setopt(handle, CURLOPT_URL, url); - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ngsi_request_writer); - curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *) &chunk); - curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(post)); - curl_easy_setopt(handle, CURLOPT_POSTFIELDS, post); + curl_easy_setopt(handle, CURLOPT_URL, url); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ngsi_request_writer); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *)&chunk); + curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(post)); + curl_easy_setopt(handle, CURLOPT_POSTFIELDS, post); - logger->debug("Request to context broker: {}\n{}", url, post); + logger->debug("Request to context broker: {}\n{}", url, post); - // We don't want to leave the handle in an invalid state - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old); - CURLcode ret = curl_easy_perform(handle); - pthread_setcancelstate(old, nullptr); + // We don't want to leave the handle in an invalid state + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old); + CURLcode ret = curl_easy_perform(handle); + pthread_setcancelstate(old, nullptr); - if (ret) { - logger->warn("HTTP request failed: {}", curl_easy_strerror(ret)); - goto out; - } + if (ret) { + logger->warn("HTTP request failed: {}", curl_easy_strerror(ret)); + goto out; + } - curl_easy_getinfo(handle, CURLINFO_TOTAL_TIME, &time); + curl_easy_getinfo(handle, CURLINFO_TOTAL_TIME, &time); - logger->debug("Request to context broker completed in {} seconds", time); - logger->debug("Response from context broker:\n{}", chunk.data); + logger->debug("Request to context broker completed in {} seconds", time); + logger->debug("Response from context broker:\n{}", chunk.data); - *json_response = json_loads(chunk.data, 0, &err); - if (!*json_response) - logger->warn("Received invalid JSON: {} in {}:{}:{}\n{}", err.text, err.source, err.line, err.column, chunk.data); + *json_response = json_loads(chunk.data, 0, &err); + if (!*json_response) + logger->warn("Received invalid JSON: {} in {}:{}:{}\n{}", err.text, + err.source, err.line, err.column, chunk.data); -out: free(post); - free(chunk.data); +out: + free(post); + free(chunk.data); - return ret; + return ret; } -static -int ngsi_request_context_query(CURL *handle, const char *endpoint, json_t *json_entity, json_t **json_rentity, Logger logger) -{ - int ret, code; - char *reason; +static int ngsi_request_context_query(CURL *handle, const char *endpoint, + json_t *json_entity, + json_t **json_rentity, Logger logger) { + int ret, code; + char *reason; - json_t *json_response; - json_t *json_request = json_pack("{ s: [ O ] }", "entities", json_entity); + json_t *json_response; + json_t *json_request = json_pack("{ s: [ O ] }", "entities", json_entity); - ret = ngsi_request(handle, endpoint, "queryContext", json_request, &json_response, logger); - if (ret) { - ret = -1; - goto out; - } + ret = ngsi_request(handle, endpoint, "queryContext", json_request, + &json_response, logger); + if (ret) { + ret = -1; + goto out; + } - ret = ngsi_parse_context_response(json_response, &code, &reason, json_rentity, logger); - if (ret) - goto out2; + ret = ngsi_parse_context_response(json_response, &code, &reason, json_rentity, + logger); + if (ret) + goto out2; -out2: json_decref(json_response); -out: json_decref(json_request); +out2: + json_decref(json_response); +out: + json_decref(json_request); - return ret; + return ret; } -static -int ngsi_request_context_update(CURL *handle, const char *endpoint, const char *action, json_t *json_entity, Logger logger) -{ - int ret, code; - char *reason; +static int ngsi_request_context_update(CURL *handle, const char *endpoint, + const char *action, json_t *json_entity, + Logger logger) { + int ret, code; + char *reason; - json_t *json_response; - json_t *json_request = json_pack("{ s: s, s: [ O ] }", - "updateAction", action, - "contextElements", json_entity - ); + json_t *json_response; + json_t *json_request = json_pack("{ s: s, s: [ O ] }", "updateAction", action, + "contextElements", json_entity); - ret = ngsi_request(handle, endpoint, "updateContext", json_request, &json_response, logger); - if (ret) - goto out; + ret = ngsi_request(handle, endpoint, "updateContext", json_request, + &json_response, logger); + if (ret) + goto out; - json_t *json_rentity; - ret = ngsi_parse_context_response(json_response, &code, &reason, &json_rentity, logger); - if (ret) - goto out2; + json_t *json_rentity; + ret = ngsi_parse_context_response(json_response, &code, &reason, + &json_rentity, logger); + if (ret) + goto out2; - json_decref(json_rentity); -out2: json_decref(json_response); -out: json_decref(json_request); + json_decref(json_rentity); +out2: + json_decref(json_response); +out: + json_decref(json_request); - return ret; + return ret; } -int villas::node::ngsi_type_start(villas::node::SuperNode *sn) -{ +int villas::node::ngsi_type_start(villas::node::SuperNode *sn) { #ifdef CURL_SSL_REQUIRES_LOCKING - mutex_buf = new pthread_mutex_t[CRYPTO_num_locks()]; - if (!mutex_buf) - return -1; + mutex_buf = new pthread_mutex_t[CRYPTO_num_locks()]; + if (!mutex_buf) + return -1; - for (int i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_init(&mutex_buf[i], nullptr); + for (int i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_init(&mutex_buf[i], nullptr); - CRYPTO_set_id_callback(curl_ssl_thread_id_function); - CRYPTO_set_locking_callback(curl_ssl_locking_function); + CRYPTO_set_id_callback(curl_ssl_thread_id_function); + CRYPTO_set_locking_callback(curl_ssl_locking_function); - auto logger = logging.get("curl"); - logger->info("Setup libcurl/openssl locking primitives"); + auto logger = logging.get("curl"); + logger->info("Setup libcurl/openssl locking primitives"); #endif // CURL_SSL_REQUIRES_LOCKING - return curl_global_init(CURL_GLOBAL_ALL); + return curl_global_init(CURL_GLOBAL_ALL); } -int villas::node::ngsi_type_stop() -{ +int villas::node::ngsi_type_stop() { #ifdef CURL_SSL_REQUIRES_LOCKING - if (!mutex_buf) - return -1; + if (!mutex_buf) + return -1; - CRYPTO_set_id_callback(NULL); - CRYPTO_set_locking_callback(NULL); + CRYPTO_set_id_callback(NULL); + CRYPTO_set_locking_callback(NULL); - for (int i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_destroy(&mutex_buf[i]); + for (int i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_destroy(&mutex_buf[i]); - delete mutex_buf; + delete mutex_buf; #endif // CURL_SSL_REQUIRES_LOCKING - curl_global_cleanup(); + curl_global_cleanup(); - return 0; + return 0; } -int villas::node::ngsi_parse(NodeCompat *n, json_t *json) -{ - auto *i = n->getData(); +int villas::node::ngsi_parse(NodeCompat *n, json_t *json) { + auto *i = n->getData(); - int ret; - json_error_t err; - json_t *json_signals_in = nullptr; - json_t *json_signals_out = nullptr; + int ret; + json_error_t err; + json_t *json_signals_in = nullptr; + json_t *json_signals_out = nullptr; - int create = 1; - int remove = 1; + int create = 1; + int remove = 1; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s: s, s: s, s: s, s?: b, s?: F, s?: F, s?: b, s?: b, s?: { s?: o }, s?: { s?: o } }", - "access_token", &i->access_token, - "endpoint", &i->endpoint, - "entity_id", &i->entity_id, - "entity_type", &i->entity_type, - "ssl_verify", &i->ssl_verify, - "timeout", &i->timeout, - "rate", &i->rate, - "create", &create, - "delete", &remove, - "in", - "signals", &json_signals_in, - "out", - "signals", &json_signals_out - ); - if (ret) - throw ConfigError(json, err, "node-config-node-ngsi"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: s, s: s, s: s, s: s, s?: b, s?: F, s?: F, s?: b, " + "s?: b, s?: { s?: o }, s?: { s?: o } }", + "access_token", &i->access_token, "endpoint", + &i->endpoint, "entity_id", &i->entity_id, "entity_type", + &i->entity_type, "ssl_verify", &i->ssl_verify, "timeout", + &i->timeout, "rate", &i->rate, "create", &create, + "delete", &remove, "in", "signals", &json_signals_in, + "out", "signals", &json_signals_out); + if (ret) + throw ConfigError(json, err, "node-config-node-ngsi"); - i->create = create; - i->remove = remove; + i->create = create; + i->remove = remove; - if (json_signals_in) { - ret = ngsi_parse_signals(json_signals_in, &i->in.signals, n->in.signals); - if (ret) - throw ConfigError(json_signals_in, "node-config-node-ngsi-in-signals", "Invalid setting 'in.signals' of node {}", n->getName()); - } + if (json_signals_in) { + ret = ngsi_parse_signals(json_signals_in, &i->in.signals, n->in.signals); + if (ret) + throw ConfigError(json_signals_in, "node-config-node-ngsi-in-signals", + "Invalid setting 'in.signals' of node {}", + n->getName()); + } - if (json_signals_out) { - ret = ngsi_parse_signals(json_signals_out, &i->out.signals, n->out.signals); - if (ret) - throw ConfigError(json_signals_out, "node-config-node-ngsi-out-signals", "Invalid setting 'out.signals' of node {}", n->getName()); - } + if (json_signals_out) { + ret = ngsi_parse_signals(json_signals_out, &i->out.signals, n->out.signals); + if (ret) + throw ConfigError(json_signals_out, "node-config-node-ngsi-out-signals", + "Invalid setting 'out.signals' of node {}", + n->getName()); + } - return 0; + return 0; } -char * villas::node::ngsi_print(NodeCompat *n) -{ - auto *i = n->getData(); +char *villas::node::ngsi_print(NodeCompat *n) { + auto *i = n->getData(); - return strf("endpoint=%s, timeout=%.3f secs", - i->endpoint, i->timeout); + return strf("endpoint=%s, timeout=%.3f secs", i->endpoint, i->timeout); } -int villas::node::ngsi_start(NodeCompat *n) -{ - auto *i = n->getData(); +int villas::node::ngsi_start(NodeCompat *n) { + auto *i = n->getData(); - i->in.curl = curl_easy_init(); - i->out.curl = curl_easy_init(); - i->headers = nullptr; + i->in.curl = curl_easy_init(); + i->out.curl = curl_easy_init(); + i->headers = nullptr; - if (i->access_token) { - char buf[128]; - snprintf(buf, sizeof(buf), "Auth-Token: %s", i->access_token); - i->headers = curl_slist_append(i->headers, buf); - } + if (i->access_token) { + char buf[128]; + snprintf(buf, sizeof(buf), "Auth-Token: %s", i->access_token); + i->headers = curl_slist_append(i->headers, buf); + } - // Create task - if (i->timeout > 1 / i->rate) - n->logger->warn("Timeout is to large for given rate: {}", i->rate); + // Create task + if (i->timeout > 1 / i->rate) + n->logger->warn("Timeout is to large for given rate: {}", i->rate); - i->task.setRate(i->rate); + i->task.setRate(i->rate); - i->headers = curl_slist_append(i->headers, "Accept: application/json"); - i->headers = curl_slist_append(i->headers, "Content-Type: application/json"); + i->headers = curl_slist_append(i->headers, "Accept: application/json"); + i->headers = curl_slist_append(i->headers, "Content-Type: application/json"); - CURL *handles[] = { i->in.curl, i->out.curl }; + CURL *handles[] = {i->in.curl, i->out.curl}; - for (unsigned p = 0; p < ARRAY_LEN(handles); p++) { - curl_easy_setopt(handles[p], CURLOPT_SSL_VERIFYPEER, i->ssl_verify); - curl_easy_setopt(handles[p], CURLOPT_TIMEOUT_MS, i->timeout * 1e3); - curl_easy_setopt(handles[p], CURLOPT_HTTPHEADER, i->headers); - curl_easy_setopt(handles[p], CURLOPT_USERAGENT, HTTP_USER_AGENT); - } + for (unsigned p = 0; p < ARRAY_LEN(handles); p++) { + curl_easy_setopt(handles[p], CURLOPT_SSL_VERIFYPEER, i->ssl_verify); + curl_easy_setopt(handles[p], CURLOPT_TIMEOUT_MS, i->timeout * 1e3); + curl_easy_setopt(handles[p], CURLOPT_HTTPHEADER, i->headers); + curl_easy_setopt(handles[p], CURLOPT_USERAGENT, HTTP_USER_AGENT); + } - // Create entity and atributes - if (i->create) { - json_t *json_entity = ngsi_build_entity(n, nullptr, 0, NGSI_ENTITY_ATTRIBUTES | NGSI_ENTITY_METADATA); + // Create entity and atributes + if (i->create) { + json_t *json_entity = ngsi_build_entity( + n, nullptr, 0, NGSI_ENTITY_ATTRIBUTES | NGSI_ENTITY_METADATA); - int ret = ngsi_request_context_update(i->out.curl, i->endpoint, "APPEND", json_entity, n->logger); - if (ret) - throw RuntimeError("Failed to create NGSI context for node {}", n->getName()); + int ret = ngsi_request_context_update(i->out.curl, i->endpoint, "APPEND", + json_entity, n->logger); + if (ret) + throw RuntimeError("Failed to create NGSI context for node {}", + n->getName()); - json_decref(json_entity); - } + json_decref(json_entity); + } - return 0; + return 0; } -int villas::node::ngsi_stop(NodeCompat *n) -{ - auto *i = n->getData(); - int ret; +int villas::node::ngsi_stop(NodeCompat *n) { + auto *i = n->getData(); + int ret; - i->task.stop(); + i->task.stop(); - // Delete complete entity (not just attributes) - json_t *json_entity = ngsi_build_entity(n, nullptr, 0, 0); + // Delete complete entity (not just attributes) + json_t *json_entity = ngsi_build_entity(n, nullptr, 0, 0); - ret = ngsi_request_context_update(i->out.curl, i->endpoint, "DELETE", json_entity, n->logger); + ret = ngsi_request_context_update(i->out.curl, i->endpoint, "DELETE", + json_entity, n->logger); - json_decref(json_entity); + json_decref(json_entity); - curl_easy_cleanup(i->in.curl); - curl_easy_cleanup(i->out.curl); - curl_slist_free_all(i->headers); + curl_easy_cleanup(i->in.curl); + curl_easy_cleanup(i->out.curl); + curl_slist_free_all(i->headers); - return ret; + return ret; } -int villas::node::ngsi_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *i = n->getData(); - int ret; +int villas::node::ngsi_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *i = n->getData(); + int ret; - if (i->task.wait() == 0) - throw SystemError("Failed to wait for task"); + if (i->task.wait() == 0) + throw SystemError("Failed to wait for task"); - json_t *json_rentity; - json_t *json_entity = ngsi_build_entity(n, nullptr, 0, 0); + json_t *json_rentity; + json_t *json_entity = ngsi_build_entity(n, nullptr, 0, 0); - ret = ngsi_request_context_query(i->in.curl, i->endpoint, json_entity, &json_rentity, n->logger); - if (ret) - goto out; + ret = ngsi_request_context_query(i->in.curl, i->endpoint, json_entity, + &json_rentity, n->logger); + if (ret) + goto out; - ret = ngsi_parse_entity(n, json_rentity, smps, cnt); - if (ret) - goto out2; + ret = ngsi_parse_entity(n, json_rentity, smps, cnt); + if (ret) + goto out2; -out2: json_decref(json_rentity); -out: json_decref(json_entity); +out2: + json_decref(json_rentity); +out: + json_decref(json_entity); - return ret; + return ret; } -int villas::node::ngsi_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *i = n->getData(); - int ret; +int villas::node::ngsi_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *i = n->getData(); + int ret; - json_t *json_entity = ngsi_build_entity(n, smps, cnt, NGSI_ENTITY_ATTRIBUTES_OUT | NGSI_ENTITY_VALUES); + json_t *json_entity = ngsi_build_entity( + n, smps, cnt, NGSI_ENTITY_ATTRIBUTES_OUT | NGSI_ENTITY_VALUES); - ret = ngsi_request_context_update(i->out.curl, i->endpoint, "UPDATE", json_entity, n->logger); + ret = ngsi_request_context_update(i->out.curl, i->endpoint, "UPDATE", + json_entity, n->logger); - json_decref(json_entity); + json_decref(json_entity); - return ret ? 0 : cnt; + return ret ? 0 : cnt; } -int villas::node::ngsi_poll_fds(NodeCompat *n, int fds[]) -{ - auto *i = n->getData(); +int villas::node::ngsi_poll_fds(NodeCompat *n, int fds[]) { + auto *i = n->getData(); - fds[0] = i->task.getFD(); + fds[0] = i->task.getFD(); - return 1; + return 1; } -int villas::node::ngsi_init(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::ngsi_init(NodeCompat *n) { + int ret; + auto *i = n->getData(); - new (&i->task) Task(CLOCK_REALTIME); + new (&i->task) Task(CLOCK_REALTIME); - ret = list_init(&i->in.signals); - if (ret) - return ret; + ret = list_init(&i->in.signals); + if (ret) + return ret; - ret = list_init(&i->out.signals); - if (ret) - return ret; + ret = list_init(&i->out.signals); + if (ret) + return ret; - // Default values - i->access_token = nullptr; // disabled by default - i->ssl_verify = 1; // verify by default - i->timeout = 1; // default value - i->rate = 1; // default value + // Default values + i->access_token = nullptr; // disabled by default + i->ssl_verify = 1; // verify by default + i->timeout = 1; // default value + i->rate = 1; // default value - return 0; + return 0; } -int villas::node::ngsi_destroy(NodeCompat *n) -{ - int ret; - auto *i = n->getData(); +int villas::node::ngsi_destroy(NodeCompat *n) { + int ret; + auto *i = n->getData(); - for (size_t j = 0; j < list_length(&i->in.signals); j++) { - auto *attr = (NgsiAttribute *) list_at(&i->in.signals, j); + for (size_t j = 0; j < list_length(&i->in.signals); j++) { + auto *attr = (NgsiAttribute *)list_at(&i->in.signals, j); - delete attr; - } + delete attr; + } - for (size_t j = 0; j < list_length(&i->out.signals); j++) { - auto *attr = (NgsiAttribute *) list_at(&i->out.signals, j); + for (size_t j = 0; j < list_length(&i->out.signals); j++) { + auto *attr = (NgsiAttribute *)list_at(&i->out.signals, j); - delete attr; - } + delete attr; + } - ret = list_destroy(&i->in.signals); - if (ret) - return ret; + ret = list_destroy(&i->in.signals); + if (ret) + return ret; - ret = list_destroy(&i->out.signals); - if (ret) - return ret; + ret = list_destroy(&i->out.signals); + if (ret) + return ret; - i->task.~Task(); + i->task.~Task(); - return 0; + return 0; } -int villas::node::ngsi_reverse(NodeCompat *n) -{ - auto *i = n->getData(); +int villas::node::ngsi_reverse(NodeCompat *n) { + auto *i = n->getData(); - n->swapSignals(); - SWAP(i->in.signals, i->out.signals); + n->swapSignals(); + SWAP(i->in.signals, i->out.signals); - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "ngsi"; - p.description = "OMA Next Generation Services Interface 10 (libcurl, libjansson)"; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "ngsi"; + p.description = + "OMA Next Generation Services Interface 10 (libcurl, libjansson)"; #ifdef NGSI_VECTORS - p.vectorize = 0, // unlimited + p.vectorize = 0, // unlimited #else - p.vectorize = 1, + p.vectorize = 1, #endif - p.size = sizeof(struct ngsi); - p.type.start = ngsi_type_start; - p.type.stop = ngsi_type_stop; - p.init = ngsi_init; - p.destroy = ngsi_destroy; - p.parse = ngsi_parse; - p.print = ngsi_print; - p.start = ngsi_start; - p.stop = ngsi_stop; - p.read = ngsi_read; - p.write = ngsi_write; - p.poll_fds = ngsi_poll_fds; - p.reverse = ngsi_reverse; + p.size = sizeof(struct ngsi); + p.type.start = ngsi_type_start; + p.type.stop = ngsi_type_stop; + p.init = ngsi_init; + p.destroy = ngsi_destroy; + p.parse = ngsi_parse; + p.print = ngsi_print; + p.start = ngsi_start; + p.stop = ngsi_stop; + p.read = ngsi_read; + p.write = ngsi_write; + p.poll_fds = ngsi_poll_fds; + p.reverse = ngsi_reverse; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/opal.cpp b/lib/nodes/opal.cpp index 4525ff368..d0d224ce4 100644 --- a/lib/nodes/opal.cpp +++ b/lib/nodes/opal.cpp @@ -7,44 +7,43 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include -#include #include +#include #include +#include #include #include #include -#include extern "C" { - /* Define RTLAB before including OpalPrint.h for messages to be sent +/* Define RTLAB before including OpalPrint.h for messages to be sent * to the OpalDisplay. Otherwise stdout will be used. */ - #define RTLAB - #include - #include - #include +#define RTLAB +#include +#include +#include } // Private static storage -static -std::string asyncShmemName; // Shared Memory identifiers and size, provided via argv. -static -std::string printShmemName; // Shared Memory identifiers and size, provided via argv. -static -size_t asyncShmemSize; // Shared Memory identifiers and size, provided via argv. +static std::string + asyncShmemName; // Shared Memory identifiers and size, provided via argv. +static std::string + printShmemName; // Shared Memory identifiers and size, provided via argv. +static size_t + asyncShmemSize; // Shared Memory identifiers and size, provided via argv. -static -std::vector sendIDs, recvIDs; // A dynamically allocated array of SendIDs. +static std::vector sendIDs, + recvIDs; // A dynamically allocated array of SendIDs. -static -Opal_GenAsyncParam_Ctrl params; // String and Float parameters, provided by the OPAL AsyncProcess block. +static Opal_GenAsyncParam_Ctrl + params; // String and Float parameters, provided by the OPAL AsyncProcess block. -static -pthread_mutex_t lock; // Big Global Lock for libOpalAsync API +static pthread_mutex_t lock; // Big Global Lock for libOpalAsync API using namespace villas; using namespace villas::utils; @@ -53,321 +52,300 @@ using namespace villas::utils; * and undefined by GCC. We replace them by GCC variants here. */ extern "C" { - int __xstat(int ver, const char * path, struct stat * stat_buf) - { - return stat(path, stat_buf); - } - - int backtrace(void **buffer, int size) - { - return 0; - } - - char **backtrace_symbols(void *const *buffer, int size) - { - return nullptr; - } - - void backtrace_symbols_fd(void *const *buffer, int size, int fd) - { - } - - void * _intel_fast_memset(void *b, int c, size_t len) - { - return memset(b, c, len); - } - - void * _intel_fast_memcpy(void *dst, const void *src, size_t n) - { - return memcpy(dst, src, n); - } - - int _intel_fast_memcmp(const void *s1, const void *s2, size_t n) - { - return memcmp(s1, s2, n); - } - - void * _intel_fast_memmove(void *s1, const void *s2, size_t n) - { - return memmove(s1, s2, n); - } +int __xstat(int ver, const char *path, struct stat *stat_buf) { + return stat(path, stat_buf); } -static -int opal_register_region(int argc, char *argv[]) -{ - if (argc != 4) - return -1; +int backtrace(void **buffer, int size) { return 0; } - asyncShmemName = argv[1]; - asyncShmemSize = atoi(argv[2]); - printShmemName = argv[3]; +char **backtrace_symbols(void *const *buffer, int size) { return nullptr; } - return 0; +void backtrace_symbols_fd(void *const *buffer, int size, int fd) {} + +void *_intel_fast_memset(void *b, int c, size_t len) { + return memset(b, c, len); } -int villas::node::opal_type_start(villas::node::SuperNode *sn) -{ - int err, noRecvIcons, noSendIcons; - - pthread_mutex_init(&lock, nullptr); - - // Enable the OpalPrint function. This prints to the OpalDisplay. - err = OpalSystemCtrl_Register((char *) printShmemName.c_str()); - if (err != EOK) - throw RuntimeError("OpalPrint() access not available ({})", err); - - // Open Share Memory created by the model. - err = OpalOpenAsyncMem(asyncShmemSize, asyncShmemName.c_str()); - if (err != EOK) - throw RuntimeError("Model shared memory not available ({})", err); - - err = OpalGetAsyncCtrlParameters(¶ms, sizeof(Opal_GenAsyncParam_Ctrl)); - if (err != EOK) - throw RuntimeError("Could not get OPAL controller parameters ({})", err); - - // Get list of Send and RecvIDs - err = OpalGetNbAsyncSendIcon(&noSendIcons); - if (err != EOK) - throw RuntimeError("Failed to get number of send blocks ({})", err); - err = OpalGetNbAsyncRecvIcon(&noRecvIcons); - if (err != EOK) - throw RuntimeError("Failed to get number of recv blocks ({})", err); - - sendIDs.resize(noSendIcons); - recvIDs.resize(noRecvIcons); - - err = OpalGetAsyncSendIDList(sendIDs.data(), noSendIcons * sizeof(int)); - if (err != EOK) - throw RuntimeError("Failed to get list of send ids ({})", err); - err = OpalGetAsyncRecvIDList(recvIDs.data(), noRecvIcons * sizeof(int)); - if (err != EOK) - throw RuntimeError("Failed to get list of recv ids ({})", err); - - auto logger = logging.get("node:opal"); - logger->info("Started as OPAL Asynchronous process"); - logger->info("This is VILLASnode %s (built on %s, %s)", - PROJECT_BUILD_ID, __DATE__, __TIME__); - - opal_print_global(); - - return 0; +void *_intel_fast_memcpy(void *dst, const void *src, size_t n) { + return memcpy(dst, src, n); } -int villas::node::opal_type_stop() -{ - int err; - - err = OpalCloseAsyncMem(asyncShmemSize, asyncShmemName.c_str()); - if (err != EOK) - throw RuntimeError("Failed to close shared memory area ({})", err); - - auto logger = logging.get("node:opal"); - logger->debug("Closing OPAL shared memory mapping"); - - err = OpalSystemCtrl_UnRegister((char *) printShmemName.c_str()); - if (err != EOK) - throw RuntimeError("Failed to close shared memory for system control ({})", err); - - pthread_mutex_destroy(&lock); - - return 0; +int _intel_fast_memcmp(const void *s1, const void *s2, size_t n) { + return memcmp(s1, s2, n); } -static -int opal_print_global() -{ - auto logger = logging.get("node:opal"); - logger->debug("Controller ID: {}", params.controllerID); - - std::stringstream sss, rss; - - for (auto i : sendIDs) - sss << i << " "; - for (auto i : recvIDs) - rss << i << " "; - - logger->debug("Send Blocks: {}", sss.str()); - logger->debug("Receive Blocks: {}", rss.str()); - - logger->debug("Control Block Parameters:"); - for (int i = 0; i < GENASYNC_NB_FLOAT_PARAM; i++) - logger->debug("FloatParam[{}] = {}", i, (double) params.FloatParam[i]); - for (int i = 0; i < GENASYNC_NB_STRING_PARAM; i++) - logger->debug("StringParam[{}] = {}", i, params.StringParam[i]); - - return 0; +void *_intel_fast_memmove(void *s1, const void *s2, size_t n) { + return memmove(s1, s2, n); +} } -int villas::node::opal_parse(NodeCompat *n, json_t *json) -{ - auto *o = n->getData(); +static int opal_register_region(int argc, char *argv[]) { + if (argc != 4) + return -1; - int ret; - json_error_t err; + asyncShmemName = argv[1]; + asyncShmemSize = atoi(argv[2]); + printShmemName = argv[3]; - ret = json_unpack_ex(json, &err, 0, "{ s: i, s: i, s: b }", - "send_id", &o->sendID, - "recv_id", &o->sendID, - "reply", &o->reply - ); - if (ret) - throw ConfigError(json, err, "node-config-node-opal"); - - return 0; + return 0; } -char * villas::node::opal_print(NodeCompat *n) -{ - auto *o = n->getData(); +int villas::node::opal_type_start(villas::node::SuperNode *sn) { + int err, noRecvIcons, noSendIcons; - // TODO: Print send_params, recv_params + pthread_mutex_init(&lock, nullptr); - return strf("sendID=%u, recvID=%u, reply=%u", - o->sendID, o->recvID, o->reply); + // Enable the OpalPrint function. This prints to the OpalDisplay. + err = OpalSystemCtrl_Register((char *)printShmemName.c_str()); + if (err != EOK) + throw RuntimeError("OpalPrint() access not available ({})", err); + + // Open Share Memory created by the model. + err = OpalOpenAsyncMem(asyncShmemSize, asyncShmemName.c_str()); + if (err != EOK) + throw RuntimeError("Model shared memory not available ({})", err); + + err = OpalGetAsyncCtrlParameters(¶ms, sizeof(Opal_GenAsyncParam_Ctrl)); + if (err != EOK) + throw RuntimeError("Could not get OPAL controller parameters ({})", err); + + // Get list of Send and RecvIDs + err = OpalGetNbAsyncSendIcon(&noSendIcons); + if (err != EOK) + throw RuntimeError("Failed to get number of send blocks ({})", err); + err = OpalGetNbAsyncRecvIcon(&noRecvIcons); + if (err != EOK) + throw RuntimeError("Failed to get number of recv blocks ({})", err); + + sendIDs.resize(noSendIcons); + recvIDs.resize(noRecvIcons); + + err = OpalGetAsyncSendIDList(sendIDs.data(), noSendIcons * sizeof(int)); + if (err != EOK) + throw RuntimeError("Failed to get list of send ids ({})", err); + err = OpalGetAsyncRecvIDList(recvIDs.data(), noRecvIcons * sizeof(int)); + if (err != EOK) + throw RuntimeError("Failed to get list of recv ids ({})", err); + + auto logger = logging.get("node:opal"); + logger->info("Started as OPAL Asynchronous process"); + logger->info("This is VILLASnode %s (built on %s, %s)", PROJECT_BUILD_ID, + __DATE__, __TIME__); + + opal_print_global(); + + return 0; } -int villas::node::opal_start(NodeCompat *n) -{ - auto *o = n->getData(); +int villas::node::opal_type_stop() { + int err; - // Search for valid send and recv ids - int sfound = 0, rfound = 0; - for (auto i : sendIDs) - sfound += i == o->sendID; - for (auto i : recvIDs) - rfound += i == o->sendID; + err = OpalCloseAsyncMem(asyncShmemSize, asyncShmemName.c_str()); + if (err != EOK) + throw RuntimeError("Failed to close shared memory area ({})", err); - if (!sfound) - throw RuntimeError("Invalid send_id '{}'", o->sendID); - if (!rfound) - throw RuntimeError("Invalid recv_id '{}'", o->recvID); + auto logger = logging.get("node:opal"); + logger->debug("Closing OPAL shared memory mapping"); - // Get some more informations and paramters from OPAL-RT - OpalGetAsyncSendIconMode(&o->mode, o->sendID); - OpalGetAsyncSendParameters(&o->sendParams, sizeof(Opal_SendAsyncParam), o->sendID); - OpalGetAsyncRecvParameters(&o->recvParams, sizeof(Opal_RecvAsyncParam), o->recvID); + err = OpalSystemCtrl_UnRegister((char *)printShmemName.c_str()); + if (err != EOK) + throw RuntimeError("Failed to close shared memory for system control ({})", + err); - o->sequenceNo = 0; + pthread_mutex_destroy(&lock); - return 0; + return 0; } -int villas::node::opal_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *o = n->getData(); +static int opal_print_global() { + auto logger = logging.get("node:opal"); + logger->debug("Controller ID: {}", params.controllerID); - int state, ret, len; - unsigned id; + std::stringstream sss, rss; - struct Sample *s = smps[0]; + for (auto i : sendIDs) + sss << i << " "; + for (auto i : recvIDs) + rss << i << " "; - double data[s->capacity]; + logger->debug("Send Blocks: {}", sss.str()); + logger->debug("Receive Blocks: {}", rss.str()); - if (cnt != 1) - throw RuntimeError("The OPAL-RT node type does not support combining!"); + logger->debug("Control Block Parameters:"); + for (int i = 0; i < GENASYNC_NB_FLOAT_PARAM; i++) + logger->debug("FloatParam[{}] = {}", i, (double)params.FloatParam[i]); + for (int i = 0; i < GENASYNC_NB_STRING_PARAM; i++) + logger->debug("StringParam[{}] = {}", i, params.StringParam[i]); - // This call unblocks when the 'Data Ready' line of a send icon is asserted. - do { - ret = OpalWaitForAsyncSendRequest(&id); - if (ret != EOK) { - state = OpalGetAsyncModelState(); - if ((state == STATE_RESET) || (state == STATE_STOP)) - throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); + return 0; +} - return -1; // TODO: correct return value - } - } while (id != o->sendID); +int villas::node::opal_parse(NodeCompat *n, json_t *json) { + auto *o = n->getData(); - // No errors encountered yet - OpalSetAsyncSendIconError(0, o->sendID); + int ret; + json_error_t err; - // Get the size of the data being sent by the unblocking SendID - OpalGetAsyncSendIconDataLength(&len, o->sendID); - if ((unsigned) len > s->capacity * sizeof(s->data[0])) { - n->logger->warn("Ignoring the last {} of {} values for OPAL (send_id={}).", - len / sizeof(double) - s->capacity, len / sizeof(double), o->sendID); + ret = json_unpack_ex(json, &err, 0, "{ s: i, s: i, s: b }", "send_id", + &o->sendID, "recv_id", &o->sendID, "reply", &o->reply); + if (ret) + throw ConfigError(json, err, "node-config-node-opal"); - len = sizeof(data); - } + return 0; +} - // Read data from the model - OpalGetAsyncSendIconData(data, len, o->sendID); +char *villas::node::opal_print(NodeCompat *n) { + auto *o = n->getData(); - s->sequence = htons(o->sequenceNo++); - s->length = (unsigned) len / sizeof(double); + // TODO: Print send_params, recv_params - for (unsigned i = 0; i < s->length; i++) - s->data[i].f = (float) data[i]; // OPAL provides double precission + return strf("sendID=%u, recvID=%u, reply=%u", o->sendID, o->recvID, o->reply); +} - /* This next call allows the execution of the "asynchronous" process +int villas::node::opal_start(NodeCompat *n) { + auto *o = n->getData(); + + // Search for valid send and recv ids + int sfound = 0, rfound = 0; + for (auto i : sendIDs) + sfound += i == o->sendID; + for (auto i : recvIDs) + rfound += i == o->sendID; + + if (!sfound) + throw RuntimeError("Invalid send_id '{}'", o->sendID); + if (!rfound) + throw RuntimeError("Invalid recv_id '{}'", o->recvID); + + // Get some more informations and paramters from OPAL-RT + OpalGetAsyncSendIconMode(&o->mode, o->sendID); + OpalGetAsyncSendParameters(&o->sendParams, sizeof(Opal_SendAsyncParam), + o->sendID); + OpalGetAsyncRecvParameters(&o->recvParams, sizeof(Opal_RecvAsyncParam), + o->recvID); + + o->sequenceNo = 0; + + return 0; +} + +int villas::node::opal_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *o = n->getData(); + + int state, ret, len; + unsigned id; + + struct Sample *s = smps[0]; + + double data[s->capacity]; + + if (cnt != 1) + throw RuntimeError("The OPAL-RT node type does not support combining!"); + + // This call unblocks when the 'Data Ready' line of a send icon is asserted. + do { + ret = OpalWaitForAsyncSendRequest(&id); + if (ret != EOK) { + state = OpalGetAsyncModelState(); + if ((state == STATE_RESET) || (state == STATE_STOP)) + throw RuntimeError( + "OpalGetAsyncModelState(): Model stopped or resetted!"); + + return -1; // TODO: correct return value + } + } while (id != o->sendID); + + // No errors encountered yet + OpalSetAsyncSendIconError(0, o->sendID); + + // Get the size of the data being sent by the unblocking SendID + OpalGetAsyncSendIconDataLength(&len, o->sendID); + if ((unsigned)len > s->capacity * sizeof(s->data[0])) { + n->logger->warn("Ignoring the last {} of {} values for OPAL (send_id={}).", + len / sizeof(double) - s->capacity, len / sizeof(double), + o->sendID); + + len = sizeof(data); + } + + // Read data from the model + OpalGetAsyncSendIconData(data, len, o->sendID); + + s->sequence = htons(o->sequenceNo++); + s->length = (unsigned)len / sizeof(double); + + for (unsigned i = 0; i < s->length; i++) + s->data[i].f = (float)data[i]; // OPAL provides double precission + + /* This next call allows the execution of the "asynchronous" process * to actually be synchronous with the model. To achieve this, you * should set the "Sending Mode" in the Async_Send block to * NEED_REPLY_BEFORE_NEXT_SEND or NEED_REPLY_NOW. This will force * the model to wait for this process to call this * OpalAsyncSendRequestDone function before continuing. */ - if (o->reply) - OpalAsyncSendRequestDone(o->sendID); + if (o->reply) + OpalAsyncSendRequestDone(o->sendID); - /* Before continuing, we make sure that the real-time model + /* Before continuing, we make sure that the real-time model * has not been stopped. If it has, we quit. */ - state = OpalGetAsyncModelState(); - if ((state == STATE_RESET) || (state == STATE_STOP)) - throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); + state = OpalGetAsyncModelState(); + if ((state == STATE_RESET) || (state == STATE_STOP)) + throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); - return 1; + return 1; } -int villas::node::opal_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *o = n->getData(); +int villas::node::opal_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *o = n->getData(); - struct Sample *s = smps[0]; + struct Sample *s = smps[0]; - int state; - int len; - double data[s->length]; + int state; + int len; + double data[s->length]; - if (cnt != 1) - throw RuntimeError("The OPAL-RT node type does not support combining!"); + if (cnt != 1) + throw RuntimeError("The OPAL-RT node type does not support combining!"); - state = OpalGetAsyncModelState(); - if ((state == STATE_RESET) || (state == STATE_STOP)) - throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); + state = OpalGetAsyncModelState(); + if ((state == STATE_RESET) || (state == STATE_STOP)) + throw RuntimeError("OpalGetAsyncModelState(): Model stopped or resetted!"); - OpalSetAsyncRecvIconStatus(s->sequence, o->recvID); // Set the Status to the message ID - OpalSetAsyncRecvIconError(0, o->recvID); // Set the Error to 0 + OpalSetAsyncRecvIconStatus(s->sequence, + o->recvID); // Set the Status to the message ID + OpalSetAsyncRecvIconError(0, o->recvID); // Set the Error to 0 - // Get the number of signals to send back to the model - OpalGetAsyncRecvIconDataLength(&len, o->recvID); - if (len > (int) sizeof(data)) - n->logger->warn("Node expecting more signals ({}) than values in message ({})", len / sizeof(double), s->length); + // Get the number of signals to send back to the model + OpalGetAsyncRecvIconDataLength(&len, o->recvID); + if (len > (int)sizeof(data)) + n->logger->warn( + "Node expecting more signals ({}) than values in message ({})", + len / sizeof(double), s->length); - for (unsigned i = 0; i < s->length; i++) - data[i] = (double) s->data[i].f; // OPAL expects double precission + for (unsigned i = 0; i < s->length; i++) + data[i] = (double)s->data[i].f; // OPAL expects double precission - OpalSetAsyncRecvIconData(data, s->length * sizeof(double), o->recvID); + OpalSetAsyncRecvIconData(data, s->length * sizeof(double), o->recvID); - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "opal"; - p.description = "run as OPAL Asynchronous Process (libOpalAsyncApi)"; - p.vectorize = 1; - p.size = sizeof(struct opal); - p.type.start = opal_type_start; - p.type.stop = opal_type_stop; - p.parse = opal_parse; - p.print = opal_print; - p.start = opal_start; - p.read = opal_read; - p.write = opal_write; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "opal"; + p.description = "run as OPAL Asynchronous Process (libOpalAsyncApi)"; + p.vectorize = 1; + p.size = sizeof(struct opal); + p.type.start = opal_type_start; + p.type.stop = opal_type_stop; + p.parse = opal_parse; + p.print = opal_print; + p.start = opal_start; + p.read = opal_read; + p.write = opal_write; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/redis.cpp b/lib/nodes/redis.cpp index 2a07d1dfd..bae08e5e0 100644 --- a/lib/nodes/redis.cpp +++ b/lib/nodes/redis.cpp @@ -5,678 +5,640 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include #include -#include -#include -#include -#include #include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; // Forward declartions -static -NodeCompatType p; -static -void redis_on_message(NodeCompat *n, const std::string &channel, const std::string &msg); +static NodeCompatType p; +static void redis_on_message(NodeCompat *n, const std::string &channel, + const std::string &msg); -static -std::unordered_map connections; +static std::unordered_map + connections; -RedisConnection::RedisConnection(const sw::redis::ConnectionOptions &opts) : - context(opts), - subscriber(context.subscriber()), - logger(logging.get("nodes:redis")) -{ - // Enable keyspace notifications - context.command("config", "set", "notify-keyspace-events", "K$h"); +RedisConnection::RedisConnection(const sw::redis::ConnectionOptions &opts) + : context(opts), subscriber(context.subscriber()), + logger(logging.get("nodes:redis")) { + // Enable keyspace notifications + context.command("config", "set", "notify-keyspace-events", "K$h"); - subscriber.on_message([this](const std::string &channel, const std::string &msg) { - onMessage(channel, msg); - }); + subscriber.on_message( + [this](const std::string &channel, const std::string &msg) { + onMessage(channel, msg); + }); - logger->info("New connection: {}", opts); + logger->info("New connection: {}", opts); - state = State::INITIALIZED; + state = State::INITIALIZED; } -RedisConnection * RedisConnection::get(const sw::redis::ConnectionOptions &opts) -{ - RedisConnection *conn; +RedisConnection * +RedisConnection::get(const sw::redis::ConnectionOptions &opts) { + RedisConnection *conn; - auto it = connections.find(opts); - if (it != connections.end()) - conn = it->second; - else { - try { - conn = new RedisConnection(opts); - } catch (sw::redis::IoError &e) { - throw RuntimeError(e.what()); - } + auto it = connections.find(opts); + if (it != connections.end()) + conn = it->second; + else { + try { + conn = new RedisConnection(opts); + } catch (sw::redis::IoError &e) { + throw RuntimeError(e.what()); + } - connections[opts] = conn; - } + connections[opts] = conn; + } - return conn; + return conn; } -void RedisConnection::onMessage(const std::string &channel, const std::string &msg) -{ - auto itp = subscriberMap.equal_range(channel); - for (auto it = itp.first; it != itp.second; ++it) { - NodeCompat *n = it->second; +void RedisConnection::onMessage(const std::string &channel, + const std::string &msg) { + auto itp = subscriberMap.equal_range(channel); + for (auto it = itp.first; it != itp.second; ++it) { + NodeCompat *n = it->second; - redis_on_message(n, channel, msg); - } + redis_on_message(n, channel, msg); + } } -void RedisConnection::subscribe(NodeCompat *n, const std::string &channel) -{ - subscriber.subscribe(channel); +void RedisConnection::subscribe(NodeCompat *n, const std::string &channel) { + subscriber.subscribe(channel); - subscriberMap.emplace(channel, n); + subscriberMap.emplace(channel, n); } -void RedisConnection::unsubscribe(NodeCompat *n, const std::string &channel) -{ - auto itp = subscriberMap.equal_range(channel); - for (auto it = itp.first; it != itp.second; ++it) { - if (it->second == n) - subscriberMap.erase(it); - } +void RedisConnection::unsubscribe(NodeCompat *n, const std::string &channel) { + auto itp = subscriberMap.equal_range(channel); + for (auto it = itp.first; it != itp.second; ++it) { + if (it->second == n) + subscriberMap.erase(it); + } - if (subscriberMap.count(channel) == 0) - subscriber.subscribe(channel); + if (subscriberMap.count(channel) == 0) + subscriber.subscribe(channel); } -void RedisConnection::start() -{ - if (state == State::RUNNING) - return; // Already running +void RedisConnection::start() { + if (state == State::RUNNING) + return; // Already running - state = State::RUNNING; + state = State::RUNNING; - thread = std::thread(&RedisConnection::loop, this); + thread = std::thread(&RedisConnection::loop, this); } -void RedisConnection::stop() -{ - state = State::STOPPING; +void RedisConnection::stop() { + state = State::STOPPING; - thread.join(); + thread.join(); - state = State::INITIALIZED; + state = State::INITIALIZED; } -void RedisConnection::loop() -{ - while (state == State::RUNNING) { - try { - subscriber.consume(); - } - catch (const sw::redis::TimeoutError &e) { - logger->debug("Timeout."); - continue; - } - catch (const sw::redis::ReplyError &e) { - logger->error("Error: {}", e.what()); - continue; - } - catch (const sw::redis::Error &e) { - logger->error("Error: {}. Recreating subscriber", e.what()); +void RedisConnection::loop() { + while (state == State::RUNNING) { + try { + subscriber.consume(); + } catch (const sw::redis::TimeoutError &e) { + logger->debug("Timeout."); + continue; + } catch (const sw::redis::ReplyError &e) { + logger->error("Error: {}", e.what()); + continue; + } catch (const sw::redis::Error &e) { + logger->error("Error: {}. Recreating subscriber", e.what()); - // Create a new subscriber - subscriber = context.subscriber(); - } - } + // Create a new subscriber + subscriber = context.subscriber(); + } + } } -static -int redis_get(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *r = n->getData(); +static int redis_get(NodeCompat *n, struct Sample *const smps[], unsigned cnt) { + int ret; + auto *r = n->getData(); - switch (r->mode) { - case RedisMode::KEY: { - auto value = r->conn->context.get(r->key); - if (value) { - size_t rbytes, bytes = value->size(); - ret = r->formatter->sscan(value->c_str(), bytes, &rbytes, smps, cnt); + switch (r->mode) { + case RedisMode::KEY: { + auto value = r->conn->context.get(r->key); + if (value) { + size_t rbytes, bytes = value->size(); + ret = r->formatter->sscan(value->c_str(), bytes, &rbytes, smps, cnt); - if (rbytes != bytes) - return -1; + if (rbytes != bytes) + return -1; - return ret; - } - else - return -1; - } + return ret; + } else + return -1; + } - case RedisMode::HASH: { - struct Sample *smp = smps[0]; + case RedisMode::HASH: { + struct Sample *smp = smps[0]; - unsigned j = 0; - for (auto sig : *n->getInputSignals(false)) { - auto *data = &smp->data[j++]; + unsigned j = 0; + for (auto sig : *n->getInputSignals(false)) { + auto *data = &smp->data[j++]; - *data = sig->init; - } + *data = sig->init; + } - std::unordered_map kvs; - r->conn->context.hgetall(r->key, std::inserter(kvs, kvs.begin())); + std::unordered_map kvs; + r->conn->context.hgetall(r->key, std::inserter(kvs, kvs.begin())); - int max_idx = -1; - for (auto &it : kvs) { - auto &name = it.first; - auto &value = it.second; + int max_idx = -1; + for (auto &it : kvs) { + auto &name = it.first; + auto &value = it.second; - auto sig = n->getInputSignals(false)->getByName(name); - if (!sig) - continue; + auto sig = n->getInputSignals(false)->getByName(name); + if (!sig) + continue; - auto idx = n->getInputSignals(false)->getIndexByName(name); - if (idx > max_idx) - max_idx = idx; + auto idx = n->getInputSignals(false)->getIndexByName(name); + if (idx > max_idx) + max_idx = idx; - char *end; - ret = smp->data[idx].parseString(sig->type, value.c_str(), &end); - if (ret < 0) - continue; - } + char *end; + ret = smp->data[idx].parseString(sig->type, value.c_str(), &end); + if (ret < 0) + continue; + } - smp->flags = 0; - smp->length = max_idx + 1; + smp->flags = 0; + smp->length = max_idx + 1; - if (smp->length > 0) - smp->flags |= (int) SampleFlags::HAS_DATA; + if (smp->length > 0) + smp->flags |= (int)SampleFlags::HAS_DATA; - return 1; - } + return 1; + } - default: - return -1; - } + default: + return -1; + } } -static -void redis_on_message(NodeCompat *n, const std::string &channel, const std::string &msg) -{ - auto *r = n->getData(); +static void redis_on_message(NodeCompat *n, const std::string &channel, + const std::string &msg) { + auto *r = n->getData(); - n->logger->debug("Message: {}: {}", channel, msg); + n->logger->debug("Message: {}: {}", channel, msg); - int alloc, scanned, pushed = 0; - unsigned cnt = n->in.vectorize; - struct Sample *smps[cnt]; + int alloc, scanned, pushed = 0; + unsigned cnt = n->in.vectorize; + struct Sample *smps[cnt]; - alloc = sample_alloc_many(&r->pool, smps, cnt); - if (alloc < 0) { - n->logger->error("Failed to allocate samples"); - return; - } - else if ((unsigned) alloc < cnt) - n->logger->warn("Pool underrun"); + alloc = sample_alloc_many(&r->pool, smps, cnt); + if (alloc < 0) { + n->logger->error("Failed to allocate samples"); + return; + } else if ((unsigned)alloc < cnt) + n->logger->warn("Pool underrun"); - switch (r->mode) { - case RedisMode::CHANNEL: { - size_t rbytes; - scanned = r->formatter->sscan(msg.c_str(), msg.size(), &rbytes, smps, alloc); - break; - } + switch (r->mode) { + case RedisMode::CHANNEL: { + size_t rbytes; + scanned = + r->formatter->sscan(msg.c_str(), msg.size(), &rbytes, smps, alloc); + break; + } - case RedisMode::HASH: - case RedisMode::KEY: - scanned = redis_get(n, smps, cnt); - break; + case RedisMode::HASH: + case RedisMode::KEY: + scanned = redis_get(n, smps, cnt); + break; - default: - pushed = 0; - goto out; - } + default: + pushed = 0; + goto out; + } - if (scanned < 0) { - n->logger->error("Failed to decode samples"); - goto out; - } + if (scanned < 0) { + n->logger->error("Failed to decode samples"); + goto out; + } - pushed = queue_signalled_push_many(&r->queue, (void **) smps, scanned); - if (pushed < 0) { - n->logger->error("Failed to enqueue"); - pushed = 0; - } - else if (pushed != scanned) - n->logger->warn("Queue underrun"); + pushed = queue_signalled_push_many(&r->queue, (void **)smps, scanned); + if (pushed < 0) { + n->logger->error("Failed to enqueue"); + pushed = 0; + } else if (pushed != scanned) + n->logger->warn("Queue underrun"); -out: sample_decref_many(smps + pushed, alloc - pushed); +out: + sample_decref_many(smps + pushed, alloc - pushed); } -int villas::node::redis_init(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::redis_init(NodeCompat *n) { + auto *r = n->getData(); - r->mode = RedisMode::KEY; - r->formatter = nullptr; - r->notify = true; - r->rate = 1.0; + r->mode = RedisMode::KEY; + r->formatter = nullptr; + r->notify = true; + r->rate = 1.0; - new (&r->options) sw::redis::ConnectionOptions; - new (&r->task) Task(CLOCK_REALTIME); - new (&r->key) std::string(); + new (&r->options) sw::redis::ConnectionOptions; + new (&r->task) Task(CLOCK_REALTIME); + new (&r->key) std::string(); - /* We need a timeout in order for RedisConnection::loop() to properly + /* We need a timeout in order for RedisConnection::loop() to properly * terminate after the node is stopped */ - r->options.socket_timeout = std::chrono::milliseconds(500); + r->options.socket_timeout = std::chrono::milliseconds(500); - return 0; + return 0; } -int villas::node::redis_destroy(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_destroy(NodeCompat *n) { + int ret; + auto *r = n->getData(); - if (r->formatter) - delete r->formatter; + if (r->formatter) + delete r->formatter; - using string = std::string; - using redis_co = sw::redis::ConnectionOptions; + using string = std::string; + using redis_co = sw::redis::ConnectionOptions; - r->options.~redis_co(); - r->key.~string(); - r->task.~Task(); + r->options.~redis_co(); + r->key.~string(); + r->task.~Task(); - ret = queue_signalled_destroy(&r->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&r->queue); + if (ret) + return ret; - ret = pool_destroy(&r->pool); - if (ret) - return ret; + ret = pool_destroy(&r->pool); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::redis_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_parse(NodeCompat *n, json_t *json) { + int ret; + auto *r = n->getData(); - json_error_t err; - json_t *json_ssl = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_ssl = nullptr; + json_t *json_format = nullptr; - const char *host = nullptr; - const char *path = nullptr; - const char *user = nullptr; - const char *password = nullptr; - const char *mode = nullptr; - const char *uri = nullptr; - const char *key = nullptr; - const char *channel = nullptr; - int keepalive = -1; - int db = -1; - int notify = -1; + const char *host = nullptr; + const char *path = nullptr; + const char *user = nullptr; + const char *password = nullptr; + const char *mode = nullptr; + const char *uri = nullptr; + const char *key = nullptr; + const char *channel = nullptr; + int keepalive = -1; + int db = -1; + int notify = -1; - double connect_timeout = -1; - double socket_timeout = -1; + double connect_timeout = -1; + double socket_timeout = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: s, s?: s, s?: i, s?: s, s?: s, s?: s, s?: i, s?: { s?: F, s?: F }, s?: o, s?: b, s?: s, s?: s, s?: s, s?: b, s?: F }", - "format", &json_format, - "uri", &uri, - "host", &host, - "port", &r->options.port, - "path", &path, - "user", &user, - "password", &password, - "db", &db, - "timeout", - "connect", &connect_timeout, - "socket", &socket_timeout, - "ssl", &json_ssl, - "keepalive", &keepalive, - "mode", &mode, - "key", &key, - "channel", &channel, - "notify", ¬ify, - "rate", &r->rate - ); - if (ret) - throw ConfigError(json, err, "node-config-node-redis", "Failed to parse node configuration"); + ret = json_unpack_ex( + json, &err, 0, + "{ s?: o, s?: s, s?: s, s?: i, s?: s, s?: s, s?: s, s?: i, s?: { s?: F, " + "s?: F }, s?: o, s?: b, s?: s, s?: s, s?: s, s?: b, s?: F }", + "format", &json_format, "uri", &uri, "host", &host, "port", + &r->options.port, "path", &path, "user", &user, "password", &password, + "db", &db, "timeout", "connect", &connect_timeout, "socket", + &socket_timeout, "ssl", &json_ssl, "keepalive", &keepalive, "mode", &mode, + "key", &key, "channel", &channel, "notify", ¬ify, "rate", &r->rate); + if (ret) + throw ConfigError(json, err, "node-config-node-redis", + "Failed to parse node configuration"); - if (json_ssl) { + if (json_ssl) { #ifdef REDISPP_WITH_TLS - const char *cacert; - const char *cacertdir; - const char *cert; - const char *key; + const char *cacert; + const char *cacertdir; + const char *cert; + const char *key; - int enabled = 1; + int enabled = 1; - ret = json_unpack_ex(json_ssl, &err, 0, "{ s?: b, s?: s, s?: s, s?: s, s?: s }", - "enabled", &enabled, - "cacert", &cacert, - "cacertdir", &cacertdir, - "cert", &cert, - "key", &key - ); - if (ret) - throw ConfigError(json, err, "node-config-node-redis-ssl", "Failed to parse Redis SSL configuration"); + ret = json_unpack_ex(json_ssl, &err, 0, + "{ s?: b, s?: s, s?: s, s?: s, s?: s }", "enabled", + &enabled, "cacert", &cacert, "cacertdir", &cacertdir, + "cert", &cert, "key", &key); + if (ret) + throw ConfigError(json, err, "node-config-node-redis-ssl", + "Failed to parse Redis SSL configuration"); - r->options.tls.enabled = enabled != 0; + r->options.tls.enabled = enabled != 0; - r->options.tls.cacert = cacert; - r->options.tls.cacertdir = cacertdir; - r->options.tls.cert = cert; - r->options.tls.key = key; + r->options.tls.cacert = cacert; + r->options.tls.cacertdir = cacertdir; + r->options.tls.cert = cert; + r->options.tls.key = key; - if (host) - r->options.tls.sni = host; + if (host) + r->options.tls.sni = host; #else - throw ConfigError(json_ssl, "node-config-node-redis-ssl", "This built of the redis++ library does not support SSL"); + throw ConfigError(json_ssl, "node-config-node-redis-ssl", + "This built of the redis++ library does not support SSL"); #endif // REDISPP_WITH_TLS - } + } - // Mode - if (mode) { - if (!strcmp(mode, "key") || !strcmp(mode, "set-get")) - r->mode = RedisMode::KEY; - else if (!strcmp(mode, "hash") || !strcmp(mode, "hset-hget")) - r->mode = RedisMode::HASH; - else if (!strcmp(mode, "channel") || !strcmp(mode, "pub-sub")) - r->mode = RedisMode::CHANNEL; - else - throw ConfigError(json, "node-config-node-redis-mode", "Invalid Redis mode: {}", mode); - } + // Mode + if (mode) { + if (!strcmp(mode, "key") || !strcmp(mode, "set-get")) + r->mode = RedisMode::KEY; + else if (!strcmp(mode, "hash") || !strcmp(mode, "hset-hget")) + r->mode = RedisMode::HASH; + else if (!strcmp(mode, "channel") || !strcmp(mode, "pub-sub")) + r->mode = RedisMode::CHANNEL; + else + throw ConfigError(json, "node-config-node-redis-mode", + "Invalid Redis mode: {}", mode); + } - // Format - if (r->formatter) - delete r->formatter; - r->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("json"); - if (!r->formatter) - throw ConfigError(json_format, "node-config-node-redis-format", "Invalid format configuration"); + // Format + if (r->formatter) + delete r->formatter; + r->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("json"); + if (!r->formatter) + throw ConfigError(json_format, "node-config-node-redis-format", + "Invalid format configuration"); - if (key && r->mode == RedisMode::KEY) - r->key = key; - if (channel && r->mode == RedisMode::CHANNEL) - r->key = channel; + if (key && r->mode == RedisMode::KEY) + r->key = key; + if (channel && r->mode == RedisMode::CHANNEL) + r->key = channel; - if (notify >= 0) - r->notify = notify != 0; + if (notify >= 0) + r->notify = notify != 0; - // Connection options - if (uri) - r->options = make_redis_connection_options(uri); + // Connection options + if (uri) + r->options = make_redis_connection_options(uri); - if (db >= 0) - r->options.db = db; + if (db >= 0) + r->options.db = db; - if (user) - r->options.user = user; + if (user) + r->options.user = user; - if (password) - r->options.password = password; + if (password) + r->options.password = password; - if (host) - r->options.host = host; + if (host) + r->options.host = host; - if (path) - r->options.path = path; + if (path) + r->options.path = path; - if (keepalive >= 0) - r->options.keep_alive = keepalive != 0; + if (keepalive >= 0) + r->options.keep_alive = keepalive != 0; - if (socket_timeout > 0) - r->options.socket_timeout = std::chrono::milliseconds((int) (1000 * socket_timeout)); + if (socket_timeout > 0) + r->options.socket_timeout = + std::chrono::milliseconds((int)(1000 * socket_timeout)); - if (connect_timeout > 0) - r->options.connect_timeout = std::chrono::milliseconds((int) (1000 * connect_timeout)); + if (connect_timeout > 0) + r->options.connect_timeout = + std::chrono::milliseconds((int)(1000 * connect_timeout)); - return 0; + return 0; } -int villas::node::redis_check(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::redis_check(NodeCompat *n) { + auto *r = n->getData(); - if (!r->options.host.empty() && !r->options.path.empty()) - return -1; + if (!r->options.host.empty() && !r->options.path.empty()) + return -1; - if (r->options.db < 0) - return -1; + if (r->options.db < 0) + return -1; - return 0; + return 0; } -char * villas::node::redis_print(NodeCompat *n) -{ - auto *r = n->getData(); +char *villas::node::redis_print(NodeCompat *n) { + auto *r = n->getData(); - std::stringstream ss; + std::stringstream ss; - ss << "mode=" << r->mode - << ", key=" << r->key - << ", notify=" << (r->notify ? "yes" : "no"); + ss << "mode=" << r->mode << ", key=" << r->key + << ", notify=" << (r->notify ? "yes" : "no"); - if (!r->notify) - ss << ", rate=" << r->rate; + if (!r->notify) + ss << ", rate=" << r->rate; - ss << ", " << r->options; + ss << ", " << r->options; - return strdup(ss.str().c_str()); + return strdup(ss.str().c_str()); } -int villas::node::redis_prepare(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_prepare(NodeCompat *n) { + int ret; + auto *r = n->getData(); - r->options.type = r->options.path.empty() - ? sw::redis::ConnectionType::TCP - : sw::redis::ConnectionType::UNIX; + r->options.type = r->options.path.empty() ? sw::redis::ConnectionType::TCP + : sw::redis::ConnectionType::UNIX; - if (r->key.empty()) - r->key = n->getNameShort(); + if (r->key.empty()) + r->key = n->getNameShort(); - ret = queue_signalled_init(&r->queue, 1024); - if (ret) - return ret; + ret = queue_signalled_init(&r->queue, 1024); + if (ret) + return ret; - ret = pool_init(&r->pool, 1024, SAMPLE_LENGTH(64)); - if (ret) - return ret; + ret = pool_init(&r->pool, 1024, SAMPLE_LENGTH(64)); + if (ret) + return ret; - r->conn = RedisConnection::get(r->options); - if (!r->conn) - return -1; + r->conn = RedisConnection::get(r->options); + if (!r->conn) + return -1; - return 0; + return 0; } -int villas::node::redis_start(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::redis_start(NodeCompat *n) { + auto *r = n->getData(); - r->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + r->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - if (!r->notify) - r->task.setRate(r->rate); + if (!r->notify) + r->task.setRate(r->rate); - switch (r->mode) { - case RedisMode::CHANNEL: - r->conn->subscribe(n, r->key); - break; + switch (r->mode) { + case RedisMode::CHANNEL: + r->conn->subscribe(n, r->key); + break; - case RedisMode::HASH: - case RedisMode::KEY: - if (r->notify) { - auto pattern = fmt::format("__keyspace@{}__:{}", r->options.db, r->key); - r->conn->subscribe(n, pattern); - } - break; - } + case RedisMode::HASH: + case RedisMode::KEY: + if (r->notify) { + auto pattern = fmt::format("__keyspace@{}__:{}", r->options.db, r->key); + r->conn->subscribe(n, pattern); + } + break; + } - r->conn->start(); + r->conn->start(); - return 0; + return 0; } -int villas::node::redis_stop(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_stop(NodeCompat *n) { + int ret; + auto *r = n->getData(); - r->conn->stop(); + r->conn->stop(); - if (!r->notify) - r->task.stop(); + if (!r->notify) + r->task.stop(); - switch (r->mode) { - case RedisMode::CHANNEL: - r->conn->unsubscribe(n, r->key); - break; + switch (r->mode) { + case RedisMode::CHANNEL: + r->conn->unsubscribe(n, r->key); + break; - case RedisMode::HASH: - case RedisMode::KEY: - if (r->notify) { - auto pattern = fmt::format("__keyspace@{}__:{}", r->options.db, r->key); - r->conn->unsubscribe(n, pattern); - } - break; - } + case RedisMode::HASH: + case RedisMode::KEY: + if (r->notify) { + auto pattern = fmt::format("__keyspace@{}__:{}", r->options.db, r->key); + r->conn->unsubscribe(n, pattern); + } + break; + } - ret = queue_signalled_close(&r->queue); - if (ret) - return ret; + ret = queue_signalled_close(&r->queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::redis_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *r = n->getData(); +int villas::node::redis_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *r = n->getData(); - // Wait for new data - if (r->notify || r->mode == RedisMode::CHANNEL) { - int pulled_cnt; - struct Sample *pulled_smps[cnt]; + // Wait for new data + if (r->notify || r->mode == RedisMode::CHANNEL) { + int pulled_cnt; + struct Sample *pulled_smps[cnt]; - pulled_cnt = queue_signalled_pull_many(&r->queue, (void **) pulled_smps, cnt); + pulled_cnt = + queue_signalled_pull_many(&r->queue, (void **)pulled_smps, cnt); - sample_copy_many(smps, pulled_smps, pulled_cnt); - sample_decref_many(pulled_smps, pulled_cnt); + sample_copy_many(smps, pulled_smps, pulled_cnt); + sample_decref_many(pulled_smps, pulled_cnt); - return pulled_cnt; - } - else { - if (r->task.wait() == 0) - throw SystemError("Failed to wait for task"); + return pulled_cnt; + } else { + if (r->task.wait() == 0) + throw SystemError("Failed to wait for task"); - return redis_get(n, smps, cnt); - } + return redis_get(n, smps, cnt); + } } -int villas::node::redis_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *r = n->getData(); +int villas::node::redis_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *r = n->getData(); - switch (r->mode) { - case RedisMode::CHANNEL: - for (unsigned i = 0; i < cnt; i++) { - char buf[1500]; - size_t wbytes; + switch (r->mode) { + case RedisMode::CHANNEL: + for (unsigned i = 0; i < cnt; i++) { + char buf[1500]; + size_t wbytes; - ret = r->formatter->sprint(buf, sizeof(buf), &wbytes, &smps[i], cnt); - if (ret < 0) - return ret; + ret = r->formatter->sprint(buf, sizeof(buf), &wbytes, &smps[i], cnt); + if (ret < 0) + return ret; - auto value = std::string_view(buf, wbytes); + auto value = std::string_view(buf, wbytes); - r->conn->context.publish(r->key, value); - } - break; + r->conn->context.publish(r->key, value); + } + break; - case RedisMode::KEY: { - char buf[1500]; - size_t wbytes; + case RedisMode::KEY: { + char buf[1500]; + size_t wbytes; - ret = r->formatter->sprint(buf, sizeof(buf), &wbytes, smps, cnt); - if (ret < 0) - return ret; + ret = r->formatter->sprint(buf, sizeof(buf), &wbytes, smps, cnt); + if (ret < 0) + return ret; - auto value = std::string_view(buf, wbytes); + auto value = std::string_view(buf, wbytes); - r->conn->context.set(r->key, value); - break; - } + r->conn->context.set(r->key, value); + break; + } - case RedisMode::HASH: { - // We only update the signals with their latest value here. - struct Sample *smp = smps[cnt - 1]; + case RedisMode::HASH: { + // We only update the signals with their latest value here. + struct Sample *smp = smps[cnt - 1]; - std::unordered_map kvs; + std::unordered_map kvs; - unsigned len = MIN(smp->signals->size(), smp->length); - for (unsigned j = 0; j < len; j++) { - const auto sig = smp->signals->getByIndex(j); - const auto *data = &smp->data[j]; + unsigned len = MIN(smp->signals->size(), smp->length); + for (unsigned j = 0; j < len; j++) { + const auto sig = smp->signals->getByIndex(j); + const auto *data = &smp->data[j]; - kvs[sig->name] = data->toString(sig->type); - } + kvs[sig->name] = data->toString(sig->type); + } - r->conn->context.hmset(r->key, kvs.begin(), kvs.end()); - break; - } - } + r->conn->context.hmset(r->key, kvs.begin(), kvs.end()); + break; + } + } - return cnt; + return cnt; } -int villas::node::redis_poll_fds(NodeCompat *n, int fds[]) -{ - auto *r = n->getData(); +int villas::node::redis_poll_fds(NodeCompat *n, int fds[]) { + auto *r = n->getData(); - fds[0] = r->notify - ? queue_signalled_fd(&r->queue) - : r->task.getFD(); + fds[0] = r->notify ? queue_signalled_fd(&r->queue) : r->task.getFD(); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "redis"; - p.description = "Redis key-value store"; - p.vectorize = 0; - p.size = sizeof(struct redis); - p.init = redis_init; - p.destroy = redis_destroy; - p.parse = redis_parse; - p.check = redis_check; - p.print = redis_print; - p.prepare = redis_prepare; - p.start = redis_start; - p.stop = redis_stop; - p.read = redis_read; - p.write = redis_write; - p.poll_fds = redis_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "redis"; + p.description = "Redis key-value store"; + p.vectorize = 0; + p.size = sizeof(struct redis); + p.init = redis_init; + p.destroy = redis_destroy; + p.parse = redis_parse; + p.check = redis_check; + p.print = redis_print; + p.prepare = redis_prepare; + p.start = redis_start; + p.stop = redis_stop; + p.read = redis_read; + p.write = redis_write; + p.poll_fds = redis_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index dc68965fb..27de3c0e7 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -7,587 +7,568 @@ */ #include -#include #include #include +#include #include #include extern "C" { - #include - #include - #include - #include - #include - #include - #include - #undef ALIGN_MASK +#include +#include +#include +#include +#include +#include +#include +#undef ALIGN_MASK } +#include #include #include -#include #include -#include #include +#include #ifdef WITH_NETEM - #include +#include #endif // WITH_NETEM -static -pthread_t re_pthread; +static pthread_t re_pthread; using namespace villas; using namespace villas::utils; using namespace villas::node; using namespace villas::kernel; -static -NodeCompatType p; -static -NodeCompatFactory ncp(&p); +static NodeCompatType p; +static NodeCompatFactory ncp(&p); -static -int rtp_aimd(NodeCompat *n, double loss_frac) -{ - auto *r = n->getData(); +static int rtp_aimd(NodeCompat *n, double loss_frac) { + auto *r = n->getData(); - double rate; + double rate; - if (!r->rtcp.enabled) - return -1; + if (!r->rtcp.enabled) + return -1; - if (loss_frac < 0.01) - rate = r->aimd.rate + r->aimd.a; - else - rate = r->aimd.rate * r->aimd.b; + if (loss_frac < 0.01) + rate = r->aimd.rate + r->aimd.a; + else + rate = r->aimd.rate * r->aimd.b; - r->aimd.rate = r->aimd.rate_pid.calculate(rate, r->aimd.rate); + r->aimd.rate = r->aimd.rate_pid.calculate(rate, r->aimd.rate); - if (r->aimd.rate_hook) { - r->aimd.rate_hook->setRate(r->aimd.rate); - n->logger->debug("AIMD: Set rate limit to: {}", r->aimd.rate); - } + if (r->aimd.rate_hook) { + r->aimd.rate_hook->setRate(r->aimd.rate); + n->logger->debug("AIMD: Set rate limit to: {}", r->aimd.rate); + } - if (r->aimd.log) - *(r->aimd.log) << r->rtcp.num_rrs << "\t" << loss_frac << "\t" << r->aimd.rate << std::endl; + if (r->aimd.log) + *(r->aimd.log) << r->rtcp.num_rrs << "\t" << loss_frac << "\t" + << r->aimd.rate << std::endl; - n->logger->debug("AIMD: {}\t{}\t{}", r->rtcp.num_rrs, loss_frac, r->aimd.rate); + n->logger->debug("AIMD: {}\t{}\t{}", r->rtcp.num_rrs, loss_frac, + r->aimd.rate); - return 0; + return 0; } -int villas::node::rtp_init(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::rtp_init(NodeCompat *n) { + auto *r = n->getData(); - n->logger = villas::logging.get("node:rtp"); + n->logger = villas::logging.get("node:rtp"); - // Default values - r->aimd.a = 10; - r->aimd.b = 0.5; - r->aimd.Kp = 1; - r->aimd.Ki = 0; - r->aimd.Kd = 0; + // Default values + r->aimd.a = 10; + r->aimd.b = 0.5; + r->aimd.Kp = 1; + r->aimd.Ki = 0; + r->aimd.Kd = 0; - r->aimd.rate = 1; - r->aimd.rate_min = 1; - r->aimd.rate_source = 2000; + r->aimd.rate = 1; + r->aimd.rate_min = 1; + r->aimd.rate_source = 2000; - r->aimd.log_filename = nullptr; - r->aimd.log = nullptr; + r->aimd.log_filename = nullptr; + r->aimd.log = nullptr; - r->rtcp.enabled = false; - r->aimd.rate_hook_type = RTPHookType::DISABLED; + r->rtcp.enabled = false; + r->aimd.rate_hook_type = RTPHookType::DISABLED; - r->formatter = nullptr; + r->formatter = nullptr; - return 0; + return 0; } -int villas::node::rtp_reverse(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::rtp_reverse(NodeCompat *n) { + auto *r = n->getData(); - SWAP(r->in.saddr_rtp, r->out.saddr_rtp); - SWAP(r->in.saddr_rtcp, r->out.saddr_rtcp); + SWAP(r->in.saddr_rtp, r->out.saddr_rtp); + SWAP(r->in.saddr_rtcp, r->out.saddr_rtcp); - return 0; + return 0; } -int villas::node::rtp_parse(NodeCompat *n, json_t *json) -{ - int ret = 0; - auto *r = n->getData(); +int villas::node::rtp_parse(NodeCompat *n, json_t *json) { + int ret = 0; + auto *r = n->getData(); - const char *local, *remote; - const char *log = nullptr; - const char *hook_type = nullptr; - uint16_t port; + const char *local, *remote; + const char *log = nullptr; + const char *hook_type = nullptr; + uint16_t port; - json_error_t err; - json_t *json_aimd = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_aimd = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: b, s?: o, s: { s: s }, s: { s: s } }", - "format", &json_format, - "rtcp", &r->rtcp.enabled, - "aimd", &json_aimd, - "out", - "address", &remote, - "in", - "address", &local - ); - if (ret) - throw ConfigError(json, err, "node-config-node-rtp"); + ret = json_unpack_ex( + json, &err, 0, "{ s?: o, s?: b, s?: o, s: { s: s }, s: { s: s } }", + "format", &json_format, "rtcp", &r->rtcp.enabled, "aimd", &json_aimd, + "out", "address", &remote, "in", "address", &local); + if (ret) + throw ConfigError(json, err, "node-config-node-rtp"); - // AIMD - if (json_aimd) { - ret = json_unpack_ex(json_aimd, &err, 0, "{ s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: s, s?: s }", - "a", &r->aimd.a, - "b", &r->aimd.b, - "Kp", &r->aimd.Kp, - "Ki", &r->aimd.Ki, - "Kd", &r->aimd.Kd, - "rate_min", &r->aimd.rate_min, - "rate_source", &r->aimd.rate_source, - "rate_init", &r->aimd.rate, - "log", &log, - "hook_type", &hook_type - ); - if (ret) - throw ConfigError(json_aimd, err, "node-config-node-rtp-aimd"); + // AIMD + if (json_aimd) { + ret = json_unpack_ex(json_aimd, &err, 0, + "{ s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, " + "s?: F, s?: s, s?: s }", + "a", &r->aimd.a, "b", &r->aimd.b, "Kp", &r->aimd.Kp, + "Ki", &r->aimd.Ki, "Kd", &r->aimd.Kd, "rate_min", + &r->aimd.rate_min, "rate_source", &r->aimd.rate_source, + "rate_init", &r->aimd.rate, "log", &log, "hook_type", + &hook_type); + if (ret) + throw ConfigError(json_aimd, err, "node-config-node-rtp-aimd"); - // AIMD Hook type - if (!r->rtcp.enabled) - r->aimd.rate_hook_type = RTPHookType::DISABLED; - else if (hook_type) { - if (!strcmp(hook_type, "decimate")) - r->aimd.rate_hook_type = RTPHookType::DECIMATE; - else if (!strcmp(hook_type, "limit_rate")) - r->aimd.rate_hook_type = RTPHookType::LIMIT_RATE; - else if (!strcmp(hook_type, "disabled")) - r->aimd.rate_hook_type = RTPHookType::DISABLED; - else - throw RuntimeError("Unknown RTCP hook_type: {}", hook_type); - } - } + // AIMD Hook type + if (!r->rtcp.enabled) + r->aimd.rate_hook_type = RTPHookType::DISABLED; + else if (hook_type) { + if (!strcmp(hook_type, "decimate")) + r->aimd.rate_hook_type = RTPHookType::DECIMATE; + else if (!strcmp(hook_type, "limit_rate")) + r->aimd.rate_hook_type = RTPHookType::LIMIT_RATE; + else if (!strcmp(hook_type, "disabled")) + r->aimd.rate_hook_type = RTPHookType::DISABLED; + else + throw RuntimeError("Unknown RTCP hook_type: {}", hook_type); + } + } - if (log) - r->aimd.log_filename = strdup(log); + if (log) + r->aimd.log_filename = strdup(log); - // Format - if (r->formatter) - delete r->formatter; - r->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); - if (!r->formatter) - throw ConfigError(json_format, "node-config-node-rtp-format", "Invalid format configuration"); + // Format + if (r->formatter) + delete r->formatter; + r->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); + if (!r->formatter) + throw ConfigError(json_format, "node-config-node-rtp-format", + "Invalid format configuration"); - // Remote address - ret = sa_decode(&r->out.saddr_rtp, remote, strlen(remote)); - if (ret) - throw RuntimeError("Failed to resolve remote address '{}': {}", remote, strerror(ret)); + // Remote address + ret = sa_decode(&r->out.saddr_rtp, remote, strlen(remote)); + if (ret) + throw RuntimeError("Failed to resolve remote address '{}': {}", remote, + strerror(ret)); - // Assign even port number to RTP socket, next odd number to RTCP socket - port = sa_port(&r->out.saddr_rtp) & ~1; - sa_set_sa(&r->out.saddr_rtcp, &r->out.saddr_rtp.u.sa); - sa_set_port(&r->out.saddr_rtp, port); - sa_set_port(&r->out.saddr_rtcp, port+1); + // Assign even port number to RTP socket, next odd number to RTCP socket + port = sa_port(&r->out.saddr_rtp) & ~1; + sa_set_sa(&r->out.saddr_rtcp, &r->out.saddr_rtp.u.sa); + sa_set_port(&r->out.saddr_rtp, port); + sa_set_port(&r->out.saddr_rtcp, port + 1); - // Local address - ret = sa_decode(&r->in.saddr_rtp, local, strlen(local)); - if (ret) - throw RuntimeError("Failed to resolve local address '{}': {}", local, strerror(ret)); + // Local address + ret = sa_decode(&r->in.saddr_rtp, local, strlen(local)); + if (ret) + throw RuntimeError("Failed to resolve local address '{}': {}", local, + strerror(ret)); - // Assign even port number to RTP socket, next odd number to RTCP socket - port = sa_port(&r->in.saddr_rtp) & ~1; - sa_set_sa(&r->in.saddr_rtcp, &r->in.saddr_rtp.u.sa); - sa_set_port(&r->in.saddr_rtp, port); - sa_set_port(&r->in.saddr_rtcp, port+1); + // Assign even port number to RTP socket, next odd number to RTCP socket + port = sa_port(&r->in.saddr_rtp) & ~1; + sa_set_sa(&r->in.saddr_rtcp, &r->in.saddr_rtp.u.sa); + sa_set_port(&r->in.saddr_rtp, port); + sa_set_port(&r->in.saddr_rtcp, port + 1); - // TODO: parse * in addresses + // TODO: parse * in addresses - return 0; + return 0; } -char * villas::node::rtp_print(NodeCompat *n) -{ - auto *r = n->getData(); - char *buf; +char *villas::node::rtp_print(NodeCompat *n) { + auto *r = n->getData(); + char *buf; - char *local = socket_print_addr((struct sockaddr *) &r->in.saddr_rtp.u); - char *remote = socket_print_addr((struct sockaddr *) &r->out.saddr_rtp.u); + char *local = socket_print_addr((struct sockaddr *)&r->in.saddr_rtp.u); + char *remote = socket_print_addr((struct sockaddr *)&r->out.saddr_rtp.u); - buf = strf("in.address=%s, out.address=%s, rtcp.enabled=%s", - local, remote, - r->rtcp.enabled ? "yes" : "no"); + buf = strf("in.address=%s, out.address=%s, rtcp.enabled=%s", local, remote, + r->rtcp.enabled ? "yes" : "no"); - if (r->rtcp.enabled) { - const char *hook_type; + if (r->rtcp.enabled) { + const char *hook_type; - switch (r->aimd.rate_hook_type) { - case RTPHookType::DECIMATE: - hook_type = "decimate"; - break; + switch (r->aimd.rate_hook_type) { + case RTPHookType::DECIMATE: + hook_type = "decimate"; + break; - case RTPHookType::LIMIT_RATE: - hook_type = "limit_rate"; - break; + case RTPHookType::LIMIT_RATE: + hook_type = "limit_rate"; + break; - case RTPHookType::DISABLED: - hook_type = "disabled"; - break; + case RTPHookType::DISABLED: + hook_type = "disabled"; + break; - default: - hook_type = "unknown"; - } + default: + hook_type = "unknown"; + } - strcatf(&buf, ", aimd.hook_type=%s", hook_type); - strcatf(&buf, ", aimd.a=%f, aimd.b=%f, aimd.start_rate=%f", r->aimd.a, r->aimd.b, r->aimd.rate); - } + strcatf(&buf, ", aimd.hook_type=%s", hook_type); + strcatf(&buf, ", aimd.a=%f, aimd.b=%f, aimd.start_rate=%f", r->aimd.a, + r->aimd.b, r->aimd.rate); + } - free(local); - free(remote); + free(local); + free(remote); - return buf; + return buf; } -static -void rtp_handler(const struct sa *src, const struct rtp_header *hdr, struct mbuf *mb, void *arg) -{ - int ret; - auto *n = (NodeCompat *) arg; - auto *r = n->getData(); +static void rtp_handler(const struct sa *src, const struct rtp_header *hdr, + struct mbuf *mb, void *arg) { + int ret; + auto *n = (NodeCompat *)arg; + auto *r = n->getData(); - // source, header not used - (void) src; - (void) hdr; + // source, header not used + (void)src; + (void)hdr; - void *d = mem_ref((void *) mb); + void *d = mem_ref((void *)mb); - ret = queue_signalled_push(&r->recv_queue, d); - if (ret != 1) { - n->logger->warn("Failed to push to queue"); - mem_deref(d); - } + ret = queue_signalled_push(&r->recv_queue, d); + if (ret != 1) { + n->logger->warn("Failed to push to queue"); + mem_deref(d); + } } -static -void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg) -{ - auto *n = (NodeCompat *) arg; - auto *r = n->getData(); +static void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, + void *arg) { + auto *n = (NodeCompat *)arg; + auto *r = n->getData(); - // source not used - (void) src; + // source not used + (void)src; - n->logger->debug("RTCP: recv {}", rtcp_type_name((enum rtcp_type) msg->hdr.pt)); + n->logger->debug("RTCP: recv {}", + rtcp_type_name((enum rtcp_type)msg->hdr.pt)); - if (msg->hdr.pt == RTCP_SR) { - if (msg->hdr.count > 0) { - const struct rtcp_rr *rr = &msg->r.sr.rrv[0]; + if (msg->hdr.pt == RTCP_SR) { + if (msg->hdr.count > 0) { + const struct rtcp_rr *rr = &msg->r.sr.rrv[0]; - double loss_frac = (double) rr->fraction / 256; + double loss_frac = (double)rr->fraction / 256; - rtp_aimd(n, loss_frac); + rtp_aimd(n, loss_frac); - auto stats = n->getStats(); - if (stats) { - stats->update(Stats::Metric::RTP_PKTS_LOST, rr->lost); - stats->update(Stats::Metric::RTP_LOSS_FRACTION, loss_frac); - stats->update(Stats::Metric::RTP_JITTER, rr->jitter); - } + auto stats = n->getStats(); + if (stats) { + stats->update(Stats::Metric::RTP_PKTS_LOST, rr->lost); + stats->update(Stats::Metric::RTP_LOSS_FRACTION, loss_frac); + stats->update(Stats::Metric::RTP_JITTER, rr->jitter); + } - n->logger->info("RTCP: rr: num_rrs={}, loss_frac={}, pkts_lost={}, jitter={}", r->rtcp.num_rrs, loss_frac, rr->lost, rr->jitter); - } - else - n->logger->debug("RTCP: Received sender report with zero reception reports"); - } + n->logger->info( + "RTCP: rr: num_rrs={}, loss_frac={}, pkts_lost={}, jitter={}", + r->rtcp.num_rrs, loss_frac, rr->lost, rr->jitter); + } else + n->logger->debug( + "RTCP: Received sender report with zero reception reports"); + } - r->rtcp.num_rrs++; + r->rtcp.num_rrs++; } -int villas::node::rtp_start(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::rtp_start(NodeCompat *n) { + int ret; + auto *r = n->getData(); - // Initialize queue - ret = queue_signalled_init(&r->recv_queue, 1024, &memory::heap); - if (ret) - return ret; + // Initialize queue + ret = queue_signalled_init(&r->recv_queue, 1024, &memory::heap); + if (ret) + return ret; - // Initialize IO - r->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + // Initialize IO + r->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - // Initialize memory buffer for sending - r->send_mb = mbuf_alloc(RTP_INITIAL_BUFFER_LEN); - if (!r->send_mb) - return -1; + // Initialize memory buffer for sending + r->send_mb = mbuf_alloc(RTP_INITIAL_BUFFER_LEN); + if (!r->send_mb) + return -1; - ret = mbuf_fill(r->send_mb, 0, RTP_HEADER_SIZE); - if (ret) - return -1; + ret = mbuf_fill(r->send_mb, 0, RTP_HEADER_SIZE); + if (ret) + return -1; - // Initialize AIMD hook - if (r->aimd.rate_hook_type != RTPHookType::DISABLED) { + // Initialize AIMD hook + if (r->aimd.rate_hook_type != RTPHookType::DISABLED) { #ifdef WITH_HOOKS - switch (r->aimd.rate_hook_type) { - case RTPHookType::DECIMATE: - r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); - break; + switch (r->aimd.rate_hook_type) { + case RTPHookType::DECIMATE: + r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); + break; - case RTPHookType::LIMIT_RATE: - r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); - break; + case RTPHookType::LIMIT_RATE: + r->aimd.rate_hook = std::make_shared(nullptr, n, 0, 0); + break; - default: - return -1; - } + default: + return -1; + } - if (!r->aimd.rate_hook) - throw MemoryAllocationError(); + if (!r->aimd.rate_hook) + throw MemoryAllocationError(); - r->aimd.rate_hook->init(); + r->aimd.rate_hook->init(); - n->out.hooks.push_back(r->aimd.rate_hook); + n->out.hooks.push_back(r->aimd.rate_hook); - r->aimd.rate_hook->setRate(r->aimd.rate, r->aimd.rate_source); + r->aimd.rate_hook->setRate(r->aimd.rate, r->aimd.rate_source); #else - throw RuntimeError("Rate limiting is not supported"); + throw RuntimeError("Rate limiting is not supported"); - return -1; + return -1; #endif - } + } - double dt = 5.0; // TODO + double dt = 5.0; // TODO - r->aimd.rate_pid = villas::dsp::PID(dt, r->aimd.rate_source, r->aimd.rate_min, r->aimd.Kp, r->aimd.Ki, r->aimd.Kd); + r->aimd.rate_pid = villas::dsp::PID(dt, r->aimd.rate_source, r->aimd.rate_min, + r->aimd.Kp, r->aimd.Ki, r->aimd.Kd); - // Initialize RTP socket - uint16_t port = sa_port(&r->in.saddr_rtp) & ~1; - ret = rtp_listen(&r->rs, IPPROTO_UDP, &r->in.saddr_rtp, port, port+1, r->rtcp.enabled, rtp_handler, rtcp_handler, n); + // Initialize RTP socket + uint16_t port = sa_port(&r->in.saddr_rtp) & ~1; + ret = rtp_listen(&r->rs, IPPROTO_UDP, &r->in.saddr_rtp, port, port + 1, + r->rtcp.enabled, rtp_handler, rtcp_handler, n); - // Start RTCP session - if (r->rtcp.enabled) { - r->rtcp.num_rrs = 0; + // Start RTCP session + if (r->rtcp.enabled) { + r->rtcp.num_rrs = 0; - rtcp_start(r->rs, n->getNameShort().c_str(), &r->out.saddr_rtcp); + rtcp_start(r->rs, n->getNameShort().c_str(), &r->out.saddr_rtcp); - if (r->aimd.log_filename) { - char fn[128]; + if (r->aimd.log_filename) { + char fn[128]; - time_t ts = time(nullptr); - struct tm tm; + time_t ts = time(nullptr); + struct tm tm; - // Convert time - gmtime_r(&ts, &tm); - strftime(fn, sizeof(fn), r->aimd.log_filename, &tm); + // Convert time + gmtime_r(&ts, &tm); + strftime(fn, sizeof(fn), r->aimd.log_filename, &tm); - r->aimd.log = new std::ofstream(fn, std::ios::out | std::ios::trunc); - if (!r->aimd.log) - throw MemoryAllocationError(); + r->aimd.log = new std::ofstream(fn, std::ios::out | std::ios::trunc); + if (!r->aimd.log) + throw MemoryAllocationError(); - *(r->aimd.log) << "# cnt\tfrac_loss\trate" << std::endl; - } - else - r->aimd.log = nullptr; - } + *(r->aimd.log) << "# cnt\tfrac_loss\trate" << std::endl; + } else + r->aimd.log = nullptr; + } - return ret; + return ret; } -int villas::node::rtp_stop(NodeCompat *n) -{ - int ret; - auto *r = n->getData(); +int villas::node::rtp_stop(NodeCompat *n) { + int ret; + auto *r = n->getData(); - mem_deref(r->rs); + mem_deref(r->rs); - ret = queue_signalled_close(&r->recv_queue); - if (ret) - throw RuntimeError("Problem closing queue"); + ret = queue_signalled_close(&r->recv_queue); + if (ret) + throw RuntimeError("Problem closing queue"); - ret = queue_signalled_destroy(&r->recv_queue); - if (ret) - throw RuntimeError("Problem destroying queue"); + ret = queue_signalled_destroy(&r->recv_queue); + if (ret) + throw RuntimeError("Problem destroying queue"); - mem_deref(r->send_mb); + mem_deref(r->send_mb); - if (r->aimd.log) - r->aimd.log->close(); + if (r->aimd.log) + r->aimd.log->close(); - return 0; + return 0; } -int villas::node::rtp_destroy(NodeCompat *n) -{ - auto *r = n->getData(); +int villas::node::rtp_destroy(NodeCompat *n) { + auto *r = n->getData(); - if (r->aimd.log) - delete r->aimd.log; + if (r->aimd.log) + delete r->aimd.log; - if (r->aimd.log_filename) - free(r->aimd.log_filename); + if (r->aimd.log_filename) + free(r->aimd.log_filename); - if (r->formatter) - delete r->formatter; + if (r->formatter) + delete r->formatter; - return 0; + return 0; } -static -void stop_handler(int sig, siginfo_t *si, void *ctx) -{ - re_cancel(); -} +static void stop_handler(int sig, siginfo_t *si, void *ctx) { re_cancel(); } typedef void *(*pthread_start_routine)(void *); -int villas::node::rtp_type_start(villas::node::SuperNode *sn) -{ - int ret; +int villas::node::rtp_type_start(villas::node::SuperNode *sn) { + int ret; - // Initialize library - ret = libre_init(); - if (ret) - throw RuntimeError("Error initializing libre"); + // Initialize library + ret = libre_init(); + if (ret) + throw RuntimeError("Error initializing libre"); - // Add worker thread - ret = pthread_create(&re_pthread, nullptr, (pthread_start_routine) re_main, nullptr); - if (ret) - throw RuntimeError("Error creating rtp node type pthread"); + // Add worker thread + ret = pthread_create(&re_pthread, nullptr, (pthread_start_routine)re_main, + nullptr); + if (ret) + throw RuntimeError("Error creating rtp node type pthread"); - struct sigaction sa; - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = stop_handler; + struct sigaction sa; + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = stop_handler; - ret = sigaction(SIGUSR1, &sa, nullptr); - if (ret) - return ret; + ret = sigaction(SIGUSR1, &sa, nullptr); + if (ret) + return ret; #ifdef WITH_NETEM - if (sn != nullptr) { - // Gather list of used network interfaces - for (auto *n : ncp.instances) { - auto *nc = dynamic_cast(n); - auto *r = nc->getData(); - Interface *j = Interface::getEgress(&r->out.saddr_rtp.u.sa, sn); + if (sn != nullptr) { + // Gather list of used network interfaces + for (auto *n : ncp.instances) { + auto *nc = dynamic_cast(n); + auto *r = nc->getData(); + Interface *j = Interface::getEgress(&r->out.saddr_rtp.u.sa, sn); - if (!j) - throw RuntimeError("Failed to find egress interface"); + if (!j) + throw RuntimeError("Failed to find egress interface"); - j->addNode(n); - } - } + j->addNode(n); + } + } #endif // WITH_NETEM - return 0; + return 0; } -int villas::node::rtp_type_stop() -{ - int ret; +int villas::node::rtp_type_stop() { + int ret; - // Join worker thread - pthread_kill(re_pthread, SIGUSR1); - ret = pthread_join(re_pthread, nullptr); - if (ret) - throw RuntimeError("Error joining rtp node type pthread"); + // Join worker thread + pthread_kill(re_pthread, SIGUSR1); + ret = pthread_join(re_pthread, nullptr); + if (ret) + throw RuntimeError("Error joining rtp node type pthread"); - libre_close(); + libre_close(); - return 0; + return 0; } -int villas::node::rtp_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *r = n->getData(); - struct mbuf *mb; +int villas::node::rtp_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *r = n->getData(); + struct mbuf *mb; - // Get data from queue - ret = queue_signalled_pull(&r->recv_queue, (void **) &mb); - if (ret < 0) - throw RuntimeError("Failed to pull from queue"); + // Get data from queue + ret = queue_signalled_pull(&r->recv_queue, (void **)&mb); + if (ret < 0) + throw RuntimeError("Failed to pull from queue"); - // Unpack data - ret = r->formatter->sscan((char *) mb->buf + mb->pos, mbuf_get_left(mb), nullptr, smps, cnt); + // Unpack data + ret = r->formatter->sscan((char *)mb->buf + mb->pos, mbuf_get_left(mb), + nullptr, smps, cnt); - mem_deref(mb); + mem_deref(mb); - return ret; + return ret; } -int villas::node::rtp_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *r = n->getData(); +int villas::node::rtp_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *r = n->getData(); - size_t wbytes; - size_t avail; + size_t wbytes; + size_t avail; - uint32_t ts = (uint32_t) time(nullptr); + uint32_t ts = (uint32_t)time(nullptr); -retry: mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); - avail = mbuf_get_space(r->send_mb); - cnt = r->formatter->sprint((char *) r->send_mb->buf + r->send_mb->pos, avail, &wbytes, smps, cnt); - if (cnt < 0) - return -1; +retry: + mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); + avail = mbuf_get_space(r->send_mb); + cnt = r->formatter->sprint((char *)r->send_mb->buf + r->send_mb->pos, avail, + &wbytes, smps, cnt); + if (cnt < 0) + return -1; - if (wbytes > avail) { - ret = mbuf_resize(r->send_mb, wbytes + RTP_HEADER_SIZE); - if (!ret) - return -1; + if (wbytes > avail) { + ret = mbuf_resize(r->send_mb, wbytes + RTP_HEADER_SIZE); + if (!ret) + return -1; - goto retry; - } - else - mbuf_set_end(r->send_mb, r->send_mb->pos + wbytes); + goto retry; + } else + mbuf_set_end(r->send_mb, r->send_mb->pos + wbytes); - mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); + mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); - // Send dataset - ret = rtp_send(r->rs, &r->out.saddr_rtp, false, false, RTP_PACKET_TYPE, ts, 0, r->send_mb); - if (ret) - throw RuntimeError("Error from rtp_send, reason: {}", ret); + // Send dataset + ret = rtp_send(r->rs, &r->out.saddr_rtp, false, false, RTP_PACKET_TYPE, ts, 0, + r->send_mb); + if (ret) + throw RuntimeError("Error from rtp_send, reason: {}", ret); - return cnt; + return cnt; } -int villas::node::rtp_poll_fds(NodeCompat *n, int fds[]) -{ - auto *r = n->getData(); +int villas::node::rtp_poll_fds(NodeCompat *n, int fds[]) { + auto *r = n->getData(); - fds[0] = queue_signalled_fd(&r->recv_queue); + fds[0] = queue_signalled_fd(&r->recv_queue); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "rtp"; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "rtp"; #ifdef WITH_NETEM - p.description = "real-time transport protocol (libre, libnl3 netem support)"; + p.description = "real-time transport protocol (libre, libnl3 netem support)"; #else - p.description = "real-time transport protocol (libre)"; + p.description = "real-time transport protocol (libre)"; #endif - p.vectorize = 0; - p.size = sizeof(struct rtp); - p.type.start = rtp_type_start; - p.type.stop = rtp_type_stop; - p.init = rtp_init; - p.destroy = rtp_destroy; - p.parse = rtp_parse; - p.print = rtp_print; - p.start = rtp_start; - p.stop = rtp_stop; - p.read = rtp_read; - p.write = rtp_write; - p.reverse = rtp_reverse; - p.poll_fds = rtp_poll_fds; + p.vectorize = 0; + p.size = sizeof(struct rtp); + p.type.start = rtp_type_start; + p.type.stop = rtp_type_stop; + p.init = rtp_init; + p.destroy = rtp_destroy; + p.parse = rtp_parse; + p.print = rtp_print; + p.start = rtp_start; + p.stop = rtp_stop; + p.read = rtp_read; + p.write = rtp_write; + p.reverse = rtp_reverse; + p.poll_fds = rtp_poll_fds; } diff --git a/lib/nodes/shmem.cpp b/lib/nodes/shmem.cpp index 3cbb95270..4f9e363cc 100644 --- a/lib/nodes/shmem.cpp +++ b/lib/nodes/shmem.cpp @@ -5,19 +5,19 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include #include #include #include +#include #include #include -#include -#include #include #include +#include #include #include @@ -25,210 +25,198 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -int villas::node::shmem_init(NodeCompat *n) -{ - auto *shm = n->getData(); +int villas::node::shmem_init(NodeCompat *n) { + auto *shm = n->getData(); - // Default values - shm->conf.queuelen = -1; - shm->conf.samplelen = -1; - shm->conf.polling = false; - shm->exec = nullptr; + // Default values + shm->conf.queuelen = -1; + shm->conf.samplelen = -1; + shm->conf.polling = false; + shm->exec = nullptr; - return 0; + return 0; } -int villas::node::shmem_parse(NodeCompat *n, json_t *json) -{ - auto *shm = n->getData(); - const char *val, *mode_str = nullptr; +int villas::node::shmem_parse(NodeCompat *n, json_t *json) { + auto *shm = n->getData(); + const char *val, *mode_str = nullptr; - int ret; - json_t *json_exec = nullptr; - json_error_t err; + int ret; + json_t *json_exec = nullptr; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s: { s: s }, s: { s: s }, s?: i, s?: o, s?: s }", - "out", - "name", &shm->out_name, - "in", - "name", &shm->in_name, - "queuelen", &shm->conf.queuelen, - "exec", &json_exec, - "mode", &mode_str - ); - if (ret) - throw ConfigError(json, err, "node-config-node-shmem"); + ret = json_unpack_ex( + json, &err, 0, "{ s: { s: s }, s: { s: s }, s?: i, s?: o, s?: s }", "out", + "name", &shm->out_name, "in", "name", &shm->in_name, "queuelen", + &shm->conf.queuelen, "exec", &json_exec, "mode", &mode_str); + if (ret) + throw ConfigError(json, err, "node-config-node-shmem"); - if (mode_str) { - if (!strcmp(mode_str, "polling")) - shm->conf.polling = true; - else if (!strcmp(mode_str, "pthread")) - shm->conf.polling = false; - else - throw SystemError("Unknown mode '{}'", mode_str); - } + if (mode_str) { + if (!strcmp(mode_str, "polling")) + shm->conf.polling = true; + else if (!strcmp(mode_str, "pthread")) + shm->conf.polling = false; + else + throw SystemError("Unknown mode '{}'", mode_str); + } - if (json_exec) { - if (!json_is_array(json_exec)) - throw SystemError("Setting 'exec' must be an array of strings"); + if (json_exec) { + if (!json_is_array(json_exec)) + throw SystemError("Setting 'exec' must be an array of strings"); - shm->exec = new char*[json_array_size(json_exec) + 1]; - if (!shm->exec) - throw MemoryAllocationError(); + shm->exec = new char *[json_array_size(json_exec) + 1]; + if (!shm->exec) + throw MemoryAllocationError(); - size_t i; - json_t *json_val; - json_array_foreach(json_exec, i, json_val) { - val = json_string_value(json_val); - if (!val) - throw SystemError("Setting 'exec' must be an array of strings"); + size_t i; + json_t *json_val; + json_array_foreach(json_exec, i, json_val) { + val = json_string_value(json_val); + if (!val) + throw SystemError("Setting 'exec' must be an array of strings"); - shm->exec[i] = strdup(val); - } + shm->exec[i] = strdup(val); + } - shm->exec[i] = nullptr; - } + shm->exec[i] = nullptr; + } - return 0; + return 0; } -int villas::node::shmem_prepare(NodeCompat *n) -{ - auto *shm = n->getData(); +int villas::node::shmem_prepare(NodeCompat *n) { + auto *shm = n->getData(); - if (shm->conf.queuelen < 0) - shm->conf.queuelen = MAX(DEFAULT_SHMEM_QUEUELEN, n->in.vectorize); + if (shm->conf.queuelen < 0) + shm->conf.queuelen = MAX(DEFAULT_SHMEM_QUEUELEN, n->in.vectorize); - if (shm->conf.samplelen < 0) { - auto input_sigs = n->getInputSignals(false)->size(); - auto output_sigs = 0U; + if (shm->conf.samplelen < 0) { + auto input_sigs = n->getInputSignals(false)->size(); + auto output_sigs = 0U; - if (n->getOutputSignals(true)) - output_sigs = n->getOutputSignals(true)->size(); + if (n->getOutputSignals(true)) + output_sigs = n->getOutputSignals(true)->size(); - shm->conf.samplelen = MAX(input_sigs, output_sigs); - } + shm->conf.samplelen = MAX(input_sigs, output_sigs); + } - return 0; + return 0; } -int villas::node::shmem_start(NodeCompat *n) -{ - auto *shm = n->getData(); - int ret; +int villas::node::shmem_start(NodeCompat *n) { + auto *shm = n->getData(); + int ret; - if (shm->exec) { - ret = spawn(shm->exec[0], shm->exec); - if (!ret) - throw SystemError("Failed to spawn external program"); + if (shm->exec) { + ret = spawn(shm->exec[0], shm->exec); + if (!ret) + throw SystemError("Failed to spawn external program"); - sleep(1); - } + sleep(1); + } - ret = shmem_int_open(shm->out_name, shm->in_name, &shm->intf, &shm->conf); - if (ret < 0) - throw SystemError("Opening shared memory interface failed (ret={})", ret); + ret = shmem_int_open(shm->out_name, shm->in_name, &shm->intf, &shm->conf); + if (ret < 0) + throw SystemError("Opening shared memory interface failed (ret={})", ret); - return 0; + return 0; } -int villas::node::shmem_stop(NodeCompat *n) -{ - auto* shm = n->getData(); +int villas::node::shmem_stop(NodeCompat *n) { + auto *shm = n->getData(); - return shmem_int_close(&shm->intf); + return shmem_int_close(&shm->intf); } -int villas::node::shmem_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *shm = n->getData(); - int recv; - struct Sample *shared_smps[cnt]; +int villas::node::shmem_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *shm = n->getData(); + int recv; + struct Sample *shared_smps[cnt]; - do { - recv = shmem_int_read(&shm->intf, shared_smps, cnt); - } while (recv == 0); + do { + recv = shmem_int_read(&shm->intf, shared_smps, cnt); + } while (recv == 0); - if (recv < 0) { - /* This can only really mean that the other process has exited, so close + if (recv < 0) { + /* This can only really mean that the other process has exited, so close * the interface to make sure the shared memory object is unlinked */ - n->logger->info("Shared memory segment has been closed."); + n->logger->info("Shared memory segment has been closed."); - n->setState(State::STOPPING); + n->setState(State::STOPPING); - return recv; - } + return recv; + } - sample_copy_many(smps, shared_smps, recv); - sample_decref_many(shared_smps, recv); + sample_copy_many(smps, shared_smps, recv); + sample_decref_many(shared_smps, recv); - // TODO: signal descriptions are currently not shared between processes - for (int i = 0; i < recv; i++) - smps[i]->signals = n->getInputSignals(false); + // TODO: signal descriptions are currently not shared between processes + for (int i = 0; i < recv; i++) + smps[i]->signals = n->getInputSignals(false); - return recv; + return recv; } -int villas::node::shmem_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *shm = n->getData(); - struct Sample *shared_smps[cnt]; // Samples need to be copied to the shared pool first - int avail, pushed, copied; +int villas::node::shmem_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *shm = n->getData(); + struct Sample + *shared_smps[cnt]; // Samples need to be copied to the shared pool first + int avail, pushed, copied; - avail = sample_alloc_many(&shm->intf.write.shared->pool, shared_smps, cnt); - if (avail != (int) cnt) - n->logger->warn("Pool underrun for shmem node {}", shm->out_name); + avail = sample_alloc_many(&shm->intf.write.shared->pool, shared_smps, cnt); + if (avail != (int)cnt) + n->logger->warn("Pool underrun for shmem node {}", shm->out_name); - copied = sample_copy_many(shared_smps, smps, avail); - if (copied < avail) - n->logger->warn("Outgoing pool underrun"); + copied = sample_copy_many(shared_smps, smps, avail); + if (copied < avail) + n->logger->warn("Outgoing pool underrun"); - pushed = shmem_int_write(&shm->intf, shared_smps, copied); - if (pushed != avail) - n->logger->warn("Outgoing queue overrun for node"); + pushed = shmem_int_write(&shm->intf, shared_smps, copied); + if (pushed != avail) + n->logger->warn("Outgoing queue overrun for node"); - return pushed; + return pushed; } -char * villas::node::shmem_print(NodeCompat *n) -{ - auto *shm = n->getData(); - char *buf = nullptr; +char *villas::node::shmem_print(NodeCompat *n) { + auto *shm = n->getData(); + char *buf = nullptr; - strcatf(&buf, "out_name=%s, in_name=%s, queuelen=%d, polling=%s", - shm->out_name, shm->in_name, shm->conf.queuelen, shm->conf.polling ? "yes" : "no"); + strcatf(&buf, "out_name=%s, in_name=%s, queuelen=%d, polling=%s", + shm->out_name, shm->in_name, shm->conf.queuelen, + shm->conf.polling ? "yes" : "no"); - if (shm->exec) { - strcatf(&buf, ", exec='"); + if (shm->exec) { + strcatf(&buf, ", exec='"); - for (int i = 0; shm->exec[i]; i++) - strcatf(&buf, shm->exec[i+1] ? "%s " : "%s", shm->exec[i]); + for (int i = 0; shm->exec[i]; i++) + strcatf(&buf, shm->exec[i + 1] ? "%s " : "%s", shm->exec[i]); - strcatf(&buf, "'"); - } + strcatf(&buf, "'"); + } - return buf; + return buf; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "shmem"; - p.description = "POSIX shared memory interface with external processes"; - p.vectorize = 0; - p.size = sizeof(struct shmem); - p.parse = shmem_parse; - p.print = shmem_print; - p.start = shmem_start; - p.stop = shmem_stop; - p.read = shmem_read; - p.write = shmem_write; - p.prepare = shmem_prepare; - p.init = shmem_init; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "shmem"; + p.description = "POSIX shared memory interface with external processes"; + p.vectorize = 0; + p.size = sizeof(struct shmem); + p.parse = shmem_parse; + p.print = shmem_print; + p.start = shmem_start; + p.stop = shmem_stop; + p.read = shmem_read; + p.write = shmem_write; + p.prepare = shmem_prepare; + p.init = shmem_init; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/signal.cpp b/lib/nodes/signal.cpp index 798569229..eba731d35 100644 --- a/lib/nodes/signal.cpp +++ b/lib/nodes/signal.cpp @@ -5,9 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include #include #include @@ -18,365 +18,337 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -SignalNodeSignal::SignalNodeSignal(json_t *json) : - type(Type::MIXED), - frequency(1.0), - amplitude(1.0), - stddev(0.2), - offset(0.0), - pulse_width(1.0), - pulse_low(0.0), - pulse_high(1.0), - phase(0.0) -{ - parse(json); +SignalNodeSignal::SignalNodeSignal(json_t *json) + : type(Type::MIXED), frequency(1.0), amplitude(1.0), stddev(0.2), + offset(0.0), pulse_width(1.0), pulse_low(0.0), pulse_high(1.0), + phase(0.0) { + parse(json); - last = offset; + last = offset; } -enum SignalNodeSignal::Type SignalNodeSignal::lookupType(const std::string &type) -{ - if (type == "random") - return Type::RANDOM; - else if (type == "sine") - return Type::SINE; - else if (type == "square") - return Type::SQUARE; - else if (type == "triangle") - return Type::TRIANGLE; - else if (type == "ramp") - return Type::RAMP; - else if (type == "counter") - return Type::COUNTER; - else if (type == "constant") - return Type::CONSTANT; - else if (type == "mixed") - return Type::MIXED; - else if (type == "pulse") - return Type::PULSE; +enum SignalNodeSignal::Type +SignalNodeSignal::lookupType(const std::string &type) { + if (type == "random") + return Type::RANDOM; + else if (type == "sine") + return Type::SINE; + else if (type == "square") + return Type::SQUARE; + else if (type == "triangle") + return Type::TRIANGLE; + else if (type == "ramp") + return Type::RAMP; + else if (type == "counter") + return Type::COUNTER; + else if (type == "constant") + return Type::CONSTANT; + else if (type == "mixed") + return Type::MIXED; + else if (type == "pulse") + return Type::PULSE; - throw std::invalid_argument("Invalid signal type"); + throw std::invalid_argument("Invalid signal type"); } -std::string SignalNodeSignal::typeToString(enum Type type) -{ - switch (type) { - case Type::CONSTANT: - return "constant"; +std::string SignalNodeSignal::typeToString(enum Type type) { + switch (type) { + case Type::CONSTANT: + return "constant"; - case Type::SINE: - return "sine"; + case Type::SINE: + return "sine"; - case Type::TRIANGLE: - return "triangle"; + case Type::TRIANGLE: + return "triangle"; - case Type::SQUARE: - return "square"; + case Type::SQUARE: + return "square"; - case Type::RAMP: - return "ramp"; + case Type::RAMP: + return "ramp"; - case Type::COUNTER: - return "counter"; + case Type::COUNTER: + return "counter"; - case Type::RANDOM: - return "random"; + case Type::RANDOM: + return "random"; - case Type::MIXED: - return "mixed"; + case Type::MIXED: + return "mixed"; - case Type::PULSE: - return "pulse"; + case Type::PULSE: + return "pulse"; - default: - return nullptr; - } + default: + return nullptr; + } } -void SignalNodeSignal::start() -{ - last = offset; +void SignalNodeSignal::start() { last = offset; } +void SignalNodeSignal::read(unsigned c, double t, double r, SignalData *d) { + switch (type) { + case Type::CONSTANT: + d->f = offset + amplitude; + break; + + case Type::SINE: + d->f = offset + amplitude * sin(t * frequency * 2 * M_PI + phase); + break; + + case Type::TRIANGLE: + d->f = + offset + + amplitude * + (fabs(fmod(t * frequency + (phase / (2 * M_PI)), 1) - .5) - 0.25) * + 4; + break; + + case Type::SQUARE: + d->f = offset + + amplitude * + ((fmod(t * frequency + (phase / (2 * M_PI)), 1) < .5) ? -1 : 1); + break; + + case Type::RAMP: + d->f = offset + amplitude * fmod(t, frequency); + break; + + case Type::COUNTER: + d->f = offset + amplitude * c; + break; + + case Type::RANDOM: + last += boxMuller(0, stddev); + d->f = last; + break; + + case Type::MIXED: + break; + + case Type::PULSE: + d->f = + abs(fmod(t * frequency + (phase / (2 * M_PI)), 1)) <= (pulse_width / r) + ? pulse_high + : pulse_low; + d->f += offset; + break; + } } -void SignalNodeSignal::read(unsigned c, double t, double r, SignalData *d) -{ - switch (type) { - case Type::CONSTANT: - d->f = offset + amplitude; - break; +int SignalNodeSignal::parse(json_t *json) { + int ret; + const char *type_str; - case Type::SINE: - d->f = offset + amplitude * sin(t * frequency * 2 * M_PI + phase); - break; + json_error_t err; - case Type::TRIANGLE: - d->f = offset + amplitude * (fabs(fmod(t * frequency + (phase / (2 * M_PI)), 1) - .5) - 0.25) * 4; - break; + ret = json_unpack_ex( + json, &err, 0, + "{ s: s, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F }", + "signal", &type_str, "frequency", &frequency, "amplitude", &litude, + "stddev", &stddev, "offset", &offset, "pulse_width", &pulse_width, + "pulse_low", &pulse_low, "pulse_high", &pulse_high, "phase", &phase); + if (ret) + throw ConfigError(json, err, "node-config-node-signal"); - case Type::SQUARE: - d->f = offset + amplitude * ( (fmod(t * frequency + (phase / (2 * M_PI)), 1) < .5) ? -1 : 1); - break; + try { + type = lookupType(type_str); + } catch (std::invalid_argument &e) { + throw ConfigError(json, "node-config-node-signal-type", + "Unknown signal type: {}", type_str); + } - case Type::RAMP: - d->f = offset + amplitude * fmod(t, frequency); - break; - - case Type::COUNTER: - d->f = offset + amplitude * c; - break; - - case Type::RANDOM: - last += boxMuller(0, stddev); - d->f = last; - break; - - case Type::MIXED: - break; - - case Type::PULSE: - d->f = abs(fmod(t * frequency + (phase / (2 * M_PI)) , 1)) <= (pulse_width / r) - ? pulse_high - : pulse_low; - d->f += offset; - break; - } + return 0; } -int SignalNodeSignal::parse(json_t *json) -{ - int ret; - const char *type_str; +Signal::Ptr SignalNodeSignal::toSignal(Signal::Ptr tpl) const { + auto isDefaultName = tpl->name.rfind("signal", 0) == 0; - json_error_t err; + auto name = isDefaultName ? typeToString(type) : tpl->name; + auto unit = tpl->unit; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F, s?: F }", - "signal", &type_str, - "frequency", &frequency, - "amplitude", &litude, - "stddev", &stddev, - "offset", &offset, - "pulse_width", &pulse_width, - "pulse_low", &pulse_low, - "pulse_high", &pulse_high, - "phase", &phase - ); - if (ret) - throw ConfigError(json, err, "node-config-node-signal"); + auto sig = std::make_shared(name, unit, SignalType::FLOAT); - try { - type = lookupType(type_str); - } catch (std::invalid_argument &e) { - throw ConfigError(json, "node-config-node-signal-type", "Unknown signal type: {}", type_str); - } + sig->init.f = offset; - return 0; + return sig; } -Signal::Ptr SignalNodeSignal::toSignal(Signal::Ptr tpl) const -{ - auto isDefaultName = tpl->name.rfind("signal", 0) == 0; +SignalNode::SignalNode(const uuid_t &id, const std::string &name) + : Node(id, name), task(CLOCK_MONOTONIC), rt(1), rate(10), + monitor_missed(true), limit(-1), missed_steps(0) {} - auto name = isDefaultName ? typeToString(type) : tpl->name; - auto unit = tpl->unit; +int SignalNode::prepare() { + assert(state == State::CHECKED); - auto sig = std::make_shared(name, unit, SignalType::FLOAT); + for (unsigned i = 0; i < signals.size(); i++) { + auto &sig = (*in.signals)[i]; + auto &ssig = signals[i]; - sig->init.f = offset; + sig = ssig.toSignal(sig); + } - return sig; + if (logger->level() <= spdlog::level::debug) + in.signals->dump(logger); + + return Node::prepare(); } -SignalNode::SignalNode(const uuid_t &id, const std::string &name) : - Node(id, name), - task(CLOCK_MONOTONIC), - rt(1), - rate(10), - monitor_missed(true), - limit(-1), - missed_steps(0) -{ } +int SignalNode::parse(json_t *json) { + int r = -1, m = -1, ret = Node::parse(json); + if (ret) + return ret; -int SignalNode::prepare() -{ - assert(state == State::CHECKED); + json_error_t err; - for (unsigned i = 0; i < signals.size(); i++) { - auto &sig = (*in.signals)[i]; - auto &ssig = signals[i]; + size_t i; + json_t *json_signals, *json_signal; - sig = ssig.toSignal(sig); - } + ret = json_unpack_ex(json, &err, 0, + "{ s?: b, s?: i, s?: F, s?: b, s: { s: o } }", + "realtime", &r, "limit", &limit, "rate", &rate, + "monitor_missed", &m, "in", "signals", &json_signals); + if (ret) + throw ConfigError(json, err, "node-config-node-signal"); - if (logger->level() <= spdlog::level::debug) - in.signals->dump(logger); + if (r >= 0) + rt = r != 0; - return Node::prepare(); + if (m >= 0) + monitor_missed = m != 0; + + signals.clear(); + unsigned j = 0; + json_array_foreach(json_signals, i, json_signal) { + auto sig = SignalNodeSignal(json_signal); + + if (sig.type == SignalNodeSignal::Type::MIXED) + sig.type = + (SignalNodeSignal::Type)(j++ % (int)SignalNodeSignal::Type::MIXED); + + signals.push_back(sig); + } + + state = State::PARSED; + + return 0; } -int SignalNode::parse(json_t *json) -{ - int r = -1, m = -1, ret = Node::parse(json); - if (ret) - return ret; +int SignalNode::start() { + assert(state == State::PREPARED || state == State::PAUSED); - json_error_t err; + missed_steps = 0; + started = time_now(); - size_t i; - json_t *json_signals, *json_signal; + for (auto sig : signals) + sig.start(); - ret = json_unpack_ex(json, &err, 0, "{ s?: b, s?: i, s?: F, s?: b, s: { s: o } }", - "realtime", &r, - "limit", &limit, - "rate", &rate, - "monitor_missed", &m, - "in", - "signals", &json_signals - ); - if (ret) - throw ConfigError(json, err, "node-config-node-signal"); + // Setup task + if (rt) + task.setRate(rate); - if (r >= 0) - rt = r != 0; + int ret = Node::start(); + if (!ret) + state = State::STARTED; - if (m >= 0) - monitor_missed = m != 0; - - signals.clear(); - unsigned j = 0; - json_array_foreach(json_signals, i, json_signal) { - auto sig = SignalNodeSignal(json_signal); - - if (sig.type == SignalNodeSignal::Type::MIXED) - sig.type = (SignalNodeSignal::Type) (j++ % (int) SignalNodeSignal::Type::MIXED); - - signals.push_back(sig); - } - - state = State::PARSED; - - return 0; + return ret; } -int SignalNode::start() -{ - assert(state == State::PREPARED || - state == State::PAUSED); +int SignalNode::stop() { + assert(state == State::STARTED || state == State::PAUSED || + state == State::STOPPING); - missed_steps = 0; - started = time_now(); + int ret = Node::stop(); + if (ret) + return ret; - for (auto sig : signals) - sig.start(); + if (rt) + task.stop(); - // Setup task - if (rt) - task.setRate(rate); + if (missed_steps > 0 && monitor_missed) + logger->warn("Missed a total of {} steps.", missed_steps); - int ret = Node::start(); - if (!ret) - state = State::STARTED; + state = State::STOPPED; - return ret; + return 0; } -int SignalNode::stop() -{ - assert(state == State::STARTED || - state == State::PAUSED || - state == State::STOPPING); +int SignalNode::_read(struct Sample *smps[], unsigned cnt) { + struct Sample *t = smps[0]; - int ret = Node::stop(); - if (ret) - return ret; + struct timespec ts; + uint64_t steps, counter = sequence - sequence_init; - if (rt) - task.stop(); + assert(cnt == 1); - if (missed_steps > 0 && monitor_missed) - logger->warn("Missed a total of {} steps.", missed_steps); + if (rt) + ts = time_now(); + else { + struct timespec offset = time_from_double(counter * 1.0 / rate); + ts = time_add(&started, &offset); + } - state = State::STOPPED; + double running = time_delta(&started, &ts); - return 0; + t->flags = (int)SampleFlags::HAS_TS_ORIGIN | (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE; + t->ts.origin = ts; + t->sequence = sequence; + t->length = MIN(signals.size(), t->capacity); + t->signals = in.signals; + + for (unsigned i = 0; i < t->length; i++) { + auto &sig = signals[i]; + + sig.read(counter, running, rate, &t->data[i]); + } + + if (limit > 0 && counter >= (unsigned)limit) { + logger->info("Reached limit."); + + setState(State::STOPPING); + return -1; + } + + // Throttle output if desired + if (rt) { + // Block until 1/p->rate seconds elapsed + steps = task.wait(); + if (steps > 1 && monitor_missed) { + logger->debug("Missed steps: {}", steps - 1); + missed_steps += steps - 1; + } + } else + steps = 1; + + sequence += steps; + + return 1; } -int SignalNode::_read(struct Sample *smps[], unsigned cnt) -{ - struct Sample *t = smps[0]; +const std::string &SignalNode::getDetails() { + if (details.empty()) { + details = fmt::format("rt={}, rate={}", rt ? "yes" : "no", rate); - struct timespec ts; - uint64_t steps, counter = sequence - sequence_init; + if (limit > 0) + details += fmt::format(", limit={}", limit); + } - assert(cnt == 1); - - if (rt) - ts = time_now(); - else { - struct timespec offset = time_from_double(counter * 1.0 / rate); - ts = time_add(&started, &offset); - } - - double running = time_delta(&started, &ts); - - t->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE; - t->ts.origin = ts; - t->sequence = sequence; - t->length = MIN(signals.size(), t->capacity); - t->signals = in.signals; - - for (unsigned i = 0; i < t->length; i++) { - auto &sig = signals[i]; - - sig.read(counter, running, rate, &t->data[i]); - } - - if (limit > 0 && counter >= (unsigned) limit) { - logger->info("Reached limit."); - - setState(State::STOPPING); - return -1; - } - - // Throttle output if desired - if (rt) { - // Block until 1/p->rate seconds elapsed - steps = task.wait(); - if (steps > 1 && monitor_missed) { - logger->debug("Missed steps: {}", steps-1); - missed_steps += steps-1; - } - } - else - steps = 1; - - sequence += steps; - - return 1; + return details; } -const std::string & SignalNode::getDetails() -{ - if (details.empty()) { - details = fmt::format("rt={}, rate={}", rt ? "yes" : "no", rate); +std::vector SignalNode::getPollFDs() { + if (rt) + return {task.getFD()}; - if (limit > 0) - details += fmt::format(", limit={}", limit); - - } - - return details; -} - -std::vector SignalNode::getPollFDs() -{ - if (rt) - return { task.getFD() }; - - return {}; + return {}; } // Register node static char n[] = "signal.v2"; static char d[] = "Signal generator"; -static NodePlugin p; +static NodePlugin + p; diff --git a/lib/nodes/signal_v1.cpp b/lib/nodes/signal_v1.cpp index f9d17b0e6..8c745cba6 100644 --- a/lib/nodes/signal_v1.cpp +++ b/lib/nodes/signal_v1.cpp @@ -5,9 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include #include #include @@ -18,453 +18,458 @@ using namespace villas; using namespace villas::node; using namespace villas::utils; -static -enum signal_node::SignalType signal_node_lookup_type(const char *type) -{ - if (!strcmp(type, "random")) - return signal_node::SignalType::RANDOM; - else if (!strcmp(type, "sine")) - return signal_node::SignalType::SINE; - else if (!strcmp(type, "square")) - return signal_node::SignalType::SQUARE; - else if (!strcmp(type, "triangle")) - return signal_node::SignalType::TRIANGLE; - else if (!strcmp(type, "ramp")) - return signal_node::SignalType::RAMP; - else if (!strcmp(type, "counter")) - return signal_node::SignalType::COUNTER; - else if (!strcmp(type, "constant")) - return signal_node::SignalType::CONSTANT; - else if (!strcmp(type, "mixed")) - return signal_node::SignalType::MIXED; - else if (!strcmp(type, "pulse")) - return signal_node::SignalType::PULSE; +static enum signal_node::SignalType signal_node_lookup_type(const char *type) { + if (!strcmp(type, "random")) + return signal_node::SignalType::RANDOM; + else if (!strcmp(type, "sine")) + return signal_node::SignalType::SINE; + else if (!strcmp(type, "square")) + return signal_node::SignalType::SQUARE; + else if (!strcmp(type, "triangle")) + return signal_node::SignalType::TRIANGLE; + else if (!strcmp(type, "ramp")) + return signal_node::SignalType::RAMP; + else if (!strcmp(type, "counter")) + return signal_node::SignalType::COUNTER; + else if (!strcmp(type, "constant")) + return signal_node::SignalType::CONSTANT; + else if (!strcmp(type, "mixed")) + return signal_node::SignalType::MIXED; + else if (!strcmp(type, "pulse")) + return signal_node::SignalType::PULSE; - throw std::invalid_argument("Invalid signal type"); + throw std::invalid_argument("Invalid signal type"); } -static -const char * signal_node_type_str(enum signal_node::SignalType type) -{ - switch (type) { - case signal_node::SignalType::CONSTANT: - return "constant"; +static const char *signal_node_type_str(enum signal_node::SignalType type) { + switch (type) { + case signal_node::SignalType::CONSTANT: + return "constant"; - case signal_node::SignalType::SINE: - return "sine"; + case signal_node::SignalType::SINE: + return "sine"; - case signal_node::SignalType::TRIANGLE: - return "triangle"; + case signal_node::SignalType::TRIANGLE: + return "triangle"; - case signal_node::SignalType::SQUARE: - return "square"; + case signal_node::SignalType::SQUARE: + return "square"; - case signal_node::SignalType::RAMP: - return "ramp"; + case signal_node::SignalType::RAMP: + return "ramp"; - case signal_node::SignalType::COUNTER: - return "counter"; + case signal_node::SignalType::COUNTER: + return "counter"; - case signal_node::SignalType::RANDOM: - return "random"; + case signal_node::SignalType::RANDOM: + return "random"; - case signal_node::SignalType::MIXED: - return "mixed"; + case signal_node::SignalType::MIXED: + return "mixed"; - case signal_node::SignalType::PULSE: - return "pulse"; + case signal_node::SignalType::PULSE: + return "pulse"; - default: - return nullptr; - } + default: + return nullptr; + } } -int villas::node::signal_node_init(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_init(NodeCompat *n) { + auto *s = n->getData(); - new (&s->task) Task(CLOCK_MONOTONIC); + new (&s->task) Task(CLOCK_MONOTONIC); - s->rt = 1; - s->limit = -1; - s->values = 1; - s->rate = 10; - s->monitor_missed = 1; + s->rt = 1; + s->limit = -1; + s->values = 1; + s->rate = 10; + s->monitor_missed = 1; - s->type = nullptr; - s->frequency = nullptr; - s->amplitude = nullptr; - s->stddev = nullptr; - s->offset = nullptr; - s->phase = nullptr; - s->pulse_width = nullptr; - s->pulse_low = nullptr; - s->pulse_high = nullptr; + s->type = nullptr; + s->frequency = nullptr; + s->amplitude = nullptr; + s->stddev = nullptr; + s->offset = nullptr; + s->phase = nullptr; + s->pulse_width = nullptr; + s->pulse_low = nullptr; + s->pulse_high = nullptr; - return 0; + return 0; } -int villas::node::signal_node_destroy(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_destroy(NodeCompat *n) { + auto *s = n->getData(); - s->task.~Task(); + s->task.~Task(); - if (s->type) - delete[] s->type; + if (s->type) + delete[] s->type; - if (s->frequency) - delete[] s->frequency; + if (s->frequency) + delete[] s->frequency; - if (s->amplitude) - delete[] s->amplitude; + if (s->amplitude) + delete[] s->amplitude; - if (s->stddev) - delete[] s->stddev; + if (s->stddev) + delete[] s->stddev; - if (s->offset) - delete[] s->offset; + if (s->offset) + delete[] s->offset; - if (s->phase) - delete[] s->phase; + if (s->phase) + delete[] s->phase; - if (s->pulse_width) - delete[] s->pulse_width; + if (s->pulse_width) + delete[] s->pulse_width; - if (s->pulse_low) - delete[] s->pulse_low; + if (s->pulse_low) + delete[] s->pulse_low; - if (s->pulse_high) - delete[] s->pulse_high; + if (s->pulse_high) + delete[] s->pulse_high; - return 0; + return 0; } -int villas::node::signal_node_prepare(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_prepare(NodeCompat *n) { + auto *s = n->getData(); - n->in.signals = std::make_shared(); - for (unsigned i = 0; i < s->values; i++) { - auto name = signal_node_type_str((enum signal_node::SignalType) s->type[i]); - auto sig = std::make_shared(name, "", SignalType::FLOAT); + n->in.signals = std::make_shared(); + for (unsigned i = 0; i < s->values; i++) { + auto name = signal_node_type_str((enum signal_node::SignalType)s->type[i]); + auto sig = std::make_shared(name, "", SignalType::FLOAT); - n->in.signals->push_back(sig); - } + n->in.signals->push_back(sig); + } - return 0; + return 0; } -int villas::node::signal_node_parse(NodeCompat *n, json_t *json) -{ - auto *s = n->getData(); +int villas::node::signal_node_parse(NodeCompat *n, json_t *json) { + auto *s = n->getData(); - int ret; + int ret; - json_error_t err; + json_error_t err; - json_t *json_type = nullptr; - json_t *json_amplitude = nullptr; - json_t *json_offset = nullptr; - json_t *json_frequency = nullptr; - json_t *json_stddev = nullptr; - json_t *json_pulse_width = nullptr; - json_t *json_pulse_high = nullptr; - json_t *json_pulse_low = nullptr; - json_t *json_phase = nullptr; + json_t *json_type = nullptr; + json_t *json_amplitude = nullptr; + json_t *json_offset = nullptr; + json_t *json_frequency = nullptr; + json_t *json_stddev = nullptr; + json_t *json_pulse_width = nullptr; + json_t *json_pulse_high = nullptr; + json_t *json_pulse_low = nullptr; + json_t *json_phase = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s?: b, s?: i, s?: i, s?: F, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: o, s?: b }", - "signal", &json_type, - "realtime", &s->rt, - "limit", &s->limit, - "values", &s->values, - "rate", &s->rate, - "frequency", &json_frequency, - "amplitude", &json_amplitude, - "stddev", &json_stddev, - "offset", &json_offset, - "pulse_width", &json_pulse_width, - "pulse_low", &json_pulse_low, - "pulse_high", &json_pulse_high, - "phase", &json_phase, - "monitor_missed", &s->monitor_missed - ); - if (ret) - throw ConfigError(json, err, "node-config-node-signal"); + ret = json_unpack_ex( + json, &err, 0, + "{ s: o, s?: b, s?: i, s?: i, s?: F, s?: o, s?: o, s?: o, s?: o, s?: o, " + "s?: o, s?: o, s?: o, s?: b }", + "signal", &json_type, "realtime", &s->rt, "limit", &s->limit, "values", + &s->values, "rate", &s->rate, "frequency", &json_frequency, "amplitude", + &json_amplitude, "stddev", &json_stddev, "offset", &json_offset, + "pulse_width", &json_pulse_width, "pulse_low", &json_pulse_low, + "pulse_high", &json_pulse_high, "phase", &json_phase, "monitor_missed", + &s->monitor_missed); + if (ret) + throw ConfigError(json, err, "node-config-node-signal"); - struct desc { - json_t *json; - double **array; - double def_value; - const char *name; - }; + struct desc { + json_t *json; + double **array; + double def_value; + const char *name; + }; - std::list arrays = { - { json_frequency, &s->frequency, 1, "frequency" }, - { json_amplitude, &s->amplitude, 1, "amplitude" }, - { json_stddev, &s->stddev, 0.2, "stddev" }, - { json_offset, &s->offset, 0, "offset" }, - { json_pulse_width, &s->pulse_width, 1, "pulse_width" }, - { json_pulse_high, &s->pulse_high, 1, "pulse_high" }, - { json_pulse_low, &s->pulse_low, 0, "pulse_low" }, - { json_phase, &s->phase, 0, "phase" } - }; + std::list arrays = { + {json_frequency, &s->frequency, 1, "frequency"}, + {json_amplitude, &s->amplitude, 1, "amplitude"}, + {json_stddev, &s->stddev, 0.2, "stddev"}, + {json_offset, &s->offset, 0, "offset"}, + {json_pulse_width, &s->pulse_width, 1, "pulse_width"}, + {json_pulse_high, &s->pulse_high, 1, "pulse_high"}, + {json_pulse_low, &s->pulse_low, 0, "pulse_low"}, + {json_phase, &s->phase, 0, "phase"}}; - size_t i; - json_t *json_value; - const char *type_str; - signal_node::SignalType type; + size_t i; + json_t *json_value; + const char *type_str; + signal_node::SignalType type; - s->type = new enum signal_node::SignalType[s->values]; + s->type = new enum signal_node::SignalType[s->values]; - switch (json_typeof(json_type)) { - case JSON_ARRAY: - if (json_array_size(json_type) != s->values) - throw ConfigError(json_type, "node-config-node-signal", "Length of values must match"); + switch (json_typeof(json_type)) { + case JSON_ARRAY: + if (json_array_size(json_type) != s->values) + throw ConfigError(json_type, "node-config-node-signal", + "Length of values must match"); - json_array_foreach(json_type, i, json_value) { - type_str = json_string_value(json_value); - if (!type_str) - throw ConfigError(json_value, "node-config-node-signal", "Signal type must be a string"); + json_array_foreach(json_type, i, json_value) { + type_str = json_string_value(json_value); + if (!type_str) + throw ConfigError(json_value, "node-config-node-signal", + "Signal type must be a string"); - s->type[i] = signal_node_lookup_type(type_str); - } - break; + s->type[i] = signal_node_lookup_type(type_str); + } + break; - case JSON_STRING: - type_str = json_string_value(json_type); - type = signal_node_lookup_type(type_str); + case JSON_STRING: + type_str = json_string_value(json_type); + type = signal_node_lookup_type(type_str); - for (size_t i = 0; i < s->values; i++) { - s->type[i] = (type == signal_node::SignalType::MIXED - ? (signal_node::SignalType) (i % 7) - : type); - } - break; + for (size_t i = 0; i < s->values; i++) { + s->type[i] = (type == signal_node::SignalType::MIXED + ? (signal_node::SignalType)(i % 7) + : type); + } + break; - default: - throw ConfigError(json_type, "node-config-node-signal", "Invalid setting 'signal' for node {}", n->getName()); - } + default: + throw ConfigError(json_type, "node-config-node-signal", + "Invalid setting 'signal' for node {}", n->getName()); + } - for (auto &a : arrays) { - if (*a.array) - delete *a.array; + for (auto &a : arrays) { + if (*a.array) + delete *a.array; - *a.array = new double[s->values]; + *a.array = new double[s->values]; - if (a.json) { - switch (json_typeof(a.json)) { - case JSON_ARRAY: - if (json_array_size(a.json) != s->values) - throw ConfigError(a.json, "node-config-node-signal", "Length of values must match"); + if (a.json) { + switch (json_typeof(a.json)) { + case JSON_ARRAY: + if (json_array_size(a.json) != s->values) + throw ConfigError(a.json, "node-config-node-signal", + "Length of values must match"); - size_t i; - json_t *json_value; - json_array_foreach(a.json, i, json_value) { - if (!json_is_number(json_value)) - throw ConfigError(json_value, "node-config-node-signal", "Values must gives as array of integer or float values!"); + size_t i; + json_t *json_value; + json_array_foreach(a.json, i, json_value) { + if (!json_is_number(json_value)) + throw ConfigError( + json_value, "node-config-node-signal", + "Values must gives as array of integer or float values!"); - (*a.array)[i] = json_number_value(json_value); - } + (*a.array)[i] = json_number_value(json_value); + } - break; + break; - case JSON_INTEGER: - case JSON_REAL: - for (size_t i = 0; i < s->values; i++) - (*a.array)[i] = json_number_value(a.json); + case JSON_INTEGER: + case JSON_REAL: + for (size_t i = 0; i < s->values; i++) + (*a.array)[i] = json_number_value(a.json); - break; + break; - default: - throw ConfigError(a.json, "node-config-node-signal", "Values must given as array or scalar integer or float value!"); - } - } - else { - for (size_t i = 0; i < s->values; i++) - (*a.array)[i] = a.def_value; - } - } + default: + throw ConfigError( + a.json, "node-config-node-signal", + "Values must given as array or scalar integer or float value!"); + } + } else { + for (size_t i = 0; i < s->values; i++) + (*a.array)[i] = a.def_value; + } + } - return 0; + return 0; } -int villas::node::signal_node_start(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_start(NodeCompat *n) { + auto *s = n->getData(); - s->missed_steps = 0; - s->counter = 0; - s->started = time_now(); - s->last = new double[s->values]; - if (!s->last) - throw MemoryAllocationError(); + s->missed_steps = 0; + s->counter = 0; + s->started = time_now(); + s->last = new double[s->values]; + if (!s->last) + throw MemoryAllocationError(); - for (unsigned i = 0; i < s->values; i++) - s->last[i] = s->offset[i]; + for (unsigned i = 0; i < s->values; i++) + s->last[i] = s->offset[i]; - // Setup task - if (s->rt) - s->task.setRate(s->rate); + // Setup task + if (s->rt) + s->task.setRate(s->rate); - return 0; + return 0; } -int villas::node::signal_node_stop(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::signal_node_stop(NodeCompat *n) { + auto *s = n->getData(); - if (s->rt) - s->task.stop(); + if (s->rt) + s->task.stop(); - if (s->missed_steps > 0 && s->monitor_missed) - n->logger->warn("Missed a total of {} steps.", s->missed_steps); + if (s->missed_steps > 0 && s->monitor_missed) + n->logger->warn("Missed a total of {} steps.", s->missed_steps); - delete[] s->last; + delete[] s->last; - return 0; + return 0; } -int villas::node::signal_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *s = n->getData(); - struct Sample *t = smps[0]; +int villas::node::signal_node_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *s = n->getData(); + struct Sample *t = smps[0]; - struct timespec ts; - int steps; + struct timespec ts; + int steps; - assert(cnt == 1); + assert(cnt == 1); - if (s->rt) - ts = time_now(); - else { - struct timespec offset = time_from_double(s->counter * 1.0 / s->rate); + if (s->rt) + ts = time_now(); + else { + struct timespec offset = time_from_double(s->counter * 1.0 / s->rate); - ts = time_add(&s->started, &offset); + ts = time_add(&s->started, &offset); - steps = 1; - } + steps = 1; + } - double running = time_delta(&s->started, &ts); + double running = time_delta(&s->started, &ts); - t->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE; - t->ts.origin = ts; - t->sequence = s->counter; - t->length = MIN(s->values, t->capacity); - t->signals = n->getInputSignals(false); + t->flags = (int)SampleFlags::HAS_TS_ORIGIN | (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE; + t->ts.origin = ts; + t->sequence = s->counter; + t->length = MIN(s->values, t->capacity); + t->signals = n->getInputSignals(false); - for (unsigned i = 0; i < t->length; i++) { - switch (s->type[i]) { - case signal_node::SignalType::CONSTANT: - t->data[i].f = s->offset[i] + s->amplitude[i]; - break; + for (unsigned i = 0; i < t->length; i++) { + switch (s->type[i]) { + case signal_node::SignalType::CONSTANT: + t->data[i].f = s->offset[i] + s->amplitude[i]; + break; - case signal_node::SignalType::SINE: - t->data[i].f = s->offset[i] + s->amplitude[i] * sin(running * s->frequency[i] * 2 * M_PI + s->phase[i]); - break; + case signal_node::SignalType::SINE: + t->data[i].f = + s->offset[i] + + s->amplitude[i] * + sin(running * s->frequency[i] * 2 * M_PI + s->phase[i]); + break; - case signal_node::SignalType::TRIANGLE: - t->data[i].f = s->offset[i] + s->amplitude[i] * (fabs(fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), 1) - .5) - 0.25) * 4; - break; + case signal_node::SignalType::TRIANGLE: + t->data[i].f = + s->offset[i] + + s->amplitude[i] * + (fabs(fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), + 1) - + .5) - + 0.25) * + 4; + break; - case signal_node::SignalType::SQUARE: - t->data[i].f = s->offset[i] + s->amplitude[i] * ( (fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), 1) < .5) ? -1 : 1); - break; + case signal_node::SignalType::SQUARE: + t->data[i].f = + s->offset[i] + + s->amplitude[i] * + ((fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), + 1) < .5) + ? -1 + : 1); + break; - case signal_node::SignalType::RAMP: - t->data[i].f = s->offset[i] + s->amplitude[i] * fmod(running, s->frequency[i]); - break; + case signal_node::SignalType::RAMP: + t->data[i].f = + s->offset[i] + s->amplitude[i] * fmod(running, s->frequency[i]); + break; - case signal_node::SignalType::COUNTER: - t->data[i].f = s->offset[i] + s->amplitude[i] * s->counter; - break; + case signal_node::SignalType::COUNTER: + t->data[i].f = s->offset[i] + s->amplitude[i] * s->counter; + break; - case signal_node::SignalType::RANDOM: - s->last[i] += boxMuller(0, s->stddev[i]); - t->data[i].f = s->last[i]; - break; + case signal_node::SignalType::RANDOM: + s->last[i] += boxMuller(0, s->stddev[i]); + t->data[i].f = s->last[i]; + break; - case signal_node::SignalType::MIXED: - break; + case signal_node::SignalType::MIXED: + break; - case signal_node::SignalType::PULSE: - t->data[i].f = abs(fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)) , 1)) <= (s->pulse_width[i] / s->rate) - ? s->pulse_high[i] - : s->pulse_low[i]; - t->data[i].f += s->offset[i]; - break; - } - } + case signal_node::SignalType::PULSE: + t->data[i].f = + abs(fmod(running * s->frequency[i] + (s->phase[i] / (2 * M_PI)), + 1)) <= (s->pulse_width[i] / s->rate) + ? s->pulse_high[i] + : s->pulse_low[i]; + t->data[i].f += s->offset[i]; + break; + } + } - if (s->limit > 0 && s->counter >= (unsigned) s->limit) { - n->logger->info("Reached limit."); + if (s->limit > 0 && s->counter >= (unsigned)s->limit) { + n->logger->info("Reached limit."); - n->setState(State::STOPPING); + n->setState(State::STOPPING); - return -1; - } + return -1; + } - // Throttle output if desired - if (s->rt) { - // Block until 1/p->rate seconds elapsed - steps = s->task.wait(); - if (steps > 1 && s->monitor_missed) { - n->logger->debug("Missed steps: {}", steps-1); - s->missed_steps += steps-1; - } - } + // Throttle output if desired + if (s->rt) { + // Block until 1/p->rate seconds elapsed + steps = s->task.wait(); + if (steps > 1 && s->monitor_missed) { + n->logger->debug("Missed steps: {}", steps - 1); + s->missed_steps += steps - 1; + } + } - s->counter += steps; + s->counter += steps; - return 1; + return 1; } -char * villas::node::signal_node_print(NodeCompat *n) -{ - auto *s = n->getData(); - char *buf = nullptr; +char *villas::node::signal_node_print(NodeCompat *n) { + auto *s = n->getData(); + char *buf = nullptr; - strcatf(&buf, "rt=%s, rate=%.2f, values=%d", s->rt ? "yes" : "no", s->rate, s->values); + strcatf(&buf, "rt=%s, rate=%.2f, values=%d", s->rt ? "yes" : "no", s->rate, + s->values); - if (s->limit > 0) - strcatf(&buf, ", limit=%d", s->limit); + if (s->limit > 0) + strcatf(&buf, ", limit=%d", s->limit); - return buf; + return buf; } -int villas::node::signal_node_poll_fds(NodeCompat *n, int fds[]) -{ - auto *s = n->getData(); +int villas::node::signal_node_poll_fds(NodeCompat *n, int fds[]) { + auto *s = n->getData(); - if (s->rt) { - fds[0] = s->task.getFD(); + if (s->rt) { + fds[0] = s->task.getFD(); - return 1; - } - else - return 0; + return 1; + } else + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "signal"; - p.description = "Legacy Signal generator"; - p.vectorize = 1; - p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; - p.size = sizeof(struct signal_node); - p.init = signal_node_init; - p.destroy = signal_node_destroy; - p.parse = signal_node_parse; - p.prepare = signal_node_prepare; - p.print = signal_node_print; - p.start = signal_node_start; - p.stop = signal_node_stop; - p.read = signal_node_read; - p.poll_fds = signal_node_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "signal"; + p.description = "Legacy Signal generator"; + p.vectorize = 1; + p.flags = (int)NodeFactory::Flags::PROVIDES_SIGNALS; + p.size = sizeof(struct signal_node); + p.init = signal_node_init; + p.destroy = signal_node_destroy; + p.parse = signal_node_parse; + p.prepare = signal_node_prepare; + p.print = signal_node_print; + p.start = signal_node_start; + p.stop = signal_node_stop; + p.read = signal_node_read; + p.poll_fds = signal_node_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/socket.cpp b/lib/nodes/socket.cpp index e6c1b9564..965bb4949 100644 --- a/lib/nodes/socket.cpp +++ b/lib/nodes/socket.cpp @@ -5,27 +5,27 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include #include +#include +#include #include +#include +#include #include #include -#include -#include #include -#include +#include #include +#include #ifdef WITH_SOCKET_LAYER_ETH - #include +#include #endif // WITH_SOCKET_LAYER_ETH #ifdef WITH_NETEM - #include - #include +#include +#include #endif // WITH_NETEM using namespace villas; @@ -34,554 +34,556 @@ using namespace villas::node; using namespace villas::kernel; // Forward declartions -static -NodeCompatType p; -static -NodeCompatFactory ncp(&p); +static NodeCompatType p; +static NodeCompatFactory ncp(&p); -int villas::node::socket_type_start(villas::node::SuperNode *sn) -{ +int villas::node::socket_type_start(villas::node::SuperNode *sn) { #ifdef WITH_NETEM - if (sn != nullptr) { - // Gather list of used network interfaces - for (auto *n : ncp.instances) { - auto *nc = dynamic_cast(n); - auto *s = nc->getData(); + if (sn != nullptr) { + // Gather list of used network interfaces + for (auto *n : ncp.instances) { + auto *nc = dynamic_cast(n); + auto *s = nc->getData(); - if (s->layer == SocketLayer::UNIX) - continue; + if (s->layer == SocketLayer::UNIX) + continue; - // Determine outgoing interface - Interface *j = Interface::getEgress((struct sockaddr *) &s->out.saddr, sn); + // Determine outgoing interface + Interface *j = Interface::getEgress((struct sockaddr *)&s->out.saddr, sn); - j->addNode(n); - } - } + j->addNode(n); + } + } #endif // WITH_NETEM - return 0; + return 0; } -int villas::node::socket_init(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::socket_init(NodeCompat *n) { + auto *s = n->getData(); - s->formatter = nullptr; + s->formatter = nullptr; - return 0; + return 0; } -int villas::node::socket_destroy(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::socket_destroy(NodeCompat *n) { + auto *s = n->getData(); - if (s->formatter) - delete s->formatter; + if (s->formatter) + delete s->formatter; - return 0; + return 0; } -char * villas::node::socket_print(NodeCompat *n) -{ - auto *s = n->getData(); - const char *layer = nullptr; - char *buf; +char *villas::node::socket_print(NodeCompat *n) { + auto *s = n->getData(); + const char *layer = nullptr; + char *buf; - switch (s->layer) { - case SocketLayer::UDP: - layer = "udp"; - break; + switch (s->layer) { + case SocketLayer::UDP: + layer = "udp"; + break; - case SocketLayer::IP: - layer = "ip"; - break; + case SocketLayer::IP: + layer = "ip"; + break; - case SocketLayer::ETH: - layer = "eth"; - break; + case SocketLayer::ETH: + layer = "eth"; + break; - case SocketLayer::UNIX: - layer = "unix"; - break; - } + case SocketLayer::UNIX: + layer = "unix"; + break; + } - char *local = socket_print_addr((struct sockaddr *) &s->in.saddr); - char *remote = socket_print_addr((struct sockaddr *) &s->out.saddr); + char *local = socket_print_addr((struct sockaddr *)&s->in.saddr); + char *remote = socket_print_addr((struct sockaddr *)&s->out.saddr); - buf = strf("layer=%s, in.address=%s, out.address=%s", layer, local, remote); + buf = strf("layer=%s, in.address=%s, out.address=%s", layer, local, remote); - if (s->multicast.enabled) { - char group[INET_ADDRSTRLEN]; - char interface[INET_ADDRSTRLEN]; + if (s->multicast.enabled) { + char group[INET_ADDRSTRLEN]; + char interface[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &s->multicast.mreq.imr_multiaddr, group, sizeof(group)); - inet_ntop(AF_INET, &s->multicast.mreq.imr_interface, interface, sizeof(interface)); + inet_ntop(AF_INET, &s->multicast.mreq.imr_multiaddr, group, sizeof(group)); + inet_ntop(AF_INET, &s->multicast.mreq.imr_interface, interface, + sizeof(interface)); - strcatf(&buf, ", in.multicast.enabled=%s", s->multicast.enabled ? "yes" : "no"); - strcatf(&buf, ", in.multicast.loop=%s", s->multicast.loop ? "yes" : "no"); - strcatf(&buf, ", in.multicast.group=%s", group); - strcatf(&buf, ", in.multicast.interface=%s", s->multicast.mreq.imr_interface.s_addr == INADDR_ANY ? "any" : interface); - strcatf(&buf, ", in.multicast.ttl=%u", s->multicast.ttl); - } + strcatf(&buf, ", in.multicast.enabled=%s", + s->multicast.enabled ? "yes" : "no"); + strcatf(&buf, ", in.multicast.loop=%s", s->multicast.loop ? "yes" : "no"); + strcatf(&buf, ", in.multicast.group=%s", group); + strcatf(&buf, ", in.multicast.interface=%s", + s->multicast.mreq.imr_interface.s_addr == INADDR_ANY ? "any" + : interface); + strcatf(&buf, ", in.multicast.ttl=%u", s->multicast.ttl); + } - free(local); - free(remote); + free(local); + free(remote); - return buf; + return buf; } -int villas::node::socket_check(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::socket_check(NodeCompat *n) { + auto *s = n->getData(); - // Some checks on the addresses - if (s->layer != SocketLayer::UNIX) { - if (s->in.saddr.sa.sa_family != s->out.saddr.sa.sa_family) - throw RuntimeError("Address families of local and remote must match!"); - } + // Some checks on the addresses + if (s->layer != SocketLayer::UNIX) { + if (s->in.saddr.sa.sa_family != s->out.saddr.sa.sa_family) + throw RuntimeError("Address families of local and remote must match!"); + } - if (s->layer == SocketLayer::IP) { - if (ntohs(s->in.saddr.sin.sin_port) != ntohs(s->out.saddr.sin.sin_port)) - throw RuntimeError("IP protocol numbers of local and remote must match!"); - } + if (s->layer == SocketLayer::IP) { + if (ntohs(s->in.saddr.sin.sin_port) != ntohs(s->out.saddr.sin.sin_port)) + throw RuntimeError("IP protocol numbers of local and remote must match!"); + } #ifdef WITH_SOCKET_LAYER_ETH - else if (s->layer == SocketLayer::ETH) { - if (ntohs(s->in.saddr.sll.sll_protocol) != ntohs(s->out.saddr.sll.sll_protocol)) - throw RuntimeError("Ethertypes of local and remote must match!"); + else if (s->layer == SocketLayer::ETH) { + if (ntohs(s->in.saddr.sll.sll_protocol) != + ntohs(s->out.saddr.sll.sll_protocol)) + throw RuntimeError("Ethertypes of local and remote must match!"); - if (ntohs(s->in.saddr.sll.sll_protocol) <= 0x5DC) - throw RuntimeError("Ethertype must be large than {} or it is interpreted as an IEEE802.3 length field!", 0x5DC); - } + if (ntohs(s->in.saddr.sll.sll_protocol) <= 0x5DC) + throw RuntimeError("Ethertype must be large than {} or it is interpreted " + "as an IEEE802.3 length field!", + 0x5DC); + } #endif // WITH_SOCKET_LAYER_ETH - if (s->multicast.enabled) { - if (s->in.saddr.sa.sa_family != AF_INET) - throw RuntimeError("Multicast is only supported by IPv4"); + if (s->multicast.enabled) { + if (s->in.saddr.sa.sa_family != AF_INET) + throw RuntimeError("Multicast is only supported by IPv4"); - uint32_t addr = ntohl(s->multicast.mreq.imr_multiaddr.s_addr); - if ((addr >> 28) != 14) - throw RuntimeError("Multicast group address must be within 224.0.0.0/4"); - } + uint32_t addr = ntohl(s->multicast.mreq.imr_multiaddr.s_addr); + if ((addr >> 28) != 14) + throw RuntimeError("Multicast group address must be within 224.0.0.0/4"); + } - return 0; + return 0; } -int villas::node::socket_start(NodeCompat *n) -{ - auto *s = n->getData(); - int ret; +int villas::node::socket_start(NodeCompat *n) { + auto *s = n->getData(); + int ret; - // Initialize IO - s->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + // Initialize IO + s->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - // Create socket - switch (s->layer) { - case SocketLayer::UDP: - s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); - break; + // Create socket + switch (s->layer) { + case SocketLayer::UDP: + s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); + break; - case SocketLayer::IP: - s->sd = socket(s->in.saddr.sa.sa_family, SOCK_RAW, ntohs(s->in.saddr.sin.sin_port)); - break; + case SocketLayer::IP: + s->sd = socket(s->in.saddr.sa.sa_family, SOCK_RAW, + ntohs(s->in.saddr.sin.sin_port)); + break; #ifdef WITH_SOCKET_LAYER_ETH - case SocketLayer::ETH: - s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, s->in.saddr.sll.sll_protocol); - break; + case SocketLayer::ETH: + s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, + s->in.saddr.sll.sll_protocol); + break; #endif // WITH_SOCKET_LAYER_ETH - case SocketLayer::UNIX: - s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, 0); - break; + case SocketLayer::UNIX: + s->sd = socket(s->in.saddr.sa.sa_family, SOCK_DGRAM, 0); + break; - default: - throw RuntimeError("Invalid socket type!"); - } + default: + throw RuntimeError("Invalid socket type!"); + } - if (s->sd < 0) - throw SystemError("Failed to create socket"); + if (s->sd < 0) + throw SystemError("Failed to create socket"); - // Delete Unix domain socket if already existing - if (s->layer == SocketLayer::UNIX) { - ret = unlink(s->in.saddr.sun.sun_path); - if (ret && errno != ENOENT) - return ret; - } + // Delete Unix domain socket if already existing + if (s->layer == SocketLayer::UNIX) { + ret = unlink(s->in.saddr.sun.sun_path); + if (ret && errno != ENOENT) + return ret; + } - // Bind socket for receiving - socklen_t addrlen = 0; - switch(s->in.saddr.ss.ss_family) { - case AF_INET: - addrlen = sizeof(struct sockaddr_in); - break; + // Bind socket for receiving + socklen_t addrlen = 0; + switch (s->in.saddr.ss.ss_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; - case AF_INET6: - addrlen = sizeof(struct sockaddr_in6); - break; + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; - case AF_UNIX: - addrlen = SUN_LEN(&s->in.saddr.sun); - break; + case AF_UNIX: + addrlen = SUN_LEN(&s->in.saddr.sun); + break; #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: - addrlen = sizeof(struct sockaddr_ll); - break; + case AF_PACKET: + addrlen = sizeof(struct sockaddr_ll); + break; #endif // WITH_SOCKET_LAYER_ETH - default: - addrlen = sizeof(s->in.saddr); - } + default: + addrlen = sizeof(s->in.saddr); + } - ret = bind(s->sd, (struct sockaddr *) &s->in.saddr, addrlen); - if (ret < 0) - throw SystemError("Failed to bind socket"); + ret = bind(s->sd, (struct sockaddr *)&s->in.saddr, addrlen); + if (ret < 0) + throw SystemError("Failed to bind socket"); - if (s->multicast.enabled) { - ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_LOOP, &s->multicast.loop, sizeof(s->multicast.loop)); - if (ret) - throw SystemError("Failed to set multicast loop option"); + if (s->multicast.enabled) { + ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_LOOP, &s->multicast.loop, + sizeof(s->multicast.loop)); + if (ret) + throw SystemError("Failed to set multicast loop option"); - ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_TTL, &s->multicast.ttl, sizeof(s->multicast.ttl)); - if (ret) - throw SystemError("Failed to set multicast ttl option"); + ret = setsockopt(s->sd, IPPROTO_IP, IP_MULTICAST_TTL, &s->multicast.ttl, + sizeof(s->multicast.ttl)); + if (ret) + throw SystemError("Failed to set multicast ttl option"); - ret = setsockopt(s->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &s->multicast.mreq, sizeof(s->multicast.mreq)); - if (ret) - throw SystemError("Failed to join multicast group"); - } + ret = setsockopt(s->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &s->multicast.mreq, + sizeof(s->multicast.mreq)); + if (ret) + throw SystemError("Failed to join multicast group"); + } - // Set socket priority, QoS or TOS IP options - int prio; - switch (s->layer) { - case SocketLayer::UDP: - case SocketLayer::IP: - prio = IPTOS_LOWDELAY; - if (setsockopt(s->sd, IPPROTO_IP, IP_TOS, &prio, sizeof(prio))) - throw SystemError("Failed to set type of service (QoS)"); - else - n->logger->debug("Set QoS/TOS IP option to {:#x}", prio); - break; + // Set socket priority, QoS or TOS IP options + int prio; + switch (s->layer) { + case SocketLayer::UDP: + case SocketLayer::IP: + prio = IPTOS_LOWDELAY; + if (setsockopt(s->sd, IPPROTO_IP, IP_TOS, &prio, sizeof(prio))) + throw SystemError("Failed to set type of service (QoS)"); + else + n->logger->debug("Set QoS/TOS IP option to {:#x}", prio); + break; - default: + default: #ifdef __linux__ - prio = SOCKET_PRIO; - if (setsockopt(s->sd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) - throw SystemError("Failed to set socket priority"); - else - n->logger->debug("Set socket priority to {}", prio); - break; + prio = SOCKET_PRIO; + if (setsockopt(s->sd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) + throw SystemError("Failed to set socket priority"); + else + n->logger->debug("Set socket priority to {}", prio); + break; #else - { } + { + } #endif // __linux__ - } + } - s->out.buflen = SOCKET_INITIAL_BUFFER_LEN; - s->out.buf = new char[s->out.buflen]; - if (!s->out.buf) - throw MemoryAllocationError(); + s->out.buflen = SOCKET_INITIAL_BUFFER_LEN; + s->out.buf = new char[s->out.buflen]; + if (!s->out.buf) + throw MemoryAllocationError(); - s->in.buflen = SOCKET_INITIAL_BUFFER_LEN; - s->in.buf = new char[s->in.buflen]; - if (!s->in.buf) - throw MemoryAllocationError(); + s->in.buflen = SOCKET_INITIAL_BUFFER_LEN; + s->in.buf = new char[s->in.buflen]; + if (!s->in.buf) + throw MemoryAllocationError(); - return 0; + return 0; } -int villas::node::socket_reverse(NodeCompat *n) -{ - auto *s = n->getData(); - union sockaddr_union tmp; +int villas::node::socket_reverse(NodeCompat *n) { + auto *s = n->getData(); + union sockaddr_union tmp; - tmp = s->in.saddr; - s->in.saddr = s->out.saddr; - s->out.saddr = tmp; + tmp = s->in.saddr; + s->in.saddr = s->out.saddr; + s->out.saddr = tmp; - return 0; + return 0; } -int villas::node::socket_stop(NodeCompat *n) -{ - int ret; - auto *s = n->getData(); +int villas::node::socket_stop(NodeCompat *n) { + int ret; + auto *s = n->getData(); - if (s->multicast.enabled) { - ret = setsockopt(s->sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &s->multicast.mreq, sizeof(s->multicast.mreq)); - if (ret) - throw SystemError("Failed to leave multicast group"); - } + if (s->multicast.enabled) { + ret = setsockopt(s->sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &s->multicast.mreq, + sizeof(s->multicast.mreq)); + if (ret) + throw SystemError("Failed to leave multicast group"); + } - if (s->sd >= 0) { - ret = close(s->sd); - if (ret) - return ret; - } + if (s->sd >= 0) { + ret = close(s->sd); + if (ret) + return ret; + } - delete[] s->in.buf; - delete[] s->out.buf; + delete[] s->in.buf; + delete[] s->out.buf; - return 0; + return 0; } -int villas::node::socket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *s = n->getData(); +int villas::node::socket_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *s = n->getData(); - char *ptr; - ssize_t bytes; - size_t rbytes; + char *ptr; + ssize_t bytes; + size_t rbytes; - union sockaddr_union src; - socklen_t srclen = sizeof(src); + union sockaddr_union src; + socklen_t srclen = sizeof(src); - // Receive next sample - bytes = recvfrom(s->sd, s->in.buf, s->in.buflen, 0, &src.sa, &srclen); - if (bytes < 0) { - if (errno == EINTR) - return -1; + // Receive next sample + bytes = recvfrom(s->sd, s->in.buf, s->in.buflen, 0, &src.sa, &srclen); + if (bytes < 0) { + if (errno == EINTR) + return -1; - throw SystemError("Failed recvfrom()"); - } - else if (bytes == 0) - return 0; + throw SystemError("Failed recvfrom()"); + } else if (bytes == 0) + return 0; - ptr = s->in.buf; + ptr = s->in.buf; - // Strip IP header from packet - if (s->layer == SocketLayer::IP) { - struct ip *iphdr = (struct ip *) ptr; + // Strip IP header from packet + if (s->layer == SocketLayer::IP) { + struct ip *iphdr = (struct ip *)ptr; - bytes -= iphdr->ip_hl * 4; - ptr += iphdr->ip_hl * 4; - } + bytes -= iphdr->ip_hl * 4; + ptr += iphdr->ip_hl * 4; + } - /* SOCK_RAW IP sockets to not provide the IP protocol number via recvmsg() + /* SOCK_RAW IP sockets to not provide the IP protocol number via recvmsg() * So we simply set it ourself. */ - if (s->layer == SocketLayer::IP) { - switch (src.sa.sa_family) { - case AF_INET: - src.sin.sin_port = s->out.saddr.sin.sin_port; - break; + if (s->layer == SocketLayer::IP) { + switch (src.sa.sa_family) { + case AF_INET: + src.sin.sin_port = s->out.saddr.sin.sin_port; + break; - case AF_INET6: - src.sin6.sin6_port = s->out.saddr.sin6.sin6_port; - break; - } - } + case AF_INET6: + src.sin6.sin6_port = s->out.saddr.sin6.sin6_port; + break; + } + } - if (s->verify_source && socket_compare_addr(&src.sa, &s->out.saddr.sa) != 0) { - char *buf = socket_print_addr((struct sockaddr *) &src); - n->logger->warn("Received packet from unauthorized source: {}", buf); - free(buf); + if (s->verify_source && socket_compare_addr(&src.sa, &s->out.saddr.sa) != 0) { + char *buf = socket_print_addr((struct sockaddr *)&src); + n->logger->warn("Received packet from unauthorized source: {}", buf); + free(buf); - return 0; - } + return 0; + } - ret = s->formatter->sscan(ptr, bytes, &rbytes, smps, cnt); - if (ret < 0 || (size_t) bytes != rbytes) - n->logger->warn("Received invalid packet: ret={}, bytes={}, rbytes={}", ret, bytes, rbytes); + ret = s->formatter->sscan(ptr, bytes, &rbytes, smps, cnt); + if (ret < 0 || (size_t)bytes != rbytes) + n->logger->warn("Received invalid packet: ret={}, bytes={}, rbytes={}", ret, + bytes, rbytes); - return ret; + return ret; } -int villas::node::socket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *s = n->getData(); +int villas::node::socket_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *s = n->getData(); - int ret; - ssize_t bytes; - size_t wbytes; + int ret; + ssize_t bytes; + size_t wbytes; -retry: ret = s->formatter->sprint(s->out.buf, s->out.buflen, &wbytes, smps, cnt); - if (ret < 0) { - n->logger->warn("Failed to format payload: reason={}", ret); - return ret; - } +retry: + ret = s->formatter->sprint(s->out.buf, s->out.buflen, &wbytes, smps, cnt); + if (ret < 0) { + n->logger->warn("Failed to format payload: reason={}", ret); + return ret; + } - if (wbytes == 0) { - n->logger->warn("Failed to format payload: wbytes={}", wbytes); - return -1; - } + if (wbytes == 0) { + n->logger->warn("Failed to format payload: wbytes={}", wbytes); + return -1; + } - if (wbytes > s->out.buflen) { - s->out.buflen = wbytes; + if (wbytes > s->out.buflen) { + s->out.buflen = wbytes; - delete[] s->out.buf; - s->out.buf = new char[s->out.buflen]; - if (!s->out.buf) - throw MemoryAllocationError(); + delete[] s->out.buf; + s->out.buf = new char[s->out.buflen]; + if (!s->out.buf) + throw MemoryAllocationError(); - goto retry; - } + goto retry; + } - // Send message - socklen_t addrlen = 0; - switch(s->in.saddr.ss.ss_family) { - case AF_INET: - addrlen = sizeof(struct sockaddr_in); - break; + // Send message + socklen_t addrlen = 0; + switch (s->in.saddr.ss.ss_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; - case AF_INET6: - addrlen = sizeof(struct sockaddr_in6); - break; + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; - case AF_UNIX: - addrlen = SUN_LEN(&s->out.saddr.sun); - break; + case AF_UNIX: + addrlen = SUN_LEN(&s->out.saddr.sun); + break; #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: - addrlen = sizeof(struct sockaddr_ll); - break; + case AF_PACKET: + addrlen = sizeof(struct sockaddr_ll); + break; #endif // WITH_SOCKET_LAYER_ETH - default: - addrlen = sizeof(s->in.saddr); - } + default: + addrlen = sizeof(s->in.saddr); + } -retry2: bytes = sendto(s->sd, s->out.buf, wbytes, 0, (struct sockaddr *) &s->out.saddr, addrlen); - if (bytes < 0) { - if ((errno == EPERM) || - (errno == ENOENT && s->layer == SocketLayer::UNIX)) - n->logger->warn("Failed sendto(): {}", strerror(errno)); - else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { - n->logger->warn("Blocking sendto()"); - goto retry2; - } - else - n->logger->warn("Failed sendto(): {}", strerror(errno)); - } - else if ((size_t) bytes < wbytes) - n->logger->warn("Partial sendto()"); +retry2: + bytes = sendto(s->sd, s->out.buf, wbytes, 0, (struct sockaddr *)&s->out.saddr, + addrlen); + if (bytes < 0) { + if ((errno == EPERM) || (errno == ENOENT && s->layer == SocketLayer::UNIX)) + n->logger->warn("Failed sendto(): {}", strerror(errno)); + else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + n->logger->warn("Blocking sendto()"); + goto retry2; + } else + n->logger->warn("Failed sendto(): {}", strerror(errno)); + } else if ((size_t)bytes < wbytes) + n->logger->warn("Partial sendto()"); - return cnt; + return cnt; } -int villas::node::socket_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *s = n->getData(); +int villas::node::socket_parse(NodeCompat *n, json_t *json) { + int ret; + auto *s = n->getData(); - const char *local, *remote; - const char *layer = nullptr; + const char *local, *remote; + const char *layer = nullptr; - json_error_t err; - json_t *json_multicast = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_multicast = nullptr; + json_t *json_format = nullptr; - // Default values - s->layer = SocketLayer::UDP; - s->verify_source = 0; + // Default values + s->layer = SocketLayer::UDP; + s->verify_source = 0; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: o, s: { s: s }, s: { s: s, s?: b, s?: o } }", - "layer", &layer, - "format", &json_format, - "out", - "address", &remote, - "in", - "address", &local, - "verify_source", &s->verify_source, - "multicast", &json_multicast - ); - if (ret) - throw ConfigError(json, err, "node-config-node-socket"); + ret = json_unpack_ex( + json, &err, 0, "{ s?: s, s?: o, s: { s: s }, s: { s: s, s?: b, s?: o } }", + "layer", &layer, "format", &json_format, "out", "address", &remote, "in", + "address", &local, "verify_source", &s->verify_source, "multicast", + &json_multicast); + if (ret) + throw ConfigError(json, err, "node-config-node-socket"); - // Format - if (s->formatter) - delete s->formatter; - s->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); - if (!s->formatter) - throw ConfigError(json_format, "node-config-node-socket-format", "Invalid format configuration"); + // Format + if (s->formatter) + delete s->formatter; + s->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); + if (!s->formatter) + throw ConfigError(json_format, "node-config-node-socket-format", + "Invalid format configuration"); - // IP layer - if (layer) { - if (!strcmp(layer, "ip")) - s->layer = SocketLayer::IP; + // IP layer + if (layer) { + if (!strcmp(layer, "ip")) + s->layer = SocketLayer::IP; #ifdef WITH_SOCKET_LAYER_ETH - else if (!strcmp(layer, "eth")) - s->layer = SocketLayer::ETH; + else if (!strcmp(layer, "eth")) + s->layer = SocketLayer::ETH; #endif // WITH_SOCKET_LAYER_ETH - else if (!strcmp(layer, "udp")) - s->layer = SocketLayer::UDP; - else if (!strcmp(layer, "unix") || !strcmp(layer, "local")) - s->layer = SocketLayer::UNIX; - else - throw SystemError("Invalid layer '{}'", layer); - } + else if (!strcmp(layer, "udp")) + s->layer = SocketLayer::UDP; + else if (!strcmp(layer, "unix") || !strcmp(layer, "local")) + s->layer = SocketLayer::UNIX; + else + throw SystemError("Invalid layer '{}'", layer); + } - ret = socket_parse_address(remote, (struct sockaddr *) &s->out.saddr, s->layer, 0); - if (ret) - throw SystemError("Failed to resolve remote address '{}': {}", remote, gai_strerror(ret)); + ret = socket_parse_address(remote, (struct sockaddr *)&s->out.saddr, s->layer, + 0); + if (ret) + throw SystemError("Failed to resolve remote address '{}': {}", remote, + gai_strerror(ret)); - ret = socket_parse_address(local, (struct sockaddr *) &s->in.saddr, s->layer, AI_PASSIVE); - if (ret) - throw SystemError("Failed to resolve local address '{}': {}", local, gai_strerror(ret)); + ret = socket_parse_address(local, (struct sockaddr *)&s->in.saddr, s->layer, + AI_PASSIVE); + if (ret) + throw SystemError("Failed to resolve local address '{}': {}", local, + gai_strerror(ret)); - if (json_multicast) { - const char *group, *interface = nullptr; + if (json_multicast) { + const char *group, *interface = nullptr; - // Default values - s->multicast.enabled = true; - s->multicast.mreq.imr_interface.s_addr = INADDR_ANY; - s->multicast.loop = 0; - s->multicast.ttl = 255; + // Default values + s->multicast.enabled = true; + s->multicast.mreq.imr_interface.s_addr = INADDR_ANY; + s->multicast.loop = 0; + s->multicast.ttl = 255; - ret = json_unpack_ex(json_multicast, &err, 0, "{ s?: b, s: s, s?: s, s?: b, s?: i }", - "enabled", &s->multicast.enabled, - "group", &group, - "interface", &interface, - "loop", &s->multicast.loop, - "ttl", &s->multicast.ttl - ); - if (ret) - throw ConfigError(json_multicast, err, "node-config-node-socket-multicast", "Failed to parse multicast settings"); + ret = json_unpack_ex( + json_multicast, &err, 0, "{ s?: b, s: s, s?: s, s?: b, s?: i }", + "enabled", &s->multicast.enabled, "group", &group, "interface", + &interface, "loop", &s->multicast.loop, "ttl", &s->multicast.ttl); + if (ret) + throw ConfigError(json_multicast, err, + "node-config-node-socket-multicast", + "Failed to parse multicast settings"); - ret = inet_aton(group, &s->multicast.mreq.imr_multiaddr); - if (!ret) - throw SystemError("Failed to resolve multicast group address '{}'", group); + ret = inet_aton(group, &s->multicast.mreq.imr_multiaddr); + if (!ret) + throw SystemError("Failed to resolve multicast group address '{}'", + group); - if (interface) { - ret = inet_aton(group, &s->multicast.mreq.imr_interface); - if (!ret) - throw SystemError("Failed to resolve multicast interface address '{}'", interface); - } - } + if (interface) { + ret = inet_aton(group, &s->multicast.mreq.imr_interface); + if (!ret) + throw SystemError("Failed to resolve multicast interface address '{}'", + interface); + } + } - return 0; + return 0; } -int villas::node::socket_fds(NodeCompat *n, int fds[]) -{ - auto *s = n->getData(); +int villas::node::socket_fds(NodeCompat *n, int fds[]) { + auto *s = n->getData(); - fds[0] = s->sd; + fds[0] = s->sd; - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "socket"; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "socket"; #ifdef WITH_NETEM - p.description = "BSD network sockets for Ethernet / IP / UDP (libnl3, netem support)"; + p.description = + "BSD network sockets for Ethernet / IP / UDP (libnl3, netem support)"; #else - p.description = "BSD network sockets for Ethernet / IP / UDP"; + p.description = "BSD network sockets for Ethernet / IP / UDP"; #endif - p.vectorize = 0; - p.size = sizeof(struct Socket); - p.type.start = socket_type_start; - p.reverse = socket_reverse; - p.init = socket_init; - p.destroy = socket_destroy; - p.parse = socket_parse; - p.print = socket_print; - p.check = socket_check; - p.start = socket_start; - p.stop = socket_stop; - p.read = socket_read; - p.write = socket_write; - p.poll_fds = socket_fds; - p.netem_fds = socket_fds; + p.vectorize = 0; + p.size = sizeof(struct Socket); + p.type.start = socket_type_start; + p.reverse = socket_reverse; + p.init = socket_init; + p.destroy = socket_destroy; + p.parse = socket_parse; + p.print = socket_print; + p.check = socket_check; + p.start = socket_start; + p.stop = socket_stop; + p.read = socket_read; + p.write = socket_write; + p.poll_fds = socket_fds; + p.netem_fds = socket_fds; } diff --git a/lib/nodes/stats.cpp b/lib/nodes/stats.cpp index 000915f9c..aae148fa2 100644 --- a/lib/nodes/stats.cpp +++ b/lib/nodes/stats.cpp @@ -7,262 +7,250 @@ #include -#include -#include #include #include +#include +#include +#include #include #include -#include #include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -NodeList nodes; // The global list of nodes +static NodeList nodes; // The global list of nodes -int villas::node::stats_node_signal_destroy(struct stats_node_signal *s) -{ - free(s->node_str); +int villas::node::stats_node_signal_destroy(struct stats_node_signal *s) { + free(s->node_str); - return 0; + return 0; } -int villas::node::stats_node_signal_parse(struct stats_node_signal *s, json_t *json) -{ - json_error_t err; +int villas::node::stats_node_signal_parse(struct stats_node_signal *s, + json_t *json) { + json_error_t err; - int ret; - const char *stats; - char *metric, *type, *node, *cpy, *lasts; + int ret; + const char *stats; + char *metric, *type, *node, *cpy, *lasts; - ret = json_unpack_ex(json, &err, 0, "{ s: s }", - "stats", &stats - ); - if (ret) - throw ConfigError(json, err, "node-config-node-stats"); + ret = json_unpack_ex(json, &err, 0, "{ s: s }", "stats", &stats); + if (ret) + throw ConfigError(json, err, "node-config-node-stats"); - cpy = strdup(stats); + cpy = strdup(stats); - node = strtok_r(cpy, ".", &lasts); - if (!node) - goto invalid_format; + node = strtok_r(cpy, ".", &lasts); + if (!node) + goto invalid_format; - metric = strtok_r(nullptr, ".", &lasts); - if (!metric) - goto invalid_format; + metric = strtok_r(nullptr, ".", &lasts); + if (!metric) + goto invalid_format; - type = strtok_r(nullptr, ".", &lasts); - if (!type) - goto invalid_format; + type = strtok_r(nullptr, ".", &lasts); + if (!type) + goto invalid_format; - s->metric = Stats::lookupMetric(metric); - s->type = Stats::lookupType(type); + s->metric = Stats::lookupMetric(metric); + s->type = Stats::lookupType(type); - s->node_str = strdup(node); + s->node_str = strdup(node); - free(cpy); - return 0; + free(cpy); + return 0; invalid_format: - free(cpy); - return -1; + free(cpy); + return -1; } -int villas::node::stats_node_type_start(villas::node::SuperNode *sn) -{ - if (sn == nullptr) - throw RuntimeError("Stats node-type requires super-node"); +int villas::node::stats_node_type_start(villas::node::SuperNode *sn) { + if (sn == nullptr) + throw RuntimeError("Stats node-type requires super-node"); - nodes = sn->getNodes(); + nodes = sn->getNodes(); - return 0; + return 0; } -int villas::node::stats_node_prepare(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::stats_node_prepare(NodeCompat *n) { + auto *s = n->getData(); - assert(n->getInputSignals(false)->size() == 0); + assert(n->getInputSignals(false)->size() == 0); - // Generate signal list - for (size_t i = 0; i < list_length(&s->signals); i++) { - struct stats_node_signal *stats_sig = (struct stats_node_signal *) list_at(&s->signals, i); + // Generate signal list + for (size_t i = 0; i < list_length(&s->signals); i++) { + struct stats_node_signal *stats_sig = + (struct stats_node_signal *)list_at(&s->signals, i); - const char *metric = Stats::metrics[stats_sig->metric].name; - const char *type = Stats::types[stats_sig->type].name; + const char *metric = Stats::metrics[stats_sig->metric].name; + const char *type = Stats::types[stats_sig->type].name; - auto name = fmt::format("{}.{}.{}", stats_sig->node_str, metric, type); + auto name = fmt::format("{}.{}.{}", stats_sig->node_str, metric, type); - auto sig = std::make_shared(name.c_str(), - Stats::metrics[stats_sig->metric].unit, - Stats::types[stats_sig->type].signal_type); + auto sig = std::make_shared( + name.c_str(), Stats::metrics[stats_sig->metric].unit, + Stats::types[stats_sig->type].signal_type); - n->in.signals->push_back(sig); - } + n->in.signals->push_back(sig); + } - return 0; + return 0; } -int villas::node::stats_node_start(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::stats_node_start(NodeCompat *n) { + auto *s = n->getData(); - s->task.setRate(s->rate); + s->task.setRate(s->rate); - for (size_t i = 0; i < list_length(&s->signals); i++) { - struct stats_node_signal *stats_sig = (struct stats_node_signal *) list_at(&s->signals, i); + for (size_t i = 0; i < list_length(&s->signals); i++) { + struct stats_node_signal *stats_sig = + (struct stats_node_signal *)list_at(&s->signals, i); - stats_sig->node = nodes.lookup(stats_sig->node_str); - if (!stats_sig->node) - throw ConfigError(n->getConfig(), "node-config-node-stats-node", "Invalid reference node {}", stats_sig->node_str); - } + stats_sig->node = nodes.lookup(stats_sig->node_str); + if (!stats_sig->node) + throw ConfigError(n->getConfig(), "node-config-node-stats-node", + "Invalid reference node {}", stats_sig->node_str); + } - return 0; + return 0; } -int villas::node::stats_node_stop(NodeCompat *n) -{ - auto *s = n->getData(); +int villas::node::stats_node_stop(NodeCompat *n) { + auto *s = n->getData(); - s->task.stop(); + s->task.stop(); - return 0; + return 0; } -char * villas::node::stats_node_print(NodeCompat *n) -{ - auto *s = n->getData(); +char *villas::node::stats_node_print(NodeCompat *n) { + auto *s = n->getData(); - return strf("rate=%f", s->rate); + return strf("rate=%f", s->rate); } -int villas::node::stats_node_init(NodeCompat *n) -{ - int ret; - auto *s = n->getData(); +int villas::node::stats_node_init(NodeCompat *n) { + int ret; + auto *s = n->getData(); - new (&s->task) Task(CLOCK_MONOTONIC); + new (&s->task) Task(CLOCK_MONOTONIC); - ret = list_init(&s->signals); - if (ret) - return ret; + ret = list_init(&s->signals); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::stats_node_destroy(NodeCompat *n) -{ - int ret; - auto *s = n->getData(); +int villas::node::stats_node_destroy(NodeCompat *n) { + int ret; + auto *s = n->getData(); - s->task.~Task(); + s->task.~Task(); - ret = list_destroy(&s->signals, (dtor_cb_t) stats_node_signal_destroy, true); - if (ret) - return ret; + ret = list_destroy(&s->signals, (dtor_cb_t)stats_node_signal_destroy, true); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::stats_node_parse(NodeCompat *n, json_t *json) -{ - auto *s = n->getData(); +int villas::node::stats_node_parse(NodeCompat *n, json_t *json) { + auto *s = n->getData(); - int ret; - size_t i; - json_error_t err; - json_t *json_signals, *json_signal; + int ret; + size_t i; + json_error_t err; + json_t *json_signals, *json_signal; - ret = json_unpack_ex(json, &err, 0, "{ s: F, s: { s: o } }", - "rate", &s->rate, - "in", - "signals", &json_signals - ); - if (ret) - throw ConfigError(json, err, "node-config-node-stats"); + ret = json_unpack_ex(json, &err, 0, "{ s: F, s: { s: o } }", "rate", &s->rate, + "in", "signals", &json_signals); + if (ret) + throw ConfigError(json, err, "node-config-node-stats"); - if (s->rate <= 0) - throw ConfigError(json, "node-config-node-stats-rate", "Setting 'rate' must be positive"); + if (s->rate <= 0) + throw ConfigError(json, "node-config-node-stats-rate", + "Setting 'rate' must be positive"); - if (!json_is_array(json_signals)) - throw ConfigError(json, "node-config-node-stats-in-signals", "Setting 'in.signals' must be an array"); + if (!json_is_array(json_signals)) + throw ConfigError(json, "node-config-node-stats-in-signals", + "Setting 'in.signals' must be an array"); - json_array_foreach(json_signals, i, json_signal) { - auto *stats_sig = new struct stats_node_signal; - if (!stats_sig) - throw MemoryAllocationError(); + json_array_foreach(json_signals, i, json_signal) { + auto *stats_sig = new struct stats_node_signal; + if (!stats_sig) + throw MemoryAllocationError(); - ret = stats_node_signal_parse(stats_sig, json_signal); - if (ret) - throw ConfigError(json_signal, "node-config-node-stats-signals", "Failed to parse statistics signal definition"); + ret = stats_node_signal_parse(stats_sig, json_signal); + if (ret) + throw ConfigError(json_signal, "node-config-node-stats-signals", + "Failed to parse statistics signal definition"); - list_push(&s->signals, stats_sig); - } + list_push(&s->signals, stats_sig); + } - return 0; + return 0; } -int villas::node::stats_node_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *s = n->getData(); +int villas::node::stats_node_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *s = n->getData(); - if (!cnt) - return 0; + if (!cnt) + return 0; - s->task.wait(); + s->task.wait(); - unsigned len = MIN(list_length(&s->signals), smps[0]->capacity); + unsigned len = MIN(list_length(&s->signals), smps[0]->capacity); - for (size_t i = 0; i < len; i++) { - struct stats_node_signal *sig = (struct stats_node_signal *) list_at(&s->signals, i); + for (size_t i = 0; i < len; i++) { + struct stats_node_signal *sig = + (struct stats_node_signal *)list_at(&s->signals, i); - auto st = sig->node->getStats(); - if (!st) - return -1; + auto st = sig->node->getStats(); + if (!st) + return -1; - smps[0]->data[i] = st->getValue(sig->metric, sig->type); - } + smps[0]->data[i] = st->getValue(sig->metric, sig->type); + } - smps[0]->length = len; - smps[0]->flags = (int) SampleFlags::HAS_DATA; - smps[0]->signals = n->getInputSignals(false); + smps[0]->length = len; + smps[0]->flags = (int)SampleFlags::HAS_DATA; + smps[0]->signals = n->getInputSignals(false); - return 1; + return 1; } -int villas::node::stats_node_poll_fds(NodeCompat *n, int fds[]) -{ - auto *s = n->getData(); +int villas::node::stats_node_poll_fds(NodeCompat *n, int fds[]) { + auto *s = n->getData(); - fds[0] = s->task.getFD(); + fds[0] = s->task.getFD(); - return 0; + return 0; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "stats"; - p.description = "Send statistics to another node"; - p.vectorize = 1; - p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; - p.size = sizeof(struct stats_node); - p.type.start = stats_node_type_start; - p.parse = stats_node_parse; - p.init = stats_node_init; - p.destroy = stats_node_destroy; - p.print = stats_node_print; - p.prepare = stats_node_prepare; - p.start = stats_node_start; - p.stop = stats_node_stop; - p.read = stats_node_read; - p.poll_fds = stats_node_poll_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "stats"; + p.description = "Send statistics to another node"; + p.vectorize = 1; + p.flags = (int)NodeFactory::Flags::PROVIDES_SIGNALS; + p.size = sizeof(struct stats_node); + p.type.start = stats_node_type_start; + p.parse = stats_node_parse; + p.init = stats_node_init; + p.destroy = stats_node_destroy; + p.print = stats_node_print; + p.prepare = stats_node_prepare; + p.start = stats_node_start; + p.stop = stats_node_stop; + p.read = stats_node_read; + p.poll_fds = stats_node_poll_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/temper.cpp b/lib/nodes/temper.cpp index fcf890d0c..da0138908 100644 --- a/lib/nodes/temper.cpp +++ b/lib/nodes/temper.cpp @@ -16,407 +16,390 @@ * https://github.com/shakemid/pcsensor */ +#include #include #include -#include #include using namespace villas; using namespace villas::utils; using namespace villas::node; -static -Logger logger; +static Logger logger; -static -std::list devices; +static std::list devices; -static -struct libusb_context *context; +static struct libusb_context *context; // Forward declartions -static -NodeCompatType p; +static NodeCompatType p; -TEMPerDevice::TEMPerDevice(struct libusb_device *dev) : - usb::Device(dev), - scale(1.0), - offset(0.0), - timeout(5000) -{ - int ret = libusb_get_device_descriptor(dev, &desc); - if (ret != LIBUSB_SUCCESS) - throw RuntimeError("Could not get USB device descriptor: {}", libusb_strerror((enum libusb_error) ret)); +TEMPerDevice::TEMPerDevice(struct libusb_device *dev) + : usb::Device(dev), scale(1.0), offset(0.0), timeout(5000) { + int ret = libusb_get_device_descriptor(dev, &desc); + if (ret != LIBUSB_SUCCESS) + throw RuntimeError("Could not get USB device descriptor: {}", + libusb_strerror((enum libusb_error)ret)); } -void TEMPerDevice::open(bool reset) -{ - int ret; +void TEMPerDevice::open(bool reset) { + int ret; - usb::detach(handle, 0x00); - usb::detach(handle, 0x01); + usb::detach(handle, 0x00); + usb::detach(handle, 0x01); - if (reset) - libusb_reset_device(handle); + if (reset) + libusb_reset_device(handle); - ret = libusb_set_configuration(handle, 0x01); - if (ret < 0) - throw RuntimeError("Could not set configuration 1"); + ret = libusb_set_configuration(handle, 0x01); + if (ret < 0) + throw RuntimeError("Could not set configuration 1"); - ret = libusb_claim_interface(handle, 0x00); - if (ret < 0) - throw RuntimeError("Could not claim interface. Error: {}", ret); + ret = libusb_claim_interface(handle, 0x00); + if (ret < 0) + throw RuntimeError("Could not claim interface. Error: {}", ret); - ret = libusb_claim_interface(handle, 0x01); - if (ret < 0) - throw RuntimeError("Could not claim interface. Error: {}", ret); + ret = libusb_claim_interface(handle, 0x01); + if (ret < 0) + throw RuntimeError("Could not claim interface. Error: {}", ret); } -void TEMPerDevice::close() -{ - libusb_release_interface(handle, 0x00); - libusb_release_interface(handle, 0x01); +void TEMPerDevice::close() { + libusb_release_interface(handle, 0x00); + libusb_release_interface(handle, 0x01); - libusb_close(handle); + libusb_close(handle); } -void TEMPerDevice::read(struct Sample *smp) -{ - unsigned char answer[8]; - float temp[2]; - int i = 0, al, ret; +void TEMPerDevice::read(struct Sample *smp) { + unsigned char answer[8]; + float temp[2]; + int i = 0, al, ret; - // Read from device - unsigned char question[sizeof(question_temperature)]; - memcpy(question, question_temperature, sizeof(question_temperature)); + // Read from device + unsigned char question[sizeof(question_temperature)]; + memcpy(question, question_temperature, sizeof(question_temperature)); - ret = libusb_control_transfer(handle, 0x21, 0x09, 0x0200, 0x01, question, 8, timeout); - if (ret < 0) - throw SystemError("USB control write failed: {}", ret); + ret = libusb_control_transfer(handle, 0x21, 0x09, 0x0200, 0x01, question, 8, + timeout); + if (ret < 0) + throw SystemError("USB control write failed: {}", ret); - memset(answer, 0, 8); + memset(answer, 0, 8); - ret = libusb_interrupt_transfer(handle, 0x82, answer, 8, &al, timeout); - if (al != 8) - throw SystemError("USB interrupt read failed: {}", ret); + ret = libusb_interrupt_transfer(handle, 0x82, answer, 8, &al, timeout); + if (al != 8) + throw SystemError("USB interrupt read failed: {}", ret); - decode(answer, temp); + decode(answer, temp); - // Temperature 1 - smp->data[i++].f = temp[0]; + // Temperature 1 + smp->data[i++].f = temp[0]; - // Temperature 2 - if (getNumSensors() == 2) - smp->data[i++].f = temp[1]; + // Temperature 2 + if (getNumSensors() == 2) + smp->data[i++].f = temp[1]; - // Humidity - if (hasHumiditySensor()) - smp->data[i++].f = temp[1]; + // Humidity + if (hasHumiditySensor()) + smp->data[i++].f = temp[1]; - smp->flags = 0; - smp->length = i; - smp->flags |= (int) SampleFlags::HAS_DATA; + smp->flags = 0; + smp->length = i; + smp->flags |= (int)SampleFlags::HAS_DATA; } // Thanks to https://github.com/edorfaus/TEMPered -void TEMPer1Device::decode(unsigned char *answer, float *temp) -{ - int buf; +void TEMPer1Device::decode(unsigned char *answer, float *temp) { + int buf; - // Temperature Celsius internal - buf = ((signed char) answer[2] << 8) + (answer[3] & 0xFF); - temp[0] = buf * (125.0 / 32000.0); - temp[0] *= scale; - temp[0] += offset; + // Temperature Celsius internal + buf = ((signed char)answer[2] << 8) + (answer[3] & 0xFF); + temp[0] = buf * (125.0 / 32000.0); + temp[0] *= scale; + temp[0] += offset; } -void TEMPer2Device::decode(unsigned char *answer, float *temp) -{ - int buf; +void TEMPer2Device::decode(unsigned char *answer, float *temp) { + int buf; - TEMPer1Device::decode(answer, temp); + TEMPer1Device::decode(answer, temp); - // Temperature Celsius external - buf = ((signed char) answer[4] << 8) + (answer[5] & 0xFF); - temp[1] = buf * (125.0 / 32000.0); - temp[1] *= scale; - temp[1] += offset; + // Temperature Celsius external + buf = ((signed char)answer[4] << 8) + (answer[5] & 0xFF); + temp[1] = buf * (125.0 / 32000.0); + temp[1] *= scale; + temp[1] += offset; } -void TEMPerHUMDevice::decode(unsigned char *answer, float *temp) -{ - int buf; +void TEMPerHUMDevice::decode(unsigned char *answer, float *temp) { + int buf; - // Temperature Celsius - buf = ((signed char) answer[2] << 8) + (answer[3] & 0xFF); - temp[0] = -39.7 + 0.01 * buf; - temp[0] *= scale; - temp[0] += offset; + // Temperature Celsius + buf = ((signed char)answer[2] << 8) + (answer[3] & 0xFF); + temp[0] = -39.7 + 0.01 * buf; + temp[0] *= scale; + temp[0] += offset; - // Relative Humidity - buf = ((signed char) answer[4] << 8) + (answer[5] & 0xFF); - temp[1] = -2.0468 + 0.0367 * buf - 1.5955e-6 * buf * buf; - temp[1] = (temp[0] - 25) * (0.01 + 0.00008 * buf) + temp[1]; + // Relative Humidity + buf = ((signed char)answer[4] << 8) + (answer[5] & 0xFF); + temp[1] = -2.0468 + 0.0367 * buf - 1.5955e-6 * buf * buf; + temp[1] = (temp[0] - 25) * (0.01 + 0.00008 * buf) + temp[1]; - if (temp[1] < 0) - temp[1] = 0; + if (temp[1] < 0) + temp[1] = 0; - if (temp[1] > 99) - temp[1] = 100; + if (temp[1] > 99) + temp[1] = 100; } -TEMPerDevice * TEMPerDevice::make(struct libusb_device *dev) -{ - if (TEMPerHUMDevice::match(dev)) - return new TEMPerHUMDevice(dev); - else if (TEMPer2Device::match(dev)) - return new TEMPer2Device(dev); - else if (TEMPer1Device::match(dev)) - return new TEMPer1Device(dev); - else - return nullptr; +TEMPerDevice *TEMPerDevice::make(struct libusb_device *dev) { + if (TEMPerHUMDevice::match(dev)) + return new TEMPerHUMDevice(dev); + else if (TEMPer2Device::match(dev)) + return new TEMPer2Device(dev); + else if (TEMPer1Device::match(dev)) + return new TEMPer1Device(dev); + else + return nullptr; } -bool TEMPer1Device::match(struct libusb_device *dev) -{ - struct libusb_device_descriptor desc; - int ret = libusb_get_device_descriptor(dev, &desc); - if (ret < 0) { - logging.get("node:temper")->warn("Could not get USB device descriptor: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } +bool TEMPer1Device::match(struct libusb_device *dev) { + struct libusb_device_descriptor desc; + int ret = libusb_get_device_descriptor(dev, &desc); + if (ret < 0) { + logging.get("node:temper") + ->warn("Could not get USB device descriptor: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - return desc.idProduct == 0x7401 && - desc.idVendor == 0x0c45; + return desc.idProduct == 0x7401 && desc.idVendor == 0x0c45; } -bool TEMPer2Device::match(struct libusb_device *dev) -{ - int ret; - struct libusb_device_handle *handle; - unsigned char product[256]; +bool TEMPer2Device::match(struct libusb_device *dev) { + int ret; + struct libusb_device_handle *handle; + unsigned char product[256]; - struct libusb_device_descriptor desc; - ret = libusb_get_device_descriptor(dev, &desc); - if (ret < 0) { - logging.get("node:temper")->warn("Could not get USB device descriptor: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } + struct libusb_device_descriptor desc; + ret = libusb_get_device_descriptor(dev, &desc); + if (ret < 0) { + logging.get("node:temper") + ->warn("Could not get USB device descriptor: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - ret = libusb_open(dev, &handle); - if (ret < 0) { - logging.get("node:temper")->warn("Failed to open USB device: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } + ret = libusb_open(dev, &handle); + if (ret < 0) { + logging.get("node:temper") + ->warn("Failed to open USB device: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, product, sizeof(product)); - if (ret < 0) { - logging.get("node:temper")->warn("Could not get USB string descriptor: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } + ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, product, + sizeof(product)); + if (ret < 0) { + logging.get("node:temper") + ->warn("Could not get USB string descriptor: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - libusb_close(handle); + libusb_close(handle); - return TEMPer1Device::match(dev) && getName() == (char *) product; + return TEMPer1Device::match(dev) && getName() == (char *)product; } -bool TEMPerHUMDevice::match(struct libusb_device *dev) -{ - struct libusb_device_descriptor desc; - int ret = libusb_get_device_descriptor(dev, &desc); - if (ret < 0) { - logging.get("node:temper")->warn("Could not get USB device descriptor: {}", libusb_strerror((enum libusb_error) ret)); - return false; - } +bool TEMPerHUMDevice::match(struct libusb_device *dev) { + struct libusb_device_descriptor desc; + int ret = libusb_get_device_descriptor(dev, &desc); + if (ret < 0) { + logging.get("node:temper") + ->warn("Could not get USB device descriptor: {}", + libusb_strerror((enum libusb_error)ret)); + return false; + } - return desc.idProduct == 0x7401 && - desc.idVendor == 0x7402; + return desc.idProduct == 0x7401 && desc.idVendor == 0x7402; } -int villas::node::temper_type_start(villas::node::SuperNode *sn) -{ - context = usb::get_context(); +int villas::node::temper_type_start(villas::node::SuperNode *sn) { + context = usb::get_context(); - logger = logging.get("node:temper"); + logger = logging.get("node:temper"); - // Enumerate temper devices - devices.clear(); - struct libusb_device **devs; + // Enumerate temper devices + devices.clear(); + struct libusb_device **devs; - int cnt = libusb_get_device_list(context, &devs); - for (int i = 0; i < cnt; i++) { - auto *dev = TEMPerDevice::make(devs[i]); + int cnt = libusb_get_device_list(context, &devs); + for (int i = 0; i < cnt; i++) { + auto *dev = TEMPerDevice::make(devs[i]); - logger->debug("Found Temper device at bus={03d}, port={03d}, vendor_id={04x}, product_id={04x}, manufacturer={}, product={}, serial={}", - dev->getBus(), dev->getPort(), - dev->getDescriptor().idVendor, dev->getDescriptor().idProduct, - dev->getManufacturer(), - dev->getProduct(), - dev->getSerial()); + logger->debug( + "Found Temper device at bus={03d}, port={03d}, vendor_id={04x}, " + "product_id={04x}, manufacturer={}, product={}, serial={}", + dev->getBus(), dev->getPort(), dev->getDescriptor().idVendor, + dev->getDescriptor().idProduct, dev->getManufacturer(), + dev->getProduct(), dev->getSerial()); - devices.push_back(dev); - } + devices.push_back(dev); + } - libusb_free_device_list(devs, 1); + libusb_free_device_list(devs, 1); - return 0; + return 0; } -int villas::node::temper_type_stop() -{ - usb::deinit_context(context); +int villas::node::temper_type_stop() { + usb::deinit_context(context); - return 0; + return 0; } -int villas::node::temper_init(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_init(NodeCompat *n) { + auto *t = n->getData(); - t->calibration.scale = 1.0; - t->calibration.offset = 0.0; + t->calibration.scale = 1.0; + t->calibration.offset = 0.0; - t->filter.bus = -1; - t->filter.port = -1; - t->filter.vendor_id = -1; - t->filter.product_id = -1; + t->filter.bus = -1; + t->filter.port = -1; + t->filter.vendor_id = -1; + t->filter.product_id = -1; - t->device = nullptr; + t->device = nullptr; - return 0; + return 0; } -int villas::node::temper_destroy(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_destroy(NodeCompat *n) { + auto *t = n->getData(); - if (t->device) - delete t->device; + if (t->device) + delete t->device; - return 0; + return 0; } -int villas::node::temper_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *t = n->getData(); +int villas::node::temper_parse(NodeCompat *n, json_t *json) { + int ret; + auto *t = n->getData(); - json_error_t err; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: F, s?: F}, s?: i, s?: i }", - "calibration", - "scale", &t->calibration.scale, - "offset", &t->calibration.offset, + ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: F, s?: F}, s?: i, s?: i }", + "calibration", "scale", &t->calibration.scale, "offset", + &t->calibration.offset, - "bus", &t->filter.bus, - "port", &t->filter.port - ); - if (ret) - throw ConfigError(json, err, "node-config-node-temper"); + "bus", &t->filter.bus, "port", &t->filter.port); + if (ret) + throw ConfigError(json, err, "node-config-node-temper"); - return 0; + return 0; } -char * villas::node::temper_print(NodeCompat *n) -{ - auto *t = n->getData(); +char *villas::node::temper_print(NodeCompat *n) { + auto *t = n->getData(); - return strf("product=%s, manufacturer=%s, serial=%s humidity=%s, temperature=%d, usb.vendor_id=%#x, usb.product_id=%#x, calibration.scale=%f, calibration.offset=%f", - t->device->getProduct(), t->device->getManufacturer(), t->device->getSerial(), - t->device->hasHumiditySensor() ? "yes" : "no", - t->device->getNumSensors(), - t->device->getDescriptor().idVendor, - t->device->getDescriptor().idProduct, - t->calibration.scale, - t->calibration.offset - ); + return strf("product=%s, manufacturer=%s, serial=%s humidity=%s, " + "temperature=%d, usb.vendor_id=%#x, usb.product_id=%#x, " + "calibration.scale=%f, calibration.offset=%f", + t->device->getProduct(), t->device->getManufacturer(), + t->device->getSerial(), + t->device->hasHumiditySensor() ? "yes" : "no", + t->device->getNumSensors(), t->device->getDescriptor().idVendor, + t->device->getDescriptor().idProduct, t->calibration.scale, + t->calibration.offset); } -int villas::node::temper_prepare(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_prepare(NodeCompat *n) { + auto *t = n->getData(); - // Find matching USB device - t->device = nullptr; - for (auto *dev : devices) { - if (dev->match(&t->filter)) { - t->device = dev; - break; - } - } + // Find matching USB device + t->device = nullptr; + for (auto *dev : devices) { + if (dev->match(&t->filter)) { + t->device = dev; + break; + } + } - if (t->device == nullptr) - throw RuntimeError("No matching TEMPer USB device found!"); + if (t->device == nullptr) + throw RuntimeError("No matching TEMPer USB device found!"); - // Create signal list - assert(n->getInputSignals(false)->size() == 0); + // Create signal list + assert(n->getInputSignals(false)->size() == 0); - // Temperature 1 - auto sig1 = std::make_shared(t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", SignalType::FLOAT); - n->in.signals->push_back(sig1); + // Temperature 1 + auto sig1 = std::make_shared( + t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", + SignalType::FLOAT); + n->in.signals->push_back(sig1); - // Temperature 2 - if (t->device->getNumSensors() == 2) { - auto sig2 = std::make_shared(t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", SignalType::FLOAT); - n->in.signals->push_back(sig2); - } + // Temperature 2 + if (t->device->getNumSensors() == 2) { + auto sig2 = std::make_shared( + t->device->getNumSensors() == 2 ? "temp_int" : "temp", "°C", + SignalType::FLOAT); + n->in.signals->push_back(sig2); + } - // Humidity - if (t->device->hasHumiditySensor()) { - auto sig3 = std::make_shared("humidity", "%", SignalType::FLOAT); - n->in.signals->push_back(sig3); - } + // Humidity + if (t->device->hasHumiditySensor()) { + auto sig3 = std::make_shared("humidity", "%", SignalType::FLOAT); + n->in.signals->push_back(sig3); + } - return 0; + return 0; } -int villas::node::temper_start(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_start(NodeCompat *n) { + auto *t = n->getData(); - t->device->open(); + t->device->open(); - return 0; + return 0; } -int villas::node::temper_stop(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::temper_stop(NodeCompat *n) { + auto *t = n->getData(); - t->device->close(); + t->device->close(); - return 0; + return 0; } -int villas::node::temper_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *t = n->getData(); +int villas::node::temper_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *t = n->getData(); - assert(cnt == 1); + assert(cnt == 1); - t->device->read(smps[0]); + t->device->read(smps[0]); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "temper"; - p.description = "An temper for staring new node-type implementations"; - p.vectorize = 1; - p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; - p.size = sizeof(struct temper); - p.type.start = temper_type_start; - p.type.stop = temper_type_stop; - p.init = temper_init; - p.destroy = temper_destroy; - p.prepare = temper_prepare; - p.parse = temper_parse; - p.print = temper_print; - p.start = temper_start; - p.stop = temper_stop; - p.read = temper_read; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "temper"; + p.description = "An temper for staring new node-type implementations"; + p.vectorize = 1; + p.flags = (int)NodeFactory::Flags::PROVIDES_SIGNALS; + p.size = sizeof(struct temper); + p.type.start = temper_type_start; + p.type.stop = temper_type_stop; + p.init = temper_init; + p.destroy = temper_destroy; + p.prepare = temper_prepare; + p.parse = temper_parse; + p.print = temper_print; + p.start = temper_start; + p.stop = temper_stop; + p.read = temper_read; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/test_rtt.cpp b/lib/nodes/test_rtt.cpp index bb5ea6223..551ed6650 100644 --- a/lib/nodes/test_rtt.cpp +++ b/lib/nodes/test_rtt.cpp @@ -7,433 +7,427 @@ #include #include -#include #include +#include -#include -#include -#include -#include -#include #include +#include #include #include +#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -NodeCompatType p; +static NodeCompatType p; -static -int test_rtt_case_start(NodeCompat *n, int id) -{ - auto *t = n->getData(); - struct test_rtt_case *c = (struct test_rtt_case *) list_at(&t->cases, id); +static int test_rtt_case_start(NodeCompat *n, int id) { + auto *t = n->getData(); + struct test_rtt_case *c = (struct test_rtt_case *)list_at(&t->cases, id); - n->logger->info("Starting case #{}: filename={}, rate={}, values={}, limit={}", t->current, c->filename_formatted, c->rate, c->values, c->limit); + n->logger->info( + "Starting case #{}: filename={}, rate={}, values={}, limit={}", + t->current, c->filename_formatted, c->rate, c->values, c->limit); - // Open file - t->stream = fopen(c->filename_formatted, "a+"); - if (!t->stream) - return -1; + // Open file + t->stream = fopen(c->filename_formatted, "a+"); + if (!t->stream) + return -1; - // Start timer - t->task.setRate(c->rate); + // Start timer + t->task.setRate(c->rate); - t->counter = 0; - t->current = id; + t->counter = 0; + t->current = id; - return 0; + return 0; } -static -int test_rtt_case_stop(NodeCompat *n, int id) -{ - int ret; - auto *t = n->getData(); +static int test_rtt_case_stop(NodeCompat *n, int id) { + int ret; + auto *t = n->getData(); - // Stop timer - t->task.stop(); + // Stop timer + t->task.stop(); - ret = fclose(t->stream); - if (ret) - throw SystemError("Failed to close file"); + ret = fclose(t->stream); + if (ret) + throw SystemError("Failed to close file"); - n->logger->info("Stopping case #{}", id); + n->logger->info("Stopping case #{}", id); - return 0; + return 0; } -static -int test_rtt_case_destroy(struct test_rtt_case *c) -{ - if (c->filename) - free(c->filename); +static int test_rtt_case_destroy(struct test_rtt_case *c) { + if (c->filename) + free(c->filename); - if (c->filename_formatted) - free(c->filename_formatted); + if (c->filename_formatted) + free(c->filename_formatted); - return 0; + return 0; } -int villas::node::test_rtt_prepare(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::test_rtt_prepare(NodeCompat *n) { + auto *t = n->getData(); - unsigned max_values = 0; + unsigned max_values = 0; - // Take current for time for test case prefix - time_t ts = time(nullptr); - struct tm tm; - gmtime_r(&ts, &tm); + // Take current for time for test case prefix + time_t ts = time(nullptr); + struct tm tm; + gmtime_r(&ts, &tm); - for (size_t i = 0; i < list_length(&t->cases); i++) { - struct test_rtt_case *c = (struct test_rtt_case *) list_at(&t->cases, i); + for (size_t i = 0; i < list_length(&t->cases); i++) { + struct test_rtt_case *c = (struct test_rtt_case *)list_at(&t->cases, i); - if (c->values > max_values) - max_values = c->values; + if (c->values > max_values) + max_values = c->values; - c->filename_formatted = new char[NAME_MAX]; - if (!c->filename_formatted) - throw MemoryAllocationError(); + c->filename_formatted = new char[NAME_MAX]; + if (!c->filename_formatted) + throw MemoryAllocationError(); - strftime(c->filename_formatted, NAME_MAX, c->filename, &tm); - } + strftime(c->filename_formatted, NAME_MAX, c->filename, &tm); + } - n->in.signals = std::make_shared(max_values, SignalType::FLOAT); + n->in.signals = std::make_shared(max_values, SignalType::FLOAT); - return 0; + return 0; } -int villas::node::test_rtt_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *t = n->getData(); +int villas::node::test_rtt_parse(NodeCompat *n, json_t *json) { + int ret; + auto *t = n->getData(); - const char *output = "."; - const char *prefix = nullptr; + const char *output = "."; + const char *prefix = nullptr; - std::vector rates; - std::vector values; + std::vector rates; + std::vector values; - size_t i; - json_t *json_cases, *json_case, *json_val, *json_format = nullptr; - json_t *json_rates = nullptr, *json_values = nullptr; - json_error_t err; + size_t i; + json_t *json_cases, *json_case, *json_val, *json_format = nullptr; + json_t *json_rates = nullptr, *json_values = nullptr; + json_error_t err; - t->cooldown = 0; + t->cooldown = 0; - // Generate list of test cases - ret = list_init(&t->cases); - if (ret) - return ret; + // Generate list of test cases + ret = list_init(&t->cases); + if (ret) + return ret; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o, s?: F, s: o }", - "prefix", &prefix, - "output", &output, - "format", &json_format, - "cooldown", &t->cooldown, - "cases", &json_cases - ); - if (ret) - throw ConfigError(json, err, "node-config-node-test-rtt"); + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o, s?: F, s: o }", + "prefix", &prefix, "output", &output, "format", + &json_format, "cooldown", &t->cooldown, "cases", + &json_cases); + if (ret) + throw ConfigError(json, err, "node-config-node-test-rtt"); - t->output = strdup(output); - t->prefix = strdup(prefix ? prefix : n->getNameShort().c_str()); + t->output = strdup(output); + t->prefix = strdup(prefix ? prefix : n->getNameShort().c_str()); - // Initialize IO module - if (!json_format) - json_format = json_string("villas.binary"); + // Initialize IO module + if (!json_format) + json_format = json_string("villas.binary"); - t->formatter = FormatFactory::make(json_format); - if (!t->formatter) - throw ConfigError(json, "node-config-node-test-rtt-format", "Invalid value for setting 'format'"); + t->formatter = FormatFactory::make(json_format); + if (!t->formatter) + throw ConfigError(json, "node-config-node-test-rtt-format", + "Invalid value for setting 'format'"); - // Construct List of test cases - if (!json_is_array(json_cases)) - throw ConfigError(json_cases, "node-config-node-test-rtt-format", "The 'cases' setting must be an array."); + // Construct List of test cases + if (!json_is_array(json_cases)) + throw ConfigError(json_cases, "node-config-node-test-rtt-format", + "The 'cases' setting must be an array."); - json_array_foreach(json_cases, i, json_case) { - int limit = -1; - double duration = -1; // in secs + json_array_foreach(json_cases, i, json_case) { + int limit = -1; + double duration = -1; // in secs - ret = json_unpack_ex(json_case, &err, 0, "{ s: o, s: o, s?: i, s?: F }", - "rates", &json_rates, - "values", &json_values, - "limit", &limit, - "duration", &duration - ); + ret = json_unpack_ex(json_case, &err, 0, "{ s: o, s: o, s?: i, s?: F }", + "rates", &json_rates, "values", &json_values, "limit", + &limit, "duration", &duration); - if (limit > 0 && duration > 0) - throw ConfigError(json_case, "node-config-node-test-rtt-duration", "The settings 'duration' and 'limit' must be used exclusively"); + if (limit > 0 && duration > 0) + throw ConfigError( + json_case, "node-config-node-test-rtt-duration", + "The settings 'duration' and 'limit' must be used exclusively"); - if (!json_is_array(json_rates) && !json_is_number(json_rates)) - throw ConfigError(json_case, "node-config-node-test-rtt-rates", "The 'rates' setting must be a real or an array of real numbers"); + if (!json_is_array(json_rates) && !json_is_number(json_rates)) + throw ConfigError( + json_case, "node-config-node-test-rtt-rates", + "The 'rates' setting must be a real or an array of real numbers"); - if (!json_is_array(json_values) && !json_is_integer(json_values)) - throw ConfigError(json_case, "node-config-node-test-rtt-values", "The 'values' setting must be an integer or an array of integers"); + if (!json_is_array(json_values) && !json_is_integer(json_values)) + throw ConfigError( + json_case, "node-config-node-test-rtt-values", + "The 'values' setting must be an integer or an array of integers"); - values.clear(); - rates.clear(); + values.clear(); + rates.clear(); - if (json_is_array(json_rates)) { - size_t j; - json_array_foreach(json_rates, j, json_val) { - if (!json_is_number(json_val)) - throw ConfigError(json_val, "node-config-node-test-rtt-rates", "The 'rates' setting must be an array of real numbers"); + if (json_is_array(json_rates)) { + size_t j; + json_array_foreach(json_rates, j, json_val) { + if (!json_is_number(json_val)) + throw ConfigError( + json_val, "node-config-node-test-rtt-rates", + "The 'rates' setting must be an array of real numbers"); - rates.push_back(json_integer_value(json_val)); - } - } - else - rates.push_back(json_number_value(json_rates)); + rates.push_back(json_integer_value(json_val)); + } + } else + rates.push_back(json_number_value(json_rates)); - if (json_is_array(json_values)) { - size_t j; - json_array_foreach(json_values, j, json_val) { - if (!json_is_integer(json_val)) - throw ConfigError(json_val, "node-config-node-test-rtt-values", "The 'values' setting must be an array of integers"); + if (json_is_array(json_values)) { + size_t j; + json_array_foreach(json_values, j, json_val) { + if (!json_is_integer(json_val)) + throw ConfigError( + json_val, "node-config-node-test-rtt-values", + "The 'values' setting must be an array of integers"); - values.push_back(json_integer_value(json_val)); - } - } - else - values.push_back(json_integer_value(json_values)); + values.push_back(json_integer_value(json_val)); + } + } else + values.push_back(json_integer_value(json_values)); - for (int rate : rates) { - for (int value : values) { - auto *c = new struct test_rtt_case; - if (!c) - throw MemoryAllocationError(); + for (int rate : rates) { + for (int value : values) { + auto *c = new struct test_rtt_case; + if (!c) + throw MemoryAllocationError(); - c->filename = nullptr; - c->filename_formatted = nullptr; - c->node = n; + c->filename = nullptr; + c->filename_formatted = nullptr; + c->node = n; - c->rate = rate; - c->values = value; + c->rate = rate; + c->values = value; - if (limit > 0) - c->limit = limit; - else if (duration > 0) - c->limit = duration * c->rate; - else - c->limit = 1000; // default value + if (limit > 0) + c->limit = limit; + else if (duration > 0) + c->limit = duration * c->rate; + else + c->limit = 1000; // default value - c->filename = strf("%s/%s_values%d_rate%.0f.log", t->output, t->prefix, c->values, c->rate); + c->filename = strf("%s/%s_values%d_rate%.0f.log", t->output, t->prefix, + c->values, c->rate); - list_push(&t->cases, c); - } - } - } + list_push(&t->cases, c); + } + } + } - return 0; + return 0; } -int villas::node::test_rtt_init(NodeCompat *n) -{ - auto *t = n->getData(); +int villas::node::test_rtt_init(NodeCompat *n) { + auto *t = n->getData(); - new (&t->task) Task(CLOCK_MONOTONIC); + new (&t->task) Task(CLOCK_MONOTONIC); - t->formatter = nullptr; + t->formatter = nullptr; - return 0; + return 0; } -int villas::node::test_rtt_destroy(NodeCompat *n) -{ - int ret; - auto *t = n->getData(); +int villas::node::test_rtt_destroy(NodeCompat *n) { + int ret; + auto *t = n->getData(); - ret = list_destroy(&t->cases, (dtor_cb_t) test_rtt_case_destroy, true); - if (ret) - return ret; + ret = list_destroy(&t->cases, (dtor_cb_t)test_rtt_case_destroy, true); + if (ret) + return ret; - t->task.~Task(); + t->task.~Task(); - if (t->output) - free(t->output); + if (t->output) + free(t->output); - if (t->prefix) - free(t->prefix); + if (t->prefix) + free(t->prefix); - if (t->formatter) - delete t->formatter; + if (t->formatter) + delete t->formatter; - return 0; + return 0; } -char * villas::node::test_rtt_print(NodeCompat *n) -{ - auto *t = n->getData(); +char *villas::node::test_rtt_print(NodeCompat *n) { + auto *t = n->getData(); - return strf("output=%s, prefix=%s, cooldown=%f, #cases=%zu", t->output, t->prefix, t->cooldown, list_length(&t->cases)); + return strf("output=%s, prefix=%s, cooldown=%f, #cases=%zu", t->output, + t->prefix, t->cooldown, list_length(&t->cases)); } -int villas::node::test_rtt_start(NodeCompat *n) -{ - int ret; - struct stat st; - auto *t = n->getData(); - struct test_rtt_case *c = (struct test_rtt_case *) list_first(&t->cases); +int villas::node::test_rtt_start(NodeCompat *n) { + int ret; + struct stat st; + auto *t = n->getData(); + struct test_rtt_case *c = (struct test_rtt_case *)list_first(&t->cases); - // Create folder for results if not present - ret = stat(t->output, &st); - if (ret || !S_ISDIR(st.st_mode)) { - ret = mkdir(t->output, 0777); - if (ret) - throw SystemError("Failed to create output directory: {}", t->output); - } + // Create folder for results if not present + ret = stat(t->output, &st); + if (ret || !S_ISDIR(st.st_mode)) { + ret = mkdir(t->output, 0777); + if (ret) + throw SystemError("Failed to create output directory: {}", t->output); + } - t->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_DATA); + t->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_DATA); - t->task.setRate(c->rate); + t->task.setRate(c->rate); - t->current = -1; - t->counter = -1; + t->current = -1; + t->counter = -1; - return 0; + return 0; } -int villas::node::test_rtt_stop(NodeCompat *n) -{ - int ret; - auto *t = n->getData(); +int villas::node::test_rtt_stop(NodeCompat *n) { + int ret; + auto *t = n->getData(); - if (t->counter >= 0) { - ret = test_rtt_case_stop(n, t->current); - if (ret) - return ret; - } + if (t->counter >= 0) { + ret = test_rtt_case_stop(n, t->current); + if (ret) + return ret; + } - delete t->formatter; + delete t->formatter; - return 0; + return 0; } -int villas::node::test_rtt_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - unsigned i; - uint64_t steps; +int villas::node::test_rtt_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + unsigned i; + uint64_t steps; - auto *t = n->getData(); + auto *t = n->getData(); - // Handle start/stop of new cases - if (t->counter == -1) { - if (t->current < 0) { - t->current = 0; - } - else { - ret = test_rtt_case_stop(n, t->current); - if (ret) - return ret; + // Handle start/stop of new cases + if (t->counter == -1) { + if (t->current < 0) { + t->current = 0; + } else { + ret = test_rtt_case_stop(n, t->current); + if (ret) + return ret; - t->current++; - } + t->current++; + } - if ((unsigned) t->current >= list_length(&t->cases)) { - n->logger->info("This was the last case."); + if ((unsigned)t->current >= list_length(&t->cases)) { + n->logger->info("This was the last case."); - n->setState(State::STOPPING); + n->setState(State::STOPPING); - return -1; - } - else { - ret = test_rtt_case_start(n, t->current); - if (ret) - return ret; - } - } + return -1; + } else { + ret = test_rtt_case_start(n, t->current); + if (ret) + return ret; + } + } - struct test_rtt_case *c = (struct test_rtt_case *) list_at(&t->cases, t->current); + struct test_rtt_case *c = + (struct test_rtt_case *)list_at(&t->cases, t->current); - // Wait - steps = t->task.wait(); - if (steps > 1) - n->logger->warn("Skipped {} steps", steps - 1); + // Wait + steps = t->task.wait(); + if (steps > 1) + n->logger->warn("Skipped {} steps", steps - 1); - if ((unsigned) t->counter >= c->limit) { - n->logger->info("Stopping case #{}", t->current); + if ((unsigned)t->counter >= c->limit) { + n->logger->info("Stopping case #{}", t->current); - t->counter = -1; + t->counter = -1; - if (t->cooldown) { - n->logger->info("Entering cooldown phase. Waiting {} seconds...", t->cooldown); - t->task.setTimeout(t->cooldown); - } + if (t->cooldown) { + n->logger->info("Entering cooldown phase. Waiting {} seconds...", + t->cooldown); + t->task.setTimeout(t->cooldown); + } - return 0; - } - else { - struct timespec now = time_now(); + return 0; + } else { + struct timespec now = time_now(); - // Prepare samples - for (i = 0; i < cnt; i++) { - smps[i]->length = c->values; - smps[i]->sequence = t->counter; - smps[i]->ts.origin = now; - smps[i]->flags = (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN; - smps[i]->signals = n->getInputSignals(false); + // Prepare samples + for (i = 0; i < cnt; i++) { + smps[i]->length = c->values; + smps[i]->sequence = t->counter; + smps[i]->ts.origin = now; + smps[i]->flags = (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_TS_ORIGIN; + smps[i]->signals = n->getInputSignals(false); - t->counter++; - } + t->counter++; + } - return i; - } + return i; + } } -int villas::node::test_rtt_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *t = n->getData(); +int villas::node::test_rtt_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *t = n->getData(); - if (t->current < 0) - return 0; + if (t->current < 0) + return 0; - struct test_rtt_case *c = (struct test_rtt_case *) list_at(&t->cases, t->current); + struct test_rtt_case *c = + (struct test_rtt_case *)list_at(&t->cases, t->current); - unsigned i; - for (i = 0; i < cnt; i++) { - if (smps[i]->length != c->values) { - n->logger->warn("Discarding invalid sample due to mismatching length: expecting={}, has={}", c->values, smps[i]->length); - continue; - } + unsigned i; + for (i = 0; i < cnt; i++) { + if (smps[i]->length != c->values) { + n->logger->warn("Discarding invalid sample due to mismatching length: " + "expecting={}, has={}", + c->values, smps[i]->length); + continue; + } - t->formatter->print(t->stream, smps[i]); - } + t->formatter->print(t->stream, smps[i]); + } - return i; + return i; } -int villas::node::test_rtt_poll_fds(NodeCompat *n, int fds[]) -{ - auto *t = n->getData(); +int villas::node::test_rtt_poll_fds(NodeCompat *n, int fds[]) { + auto *t = n->getData(); - fds[0] = t->task.getFD(); + fds[0] = t->task.getFD(); - return 1; + return 1; } -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "test_rtt"; - p.description = "Test round-trip time with loopback"; - p.vectorize = 0; - p.flags = (int) NodeFactory::Flags::PROVIDES_SIGNALS; - p.size = sizeof(struct test_rtt); - p.parse = test_rtt_parse; - p.prepare = test_rtt_prepare; - p.init = test_rtt_init; - p.destroy = test_rtt_destroy; - p.print = test_rtt_print; - p.start = test_rtt_start; - p.stop = test_rtt_stop; - p.read = test_rtt_read; - p.write = test_rtt_write; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "test_rtt"; + p.description = "Test round-trip time with loopback"; + p.vectorize = 0; + p.flags = (int)NodeFactory::Flags::PROVIDES_SIGNALS; + p.size = sizeof(struct test_rtt); + p.parse = test_rtt_parse; + p.prepare = test_rtt_prepare; + p.init = test_rtt_init; + p.destroy = test_rtt_destroy; + p.print = test_rtt_print; + p.start = test_rtt_start; + p.stop = test_rtt_stop; + p.read = test_rtt_read; + p.write = test_rtt_write; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/uldaq.cpp b/lib/nodes/uldaq.cpp index f0b9a9916..ad442eecd 100644 --- a/lib/nodes/uldaq.cpp +++ b/lib/nodes/uldaq.cpp @@ -9,637 +9,620 @@ #include #include -#include -#include #include #include +#include +#include #include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -unsigned num_devs = ULDAQ_MAX_DEV_COUNT; -static -DaqDeviceDescriptor descriptors[ULDAQ_MAX_DEV_COUNT]; +static unsigned num_devs = ULDAQ_MAX_DEV_COUNT; +static DaqDeviceDescriptor descriptors[ULDAQ_MAX_DEV_COUNT]; -static -const struct { - const char *name; - AiInputMode mode; -} input_modes[] = { - { "differential", AI_DIFFERENTIAL }, - { "single-ended", AI_SINGLE_ENDED }, - { "pseudo-differential", AI_PSEUDO_DIFFERENTIAL } -}; +static const struct { + const char *name; + AiInputMode mode; +} input_modes[] = {{"differential", AI_DIFFERENTIAL}, + {"single-ended", AI_SINGLE_ENDED}, + {"pseudo-differential", AI_PSEUDO_DIFFERENTIAL}}; -static -const struct { - const char *name; - DaqDeviceInterface interface; -} interface_types[] = { - { "usb", USB_IFC }, - { "bluetooth", BLUETOOTH_IFC }, - { "ethernet", ETHERNET_IFC }, - { "any", ANY_IFC } -}; +static const struct { + const char *name; + DaqDeviceInterface interface; +} interface_types[] = {{"usb", USB_IFC}, + {"bluetooth", BLUETOOTH_IFC}, + {"ethernet", ETHERNET_IFC}, + {"any", ANY_IFC}}; -static -const struct { - const char *name; - Range range; - float min, max; -} ranges[] = { - { "bipolar-60", BIP60VOLTS, -60.0, +60.0 }, - { "bipolar-60", BIP60VOLTS, -60.0, +60.0 }, - { "bipolar-30", BIP30VOLTS, -30.0, +30.0 }, - { "bipolar-15", BIP15VOLTS, -15.0, +15.0 }, - { "bipolar-20", BIP20VOLTS, -20.0, +20.0 }, - { "bipolar-10", BIP10VOLTS, -10.0, +10.0 }, - { "bipolar-5", BIP5VOLTS, -5.0, +5.0 }, - { "bipolar-4", BIP4VOLTS, -4.0, +4.0 }, - { "bipolar-2.5", BIP2PT5VOLTS, -2.5, +2.5 }, - { "bipolar-2", BIP2VOLTS, -2.0, +2.0 }, - { "bipolar-1.25", BIP1PT25VOLTS, -1.25, +1.25 }, - { "bipolar-1", BIP1VOLTS, -1.0, +1.0 }, - { "bipolar-0.625", BIPPT625VOLTS, -0.625, +0.625 }, - { "bipolar-0.5", BIPPT5VOLTS, -0.5, +0.5 }, - { "bipolar-0.25", BIPPT25VOLTS, -0.25, +0.25 }, - { "bipolar-0.125", BIPPT125VOLTS, -0.125, +0.125 }, - { "bipolar-0.2", BIPPT2VOLTS, -0.2, +0.2 }, - { "bipolar-0.1", BIPPT1VOLTS, -0.1, +0.1 }, - { "bipolar-0.078", BIPPT078VOLTS, -0.078, +0.078 }, - { "bipolar-0.05", BIPPT05VOLTS, -0.05, +0.05 }, - { "bipolar-0.01", BIPPT01VOLTS, -0.01, +0.01 }, - { "bipolar-0.005", BIPPT005VOLTS, -0.005, +0.005 }, - { "unipolar-60", UNI60VOLTS , 0.0, +60.0 }, - { "unipolar-30", UNI30VOLTS , 0.0, +30.0 }, - { "unipolar-15", UNI15VOLTS , 0.0, +15.0 }, - { "unipolar-20", UNI20VOLTS , 0.0, +20.0 }, - { "unipolar-10", UNI10VOLTS , 0.0, +10.0 }, - { "unipolar-5", UNI5VOLTS , 0.0, +5.0 }, - { "unipolar-4", UNI4VOLTS , 0.0, +4.0 }, - { "unipolar-2.5", UNI2PT5VOLTS, 0.0, +2.5 }, - { "unipolar-2", UNI2VOLTS , 0.0, +2.0 }, - { "unipolar-1.25", UNI1PT25VOLTS, 0.0, +1.25 }, - { "unipolar-1", UNI1VOLTS , 0.0, +1.0 }, - { "unipolar-0.625", UNIPT625VOLTS, 0.0, +0.625 }, - { "unipolar-0.5", UNIPT5VOLTS, 0.0, +0.5 }, - { "unipolar-0.25", UNIPT25VOLTS, 0.0, +0.25 }, - { "unipolar-0.125", UNIPT125VOLTS, 0.0, +0.125 }, - { "unipolar-0.2", UNIPT2VOLTS, 0.0, +0.2 }, - { "unipolar-0.1", UNIPT1VOLTS, 0.0, +0.1 }, - { "unipolar-0.078", UNIPT078VOLTS, 0.0, +0.078 }, - { "unipolar-0.05", UNIPT05VOLTS, 0.0, +0.05 }, - { "unipolar-0.01", UNIPT01VOLTS, 0.0, +0.01 }, - { "unipolar-0.005", UNIPT005VOLTS, 0.0, +0.005 } -}; +static const struct { + const char *name; + Range range; + float min, max; +} ranges[] = {{"bipolar-60", BIP60VOLTS, -60.0, +60.0}, + {"bipolar-60", BIP60VOLTS, -60.0, +60.0}, + {"bipolar-30", BIP30VOLTS, -30.0, +30.0}, + {"bipolar-15", BIP15VOLTS, -15.0, +15.0}, + {"bipolar-20", BIP20VOLTS, -20.0, +20.0}, + {"bipolar-10", BIP10VOLTS, -10.0, +10.0}, + {"bipolar-5", BIP5VOLTS, -5.0, +5.0}, + {"bipolar-4", BIP4VOLTS, -4.0, +4.0}, + {"bipolar-2.5", BIP2PT5VOLTS, -2.5, +2.5}, + {"bipolar-2", BIP2VOLTS, -2.0, +2.0}, + {"bipolar-1.25", BIP1PT25VOLTS, -1.25, +1.25}, + {"bipolar-1", BIP1VOLTS, -1.0, +1.0}, + {"bipolar-0.625", BIPPT625VOLTS, -0.625, +0.625}, + {"bipolar-0.5", BIPPT5VOLTS, -0.5, +0.5}, + {"bipolar-0.25", BIPPT25VOLTS, -0.25, +0.25}, + {"bipolar-0.125", BIPPT125VOLTS, -0.125, +0.125}, + {"bipolar-0.2", BIPPT2VOLTS, -0.2, +0.2}, + {"bipolar-0.1", BIPPT1VOLTS, -0.1, +0.1}, + {"bipolar-0.078", BIPPT078VOLTS, -0.078, +0.078}, + {"bipolar-0.05", BIPPT05VOLTS, -0.05, +0.05}, + {"bipolar-0.01", BIPPT01VOLTS, -0.01, +0.01}, + {"bipolar-0.005", BIPPT005VOLTS, -0.005, +0.005}, + {"unipolar-60", UNI60VOLTS, 0.0, +60.0}, + {"unipolar-30", UNI30VOLTS, 0.0, +30.0}, + {"unipolar-15", UNI15VOLTS, 0.0, +15.0}, + {"unipolar-20", UNI20VOLTS, 0.0, +20.0}, + {"unipolar-10", UNI10VOLTS, 0.0, +10.0}, + {"unipolar-5", UNI5VOLTS, 0.0, +5.0}, + {"unipolar-4", UNI4VOLTS, 0.0, +4.0}, + {"unipolar-2.5", UNI2PT5VOLTS, 0.0, +2.5}, + {"unipolar-2", UNI2VOLTS, 0.0, +2.0}, + {"unipolar-1.25", UNI1PT25VOLTS, 0.0, +1.25}, + {"unipolar-1", UNI1VOLTS, 0.0, +1.0}, + {"unipolar-0.625", UNIPT625VOLTS, 0.0, +0.625}, + {"unipolar-0.5", UNIPT5VOLTS, 0.0, +0.5}, + {"unipolar-0.25", UNIPT25VOLTS, 0.0, +0.25}, + {"unipolar-0.125", UNIPT125VOLTS, 0.0, +0.125}, + {"unipolar-0.2", UNIPT2VOLTS, 0.0, +0.2}, + {"unipolar-0.1", UNIPT1VOLTS, 0.0, +0.1}, + {"unipolar-0.078", UNIPT078VOLTS, 0.0, +0.078}, + {"unipolar-0.05", UNIPT05VOLTS, 0.0, +0.05}, + {"unipolar-0.01", UNIPT01VOLTS, 0.0, +0.01}, + {"unipolar-0.005", UNIPT005VOLTS, 0.0, +0.005}}; -static -AiInputMode uldaq_parse_input_mode(const char *str) -{ - for (unsigned i = 0; i < ARRAY_LEN(input_modes); i++) { - if (!strcmp(input_modes[i].name, str)) - return input_modes[i].mode; - } +static AiInputMode uldaq_parse_input_mode(const char *str) { + for (unsigned i = 0; i < ARRAY_LEN(input_modes); i++) { + if (!strcmp(input_modes[i].name, str)) + return input_modes[i].mode; + } - return (AiInputMode) -1; + return (AiInputMode)-1; } -static -DaqDeviceInterface uldaq_parse_interface_type(const char *str) -{ - for (unsigned i = 0; i < ARRAY_LEN(interface_types); i++) { - if (!strcmp(interface_types[i].name, str)) - return interface_types[i].interface; - } +static DaqDeviceInterface uldaq_parse_interface_type(const char *str) { + for (unsigned i = 0; i < ARRAY_LEN(interface_types); i++) { + if (!strcmp(interface_types[i].name, str)) + return interface_types[i].interface; + } - return (DaqDeviceInterface) -1; + return (DaqDeviceInterface)-1; } -static -const char * uldaq_print_interface_type(DaqDeviceInterface iftype) -{ - for (unsigned i = 0; i < ARRAY_LEN(interface_types); i++) { - if (interface_types[i].interface == iftype) - return interface_types[i].name; - } +static const char *uldaq_print_interface_type(DaqDeviceInterface iftype) { + for (unsigned i = 0; i < ARRAY_LEN(interface_types); i++) { + if (interface_types[i].interface == iftype) + return interface_types[i].name; + } - return nullptr; + return nullptr; } -static -Range uldaq_parse_range(const char *str) -{ - for (unsigned i = 0; i < ARRAY_LEN(ranges); i++) { - if (!strcmp(ranges[i].name, str)) - return ranges[i].range; - } +static Range uldaq_parse_range(const char *str) { + for (unsigned i = 0; i < ARRAY_LEN(ranges); i++) { + if (!strcmp(ranges[i].name, str)) + return ranges[i].range; + } - return (Range) -1; + return (Range)-1; } -static -DaqDeviceDescriptor * uldaq_find_device(struct uldaq *u) { - DaqDeviceDescriptor *d = nullptr; +static DaqDeviceDescriptor *uldaq_find_device(struct uldaq *u) { + DaqDeviceDescriptor *d = nullptr; - if (num_devs == 0) - return nullptr; + if (num_devs == 0) + return nullptr; - if (u->device_interface_type == ANY_IFC && u->device_id == nullptr) - return &descriptors[0]; + if (u->device_interface_type == ANY_IFC && u->device_id == nullptr) + return &descriptors[0]; - for (unsigned i = 0; i < num_devs; i++) { - d = &descriptors[i]; + for (unsigned i = 0; i < num_devs; i++) { + d = &descriptors[i]; - if (u->device_id) { - if (strcmp(u->device_id, d->uniqueId)) - break; - } + if (u->device_id) { + if (strcmp(u->device_id, d->uniqueId)) + break; + } - if (u->device_interface_type != ANY_IFC) { - if (u->device_interface_type != d->devInterface) - break; - } + if (u->device_interface_type != ANY_IFC) { + if (u->device_interface_type != d->devInterface) + break; + } - return d; - } + return d; + } - return nullptr; + return nullptr; } -static -int uldaq_connect(NodeCompat *n) -{ - auto *u = n->getData(); - UlError err; +static int uldaq_connect(NodeCompat *n) { + auto *u = n->getData(); + UlError err; - // Find Matching device - if (!u->device_descriptor) { - u->device_descriptor = uldaq_find_device(u); - if (!u->device_descriptor) - throw RuntimeError("Unable to find a matching device"); - } + // Find Matching device + if (!u->device_descriptor) { + u->device_descriptor = uldaq_find_device(u); + if (!u->device_descriptor) + throw RuntimeError("Unable to find a matching device"); + } - // Get a handle to the DAQ device associated with the first descriptor - if (!u->device_handle) { - u->device_handle = ulCreateDaqDevice(*u->device_descriptor); - if (!u->device_handle) - throw RuntimeError("Unable to create handle for DAQ device"); - } + // Get a handle to the DAQ device associated with the first descriptor + if (!u->device_handle) { + u->device_handle = ulCreateDaqDevice(*u->device_descriptor); + if (!u->device_handle) + throw RuntimeError("Unable to create handle for DAQ device"); + } - // Check if device is already connected - int connected; - err = ulIsDaqDeviceConnected(u->device_handle, &connected); - if (err != ERR_NO_ERROR) - return -1; + // Check if device is already connected + int connected; + err = ulIsDaqDeviceConnected(u->device_handle, &connected); + if (err != ERR_NO_ERROR) + return -1; - // Connect to device - if (!connected) { - err = ulConnectDaqDevice(u->device_handle); - if (err != ERR_NO_ERROR) { - char buf[ERR_MSG_LEN]; - ulGetErrMsg(err, buf); - throw RuntimeError("Failed to connect to DAQ device: {}", buf); - } - } + // Connect to device + if (!connected) { + err = ulConnectDaqDevice(u->device_handle); + if (err != ERR_NO_ERROR) { + char buf[ERR_MSG_LEN]; + ulGetErrMsg(err, buf); + throw RuntimeError("Failed to connect to DAQ device: {}", buf); + } + } - return 0; + return 0; } -int villas::node::uldaq_type_start(villas::node::SuperNode *sn) -{ - UlError err; +int villas::node::uldaq_type_start(villas::node::SuperNode *sn) { + UlError err; - // Get descriptors for all of the available DAQ devices - err = ulGetDaqDeviceInventory(ANY_IFC, descriptors, &num_devs); - if (err != ERR_NO_ERROR) - throw RuntimeError("Failed to retrieve DAQ device list"); + // Get descriptors for all of the available DAQ devices + err = ulGetDaqDeviceInventory(ANY_IFC, descriptors, &num_devs); + if (err != ERR_NO_ERROR) + throw RuntimeError("Failed to retrieve DAQ device list"); - auto logger = logging.get("node:uldaq"); - logger->info("Found {} DAQ devices", num_devs); - for (unsigned i = 0; i < num_devs; i++) { - DaqDeviceDescriptor *desc = &descriptors[i]; + auto logger = logging.get("node:uldaq"); + logger->info("Found {} DAQ devices", num_devs); + for (unsigned i = 0; i < num_devs; i++) { + DaqDeviceDescriptor *desc = &descriptors[i]; - logger->info(" {}: {} {} ({})", i, desc->uniqueId, desc->devString, uldaq_print_interface_type(desc->devInterface)); - } + logger->info(" {}: {} {} ({})", i, desc->uniqueId, desc->devString, + uldaq_print_interface_type(desc->devInterface)); + } - return 0; + return 0; } -int villas::node::uldaq_init(NodeCompat *n) -{ - int ret; - auto *u = n->getData(); +int villas::node::uldaq_init(NodeCompat *n) { + int ret; + auto *u = n->getData(); - u->device_id = nullptr; - u->device_interface_type = ANY_IFC; + u->device_id = nullptr; + u->device_interface_type = ANY_IFC; - u->in.queues = nullptr; - u->in.sample_rate = 1000; - u->in.scan_options = (ScanOption) (SO_DEFAULTIO | SO_CONTINUOUS); - u->in.flags = AINSCAN_FF_DEFAULT; + u->in.queues = nullptr; + u->in.sample_rate = 1000; + u->in.scan_options = (ScanOption)(SO_DEFAULTIO | SO_CONTINUOUS); + u->in.flags = AINSCAN_FF_DEFAULT; - ret = pthread_mutex_init(&u->in.mutex, nullptr); - if (ret) - return ret; + ret = pthread_mutex_init(&u->in.mutex, nullptr); + if (ret) + return ret; - ret = pthread_cond_init(&u->in.cv, nullptr); - if (ret) - return ret; + ret = pthread_cond_init(&u->in.cv, nullptr); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::uldaq_destroy(NodeCompat *n) -{ - int ret; - auto *u = n->getData(); +int villas::node::uldaq_destroy(NodeCompat *n) { + int ret; + auto *u = n->getData(); - if (u->in.queues) - delete[] u->in.queues; + if (u->in.queues) + delete[] u->in.queues; - ret = pthread_mutex_destroy(&u->in.mutex); - if (ret) - return ret; + ret = pthread_mutex_destroy(&u->in.mutex); + if (ret) + return ret; - ret = pthread_cond_destroy(&u->in.cv); - if (ret) - return ret; + ret = pthread_cond_destroy(&u->in.cv); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::uldaq_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *u = n->getData(); +int villas::node::uldaq_parse(NodeCompat *n, json_t *json) { + int ret; + auto *u = n->getData(); - const char *default_range_str = nullptr; - const char *default_input_mode_str = nullptr; - const char *interface_type = nullptr; + const char *default_range_str = nullptr; + const char *default_input_mode_str = nullptr; + const char *interface_type = nullptr; - size_t i; - json_t *json_signals; - json_t *json_signal; - json_error_t err; + size_t i; + json_t *json_signals; + json_t *json_signal; + json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s: { s: o, s: F, s?: s, s?: s } }", - "interface_type", &interface_type, - "device_id", &u->device_id, - "in", - "signals", &json_signals, - "sample_rate", &u->in.sample_rate, - "range", &default_range_str, - "input_mode", &default_input_mode_str - ); - if (ret) - throw ConfigError(json, err, "node-config-node-uldaq"); + ret = json_unpack_ex( + json, &err, 0, "{ s?: s, s?: s, s: { s: o, s: F, s?: s, s?: s } }", + "interface_type", &interface_type, "device_id", &u->device_id, "in", + "signals", &json_signals, "sample_rate", &u->in.sample_rate, "range", + &default_range_str, "input_mode", &default_input_mode_str); + if (ret) + throw ConfigError(json, err, "node-config-node-uldaq"); - if (interface_type) { - int iftype = uldaq_parse_interface_type(interface_type); - if (iftype < 0) - throw ConfigError(json, "node-config-node-uldaq-interface-type", "Invalid interface type: {}", interface_type); + if (interface_type) { + int iftype = uldaq_parse_interface_type(interface_type); + if (iftype < 0) + throw ConfigError(json, "node-config-node-uldaq-interface-type", + "Invalid interface type: {}", interface_type); - u->device_interface_type = (DaqDeviceInterface) iftype; - } + u->device_interface_type = (DaqDeviceInterface)iftype; + } - if (u->in.queues) - delete[] u->in.queues; + if (u->in.queues) + delete[] u->in.queues; - u->in.channel_count = n->getInputSignals(false)->size(); - u->in.queues = new struct AiQueueElement[u->in.channel_count]; - if (!u->in.queues) - throw MemoryAllocationError(); + u->in.channel_count = n->getInputSignals(false)->size(); + u->in.queues = new struct AiQueueElement[u->in.channel_count]; + if (!u->in.queues) + throw MemoryAllocationError(); - json_array_foreach(json_signals, i, json_signal) { - const char *range_str = nullptr, *input_mode_str = nullptr; - int channel = -1, input_mode, range; + json_array_foreach(json_signals, i, json_signal) { + const char *range_str = nullptr, *input_mode_str = nullptr; + int channel = -1, input_mode, range; - ret = json_unpack_ex(json_signal, &err, 0, "{ s?: s, s?: s, s?: i }", - "range", &range_str, - "input_mode", &input_mode_str, - "channel", &channel - ); - if (ret) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "Failed to parse signal configuration"); + ret = json_unpack_ex(json_signal, &err, 0, "{ s?: s, s?: s, s?: i }", + "range", &range_str, "input_mode", &input_mode_str, + "channel", &channel); + if (ret) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "Failed to parse signal configuration"); - if (!range_str) - range_str = default_range_str; + if (!range_str) + range_str = default_range_str; - if (!input_mode_str) - input_mode_str = default_input_mode_str; + if (!input_mode_str) + input_mode_str = default_input_mode_str; - if (channel < 0) - channel = i; + if (channel < 0) + channel = i; - if (!range_str) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "No input range specified for signal {}.", i); + if (!range_str) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "No input range specified for signal {}.", i); - if (!input_mode_str) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "No input mode specified for signal {}.", i); + if (!input_mode_str) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "No input mode specified for signal {}.", i); - range = uldaq_parse_range(range_str); - if (range < 0) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "Invalid input range specified for signal {}.", i); + range = uldaq_parse_range(range_str); + if (range < 0) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "Invalid input range specified for signal {}.", i); - input_mode = uldaq_parse_input_mode(input_mode_str); - if (input_mode < 0) - throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", "Invalid input mode specified for signal {}.", i); + input_mode = uldaq_parse_input_mode(input_mode_str); + if (input_mode < 0) + throw ConfigError(json_signal, err, "node-config-node-uldaq-signal", + "Invalid input mode specified for signal {}.", i); - u->in.queues[i].range = (Range) range; - u->in.queues[i].inputMode = (AiInputMode) input_mode; - u->in.queues[i].channel = channel; - } + u->in.queues[i].range = (Range)range; + u->in.queues[i].inputMode = (AiInputMode)input_mode; + u->in.queues[i].channel = channel; + } - return ret; + return ret; } -char * villas::node::uldaq_print(NodeCompat *n) -{ - auto *u = n->getData(); +char *villas::node::uldaq_print(NodeCompat *n) { + auto *u = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - if (u->device_descriptor) { - char *uid = u->device_descriptor->uniqueId; - char *name = u->device_descriptor->productName; - const char *iftype = uldaq_print_interface_type(u->device_descriptor->devInterface); + if (u->device_descriptor) { + char *uid = u->device_descriptor->uniqueId; + char *name = u->device_descriptor->productName; + const char *iftype = + uldaq_print_interface_type(u->device_descriptor->devInterface); - buf = strcatf(&buf, "device=%s (%s), interface=%s", uid, name, iftype); - } - else { - const char *uid = u->device_id; - const char *iftype = uldaq_print_interface_type(u->device_interface_type); + buf = strcatf(&buf, "device=%s (%s), interface=%s", uid, name, iftype); + } else { + const char *uid = u->device_id; + const char *iftype = uldaq_print_interface_type(u->device_interface_type); - buf = strcatf(&buf, "device=%s, interface=%s", uid, iftype); - } + buf = strcatf(&buf, "device=%s, interface=%s", uid, iftype); + } - buf = strcatf(&buf, ", in.sample_rate=%f", u->in.sample_rate); + buf = strcatf(&buf, ", in.sample_rate=%f", u->in.sample_rate); - return buf; + return buf; } -int villas::node::uldaq_check(NodeCompat *n) -{ - int ret; - long long has_ai, event_types, max_channel, scan_options, num_ranges_se, num_ranges_diff; - auto *u = n->getData(); +int villas::node::uldaq_check(NodeCompat *n) { + int ret; + long long has_ai, event_types, max_channel, scan_options, num_ranges_se, + num_ranges_diff; + auto *u = n->getData(); - UlError err; + UlError err; - if (n->in.vectorize < 100) - throw ConfigError(n->getConfig(), "node-config-node-vectorize", "Setting 'vectorize' must be larger than 100"); + if (n->in.vectorize < 100) + throw ConfigError(n->getConfig(), "node-config-node-vectorize", + "Setting 'vectorize' must be larger than 100"); - ret = uldaq_connect(n); - if (ret) - return ret; + ret = uldaq_connect(n); + if (ret) + return ret; - err = ulDevGetInfo(u->device_handle, DEV_INFO_HAS_AI_DEV, 0, &has_ai); - if (err != ERR_NO_ERROR) - return -1; + err = ulDevGetInfo(u->device_handle, DEV_INFO_HAS_AI_DEV, 0, &has_ai); + if (err != ERR_NO_ERROR) + return -1; - err = ulDevGetInfo(u->device_handle, DEV_INFO_DAQ_EVENT_TYPES, 0, &event_types); - if (err != ERR_NO_ERROR) - return -1; + err = + ulDevGetInfo(u->device_handle, DEV_INFO_DAQ_EVENT_TYPES, 0, &event_types); + if (err != ERR_NO_ERROR) + return -1; - err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_CHANS, 0, &max_channel); - if (err != ERR_NO_ERROR) - return -1; + err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_CHANS, 0, &max_channel); + if (err != ERR_NO_ERROR) + return -1; - err = ulAIGetInfo(u->device_handle, AI_INFO_SCAN_OPTIONS, 0, &scan_options); - if (err != ERR_NO_ERROR) - return -1; + err = ulAIGetInfo(u->device_handle, AI_INFO_SCAN_OPTIONS, 0, &scan_options); + if (err != ERR_NO_ERROR) + return -1; - err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_DIFF_RANGES, 0, &num_ranges_diff); - if (err != ERR_NO_ERROR) - return -1; + err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_DIFF_RANGES, 0, + &num_ranges_diff); + if (err != ERR_NO_ERROR) + return -1; - err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_SE_RANGES, 0, &num_ranges_se); - if (err != ERR_NO_ERROR) - return -1; + err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_SE_RANGES, 0, &num_ranges_se); + if (err != ERR_NO_ERROR) + return -1; - Range ranges_diff[num_ranges_diff]; - Range ranges_se[num_ranges_se]; + Range ranges_diff[num_ranges_diff]; + Range ranges_se[num_ranges_se]; - for (int i = 0; i < num_ranges_diff; i++) { - err = ulAIGetInfo(u->device_handle, AI_INFO_DIFF_RANGE, i, (long long *) &ranges_diff[i]); - if (err != ERR_NO_ERROR) - return -1; - } + for (int i = 0; i < num_ranges_diff; i++) { + err = ulAIGetInfo(u->device_handle, AI_INFO_DIFF_RANGE, i, + (long long *)&ranges_diff[i]); + if (err != ERR_NO_ERROR) + return -1; + } - for (int i = 0; i < num_ranges_se; i++) { - err = ulAIGetInfo(u->device_handle, AI_INFO_SE_RANGE, i, (long long *) &ranges_se[i]); - if (err != ERR_NO_ERROR) - return -1; - } + for (int i = 0; i < num_ranges_se; i++) { + err = ulAIGetInfo(u->device_handle, AI_INFO_SE_RANGE, i, + (long long *)&ranges_se[i]); + if (err != ERR_NO_ERROR) + return -1; + } - if (!has_ai) - throw RuntimeError("DAQ device has no analog input channels"); + if (!has_ai) + throw RuntimeError("DAQ device has no analog input channels"); - if (!(event_types & DE_ON_DATA_AVAILABLE)) - throw RuntimeError("DAQ device does not support events"); + if (!(event_types & DE_ON_DATA_AVAILABLE)) + throw RuntimeError("DAQ device does not support events"); - if ((scan_options & u->in.scan_options) != u->in.scan_options) - throw RuntimeError("DAQ device does not support required scan options"); + if ((scan_options & u->in.scan_options) != u->in.scan_options) + throw RuntimeError("DAQ device does not support required scan options"); - for (size_t i = 0; i < n->getInputSignals(false)->size(); i++) { - auto sig = n->getInputSignals(false)->getByIndex(i); - AiQueueElement *q = &u->in.queues[i]; + for (size_t i = 0; i < n->getInputSignals(false)->size(); i++) { + auto sig = n->getInputSignals(false)->getByIndex(i); + AiQueueElement *q = &u->in.queues[i]; - if (sig->type != SignalType::FLOAT) - throw RuntimeError("Node supports only signals of type = float!"); + if (sig->type != SignalType::FLOAT) + throw RuntimeError("Node supports only signals of type = float!"); - switch (q->inputMode) { - case AI_PSEUDO_DIFFERENTIAL: - case AI_DIFFERENTIAL: - for (int j = 0; j < num_ranges_diff; j++) { - if (q->range == ranges_diff[j]) - goto found; - } - break; + switch (q->inputMode) { + case AI_PSEUDO_DIFFERENTIAL: + case AI_DIFFERENTIAL: + for (int j = 0; j < num_ranges_diff; j++) { + if (q->range == ranges_diff[j]) + goto found; + } + break; - case AI_SINGLE_ENDED: - for (int j = 0; j < num_ranges_se; j++) { - if (q->range == ranges_se[j]) - goto found; - } - break; - } + case AI_SINGLE_ENDED: + for (int j = 0; j < num_ranges_se; j++) { + if (q->range == ranges_se[j]) + goto found; + } + break; + } - throw RuntimeError("Unsupported range for signal {}", i); + throw RuntimeError("Unsupported range for signal {}", i); -found: if (q->channel > max_channel) - throw RuntimeError("DAQ device does not support more than {} channels", max_channel); - } + found: + if (q->channel > max_channel) + throw RuntimeError("DAQ device does not support more than {} channels", + max_channel); + } - return 0; + return 0; } -static -void uldaq_data_available(DaqDeviceHandle device_handle, DaqEventType event_type, unsigned long long event_data, void *ctx) -{ - auto *n = (NodeCompat *) ctx; - auto *u = n->getData(); +static void uldaq_data_available(DaqDeviceHandle device_handle, + DaqEventType event_type, + unsigned long long event_data, void *ctx) { + auto *n = (NodeCompat *)ctx; + auto *u = n->getData(); - pthread_mutex_lock(&u->in.mutex); + pthread_mutex_lock(&u->in.mutex); - UlError err; - err = ulAInScanStatus(device_handle, &u->in.status, &u->in.transfer_status); - if (err != ERR_NO_ERROR) - n->logger->warn("Failed to retrieve scan status in event callback"); + UlError err; + err = ulAInScanStatus(device_handle, &u->in.status, &u->in.transfer_status); + if (err != ERR_NO_ERROR) + n->logger->warn("Failed to retrieve scan status in event callback"); - pthread_mutex_unlock(&u->in.mutex); + pthread_mutex_unlock(&u->in.mutex); - // Signal uldaq_read() about new data - pthread_cond_signal(&u->in.cv); + // Signal uldaq_read() about new data + pthread_cond_signal(&u->in.cv); } -int villas::node::uldaq_start(NodeCompat *n) -{ - auto *u = n->getData(); +int villas::node::uldaq_start(NodeCompat *n) { + auto *u = n->getData(); - u->sequence = 0; - u->in.buffer_pos = 0; + u->sequence = 0; + u->in.buffer_pos = 0; - int ret; - UlError err; + int ret; + UlError err; - // Allocate a buffer to receive the data - u->in.buffer_len = u->in.channel_count * n->in.vectorize * 50; - u->in.buffer = new double[u->in.buffer_len]; - if (!u->in.buffer) - throw MemoryAllocationError(); + // Allocate a buffer to receive the data + u->in.buffer_len = u->in.channel_count * n->in.vectorize * 50; + u->in.buffer = new double[u->in.buffer_len]; + if (!u->in.buffer) + throw MemoryAllocationError(); - ret = uldaq_connect(n); - if (ret) - return ret; + ret = uldaq_connect(n); + if (ret) + return ret; - err = ulAInLoadQueue(u->device_handle, u->in.queues, n->getInputSignals(false)->size()); - if (err != ERR_NO_ERROR) - throw RuntimeError("Failed to load input queue to DAQ device"); + err = ulAInLoadQueue(u->device_handle, u->in.queues, + n->getInputSignals(false)->size()); + if (err != ERR_NO_ERROR) + throw RuntimeError("Failed to load input queue to DAQ device"); - // Enable the event to be notified every time samples are available - err = ulEnableEvent(u->device_handle, DE_ON_DATA_AVAILABLE, n->in.vectorize, uldaq_data_available, n); + // Enable the event to be notified every time samples are available + err = ulEnableEvent(u->device_handle, DE_ON_DATA_AVAILABLE, n->in.vectorize, + uldaq_data_available, n); - // Start the acquisition - err = ulAInScan(u->device_handle, 0, 0, (AiInputMode) 0, (Range) 0, u->in.buffer_len / u->in.channel_count, &u->in.sample_rate, u->in.scan_options, u->in.flags, u->in.buffer); - if (err != ERR_NO_ERROR) { - char buf[ERR_MSG_LEN]; - ulGetErrMsg(err, buf); - throw RuntimeError("Failed to start acquisition on DAQ device: {}", buf); - } + // Start the acquisition + err = ulAInScan(u->device_handle, 0, 0, (AiInputMode)0, (Range)0, + u->in.buffer_len / u->in.channel_count, &u->in.sample_rate, + u->in.scan_options, u->in.flags, u->in.buffer); + if (err != ERR_NO_ERROR) { + char buf[ERR_MSG_LEN]; + ulGetErrMsg(err, buf); + throw RuntimeError("Failed to start acquisition on DAQ device: {}", buf); + } - // Get the initial status of the acquisition - err = ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); - if (err != ERR_NO_ERROR) { - char buf[ERR_MSG_LEN]; - ulGetErrMsg(err, buf); - throw RuntimeError("Failed to retrieve scan status on DAQ device: {}", buf); - } + // Get the initial status of the acquisition + err = + ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); + if (err != ERR_NO_ERROR) { + char buf[ERR_MSG_LEN]; + ulGetErrMsg(err, buf); + throw RuntimeError("Failed to retrieve scan status on DAQ device: {}", buf); + } - if (u->in.status != SS_RUNNING) { - char buf[ERR_MSG_LEN]; - ulGetErrMsg(err, buf); - throw RuntimeError("Acquisition did not start on DAQ device: {}", buf); - } + if (u->in.status != SS_RUNNING) { + char buf[ERR_MSG_LEN]; + ulGetErrMsg(err, buf); + throw RuntimeError("Acquisition did not start on DAQ device: {}", buf); + } - return 0; + return 0; } -int villas::node::uldaq_stop(NodeCompat *n) -{ - auto *u = n->getData(); +int villas::node::uldaq_stop(NodeCompat *n) { + auto *u = n->getData(); - UlError err; + UlError err; - // TODO: Fix deadlock - //pthread_mutex_lock(&u->in.mutex); + // TODO: Fix deadlock + //pthread_mutex_lock(&u->in.mutex); - // Get the current status of the acquisition - err = ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); - if (err != ERR_NO_ERROR) - return -1; + // Get the current status of the acquisition + err = + ulAInScanStatus(u->device_handle, &u->in.status, &u->in.transfer_status); + if (err != ERR_NO_ERROR) + return -1; - // Stop the acquisition if it is still running - if (u->in.status == SS_RUNNING) { - err = ulAInScanStop(u->device_handle); - if (err != ERR_NO_ERROR) - return -1; - } + // Stop the acquisition if it is still running + if (u->in.status == SS_RUNNING) { + err = ulAInScanStop(u->device_handle); + if (err != ERR_NO_ERROR) + return -1; + } - //pthread_mutex_unlock(&u->in.mutex); + //pthread_mutex_unlock(&u->in.mutex); - err = ulDisconnectDaqDevice(u->device_handle); - if (err != ERR_NO_ERROR) - return -1; + err = ulDisconnectDaqDevice(u->device_handle); + if (err != ERR_NO_ERROR) + return -1; - err = ulReleaseDaqDevice(u->device_handle); - if (err != ERR_NO_ERROR) - return -1; + err = ulReleaseDaqDevice(u->device_handle); + if (err != ERR_NO_ERROR) + return -1; - return 0; + return 0; } -int villas::node::uldaq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - auto *u = n->getData(); +int villas::node::uldaq_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + auto *u = n->getData(); - pthread_mutex_lock(&u->in.mutex); + pthread_mutex_lock(&u->in.mutex); - if (u->in.status != SS_RUNNING) - return -1; + if (u->in.status != SS_RUNNING) + return -1; - size_t start_index = u->in.buffer_pos; + size_t start_index = u->in.buffer_pos; - // Wait for data available condition triggered by event callback - if (start_index + n->in.vectorize * u->in.channel_count > u->in.transfer_status.currentTotalCount) - pthread_cond_wait(&u->in.cv, &u->in.mutex); + // Wait for data available condition triggered by event callback + if (start_index + n->in.vectorize * u->in.channel_count > + u->in.transfer_status.currentTotalCount) + pthread_cond_wait(&u->in.cv, &u->in.mutex); - for (unsigned j = 0; j < cnt; j++) { - struct Sample *smp = smps[j]; + for (unsigned j = 0; j < cnt; j++) { + struct Sample *smp = smps[j]; - long long scan_index = start_index + j * u->in.channel_count; + long long scan_index = start_index + j * u->in.channel_count; - for (unsigned i = 0; i < u->in.channel_count; i++) { - long long channel_index = (scan_index + i) % u->in.buffer_len; + for (unsigned i = 0; i < u->in.channel_count; i++) { + long long channel_index = (scan_index + i) % u->in.buffer_len; - smp->data[i].f = u->in.buffer[channel_index]; - } + smp->data[i].f = u->in.buffer[channel_index]; + } - smp->length = u->in.channel_count; - smp->signals = n->getInputSignals(false); - smp->sequence = u->sequence++; - smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA; - } + smp->length = u->in.channel_count; + smp->signals = n->getInputSignals(false); + smp->sequence = u->sequence++; + smp->flags = (int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA; + } - u->in.buffer_pos += u->in.channel_count * cnt; + u->in.buffer_pos += u->in.channel_count * cnt; - pthread_mutex_unlock(&u->in.mutex); + pthread_mutex_unlock(&u->in.mutex); - return cnt; + return cnt; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "uldaq"; - p.description = "Measurement Computing DAQ devices like UL201 (libuldaq)"; - p.vectorize = 0; - p.flags = 0; - p.size = sizeof(struct uldaq); - p.type.start = uldaq_type_start; - p.init = uldaq_init; - p.destroy = uldaq_destroy; - p.parse = uldaq_parse; - p.print = uldaq_print; - p.start = uldaq_start; - p.stop = uldaq_stop; - p.read = uldaq_read; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "uldaq"; + p.description = "Measurement Computing DAQ devices like UL201 (libuldaq)"; + p.vectorize = 0; + p.flags = 0; + p.size = sizeof(struct uldaq); + p.type.start = uldaq_type_start; + p.init = uldaq_init; + p.destroy = uldaq_destroy; + p.parse = uldaq_parse; + p.print = uldaq_print; + p.start = uldaq_start; + p.stop = uldaq_stop; + p.read = uldaq_read; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/nodes/webrtc.cpp b/lib/nodes/webrtc.cpp index 872f365d5..c4e9ad52b 100644 --- a/lib/nodes/webrtc.cpp +++ b/lib/nodes/webrtc.cpp @@ -9,245 +9,227 @@ #include +#include #include #include -#include -#include #include -#include #include -#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -villas::node::Web *web; +static villas::node::Web *web; -WebRTCNode::WebRTCNode(const uuid_t &id, const std::string &name) : - Node(id, name), - server("https://villas.k8s.eonerc.rwth-aachen.de/ws/signaling"), - peer(uuid::toString(id)), - wait_seconds(0), - format(nullptr), - queue({}), - pool({}), - dci({}) -{ - dci.reliability.type = rtc::Reliability::Type::Rexmit; +WebRTCNode::WebRTCNode(const uuid_t &id, const std::string &name) + : Node(id, name), + server("https://villas.k8s.eonerc.rwth-aachen.de/ws/signaling"), + peer(uuid::toString(id)), wait_seconds(0), format(nullptr), queue({}), + pool({}), dci({}) { + dci.reliability.type = rtc::Reliability::Type::Rexmit; } -WebRTCNode::~WebRTCNode() -{ - int ret = pool_destroy(&pool); - if (ret) // TODO log - ; +WebRTCNode::~WebRTCNode() { + int ret = pool_destroy(&pool); + if (ret) // TODO log + ; } -int WebRTCNode::parse(json_t *json) -{ - int ret = Node::parse(json); - if (ret) - return ret; +int WebRTCNode::parse(json_t *json) { + int ret = Node::parse(json); + if (ret) + return ret; - const char *sess; - const char *svr = nullptr; - const char *pr = nullptr; - int ord = -1; - int &rexmit = dci.reliability.rexmit.emplace(0); - json_t *json_ice = nullptr; - json_t *json_format = nullptr; + const char *sess; + const char *svr = nullptr; + const char *pr = nullptr; + int ord = -1; + int &rexmit = dci.reliability.rexmit.emplace(0); + json_t *json_ice = nullptr; + json_t *json_format = nullptr; - json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s: s, s?: s, s?: s, s?: i, s?: i, s?: b, s?: o }", - "session", &sess, - "peer", &pr, - "server", &svr, - "wait_seconds", &wait_seconds, - "max_retransmits", &rexmit, - "ordered", &ord, - "ice", &json_ice, - "format", &json_format - ); - if (ret) - throw ConfigError(json, err, "node-config-node-webrtc"); + json_error_t err; + ret = json_unpack_ex( + json, &err, 0, "{ s: s, s?: s, s?: s, s?: i, s?: i, s?: b, s?: o }", + "session", &sess, "peer", &pr, "server", &svr, "wait_seconds", + &wait_seconds, "max_retransmits", &rexmit, "ordered", &ord, "ice", + &json_ice, "format", &json_format); + if (ret) + throw ConfigError(json, err, "node-config-node-webrtc"); - session = sess; + session = sess; - if (svr) - server = svr; + if (svr) + server = svr; - if (pr) - peer = pr; + if (pr) + peer = pr; - if (ord) - dci.reliability.unordered = !ord; + if (ord) + dci.reliability.unordered = !ord; - if (json_ice) { - json_t *json_servers = nullptr; + if (json_ice) { + json_t *json_servers = nullptr; - ret = json_unpack_ex(json_ice, &err, 0, "{ s?: o }", - "servers", &json_servers - ); - if (ret) - throw ConfigError(json, err, "node-config-node-webrtc-ice"); + ret = json_unpack_ex(json_ice, &err, 0, "{ s?: o }", "servers", + &json_servers); + if (ret) + throw ConfigError(json, err, "node-config-node-webrtc-ice"); - if (json_servers) { - rtcConf.iceServers.clear(); + if (json_servers) { + rtcConf.iceServers.clear(); - if (!json_is_array(json_servers)) - throw ConfigError(json_servers, "node-config-node-webrtc-ice-servers", "ICE Servers must be a an array of server configurations."); + if (!json_is_array(json_servers)) + throw ConfigError( + json_servers, "node-config-node-webrtc-ice-servers", + "ICE Servers must be a an array of server configurations."); - size_t i; - json_t *json_server; - json_array_foreach(json_servers, i, json_server) { - if (!json_is_string(json_server)) - throw ConfigError(json_server, "node-config-node-webrtc-ice-server", "ICE servers must be provided as STUN/TURN url."); + size_t i; + json_t *json_server; + json_array_foreach(json_servers, i, json_server) { + if (!json_is_string(json_server)) + throw ConfigError(json_server, "node-config-node-webrtc-ice-server", + "ICE servers must be provided as STUN/TURN url."); - std::string uri = json_string_value(json_server); + std::string uri = json_string_value(json_server); - rtcConf.iceServers.emplace_back(uri); - } - } - } + rtcConf.iceServers.emplace_back(uri); + } + } + } - format = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); + format = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); - assert(format); + assert(format); - return 0; + return 0; } -int WebRTCNode::prepare() -{ - int ret = Node::prepare(); - if (ret) - return ret; +int WebRTCNode::prepare() { + int ret = Node::prepare(); + if (ret) + return ret; - format->start(getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + format->start(getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - // TODO: Determine output signals reliably - auto signals = std::make_shared(); + // TODO: Determine output signals reliably + auto signals = std::make_shared(); - conn = std::make_shared(server, session, peer, signals, rtcConf, web, dci); + conn = std::make_shared(server, session, peer, + signals, rtcConf, web, dci); - ret = pool_init(&pool, 1024, SAMPLE_LENGTH(getInputSignals(false)->size())); - if (ret) // TODO log - return ret; + ret = pool_init(&pool, 1024, SAMPLE_LENGTH(getInputSignals(false)->size())); + if (ret) // TODO log + return ret; - ret = queue_signalled_init(&queue, 1024); - if (ret) // TODO log - return ret; + ret = queue_signalled_init(&queue, 1024); + if (ret) // TODO log + return ret; - // TODO: Move this to a member function - conn->onMessage([this](rtc::binary msg){ - int ret; - std::vector smps; - smps.resize(this->in.vectorize); + // TODO: Move this to a member function + conn->onMessage([this](rtc::binary msg) { + int ret; + std::vector smps; + smps.resize(this->in.vectorize); - ret = sample_alloc_many(&this->pool, smps.data(), smps.size()); - if (ret < 0) // TODO log - return; + ret = sample_alloc_many(&this->pool, smps.data(), smps.size()); + if (ret < 0) // TODO log + return; - ret = format->sscan((const char *)msg.data(), msg.size(), nullptr, smps.data(), ret); - if (ret < 0) // TODO log - return; + ret = format->sscan((const char *)msg.data(), msg.size(), nullptr, + smps.data(), ret); + if (ret < 0) // TODO log + return; - ret = queue_signalled_push_many(&this->queue, (void **) smps.data(), ret); - if (ret < 0) // TODO log - return; + ret = queue_signalled_push_many(&this->queue, (void **)smps.data(), ret); + if (ret < 0) // TODO log + return; - this->logger->trace("onMessage(rtc::binary) callback finished pushing {} samples", ret); - }); + this->logger->trace( + "onMessage(rtc::binary) callback finished pushing {} samples", ret); + }); - return 0; + return 0; } -int WebRTCNode::start() -{ - int ret = Node::start(); - if (!ret) - state = State::STARTED; +int WebRTCNode::start() { + int ret = Node::start(); + if (!ret) + state = State::STARTED; - conn->connect(); + conn->connect(); - if (wait_seconds > 0) { - logger->info("Waiting for datachannel..."); + if (wait_seconds > 0) { + logger->info("Waiting for datachannel..."); - if (!conn->waitForDataChannel(std::chrono::seconds { wait_seconds })) { - throw RuntimeError { "Waiting for datachannel timed out after {} seconds", wait_seconds }; - } - } + if (!conn->waitForDataChannel(std::chrono::seconds{wait_seconds})) { + throw RuntimeError{"Waiting for datachannel timed out after {} seconds", + wait_seconds}; + } + } - return 0; + return 0; } -int WebRTCNode::stop() -{ - conn->disconnect(); - return Node::stop(); +int WebRTCNode::stop() { + conn->disconnect(); + return Node::stop(); } -std::vector WebRTCNode::getPollFDs() -{ - return { queue_signalled_fd(&queue) }; +std::vector WebRTCNode::getPollFDs() { + return {queue_signalled_fd(&queue)}; } -const std::string & WebRTCNode::getDetails() -{ - // TODO - details = fmt::format(""); - return details; +const std::string &WebRTCNode::getDetails() { + // TODO + details = fmt::format(""); + return details; } -int WebRTCNode::_read(struct Sample *smps[], unsigned cnt) -{ - std::vector smpt; - smpt.resize(cnt); +int WebRTCNode::_read(struct Sample *smps[], unsigned cnt) { + std::vector smpt; + smpt.resize(cnt); - int pulled = queue_signalled_pull_many(&queue, (void **) smpt.data(), smpt.size()); + int pulled = + queue_signalled_pull_many(&queue, (void **)smpt.data(), smpt.size()); - sample_copy_many(smps, smpt.data(), pulled); - sample_decref_many(smpt.data(), pulled); + sample_copy_many(smps, smpt.data(), pulled); + sample_decref_many(smpt.data(), pulled); - return pulled; + return pulled; } -int WebRTCNode::_write(struct Sample *smps[], unsigned cnt) -{ - rtc::binary buf; - size_t wbytes; +int WebRTCNode::_write(struct Sample *smps[], unsigned cnt) { + rtc::binary buf; + size_t wbytes; - buf.resize(4 * 1024); - int ret = format->sprint((char *) buf.data(), buf.size(), &wbytes, smps, cnt); - if (ret < 0) // TODO log - return ret; + buf.resize(4 * 1024); + int ret = format->sprint((char *)buf.data(), buf.size(), &wbytes, smps, cnt); + if (ret < 0) // TODO log + return ret; - buf.resize(wbytes); - conn->sendMessage(buf); + buf.resize(wbytes); + conn->sendMessage(buf); - return ret; + return ret; } -json_t * WebRTCNode::_readStatus() const -{ - if (!conn) - return nullptr; +json_t *WebRTCNode::_readStatus() const { + if (!conn) + return nullptr; - return conn->readStatus(); + return conn->readStatus(); } -int WebRTCNodeFactory::start(SuperNode *sn) -{ - web = sn->getWeb(); - if (!web->isEnabled()) - return -1; +int WebRTCNodeFactory::start(SuperNode *sn) { + web = sn->getWeb(); + if (!web->isEnabled()) + return -1; - return 0; + return 0; } -static -WebRTCNodeFactory p; +static WebRTCNodeFactory p; diff --git a/lib/nodes/webrtc/peer_connection.cpp b/lib/nodes/webrtc/peer_connection.cpp index 944de99d8..e32e58eef 100644 --- a/lib/nodes/webrtc/peer_connection.cpp +++ b/lib/nodes/webrtc/peer_connection.cpp @@ -10,13 +10,13 @@ #include #include +#include #include #include -#include -#include #include #include +#include using namespace std::placeholders; @@ -37,416 +37,382 @@ using namespace villas::node::webrtc; * the data structures are defined, allows ADL to pick these up in spdlog/fmt. */ namespace rtc { - using ::operator<<; +using ::operator<<; } -PeerConnection::PeerConnection(const std::string &server, const std::string &session, const std::string &peer, std::shared_ptr signals, rtc::Configuration cfg, Web *w, rtc::DataChannelInit d) : - web(w), - extraServers({}), - dataChannelInit(d), - defaultConfig(cfg), - conn(nullptr), - chan(nullptr), - signals(signals), - logger(logging.get("webrtc:pc")), - stopStartup(false), - warnNotConnected(false), - standby(true), - first(false), - firstID(INT_MAX), - secondID(INT_MAX), - onMessageCallback(nullptr) -{ - client = std::make_shared(server, session, peer, web); - client->onConnected([this](){ this->onSignalingConnected(); }); - client->onDisconnected([this](){ this->onSignalingDisconnected(); }); - client->onError([this](auto err){ this->onSignalingError(std::move(err)); }); - client->onMessage([this](auto msg){ this->onSignalingMessage(std::move(msg)); }); +PeerConnection::PeerConnection(const std::string &server, + const std::string &session, + const std::string &peer, + std::shared_ptr signals, + rtc::Configuration cfg, Web *w, + rtc::DataChannelInit d) + : web(w), extraServers({}), dataChannelInit(d), defaultConfig(cfg), + conn(nullptr), chan(nullptr), signals(signals), + logger(logging.get("webrtc:pc")), stopStartup(false), + warnNotConnected(false), standby(true), first(false), firstID(INT_MAX), + secondID(INT_MAX), onMessageCallback(nullptr) { + client = std::make_shared(server, session, peer, web); + client->onConnected([this]() { this->onSignalingConnected(); }); + client->onDisconnected([this]() { this->onSignalingDisconnected(); }); + client->onError([this](auto err) { this->onSignalingError(std::move(err)); }); + client->onMessage( + [this](auto msg) { this->onSignalingMessage(std::move(msg)); }); - auto lock = std::unique_lock { mutex }; - resetConnectionAndStandby(lock); + auto lock = std::unique_lock{mutex}; + resetConnectionAndStandby(lock); } -PeerConnection::~PeerConnection() -{ +PeerConnection::~PeerConnection() {} + +bool PeerConnection::waitForDataChannel(std::chrono::seconds timeout) { + auto lock = std::unique_lock{mutex}; + + auto deadline = std::chrono::steady_clock::now() + timeout; + + return startupCondition.wait_until(lock, deadline, + [this]() { return this->stopStartup; }); } -bool PeerConnection::waitForDataChannel(std::chrono::seconds timeout) -{ - auto lock = std::unique_lock { mutex }; +json_t *PeerConnection::readStatus() const { + auto *json = + json_pack("{ s: I, s: I }", "bytes_received", conn->bytesReceived(), + "bytes_sent", conn->bytesSent()); - auto deadline = std::chrono::steady_clock::now() + timeout; + auto rtt = conn->rtt(); + if (rtt.has_value()) { + auto *json_rtt = json_real(rtt.value().count() / 1e3); + json_object_set_new(json, "rtt", json_rtt); + } - return startupCondition.wait_until(lock, deadline, [this](){ return this->stopStartup; }); + rtc::Candidate local, remote; + if (conn->getSelectedCandidatePair(&local, &remote)) { + auto *json_cp = + json_pack("{ s: s, s: s }", "local", std::string(local).c_str(), + "remote", std::string(remote).c_str()); + json_object_set_new(json, "candidate_pair", json_cp); + } + + return json; } -json_t * PeerConnection::readStatus() const -{ - auto *json = json_pack("{ s: I, s: I }", - "bytes_received", conn->bytesReceived(), - "bytes_sent", conn->bytesSent() - ); - - auto rtt = conn->rtt(); - if (rtt.has_value()) { - auto *json_rtt = json_real(rtt.value().count() / 1e3); - json_object_set_new(json, "rtt", json_rtt); - } - - rtc::Candidate local, remote; - if (conn->getSelectedCandidatePair(&local, &remote)) { - auto *json_cp = json_pack("{ s: s, s: s }", - "local", std::string(local).c_str(), - "remote", std::string(remote).c_str() - ); - json_object_set_new(json, "candidate_pair", json_cp); - } - - return json; +void PeerConnection::notifyStartup() { + stopStartup = true; + startupCondition.notify_all(); } -void PeerConnection::notifyStartup() -{ - stopStartup = true; - startupCondition.notify_all(); +void PeerConnection::onMessage(std::function callback) { + auto lock = std::unique_lock{mutex}; + + onMessageCallback = callback; } -void PeerConnection::onMessage(std::function callback) -{ - auto lock = std::unique_lock { mutex }; +void PeerConnection::sendMessage(rtc::binary msg) { + auto lock = std::unique_lock{mutex}; - onMessageCallback = callback; + if (chan && chan->isOpen()) { + chan->send(msg); + warnNotConnected = true; + } else if (warnNotConnected) { + logger->warn("Dropping messages. No peer connected."); + warnNotConnected = false; + } } -void PeerConnection::sendMessage(rtc::binary msg) -{ - auto lock = std::unique_lock { mutex }; +void PeerConnection::connect() { client->connect(); } - if (chan && chan->isOpen()) { - chan->send(msg); - warnNotConnected = true; - } else if (warnNotConnected) { - logger->warn("Dropping messages. No peer connected."); - warnNotConnected = false; - } +void PeerConnection::disconnect() { client->disconnect(); } + +void PeerConnection::resetConnection( + std::unique_lock &lock) { + lock.unlock(); + chan.reset(); + conn.reset(); + lock.lock(); } -void PeerConnection::connect() -{ - client->connect(); +void PeerConnection::resetConnectionAndStandby( + std::unique_lock &lock) { + if (!standby) + logger->info("Going to standby"); + + standby = true; + first = false; + firstID = INT_MAX; + secondID = INT_MAX; + warnNotConnected = false; + + resetConnection(lock); } -void PeerConnection::disconnect() -{ - client->disconnect(); +void PeerConnection::setupPeerConnection( + std::shared_ptr pc) { + logger->debug("Setup {} peer connection", pc ? "existing" : "new"); + + auto config = defaultConfig; + config.iceServers.insert(std::end(config.iceServers), + std::begin(extraServers), std::end(extraServers)); + + conn = pc ? std::move(pc) : std::make_shared(config); + conn->onLocalDescription( + [this](auto desc) { this->onLocalDescription(std::move(desc)); }); + conn->onLocalCandidate( + [this](auto cand) { this->onLocalCandidate(std::move(cand)); }); + conn->onDataChannel( + [this](auto channel) { this->onDataChannel(std::move(channel)); }); + conn->onGatheringStateChange( + [this](auto state) { this->onGatheringStateChange(std::move(state)); }); + conn->onSignalingStateChange( + [this](auto state) { this->onSignalingStateChange(std::move(state)); }); + conn->onStateChange( + [this](auto state) { this->onConnectionStateChange(std::move(state)); }); } -void PeerConnection::resetConnection(std::unique_lock &lock) -{ - lock.unlock(); - chan.reset(); - conn.reset(); - lock.lock(); +void PeerConnection::setupDataChannel(std::shared_ptr dc) { + logger->debug("Setup {} data channel", dc ? "existing" : "new"); + + assert(conn); + chan = + dc ? std::move(dc) : conn->createDataChannel("villas", dataChannelInit); + chan->onMessage( + [this](rtc::binary msg) { this->onDataChannelMessage(std::move(msg)); }, + [this](rtc::string msg) { this->onDataChannelMessage(std::move(msg)); }); + chan->onOpen([this]() { this->onDataChannelOpen(); }); + chan->onClosed([this]() { this->onDataChannelClosed(); }); + chan->onError([this](auto err) { this->onDataChannelError(std::move(err)); }); + + // If this node has it's data channel set up, don't accept any new ones + conn->onDataChannel(nullptr); } -void PeerConnection::resetConnectionAndStandby(std::unique_lock &lock) -{ - if (!standby) - logger->info("Going to standby"); +void PeerConnection::onLocalDescription(rtc::Description desc) { + logger->debug("New local description: type={} sdp=\n{}", desc.typeString(), + desc.generateSdp()); - standby = true; - first = false; - firstID = INT_MAX; - secondID = INT_MAX; - warnNotConnected = false; + auto lock = std::unique_lock{mutex}; - resetConnection(lock); + client->sendMessage({desc}); } -void PeerConnection::setupPeerConnection(std::shared_ptr pc) -{ - logger->debug("Setup {} peer connection", pc ? "existing" : "new"); +void PeerConnection::onLocalCandidate(rtc::Candidate cand) { + logger->debug("New local candidate: {}", std::string{cand}); - auto config = defaultConfig; - config.iceServers.insert(std::end(config.iceServers), std::begin(extraServers), std::end(extraServers)); + auto lock = std::unique_lock{mutex}; - conn = pc ? std::move(pc) : std::make_shared(config); - conn->onLocalDescription([this](auto desc){ this->onLocalDescription(std::move(desc)); }); - conn->onLocalCandidate([this](auto cand){ this->onLocalCandidate(std::move(cand)); }); - conn->onDataChannel([this](auto channel){ this->onDataChannel(std::move(channel)); }); - conn->onGatheringStateChange([this](auto state){ this->onGatheringStateChange(std::move(state)); }); - conn->onSignalingStateChange([this](auto state){ this->onSignalingStateChange(std::move(state)); }); - conn->onStateChange([this](auto state){ this->onConnectionStateChange(std::move(state)); }); + client->sendMessage({cand}); } -void PeerConnection::setupDataChannel(std::shared_ptr dc) -{ - logger->debug("Setup {} data channel", dc ? "existing" : "new"); +void PeerConnection::onConnectionStateChange(rtc::PeerConnection::State state) { + logger->debug("Connection State changed: {}", state); - assert(conn); - chan = dc ? std::move(dc) : conn->createDataChannel("villas", dataChannelInit); - chan->onMessage( - [this](rtc::binary msg){ this->onDataChannelMessage(std::move(msg)); }, - [this](rtc::string msg){ this->onDataChannelMessage(std::move(msg)); } - ); - chan->onOpen([this](){ this->onDataChannelOpen(); }); - chan->onClosed([this](){ this->onDataChannelClosed(); }); - chan->onError([this](auto err){ this->onDataChannelError(std::move(err)); }); + auto lock = std::unique_lock{mutex}; - // If this node has it's data channel set up, don't accept any new ones - conn->onDataChannel(nullptr); + switch (state) { + case rtc::PeerConnection::State::New: { + logger->debug("New peer connection"); + break; + } + + case rtc::PeerConnection::State::Connecting: { + logger->debug("Peer connection connecting."); + break; + } + + case rtc::PeerConnection::State::Connected: { + rtc::Candidate local, remote; + std::optional rtt = conn->rtt(); + if (conn->getSelectedCandidatePair(&local, &remote)) { + std::stringstream l, r; + l << local, r << remote; + logger->debug("Peer connection connected:\n" + "local: {}\n" + "remote: {}\n" + "bytes sent: {} / bytes received: {} / rtt: {}\n", + l.str(), r.str(), conn->bytesSent(), conn->bytesReceived(), + rtt.value_or(decltype(rtt)::value_type{0})); + } else { + logger->debug("Peer connection connected.\n" + "Could not get candidate pair info.\n"); + } + break; + } + + case rtc::PeerConnection::State::Disconnected: + case rtc::PeerConnection::State::Failed: { + logger->debug("Closing peer connection"); + break; + } + + case rtc::PeerConnection::State::Closed: { + logger->debug("Closed peer connection"); + resetConnectionAndStandby(lock); + break; + } + } } -void PeerConnection::onLocalDescription(rtc::Description desc) -{ - logger->debug("New local description: type={} sdp=\n{}", desc.typeString(), desc.generateSdp()); - - auto lock = std::unique_lock { mutex }; - - client->sendMessage({ desc }); +void PeerConnection::onSignalingStateChange( + rtc::PeerConnection::SignalingState state) { + std::stringstream s; + s << state; + logger->debug("Signaling state changed: {}", s.str()); } -void PeerConnection::onLocalCandidate(rtc::Candidate cand) -{ - logger->debug("New local candidate: {}", std::string { cand }); - - auto lock = std::unique_lock { mutex }; - - client->sendMessage({ cand }); +void PeerConnection::onGatheringStateChange( + rtc::PeerConnection::GatheringState state) { + std::stringstream s; + s << state; + logger->debug("Gathering state changed: {}", s.str()); } -void PeerConnection::onConnectionStateChange(rtc::PeerConnection::State state) -{ - logger->debug("Connection State changed: {}", state); +void PeerConnection::onSignalingConnected() { + logger->debug("Signaling connection established"); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - switch (state) { - case rtc::PeerConnection::State::New: { - logger->debug("New peer connection"); - break; - } - - case rtc::PeerConnection::State::Connecting: { - logger->debug("Peer connection connecting."); - break; - } - - case rtc::PeerConnection::State::Connected: { - rtc::Candidate local, remote; - std::optional rtt = conn->rtt(); - if (conn->getSelectedCandidatePair(&local, &remote)) { - std::stringstream l, r; - l << local, r << remote; - logger->debug( - "Peer connection connected:\n" - "local: {}\n" - "remote: {}\n" - "bytes sent: {} / bytes received: {} / rtt: {}\n", - l.str(), - r.str(), - conn->bytesSent(), - conn->bytesReceived(), - rtt.value_or(decltype(rtt)::value_type { 0 }) - ); - } else { - logger->debug( - "Peer connection connected.\n" - "Could not get candidate pair info.\n" - ); - } - break; - } - - case rtc::PeerConnection::State::Disconnected: - case rtc::PeerConnection::State::Failed: { - logger->debug("Closing peer connection"); - break; - } - - case rtc::PeerConnection::State::Closed: { - logger->debug("Closed peer connection"); - resetConnectionAndStandby(lock); - break; - } - } + client->sendMessage({*signals}); } -void PeerConnection::onSignalingStateChange(rtc::PeerConnection::SignalingState state) -{ - std::stringstream s; - s << state; - logger->debug("Signaling state changed: {}", s.str()); +void PeerConnection::onSignalingDisconnected() { + logger->debug("Signaling connection closed"); + + auto lock = std::unique_lock{mutex}; + + resetConnectionAndStandby(lock); } -void PeerConnection::onGatheringStateChange(rtc::PeerConnection::GatheringState state) -{ - std::stringstream s; - s << state; - logger->debug("Gathering state changed: {}", s.str()); +void PeerConnection::onSignalingError(std::string err) { + logger->debug("Signaling connection error: {}", err); + + auto lock = std::unique_lock{mutex}; + + resetConnectionAndStandby(lock); } -void PeerConnection::onSignalingConnected() -{ - logger->debug("Signaling connection established"); +void PeerConnection::onSignalingMessage(SignalingMessage msg) { + logger->debug("Signaling message received: {}", msg.toString()); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - client->sendMessage({ *signals }); + std::visit( + villas::utils::overloaded{ + [&](RelayMessage &c) { extraServers = std::move(c.servers); }, + + [&](ControlMessage &c) { + auto const &id = c.peerID; + + if (c.peers.size() < 2) { + resetConnectionAndStandby(lock); + return; + } + + auto fst = INT_MAX, snd = INT_MAX; + for (auto &c : c.peers) { + if (c.id < fst) { + snd = fst; + fst = c.id; + } else if (c.id < snd) { + snd = c.id; + } + } + + standby = (id != fst && id != snd); + + if (standby) { + logger->error("There are already two peers connected to this " + "session. Waiting in standby."); + return; + } + + if (fst == firstID && snd == secondID) { + logger->debug("Ignoring control message. This connection is " + "already being established."); + return; + } + + resetConnection(lock); + + first = (id == fst); + firstID = fst; + secondID = snd; + + setupPeerConnection(); + + if (!first) { + setupDataChannel(); + conn->setLocalDescription(rtc::Description::Type::Offer); + } + + logger->trace("New connection pair: first={}, second={}, I am {}", + firstID, secondID, first ? "first" : "second"); + }, + + [&](rtc::Description d) { + if (standby || !conn || + (!first && d.type() == rtc::Description::Type::Offer)) + return; + + conn->setRemoteDescription(d); + }, + + [&](rtc::Candidate c) { + if (standby || !conn) + return; + + conn->addRemoteCandidate(c); + }, + + [&](auto other) { logger->warn("unknown signaling message"); }}, + msg.message); } -void PeerConnection::onSignalingDisconnected() -{ - logger->debug("Signaling connection closed"); +void PeerConnection::onDataChannel(std::shared_ptr dc) { + logger->debug( + "New data channel: {}protocol={}, max_msg_size={}, label={}", + dc->id() && dc->stream() + ? fmt::format("id={}, stream={}, ", *(dc->id()), *(dc->stream())) + : "", + dc->protocol(), dc->maxMessageSize(), dc->label()); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - resetConnectionAndStandby(lock); + setupDataChannel(std::move(dc)); } -void PeerConnection::onSignalingError(std::string err) -{ - logger->debug("Signaling connection error: {}", err); +void PeerConnection::onDataChannelOpen() { + logger->debug("Datachannel opened"); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - resetConnectionAndStandby(lock); + chan->send("Hello from VILLASnode"); + + notifyStartup(); } -void PeerConnection::onSignalingMessage(SignalingMessage msg) -{ - logger->debug("Signaling message received: {}", msg.toString()); +void PeerConnection::onDataChannelClosed() { + logger->debug("Datachannel closed"); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - std::visit(villas::utils::overloaded { - [&](RelayMessage &c){ - extraServers = std::move(c.servers); - }, - - [&](ControlMessage &c){ - auto const &id = c.peerID; - - if (c.peers.size() < 2) { - resetConnectionAndStandby(lock); - return; - } - - auto fst = INT_MAX, snd = INT_MAX; - for (auto &c : c.peers) { - if (c.id < fst) { - snd = fst; - fst = c.id; - } else if (c.id < snd) { - snd = c.id; - } - } - - standby = (id != fst && id != snd); - - if (standby) { - logger->error("There are already two peers connected to this session. Waiting in standby."); - return; - } - - if (fst == firstID && snd == secondID) { - logger->debug("Ignoring control message. This connection is already being established."); - return; - } - - resetConnection(lock); - - first = (id == fst); - firstID = fst; - secondID = snd; - - setupPeerConnection(); - - if (!first) { - setupDataChannel(); - conn->setLocalDescription(rtc::Description::Type::Offer); - } - - logger->trace("New connection pair: first={}, second={}, I am {}", firstID, secondID, first ? "first" : "second"); - }, - - [&](rtc::Description d){ - if (standby || !conn || (!first && d.type() == rtc::Description::Type::Offer)) - return; - - conn->setRemoteDescription(d); - }, - - [&](rtc::Candidate c){ - if (standby || !conn) - return; - - conn->addRemoteCandidate(c); - }, - - [&](auto other){ - logger->warn("unknown signaling message"); - } - }, msg.message); + resetConnectionAndStandby(lock); } -void PeerConnection::onDataChannel(std::shared_ptr dc) -{ - logger->debug("New data channel: {}protocol={}, max_msg_size={}, label={}", - dc->id() && dc->stream() ? fmt::format("id={}, stream={}, ", - *(dc->id()), - *(dc->stream()) - ) : "", - dc->protocol(), - dc->maxMessageSize(), - dc->label() - ); +void PeerConnection::onDataChannelError(std::string err) { + logger->error("Datachannel error: {}", err); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - setupDataChannel(std::move(dc)); + resetConnectionAndStandby(lock); } -void PeerConnection::onDataChannelOpen() -{ - logger->debug("Datachannel opened"); - - auto lock = std::unique_lock { mutex }; - - chan->send("Hello from VILLASnode"); - - notifyStartup(); +void PeerConnection::onDataChannelMessage(rtc::string msg) { + logger->info("Received: {}", msg); } -void PeerConnection::onDataChannelClosed() -{ - logger->debug("Datachannel closed"); +void PeerConnection::onDataChannelMessage(rtc::binary msg) { + logger->trace("Received binary data"); - auto lock = std::unique_lock { mutex }; + auto lock = std::unique_lock{mutex}; - resetConnectionAndStandby(lock); -} - -void PeerConnection::onDataChannelError(std::string err) -{ - logger->error("Datachannel error: {}", err); - - auto lock = std::unique_lock { mutex }; - - resetConnectionAndStandby(lock); -} - -void PeerConnection::onDataChannelMessage(rtc::string msg) -{ - logger->info("Received: {}", msg); -} - -void PeerConnection::onDataChannelMessage(rtc::binary msg) -{ - logger->trace("Received binary data"); - - auto lock = std::unique_lock { mutex }; - - if (onMessageCallback) - onMessageCallback(msg); + if (onMessageCallback) + onMessageCallback(msg); } diff --git a/lib/nodes/webrtc/signaling_client.cpp b/lib/nodes/webrtc/signaling_client.cpp index aa3ab8fd9..fb3d6f28f 100644 --- a/lib/nodes/webrtc/signaling_client.cpp +++ b/lib/nodes/webrtc/signaling_client.cpp @@ -9,163 +9,164 @@ #include -#include -#include #include #include #include +#include +#include using namespace villas; using namespace villas::utils; using namespace villas::node; using namespace villas::node::webrtc; -SignalingClient::SignalingClient(const std::string &server, const std::string &session, const std::string &peer, Web *w) : - retry_count(0), - web(w), - running(false), - logger(logging.get("webrtc:signal")) -{ - int ret; - const char *prot, *a, *p; +SignalingClient::SignalingClient(const std::string &server, + const std::string &session, + const std::string &peer, Web *w) + : retry_count(0), web(w), running(false), + logger(logging.get("webrtc:signal")) { + int ret; + const char *prot, *a, *p; - memset(&info, 0, sizeof(info)); + memset(&info, 0, sizeof(info)); - ret = asprintf(&uri, "%s/%s/%s", server.c_str(), session.c_str(), peer.c_str()); - if (ret < 0) - throw RuntimeError { "Could not format signaling server uri" }; + ret = + asprintf(&uri, "%s/%s/%s", server.c_str(), session.c_str(), peer.c_str()); + if (ret < 0) + throw RuntimeError{"Could not format signaling server uri"}; - ret = lws_parse_uri(uri, &prot, &a, &info.port, &p); - if (ret) - throw RuntimeError("Failed to parse WebSocket URI: '{}'", uri); + ret = lws_parse_uri(uri, &prot, &a, &info.port, &p); + if (ret) + throw RuntimeError("Failed to parse WebSocket URI: '{}'", uri); - ret = asprintf(&path, "/%s", p); - if (ret < 0) - throw RuntimeError { "Could not format signaling client path" }; + ret = asprintf(&path, "/%s", p); + if (ret < 0) + throw RuntimeError{"Could not format signaling client path"}; - info.ssl_connection = !strcmp(prot, "https"); - info.address = a; - info.path = path; - info.host = a; - info.origin = a; - info.protocol = "webrtc-signaling"; - info.local_protocol_name = "webrtc-signaling"; - info.pwsi = &wsi; - info.retry_and_idle_policy = &retry; - info.ietf_version_or_minus_one = -1; - info.userdata = this; + info.ssl_connection = !strcmp(prot, "https"); + info.address = a; + info.path = path; + info.host = a; + info.origin = a; + info.protocol = "webrtc-signaling"; + info.local_protocol_name = "webrtc-signaling"; + info.pwsi = &wsi; + info.retry_and_idle_policy = &retry; + info.ietf_version_or_minus_one = -1; + info.userdata = this; - sul_helper.self = this; - sul_helper.sul = {}; + sul_helper.self = this; + sul_helper.sul = {}; } -SignalingClient::~SignalingClient() -{ - disconnect(); +SignalingClient::~SignalingClient() { + disconnect(); - free(path); - free(uri); + free(path); + free(uri); } -void SignalingClient::connect() -{ - running = true; +void SignalingClient::connect() { + running = true; - info.context = web->getContext(); + info.context = web->getContext(); - lws_sul_schedule(info.context, 0, &sul_helper.sul, connectStatic, 1 * LWS_US_PER_SEC); + lws_sul_schedule(info.context, 0, &sul_helper.sul, connectStatic, + 1 * LWS_US_PER_SEC); } -void SignalingClient::disconnect() -{ - running = false; - // TODO: - // - wait for connectStatic to exit - // - close LWS connection - if (wsi) - lws_callback_on_writable(wsi); +void SignalingClient::disconnect() { + running = false; + // TODO: + // - wait for connectStatic to exit + // - close LWS connection + if (wsi) + lws_callback_on_writable(wsi); } -void SignalingClient::connectStatic(struct lws_sorted_usec_list *sul) -{ - auto *sh = lws_container_of(sul, struct sul_offsetof_helper, sul); - auto *c = sh->self; +void SignalingClient::connectStatic(struct lws_sorted_usec_list *sul) { + auto *sh = lws_container_of(sul, struct sul_offsetof_helper, sul); + auto *c = sh->self; - if (!lws_client_connect_via_info(&c->info)) { - /* Failed... schedule a retry... we can't use the _retry_wsi() + if (!lws_client_connect_via_info(&c->info)) { + /* Failed... schedule a retry... we can't use the _retry_wsi() * convenience wrapper api here because no valid wsi at this * point. */ - if (lws_retry_sul_schedule(c->info.context, 0, sul, nullptr, connectStatic, &c->retry_count)) - c->logger->error("Signaling connection attempts exhausted"); - } + if (lws_retry_sul_schedule(c->info.context, 0, sul, nullptr, connectStatic, + &c->retry_count)) + c->logger->error("Signaling connection attempts exhausted"); + } } -int SignalingClient::protocolCallbackStatic(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - auto *c = reinterpret_cast(user); +int SignalingClient::protocolCallbackStatic(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + auto *c = reinterpret_cast(user); - return c->protocolCallback(wsi, reason, in, len); + return c->protocolCallback(wsi, reason, in, len); } -int SignalingClient::protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *in, size_t len) -{ - int ret; +int SignalingClient::protocolCallback(struct lws *wsi, + enum lws_callback_reasons reason, + void *in, size_t len) { + int ret; - switch (reason) { - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - cbError(in ? (char *) in : "unknown error"); - goto do_retry; + switch (reason) { + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + cbError(in ? (char *)in : "unknown error"); + goto do_retry; - case LWS_CALLBACK_CLIENT_RECEIVE: - if (lws_is_first_fragment(wsi)) - buffer.clear(); + case LWS_CALLBACK_CLIENT_RECEIVE: + if (lws_is_first_fragment(wsi)) + buffer.clear(); - buffer.append((char *) in, len); + buffer.append((char *)in, len); - if (lws_is_final_fragment(wsi)) { - logger->trace("Signaling message received: {:.{}}", buffer.data(), buffer.size()); + if (lws_is_final_fragment(wsi)) { + logger->trace("Signaling message received: {:.{}}", buffer.data(), + buffer.size()); - auto *json = buffer.decode(); - if (json == nullptr) { - logger->error("Failed to decode JSON"); - goto do_retry; - } + auto *json = buffer.decode(); + if (json == nullptr) { + logger->error("Failed to decode JSON"); + goto do_retry; + } - cbMessage(SignalingMessage::fromJson(json)); + cbMessage(SignalingMessage::fromJson(json)); - json_decref(json); - } + json_decref(json); + } - break; + break; - case LWS_CALLBACK_CLIENT_ESTABLISHED: - retry_count = 0; - cbConnected(); - break; + case LWS_CALLBACK_CLIENT_ESTABLISHED: + retry_count = 0; + cbConnected(); + break; - case LWS_CALLBACK_CLIENT_CLOSED: - cbDisconnected(); - goto do_retry; + case LWS_CALLBACK_CLIENT_CLOSED: + cbDisconnected(); + goto do_retry; - case LWS_CALLBACK_CLIENT_WRITEABLE: { - ret = writable(); - if (ret) - goto do_retry; + case LWS_CALLBACK_CLIENT_WRITEABLE: { + ret = writable(); + if (ret) + goto do_retry; - break; - } + break; + } - default: - break; - } + default: + break; + } - return lws_callback_http_dummy(wsi, reason, this, in, len); + return lws_callback_http_dummy(wsi, reason, this, in, len); do_retry: - logger->info("Attempting to reconnect..."); + logger->info("Attempting to reconnect..."); - /* Retry the connection to keep it nailed up + /* Retry the connection to keep it nailed up * * For this example, we try to conceal any problem for one set of * backoff retries and then exit the app. @@ -174,53 +175,54 @@ do_retry: * elements in the backoff table, it will never give up and keep * retrying at the last backoff delay plus the random jitter amount. */ - if (lws_retry_sul_schedule_retry_wsi(wsi, &sul_helper.sul, connectStatic, &retry_count)) - logger->error("Signaling connection attempts exhausted"); + if (lws_retry_sul_schedule_retry_wsi(wsi, &sul_helper.sul, connectStatic, + &retry_count)) + logger->error("Signaling connection attempts exhausted"); - return -1; + return -1; } -int SignalingClient::writable() -{ - if (!running) { - auto reason = "Signaling Client Closing"; - lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, (unsigned char *) reason, strlen(reason)); - return 0; - } +int SignalingClient::writable() { + if (!running) { + auto reason = "Signaling Client Closing"; + lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY, (unsigned char *)reason, + strlen(reason)); + return 0; + } - // Skip if we have nothing to send - if (outgoingMessages.empty()) { - return 0; - } + // Skip if we have nothing to send + if (outgoingMessages.empty()) { + return 0; + } - auto msg = outgoingMessages.pop(); - auto *jsonMsg = msg.toJson(); + auto msg = outgoingMessages.pop(); + auto *jsonMsg = msg.toJson(); - if (!jsonMsg) { - return 0; - } + if (!jsonMsg) { + return 0; + } - char buf[LWS_PRE + 4096]; - auto len = json_dumpb(jsonMsg, buf + LWS_PRE, 4096, JSON_INDENT(2)); - if (len > sizeof(buf) - LWS_PRE) - return -1; + char buf[LWS_PRE + 4096]; + auto len = json_dumpb(jsonMsg, buf + LWS_PRE, 4096, JSON_INDENT(2)); + if (len > sizeof(buf) - LWS_PRE) + return -1; - logger->trace("Signaling message send: {:.{}}", buf + LWS_PRE, len); + logger->trace("Signaling message send: {:.{}}", buf + LWS_PRE, len); - auto ret = lws_write(wsi, (unsigned char *) buf + LWS_PRE, len, LWS_WRITE_TEXT); - if (ret < 0) - return ret; + auto ret = + lws_write(wsi, (unsigned char *)buf + LWS_PRE, len, LWS_WRITE_TEXT); + if (ret < 0) + return ret; - // Reschedule callback if there are more messages to be send - if (!outgoingMessages.empty()) - lws_callback_on_writable(wsi); + // Reschedule callback if there are more messages to be send + if (!outgoingMessages.empty()) + lws_callback_on_writable(wsi); - return 0; + return 0; } -void SignalingClient::sendMessage(SignalingMessage msg) -{ - outgoingMessages.push(msg); +void SignalingClient::sendMessage(SignalingMessage msg) { + outgoingMessages.push(msg); - web->callbackOnWritable(wsi); + web->callbackOnWritable(wsi); } diff --git a/lib/nodes/webrtc/signaling_message.cpp b/lib/nodes/webrtc/signaling_message.cpp index 99e61660a..f7c6d0567 100644 --- a/lib/nodes/webrtc/signaling_message.cpp +++ b/lib/nodes/webrtc/signaling_message.cpp @@ -7,227 +7,187 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include -#include #include #include -#include +#include using namespace villas; using namespace villas::node; using namespace villas::node::webrtc; -json_t * Peer::toJson() const -{ - return json_pack("{ s: i, s: s*, s: s*, s: s* }", - "id", id, - "name", name.empty() ? nullptr : name.c_str(), - "remote", remote.empty() ? nullptr : remote.c_str(), - "user_agent", userAgent.empty() ? nullptr : userAgent.c_str() - // TODO: created, connected - ); +json_t *Peer::toJson() const { + return json_pack("{ s: i, s: s*, s: s*, s: s* }", "id", id, "name", + name.empty() ? nullptr : name.c_str(), "remote", + remote.empty() ? nullptr : remote.c_str(), "user_agent", + userAgent.empty() ? nullptr : userAgent.c_str() + // TODO: created, connected + ); } -Peer::Peer(json_t *json) -{ - const char *nme = nullptr, *rem = nullptr, *ua = nullptr, *tscreat, *tsconn; +Peer::Peer(json_t *json) { + const char *nme = nullptr, *rem = nullptr, *ua = nullptr, *tscreat, *tsconn; - int ret = json_unpack(json, "{ s: i, s?: s, s?: s, s?: s, s?: s, s?: s }", - "id", &id, - "name", &nme, - "remote", &rem, - "user_agent", &ua, - "created", &tscreat, - "connected", &tsconn - ); - if (ret) - throw RuntimeError("Failed to decode signaling message"); + int ret = json_unpack(json, "{ s: i, s?: s, s?: s, s?: s, s?: s, s?: s }", + "id", &id, "name", &nme, "remote", &rem, "user_agent", + &ua, "created", &tscreat, "connected", &tsconn); + if (ret) + throw RuntimeError("Failed to decode signaling message"); - if (nme) - name = nme; + if (nme) + name = nme; - if (rem) - remote = rem; + if (rem) + remote = rem; - if (ua) - userAgent = ua; + if (ua) + userAgent = ua; - // TODO: created, connected + // TODO: created, connected } -RelayMessage::RelayMessage(json_t *json) -{ +RelayMessage::RelayMessage(json_t *json) { - if (!json_is_array(json)) - throw RuntimeError("Failed to decode signaling message"); + if (!json_is_array(json)) + throw RuntimeError("Failed to decode signaling message"); - int ret; - char *url; - char *user; - char *pass; - char *realm; - char *expires; - json_t *json_server; - size_t i; - json_array_foreach(json, i, json_server) { - ret = json_unpack(json_server, "{ s: s, s: s, s: s, s: s, s: s }", - "url", &url, - "user", &user, - "pass", &pass, - "realm", &realm, - "expires", &expires - ); - if (ret) - throw RuntimeError("Failed to decode signaling message"); + int ret; + char *url; + char *user; + char *pass; + char *realm; + char *expires; + json_t *json_server; + size_t i; + json_array_foreach(json, i, json_server) { + ret = json_unpack(json_server, "{ s: s, s: s, s: s, s: s, s: s }", "url", + &url, "user", &user, "pass", &pass, "realm", &realm, + "expires", &expires); + if (ret) + throw RuntimeError("Failed to decode signaling message"); - auto &server = servers.emplace_back(url); - server.username = user; - server.password = pass; + auto &server = servers.emplace_back(url); + server.username = user; + server.password = pass; - // TODO: warn about unsupported realm - // TODO: log info about expires time - } + // TODO: warn about unsupported realm + // TODO: log info about expires time + } } -json_t * ControlMessage::toJson() const -{ - json_t *json_peers = json_array(); +json_t *ControlMessage::toJson() const { + json_t *json_peers = json_array(); - for (auto &p : peers) { - json_t *json_peer = p.toJson(); + for (auto &p : peers) { + json_t *json_peer = p.toJson(); - json_array_append_new(json_peers, json_peer); - } + json_array_append_new(json_peers, json_peer); + } - return json_pack("{ s: i, s: o }", - "peer_id", peerID, - "peers", json_peers - ); + return json_pack("{ s: i, s: o }", "peer_id", peerID, "peers", json_peers); } -ControlMessage::ControlMessage(json_t *j) -{ - int ret; +ControlMessage::ControlMessage(json_t *j) { + int ret; - json_t *json_peers; + json_t *json_peers; - ret = json_unpack(j, "{ s: i, s: o }", - "peer_id", &peerID, - "peers", &json_peers - ); - if (ret) - throw RuntimeError("Failed to decode signaling message"); + ret = json_unpack(j, "{ s: i, s: o }", "peer_id", &peerID, "peers", + &json_peers); + if (ret) + throw RuntimeError("Failed to decode signaling message"); - if (!json_is_array(json_peers)) - throw RuntimeError("Failed to decode signaling message"); + if (!json_is_array(json_peers)) + throw RuntimeError("Failed to decode signaling message"); - json_t *json_peer; - size_t i; - // cppcheck-suppress unknownMacro - json_array_foreach(json_peers, i, json_peer) - peers.emplace_back(json_peer); + json_t *json_peer; + size_t i; + // cppcheck-suppress unknownMacro + json_array_foreach(json_peers, i, json_peer) peers.emplace_back(json_peer); } -json_t * SignalingMessage::toJson() const -{ - return std::visit(villas::utils::overloaded { - [](ControlMessage const &c){ - return json_pack("{ s: o }", "control", c.toJson()); - }, - [](SignalList const &s){ - return json_pack("{ s: o }", "signals", s.toJson()); - }, - [](rtc::Description const &d){ - return json_pack("{ s: { s: s, s: s } }", "description", - "spd", d.generateSdp().c_str(), - "type", d.typeString().c_str() - ); - }, - [](rtc::Candidate const &c){ - return json_pack("{ s: { s: s, s: s } }", "candidate", - "spd", c.candidate().c_str(), - "mid", c.mid().c_str() - ); - }, - [](auto &other){ - return (json_t *) { nullptr }; - } - }, message); +json_t *SignalingMessage::toJson() const { + return std::visit( + villas::utils::overloaded{ + [](ControlMessage const &c) { + return json_pack("{ s: o }", "control", c.toJson()); + }, + [](SignalList const &s) { + return json_pack("{ s: o }", "signals", s.toJson()); + }, + [](rtc::Description const &d) { + return json_pack("{ s: { s: s, s: s } }", "description", "spd", + d.generateSdp().c_str(), "type", + d.typeString().c_str()); + }, + [](rtc::Candidate const &c) { + return json_pack("{ s: { s: s, s: s } }", "candidate", "spd", + c.candidate().c_str(), "mid", c.mid().c_str()); + }, + [](auto &other) { return (json_t *){nullptr}; }}, + message); } -std::string SignalingMessage::toString() const -{ - return std::visit(villas::utils::overloaded { - [](RelayMessage const &r){ - return fmt::format("type=relay"); - }, - [](ControlMessage const &c){ - return fmt::format("type=control, control={}", json_dumps(c.toJson(), 0)); - }, - [](SignalList const &s){ - return fmt::format("type=signal"); - }, - [](rtc::Description const &d){ - return fmt::format("type=description, type={}, spd=\n{}", d.typeString(), d.generateSdp()); - }, - [](rtc::Candidate const &c){ - return fmt::format("type=candidate, mid={}, spd=\n{}", c.candidate(), c.mid()); - }, - [](auto other){ - return fmt::format("invalid signaling message"); - } - }, message); +std::string SignalingMessage::toString() const { + return std::visit( + villas::utils::overloaded{ + [](RelayMessage const &r) { return fmt::format("type=relay"); }, + [](ControlMessage const &c) { + return fmt::format("type=control, control={}", + json_dumps(c.toJson(), 0)); + }, + [](SignalList const &s) { return fmt::format("type=signal"); }, + [](rtc::Description const &d) { + return fmt::format("type=description, type={}, spd=\n{}", + d.typeString(), d.generateSdp()); + }, + [](rtc::Candidate const &c) { + return fmt::format("type=candidate, mid={}, spd=\n{}", + c.candidate(), c.mid()); + }, + [](auto other) { return fmt::format("invalid signaling message"); }}, + message); } -SignalingMessage SignalingMessage::fromJson(json_t *json) -{ - auto self = SignalingMessage { std::monostate() }; +SignalingMessage SignalingMessage::fromJson(json_t *json) { + auto self = SignalingMessage{std::monostate()}; - // Relay message - json_t *rlys = nullptr; - // Signal message - json_t *sigs = nullptr; - // Control message - json_t *ctrl = nullptr; - // Candidate message - const char *cand = nullptr; - const char *mid = nullptr; - // Description message - const char *desc = nullptr; - const char *typ = nullptr; + // Relay message + json_t *rlys = nullptr; + // Signal message + json_t *sigs = nullptr; + // Control message + json_t *ctrl = nullptr; + // Candidate message + const char *cand = nullptr; + const char *mid = nullptr; + // Description message + const char *desc = nullptr; + const char *typ = nullptr; - int ret = json_unpack(json, "{ s?: o, s?: o, s?: o, s?: { s: s, s: s }, s?: { s: s, s: s } }", - "servers", &rlys, - "signals", &sigs, - "control", &ctrl, - "candidate", - "spd", &cand, - "mid", &mid, - "description", - "spd", &desc, - "type", &typ - ); + int ret = json_unpack( + json, "{ s?: o, s?: o, s?: o, s?: { s: s, s: s }, s?: { s: s, s: s } }", + "servers", &rlys, "signals", &sigs, "control", &ctrl, "candidate", "spd", + &cand, "mid", &mid, "description", "spd", &desc, "type", &typ); - // Exactly 1 field may be specified - const void *fields[] = { ctrl, cand, desc }; - if (ret || std::count(std::begin(fields), std::end(fields), nullptr) < std::make_signed_t(std::size(fields)) - 1) - throw RuntimeError("Failed to decode signaling message"); + // Exactly 1 field may be specified + const void *fields[] = {ctrl, cand, desc}; + if (ret || std::count(std::begin(fields), std::end(fields), nullptr) < + std::make_signed_t(std::size(fields)) - 1) + throw RuntimeError("Failed to decode signaling message"); - if (rlys) { - self.message.emplace(rlys); - } - else if (sigs) { - self.message.emplace(sigs); - } - else if (ctrl) { - self.message.emplace(ctrl); - } - else if (cand) { - self.message.emplace(cand, mid); - } - else if (desc) { - self.message.emplace(desc, typ); - } + if (rlys) { + self.message.emplace(rlys); + } else if (sigs) { + self.message.emplace(sigs); + } else if (ctrl) { + self.message.emplace(ctrl); + } else if (cand) { + self.message.emplace(cand, mid); + } else if (desc) { + self.message.emplace(desc, typ); + } - return self; + return self; } diff --git a/lib/nodes/websocket.cpp b/lib/nodes/websocket.cpp index c20516efc..2e34ebf6a 100644 --- a/lib/nodes/websocket.cpp +++ b/lib/nodes/websocket.cpp @@ -7,18 +7,18 @@ #include #include -#include #include #include +#include #include -#include #include -#include #include #include #include +#include +#include using namespace villas; using namespace villas::node; @@ -27,129 +27,124 @@ using namespace villas::utils; #define DEFAULT_WEBSOCKET_BUFFER_SIZE (1 << 12) // Private static storage -static -std::list connections; // List of active libwebsocket connections which receive samples from all nodes (catch all) -static -std::mutex connections_lock; +static std::list + connections; // List of active libwebsocket connections which receive samples from all nodes (catch all) +static std::mutex connections_lock; -static -villas::node::Web *web; -static -villas::Logger logger = logging.get("websocket"); +static villas::node::Web *web; +static villas::Logger logger = logging.get("websocket"); // Forward declarations -static -NodeCompatType p; -static -NodeCompatFactory ncp(&p); +static NodeCompatType p; +static NodeCompatFactory ncp(&p); -static -void websocket_destination_destroy(struct websocket_destination *d) -{ - free(d->uri); +static void websocket_destination_destroy(struct websocket_destination *d) { + free(d->uri); - free((char *) d->info.path); - free((char *) d->info.address); + free((char *)d->info.path); + free((char *)d->info.address); } -static -int websocket_connection_init(struct websocket_connection *c) -{ - int ret; +static int websocket_connection_init(struct websocket_connection *c) { + int ret; - ret = queue_init(&c->queue, DEFAULT_QUEUE_LENGTH); - if (ret) - return ret; + ret = queue_init(&c->queue, DEFAULT_QUEUE_LENGTH); + if (ret) + return ret; - c->formatter->start(c->node->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + c->formatter->start(c->node->getInputSignals(false), + ~(int)SampleFlags::HAS_OFFSET); - c->buffers.recv = new Buffer(DEFAULT_WEBSOCKET_BUFFER_SIZE); - c->buffers.send = new Buffer(DEFAULT_WEBSOCKET_BUFFER_SIZE); + c->buffers.recv = new Buffer(DEFAULT_WEBSOCKET_BUFFER_SIZE); + c->buffers.send = new Buffer(DEFAULT_WEBSOCKET_BUFFER_SIZE); - if (!c->buffers.recv || !c->buffers.send) - throw MemoryAllocationError(); + if (!c->buffers.recv || !c->buffers.send) + throw MemoryAllocationError(); - c->state = websocket_connection::State::INITIALIZED; + c->state = websocket_connection::State::INITIALIZED; - return 0; + return 0; } -static -int websocket_connection_destroy(struct websocket_connection *c) -{ - int ret; +static int websocket_connection_destroy(struct websocket_connection *c) { + int ret; - assert(c->state != websocket_connection::State::DESTROYED); + assert(c->state != websocket_connection::State::DESTROYED); - // Return all samples to pool - int avail; - struct Sample *smp; + // Return all samples to pool + int avail; + struct Sample *smp; - while ((avail = queue_pull(&c->queue, (void **) &smp))) - sample_decref(smp); + while ((avail = queue_pull(&c->queue, (void **)&smp))) + sample_decref(smp); - ret = queue_destroy(&c->queue); - if (ret) - return ret; + ret = queue_destroy(&c->queue); + if (ret) + return ret; - delete c->formatter; - delete c->buffers.recv; - delete c->buffers.send; + delete c->formatter; + delete c->buffers.recv; + delete c->buffers.send; - c->wsi = nullptr; - c->state = websocket_connection::State::DESTROYED; + c->wsi = nullptr; + c->state = websocket_connection::State::DESTROYED; - return 0; + return 0; } -static -int websocket_connection_write(struct websocket_connection *c, struct Sample * const smps[], unsigned cnt) -{ - int pushed; +static int websocket_connection_write(struct websocket_connection *c, + struct Sample *const smps[], + unsigned cnt) { + int pushed; - if (c->state != websocket_connection::State::ESTABLISHED) - return -1; + if (c->state != websocket_connection::State::ESTABLISHED) + return -1; - pushed = queue_push_many(&c->queue, (void **) smps, cnt); - if (pushed < (int) cnt) - c->node->logger->warn("Queue overrun in WebSocket connection: {}", c->toString()); + pushed = queue_push_many(&c->queue, (void **)smps, cnt); + if (pushed < (int)cnt) + c->node->logger->warn("Queue overrun in WebSocket connection: {}", + c->toString()); - sample_incref_many(smps, pushed); + sample_incref_many(smps, pushed); - c->node->logger->debug("Enqueued {} samples to {}", pushed, c->toString()); + c->node->logger->debug("Enqueued {} samples to {}", pushed, c->toString()); - // Client connections which are currently connecting don't have an associate c->wsi yet - if (c->wsi) - web->callbackOnWritable(c->wsi); - else - c->node->logger->warn("No WSI for conn?"); + // Client connections which are currently connecting don't have an associate c->wsi yet + if (c->wsi) + web->callbackOnWritable(c->wsi); + else + c->node->logger->warn("No WSI for conn?"); - return 0; + return 0; } -static -void websocket_connection_close(struct websocket_connection *c, struct lws *wsi, enum lws_close_status status, const char *reason) -{ - lws_close_reason(wsi, status, (unsigned char *) reason, strlen(reason)); +static void websocket_connection_close(struct websocket_connection *c, + struct lws *wsi, + enum lws_close_status status, + const char *reason) { + lws_close_reason(wsi, status, (unsigned char *)reason, strlen(reason)); - c->node->logger->debug("Closing WebSocket connection with {}: status={}, reason={}", c->toString(), status, reason); + c->node->logger->debug( + "Closing WebSocket connection with {}: status={}, reason={}", + c->toString(), status, reason); - c->state = websocket_connection::State::CLOSED; + c->state = websocket_connection::State::CLOSED; } -int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - int ret, recvd, pulled, cnt = 128; - struct websocket_connection *c = (struct websocket_connection *) user; +int villas::node::websocket_protocol_cb(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + int ret, recvd, pulled, cnt = 128; + struct websocket_connection *c = (struct websocket_connection *)user; - switch (reason) { - case LWS_CALLBACK_CLIENT_ESTABLISHED: - case LWS_CALLBACK_ESTABLISHED: - if (reason == LWS_CALLBACK_CLIENT_ESTABLISHED) - c->mode = websocket_connection::Mode::CLIENT; - else { - c->mode = websocket_connection::Mode::SERVER; - /* We use the URI to associate this connection to a node + switch (reason) { + case LWS_CALLBACK_CLIENT_ESTABLISHED: + case LWS_CALLBACK_ESTABLISHED: + if (reason == LWS_CALLBACK_CLIENT_ESTABLISHED) + c->mode = websocket_connection::Mode::CLIENT; + else { + c->mode = websocket_connection::Mode::SERVER; + /* We use the URI to associate this connection to a node * and choose a protocol. * * Example: ws://example.com/node_1.json @@ -157,488 +152,507 @@ int villas::node::websocket_protocol_cb(struct lws *wsi, enum lws_callback_reaso * and format 'json'. */ - // Get path of incoming request - char *node, *format, *lasts; - char uri[64]; + // Get path of incoming request + char *node, *format, *lasts; + char uri[64]; - lws_hdr_copy(wsi, uri, sizeof(uri), WSI_TOKEN_GET_URI); /* The path component of the*/ - if (strlen(uri) <= 0) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, "Invalid URL"); - logger->warn("Failed to get request URI"); - return -1; - } + lws_hdr_copy(wsi, uri, sizeof(uri), + WSI_TOKEN_GET_URI); /* The path component of the*/ + if (strlen(uri) <= 0) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, + "Invalid URL"); + logger->warn("Failed to get request URI"); + return -1; + } - node = strtok_r(uri, "/.", &lasts); - if (!node) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Unknown node"); - logger->warn("Failed to tokenize request URI"); - return -1; - } + node = strtok_r(uri, "/.", &lasts); + if (!node) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Unknown node"); + logger->warn("Failed to tokenize request URI"); + return -1; + } - format = strtok_r(nullptr, "", &lasts); - if (!format) - format = (char *) "villas.web"; + format = strtok_r(nullptr, "", &lasts); + if (!format) + format = (char *)"villas.web"; - // Search for node whose name matches the URI - auto *n = ncp.instances.lookup(node); - if (!n) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Unknown node"); - logger->warn("Failed to find node: {}", node); - return -1; - } + // Search for node whose name matches the URI + auto *n = ncp.instances.lookup(node); + if (!n) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Unknown node"); + logger->warn("Failed to find node: {}", node); + return -1; + } - c->node = dynamic_cast(n); - if (!c->node) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Unknown node"); - logger->warn("Failed to find node: {}", node); - return -1; - } + c->node = dynamic_cast(n); + if (!c->node) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Unknown node"); + logger->warn("Failed to find node: {}", node); + return -1; + } - c->formatter = FormatFactory::make(format); - if (!c->formatter) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Unknown format"); - c->node->logger->warn("Failed to find format: format={}", format); - return -1; - } - } + c->formatter = FormatFactory::make(format); + if (!c->formatter) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Unknown format"); + c->node->logger->warn("Failed to find format: format={}", format); + return -1; + } + } - ret = websocket_connection_init(c); - if (ret) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, "Internal error"); - c->node->logger->warn("Failed to intialize WebSocket connection: reason={}", ret); - return -1; - } + ret = websocket_connection_init(c); + if (ret) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, + "Internal error"); + c->node->logger->warn( + "Failed to intialize WebSocket connection: reason={}", ret); + return -1; + } - c->wsi = wsi; - c->state = websocket_connection::State::ESTABLISHED; - c->node->logger->info("Established WebSocket connection: {}", c->toString()); + c->wsi = wsi; + c->state = websocket_connection::State::ESTABLISHED; + c->node->logger->info("Established WebSocket connection: {}", + c->toString()); - { - std::lock_guard guard(connections_lock); - connections.push_back(c); - } + { + std::lock_guard guard(connections_lock); + connections.push_back(c); + } - break; + break; - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - c->state = websocket_connection::State::ERROR; + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + c->state = websocket_connection::State::ERROR; - logger->warn("Failed to establish WebSocket connection: reason={}", in ? (char *) in : "unknown"); + logger->warn("Failed to establish WebSocket connection: reason={}", + in ? (char *)in : "unknown"); - return -1; + return -1; - case LWS_CALLBACK_CLOSED: - c->state = websocket_connection::State::CLOSED; - c->node->logger->debug("Closed WebSocket connection: {}", c->toString()); + case LWS_CALLBACK_CLOSED: + c->state = websocket_connection::State::CLOSED; + c->node->logger->debug("Closed WebSocket connection: {}", c->toString()); - if (c->state != websocket_connection::State::CLOSING) { - // TODO: Attempt reconnect here - } + if (c->state != websocket_connection::State::CLOSING) { + // TODO: Attempt reconnect here + } - { - std::lock_guard guard(connections_lock); - connections.remove(c); - } + { + std::lock_guard guard(connections_lock); + connections.remove(c); + } - ret = websocket_connection_destroy(c); - if (ret) - return ret; + ret = websocket_connection_destroy(c); + if (ret) + return ret; - if (c->mode == websocket_connection::Mode::CLIENT) - delete c; + if (c->mode == websocket_connection::Mode::CLIENT) + delete c; - break; + break; - case LWS_CALLBACK_CLIENT_WRITEABLE: - case LWS_CALLBACK_SERVER_WRITEABLE: { - struct Sample *smps[cnt]; + case LWS_CALLBACK_CLIENT_WRITEABLE: + case LWS_CALLBACK_SERVER_WRITEABLE: { + struct Sample *smps[cnt]; - pulled = queue_pull_many(&c->queue, (void **) smps, cnt); - if (pulled > 0) { - size_t wbytes; - c->formatter->sprint(c->buffers.send->data() + LWS_PRE, c->buffers.send->size() - LWS_PRE, &wbytes, smps, pulled); + pulled = queue_pull_many(&c->queue, (void **)smps, cnt); + if (pulled > 0) { + size_t wbytes; + c->formatter->sprint(c->buffers.send->data() + LWS_PRE, + c->buffers.send->size() - LWS_PRE, &wbytes, smps, + pulled); - auto isBinary = dynamic_cast(c->formatter) != nullptr; - ret = lws_write(wsi, (unsigned char *) c->buffers.send->data() + LWS_PRE, wbytes, isBinary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT); + auto isBinary = dynamic_cast(c->formatter) != nullptr; + ret = lws_write(wsi, (unsigned char *)c->buffers.send->data() + LWS_PRE, + wbytes, isBinary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT); - sample_decref_many(smps, pulled); + sample_decref_many(smps, pulled); - if (ret < 0) - return ret; + if (ret < 0) + return ret; - c->node->logger->debug("Send {} samples to connection: {}, bytes={}", pulled, c->toString(), ret); - } + c->node->logger->debug("Send {} samples to connection: {}, bytes={}", + pulled, c->toString(), ret); + } - if (queue_available(&c->queue) > 0) - lws_callback_on_writable(wsi); - else if (c->state == websocket_connection::State::CLOSING) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_GOINGAWAY, "Node stopped"); - return -1; - } + if (queue_available(&c->queue) > 0) + lws_callback_on_writable(wsi); + else if (c->state == websocket_connection::State::CLOSING) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_GOINGAWAY, + "Node stopped"); + return -1; + } - break; - } + break; + } - case LWS_CALLBACK_CLIENT_RECEIVE: - case LWS_CALLBACK_RECEIVE: - if (lws_is_first_fragment(wsi)) - c->buffers.recv->clear(); + case LWS_CALLBACK_CLIENT_RECEIVE: + case LWS_CALLBACK_RECEIVE: + if (lws_is_first_fragment(wsi)) + c->buffers.recv->clear(); - c->buffers.recv->append((char *) in, len); + c->buffers.recv->append((char *)in, len); - // We dont try to parse the frame yet, as we have to wait for the remaining fragments - if (lws_is_final_fragment(wsi)) { - struct timespec ts_recv = time_now(); - auto *n = c->node; + // We dont try to parse the frame yet, as we have to wait for the remaining fragments + if (lws_is_final_fragment(wsi)) { + struct timespec ts_recv = time_now(); + auto *n = c->node; - int avail, enqueued; - auto *w = n->getData(); - struct Sample *smps[cnt]; + int avail, enqueued; + auto *w = n->getData(); + struct Sample *smps[cnt]; - avail = sample_alloc_many(&w->pool, smps, cnt); - if (avail < cnt) - c->node->logger->warn("Pool underrun for connection: {}", c->toString()); + avail = sample_alloc_many(&w->pool, smps, cnt); + if (avail < cnt) + c->node->logger->warn("Pool underrun for connection: {}", + c->toString()); - recvd = c->formatter->sscan(c->buffers.recv->data(), c->buffers.recv->size(), nullptr, smps, avail); - if (recvd < 0) { - c->node->logger->warn("Failed to parse sample data received on connection: {}", c->toString()); - break; - } + recvd = + c->formatter->sscan(c->buffers.recv->data(), c->buffers.recv->size(), + nullptr, smps, avail); + if (recvd < 0) { + c->node->logger->warn( + "Failed to parse sample data received on connection: {}", + c->toString()); + break; + } - c->node->logger->debug("Received {} samples from connection: {}", recvd, c->toString()); + c->node->logger->debug("Received {} samples from connection: {}", recvd, + c->toString()); - // Set receive timestamp - for (int i = 0; i < recvd; i++) { - smps[i]->ts.received = ts_recv; - smps[i]->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + // Set receive timestamp + for (int i = 0; i < recvd; i++) { + smps[i]->ts.received = ts_recv; + smps[i]->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - enqueued = queue_signalled_push_many(&w->queue, (void **) smps, recvd); - if (enqueued < recvd) - c->node->logger->warn("Queue overrun in connection: {}", c->toString()); + enqueued = queue_signalled_push_many(&w->queue, (void **)smps, recvd); + if (enqueued < recvd) + c->node->logger->warn("Queue overrun in connection: {}", c->toString()); - // Release unused samples back to pool - if (enqueued < avail) - sample_decref_many(&smps[enqueued], avail - enqueued); + // Release unused samples back to pool + if (enqueued < avail) + sample_decref_many(&smps[enqueued], avail - enqueued); - c->buffers.recv->clear(); + c->buffers.recv->clear(); - if (c->state == websocket_connection::State::CLOSING) { - websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_GOINGAWAY, "Node stopped"); - return -1; - } - } + if (c->state == websocket_connection::State::CLOSING) { + websocket_connection_close(c, wsi, LWS_CLOSE_STATUS_GOINGAWAY, + "Node stopped"); + return -1; + } + } - break; + break; - default: - break; - } + default: + break; + } - return 0; + return 0; } -int villas::node::websocket_type_start(villas::node::SuperNode *sn) -{ - if (sn == nullptr) - throw RuntimeError("WebSocket node-type requires super-node"); +int villas::node::websocket_type_start(villas::node::SuperNode *sn) { + if (sn == nullptr) + throw RuntimeError("WebSocket node-type requires super-node"); - web = sn->getWeb(); - if (!web->isEnabled()) - return -1; + web = sn->getWeb(); + if (!web->isEnabled()) + return -1; - return 0; + return 0; } -int villas::node::websocket_init(NodeCompat *n) -{ - auto *w = n->getData(); +int villas::node::websocket_init(NodeCompat *n) { + auto *w = n->getData(); - w->wait = false; + w->wait = false; - int ret = list_init(&w->destinations); - if (ret) - return ret; + int ret = list_init(&w->destinations); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::websocket_start(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::websocket_start(NodeCompat *n) { + int ret; + auto *w = n->getData(); - ret = pool_init(&w->pool, DEFAULT_WEBSOCKET_QUEUE_LENGTH, SAMPLE_LENGTH(n->getInputSignals(false)->size())); - if (ret) - return ret; + ret = pool_init(&w->pool, DEFAULT_WEBSOCKET_QUEUE_LENGTH, + SAMPLE_LENGTH(n->getInputSignals(false)->size())); + if (ret) + return ret; - ret = queue_signalled_init(&w->queue, DEFAULT_WEBSOCKET_QUEUE_LENGTH); - if (ret) - return ret; + ret = queue_signalled_init(&w->queue, DEFAULT_WEBSOCKET_QUEUE_LENGTH); + if (ret) + return ret; - for (size_t i = 0; i < list_length(&w->destinations); i++) { - const char *format; - auto *d = (struct websocket_destination *) list_at(&w->destinations, i); - auto *c = new struct websocket_connection; - if (!c) - throw MemoryAllocationError(); + for (size_t i = 0; i < list_length(&w->destinations); i++) { + const char *format; + auto *d = (struct websocket_destination *)list_at(&w->destinations, i); + auto *c = new struct websocket_connection; + if (!c) + throw MemoryAllocationError(); - c->state = websocket_connection::State::CONNECTING; + c->state = websocket_connection::State::CONNECTING; - format = strchr(d->info.path, '.'); - if (format) - format = format + 1; // Removes "." - else - format = "villas.web"; + format = strchr(d->info.path, '.'); + if (format) + format = format + 1; // Removes "." + else + format = "villas.web"; - c->formatter = FormatFactory::make(format); - if (!c->formatter) - return -1; + c->formatter = FormatFactory::make(format); + if (!c->formatter) + return -1; - c->node = n; - c->destination = d; + c->node = n; + c->destination = d; - d->info.context = web->getContext(); - d->info.vhost = web->getVHost(); - d->info.userdata = c; + d->info.context = web->getContext(); + d->info.vhost = web->getVHost(); + d->info.userdata = c; - lws_client_connect_via_info(&d->info); - } + lws_client_connect_via_info(&d->info); + } - // Wait until all destinations are connected - if (w->wait) { - unsigned connected = 0, total = list_length(&w->destinations); - do { - { - std::lock_guard guard(connections_lock); + // Wait until all destinations are connected + if (w->wait) { + unsigned connected = 0, total = list_length(&w->destinations); + do { + { + std::lock_guard guard(connections_lock); - connected = 0; - for (auto *c : connections) { - if (c->mode == websocket_connection::Mode::CLIENT && - c->state == websocket_connection::State::ESTABLISHED && - c->node == n) - connected++; - } - } + connected = 0; + for (auto *c : connections) { + if (c->mode == websocket_connection::Mode::CLIENT && + c->state == websocket_connection::State::ESTABLISHED && + c->node == n) + connected++; + } + } - if (connected < total) { - n->logger->info("Wait until all destinations are connected: pending={}", total - connected); - sleep(1); - } - } while (connected < total); - } + if (connected < total) { + n->logger->info("Wait until all destinations are connected: pending={}", + total - connected); + sleep(1); + } + } while (connected < total); + } - return 0; + return 0; } -int villas::node::websocket_stop(NodeCompat *n) -{ - int ret; - auto *w = n->getData(); +int villas::node::websocket_stop(NodeCompat *n) { + int ret; + auto *w = n->getData(); - unsigned open_connections; - do { - { - std::lock_guard guard(connections_lock); + unsigned open_connections; + do { + { + std::lock_guard guard(connections_lock); - open_connections = 0; - for (auto *c : connections) { - if (c->node == n) { - if (c->state != websocket_connection::State::CLOSED) { - open_connections++; + open_connections = 0; + for (auto *c : connections) { + if (c->node == n) { + if (c->state != websocket_connection::State::CLOSED) { + open_connections++; - c->state = websocket_connection::State::CLOSING; - lws_callback_on_writable(c->wsi); - } - } - } - } + c->state = websocket_connection::State::CLOSING; + lws_callback_on_writable(c->wsi); + } + } + } + } - if (open_connections > 0) { - n->logger->info("Waiting for open connections to be closed: pending={}", open_connections); - sleep(1); - } - } while (open_connections > 0); + if (open_connections > 0) { + n->logger->info("Waiting for open connections to be closed: pending={}", + open_connections); + sleep(1); + } + } while (open_connections > 0); - ret = queue_signalled_close(&w->queue); - if (ret) - return ret; + ret = queue_signalled_close(&w->queue); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::websocket_destroy(NodeCompat *n) -{ - auto *w = n->getData(); - int ret; +int villas::node::websocket_destroy(NodeCompat *n) { + auto *w = n->getData(); + int ret; - ret = queue_signalled_destroy(&w->queue); - if (ret) - return ret; + ret = queue_signalled_destroy(&w->queue); + if (ret) + return ret; - ret = pool_destroy(&w->pool); - if (ret) - return ret; + ret = pool_destroy(&w->pool); + if (ret) + return ret; - ret = list_destroy(&w->destinations, (dtor_cb_t) websocket_destination_destroy, true); - if (ret) - return ret; + ret = list_destroy(&w->destinations, (dtor_cb_t)websocket_destination_destroy, + true); + if (ret) + return ret; - return 0; + return 0; } -int villas::node::websocket_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int avail; +int villas::node::websocket_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int avail; - auto *w = n->getData(); - struct Sample *cpys[cnt]; + auto *w = n->getData(); + struct Sample *cpys[cnt]; - avail = queue_signalled_pull_many(&w->queue, (void **) cpys, cnt); - if (avail < 0) - return avail; + avail = queue_signalled_pull_many(&w->queue, (void **)cpys, cnt); + if (avail < 0) + return avail; - sample_copy_many(smps, cpys, avail); - sample_decref_many(cpys, avail); + sample_copy_many(smps, cpys, avail); + sample_decref_many(cpys, avail); - return avail; + return avail; } -int villas::node::websocket_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int avail; +int villas::node::websocket_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int avail; - auto *w = n->getData(); - struct Sample *cpys[cnt]; + auto *w = n->getData(); + struct Sample *cpys[cnt]; - // Make copies of all samples - avail = sample_alloc_many(&w->pool, cpys, cnt); - if (avail < (int) cnt) - n->logger->warn("Pool underrun: avail={}", avail); + // Make copies of all samples + avail = sample_alloc_many(&w->pool, cpys, cnt); + if (avail < (int)cnt) + n->logger->warn("Pool underrun: avail={}", avail); - sample_copy_many(cpys, smps, avail); + sample_copy_many(cpys, smps, avail); - { - std::lock_guard guard(connections_lock); - for (auto *c : connections) { - if (c->node == n) - websocket_connection_write(c, cpys, cnt); - } - } + { + std::lock_guard guard(connections_lock); + for (auto *c : connections) { + if (c->node == n) + websocket_connection_write(c, cpys, cnt); + } + } - sample_decref_many(cpys, avail); + sample_decref_many(cpys, avail); - return cnt; + return cnt; } -int villas::node::websocket_parse(NodeCompat *n, json_t *json) -{ - auto *w = n->getData(); - int ret; +int villas::node::websocket_parse(NodeCompat *n, json_t *json) { + auto *w = n->getData(); + int ret; - size_t i; - json_t *json_dests = nullptr; - json_t *json_dest; - json_error_t err; - int wc = -1; + size_t i; + json_t *json_dests = nullptr; + json_t *json_dest; + json_error_t err; + int wc = -1; - ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: b }", - "destinations", &json_dests, - "wait_connected", &wc - ); - if (ret) - throw ConfigError(json, err, "node-config-node-websocket"); + ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: b }", "destinations", + &json_dests, "wait_connected", &wc); + if (ret) + throw ConfigError(json, err, "node-config-node-websocket"); - if (wc >= 0) - w->wait = wc != 0; + if (wc >= 0) + w->wait = wc != 0; - list_clear(&w->destinations); - if (json_dests) { - if (!json_is_array(json_dests)) - throw ConfigError(json_dests, err, "node-config-node-websocket-destinations", "The 'destinations' setting must be an array of URLs"); + list_clear(&w->destinations); + if (json_dests) { + if (!json_is_array(json_dests)) + throw ConfigError(json_dests, err, + "node-config-node-websocket-destinations", + "The 'destinations' setting must be an array of URLs"); - json_array_foreach(json_dests, i, json_dest) { - const char *uri, *prot, *ads, *path; + json_array_foreach(json_dests, i, json_dest) { + const char *uri, *prot, *ads, *path; - uri = json_string_value(json_dest); - if (!uri) - throw ConfigError(json_dest, err, "node-config-node-websocket-destinations", "The 'destinations' setting must be an array of URLs"); + uri = json_string_value(json_dest); + if (!uri) + throw ConfigError( + json_dest, err, "node-config-node-websocket-destinations", + "The 'destinations' setting must be an array of URLs"); - auto *d = new struct websocket_destination; - if (!d) - throw MemoryAllocationError(); + auto *d = new struct websocket_destination; + if (!d) + throw MemoryAllocationError(); - memset(d, 0, sizeof(struct websocket_destination)); + memset(d, 0, sizeof(struct websocket_destination)); - d->uri = strdup(uri); + d->uri = strdup(uri); - ret = lws_parse_uri(d->uri, &prot, &ads, &d->info.port, &path); - if (ret) - throw ConfigError(json_dest, err, "node-config-node-websocket-destinations", "Failed to parse WebSocket URI: '{}'", uri); + ret = lws_parse_uri(d->uri, &prot, &ads, &d->info.port, &path); + if (ret) + throw ConfigError(json_dest, err, + "node-config-node-websocket-destinations", + "Failed to parse WebSocket URI: '{}'", uri); - d->info.ssl_connection = !strcmp(prot, "https"); - d->info.address = strdup(ads); - d->info.path = strf("/%s", path); - d->info.host = d->info.address; - d->info.origin = d->info.address; - d->info.ietf_version_or_minus_one = -1; - d->info.protocol = "live"; + d->info.ssl_connection = !strcmp(prot, "https"); + d->info.address = strdup(ads); + d->info.path = strf("/%s", path); + d->info.host = d->info.address; + d->info.origin = d->info.address; + d->info.ietf_version_or_minus_one = -1; + d->info.protocol = "live"; - list_push(&w->destinations, d); - } - } + list_push(&w->destinations, d); + } + } - return 0; + return 0; } -char * villas::node::websocket_print(NodeCompat *n) -{ - auto *w = n->getData(); +char *villas::node::websocket_print(NodeCompat *n) { + auto *w = n->getData(); - char *buf = nullptr; + char *buf = nullptr; - buf = strcatf(&buf, "destinations=[ "); + buf = strcatf(&buf, "destinations=[ "); - for (size_t i = 0; i < list_length(&w->destinations); i++) { - struct websocket_destination *d = (struct websocket_destination *) list_at(&w->destinations, i); + for (size_t i = 0; i < list_length(&w->destinations); i++) { + struct websocket_destination *d = + (struct websocket_destination *)list_at(&w->destinations, i); - buf = strcatf(&buf, "%s://%s:%d/%s ", - d->info.ssl_connection ? "wss" : "ws", - d->info.address, - d->info.port, - d->info.path - ); - } + buf = strcatf(&buf, "%s://%s:%d/%s ", d->info.ssl_connection ? "wss" : "ws", + d->info.address, d->info.port, d->info.path); + } - buf = strcatf(&buf, "]"); + buf = strcatf(&buf, "]"); - return buf; + return buf; } -int villas::node::websocket_poll_fds(NodeCompat *n, int fds[]) -{ - auto *w = n->getData(); +int villas::node::websocket_poll_fds(NodeCompat *n, int fds[]) { + auto *w = n->getData(); - fds[0] = queue_signalled_fd(&w->queue); + fds[0] = queue_signalled_fd(&w->queue); - return 1; + return 1; } -__attribute__((constructor(110))) static -void UNIQUE(__ctor)() { - p.name = "websocket"; - p.description = "Send and receive samples of a WebSocket connection (libwebsockets)"; - p.vectorize = 0; - p.size = sizeof(struct websocket); - p.type.start = websocket_type_start; - p.init = websocket_init; - p.destroy = websocket_destroy; - p.parse = websocket_parse; - p.print = websocket_print; - p.start = websocket_start; - p.stop = websocket_stop; - p.read = websocket_read; - p.write = websocket_write; - p.poll_fds = websocket_poll_fds; - p.flags = (int) NodeFactory::Flags::REQUIRES_WEB; +__attribute__((constructor(110))) static void UNIQUE(__ctor)() { + p.name = "websocket"; + p.description = + "Send and receive samples of a WebSocket connection (libwebsockets)"; + p.vectorize = 0; + p.size = sizeof(struct websocket); + p.type.start = websocket_type_start; + p.init = websocket_init; + p.destroy = websocket_destroy; + p.parse = websocket_parse; + p.print = websocket_print; + p.start = websocket_start; + p.stop = websocket_stop; + p.read = websocket_read; + p.write = websocket_write; + p.poll_fds = websocket_poll_fds; + p.flags = (int)NodeFactory::Flags::REQUIRES_WEB; } diff --git a/lib/nodes/zeromq.cpp b/lib/nodes/zeromq.cpp index 216dbc071..23ef45675 100644 --- a/lib/nodes/zeromq.cpp +++ b/lib/nodes/zeromq.cpp @@ -9,649 +9,636 @@ #include #if ZMQ_VERSION_MAJOR < 4 || (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR <= 1) - #include +#include #endif +#include #include #include +#include #include #include -#include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -static -void *context; +static void *context; /* Read one event off the monitor socket; return value and address * by reference, if not null, and event number by value. * * @returnval -1 In case of error. */ -static -int get_monitor_event(void *monitor, int *value, char **address) -{ - // First frame in message contains event number and value - zmq_msg_t msg; - zmq_msg_init (&msg); - if (zmq_msg_recv (&msg, monitor, 0) == -1) - return -1; // Interruped, presumably +static int get_monitor_event(void *monitor, int *value, char **address) { + // First frame in message contains event number and value + zmq_msg_t msg; + zmq_msg_init(&msg); + if (zmq_msg_recv(&msg, monitor, 0) == -1) + return -1; // Interruped, presumably - assert(zmq_msg_more (&msg)); + assert(zmq_msg_more(&msg)); - uint8_t *data = (uint8_t *) zmq_msg_data(&msg); - uint16_t event = *(uint16_t *) (data); - if (value) - *value = *(uint32_t *) (data + 2); + uint8_t *data = (uint8_t *)zmq_msg_data(&msg); + uint16_t event = *(uint16_t *)(data); + if (value) + *value = *(uint32_t *)(data + 2); - // Second frame in message contains event address - zmq_msg_init(&msg); - if (zmq_msg_recv(&msg, monitor, 0) == -1) - return -1; // Interruped, presumably + // Second frame in message contains event address + zmq_msg_init(&msg); + if (zmq_msg_recv(&msg, monitor, 0) == -1) + return -1; // Interruped, presumably - assert(!zmq_msg_more(&msg)); + assert(!zmq_msg_more(&msg)); - if (address) { - uint8_t *data = (uint8_t *) zmq_msg_data(&msg); - size_t size = zmq_msg_size(&msg); - *address = (char *) malloc(size + 1); - memcpy(*address, data, size); - *address [size] = 0; - } + if (address) { + uint8_t *data = (uint8_t *)zmq_msg_data(&msg); + size_t size = zmq_msg_size(&msg); + *address = (char *)malloc(size + 1); + memcpy(*address, data, size); + *address[size] = 0; + } - return event; + return event; } -int villas::node::zeromq_reverse(NodeCompat *n) -{ - auto *z = n->getData(); +int villas::node::zeromq_reverse(NodeCompat *n) { + auto *z = n->getData(); - if (list_length(&z->out.endpoints) != 1 || - list_length(&z->in.endpoints) != 1) - return -1; + if (list_length(&z->out.endpoints) != 1 || list_length(&z->in.endpoints) != 1) + return -1; - char *subscriber = (char *) list_first(&z->in.endpoints); - char *publisher = (char *) list_first(&z->out.endpoints); + char *subscriber = (char *)list_first(&z->in.endpoints); + char *publisher = (char *)list_first(&z->out.endpoints); - list_set(&z->in.endpoints, 0, publisher); - list_set(&z->out.endpoints, 0, subscriber); + list_set(&z->in.endpoints, 0, publisher); + list_set(&z->out.endpoints, 0, subscriber); - return 0; + return 0; } -int villas::node::zeromq_init(NodeCompat *n) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_init(NodeCompat *n) { + int ret; + auto *z = n->getData(); - z->out.bind = 1; - z->in.bind = 0; + z->out.bind = 1; + z->in.bind = 0; - z->curve.enabled = false; - z->ipv6 = 0; + z->curve.enabled = false; + z->ipv6 = 0; - z->in.pending = 0; - z->out.pending = 0; + z->in.pending = 0; + z->out.pending = 0; - ret = list_init(&z->in.endpoints); - if (ret) - return ret; + ret = list_init(&z->in.endpoints); + if (ret) + return ret; - ret = list_init(&z->out.endpoints); - if (ret) - return ret; + ret = list_init(&z->out.endpoints); + if (ret) + return ret; - z->formatter = nullptr; + z->formatter = nullptr; - return 0; + return 0; } -static -int zeromq_parse_endpoints(json_t *json_ep, struct List *epl) -{ - json_t *json_val; - size_t i; - const char *ep; +static int zeromq_parse_endpoints(json_t *json_ep, struct List *epl) { + json_t *json_val; + size_t i; + const char *ep; - switch (json_typeof(json_ep)) { - case JSON_ARRAY: - json_array_foreach(json_ep, i, json_val) { - ep = json_string_value(json_val); - if (!ep) - throw ConfigError(json_val, "node-config-node-publish", "All 'publish' settings must be strings"); + switch (json_typeof(json_ep)) { + case JSON_ARRAY: + json_array_foreach(json_ep, i, json_val) { + ep = json_string_value(json_val); + if (!ep) + throw ConfigError(json_val, "node-config-node-publish", + "All 'publish' settings must be strings"); - list_push(epl, strdup(ep)); - } - break; + list_push(epl, strdup(ep)); + } + break; - case JSON_STRING: - ep = json_string_value(json_ep); - list_push(epl, strdup(ep)); - break; + case JSON_STRING: + ep = json_string_value(json_ep); + list_push(epl, strdup(ep)); + break; - default: - return -1; - } + default: + return -1; + } - return 0; + return 0; } -int villas::node::zeromq_parse(NodeCompat *n, json_t *json) -{ - auto *z = n->getData(); +int villas::node::zeromq_parse(NodeCompat *n, json_t *json) { + auto *z = n->getData(); - int ret; - const char *type = nullptr; - const char *in_filter = nullptr; - const char *out_filter = nullptr; + int ret; + const char *type = nullptr; + const char *in_filter = nullptr; + const char *out_filter = nullptr; - json_error_t err; - json_t *json_in_ep = nullptr; - json_t *json_out_ep = nullptr; - json_t *json_curve = nullptr; - json_t *json_format = nullptr; + json_error_t err; + json_t *json_in_ep = nullptr; + json_t *json_out_ep = nullptr; + json_t *json_curve = nullptr; + json_t *json_format = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o, s?: s, s?: b }, s?: { s?: o, s?: s, s?: b }, s?: o, s?: s, s?: b, s?: o }", - "in", - "subscribe", &json_in_ep, - "filter", &in_filter, - "bind", &z->in.bind, - "out", - "publish", &json_out_ep, - "filter", &out_filter, - "bind", &z->out.bind, - "curve", &json_curve, - "pattern", &type, - "ipv6", &z->ipv6, - "format", &json_format - ); - if (ret) - throw ConfigError(json, err, "node-config-node-zeromq"); + ret = json_unpack_ex(json, &err, 0, + "{ s?: { s?: o, s?: s, s?: b }, s?: { s?: o, s?: s, s?: " + "b }, s?: o, s?: s, s?: b, s?: o }", + "in", "subscribe", &json_in_ep, "filter", &in_filter, + "bind", &z->in.bind, "out", "publish", &json_out_ep, + "filter", &out_filter, "bind", &z->out.bind, "curve", + &json_curve, "pattern", &type, "ipv6", &z->ipv6, + "format", &json_format); + if (ret) + throw ConfigError(json, err, "node-config-node-zeromq"); - z->in.filter = in_filter ? strdup(in_filter) : nullptr; - z->out.filter = out_filter ? strdup(out_filter) : nullptr; + z->in.filter = in_filter ? strdup(in_filter) : nullptr; + z->out.filter = out_filter ? strdup(out_filter) : nullptr; - // Format - if (z->formatter) - delete z->formatter; - z->formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make("villas.binary"); - if (!z->formatter) - throw ConfigError(json_format, "node-config-node-zeromq-format", "Invalid format configuration"); + // Format + if (z->formatter) + delete z->formatter; + z->formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make("villas.binary"); + if (!z->formatter) + throw ConfigError(json_format, "node-config-node-zeromq-format", + "Invalid format configuration"); - if (json_out_ep) { - ret = zeromq_parse_endpoints(json_out_ep, &z->out.endpoints); - if (ret) - throw ConfigError(json_out_ep, "node-config-node-zeromq-publish", "Failed to parse list of publish endpoints"); - } + if (json_out_ep) { + ret = zeromq_parse_endpoints(json_out_ep, &z->out.endpoints); + if (ret) + throw ConfigError(json_out_ep, "node-config-node-zeromq-publish", + "Failed to parse list of publish endpoints"); + } - if (json_in_ep) { - ret = zeromq_parse_endpoints(json_in_ep, &z->in.endpoints); - if (ret) - throw ConfigError(json_out_ep, "node-config-node-zeromq-subscribe", "Failed to parse list of subscribe endpoints"); - } + if (json_in_ep) { + ret = zeromq_parse_endpoints(json_in_ep, &z->in.endpoints); + if (ret) + throw ConfigError(json_out_ep, "node-config-node-zeromq-subscribe", + "Failed to parse list of subscribe endpoints"); + } - if (json_curve) { - const char *public_key, *secret_key; + if (json_curve) { + const char *public_key, *secret_key; - z->curve.enabled = true; + z->curve.enabled = true; - ret = json_unpack_ex(json_curve, &err, 0, "{ s: s, s: s, s?: b }", - "public_key", &public_key, - "secret_key", &secret_key, - "enabled", &z->curve.enabled - ); - if (ret) - throw ConfigError(json_curve, err, "node-config-node-zeromq-curve", "Failed to parse setting 'curve'"); + ret = json_unpack_ex(json_curve, &err, 0, "{ s: s, s: s, s?: b }", + "public_key", &public_key, "secret_key", &secret_key, + "enabled", &z->curve.enabled); + if (ret) + throw ConfigError(json_curve, err, "node-config-node-zeromq-curve", + "Failed to parse setting 'curve'"); - if (strlen(secret_key) != 40) - throw ConfigError(json_curve, err, "node-config-node-zeromq-curve", "Setting 'curve.secret_key' must be a Z85 encoded CurveZMQ key"); + if (strlen(secret_key) != 40) + throw ConfigError( + json_curve, err, "node-config-node-zeromq-curve", + "Setting 'curve.secret_key' must be a Z85 encoded CurveZMQ key"); - if (strlen(public_key) != 40) - throw ConfigError(json_curve, err, "node-config-node-zeromq-curve", "Setting 'curve.public_key' must be a Z85 encoded CurveZMQ key"); + if (strlen(public_key) != 40) + throw ConfigError( + json_curve, err, "node-config-node-zeromq-curve", + "Setting 'curve.public_key' must be a Z85 encoded CurveZMQ key"); - memcpy(z->curve.server.public_key, public_key, 41); - memcpy(z->curve.server.secret_key, secret_key, 41); - } + memcpy(z->curve.server.public_key, public_key, 41); + memcpy(z->curve.server.secret_key, secret_key, 41); + } - // TODO: We should fix this. Its mostly done. - if (z->curve.enabled) - throw ConfigError(json_curve, "node-config-zeromq-curve", "CurveZMQ support is currently broken"); + // TODO: We should fix this. Its mostly done. + if (z->curve.enabled) + throw ConfigError(json_curve, "node-config-zeromq-curve", + "CurveZMQ support is currently broken"); - if (type) { - if (!strcmp(type, "pubsub")) - z->pattern = zeromq::Pattern::PUBSUB; + if (type) { + if (!strcmp(type, "pubsub")) + z->pattern = zeromq::Pattern::PUBSUB; #ifdef ZMQ_BUILD_DISH - else if (!strcmp(type, "radiodish")) - z->pattern = zeromq::Pattern::RADIODISH; + else if (!strcmp(type, "radiodish")) + z->pattern = zeromq::Pattern::RADIODISH; #endif - else - throw ConfigError(json, "node-config-node-zeromq-type", "Invalid type for ZeroMQ node: {}", n->getNameShort()); - } + else + throw ConfigError(json, "node-config-node-zeromq-type", + "Invalid type for ZeroMQ node: {}", n->getNameShort()); + } - return 0; + return 0; } -char * villas::node::zeromq_print(NodeCompat *n) -{ - auto *z = n->getData(); +char *villas::node::zeromq_print(NodeCompat *n) { + auto *z = n->getData(); - char *buf = nullptr; - const char *pattern = nullptr; + char *buf = nullptr; + const char *pattern = nullptr; - switch (z->pattern) { - case zeromq::Pattern::PUBSUB: - pattern = "pubsub"; - break; + switch (z->pattern) { + case zeromq::Pattern::PUBSUB: + pattern = "pubsub"; + break; #ifdef ZMQ_BUILD_DISH - case zeromq::Pattern::RADIODISH: - pattern = "radiodish"; - break; + case zeromq::Pattern::RADIODISH: + pattern = "radiodish"; + break; #endif - } + } - strcatf(&buf, "pattern=%s, ipv6=%s, crypto=%s, in.bind=%s, out.bind=%s, in.subscribe=[ ", - pattern, - z->ipv6 ? "yes" : "no", - z->curve.enabled ? "yes" : "no", - z->in.bind ? "yes" : "no", - z->out.bind ? "yes" : "no" - ); + strcatf(&buf, + "pattern=%s, ipv6=%s, crypto=%s, in.bind=%s, out.bind=%s, " + "in.subscribe=[ ", + pattern, z->ipv6 ? "yes" : "no", z->curve.enabled ? "yes" : "no", + z->in.bind ? "yes" : "no", z->out.bind ? "yes" : "no"); - for (size_t i = 0; i < list_length(&z->in.endpoints); i++) { - char *ep = (char *) list_at(&z->in.endpoints, i); + for (size_t i = 0; i < list_length(&z->in.endpoints); i++) { + char *ep = (char *)list_at(&z->in.endpoints, i); - strcatf(&buf, "%s ", ep); - } + strcatf(&buf, "%s ", ep); + } - strcatf(&buf, "], out.publish=[ "); + strcatf(&buf, "], out.publish=[ "); - for (size_t i = 0; i < list_length(&z->out.endpoints); i++) { - char *ep = (char *) list_at(&z->out.endpoints, i); + for (size_t i = 0; i < list_length(&z->out.endpoints); i++) { + char *ep = (char *)list_at(&z->out.endpoints, i); - strcatf(&buf, "%s ", ep); - } + strcatf(&buf, "%s ", ep); + } - strcatf(&buf, "]"); + strcatf(&buf, "]"); - if (z->in.filter) - strcatf(&buf, ", in.filter=%s", z->in.filter); + if (z->in.filter) + strcatf(&buf, ", in.filter=%s", z->in.filter); - if (z->out.filter) - strcatf(&buf, ", out.filter=%s", z->out.filter); + if (z->out.filter) + strcatf(&buf, ", out.filter=%s", z->out.filter); - return buf; + return buf; } -int villas::node::zeromq_check(NodeCompat *n) -{ - auto *z = n->getData(); +int villas::node::zeromq_check(NodeCompat *n) { + auto *z = n->getData(); - if (list_length(&z->in.endpoints) == 0 && - list_length(&z->out.endpoints) == 0) - return -1; + if (list_length(&z->in.endpoints) == 0 && list_length(&z->out.endpoints) == 0) + return -1; - return 0; + return 0; } -int villas::node::zeromq_type_start(villas::node::SuperNode *sn) -{ - context = zmq_ctx_new(); +int villas::node::zeromq_type_start(villas::node::SuperNode *sn) { + context = zmq_ctx_new(); - return context == nullptr; + return context == nullptr; } -int villas::node::zeromq_type_stop() -{ - return zmq_ctx_term(context); -} +int villas::node::zeromq_type_stop() { return zmq_ctx_term(context); } -int villas::node::zeromq_start(NodeCompat *n) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_start(NodeCompat *n) { + int ret; + auto *z = n->getData(); - struct zeromq::Dir* dirs[] = { &z->out, &z->in }; + struct zeromq::Dir *dirs[] = {&z->out, &z->in}; - z->formatter->start(n->getInputSignals(false), ~(int) SampleFlags::HAS_OFFSET); + z->formatter->start(n->getInputSignals(false), ~(int)SampleFlags::HAS_OFFSET); - switch (z->pattern) { + switch (z->pattern) { #ifdef ZMQ_BUILD_DISH - case zeromq::Pattern::RADIODISH: - z->in.socket = zmq_socket(context, ZMQ_DISH); - z->out.socket = zmq_socket(context, ZMQ_RADIO); - break; + case zeromq::Pattern::RADIODISH: + z->in.socket = zmq_socket(context, ZMQ_DISH); + z->out.socket = zmq_socket(context, ZMQ_RADIO); + break; #endif - case zeromq::Pattern::PUBSUB: - z->in.socket = zmq_socket(context, ZMQ_SUB); - z->out.socket = zmq_socket(context, ZMQ_PUB); - break; - } + case zeromq::Pattern::PUBSUB: + z->in.socket = zmq_socket(context, ZMQ_SUB); + z->out.socket = zmq_socket(context, ZMQ_PUB); + break; + } - if (!z->in.socket || !z->out.socket) { - ret = -1; - goto fail; - } + if (!z->in.socket || !z->out.socket) { + ret = -1; + goto fail; + } - // Join group - switch (z->pattern) { + // Join group + switch (z->pattern) { #ifdef ZMQ_BUILD_DISH - case zeromq::Pattern::RADIODISH: - ret = zmq_join(z->in.socket, z->in.filter); - break; + case zeromq::Pattern::RADIODISH: + ret = zmq_join(z->in.socket, z->in.filter); + break; #endif - case zeromq::Pattern::PUBSUB: - ret = zmq_setsockopt(z->in.socket, ZMQ_SUBSCRIBE, z->in.filter, z->in.filter ? strlen(z->in.filter) : 0); - break; + case zeromq::Pattern::PUBSUB: + ret = zmq_setsockopt(z->in.socket, ZMQ_SUBSCRIBE, z->in.filter, + z->in.filter ? strlen(z->in.filter) : 0); + break; - default: - ret = -1; - } + default: + ret = -1; + } - if (ret < 0) - goto fail; + if (ret < 0) + goto fail; - if (z->curve.enabled) { - // Publisher has server role - ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_SECRETKEY, z->curve.server.secret_key, 41); - if (ret) - goto fail; + if (z->curve.enabled) { + // Publisher has server role + ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_SECRETKEY, + z->curve.server.secret_key, 41); + if (ret) + goto fail; - ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_PUBLICKEY, z->curve.server.public_key, 41); - if (ret) - goto fail; + ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_PUBLICKEY, + z->curve.server.public_key, 41); + if (ret) + goto fail; - int curve_server = 1; - ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_SERVER, &curve_server, sizeof(curve_server)); - if (ret) - goto fail; + int curve_server = 1; + ret = zmq_setsockopt(z->out.socket, ZMQ_CURVE_SERVER, &curve_server, + sizeof(curve_server)); + if (ret) + goto fail; - // Create temporary client keys first - ret = zmq_curve_keypair(z->curve.client.public_key, z->curve.client.secret_key); - if (ret) - goto fail; + // Create temporary client keys first + ret = zmq_curve_keypair(z->curve.client.public_key, + z->curve.client.secret_key); + if (ret) + goto fail; - // Subscriber has client role - ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_SECRETKEY, z->curve.client.secret_key, 41); - if (ret) - goto fail; + // Subscriber has client role + ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_SECRETKEY, + z->curve.client.secret_key, 41); + if (ret) + goto fail; - ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_PUBLICKEY, z->curve.client.public_key, 41); - if (ret) - goto fail; + ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_PUBLICKEY, + z->curve.client.public_key, 41); + if (ret) + goto fail; - ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_SERVERKEY, z->curve.server.public_key, 41); - if (ret) - goto fail; - } + ret = zmq_setsockopt(z->in.socket, ZMQ_CURVE_SERVERKEY, + z->curve.server.public_key, 41); + if (ret) + goto fail; + } - for (auto d : dirs) { - const char *mon_ep = d == &z->in ? "inproc://monitor-in" : "inproc://monitor-out"; + for (auto d : dirs) { + const char *mon_ep = + d == &z->in ? "inproc://monitor-in" : "inproc://monitor-out"; - ret = zmq_setsockopt(d->socket, ZMQ_IPV6, &z->ipv6, sizeof(z->ipv6)); - if (ret) - goto fail; + ret = zmq_setsockopt(d->socket, ZMQ_IPV6, &z->ipv6, sizeof(z->ipv6)); + if (ret) + goto fail; - int linger = 1000; - ret = zmq_setsockopt(d->socket, ZMQ_LINGER, &linger, sizeof(linger)); - if (ret) - goto fail; + int linger = 1000; + ret = zmq_setsockopt(d->socket, ZMQ_LINGER, &linger, sizeof(linger)); + if (ret) + goto fail; - // Monitor events on the server - ret = zmq_socket_monitor(d->socket, mon_ep, ZMQ_EVENT_ALL); - if (ret < 0) - goto fail; + // Monitor events on the server + ret = zmq_socket_monitor(d->socket, mon_ep, ZMQ_EVENT_ALL); + if (ret < 0) + goto fail; - // Create socket for collecting monitor events - d->mon_socket = zmq_socket(context, ZMQ_PAIR); - if (!d->mon_socket) { - ret = -1; - goto fail; - } + // Create socket for collecting monitor events + d->mon_socket = zmq_socket(context, ZMQ_PAIR); + if (!d->mon_socket) { + ret = -1; + goto fail; + } - // Connect it to the inproc endpoints so they'll get events - ret = zmq_connect(d->mon_socket, mon_ep); - if (ret < 0) - goto fail; + // Connect it to the inproc endpoints so they'll get events + ret = zmq_connect(d->mon_socket, mon_ep); + if (ret < 0) + goto fail; - // Connect / bind sockets to endpoints - for (size_t i = 0; i < list_length(&d->endpoints); i++) { - char *ep = (char *) list_at(&d->endpoints, i); + // Connect / bind sockets to endpoints + for (size_t i = 0; i < list_length(&d->endpoints); i++) { + char *ep = (char *)list_at(&d->endpoints, i); - if (d->bind) { - ret = zmq_bind(d->socket, ep); - if (ret < 0) - goto fail; - } - else { - ret = zmq_connect(d->socket, ep); - if (ret < 0) - goto fail; - } + if (d->bind) { + ret = zmq_bind(d->socket, ep); + if (ret < 0) + goto fail; + } else { + ret = zmq_connect(d->socket, ep); + if (ret < 0) + goto fail; + } - d->pending++; - } - } + d->pending++; + } + } - // Wait for all connections to be connected - for (auto d : dirs) { - while (d->pending > 0) { - int evt = d->bind ? ZMQ_EVENT_LISTENING : ZMQ_EVENT_CONNECTED; + // Wait for all connections to be connected + for (auto d : dirs) { + while (d->pending > 0) { + int evt = d->bind ? ZMQ_EVENT_LISTENING : ZMQ_EVENT_CONNECTED; - ret = get_monitor_event(d->mon_socket, nullptr, nullptr); - if (ret == evt) - d->pending--; - } - } + ret = get_monitor_event(d->mon_socket, nullptr, nullptr); + if (ret == evt) + d->pending--; + } + } -#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_MAJOR_VERSION >= 4 && ZMQ_MINOR_VERSION >= 2 && ZMQ_MINOR_VERSION >= 3 - if (z->curve.enabled) { - ret = get_monitor_event(z->in.mon_socket, nullptr, nullptr); - return ret == ZMQ_EVENT_HANDSHAKE_SUCCEEDED; - } - else - return 0; // The handshake events are only emitted for CurveZMQ sessions +#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_MAJOR_VERSION >= 4 && \ + ZMQ_MINOR_VERSION >= 2 && ZMQ_MINOR_VERSION >= 3 + if (z->curve.enabled) { + ret = get_monitor_event(z->in.mon_socket, nullptr, nullptr); + return ret == ZMQ_EVENT_HANDSHAKE_SUCCEEDED; + } else + return 0; // The handshake events are only emitted for CurveZMQ sessions #else - return 0; + return 0; #endif fail: - n->logger->info("Failed to start: {}", zmq_strerror(errno)); + n->logger->info("Failed to start: {}", zmq_strerror(errno)); - return ret; + return ret; } -int villas::node::zeromq_stop(NodeCompat *n) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_stop(NodeCompat *n) { + int ret; + auto *z = n->getData(); - struct zeromq::Dir* dirs[] = { &z->out, &z->in }; + struct zeromq::Dir *dirs[] = {&z->out, &z->in}; - for (auto d : dirs) { - ret = zmq_close(d->socket); - if (ret) - return ret; + for (auto d : dirs) { + ret = zmq_close(d->socket); + if (ret) + return ret; - ret = zmq_close(d->mon_socket); - if (ret) - return ret; - } + ret = zmq_close(d->mon_socket); + if (ret) + return ret; + } - return 0; + return 0; } -int villas::node::zeromq_destroy(NodeCompat *n) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_destroy(NodeCompat *n) { + int ret; + auto *z = n->getData(); - if (z->in.filter) - free(z->in.filter); + if (z->in.filter) + free(z->in.filter); - if (z->out.filter) - free(z->out.filter); + if (z->out.filter) + free(z->out.filter); - ret = list_destroy(&z->out.endpoints, nullptr, true); - if (ret) - return ret; + ret = list_destroy(&z->out.endpoints, nullptr, true); + if (ret) + return ret; - if (z->formatter) - delete z->formatter; + if (z->formatter) + delete z->formatter; - return 0; + return 0; } -int villas::node::zeromq_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int recv, ret; - auto *z = n->getData(); +int villas::node::zeromq_read(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int recv, ret; + auto *z = n->getData(); - zmq_msg_t m; + zmq_msg_t m; - ret = zmq_msg_init(&m); - if (ret < 0) - return ret; + ret = zmq_msg_init(&m); + if (ret < 0) + return ret; - if (z->in.filter) { - switch (z->pattern) { - case zeromq::Pattern::PUBSUB: - // Discard envelope - zmq_recv(z->in.socket, nullptr, 0, 0); - break; + if (z->in.filter) { + switch (z->pattern) { + case zeromq::Pattern::PUBSUB: + // Discard envelope + zmq_recv(z->in.socket, nullptr, 0, 0); + break; - default: { } - } - } + default: { + } + } + } - // Receive payload - ret = zmq_msg_recv(&m, z->in.socket, 0); - if (ret < 0) - return ret; + // Receive payload + ret = zmq_msg_recv(&m, z->in.socket, 0); + if (ret < 0) + return ret; - recv = z->formatter->sscan((const char *) zmq_msg_data(&m), zmq_msg_size(&m), nullptr, smps, cnt); + recv = z->formatter->sscan((const char *)zmq_msg_data(&m), zmq_msg_size(&m), + nullptr, smps, cnt); - ret = zmq_msg_close(&m); - if (ret) - return ret; + ret = zmq_msg_close(&m); + if (ret) + return ret; - return recv; + return recv; } -int villas::node::zeromq_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_write(NodeCompat *n, struct Sample *const smps[], + unsigned cnt) { + int ret; + auto *z = n->getData(); - size_t wbytes; - zmq_msg_t m; + size_t wbytes; + zmq_msg_t m; - char data[DEFAULT_FORMAT_BUFFER_LENGTH]; + char data[DEFAULT_FORMAT_BUFFER_LENGTH]; - ret = z->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); - if (ret <= 0) - return -1; + ret = z->formatter->sprint(data, sizeof(data), &wbytes, smps, cnt); + if (ret <= 0) + return -1; - ret = zmq_msg_init_size(&m, wbytes); + ret = zmq_msg_init_size(&m, wbytes); - if (z->out.filter) { - switch (z->pattern) { + if (z->out.filter) { + switch (z->pattern) { #ifdef ZMQ_BUILD_DISH - case zeromq::Pattern::RADIODISH: - ret = zmq_msg_set_group(&m, z->out.filter); - if (ret < 0) - goto fail; - break; + case zeromq::Pattern::RADIODISH: + ret = zmq_msg_set_group(&m, z->out.filter); + if (ret < 0) + goto fail; + break; #endif - case zeromq::Pattern::PUBSUB: // Send envelope - zmq_send(z->out.socket, z->out.filter, strlen(z->out.filter), ZMQ_SNDMORE); - break; - } - } + case zeromq::Pattern::PUBSUB: // Send envelope + zmq_send(z->out.socket, z->out.filter, strlen(z->out.filter), + ZMQ_SNDMORE); + break; + } + } - memcpy(zmq_msg_data(&m), data, wbytes); + memcpy(zmq_msg_data(&m), data, wbytes); - ret = zmq_msg_send(&m, z->out.socket, 0); - if (ret < 0) - goto fail; + ret = zmq_msg_send(&m, z->out.socket, 0); + if (ret < 0) + goto fail; - ret = zmq_msg_close(&m); - if (ret < 0) - return ret; + ret = zmq_msg_close(&m); + if (ret < 0) + return ret; - return cnt; + return cnt; fail: - zmq_msg_close(&m); + zmq_msg_close(&m); - return ret; + return ret; } -int villas::node::zeromq_poll_fds(NodeCompat *n, int fds[]) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_poll_fds(NodeCompat *n, int fds[]) { + int ret; + auto *z = n->getData(); - int fd; - size_t len = sizeof(fd); + int fd; + size_t len = sizeof(fd); - ret = zmq_getsockopt(z->in.socket, ZMQ_FD, &fd, &len); - if (ret) - return ret; + ret = zmq_getsockopt(z->in.socket, ZMQ_FD, &fd, &len); + if (ret) + return ret; - fds[0] = fd; + fds[0] = fd; - return 1; + return 1; } -int villas::node::zeromq_netem_fds(NodeCompat *n, int fds[]) -{ - int ret; - auto *z = n->getData(); +int villas::node::zeromq_netem_fds(NodeCompat *n, int fds[]) { + int ret; + auto *z = n->getData(); - int fd; - size_t len = sizeof(fd); + int fd; + size_t len = sizeof(fd); - ret = zmq_getsockopt(z->out.socket, ZMQ_FD, &fd, &len); - if (ret) - return ret; + ret = zmq_getsockopt(z->out.socket, ZMQ_FD, &fd, &len); + if (ret) + return ret; - fds[0] = fd; + fds[0] = fd; - return 1; + return 1; } -static -NodeCompatType p; +static NodeCompatType p; -__attribute__((constructor(110))) static -void register_plugin() { - p.name = "zeromq"; - p.description = "ZeroMQ Distributed Messaging (libzmq)"; - p.vectorize = 0; - p.size = sizeof(struct zeromq); - p.type.start = zeromq_type_start; - p.type.stop = zeromq_type_stop; - p.init = zeromq_init; - p.destroy = zeromq_destroy; - p.check = zeromq_check; - p.parse = zeromq_parse; - p.print = zeromq_print; - p.start = zeromq_start; - p.stop = zeromq_stop; - p.read = zeromq_read; - p.write = zeromq_write; - p.reverse = zeromq_reverse; - p.poll_fds = zeromq_poll_fds; - p.netem_fds = zeromq_netem_fds; +__attribute__((constructor(110))) static void register_plugin() { + p.name = "zeromq"; + p.description = "ZeroMQ Distributed Messaging (libzmq)"; + p.vectorize = 0; + p.size = sizeof(struct zeromq); + p.type.start = zeromq_type_start; + p.type.stop = zeromq_type_stop; + p.init = zeromq_init; + p.destroy = zeromq_destroy; + p.check = zeromq_check; + p.parse = zeromq_parse; + p.print = zeromq_print; + p.start = zeromq_start; + p.stop = zeromq_stop; + p.read = zeromq_read; + p.write = zeromq_write; + p.reverse = zeromq_reverse; + p.poll_fds = zeromq_poll_fds; + p.netem_fds = zeromq_netem_fds; - static - NodeCompatFactory ncp(&p); + static NodeCompatFactory ncp(&p); } diff --git a/lib/path.cpp b/lib/path.cpp index 4855623b2..9b6207d31 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -5,46 +5,43 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include #include -#include -#include #include +#include #include #include -#include -#include #include +#include -#include -#include #include -#include -#include -#include -#include #include #include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::node; -void * Path::runWrapper(void *arg) -{ - auto *p = (Path *) arg; +void *Path::runWrapper(void *arg) { + auto *p = (Path *)arg; - return p->poll - ? p->runPoll() - : p->runSingle(); + return p->poll ? p->runPoll() : p->runSingle(); } /* Main thread function per path: @@ -55,23 +52,22 @@ void * Path::runWrapper(void *arg) * In this case we case save a call to poll() and directly call * PathSource::read() / Node::read(). */ -void * Path::runSingle() -{ - int ret; - auto ps = sources.front(); // there is only a single source +void *Path::runSingle() { + int ret; + auto ps = sources.front(); // there is only a single source - while (state == State::STARTED) { - pthread_testcancel(); + while (state == State::STARTED) { + pthread_testcancel(); - ret = ps->read(0); - if (ret <= 0) - continue; + ret = ps->read(0); + if (ret <= 0) + continue; - for (auto pd : destinations) - pd->write(); - } + for (auto pd : destinations) + pd->write(); + } - return nullptr; + return nullptr; } /* Main thread function per path: @@ -80,655 +76,626 @@ void * Path::runSingle() * This variant of the path uses poll() to listen on an event from * all path sources. */ -void * Path::runPoll() -{ - while (state == State::STARTED) { - int ret = ::poll(pfds.data(), pfds.size(), -1); - if (ret < 0) - throw SystemError("Failed to poll"); +void *Path::runPoll() { + while (state == State::STARTED) { + int ret = ::poll(pfds.data(), pfds.size(), -1); + if (ret < 0) + throw SystemError("Failed to poll"); - logger->debug("Returned from poll(2): ret={}", ret); + logger->debug("Returned from poll(2): ret={}", ret); - for (unsigned i = 0; i < pfds.size(); i++) { - auto &pfd = pfds[i]; + for (unsigned i = 0; i < pfds.size(); i++) { + auto &pfd = pfds[i]; - if (pfd.revents & POLLIN) { - // Timeout: re-enqueue the last sample - if (pfd.fd == timeout.getFD()) { - timeout.wait(); + if (pfd.revents & POLLIN) { + // Timeout: re-enqueue the last sample + if (pfd.fd == timeout.getFD()) { + timeout.wait(); - last_sample->sequence = last_sequence++; + last_sample->sequence = last_sequence++; - PathDestination::enqueueAll(this, &last_sample, 1); - } - // A source is ready to receive samples - else { - auto ps = sources[i]; + PathDestination::enqueueAll(this, &last_sample, 1); + } + // A source is ready to receive samples + else { + auto ps = sources[i]; - ps->read(i); - } - } - } + ps->read(i); + } + } + } - for (auto pd : destinations) - pd->write(); - } + for (auto pd : destinations) + pd->write(); + } - return nullptr; + return nullptr; } -Path::Path() : - state(State::INITIALIZED), - mode(Mode::ANY), - timeout(CLOCK_MONOTONIC), - rate(0), // Disabled - affinity(0), - enabled(true), - poll(-1), - reversed(false), - builtin(true), - original_sequence_no(-1), - queuelen(DEFAULT_QUEUE_LENGTH), - logger(logging.get(fmt::format("path:{}", id++))) -{ - uuid_clear(uuid); +Path::Path() + : state(State::INITIALIZED), mode(Mode::ANY), timeout(CLOCK_MONOTONIC), + rate(0), // Disabled + affinity(0), enabled(true), poll(-1), reversed(false), builtin(true), + original_sequence_no(-1), queuelen(DEFAULT_QUEUE_LENGTH), + logger(logging.get(fmt::format("path:{}", id++))) { + uuid_clear(uuid); - pool.state = State::DESTROYED; + pool.state = State::DESTROYED; } -void Path::startPoll() -{ - pfds.clear(); +void Path::startPoll() { + pfds.clear(); - for (auto ps : sources) { - auto fds = ps->getNode()->getPollFDs(); - for (auto fd : fds) { - if (fd < 0) - throw RuntimeError("Failed to get file descriptor for node {}", ps->getNode()->getName()); + for (auto ps : sources) { + auto fds = ps->getNode()->getPollFDs(); + for (auto fd : fds) { + if (fd < 0) + throw RuntimeError("Failed to get file descriptor for node {}", + ps->getNode()->getName()); - // This slot is only used if it is not masked - struct pollfd pfd = { - .fd = fd, - .events = POLLIN - }; + // This slot is only used if it is not masked + struct pollfd pfd = {.fd = fd, .events = POLLIN}; - pfds.push_back(pfd); - } - } + pfds.push_back(pfd); + } + } - // We use the last slot for the timeout timer - if (rate > 0) { - timeout.setRate(rate); + // We use the last slot for the timeout timer + if (rate > 0) { + timeout.setRate(rate); - struct pollfd pfd = { - .fd = timeout.getFD(), - .events = POLLIN - }; + struct pollfd pfd = {.fd = timeout.getFD(), .events = POLLIN}; - if (pfd.fd < 0) - throw RuntimeError("Failed to get file descriptor for timer of path {}", this->toString()); + if (pfd.fd < 0) + throw RuntimeError("Failed to get file descriptor for timer of path {}", + this->toString()); - pfds.push_back(pfd); - } + pfds.push_back(pfd); + } } -void Path::prepare(NodeList &nodes) -{ - int ret; +void Path::prepare(NodeList &nodes) { + int ret; - struct memory::Type *pool_mt = memory::default_type; + struct memory::Type *pool_mt = memory::default_type; - assert(state == State::CHECKED); + assert(state == State::CHECKED); - mask.reset(); - signals = std::make_shared(); + mask.reset(); + signals = std::make_shared(); - // Prepare mappings - ret = mappings.prepare(nodes); - if (ret) - throw RuntimeError("Failed to prepare mappings of path: {}", this->toString()); + // Prepare mappings + ret = mappings.prepare(nodes); + if (ret) + throw RuntimeError("Failed to prepare mappings of path: {}", + this->toString()); - // Create path sources - std::map psm; - unsigned i = 0, j = 0; - for (auto me : mappings) { - Node *n = me->node; - PathSource::Ptr ps; + // Create path sources + std::map psm; + unsigned i = 0, j = 0; + for (auto me : mappings) { + Node *n = me->node; + PathSource::Ptr ps; - if (psm.find(n) != psm.end()) - // We already have a path source for this mapping entry - ps = psm[n]; - else { - /* Depending on weather the node belonging to this mapping is already + if (psm.find(n) != psm.end()) + // We already have a path source for this mapping entry + ps = psm[n]; + else { + /* Depending on weather the node belonging to this mapping is already * used by another path or not, we will create a master or secondary * path source. * A secondary path source uses an internal loopback node / queue * to forward samples from on path to another. */ - bool isSecondary = n->sources.size() > 0; + bool isSecondary = n->sources.size() > 0; - // Create new path source - if (isSecondary) { - // Get master path source - auto mps = std::dynamic_pointer_cast(n->sources.front()); - if (!mps) - throw RuntimeError("Failed to find master path source"); + // Create new path source + if (isSecondary) { + // Get master path source + auto mps = + std::dynamic_pointer_cast(n->sources.front()); + if (!mps) + throw RuntimeError("Failed to find master path source"); - auto sps = std::make_shared(this, n, nodes, mps); - if (!sps) - throw MemoryAllocationError(); + auto sps = std::make_shared(this, n, nodes, mps); + if (!sps) + throw MemoryAllocationError(); - mps->addSecondary(sps); + mps->addSecondary(sps); - ps = sps; - } - else { - ps = std::make_shared(this, n); - if (!ps) - throw MemoryAllocationError(); - } + ps = sps; + } else { + ps = std::make_shared(this, n); + if (!ps) + throw MemoryAllocationError(); + } - if (masked.empty() || std::find(masked.begin(), masked.end(), n) != masked.end()) { - ps->masked = true; - mask.set(j); - } + if (masked.empty() || + std::find(masked.begin(), masked.end(), n) != masked.end()) { + ps->masked = true; + mask.set(j); + } - /* Get the real node backing this path source + /* Get the real node backing this path source * In case of a secondary path source, its the internal loopback node! */ - auto *rn = ps->getNode(); + auto *rn = ps->getNode(); - rn->sources.push_back(ps); + rn->sources.push_back(ps); - sources.push_back(ps); - j++; - psm[n] = ps; - } + sources.push_back(ps); + j++; + psm[n] = ps; + } - SignalList::Ptr sigs = me->node->getInputSignals(); + SignalList::Ptr sigs = me->node->getInputSignals(); - // Update signals of path - for (unsigned j = 0; j < (unsigned) me->length; j++) { - Signal::Ptr sig; + // Update signals of path + for (unsigned j = 0; j < (unsigned)me->length; j++) { + Signal::Ptr sig; - /* For data mappings we simple refer to the existing + /* For data mappings we simple refer to the existing * signal descriptors of the source node. */ - if (me->type == MappingEntry::Type::DATA) { - sig = sigs->getByIndex(me->data.offset + j); - if (!sig) { - logger->warn("Failed to create signal description for path {}", this->toString()); - continue; - } - } - // For other mappings we create new signal descriptors - else { - sig = me->toSignal(j); - if (!sig) - throw RuntimeError("Failed to create signal from mapping"); - } + if (me->type == MappingEntry::Type::DATA) { + sig = sigs->getByIndex(me->data.offset + j); + if (!sig) { + logger->warn("Failed to create signal description for path {}", + this->toString()); + continue; + } + } + // For other mappings we create new signal descriptors + else { + sig = me->toSignal(j); + if (!sig) + throw RuntimeError("Failed to create signal from mapping"); + } - signals->resize(me->offset + j + 1); - (*signals)[me->offset + j] = sig; - } + signals->resize(me->offset + j + 1); + (*signals)[me->offset + j] = sig; + } - ps->mappings.push_back(me); - i++; - } + ps->mappings.push_back(me); + i++; + } - // Prepare path destinations - int mt_cnt = 0; - for (auto pd : destinations) { - auto *pd_mt = pd->node->getMemoryType(); - if (pd_mt != pool_mt) { - if (mt_cnt > 0) { - throw RuntimeError("Mixed memory types between path destinations"); - } + // Prepare path destinations + int mt_cnt = 0; + for (auto pd : destinations) { + auto *pd_mt = pd->node->getMemoryType(); + if (pd_mt != pool_mt) { + if (mt_cnt > 0) { + throw RuntimeError("Mixed memory types between path destinations"); + } - pool_mt = pd_mt; - mt_cnt++; - } + pool_mt = pd_mt; + mt_cnt++; + } - ret = pd->prepare(queuelen); - if (ret) - throw RuntimeError("Failed to prepare path destination {} of path {}", pd->node->getName(), this->toString()); - } + ret = pd->prepare(queuelen); + if (ret) + throw RuntimeError("Failed to prepare path destination {} of path {}", + pd->node->getName(), this->toString()); + } - // Autodetect whether to use original sequence numbers or not - if (original_sequence_no == -1) - original_sequence_no = sources.size() == 1; + // Autodetect whether to use original sequence numbers or not + if (original_sequence_no == -1) + original_sequence_no = sources.size() == 1; - // Autodetect whether to use poll() for this path or not - if (poll == -1) { - if (rate > 0) - poll = 1; - else if (sources.size()> 1) - poll = 1; - else - poll = 0; - } + // Autodetect whether to use poll() for this path or not + if (poll == -1) { + if (rate > 0) + poll = 1; + else if (sources.size() > 1) + poll = 1; + else + poll = 0; + } #ifdef WITH_HOOKS - // Prepare path hooks - int m = builtin - ? (int) Hook::Flags::PATH | - (int) Hook::Flags::BUILTIN - : 0; + // Prepare path hooks + int m = builtin ? (int)Hook::Flags::PATH | (int)Hook::Flags::BUILTIN : 0; - // Add internal hooks if they are not already in the list - hooks.prepare(signals, m, this, nullptr); - hooks.dump(logger, fmt::format("path {}", this->toString())); + // Add internal hooks if they are not already in the list + hooks.prepare(signals, m, this, nullptr); + hooks.dump(logger, fmt::format("path {}", this->toString())); #endif // WITH_HOOKS - // Prepare pool - auto osigs = getOutputSignals(); - unsigned pool_size = MAX(1UL, destinations.size()) * queuelen; + // Prepare pool + auto osigs = getOutputSignals(); + unsigned pool_size = MAX(1UL, destinations.size()) * queuelen; - ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(osigs->size()), pool_mt); - if (ret) - throw RuntimeError("Failed to initialize pool of path: {}", this->toString()); + ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(osigs->size()), pool_mt); + if (ret) + throw RuntimeError("Failed to initialize pool of path: {}", + this->toString()); - logger->debug("Prepared path {} with {} output signals:", this->toString(), osigs->size()); - if (logger->level() <= spdlog::level::debug) - osigs->dump(logger); + logger->debug("Prepared path {} with {} output signals:", this->toString(), + osigs->size()); + if (logger->level() <= spdlog::level::debug) + osigs->dump(logger); - checkPrepared(); + checkPrepared(); - state = State::PREPARED; + state = State::PREPARED; } -void Path::parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid) -{ - int ret, en = -1, rev = -1; +void Path::parse(json_t *json, NodeList &nodes, const uuid_t sn_uuid) { + int ret, en = -1, rev = -1; - json_error_t err; - json_t *json_in; - json_t *json_out = nullptr; - json_t *json_hooks = nullptr; - json_t *json_mask = nullptr; + json_error_t err; + json_t *json_in; + json_t *json_out = nullptr; + json_t *json_hooks = nullptr; + json_t *json_mask = nullptr; - const char *mode_str = nullptr; - const char *uuid_str = nullptr; + const char *mode_str = nullptr; + const char *uuid_str = nullptr; - ret = json_unpack_ex(json, &err, 0, "{ s: o, s?: o, s?: o, s?: b, s?: b, s?: b, s?: i, s?: s, s?: b, s?: F, s?: o, s?: b, s?: s, s?: i }", - "in", &json_in, - "out", &json_out, - "hooks", &json_hooks, - "reverse", &rev, - "enabled", &en, - "builtin", &builtin, - "queuelen", &queuelen, - "mode", &mode_str, - "poll", &poll, - "rate", &rate, - "mask", &json_mask, - "original_sequence_no", &original_sequence_no, - "uuid", &uuid_str, - "affinity", &affinity - ); - if (ret) - throw ConfigError(json, err, "node-config-path", "Failed to parse path configuration"); + ret = json_unpack_ex(json, &err, 0, + "{ s: o, s?: o, s?: o, s?: b, s?: b, s?: b, s?: i, s?: " + "s, s?: b, s?: F, s?: o, s?: b, s?: s, s?: i }", + "in", &json_in, "out", &json_out, "hooks", &json_hooks, + "reverse", &rev, "enabled", &en, "builtin", &builtin, + "queuelen", &queuelen, "mode", &mode_str, "poll", &poll, + "rate", &rate, "mask", &json_mask, + "original_sequence_no", &original_sequence_no, "uuid", + &uuid_str, "affinity", &affinity); + if (ret) + throw ConfigError(json, err, "node-config-path", + "Failed to parse path configuration"); - if (en >= 0) - enabled = en != 0; + if (en >= 0) + enabled = en != 0; - if (rev >= 0) - reversed = rev != 0; + if (rev >= 0) + reversed = rev != 0; - // Optional settings - if (mode_str) { - if (!strcmp(mode_str, "any")) - mode = Mode::ANY; - else if (!strcmp(mode_str, "all")) - mode = Mode::ALL; - else - throw ConfigError(json, "node-config-path", "Invalid path mode '{}'", mode_str); - } + // Optional settings + if (mode_str) { + if (!strcmp(mode_str, "any")) + mode = Mode::ANY; + else if (!strcmp(mode_str, "all")) + mode = Mode::ALL; + else + throw ConfigError(json, "node-config-path", "Invalid path mode '{}'", + mode_str); + } - // UUID - if (uuid_str) { - ret = uuid_parse(uuid_str, uuid); - if (ret) - throw ConfigError(json, "node-config-path-uuid", "Failed to parse UUID: {}", uuid_str); - } - else - // Generate UUID from hashed config - uuid::generateFromJson(uuid, json, sn_uuid); + // UUID + if (uuid_str) { + ret = uuid_parse(uuid_str, uuid); + if (ret) + throw ConfigError(json, "node-config-path-uuid", + "Failed to parse UUID: {}", uuid_str); + } else + // Generate UUID from hashed config + uuid::generateFromJson(uuid, json, sn_uuid); - // Input node(s) - ret = mappings.parse(json_in); - if (ret) - throw ConfigError(json_in, "node-config-path-in", "Failed to parse input mapping of path {}", this->toString()); + // Input node(s) + ret = mappings.parse(json_in); + if (ret) + throw ConfigError(json_in, "node-config-path-in", + "Failed to parse input mapping of path {}", + this->toString()); - // Output node(s) - NodeList dests; - if (json_out) { - ret = dests.parse(json_out, nodes); - if (ret) - throw ConfigError(json_out, "node-config-path-out", "Failed to parse output nodes"); - } + // Output node(s) + NodeList dests; + if (json_out) { + ret = dests.parse(json_out, nodes); + if (ret) + throw ConfigError(json_out, "node-config-path-out", + "Failed to parse output nodes"); + } - for (auto *n : dests) { - if (n->out.path) - throw ConfigError(json, "node-config-path", "Every node must only be used by a single path as destination"); + for (auto *n : dests) { + if (n->out.path) + throw ConfigError( + json, "node-config-path", + "Every node must only be used by a single path as destination"); - n->out.path = this; + n->out.path = this; - auto pd = std::make_shared(this, n); - if (!pd) - throw MemoryAllocationError(); + auto pd = std::make_shared(this, n); + if (!pd) + throw MemoryAllocationError(); - n->destinations.push_back(pd); - destinations.push_back(pd); - } + n->destinations.push_back(pd); + destinations.push_back(pd); + } #ifdef WITH_HOOKS - if (json_hooks) - hooks.parse(json_hooks, (int) Hook::Flags::PATH, this, nullptr); + if (json_hooks) + hooks.parse(json_hooks, (int)Hook::Flags::PATH, this, nullptr); #endif // WITH_HOOKS - if (json_mask) - parseMask(json_mask, nodes); + if (json_mask) + parseMask(json_mask, nodes); - config = json; - state = State::PARSED; + config = json; + state = State::PARSED; } -void Path::parseMask(json_t *json_mask, NodeList &nodes) -{ - json_t *json_entry; - size_t i; +void Path::parseMask(json_t *json_mask, NodeList &nodes) { + json_t *json_entry; + size_t i; - if (!json_is_array(json_mask)) - throw ConfigError(json_mask, "node-config-path-mask", "The 'mask' setting must be a list of node names"); + if (!json_is_array(json_mask)) + throw ConfigError(json_mask, "node-config-path-mask", + "The 'mask' setting must be a list of node names"); - json_array_foreach(json_mask, i, json_entry) { - const char *name; - Node *node; + json_array_foreach(json_mask, i, json_entry) { + const char *name; + Node *node; - name = json_string_value(json_entry); - if (!name) - throw ConfigError(json_mask, "node-config-path-mask", "The 'mask' setting must be a list of node names"); + name = json_string_value(json_entry); + if (!name) + throw ConfigError(json_mask, "node-config-path-mask", + "The 'mask' setting must be a list of node names"); - node = nodes.lookup(name); - if (!node) - throw ConfigError(json_mask, "node-config-path-mask", "The 'mask' entry '{}' is not a valid node name", name); + node = nodes.lookup(name); + if (!node) + throw ConfigError(json_mask, "node-config-path-mask", + "The 'mask' entry '{}' is not a valid node name", name); - masked.push_back(node); - } + masked.push_back(node); + } } -void Path::check() -{ - assert(state != State::DESTROYED); +void Path::check() { + assert(state != State::DESTROYED); - if (rate < 0) - throw RuntimeError("Setting 'rate' of path {} must be a positive number.", this->toString()); + if (rate < 0) + throw RuntimeError("Setting 'rate' of path {} must be a positive number.", + this->toString()); - if (!IS_POW2(queuelen)) { - queuelen = LOG2_CEIL(queuelen); - logger->warn("Queue length should always be a power of 2. Adjusting to {}", queuelen); - } + if (!IS_POW2(queuelen)) { + queuelen = LOG2_CEIL(queuelen); + logger->warn("Queue length should always be a power of 2. Adjusting to {}", + queuelen); + } #ifdef WITH_HOOKS - hooks.check(); + hooks.check(); #endif // WITH_HOOKS - state = State::CHECKED; + state = State::CHECKED; } -void Path::checkPrepared() -{ - if (poll == 0) { - // Check that we do not need to multiplex between multiple sources when polling is disabled - if (sources.size() > 1) - throw RuntimeError("Setting 'poll' must be active if the path has more than one source"); +void Path::checkPrepared() { + if (poll == 0) { + // Check that we do not need to multiplex between multiple sources when polling is disabled + if (sources.size() > 1) + throw RuntimeError( + "Setting 'poll' must be active if the path has more than one source"); - // Check that we do not use the fixed rate feature when polling is disabled - if (rate > 0) - throw RuntimeError("Setting 'poll' must be activated when used together with setting 'rate'"); - } - else { - if (rate <= 0) { - // Check that all path sources provide a file descriptor for polling if fixed rate is disabled - for (auto ps : sources) { - if (!(ps->getNode()->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_POLL)) - throw RuntimeError("Node {} can not be used in polling mode with path {}", ps->getNode()->getName(), this->toString()); - } - } - } + // Check that we do not use the fixed rate feature when polling is disabled + if (rate > 0) + throw RuntimeError("Setting 'poll' must be activated when used together " + "with setting 'rate'"); + } else { + if (rate <= 0) { + // Check that all path sources provide a file descriptor for polling if fixed rate is disabled + for (auto ps : sources) { + if (!(ps->getNode()->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_POLL)) + throw RuntimeError( + "Node {} can not be used in polling mode with path {}", + ps->getNode()->getName(), this->toString()); + } + } + } } -void Path::start() -{ - int ret; - const char *mode_str; +void Path::start() { + int ret; + const char *mode_str; - assert(state == State::PREPARED); + assert(state == State::PREPARED); - switch (mode) { - case Mode::ANY: - mode_str = "any"; - break; + switch (mode) { + case Mode::ANY: + mode_str = "any"; + break; - case Mode::ALL: - mode_str = "all"; - break; + case Mode::ALL: + mode_str = "all"; + break; - default: - mode_str = "unknown"; - break; - } + default: + mode_str = "unknown"; + break; + } - logger->info("Starting path {}: #signals={}/{}, #hooks={}, #sources={}, " - "#destinations={}, mode={}, poll={}, mask=0b{:b}, rate={}, " - "enabled={}, reversed={}, queuelen={}, original_sequence_no={}", - this->toString(), - signals->size(), - getOutputSignals()->size(), - hooks.size(), - sources.size(), - destinations.size(), - mode_str, - poll ? "yes" : "no", - mask.to_ullong(), - rate, - isEnabled() ? "yes" : "no", - isReversed() ? "yes" : "no", - queuelen, - original_sequence_no ? "yes" : "no" - ); + logger->info("Starting path {}: #signals={}/{}, #hooks={}, #sources={}, " + "#destinations={}, mode={}, poll={}, mask=0b{:b}, rate={}, " + "enabled={}, reversed={}, queuelen={}, original_sequence_no={}", + this->toString(), signals->size(), getOutputSignals()->size(), + hooks.size(), sources.size(), destinations.size(), mode_str, + poll ? "yes" : "no", mask.to_ullong(), rate, + isEnabled() ? "yes" : "no", isReversed() ? "yes" : "no", + queuelen, original_sequence_no ? "yes" : "no"); #ifdef WITH_HOOKS - hooks.start(); + hooks.start(); #endif // WITH_HOOKS - last_sequence = 0; + last_sequence = 0; - received.reset(); + received.reset(); - // We initialize the intial sample - last_sample = sample_alloc(&pool); - if (!last_sample) - throw MemoryAllocationError(); + // We initialize the intial sample + last_sample = sample_alloc(&pool); + if (!last_sample) + throw MemoryAllocationError(); - last_sample->length = signals->size(); - last_sample->signals = signals; + last_sample->length = signals->size(); + last_sample->signals = signals; - last_sample->ts.origin = time_now(); - last_sample->flags = (int) SampleFlags::HAS_TS_ORIGIN; + last_sample->ts.origin = time_now(); + last_sample->flags = (int)SampleFlags::HAS_TS_ORIGIN; - last_sample->sequence = 0; - last_sample->flags |= (int) SampleFlags::HAS_SEQUENCE; + last_sample->sequence = 0; + last_sample->flags |= (int)SampleFlags::HAS_SEQUENCE; - if (last_sample->length > 0) - last_sample->flags |= (int) SampleFlags::HAS_DATA; + if (last_sample->length > 0) + last_sample->flags |= (int)SampleFlags::HAS_DATA; - for (size_t i = 0; i < last_sample->length; i++) { - auto sig = signals->getByIndex(i); + for (size_t i = 0; i < last_sample->length; i++) { + auto sig = signals->getByIndex(i); - last_sample->data[i] = sig->init; - } + last_sample->data[i] = sig->init; + } - if (poll > 0) - startPoll(); + if (poll > 0) + startPoll(); - state = State::STARTED; + state = State::STARTED; - /* Start one thread per path for sending to destinations + /* Start one thread per path for sending to destinations * * Special case: If the path only has a single source and this source * does not offer a file descriptor for polling, we will use a special * thread function. */ - ret = pthread_create(&tid, nullptr, runWrapper, this); - if (ret) - throw RuntimeError("Failed to create path thread"); + ret = pthread_create(&tid, nullptr, runWrapper, this); + if (ret) + throw RuntimeError("Failed to create path thread"); - if (affinity) - kernel::rt::setThreadAffinity(tid, affinity); + if (affinity) + kernel::rt::setThreadAffinity(tid, affinity); } -void Path::stop() -{ - int ret; +void Path::stop() { + int ret; - if (state != State::STARTED && - state != State::STOPPING) - return; + if (state != State::STARTED && state != State::STOPPING) + return; - logger->info("Stopping path: {}", this->toString()); + logger->info("Stopping path: {}", this->toString()); - if (state != State::STOPPING) - state = State::STOPPING; + if (state != State::STOPPING) + state = State::STOPPING; - /* Cancel the thread in case is currently in a blocking syscall. + /* Cancel the thread in case is currently in a blocking syscall. * * We dont care if the thread has already been terminated. */ - ret = pthread_cancel(tid); - if (ret && ret != ESRCH) - throw RuntimeError("Failed to cancel path thread"); + ret = pthread_cancel(tid); + if (ret && ret != ESRCH) + throw RuntimeError("Failed to cancel path thread"); - ret = pthread_join(tid, nullptr); - if (ret) - throw RuntimeError("Failed to join path thread"); + ret = pthread_join(tid, nullptr); + if (ret) + throw RuntimeError("Failed to join path thread"); #ifdef WITH_HOOKS - hooks.stop(); + hooks.stop(); #endif // WITH_HOOKS - sample_decref(last_sample); + sample_decref(last_sample); - state = State::STOPPED; + state = State::STOPPED; } -Path::~Path() -{ - int ret __attribute__((unused)); +Path::~Path() { + int ret __attribute__((unused)); - assert(state != State::DESTROYED); + assert(state != State::DESTROYED); - ret = pool_destroy(&pool); + ret = pool_destroy(&pool); } -bool Path::isSimple() const -{ - int ret; - const char *in = nullptr, *out = nullptr; +bool Path::isSimple() const { + int ret; + const char *in = nullptr, *out = nullptr; - json_error_t err; - ret = json_unpack_ex(config, &err, 0, "{ s: s, s: s }", "in", &in, "out", &out); - if (ret) - return false; + json_error_t err; + ret = + json_unpack_ex(config, &err, 0, "{ s: s, s: s }", "in", &in, "out", &out); + if (ret) + return false; - ret = Node::isValidName(in); - if (!ret) - return false; + ret = Node::isValidName(in); + if (!ret) + return false; - ret = Node::isValidName(out); - if (!ret) - return false; + ret = Node::isValidName(out); + if (!ret) + return false; - return true; + return true; } -bool Path::isMuxed() const -{ - if (sources.size() > 0) - return true; +bool Path::isMuxed() const { + if (sources.size() > 0) + return true; - if (mappings.size() > 0) - return true; + if (mappings.size() > 0) + return true; - auto me = mappings.front(); + auto me = mappings.front(); - if (me->type != MappingEntry::Type::DATA) - return true; + if (me->type != MappingEntry::Type::DATA) + return true; - if (me->data.offset != 0) - return true; + if (me->data.offset != 0) + return true; - if (me->length != -1) - return true; + if (me->length != -1) + return true; - return false; + return false; } -SignalList::Ptr Path::getOutputSignals(bool after_hooks) -{ +SignalList::Ptr Path::getOutputSignals(bool after_hooks) { #ifdef WITH_HOOKS - if (after_hooks && hooks.size() > 0) - return hooks.getSignals(); + if (after_hooks && hooks.size() > 0) + return hooks.getSignals(); #endif // WITH_HOOKS - return signals; + return signals; } -unsigned Path::getOutputSignalsMaxCount() -{ +unsigned Path::getOutputSignalsMaxCount() { #ifdef WITH_HOOKS - if (hooks.size() > 0) - return MAX(signals->size(), hooks.getSignalsMaxCount()); + if (hooks.size() > 0) + return MAX(signals->size(), hooks.getSignalsMaxCount()); #endif // WITH_HOOKS - return signals->size(); + return signals->size(); } -json_t * Path::toJson() const -{ - json_t *json_signals = signals->toJson(); +json_t *Path::toJson() const { + json_t *json_signals = signals->toJson(); #ifdef WITH_HOOKS - json_t *json_hooks = hooks.toJson(); + json_t *json_hooks = hooks.toJson(); #else - json_t *json_hooks = json_array(); + json_t *json_hooks = json_array(); #endif // WITH_HOOKS - json_t *json_sources = json_array(); - json_t *json_destinations = json_array(); + json_t *json_sources = json_array(); + json_t *json_destinations = json_array(); - for (auto ps : sources) - json_array_append_new(json_sources, json_string(ps->node->getNameShort().c_str())); + for (auto ps : sources) + json_array_append_new(json_sources, + json_string(ps->node->getNameShort().c_str())); - for (auto pd : destinations) - json_array_append_new(json_destinations, json_string(pd->node->getNameShort().c_str())); + for (auto pd : destinations) + json_array_append_new(json_destinations, + json_string(pd->node->getNameShort().c_str())); - json_t *json_path = json_pack("{ s: s, s: s, s: s, s: b, s: b s: b, s: b, s: b, s: b s: i, s: o, s: o, s: o, s: o }", - "uuid", uuid::toString(uuid).c_str(), - "state", stateToString(state).c_str(), - "mode", mode == Mode::ANY ? "any" : "all", - "enabled", enabled, - "builtin", builtin, - "reversed", reversed, - "original_sequence_no", original_sequence_no, - "last_sequence", last_sequence, - "poll", poll, - "queuelen", queuelen, - "signals", json_signals, - "hooks", json_hooks, - "in", json_sources, - "out", json_destinations - ); + json_t *json_path = json_pack( + "{ s: s, s: s, s: s, s: b, s: b s: b, s: b, s: b, s: b s: i, s: o, s: o, " + "s: o, s: o }", + "uuid", uuid::toString(uuid).c_str(), "state", + stateToString(state).c_str(), "mode", mode == Mode::ANY ? "any" : "all", + "enabled", enabled, "builtin", builtin, "reversed", reversed, + "original_sequence_no", original_sequence_no, "last_sequence", + last_sequence, "poll", poll, "queuelen", queuelen, "signals", + json_signals, "hooks", json_hooks, "in", json_sources, "out", + json_destinations); - return json_path; + return json_path; } int villas::node::Path::id = 0; diff --git a/lib/path_destination.cpp b/lib/path_destination.cpp index 08535ad9c..c51332955 100644 --- a/lib/path_destination.cpp +++ b/lib/path_destination.cpp @@ -5,103 +5,105 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include -#include #include +#include +#include +#include #include +#include +#include using namespace villas; using namespace villas::node; -PathDestination::PathDestination(Path *p, Node *n) : - node(n), - path(p) -{ - queue.state = State::DESTROYED; +PathDestination::PathDestination(Path *p, Node *n) : node(n), path(p) { + queue.state = State::DESTROYED; } -PathDestination::~PathDestination() -{ - int ret __attribute__((unused)); +PathDestination::~PathDestination() { + int ret __attribute__((unused)); - ret = queue_destroy(&queue); + ret = queue_destroy(&queue); } -int PathDestination::prepare(int queuelen) -{ - int ret; +int PathDestination::prepare(int queuelen) { + int ret; - ret = queue_init(&queue, queuelen); - if (ret) - return ret; + ret = queue_init(&queue, queuelen); + if (ret) + return ret; - return 0; + return 0; } -void PathDestination::enqueueAll(Path *p, const struct Sample * const smps[], unsigned cnt) -{ - unsigned enqueued, cloned; +void PathDestination::enqueueAll(Path *p, const struct Sample *const smps[], + unsigned cnt) { + unsigned enqueued, cloned; - struct Sample *clones[cnt]; + struct Sample *clones[cnt]; - cloned = sample_clone_many(clones, smps, cnt); - if (cloned < cnt) - p->logger->warn("Pool underrun in path {}", p->toString()); + cloned = sample_clone_many(clones, smps, cnt); + if (cloned < cnt) + p->logger->warn("Pool underrun in path {}", p->toString()); - for (auto pd : p->destinations) { - enqueued = queue_push_many(&pd->queue, (void **) clones, cloned); - if (enqueued != cnt) - p->logger->warn("Queue overrun for path {}", p->toString()); + for (auto pd : p->destinations) { + enqueued = queue_push_many(&pd->queue, (void **)clones, cloned); + if (enqueued != cnt) + p->logger->warn("Queue overrun for path {}", p->toString()); - // Increase reference counter of these samples as they are now also owned by the queue - sample_incref_many(clones, cloned); + // Increase reference counter of these samples as they are now also owned by the queue + sample_incref_many(clones, cloned); - p->logger->debug("Enqueued {} samples to destination {} of path {}", enqueued, pd->node->getName(), p->toString()); - } + p->logger->debug("Enqueued {} samples to destination {} of path {}", + enqueued, pd->node->getName(), p->toString()); + } - sample_decref_many(clones, cloned); + sample_decref_many(clones, cloned); } -void PathDestination::write() -{ - int cnt = node->out.vectorize; - int sent; - int allocated; +void PathDestination::write() { + int cnt = node->out.vectorize; + int sent; + int allocated; - struct Sample *smps[cnt]; + struct Sample *smps[cnt]; - // As long as there are still samples in the queue - while (true) { - allocated = queue_pull_many(&queue, (void **) smps, cnt); - if (allocated == 0) - break; - else if (allocated < cnt) - path->logger->debug("Queue underrun for path {}: allocated={} expected={}", path->toString(), allocated, cnt); + // As long as there are still samples in the queue + while (true) { + allocated = queue_pull_many(&queue, (void **)smps, cnt); + if (allocated == 0) + break; + else if (allocated < cnt) + path->logger->debug( + "Queue underrun for path {}: allocated={} expected={}", + path->toString(), allocated, cnt); - path->logger->debug("Dequeued {} samples from queue of node {} which is part of path {}", allocated, node->getName(), path->toString()); + path->logger->debug( + "Dequeued {} samples from queue of node {} which is part of path {}", + allocated, node->getName(), path->toString()); - sent = node->write(smps, allocated); - if (sent < 0) { - path->logger->error("Failed to sent {} samples to node {}: reason={}", cnt, node->getName(), sent); - return; - } - else if (sent < allocated) - path->logger->debug("Partial write to node {}: written={}, expected={}", node->getName(), sent, allocated); + sent = node->write(smps, allocated); + if (sent < 0) { + path->logger->error("Failed to sent {} samples to node {}: reason={}", + cnt, node->getName(), sent); + return; + } else if (sent < allocated) + path->logger->debug("Partial write to node {}: written={}, expected={}", + node->getName(), sent, allocated); - int released = sample_decref_many(smps, allocated); + int released = sample_decref_many(smps, allocated); - path->logger->debug("Released {} samples back to memory pool", released); - } + path->logger->debug("Released {} samples back to memory pool", released); + } } -void PathDestination::check() -{ - if (!node->isEnabled()) - throw RuntimeError("Destination {} is not enabled", node->getName()); +void PathDestination::check() { + if (!node->isEnabled()) + throw RuntimeError("Destination {} is not enabled", node->getName()); - if (!(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_WRITE)) - throw RuntimeError("Destination node {} is not supported as a sink for path ", node->getName()); + if (!(node->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_WRITE)) + throw RuntimeError( + "Destination node {} is not supported as a sink for path ", + node->getName()); } diff --git a/lib/path_list.cpp b/lib/path_list.cpp index b2b8214da..deff55c26 100644 --- a/lib/path_list.cpp +++ b/lib/path_list.cpp @@ -5,27 +5,25 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include using namespace villas::node; -Path * PathList::lookup(const uuid_t &uuid) const -{ - for (auto *p : *this) { - if (!uuid_compare(uuid, p->uuid)) - return p; - } +Path *PathList::lookup(const uuid_t &uuid) const { + for (auto *p : *this) { + if (!uuid_compare(uuid, p->uuid)) + return p; + } - return nullptr; + return nullptr; } -json_t * PathList::toJson() const -{ - json_t *json_paths = json_array(); +json_t *PathList::toJson() const { + json_t *json_paths = json_array(); - for (auto *p : *this) - json_array_append_new(json_paths, p->toJson()); + for (auto *p : *this) + json_array_append_new(json_paths, p->toJson()); - return json_paths; + return json_paths; } diff --git a/lib/path_source.cpp b/lib/path_source.cpp index 8e6922648..ec138e71d 100644 --- a/lib/path_source.cpp +++ b/lib/path_source.cpp @@ -7,12 +7,12 @@ #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include #include @@ -22,201 +22,195 @@ using namespace villas; using namespace villas::node; -PathSource::PathSource(Path *p, Node *n) : - node(n), - path(p), - masked(false) -{ - int ret; +PathSource::PathSource(Path *p, Node *n) : node(n), path(p), masked(false) { + int ret; - int pool_size = MAX(DEFAULT_QUEUE_LENGTH, 20 * node->in.vectorize); - ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(node->getInputSignalsMaxCount()), node->getMemoryType()); - if (ret) - throw RuntimeError("Failed to initialize pool"); + int pool_size = MAX(DEFAULT_QUEUE_LENGTH, 20 * node->in.vectorize); + ret = pool_init(&pool, pool_size, + SAMPLE_LENGTH(node->getInputSignalsMaxCount()), + node->getMemoryType()); + if (ret) + throw RuntimeError("Failed to initialize pool"); } -PathSource::~PathSource() -{ - int ret __attribute__((unused)); +PathSource::~PathSource() { + int ret __attribute__((unused)); - ret = pool_destroy(&pool); + ret = pool_destroy(&pool); } -int PathSource::read(int i) -{ - int ret, recv, tomux, allocated, cnt, toenqueue, enqueued = 0, muxed_initialized = 0; +int PathSource::read(int i) { + int ret, recv, tomux, allocated, cnt, toenqueue, enqueued = 0, + muxed_initialized = 0; - cnt = node->in.vectorize; + cnt = node->in.vectorize; - struct Sample *read_smps[cnt]; - struct Sample *muxed_smps[cnt]; - struct Sample **tomux_smps; + struct Sample *read_smps[cnt]; + struct Sample *muxed_smps[cnt]; + struct Sample **tomux_smps; - // Fill smps[] free sample blocks from the pool - allocated = sample_alloc_many(&pool, read_smps, cnt); - if (allocated != cnt) - path->logger->warn("Pool underrun for path source {}", node->getName()); + // Fill smps[] free sample blocks from the pool + allocated = sample_alloc_many(&pool, read_smps, cnt); + if (allocated != cnt) + path->logger->warn("Pool underrun for path source {}", node->getName()); - // Read ready samples and store them to blocks pointed by smps[] - recv = node->read(read_smps, allocated); - if (recv == 0) { - enqueued = 0; - goto read_decref_read_smps; - } - else if (recv < 0) { - if (node->getState() == State::STOPPING) { - path->state = State::STOPPING; + // Read ready samples and store them to blocks pointed by smps[] + recv = node->read(read_smps, allocated); + if (recv == 0) { + enqueued = 0; + goto read_decref_read_smps; + } else if (recv < 0) { + if (node->getState() == State::STOPPING) { + path->state = State::STOPPING; - enqueued = -1; - goto read_decref_read_smps; - } - else { - path->logger->error("Failed to read samples from node {}", node->getName()); - enqueued = 0; - goto read_decref_read_smps; - } - } - else if (recv < allocated) - path->logger->warn("Partial read for path {}: read={}, expected={}", path->toString(), recv, allocated); + enqueued = -1; + goto read_decref_read_smps; + } else { + path->logger->error("Failed to read samples from node {}", + node->getName()); + enqueued = 0; + goto read_decref_read_smps; + } + } else if (recv < allocated) + path->logger->warn("Partial read for path {}: read={}, expected={}", + path->toString(), recv, allocated); - // Let the master path sources forward received samples to their secondaries - writeToSecondaries(read_smps, recv); + // Let the master path sources forward received samples to their secondaries + writeToSecondaries(read_smps, recv); - if (path->mode == Path::Mode::ANY) { // Mux all samples - tomux_smps = read_smps; - tomux = recv; - } - else { // Mux only last sample and discard others - tomux_smps = read_smps + recv - 1; - tomux = 1; - } + if (path->mode == Path::Mode::ANY) { // Mux all samples + tomux_smps = read_smps; + tomux = recv; + } else { // Mux only last sample and discard others + tomux_smps = read_smps + recv - 1; + tomux = 1; + } - for (int i = 0; i < tomux; i++) { - muxed_smps[i] = i == 0 - ? sample_clone(path->last_sample) - : sample_clone(muxed_smps[i-1]); - if (!muxed_smps[i]) { - path->logger->error("Pool underrun in path {}", path->toString()); - muxed_initialized = i == 0 ? 0 : i-1; - enqueued = -1; - goto read_decref_muxed_smps; - } + for (int i = 0; i < tomux; i++) { + muxed_smps[i] = i == 0 ? sample_clone(path->last_sample) + : sample_clone(muxed_smps[i - 1]); + if (!muxed_smps[i]) { + path->logger->error("Pool underrun in path {}", path->toString()); + muxed_initialized = i == 0 ? 0 : i - 1; + enqueued = -1; + goto read_decref_muxed_smps; + } - if (path->original_sequence_no) { - muxed_smps[i]->sequence = tomux_smps[i]->sequence; - muxed_smps[i]->flags |= tomux_smps[i]->flags & (int) SampleFlags::HAS_SEQUENCE; - } - else { - muxed_smps[i]->sequence = path->last_sequence++; - muxed_smps[i]->flags |= (int) SampleFlags::HAS_SEQUENCE; - } + if (path->original_sequence_no) { + muxed_smps[i]->sequence = tomux_smps[i]->sequence; + muxed_smps[i]->flags |= + tomux_smps[i]->flags & (int)SampleFlags::HAS_SEQUENCE; + } else { + muxed_smps[i]->sequence = path->last_sequence++; + muxed_smps[i]->flags |= (int)SampleFlags::HAS_SEQUENCE; + } - /* We reset the sample length after each restart of the simulation. + /* We reset the sample length after each restart of the simulation. * This is necessary for the test_rtt node to work properly. */ - if (tomux_smps[i]->flags & (int) SampleFlags::IS_FIRST) - muxed_smps[i]->length = 0; + if (tomux_smps[i]->flags & (int)SampleFlags::IS_FIRST) + muxed_smps[i]->length = 0; - muxed_smps[i]->ts = tomux_smps[i]->ts; - muxed_smps[i]->flags |= tomux_smps[i]->flags & (int) SampleFlags::HAS_TS; + muxed_smps[i]->ts = tomux_smps[i]->ts; + muxed_smps[i]->flags |= tomux_smps[i]->flags & (int)SampleFlags::HAS_TS; - ret = mappings.remap(muxed_smps[i], tomux_smps[i]); - if (ret < 0) { - enqueued = ret; - muxed_initialized = i; - goto read_decref_muxed_smps; - } + ret = mappings.remap(muxed_smps[i], tomux_smps[i]); + if (ret < 0) { + enqueued = ret; + muxed_initialized = i; + goto read_decref_muxed_smps; + } - if (muxed_smps[i]->length > 0) - muxed_smps[i]->flags |= (int) SampleFlags::HAS_DATA; - } - muxed_initialized = tomux; + if (muxed_smps[i]->length > 0) + muxed_smps[i]->flags |= (int)SampleFlags::HAS_DATA; + } + muxed_initialized = tomux; - sample_copy(path->last_sample, muxed_smps[tomux-1]); + sample_copy(path->last_sample, muxed_smps[tomux - 1]); #ifdef WITH_HOOKS - toenqueue = path->hooks.process(muxed_smps, tomux); - if (toenqueue == -1) { - path->logger->error("An error occured during hook processing. Skipping sample"); + toenqueue = path->hooks.process(muxed_smps, tomux); + if (toenqueue == -1) { + path->logger->error( + "An error occured during hook processing. Skipping sample"); - } - else if (toenqueue != tomux) { - int skipped = tomux - toenqueue; + } else if (toenqueue != tomux) { + int skipped = tomux - toenqueue; - path->logger->debug("Hooks skipped {} out of {} samples for path {}", skipped, tomux, path->toString()); - } + path->logger->debug("Hooks skipped {} out of {} samples for path {}", + skipped, tomux, path->toString()); + } #else - toenqueue = tomux; + toenqueue = tomux; #endif - path->received.set(i); + path->received.set(i); - path->logger->debug("received=0b{:b}, mask=0b{:b}", path->received.to_ullong(), path->mask.to_ullong()); + path->logger->debug("received=0b{:b}, mask=0b{:b}", + path->received.to_ullong(), path->mask.to_ullong()); - if (path->mask.test(i)) { - // Enqueue always - if (path->mode == Path::Mode::ANY) { - enqueued = toenqueue; - PathDestination::enqueueAll(path, muxed_smps, toenqueue); - } - // Enqueue only if received == mask bitset - else if (path->mode == Path::Mode::ALL) { - if (path->mask == path->received) { - PathDestination::enqueueAll(path, muxed_smps, toenqueue); + if (path->mask.test(i)) { + // Enqueue always + if (path->mode == Path::Mode::ANY) { + enqueued = toenqueue; + PathDestination::enqueueAll(path, muxed_smps, toenqueue); + } + // Enqueue only if received == mask bitset + else if (path->mode == Path::Mode::ALL) { + if (path->mask == path->received) { + PathDestination::enqueueAll(path, muxed_smps, toenqueue); - path->received.reset(); + path->received.reset(); - enqueued = toenqueue; - } - else - enqueued = 0; - } - } - else - enqueued = 0; + enqueued = toenqueue; + } else + enqueued = 0; + } + } else + enqueued = 0; read_decref_muxed_smps: - sample_decref_many(muxed_smps, muxed_initialized); + sample_decref_many(muxed_smps, muxed_initialized); read_decref_read_smps: - sample_decref_many(read_smps, allocated); + sample_decref_many(read_smps, allocated); - return enqueued; + return enqueued; } -void PathSource::check() -{ - if (!node->isEnabled()) - throw RuntimeError("Source {} is not enabled", node->getName()); +void PathSource::check() { + if (!node->isEnabled()) + throw RuntimeError("Source {} is not enabled", node->getName()); - if (!(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_READ)) - throw RuntimeError("Node {} is not supported as a source for a path", node->getName()); + if (!(node->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_READ)) + throw RuntimeError("Node {} is not supported as a source for a path", + node->getName()); } -MasterPathSource::MasterPathSource(Path *p, Node *n) : - PathSource(p, n) -{ } +MasterPathSource::MasterPathSource(Path *p, Node *n) : PathSource(p, n) {} -void MasterPathSource::writeToSecondaries(struct Sample *smps[], unsigned cnt) -{ - for (auto sps : secondaries) { - int sent = sps->getNode()->write(smps, cnt); - if (sent < 0) - throw RuntimeError("Failed to write secondary path source {} of path {}", sps->getNode()->getName(), path->toString()); - else if ((unsigned) sent < cnt) - path->logger->warn("Partial write to secondary path source {} of path {}", sps->getNode()->getName(), path->toString()); - } +void MasterPathSource::writeToSecondaries(struct Sample *smps[], unsigned cnt) { + for (auto sps : secondaries) { + int sent = sps->getNode()->write(smps, cnt); + if (sent < 0) + throw RuntimeError("Failed to write secondary path source {} of path {}", + sps->getNode()->getName(), path->toString()); + else if ((unsigned)sent < cnt) + path->logger->warn("Partial write to secondary path source {} of path {}", + sps->getNode()->getName(), path->toString()); + } } -SecondaryPathSource::SecondaryPathSource(Path *p, Node *n, NodeList &nodes, PathSource::Ptr m) : - PathSource(p, n), - master(m) -{ - auto mps = std::dynamic_pointer_cast(m); +SecondaryPathSource::SecondaryPathSource(Path *p, Node *n, NodeList &nodes, + PathSource::Ptr m) + : PathSource(p, n), master(m) { + auto mps = std::dynamic_pointer_cast(m); - node = new InternalLoopbackNode(n, mps->getSecondaries().size(), mps->getPath()->queuelen); - if (!node) - throw RuntimeError("Failed to create internal loopback"); + node = new InternalLoopbackNode(n, mps->getSecondaries().size(), + mps->getPath()->queuelen); + if (!node) + throw RuntimeError("Failed to create internal loopback"); - // Register new loopback node in node list of super node - nodes.push_back(node); + // Register new loopback node in node list of super node + nodes.push_back(node); } diff --git a/lib/pool.cpp b/lib/pool.cpp index a34cf839d..f3c4c0465 100644 --- a/lib/pool.cpp +++ b/lib/pool.cpp @@ -5,83 +5,81 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include -#include -#include #include #include +#include +#include +#include using namespace villas; -int villas::node::pool_init(struct Pool *p, size_t cnt, size_t blocksz, struct memory::Type *m) -{ - int ret; - auto logger = logging.get("pool"); +int villas::node::pool_init(struct Pool *p, size_t cnt, size_t blocksz, + struct memory::Type *m) { + int ret; + auto logger = logging.get("pool"); - // Make sure that we use a block size that is aligned to the size of a cache line - p->alignment = kernel::getCachelineSize(); - p->blocksz = p->alignment * CEIL(blocksz, p->alignment); - p->len = cnt * p->blocksz; + // Make sure that we use a block size that is aligned to the size of a cache line + p->alignment = kernel::getCachelineSize(); + p->blocksz = p->alignment * CEIL(blocksz, p->alignment); + p->len = cnt * p->blocksz; - logger->debug("New memory pool: alignment={}, blocksz={}, len={}, memory={}", p->alignment, p->blocksz, p->len, m->name); + logger->debug("New memory pool: alignment={}, blocksz={}, len={}, memory={}", + p->alignment, p->blocksz, p->len, m->name); - void *buffer = memory::alloc_aligned(p->len, p->alignment, m); - if (!buffer) - throw MemoryAllocationError(); + void *buffer = memory::alloc_aligned(p->len, p->alignment, m); + if (!buffer) + throw MemoryAllocationError(); - logger->debug("Allocated {:#x} bytes for memory pool", p->len); + logger->debug("Allocated {:#x} bytes for memory pool", p->len); - p->buffer_off = (char*) buffer - (char*) p; + p->buffer_off = (char *)buffer - (char *)p; - ret = queue_init(&p->queue, LOG2_CEIL(cnt), m); - if (ret) - return ret; + ret = queue_init(&p->queue, LOG2_CEIL(cnt), m); + if (ret) + return ret; - for (unsigned i = 0; i < cnt; i++) - queue_push(&p->queue, (char *) buffer + i * p->blocksz); + for (unsigned i = 0; i < cnt; i++) + queue_push(&p->queue, (char *)buffer + i * p->blocksz); - p->state = State::INITIALIZED; + p->state = State::INITIALIZED; - return 0; + return 0; } -int villas::node::pool_destroy(struct Pool *p) -{ - int ret; +int villas::node::pool_destroy(struct Pool *p) { + int ret; - if (p->state == State::DESTROYED) - return 0; + if (p->state == State::DESTROYED) + return 0; - ret = queue_destroy(&p->queue); - if (ret) - return ret; + ret = queue_destroy(&p->queue); + if (ret) + return ret; - void *buffer = (char *) p + p->buffer_off; - ret = memory::free(buffer); - if (ret == 0) - p->state = State::DESTROYED; + void *buffer = (char *)p + p->buffer_off; + ret = memory::free(buffer); + if (ret == 0) + p->state = State::DESTROYED; - return ret; + return ret; } -ssize_t villas::node::pool_get_many(struct Pool *p, void *blocks[], size_t cnt) -{ - return queue_pull_many(&p->queue, blocks, cnt); +ssize_t villas::node::pool_get_many(struct Pool *p, void *blocks[], + size_t cnt) { + return queue_pull_many(&p->queue, blocks, cnt); } -ssize_t villas::node::pool_put_many(struct Pool *p, void *blocks[], size_t cnt) -{ - return queue_push_many(&p->queue, blocks, cnt); +ssize_t villas::node::pool_put_many(struct Pool *p, void *blocks[], + size_t cnt) { + return queue_push_many(&p->queue, blocks, cnt); } -void * villas::node::pool_get(struct Pool *p) -{ - void *ptr; - return queue_pull(&p->queue, &ptr) == 1 ? ptr : nullptr; +void *villas::node::pool_get(struct Pool *p) { + void *ptr; + return queue_pull(&p->queue, &ptr) == 1 ? ptr : nullptr; } -int villas::node::pool_put(struct Pool *p, void *buf) -{ - return queue_push(&p->queue, buf); +int villas::node::pool_put(struct Pool *p, void *buf) { + return queue_push(&p->queue, buf); } diff --git a/lib/queue.cpp b/lib/queue.cpp index c37f495cd..eb1f96407 100644 --- a/lib/queue.cpp +++ b/lib/queue.cpp @@ -31,172 +31,175 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include #include -#include -#include using namespace villas; // Initialize MPMC queue -int villas::node::queue_init(struct CQueue *q, size_t size, struct memory::Type *m) -{ - // Queue size must be 2 exponent - if (!IS_POW2(size)) { - size_t old_size = size; - size = LOG2_CEIL(size); +int villas::node::queue_init(struct CQueue *q, size_t size, + struct memory::Type *m) { + // Queue size must be 2 exponent + if (!IS_POW2(size)) { + size_t old_size = size; + size = LOG2_CEIL(size); - auto logger = logging.get("queue"); - logger->warn("A queue size was changed from {} to {}", old_size, size); - } + auto logger = logging.get("queue"); + logger->warn("A queue size was changed from {} to {}", old_size, size); + } - q->buffer_mask = size - 1; - struct CQueue_cell *buffer = (struct CQueue_cell *) memory::alloc(sizeof(struct CQueue_cell) * size, m); - if (!buffer) - return -2; + q->buffer_mask = size - 1; + struct CQueue_cell *buffer = + (struct CQueue_cell *)memory::alloc(sizeof(struct CQueue_cell) * size, m); + if (!buffer) + return -2; - q->buffer_off = (char *) buffer - (char *) q; + q->buffer_off = (char *)buffer - (char *)q; - for (size_t i = 0; i != size; i += 1) - std::atomic_store_explicit(&buffer[i].sequence, i, std::memory_order_relaxed); + for (size_t i = 0; i != size; i += 1) + std::atomic_store_explicit(&buffer[i].sequence, i, + std::memory_order_relaxed); #ifndef __arm__ - std::atomic_store_explicit(&q->tail, 0ul, std::memory_order_relaxed); - std::atomic_store_explicit(&q->head, 0ul, std::memory_order_relaxed); + std::atomic_store_explicit(&q->tail, 0ul, std::memory_order_relaxed); + std::atomic_store_explicit(&q->head, 0ul, std::memory_order_relaxed); #else - std::atomic_store_explicit(&q->tail, 0u, std::memory_order_relaxed); - std::atomic_store_explicit(&q->head, 0u, std::memory_order_relaxed); + std::atomic_store_explicit(&q->tail, 0u, std::memory_order_relaxed); + std::atomic_store_explicit(&q->head, 0u, std::memory_order_relaxed); #endif - q->state = State::INITIALIZED; + q->state = State::INITIALIZED; - return 0; + return 0; } -int villas::node::queue_destroy(struct CQueue *q) -{ - void *buffer = (char *) q + q->buffer_off; - int ret = 0; +int villas::node::queue_destroy(struct CQueue *q) { + void *buffer = (char *)q + q->buffer_off; + int ret = 0; - if (q->state == State::DESTROYED) - return 0; + if (q->state == State::DESTROYED) + return 0; - ret = memory::free(buffer); - if (ret == 0) - q->state = State::DESTROYED; + ret = memory::free(buffer); + if (ret == 0) + q->state = State::DESTROYED; - return ret; + return ret; } -size_t villas::node::queue_available(struct CQueue *q) -{ - return std::atomic_load_explicit(&q->tail, std::memory_order_relaxed) - - std::atomic_load_explicit(&q->head, std::memory_order_relaxed); +size_t villas::node::queue_available(struct CQueue *q) { + return std::atomic_load_explicit(&q->tail, std::memory_order_relaxed) - + std::atomic_load_explicit(&q->head, std::memory_order_relaxed); } -int villas::node::queue_push(struct CQueue *q, void *ptr) -{ - struct CQueue_cell *cell, *buffer; - size_t pos, seq; - intptr_t diff; +int villas::node::queue_push(struct CQueue *q, void *ptr) { + struct CQueue_cell *cell, *buffer; + size_t pos, seq; + intptr_t diff; - if (std::atomic_load_explicit(&q->state, std::memory_order_relaxed) == State::STOPPED) - return -1; + if (std::atomic_load_explicit(&q->state, std::memory_order_relaxed) == + State::STOPPED) + return -1; - buffer = (struct CQueue_cell *) ((char *) q + q->buffer_off); - pos = std::atomic_load_explicit(&q->tail, std::memory_order_relaxed); - while (true) { - cell = &buffer[pos & q->buffer_mask]; - seq = std::atomic_load_explicit(&cell->sequence, std::memory_order_acquire); - diff = (intptr_t) seq - (intptr_t) pos; + buffer = (struct CQueue_cell *)((char *)q + q->buffer_off); + pos = std::atomic_load_explicit(&q->tail, std::memory_order_relaxed); + while (true) { + cell = &buffer[pos & q->buffer_mask]; + seq = std::atomic_load_explicit(&cell->sequence, std::memory_order_acquire); + diff = (intptr_t)seq - (intptr_t)pos; - if (diff == 0) { - if (std::atomic_compare_exchange_weak_explicit(&q->tail, &pos, pos + 1, std::memory_order_relaxed, std::memory_order_relaxed)) - break; - } - else if (diff < 0) - return 0; - else - pos = std::atomic_load_explicit(&q->tail, std::memory_order_relaxed); - } + if (diff == 0) { + if (std::atomic_compare_exchange_weak_explicit(&q->tail, &pos, pos + 1, + std::memory_order_relaxed, + std::memory_order_relaxed)) + break; + } else if (diff < 0) + return 0; + else + pos = std::atomic_load_explicit(&q->tail, std::memory_order_relaxed); + } - cell->data_off = (char *) ptr - (char *) q; - std::atomic_store_explicit(&cell->sequence, pos + 1, std::memory_order_release); + cell->data_off = (char *)ptr - (char *)q; + std::atomic_store_explicit(&cell->sequence, pos + 1, + std::memory_order_release); - return 1; + return 1; } -int villas::node::queue_pull(struct CQueue *q, void **ptr) -{ - struct CQueue_cell *cell, *buffer; - size_t pos, seq; - intptr_t diff; +int villas::node::queue_pull(struct CQueue *q, void **ptr) { + struct CQueue_cell *cell, *buffer; + size_t pos, seq; + intptr_t diff; - if (std::atomic_load_explicit(&q->state, std::memory_order_relaxed) == State::STOPPED) - return -1; + if (std::atomic_load_explicit(&q->state, std::memory_order_relaxed) == + State::STOPPED) + return -1; - buffer = (struct CQueue_cell *) ((char *) q + q->buffer_off); - pos = std::atomic_load_explicit(&q->head, std::memory_order_relaxed); - while (true) { - cell = &buffer[pos & q->buffer_mask]; - seq = std::atomic_load_explicit(&cell->sequence, std::memory_order_acquire); - diff = (intptr_t) seq - (intptr_t) (pos + 1); + buffer = (struct CQueue_cell *)((char *)q + q->buffer_off); + pos = std::atomic_load_explicit(&q->head, std::memory_order_relaxed); + while (true) { + cell = &buffer[pos & q->buffer_mask]; + seq = std::atomic_load_explicit(&cell->sequence, std::memory_order_acquire); + diff = (intptr_t)seq - (intptr_t)(pos + 1); - if (diff == 0) { - if (atomic_compare_exchange_weak_explicit(&q->head, &pos, pos + 1, std::memory_order_relaxed, std::memory_order_relaxed)) - break; - } - else if (diff < 0) - return 0; - else - pos = std::atomic_load_explicit(&q->head, std::memory_order_relaxed); - } + if (diff == 0) { + if (atomic_compare_exchange_weak_explicit(&q->head, &pos, pos + 1, + std::memory_order_relaxed, + std::memory_order_relaxed)) + break; + } else if (diff < 0) + return 0; + else + pos = std::atomic_load_explicit(&q->head, std::memory_order_relaxed); + } - *ptr = (char *) q + cell->data_off; - std::atomic_store_explicit(&cell->sequence, pos + q->buffer_mask + 1, std::memory_order_release); + *ptr = (char *)q + cell->data_off; + std::atomic_store_explicit(&cell->sequence, pos + q->buffer_mask + 1, + std::memory_order_release); - return 1; + return 1; } -int villas::node::queue_push_many(struct CQueue *q, void *ptr[], size_t cnt) -{ - int ret; - size_t i; +int villas::node::queue_push_many(struct CQueue *q, void *ptr[], size_t cnt) { + int ret; + size_t i; - for (ret = 0, i = 0; i < cnt; i++) { - ret = queue_push(q, ptr[i]); - if (ret <= 0) - break; - } + for (ret = 0, i = 0; i < cnt; i++) { + ret = queue_push(q, ptr[i]); + if (ret <= 0) + break; + } - if (ret == -1 && i == 0) - return -1; + if (ret == -1 && i == 0) + return -1; - return i; + return i; } -int villas::node::queue_pull_many(struct CQueue *q, void *ptr[], size_t cnt) -{ - int ret; - size_t i; +int villas::node::queue_pull_many(struct CQueue *q, void *ptr[], size_t cnt) { + int ret; + size_t i; - for (ret = 0, i = 0; i < cnt; i++) { - ret = queue_pull(q, &ptr[i]); - if (ret <= 0) - break; - } + for (ret = 0, i = 0; i < cnt; i++) { + ret = queue_pull(q, &ptr[i]); + if (ret <= 0) + break; + } - if (ret == -1 && i == 0) - return -1; + if (ret == -1 && i == 0) + return -1; - return i; + return i; } -int villas::node::queue_close(struct CQueue *q) -{ - enum State expected = State::INITIALIZED; - if (std::atomic_compare_exchange_weak_explicit(&q->state, &expected, State::STOPPED, std::memory_order_relaxed, std::memory_order_relaxed)) - return 0; +int villas::node::queue_close(struct CQueue *q) { + enum State expected = State::INITIALIZED; + if (std::atomic_compare_exchange_weak_explicit( + &q->state, &expected, State::STOPPED, std::memory_order_relaxed, + std::memory_order_relaxed)) + return 0; - return -1; + return -1; } diff --git a/lib/queue_signalled.cpp b/lib/queue_signalled.cpp index f8fbeaad2..0b3ec44f4 100644 --- a/lib/queue_signalled.cpp +++ b/lib/queue_signalled.cpp @@ -9,293 +9,284 @@ #include #ifdef HAS_EVENTFD - #include +#include #endif using namespace villas::node; -static -void queue_signalled_cleanup(void *p) -{ - struct CQueueSignalled *qs = (struct CQueueSignalled *) p; +static void queue_signalled_cleanup(void *p) { + struct CQueueSignalled *qs = (struct CQueueSignalled *)p; - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_unlock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_unlock(&qs->pthread.mutex); } -int villas::node::queue_signalled_init(struct CQueueSignalled *qs, size_t size, struct memory::Type *mem, enum QueueSignalledMode mode, int flags) -{ - int ret; +int villas::node::queue_signalled_init(struct CQueueSignalled *qs, size_t size, + struct memory::Type *mem, + enum QueueSignalledMode mode, + int flags) { + int ret; - qs->mode = mode; + qs->mode = mode; - if (qs->mode == QueueSignalledMode::AUTO) { + if (qs->mode == QueueSignalledMode::AUTO) { #ifdef __linux__ - if (flags & (int) QueueSignalledFlags::PROCESS_SHARED) - qs->mode = QueueSignalledMode::PTHREAD; - else { + if (flags & (int)QueueSignalledFlags::PROCESS_SHARED) + qs->mode = QueueSignalledMode::PTHREAD; + else { #ifdef HAS_EVENTFD - qs->mode = QueueSignalledMode::EVENTFD; + qs->mode = QueueSignalledMode::EVENTFD; #else - qs->mode = QueueSignalledMode::PTHREAD; + qs->mode = QueueSignalledMode::PTHREAD; #endif - } + } #else - qs->mode = QueueSignalledMode::PTHREAD; + qs->mode = QueueSignalledMode::PTHREAD; #endif - } + } - ret = queue_init(&qs->queue, size, mem); - if (ret < 0) - return ret; + ret = queue_init(&qs->queue, size, mem); + if (ret < 0) + return ret; - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_condattr_t cvattr; - pthread_mutexattr_t mtattr; + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_condattr_t cvattr; + pthread_mutexattr_t mtattr; - pthread_mutexattr_init(&mtattr); - pthread_condattr_init(&cvattr); + pthread_mutexattr_init(&mtattr); + pthread_condattr_init(&cvattr); - if (flags & (int) QueueSignalledFlags::PROCESS_SHARED) { - pthread_mutexattr_setpshared(&mtattr, PTHREAD_PROCESS_SHARED); - pthread_condattr_setpshared(&cvattr, PTHREAD_PROCESS_SHARED); - } + if (flags & (int)QueueSignalledFlags::PROCESS_SHARED) { + pthread_mutexattr_setpshared(&mtattr, PTHREAD_PROCESS_SHARED); + pthread_condattr_setpshared(&cvattr, PTHREAD_PROCESS_SHARED); + } - pthread_mutex_init(&qs->pthread.mutex, &mtattr); - pthread_cond_init(&qs->pthread.ready, &cvattr); + pthread_mutex_init(&qs->pthread.mutex, &mtattr); + pthread_cond_init(&qs->pthread.ready, &cvattr); - pthread_mutexattr_destroy(&mtattr); - pthread_condattr_destroy(&cvattr); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + pthread_mutexattr_destroy(&mtattr); + pthread_condattr_destroy(&cvattr); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - qs->eventfd = eventfd(0, 0); - if (qs->eventfd < 0) - return -2; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + qs->eventfd = eventfd(0, 0); + if (qs->eventfd < 0) + return -2; + } #endif - else - return -1; + else + return -1; - return 0; + return 0; } -int villas::node::queue_signalled_destroy(struct CQueueSignalled *qs) -{ - int ret; +int villas::node::queue_signalled_destroy(struct CQueueSignalled *qs) { + int ret; - ret = queue_destroy(&qs->queue); - if (ret < 0) - return ret; + ret = queue_destroy(&qs->queue); + if (ret < 0) + return ret; - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_cond_destroy(&qs->pthread.ready); - pthread_mutex_destroy(&qs->pthread.mutex); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_cond_destroy(&qs->pthread.ready); + pthread_mutex_destroy(&qs->pthread.mutex); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - ret = close(qs->eventfd); - if (ret) - return ret; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + ret = close(qs->eventfd); + if (ret) + return ret; + } #endif - else - return -1; + else + return -1; - return 0; + return 0; } -int villas::node::queue_signalled_push(struct CQueueSignalled *qs, void *ptr) -{ - int pushed; +int villas::node::queue_signalled_push(struct CQueueSignalled *qs, void *ptr) { + int pushed; - pushed = queue_push(&qs->queue, ptr); - if (pushed <= 0) - return pushed; + pushed = queue_push(&qs->queue, ptr); + if (pushed <= 0) + return pushed; - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_mutex_lock(&qs->pthread.mutex); - pthread_cond_broadcast(&qs->pthread.ready); - pthread_mutex_unlock(&qs->pthread.mutex); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_mutex_lock(&qs->pthread.mutex); + pthread_cond_broadcast(&qs->pthread.ready); + pthread_mutex_unlock(&qs->pthread.mutex); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t incr = 1; - ret = write(qs->eventfd, &incr, sizeof(incr)); - if (ret < 0) - return ret; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t incr = 1; + ret = write(qs->eventfd, &incr, sizeof(incr)); + if (ret < 0) + return ret; + } #endif - else - return -1; + else + return -1; - return pushed; + return pushed; } -int villas::node::queue_signalled_push_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) -{ - int pushed; +int villas::node::queue_signalled_push_many(struct CQueueSignalled *qs, + void *ptr[], size_t cnt) { + int pushed; - pushed = queue_push_many(&qs->queue, ptr, cnt); - if (pushed <= 0) - return pushed; + pushed = queue_push_many(&qs->queue, ptr, cnt); + if (pushed <= 0) + return pushed; - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_mutex_lock(&qs->pthread.mutex); - pthread_cond_broadcast(&qs->pthread.ready); - pthread_mutex_unlock(&qs->pthread.mutex); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_mutex_lock(&qs->pthread.mutex); + pthread_cond_broadcast(&qs->pthread.ready); + pthread_mutex_unlock(&qs->pthread.mutex); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t incr = 1; - ret = write(qs->eventfd, &incr, sizeof(incr)); - if (ret < 0) - return ret; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t incr = 1; + ret = write(qs->eventfd, &incr, sizeof(incr)); + if (ret < 0) + return ret; + } #endif - else - return -1; + else + return -1; - return pushed; + return pushed; } -int villas::node::queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) -{ - int pulled = 0; +int villas::node::queue_signalled_pull(struct CQueueSignalled *qs, void **ptr) { + int pulled = 0; - // Make sure that qs->mutex is unlocked if this thread gets cancelled - pthread_cleanup_push(queue_signalled_cleanup, qs); + // Make sure that qs->mutex is unlocked if this thread gets cancelled + pthread_cleanup_push(queue_signalled_cleanup, qs); - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_lock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_lock(&qs->pthread.mutex); - while (!pulled) { - pulled = queue_pull(&qs->queue, ptr); - if (pulled < 0) - break; - else if (pulled == 0) { - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); - else if (qs->mode == QueueSignalledMode::POLLING) - continue; // Try again + while (!pulled) { + pulled = queue_pull(&qs->queue, ptr); + if (pulled < 0) + break; + else if (pulled == 0) { + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); + else if (qs->mode == QueueSignalledMode::POLLING) + continue; // Try again #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t cntr; - ret = read(qs->eventfd, &cntr, sizeof(cntr)); - if (ret < 0) - break; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t cntr; + ret = read(qs->eventfd, &cntr, sizeof(cntr)); + if (ret < 0) + break; + } #endif - else - break; - } - } + else + break; + } + } - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_unlock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_unlock(&qs->pthread.mutex); - pthread_cleanup_pop(0); + pthread_cleanup_pop(0); - return pulled; + return pulled; } -int villas::node::queue_signalled_pull_many(struct CQueueSignalled *qs, void *ptr[], size_t cnt) -{ - int pulled = 0; +int villas::node::queue_signalled_pull_many(struct CQueueSignalled *qs, + void *ptr[], size_t cnt) { + int pulled = 0; - // Make sure that qs->mutex is unlocked if this thread gets cancelled - pthread_cleanup_push(queue_signalled_cleanup, qs); + // Make sure that qs->mutex is unlocked if this thread gets cancelled + pthread_cleanup_push(queue_signalled_cleanup, qs); - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_lock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_lock(&qs->pthread.mutex); - while (!pulled) { - pulled = queue_pull_many(&qs->queue, ptr, cnt); - if (pulled < 0) - break; - else if (pulled == 0) { - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); - else if (qs->mode == QueueSignalledMode::POLLING) - continue; // Try again + while (!pulled) { + pulled = queue_pull_many(&qs->queue, ptr, cnt); + if (pulled < 0) + break; + else if (pulled == 0) { + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_cond_wait(&qs->pthread.ready, &qs->pthread.mutex); + else if (qs->mode == QueueSignalledMode::POLLING) + continue; // Try again #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t cntr; - ret = read(qs->eventfd, &cntr, sizeof(cntr)); - if (ret < 0) - break; - } + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t cntr; + ret = read(qs->eventfd, &cntr, sizeof(cntr)); + if (ret < 0) + break; + } #endif - else - break; - } - } + else + break; + } + } - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_unlock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_unlock(&qs->pthread.mutex); - pthread_cleanup_pop(0); + pthread_cleanup_pop(0); - return pulled; + return pulled; } -int villas::node::queue_signalled_close(struct CQueueSignalled *qs) -{ - int ret; +int villas::node::queue_signalled_close(struct CQueueSignalled *qs) { + int ret; - if (qs->mode == QueueSignalledMode::PTHREAD) - pthread_mutex_lock(&qs->pthread.mutex); + if (qs->mode == QueueSignalledMode::PTHREAD) + pthread_mutex_lock(&qs->pthread.mutex); - ret = queue_close(&qs->queue); + ret = queue_close(&qs->queue); - if (qs->mode == QueueSignalledMode::PTHREAD) { - pthread_cond_broadcast(&qs->pthread.ready); - pthread_mutex_unlock(&qs->pthread.mutex); - } - else if (qs->mode == QueueSignalledMode::POLLING) { - // Nothing todo - } + if (qs->mode == QueueSignalledMode::PTHREAD) { + pthread_cond_broadcast(&qs->pthread.ready); + pthread_mutex_unlock(&qs->pthread.mutex); + } else if (qs->mode == QueueSignalledMode::POLLING) { + // Nothing todo + } #ifdef HAS_EVENTFD - else if (qs->mode == QueueSignalledMode::EVENTFD) { - int ret; - uint64_t incr = 1; + else if (qs->mode == QueueSignalledMode::EVENTFD) { + int ret; + uint64_t incr = 1; - ret = write(qs->eventfd, &incr, sizeof(incr)); - if (ret < 0) - return ret; - } + ret = write(qs->eventfd, &incr, sizeof(incr)); + if (ret < 0) + return ret; + } #endif - else - return -1; + else + return -1; - return ret; + return ret; } -int villas::node::queue_signalled_fd(struct CQueueSignalled *qs) -{ - switch (qs->mode) { +int villas::node::queue_signalled_fd(struct CQueueSignalled *qs) { + switch (qs->mode) { #ifdef HAS_EVENTFD - case QueueSignalledMode::EVENTFD: - return qs->eventfd; + case QueueSignalledMode::EVENTFD: + return qs->eventfd; #endif - default: { } - } + default: { + } + } - return -1; + return -1; } diff --git a/lib/sample.cpp b/lib/sample.cpp index b4ebc1015..c8d81f9ba 100644 --- a/lib/sample.cpp +++ b/lib/sample.cpp @@ -5,319 +5,315 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include #include -#include +#include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int villas::node::sample_init(struct Sample *s) -{ - struct Pool *p = sample_pool(s); +int villas::node::sample_init(struct Sample *s) { + struct Pool *p = sample_pool(s); - s->length = 0; - s->capacity = (p->blocksz - sizeof(struct Sample)) / sizeof(s->data[0]); - s->refcnt = ATOMIC_VAR_INIT(1); + s->length = 0; + s->capacity = (p->blocksz - sizeof(struct Sample)) / sizeof(s->data[0]); + s->refcnt = ATOMIC_VAR_INIT(1); - new (&s->signals) std::shared_ptr; + new (&s->signals) std::shared_ptr; - return 0; + return 0; } -struct Sample * villas::node::sample_alloc(struct Pool *p) -{ - struct Sample *s; +struct Sample *villas::node::sample_alloc(struct Pool *p) { + struct Sample *s; - s = (struct Sample *) pool_get(p); - if (!s) - return nullptr; + s = (struct Sample *)pool_get(p); + if (!s) + return nullptr; - s->pool_off = (char *) p - (char *) s; + s->pool_off = (char *)p - (char *)s; - int ret = sample_init(s); - if (ret) { - pool_put(p, s); - return nullptr; - } + int ret = sample_init(s); + if (ret) { + pool_put(p, s); + return nullptr; + } - return s; + return s; } -struct Sample * villas::node::sample_alloc_mem(int capacity) -{ - size_t sz = SAMPLE_LENGTH(capacity); +struct Sample *villas::node::sample_alloc_mem(int capacity) { + size_t sz = SAMPLE_LENGTH(capacity); - auto *s = (struct Sample *) new char[sz]; - if (!s) - throw MemoryAllocationError(); + auto *s = (struct Sample *)new char[sz]; + if (!s) + throw MemoryAllocationError(); - memset((void *) s, 0, sz); + memset((void *)s, 0, sz); - s->pool_off = SAMPLE_NON_POOL; + s->pool_off = SAMPLE_NON_POOL; - s->length = 0; - s->capacity = capacity; - s->refcnt = ATOMIC_VAR_INIT(1); + s->length = 0; + s->capacity = capacity; + s->refcnt = ATOMIC_VAR_INIT(1); - return s; + return s; } -void villas::node::sample_free(struct Sample *s) -{ - struct Pool *p = sample_pool(s); +void villas::node::sample_free(struct Sample *s) { + struct Pool *p = sample_pool(s); - if (p) - pool_put(p, s); - else - delete[] (char *) s; + if (p) + pool_put(p, s); + else + delete[] (char *)s; } -int villas::node::sample_alloc_many(struct Pool *p, struct Sample *smps[], int cnt) -{ - int ret; +int villas::node::sample_alloc_many(struct Pool *p, struct Sample *smps[], + int cnt) { + int ret; - ret = pool_get_many(p, (void **) smps, cnt); - if (ret < 0) - return ret; + ret = pool_get_many(p, (void **)smps, cnt); + if (ret < 0) + return ret; - for (int i = 0; i < ret; i++) { - smps[i]->pool_off = (char *) p - (char *) smps[i]; + for (int i = 0; i < ret; i++) { + smps[i]->pool_off = (char *)p - (char *)smps[i]; - sample_init(smps[i]); - } + sample_init(smps[i]); + } - return ret; + return ret; } -void villas::node::sample_free_many(struct Sample *smps[], int cnt) -{ - for (int i = 0; i < cnt; i++) - sample_free(smps[i]); +void villas::node::sample_free_many(struct Sample *smps[], int cnt) { + for (int i = 0; i < cnt; i++) + sample_free(smps[i]); } -int villas::node::sample_decref_many(struct Sample * const smps[], int cnt) -{ - int released = 0; +int villas::node::sample_decref_many(struct Sample *const smps[], int cnt) { + int released = 0; - for (int i = 0; i < cnt; i++) { - if (sample_decref(smps[i]) == 0) - released++; - } + for (int i = 0; i < cnt; i++) { + if (sample_decref(smps[i]) == 0) + released++; + } - return released; + return released; } -int villas::node::sample_incref_many(struct Sample * const smps[], int cnt) -{ - for (int i = 0; i < cnt; i++) - sample_incref(smps[i]); +int villas::node::sample_incref_many(struct Sample *const smps[], int cnt) { + for (int i = 0; i < cnt; i++) + sample_incref(smps[i]); - return cnt; + return cnt; } -int villas::node::sample_incref(struct Sample *s) -{ - return atomic_fetch_add(&s->refcnt, 1) + 1; +int villas::node::sample_incref(struct Sample *s) { + return atomic_fetch_add(&s->refcnt, 1) + 1; } -int villas::node::sample_decref(struct Sample *s) -{ - int prev = atomic_fetch_sub(&s->refcnt, 1); +int villas::node::sample_decref(struct Sample *s) { + int prev = atomic_fetch_sub(&s->refcnt, 1); - // Did we had the last reference? - if (prev == 1) - sample_free(s); + // Did we had the last reference? + if (prev == 1) + sample_free(s); - return prev - 1; + return prev - 1; } -int villas::node::sample_copy(struct Sample *dst, const struct Sample *src) -{ - dst->length = MIN(src->length, dst->capacity); +int villas::node::sample_copy(struct Sample *dst, const struct Sample *src) { + dst->length = MIN(src->length, dst->capacity); - dst->sequence = src->sequence; - dst->flags = src->flags; - dst->ts = src->ts; - dst->signals = src->signals; + dst->sequence = src->sequence; + dst->flags = src->flags; + dst->ts = src->ts; + dst->signals = src->signals; - memcpy(&dst->data, &src->data, SAMPLE_DATA_LENGTH(dst->length)); + memcpy(&dst->data, &src->data, SAMPLE_DATA_LENGTH(dst->length)); - return 0; + return 0; } -struct Sample * villas::node::sample_clone(struct Sample *orig) -{ - struct Sample *clone; - struct Pool *pool; +struct Sample *villas::node::sample_clone(struct Sample *orig) { + struct Sample *clone; + struct Pool *pool; - pool = sample_pool(orig); - if (!pool) - return nullptr; + pool = sample_pool(orig); + if (!pool) + return nullptr; - clone = sample_alloc(pool); - if (!clone) - return nullptr; + clone = sample_alloc(pool); + if (!clone) + return nullptr; - sample_copy(clone, orig); + sample_copy(clone, orig); - return clone; + return clone; } -int villas::node::sample_clone_many(struct Sample *dsts[], const struct Sample * const srcs[], int cnt) -{ - int alloced, copied; - struct Pool *pool; +int villas::node::sample_clone_many(struct Sample *dsts[], + const struct Sample *const srcs[], + int cnt) { + int alloced, copied; + struct Pool *pool; - if (cnt <= 0) - return 0; + if (cnt <= 0) + return 0; - pool = sample_pool(srcs[0]); - if (!pool) - return 0; + pool = sample_pool(srcs[0]); + if (!pool) + return 0; - alloced = sample_alloc_many(pool, dsts, cnt); + alloced = sample_alloc_many(pool, dsts, cnt); - copied = sample_copy_many(dsts, srcs, alloced); + copied = sample_copy_many(dsts, srcs, alloced); - return copied; + return copied; } -int villas::node::sample_copy_many(struct Sample * const dsts[], const struct Sample * const srcs[], int cnt) -{ - for (int i = 0; i < cnt; i++) - sample_copy(dsts[i], srcs[i]); +int villas::node::sample_copy_many(struct Sample *const dsts[], + const struct Sample *const srcs[], int cnt) { + for (int i = 0; i < cnt; i++) + sample_copy(dsts[i], srcs[i]); - return cnt; + return cnt; } -int villas::node::sample_cmp(struct Sample *a, struct Sample *b, double epsilon, int flags) -{ - if ((a->flags & b->flags & flags) != flags) { - printf("flags: a=%#x, b=%#x, wanted=%#x\n", a->flags, b->flags, flags); - return -1; - } +int villas::node::sample_cmp(struct Sample *a, struct Sample *b, double epsilon, + int flags) { + if ((a->flags & b->flags & flags) != flags) { + printf("flags: a=%#x, b=%#x, wanted=%#x\n", a->flags, b->flags, flags); + return -1; + } - // Compare sequence no - if (flags & (int) SampleFlags::HAS_SEQUENCE) { - if (a->sequence != b->sequence) { - printf("sequence no: %" PRIu64 " != %" PRIu64 "\n", a->sequence, b->sequence); - return 2; - } - } + // Compare sequence no + if (flags & (int)SampleFlags::HAS_SEQUENCE) { + if (a->sequence != b->sequence) { + printf("sequence no: %" PRIu64 " != %" PRIu64 "\n", a->sequence, + b->sequence); + return 2; + } + } - // Compare timestamp - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { - if (time_delta(&a->ts.origin, &b->ts.origin) > epsilon) { - printf("ts.origin: %f != %f\n", time_to_double(&a->ts.origin), time_to_double(&b->ts.origin)); - return 3; - } - } + // Compare timestamp + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) { + if (time_delta(&a->ts.origin, &b->ts.origin) > epsilon) { + printf("ts.origin: %f != %f\n", time_to_double(&a->ts.origin), + time_to_double(&b->ts.origin)); + return 3; + } + } - // Compare data - if (flags & (int) SampleFlags::HAS_DATA) { - if (a->length != b->length) { - printf("length: %u != %u\n", a->length, b->length); - return 4; - } + // Compare data + if (flags & (int)SampleFlags::HAS_DATA) { + if (a->length != b->length) { + printf("length: %u != %u\n", a->length, b->length); + return 4; + } - for (unsigned i = 0; i < a->length; i++) { - // Compare format - if (sample_format(a, i) != sample_format(b, i)) - return 6; + for (unsigned i = 0; i < a->length; i++) { + // Compare format + if (sample_format(a, i) != sample_format(b, i)) + return 6; - switch (sample_format(a, i)) { - case SignalType::FLOAT: - if (fabs(a->data[i].f - b->data[i].f) > epsilon) { - printf("data[%u].f: %f != %f\n", i, a->data[i].f, b->data[i].f); - return 5; - } - break; + switch (sample_format(a, i)) { + case SignalType::FLOAT: + if (fabs(a->data[i].f - b->data[i].f) > epsilon) { + printf("data[%u].f: %f != %f\n", i, a->data[i].f, b->data[i].f); + return 5; + } + break; - case SignalType::INTEGER: - if (a->data[i].i != b->data[i].i) { - printf("data[%u].i: %" PRId64 " != %" PRId64 "\n", i, a->data[i].i, b->data[i].i); - return 5; - } - break; + case SignalType::INTEGER: + if (a->data[i].i != b->data[i].i) { + printf("data[%u].i: %" PRId64 " != %" PRId64 "\n", i, a->data[i].i, + b->data[i].i); + return 5; + } + break; - case SignalType::BOOLEAN: - if (a->data[i].b != b->data[i].b) { - printf("data[%u].b: %s != %s\n", i, a->data[i].b ? "true" : "false", b->data[i].b ? "true" : "false"); - return 5; - } - break; + case SignalType::BOOLEAN: + if (a->data[i].b != b->data[i].b) { + printf("data[%u].b: %s != %s\n", i, a->data[i].b ? "true" : "false", + b->data[i].b ? "true" : "false"); + return 5; + } + break; - case SignalType::COMPLEX: - if (std::abs(a->data[i].z - b->data[i].z) > epsilon) { - printf("data[%u].z: %f+%fi != %f+%fi\n", i, std::real(a->data[i].z), std::imag(a->data[i].z), std::real(b->data[i].z), std::imag(b->data[i].z)); - return 5; - } - break; + case SignalType::COMPLEX: + if (std::abs(a->data[i].z - b->data[i].z) > epsilon) { + printf("data[%u].z: %f+%fi != %f+%fi\n", i, std::real(a->data[i].z), + std::imag(a->data[i].z), std::real(b->data[i].z), + std::imag(b->data[i].z)); + return 5; + } + break; - default: { } - } - } - } + default: { + } + } + } + } - return 0; + return 0; } -enum SignalType villas::node::sample_format(const struct Sample *s, unsigned idx) -{ - auto sig = s->signals->getByIndex(idx); +enum SignalType villas::node::sample_format(const struct Sample *s, + unsigned idx) { + auto sig = s->signals->getByIndex(idx); - return sig ? sig->type : SignalType::INVALID; + return sig ? sig->type : SignalType::INVALID; } -void villas::node::sample_dump(Logger logger, struct Sample *s) -{ - logger->info("Sample: sequence={}, length={}, capacity={}, " - "flags={:#x}, #signals={}, " - "refcnt={}, pool_off={:#x}", - s->sequence, - s->length, - s->capacity, - s->flags, - s->signals ? s->signals->size() : -1, - atomic_load(&s->refcnt), - s->pool_off); +void villas::node::sample_dump(Logger logger, struct Sample *s) { + logger->info("Sample: sequence={}, length={}, capacity={}, " + "flags={:#x}, #signals={}, " + "refcnt={}, pool_off={:#x}", + s->sequence, s->length, s->capacity, s->flags, + s->signals ? s->signals->size() : -1, atomic_load(&s->refcnt), + s->pool_off); - if (s->flags & (int) SampleFlags::HAS_TS_ORIGIN) - logger->info(" ts.origin={}.{:09d}", s->ts.origin.tv_sec, s->ts.origin.tv_nsec); + if (s->flags & (int)SampleFlags::HAS_TS_ORIGIN) + logger->info(" ts.origin={}.{:09d}", s->ts.origin.tv_sec, + s->ts.origin.tv_nsec); - if (s->flags & (int) SampleFlags::HAS_TS_RECEIVED) - logger->info(" ts.received={}.{:09d}", s->ts.received.tv_sec, s->ts.received.tv_nsec); + if (s->flags & (int)SampleFlags::HAS_TS_RECEIVED) + logger->info(" ts.received={}.{:09d}", s->ts.received.tv_sec, + s->ts.received.tv_nsec); - if (s->signals) { - logger->info(" Signals:"); - s->signals->dump(logger, s->data, s->length); - } + if (s->signals) { + logger->info(" Signals:"); + s->signals->dump(logger, s->data, s->length); + } } -void villas::node::sample_data_insert(struct Sample *smp, const union SignalData *src, size_t offset, size_t len) -{ - memmove(&smp->data[offset + len], &smp->data[offset], sizeof(smp->data[0]) * (smp->length - offset)); - memcpy(&smp->data[offset], src, sizeof(smp->data[0]) * len); +void villas::node::sample_data_insert(struct Sample *smp, + const union SignalData *src, + size_t offset, size_t len) { + memmove(&smp->data[offset + len], &smp->data[offset], + sizeof(smp->data[0]) * (smp->length - offset)); + memcpy(&smp->data[offset], src, sizeof(smp->data[0]) * len); - smp->length += len; + smp->length += len; } -void villas::node::sample_data_remove(struct Sample *smp, size_t offset, size_t len) -{ - size_t sz = sizeof(smp->data[0]) * len; +void villas::node::sample_data_remove(struct Sample *smp, size_t offset, + size_t len) { + size_t sz = sizeof(smp->data[0]) * len; - memmove(&smp->data[offset], &smp->data[offset + len], sz); + memmove(&smp->data[offset], &smp->data[offset + len], sz); - smp->length -= len; + smp->length -= len; } diff --git a/lib/shmem.cpp b/lib/shmem.cpp index 8ca3a1223..9ab914b6b 100644 --- a/lib/shmem.cpp +++ b/lib/shmem.cpp @@ -13,190 +13,196 @@ #include #include -#include #include #include +#include using namespace villas; using namespace villas::node; -size_t villas::node::shmem_total_size(int queuelen, int samplelen) -{ - // We have the constant const of the memory_type header - return sizeof(struct memory::Type) - // and the shared struct itself - + sizeof(struct ShmemShared) - // the size of the actual queue and the queue for the pool - + queuelen * (2 * sizeof(struct CQueue_cell)) - // the size of the pool - + queuelen * kernel::getCachelineSize() * CEIL(SAMPLE_LENGTH(samplelen), kernel::getCachelineSize()) - // a memblock for each allocation (1 shmem_shared, 2 queues, 1 pool) - + 4 * sizeof(struct memory::Block) - // and some extra buffer for alignment - + 1024; +size_t villas::node::shmem_total_size(int queuelen, int samplelen) { + // We have the constant const of the memory_type header + return sizeof(struct memory::Type) + // and the shared struct itself + + sizeof(struct ShmemShared) + // the size of the actual queue and the queue for the pool + + queuelen * (2 * sizeof(struct CQueue_cell)) + // the size of the pool + + queuelen * kernel::getCachelineSize() * + CEIL(SAMPLE_LENGTH(samplelen), kernel::getCachelineSize()) + // a memblock for each allocation (1 shmem_shared, 2 queues, 1 pool) + + 4 * sizeof(struct memory::Block) + // and some extra buffer for alignment + + 1024; } -int villas::node::shmem_int_open(const char *wname, const char* rname, struct ShmemInterface *shm, struct ShmemConfig *conf) -{ - char *cptr; - int fd, ret; - size_t len; - void *base; - struct memory::Type *manager; - struct ShmemShared *shared; - struct stat stat_buf; - sem_t *sem_own, *sem_other; +int villas::node::shmem_int_open(const char *wname, const char *rname, + struct ShmemInterface *shm, + struct ShmemConfig *conf) { + char *cptr; + int fd, ret; + size_t len; + void *base; + struct memory::Type *manager; + struct ShmemShared *shared; + struct stat stat_buf; + sem_t *sem_own, *sem_other; - // Ensure both semaphores exist - sem_own = sem_open(wname, O_CREAT, 0600, 0); - if (sem_own == SEM_FAILED) - return -1; + // Ensure both semaphores exist + sem_own = sem_open(wname, O_CREAT, 0600, 0); + if (sem_own == SEM_FAILED) + return -1; - sem_other = sem_open(rname, O_CREAT, 0600, 0); - if (sem_other == SEM_FAILED) - return -2; + sem_other = sem_open(rname, O_CREAT, 0600, 0); + if (sem_other == SEM_FAILED) + return -2; - // Open and initialize the shared region for the output queue -retry: fd = shm_open(wname, O_RDWR|O_CREAT|O_EXCL, 0600); - if (fd < 0) { - if (errno == EEXIST) { - ret = shm_unlink(wname); - if (ret) - return -12; + // Open and initialize the shared region for the output queue +retry: + fd = shm_open(wname, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd < 0) { + if (errno == EEXIST) { + ret = shm_unlink(wname); + if (ret) + return -12; - goto retry; - } + goto retry; + } - return -3; - } + return -3; + } - len = shmem_total_size(conf->queuelen, conf->samplelen); - if (ftruncate(fd, len) < 0) - return -1; + len = shmem_total_size(conf->queuelen, conf->samplelen); + if (ftruncate(fd, len) < 0) + return -1; - base = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (base == MAP_FAILED) - return -4; + base = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (base == MAP_FAILED) + return -4; - close(fd); + close(fd); - manager = memory::managed(base, len); - shared = (struct ShmemShared *) memory::alloc(sizeof(struct ShmemShared), manager); - if (!shared) { - errno = ENOMEM; - return -5; - } + manager = memory::managed(base, len); + shared = + (struct ShmemShared *)memory::alloc(sizeof(struct ShmemShared), manager); + if (!shared) { + errno = ENOMEM; + return -5; + } - shared->polling = conf->polling; + shared->polling = conf->polling; - int flags = (int) QueueSignalledFlags::PROCESS_SHARED; - enum QueueSignalledMode mode = conf->polling - ? QueueSignalledMode::POLLING - : QueueSignalledMode::PTHREAD; + int flags = (int)QueueSignalledFlags::PROCESS_SHARED; + enum QueueSignalledMode mode = + conf->polling ? QueueSignalledMode::POLLING : QueueSignalledMode::PTHREAD; - ret = queue_signalled_init(&shared->queue, conf->queuelen, manager, mode, flags); - if (ret) { - errno = ENOMEM; - return -6; - } + ret = queue_signalled_init(&shared->queue, conf->queuelen, manager, mode, + flags); + if (ret) { + errno = ENOMEM; + return -6; + } - ret = pool_init(&shared->pool, conf->queuelen, SAMPLE_LENGTH(conf->samplelen), manager); - if (ret) { - errno = ENOMEM; - return -7; - } + ret = pool_init(&shared->pool, conf->queuelen, SAMPLE_LENGTH(conf->samplelen), + manager); + if (ret) { + errno = ENOMEM; + return -7; + } - shm->write.base = base; - shm->write.name = wname; - shm->write.len = len; - shm->write.shared = shared; + shm->write.base = base; + shm->write.name = wname; + shm->write.len = len; + shm->write.shared = shared; - /* Post own semaphore and wait on the other one, so both processes know that + /* Post own semaphore and wait on the other one, so both processes know that * both regions are initialized */ - sem_post(sem_own); - sem_wait(sem_other); + sem_post(sem_own); + sem_wait(sem_other); - // Open and map the other region - fd = shm_open(rname, O_RDWR, 0); - if (fd < 0) - return -8; + // Open and map the other region + fd = shm_open(rname, O_RDWR, 0); + if (fd < 0) + return -8; - if (fstat(fd, &stat_buf) < 0) - return -9; + if (fstat(fd, &stat_buf) < 0) + return -9; - len = stat_buf.st_size; - base = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + len = stat_buf.st_size; + base = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (base == MAP_FAILED) - return -10; + if (base == MAP_FAILED) + return -10; - cptr = (char *) base + sizeof(struct memory::Type) + sizeof(struct memory::Block); - shared = (struct ShmemShared *) cptr; - shm->read.base = base; - shm->read.name = rname; - shm->read.len = len; - shm->read.shared = shared; + cptr = + (char *)base + sizeof(struct memory::Type) + sizeof(struct memory::Block); + shared = (struct ShmemShared *)cptr; + shm->read.base = base; + shm->read.name = rname; + shm->read.len = len; + shm->read.shared = shared; - shm->readers = 0; - shm->writers = 0; - shm->closed = 0; + shm->readers = 0; + shm->writers = 0; + shm->closed = 0; - // Unlink the semaphores; we don't need them anymore - sem_unlink(wname); + // Unlink the semaphores; we don't need them anymore + sem_unlink(wname); - return 0; + return 0; } -int villas::node::shmem_int_close(struct ShmemInterface *shm) -{ - int ret; +int villas::node::shmem_int_close(struct ShmemInterface *shm) { + int ret; - atomic_store(&shm->closed, 1); + atomic_store(&shm->closed, 1); - ret = queue_signalled_close(&shm->write.shared->queue); - if (ret) - return ret; + ret = queue_signalled_close(&shm->write.shared->queue); + if (ret) + return ret; - shm_unlink(shm->write.name); + shm_unlink(shm->write.name); - if (atomic_load(&shm->readers) == 0) - munmap(shm->read.base, shm->read.len); + if (atomic_load(&shm->readers) == 0) + munmap(shm->read.base, shm->read.len); - if (atomic_load(&shm->writers) == 0) - munmap(shm->write.base, shm->write.len); + if (atomic_load(&shm->writers) == 0) + munmap(shm->write.base, shm->write.len); - return 0; + return 0; } -int villas::node::shmem_int_read(struct ShmemInterface *shm, struct Sample * const smps[], unsigned cnt) -{ - int ret; +int villas::node::shmem_int_read(struct ShmemInterface *shm, + struct Sample *const smps[], unsigned cnt) { + int ret; - atomic_fetch_add(&shm->readers, 1); + atomic_fetch_add(&shm->readers, 1); - ret = queue_signalled_pull_many(&shm->read.shared->queue, (void **) smps, cnt); + ret = queue_signalled_pull_many(&shm->read.shared->queue, (void **)smps, cnt); - if (atomic_fetch_sub(&shm->readers, 1) == 1 && atomic_load(&shm->closed) == 1) - munmap(shm->read.base, shm->read.len); + if (atomic_fetch_sub(&shm->readers, 1) == 1 && atomic_load(&shm->closed) == 1) + munmap(shm->read.base, shm->read.len); - return ret; + return ret; } -int villas::node::shmem_int_write(struct ShmemInterface *shm, const struct Sample * const smps[], unsigned cnt) -{ - int ret; +int villas::node::shmem_int_write(struct ShmemInterface *shm, + const struct Sample *const smps[], + unsigned cnt) { + int ret; - atomic_fetch_add(&shm->writers, 1); + atomic_fetch_add(&shm->writers, 1); - ret = queue_signalled_push_many(&shm->write.shared->queue, (void **) smps, cnt); + ret = + queue_signalled_push_many(&shm->write.shared->queue, (void **)smps, cnt); - if (atomic_fetch_sub(&shm->writers, 1) == 1 && atomic_load(&shm->closed) == 1) - munmap(shm->write.base, shm->write.len); + if (atomic_fetch_sub(&shm->writers, 1) == 1 && atomic_load(&shm->closed) == 1) + munmap(shm->write.base, shm->write.len); - return ret; + return ret; } -int villas::node::shmem_int_alloc(struct ShmemInterface *shm, struct Sample *smps[], unsigned cnt) -{ - return sample_alloc_many(&shm->write.shared->pool, smps, cnt); +int villas::node::shmem_int_alloc(struct ShmemInterface *shm, + struct Sample *smps[], unsigned cnt) { + return sample_alloc_many(&shm->write.shared->pool, smps, cnt); } diff --git a/lib/signal.cpp b/lib/signal.cpp index 65c0a3c42..58a81bfc9 100644 --- a/lib/signal.cpp +++ b/lib/signal.cpp @@ -5,137 +5,122 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include -#include #include +#include using namespace villas; using namespace villas::node; using namespace villas::utils; -Signal::Signal(const std::string &n, const std::string &u, enum SignalType t) : - name(n), - unit(u), - init(SignalData::nan()), - type(t) -{ } +Signal::Signal(const std::string &n, const std::string &u, enum SignalType t) + : name(n), unit(u), init(SignalData::nan()), type(t) {} -int Signal::parse(json_t *json) -{ - int ret; - json_error_t err; - json_t *json_init = nullptr; - const char *name_str = nullptr; - const char *unit_str = nullptr; - const char *type_str = "float"; +int Signal::parse(json_t *json) { + int ret; + json_error_t err; + json_t *json_init = nullptr; + const char *name_str = nullptr; + const char *unit_str = nullptr; + const char *type_str = "float"; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: o }", - "name", &name_str, - "unit", &unit_str, - "type", &type_str, - "init", &json_init - ); - if (ret) - return -1; + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: o }", "name", + &name_str, "unit", &unit_str, "type", &type_str, "init", + &json_init); + if (ret) + return -1; - if (name_str) - name = name_str; + if (name_str) + name = name_str; - if (unit_str) - unit = unit_str; + if (unit_str) + unit = unit_str; - if (type_str) { - type = signalTypeFromString(type_str); - if (type == SignalType::INVALID) - return -1; - } + if (type_str) { + type = signalTypeFromString(type_str); + if (type == SignalType::INVALID) + return -1; + } - if (json_init) { - ret = init.parseJson(type, json_init); - if (ret) - return ret; - } - else - init.set(type, 0); + if (json_init) { + ret = init.parseJson(type, json_init); + if (ret) + return ret; + } else + init.set(type, 0); - return 0; + return 0; } -json_t * Signal::toJson() const -{ - json_t *json_sig = json_pack("{ s: s }", - "type", signalTypeToString(type).c_str() - ); +json_t *Signal::toJson() const { + json_t *json_sig = + json_pack("{ s: s }", "type", signalTypeToString(type).c_str()); - auto *json_init = init.toJson(type); - if (json_init) - json_object_set_new(json_sig, "init", json_init); + auto *json_init = init.toJson(type); + if (json_init) + json_object_set_new(json_sig, "init", json_init); - if (!name.empty()) - json_object_set_new(json_sig, "name", json_string(name.c_str())); + if (!name.empty()) + json_object_set_new(json_sig, "name", json_string(name.c_str())); - if (!unit.empty()) - json_object_set_new(json_sig, "unit", json_string(unit.c_str())); + if (!unit.empty()) + json_object_set_new(json_sig, "unit", json_string(unit.c_str())); - return json_sig; + return json_sig; } -std::string Signal::toString(const union SignalData *d) const -{ - std::stringstream ss; +std::string Signal::toString(const union SignalData *d) const { + std::stringstream ss; - if (!name.empty()) - ss << " " << name; + if (!name.empty()) + ss << " " << name; - if (!unit.empty()) - ss << " [" << unit << "]"; + if (!unit.empty()) + ss << " [" << unit << "]"; - ss << "(" << signalTypeToString(type) << ")"; + ss << "(" << signalTypeToString(type) << ")"; - if (d) - ss << " = " << d->toString(type); + if (d) + ss << " = " << d->toString(type); - return ss.str(); + return ss.str(); } /* Check if two signal names are numbered ascendingly * * E.g. signal3 -> signal4 */ -static -bool isNextName(const std::string &a, const std::string &b) -{ - // Find common prefix - std::string::const_iterator ia, ib; - for (ia = a.cbegin(), ib = b.cbegin(); - ia != b.cend() && ib != b.cend() && *ia == *ib; - ++ia, ++ib); +static bool isNextName(const std::string &a, const std::string &b) { + // Find common prefix + std::string::const_iterator ia, ib; + for (ia = a.cbegin(), ib = b.cbegin(); + ia != b.cend() && ib != b.cend() && *ia == *ib; ++ia, ++ib) + ; - // Suffixes - auto sa = std::string(ia, a.cend()); - auto sb = std::string(ib, b.cend()); + // Suffixes + auto sa = std::string(ia, a.cend()); + auto sb = std::string(ib, b.cend()); - try { - size_t ea, eb; - auto na = std::stoul(sa, &ea, 10); - auto nb = std::stoul(sb, &eb, 10); + try { + size_t ea, eb; + auto na = std::stoul(sa, &ea, 10); + auto nb = std::stoul(sb, &eb, 10); - return na + 1 == nb; - } catch (std::exception &) { - return false; - } + return na + 1 == nb; + } catch (std::exception &) { + return false; + } } -bool Signal::isNext(const Signal &sig) -{ - if (type != sig.type) - return false; +bool Signal::isNext(const Signal &sig) { + if (type != sig.type) + return false; - if (!unit.empty() && !sig.unit.empty() && unit != sig.unit) - return false; + if (!unit.empty() && !sig.unit.empty() && unit != sig.unit) + return false; - return isNextName(name, sig.name); + return isNextName(name, sig.name); } diff --git a/lib/signal_data.cpp b/lib/signal_data.cpp index 5d7d09575..6a40c4b28 100644 --- a/lib/signal_data.cpp +++ b/lib/signal_data.cpp @@ -5,280 +5,271 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include -#include #include +#include using namespace villas::node; -void SignalData::set(enum SignalType type, double val) -{ - switch (type) { - case SignalType::BOOLEAN: - this->b = val; - break; +void SignalData::set(enum SignalType type, double val) { + switch (type) { + case SignalType::BOOLEAN: + this->b = val; + break; - case SignalType::FLOAT: - this->f = val; - break; + case SignalType::FLOAT: + this->f = val; + break; - case SignalType::INTEGER: - this->i = val; - break; + case SignalType::INTEGER: + this->i = val; + break; - case SignalType::COMPLEX: - this->z = val; - break; + case SignalType::COMPLEX: + this->z = val; + break; - case SignalType::INVALID: - *this = nan(); - break; - } + case SignalType::INVALID: + *this = nan(); + break; + } } -SignalData SignalData::cast(enum SignalType from, enum SignalType to) const -{ - SignalData n = *this; +SignalData SignalData::cast(enum SignalType from, enum SignalType to) const { + SignalData n = *this; - switch (to) { - case SignalType::BOOLEAN: - switch(from) { - case SignalType::INTEGER: - n.b = this->i; - break; + switch (to) { + case SignalType::BOOLEAN: + switch (from) { + case SignalType::INTEGER: + n.b = this->i; + break; - case SignalType::FLOAT: - n.b = this->f; - break; + case SignalType::FLOAT: + n.b = this->f; + break; - case SignalType::COMPLEX: - n.b = std::real(this->z); - break; + case SignalType::COMPLEX: + n.b = std::real(this->z); + break; - case SignalType::INVALID: - case SignalType::BOOLEAN: - break; - } - break; + case SignalType::INVALID: + case SignalType::BOOLEAN: + break; + } + break; - case SignalType::INTEGER: - switch(from) { - case SignalType::BOOLEAN: - n.i = this->b; - break; + case SignalType::INTEGER: + switch (from) { + case SignalType::BOOLEAN: + n.i = this->b; + break; - case SignalType::FLOAT: - n.i = this->f; - break; + case SignalType::FLOAT: + n.i = this->f; + break; - case SignalType::COMPLEX: - n.i = std::real(this->z); - break; + case SignalType::COMPLEX: + n.i = std::real(this->z); + break; - case SignalType::INVALID: - case SignalType::INTEGER: - break; - } - break; + case SignalType::INVALID: + case SignalType::INTEGER: + break; + } + break; - case SignalType::FLOAT: - switch(from) { - case SignalType::BOOLEAN: - n.f = this->b; - break; + case SignalType::FLOAT: + switch (from) { + case SignalType::BOOLEAN: + n.f = this->b; + break; - case SignalType::INTEGER: - n.f = this->i; - break; + case SignalType::INTEGER: + n.f = this->i; + break; - case SignalType::COMPLEX: - n.f = std::real(this->z); - break; + case SignalType::COMPLEX: + n.f = std::real(this->z); + break; - case SignalType::INVALID: - case SignalType::FLOAT: - break; - } - break; + case SignalType::INVALID: + case SignalType::FLOAT: + break; + } + break; - case SignalType::COMPLEX: - switch(from) { - case SignalType::BOOLEAN: - n.z = this->b; - break; + case SignalType::COMPLEX: + switch (from) { + case SignalType::BOOLEAN: + n.z = this->b; + break; - case SignalType::INTEGER: - n.z = this->i; - break; + case SignalType::INTEGER: + n.z = this->i; + break; - case SignalType::FLOAT: - n.z = this->f; - break; + case SignalType::FLOAT: + n.z = this->f; + break; - case SignalType::INVALID: - case SignalType::COMPLEX: - break; - } - break; + case SignalType::INVALID: + case SignalType::COMPLEX: + break; + } + break; - default: { } - } + default: { + } + } - return n; + return n; } -int SignalData::parseString(enum SignalType type, const char *ptr, char **end) -{ - switch (type) { - case SignalType::FLOAT: - this->f = strtod(ptr, end); - break; +int SignalData::parseString(enum SignalType type, const char *ptr, char **end) { + switch (type) { + case SignalType::FLOAT: + this->f = strtod(ptr, end); + break; - case SignalType::INTEGER: - this->i = strtol(ptr, end, 10); - break; + case SignalType::INTEGER: + this->i = strtol(ptr, end, 10); + break; - case SignalType::BOOLEAN: - this->b = strtol(ptr, end, 10); - break; + case SignalType::BOOLEAN: + this->b = strtol(ptr, end, 10); + break; - case SignalType::COMPLEX: { - float real, imag = 0; + case SignalType::COMPLEX: { + float real, imag = 0; - real = strtod(ptr, end); - if (*end == ptr) - return -1; + real = strtod(ptr, end); + if (*end == ptr) + return -1; - ptr = *end; + ptr = *end; - if (*ptr == 'i' || *ptr == 'j') { - imag = real; - real = 0; + if (*ptr == 'i' || *ptr == 'j') { + imag = real; + real = 0; - (*end)++; - } - else if (*ptr == '-' || *ptr == '+') { - imag = strtod(ptr, end); - if (*end == ptr) - return -1; + (*end)++; + } else if (*ptr == '-' || *ptr == '+') { + imag = strtod(ptr, end); + if (*end == ptr) + return -1; - if (**end != 'i' && **end != 'j') - return -1; + if (**end != 'i' && **end != 'j') + return -1; - (*end)++; - } + (*end)++; + } - this->z = std::complex(real, imag); - break; - } + this->z = std::complex(real, imag); + break; + } - case SignalType::INVALID: - return -1; - } + case SignalType::INVALID: + return -1; + } - return 0; + return 0; } -int SignalData::parseJson(enum SignalType type, json_t *json) -{ - int ret; +int SignalData::parseJson(enum SignalType type, json_t *json) { + int ret; - switch (type) { - case SignalType::FLOAT: - if (!json_is_number(json)) - return -1; + switch (type) { + case SignalType::FLOAT: + if (!json_is_number(json)) + return -1; - this->f = json_number_value(json); - break; + this->f = json_number_value(json); + break; - case SignalType::INTEGER: - if (!json_is_integer(json)) - return -1; + case SignalType::INTEGER: + if (!json_is_integer(json)) + return -1; - this->i = json_integer_value(json); - break; + this->i = json_integer_value(json); + break; - case SignalType::BOOLEAN: - if (!json_is_boolean(json)) - return -1; + case SignalType::BOOLEAN: + if (!json_is_boolean(json)) + return -1; - this->b = json_boolean_value(json); - break; + this->b = json_boolean_value(json); + break; - case SignalType::COMPLEX: { - double real, imag; + case SignalType::COMPLEX: { + double real, imag; - json_error_t err; - ret = json_unpack_ex(json, &err, 0, "{ s: F, s: F }", - "real", &real, - "imag", &imag - ); - if (ret) - return -1; + json_error_t err; + ret = json_unpack_ex(json, &err, 0, "{ s: F, s: F }", "real", &real, "imag", + &imag); + if (ret) + return -1; - this->z = std::complex(real, imag); - break; - } + this->z = std::complex(real, imag); + break; + } - case SignalType::INVALID: - return -2; - } + case SignalType::INVALID: + return -2; + } - return 0; + return 0; } -json_t * SignalData::toJson(enum SignalType type) const -{ - switch (type) { - case SignalType::INTEGER: - return json_integer(this->i); +json_t *SignalData::toJson(enum SignalType type) const { + switch (type) { + case SignalType::INTEGER: + return json_integer(this->i); - case SignalType::FLOAT: - return json_real(this->f); + case SignalType::FLOAT: + return json_real(this->f); - case SignalType::BOOLEAN: - return json_boolean(this->b); + case SignalType::BOOLEAN: + return json_boolean(this->b); - case SignalType::COMPLEX: - return json_pack("{ s: f, s: f }", - "real", std::real(this->z), - "imag", std::imag(this->z) - ); + case SignalType::COMPLEX: + return json_pack("{ s: f, s: f }", "real", std::real(this->z), "imag", + std::imag(this->z)); - case SignalType::INVALID: - return nullptr; - } + case SignalType::INVALID: + return nullptr; + } - return nullptr; + return nullptr; } -int SignalData::printString(enum SignalType type, char *buf, size_t len, int precision) const -{ - switch (type) { - case SignalType::FLOAT: - return snprintf(buf, len, "%.*f", precision, this->f); +int SignalData::printString(enum SignalType type, char *buf, size_t len, + int precision) const { + switch (type) { + case SignalType::FLOAT: + return snprintf(buf, len, "%.*f", precision, this->f); - case SignalType::INTEGER: - return snprintf(buf, len, "%" PRIi64, this->i); + case SignalType::INTEGER: + return snprintf(buf, len, "%" PRIi64, this->i); - case SignalType::BOOLEAN: - return snprintf(buf, len, "%u", this->b); + case SignalType::BOOLEAN: + return snprintf(buf, len, "%u", this->b); - case SignalType::COMPLEX: - return snprintf(buf, len, "%.*f%+.*fi", precision, std::real(this->z), precision, std::imag(this->z)); + case SignalType::COMPLEX: + return snprintf(buf, len, "%.*f%+.*fi", precision, std::real(this->z), + precision, std::imag(this->z)); - default: - return snprintf(buf, len, ""); - } + default: + return snprintf(buf, len, ""); + } } -std::string SignalData::toString(enum SignalType type, int precission) const -{ - char buf[128]; +std::string SignalData::toString(enum SignalType type, int precission) const { + char buf[128]; - printString(type, buf, sizeof(buf), precission); + printString(type, buf, sizeof(buf), precission); - return buf; + return buf; } diff --git a/lib/signal_list.cpp b/lib/signal_list.cpp index 18717d0d4..dd1359973 100644 --- a/lib/signal_list.cpp +++ b/lib/signal_list.cpp @@ -5,158 +5,149 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include -#include #include #include -#include +#include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; -int SignalList::parse(json_t *json) -{ - int ret; +int SignalList::parse(json_t *json) { + int ret; - if (!json_is_array(json)) - return -1; + if (!json_is_array(json)) + return -1; - size_t i; - json_t *json_signal; - json_array_foreach(json, i, json_signal) { - auto sig = std::make_shared(); - if (!sig) - throw MemoryAllocationError(); + size_t i; + json_t *json_signal; + json_array_foreach(json, i, json_signal) { + auto sig = std::make_shared(); + if (!sig) + throw MemoryAllocationError(); - ret = sig->parse(json_signal); - if (ret) - return ret; + ret = sig->parse(json_signal); + if (ret) + return ret; - push_back(sig); - } + push_back(sig); + } - return 0; + return 0; } -SignalList::SignalList(unsigned len, enum SignalType typ) -{ - char name[32]; +SignalList::SignalList(unsigned len, enum SignalType typ) { + char name[32]; - for (unsigned i = 0; i < len; i++) { - snprintf(name, sizeof(name), "signal%u", i); + for (unsigned i = 0; i < len; i++) { + snprintf(name, sizeof(name), "signal%u", i); - auto sig = std::make_shared(name, "", typ); - if (!sig) - throw RuntimeError("Failed to create signal list"); + auto sig = std::make_shared(name, "", typ); + if (!sig) + throw RuntimeError("Failed to create signal list"); - push_back(sig); - } + push_back(sig); + } } -SignalList::SignalList(const char *dt) -{ - int len, i = 0; - char name[32], *e; - enum SignalType typ; +SignalList::SignalList(const char *dt) { + int len, i = 0; + char name[32], *e; + enum SignalType typ; - for (const char *t = dt; *t; t = e + 1) { - len = strtoul(t, &e, 10); - if (t == e) - len = 1; + for (const char *t = dt; *t; t = e + 1) { + len = strtoul(t, &e, 10); + if (t == e) + len = 1; - typ = signalTypeFromFormatString(*e); - if (typ == SignalType::INVALID) - throw RuntimeError("Failed to create signal list"); + typ = signalTypeFromFormatString(*e); + if (typ == SignalType::INVALID) + throw RuntimeError("Failed to create signal list"); - for (int j = 0; j < len; j++) { - snprintf(name, sizeof(name), "signal%d", i++); + for (int j = 0; j < len; j++) { + snprintf(name, sizeof(name), "signal%d", i++); - auto sig = std::make_shared(name, "", typ); - if (!sig) - throw RuntimeError("Failed to create signal list"); + auto sig = std::make_shared(name, "", typ); + if (!sig) + throw RuntimeError("Failed to create signal list"); - push_back(sig); - } - } + push_back(sig); + } + } } -void SignalList::dump(Logger logger, const union SignalData *data, unsigned len) const -{ - const char *pfx; - bool abbrev = false; +void SignalList::dump(Logger logger, const union SignalData *data, + unsigned len) const { + const char *pfx; + bool abbrev = false; - Signal::Ptr prevSig; - unsigned i = 0; - for (auto sig : *this) { - // Check if this is a sequence of similar signals which can be abbreviated - if (i >= 1 && i < size() - 1) { - if (prevSig->isNext(*sig)) { - abbrev = true; - goto skip; - } - } + Signal::Ptr prevSig; + unsigned i = 0; + for (auto sig : *this) { + // Check if this is a sequence of similar signals which can be abbreviated + if (i >= 1 && i < size() - 1) { + if (prevSig->isNext(*sig)) { + abbrev = true; + goto skip; + } + } - if (abbrev) { - pfx = "..."; - abbrev = false; - } - else - pfx = " "; + if (abbrev) { + pfx = "..."; + abbrev = false; + } else + pfx = " "; - logger->info(" {}{:>3}: {}", pfx, i, sig->toString(i < len ? &data[i] : nullptr)); + logger->info(" {}{:>3}: {}", pfx, i, + sig->toString(i < len ? &data[i] : nullptr)); -skip: prevSig = sig; - i++; - } + skip: + prevSig = sig; + i++; + } } -json_t * SignalList::toJson() const -{ - json_t *json_signals = json_array(); +json_t *SignalList::toJson() const { + json_t *json_signals = json_array(); - for (const auto &sig : *this) - json_array_append_new(json_signals, sig->toJson()); + for (const auto &sig : *this) + json_array_append_new(json_signals, sig->toJson()); - return json_signals; + return json_signals; } -Signal::Ptr SignalList::getByIndex(unsigned idx) -{ - return this->at(idx); +Signal::Ptr SignalList::getByIndex(unsigned idx) { return this->at(idx); } + +int SignalList::getIndexByName(const std::string &name) { + unsigned i = 0; + for (auto s : *this) { + if (name == s->name) + return i; + + i++; + } + + return -1; } -int SignalList::getIndexByName(const std::string &name) -{ - unsigned i = 0; - for (auto s : *this) { - if (name == s->name) - return i; +Signal::Ptr SignalList::getByName(const std::string &name) { + for (auto s : *this) { + if (name == s->name) + return s; + } - i++; - } - - return -1; + return Signal::Ptr(); } -Signal::Ptr SignalList::getByName(const std::string &name) -{ - for (auto s : *this) { - if (name == s->name) - return s; - } +SignalList::Ptr SignalList::clone() { + auto l = std::make_shared(); - return Signal::Ptr(); -} - -SignalList::Ptr SignalList::clone() -{ - auto l = std::make_shared(); - - for (auto s : *this) - l->push_back(s); - - return l; + for (auto s : *this) + l->push_back(s); + + return l; } diff --git a/lib/signal_type.cpp b/lib/signal_type.cpp index 40c770822..a42410935 100644 --- a/lib/signal_type.cpp +++ b/lib/signal_type.cpp @@ -11,75 +11,71 @@ using namespace villas::node; -enum SignalType villas::node::signalTypeFromString(const std::string &str) -{ - if (str == "boolean") - return SignalType::BOOLEAN; - else if (str == "complex") - return SignalType::COMPLEX; - else if (str == "float") - return SignalType::FLOAT; - else if (str == "integer") - return SignalType::INTEGER; - else - return SignalType::INVALID; +enum SignalType villas::node::signalTypeFromString(const std::string &str) { + if (str == "boolean") + return SignalType::BOOLEAN; + else if (str == "complex") + return SignalType::COMPLEX; + else if (str == "float") + return SignalType::FLOAT; + else if (str == "integer") + return SignalType::INTEGER; + else + return SignalType::INVALID; } -enum SignalType villas::node::signalTypeFromFormatString(char c) -{ - switch (c) { - case 'f': - return SignalType::FLOAT; +enum SignalType villas::node::signalTypeFromFormatString(char c) { + switch (c) { + case 'f': + return SignalType::FLOAT; - case 'i': - return SignalType::INTEGER; + case 'i': + return SignalType::INTEGER; - case 'c': - return SignalType::COMPLEX; + case 'c': + return SignalType::COMPLEX; - case 'b': - return SignalType::BOOLEAN; + case 'b': + return SignalType::BOOLEAN; - default: - return SignalType::INVALID; - } + default: + return SignalType::INVALID; + } } -std::string villas::node::signalTypeToString(enum SignalType fmt) -{ - switch (fmt) { - case SignalType::BOOLEAN: - return "boolean"; +std::string villas::node::signalTypeToString(enum SignalType fmt) { + switch (fmt) { + case SignalType::BOOLEAN: + return "boolean"; - case SignalType::COMPLEX: - return "complex"; + case SignalType::COMPLEX: + return "complex"; - case SignalType::FLOAT: - return "float"; + case SignalType::FLOAT: + return "float"; - case SignalType::INTEGER: - return "integer"; + case SignalType::INTEGER: + return "integer"; - case SignalType::INVALID: - return "invalid"; - } + case SignalType::INVALID: + return "invalid"; + } - return nullptr; + return nullptr; } -enum SignalType villas::node::signalTypeDetect(const std::string &val) -{ - int len; +enum SignalType villas::node::signalTypeDetect(const std::string &val) { + int len; - if (val.find('i') != std::string::npos) - return SignalType::COMPLEX; + if (val.find('i') != std::string::npos) + return SignalType::COMPLEX; - if (val.find(',') != std::string::npos) - return SignalType::FLOAT; + if (val.find(',') != std::string::npos) + return SignalType::FLOAT; - len = val.size(); - if (len == 1 && (val[0] == '1' || val[0] == '0')) - return SignalType::BOOLEAN; + len = val.size(); + if (len == 1 && (val[0] == '1' || val[0] == '0')) + return SignalType::BOOLEAN; - return SignalType::INTEGER; + return SignalType::INTEGER; } diff --git a/lib/socket_addr.cpp b/lib/socket_addr.cpp index faa5a6d94..a8e4e5f4c 100644 --- a/lib/socket_addr.cpp +++ b/lib/socket_addr.cpp @@ -5,221 +5,224 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include -#include +#include +#include #include #include -#include #ifdef WITH_SOCKET_LAYER_ETH - #include +#include #endif // WITH_SOCKET_LAYER_ETH using namespace villas; using namespace villas::node; using namespace villas::utils; -char * villas::node::socket_print_addr(struct sockaddr *saddr) -{ - union sockaddr_union *sa = (union sockaddr_union *) saddr; - auto *buf = reinterpret_cast(::malloc(256)); - if (!buf) - throw MemoryAllocationError(); +char *villas::node::socket_print_addr(struct sockaddr *saddr) { + union sockaddr_union *sa = (union sockaddr_union *)saddr; + auto *buf = reinterpret_cast(::malloc(256)); + if (!buf) + throw MemoryAllocationError(); - // Address - switch (sa->sa.sa_family) { - case AF_INET6: - inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, 64); - break; + // Address + switch (sa->sa.sa_family) { + case AF_INET6: + inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, 64); + break; - case AF_INET: - inet_ntop(AF_INET, &sa->sin.sin_addr, buf, 64); - break; + case AF_INET: + inet_ntop(AF_INET, &sa->sin.sin_addr, buf, 64); + break; #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: - strcatf(&buf, "%02x", sa->sll.sll_addr[0]); - for (int i = 1; i < sa->sll.sll_halen; i++) - strcatf(&buf, ":%02x", sa->sll.sll_addr[i]); - break; + case AF_PACKET: + strcatf(&buf, "%02x", sa->sll.sll_addr[0]); + for (int i = 1; i < sa->sll.sll_halen; i++) + strcatf(&buf, ":%02x", sa->sll.sll_addr[i]); + break; #endif // WITH_SOCKET_LAYER_ETH - case AF_UNIX: - snprintf(buf, 256, "%s", sa->sun.sun_path); - break; + case AF_UNIX: + snprintf(buf, 256, "%s", sa->sun.sun_path); + break; - default: - throw RuntimeError("Unknown address family: '{}'", sa->sa.sa_family); - } + default: + throw RuntimeError("Unknown address family: '{}'", sa->sa.sa_family); + } - // Port / Interface - switch (sa->sa.sa_family) { - case AF_INET6: - case AF_INET: - strcatf(&buf, ":%hu", ntohs(sa->sin.sin_port)); - break; + // Port / Interface + switch (sa->sa.sa_family) { + case AF_INET6: + case AF_INET: + strcatf(&buf, ":%hu", ntohs(sa->sin.sin_port)); + break; #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: { - struct nl_cache *cache = nl_cache_mngt_require("route/link"); - struct rtnl_link *link = rtnl_link_get(cache, sa->sll.sll_ifindex); - if (!link) - throw RuntimeError("Failed to get interface for index: {}", sa->sll.sll_ifindex); + case AF_PACKET: { + struct nl_cache *cache = nl_cache_mngt_require("route/link"); + struct rtnl_link *link = rtnl_link_get(cache, sa->sll.sll_ifindex); + if (!link) + throw RuntimeError("Failed to get interface for index: {}", + sa->sll.sll_ifindex); - strcatf(&buf, "%%%s", rtnl_link_get_name(link)); - strcatf(&buf, ":%hu", ntohs(sa->sll.sll_protocol)); - break; - } + strcatf(&buf, "%%%s", rtnl_link_get_name(link)); + strcatf(&buf, ":%hu", ntohs(sa->sll.sll_protocol)); + break; + } #endif // WITH_SOCKET_LAYER_ETH - } + } - return buf; + return buf; } -int villas::node::socket_parse_address(const char *addr, struct sockaddr *saddr, enum SocketLayer layer, int flags) -{ - // TODO: Add support for IPv6 - union sockaddr_union *sa = (union sockaddr_union *) saddr; +int villas::node::socket_parse_address(const char *addr, struct sockaddr *saddr, + enum SocketLayer layer, int flags) { + // TODO: Add support for IPv6 + union sockaddr_union *sa = (union sockaddr_union *)saddr; - char *copy = strdup(addr); - int ret; + char *copy = strdup(addr); + int ret; - if (layer == SocketLayer::UNIX) { // Format: "/path/to/socket" - sa->sun.sun_family = AF_UNIX; + if (layer == SocketLayer::UNIX) { // Format: "/path/to/socket" + sa->sun.sun_family = AF_UNIX; - if (strlen(addr) > sizeof(sa->sun.sun_path) - 1) - throw RuntimeError("Length of unix socket path is too long!"); + if (strlen(addr) > sizeof(sa->sun.sun_path) - 1) + throw RuntimeError("Length of unix socket path is too long!"); - memcpy(sa->sun.sun_path, addr, strlen(addr) + 1); + memcpy(sa->sun.sun_path, addr, strlen(addr) + 1); - ret = 0; - } + ret = 0; + } #ifdef WITH_SOCKET_LAYER_ETH - else if (layer == SocketLayer::ETH) { // Format: "ab:cd:ef:12:34:56%ifname:protocol" - // Split string - char *lasts; - char *node = strtok_r(copy, "%", &lasts); - char *ifname = strtok_r(nullptr, ":", &lasts); - char *proto = strtok_r(nullptr, "\0", &lasts); + else if (layer == + SocketLayer::ETH) { // Format: "ab:cd:ef:12:34:56%ifname:protocol" + // Split string + char *lasts; + char *node = strtok_r(copy, "%", &lasts); + char *ifname = strtok_r(nullptr, ":", &lasts); + char *proto = strtok_r(nullptr, "\0", &lasts); - // Parse link layer (MAC) address - struct ether_addr *mac = ether_aton(node); - if (!mac) - throw RuntimeError("Failed to parse MAC address: {}", node); + // Parse link layer (MAC) address + struct ether_addr *mac = ether_aton(node); + if (!mac) + throw RuntimeError("Failed to parse MAC address: {}", node); - memcpy(&sa->sll.sll_addr, &mac->ether_addr_octet, ETHER_ADDR_LEN); + memcpy(&sa->sll.sll_addr, &mac->ether_addr_octet, ETHER_ADDR_LEN); - // Get interface index from name - kernel::nl::init(); + // Get interface index from name + kernel::nl::init(); - struct nl_cache *cache = nl_cache_mngt_require("route/link"); - struct rtnl_link *link = rtnl_link_get_by_name(cache, ifname); - if (!link) - throw RuntimeError("Failed to get network interface: '{}'", ifname); + struct nl_cache *cache = nl_cache_mngt_require("route/link"); + struct rtnl_link *link = rtnl_link_get_by_name(cache, ifname); + if (!link) + throw RuntimeError("Failed to get network interface: '{}'", ifname); - sa->sll.sll_protocol = htons(proto ? strtol(proto, nullptr, 0) : ETH_P_VILLAS); - sa->sll.sll_halen = ETHER_ADDR_LEN; - sa->sll.sll_family = AF_PACKET; - sa->sll.sll_ifindex = rtnl_link_get_ifindex(link); + sa->sll.sll_protocol = + htons(proto ? strtol(proto, nullptr, 0) : ETH_P_VILLAS); + sa->sll.sll_halen = ETHER_ADDR_LEN; + sa->sll.sll_family = AF_PACKET; + sa->sll.sll_ifindex = rtnl_link_get_ifindex(link); - ret = 0; - } -#endif // WITH_SOCKET_LAYER_ETH - else { // Format: "192.168.0.10:12001" - struct addrinfo hint = { - .ai_flags = flags, - .ai_family = AF_UNSPEC - }; + ret = 0; + } +#endif // WITH_SOCKET_LAYER_ETH + else { // Format: "192.168.0.10:12001" + struct addrinfo hint = {.ai_flags = flags, .ai_family = AF_UNSPEC}; - // Split string - char *lasts; - char *node = strtok_r(copy, ":", &lasts); - char *service = strtok_r(nullptr, "\0", &lasts); + // Split string + char *lasts; + char *node = strtok_r(copy, ":", &lasts); + char *service = strtok_r(nullptr, "\0", &lasts); - if (node && !strcmp(node, "*")) - node = nullptr; + if (node && !strcmp(node, "*")) + node = nullptr; - if (service && !strcmp(service, "*")) - service = nullptr; + if (service && !strcmp(service, "*")) + service = nullptr; - switch (layer) { - case SocketLayer::IP: - hint.ai_socktype = SOCK_RAW; - hint.ai_protocol = (service) ? strtol(service, nullptr, 0) : IPPROTO_VILLAS; - hint.ai_flags |= AI_NUMERICSERV; - break; + switch (layer) { + case SocketLayer::IP: + hint.ai_socktype = SOCK_RAW; + hint.ai_protocol = + (service) ? strtol(service, nullptr, 0) : IPPROTO_VILLAS; + hint.ai_flags |= AI_NUMERICSERV; + break; - case SocketLayer::UDP: - hint.ai_socktype = SOCK_DGRAM; - hint.ai_protocol = IPPROTO_UDP; - break; + case SocketLayer::UDP: + hint.ai_socktype = SOCK_DGRAM; + hint.ai_protocol = IPPROTO_UDP; + break; - default: - throw RuntimeError("Invalid address type"); - } + default: + throw RuntimeError("Invalid address type"); + } - // Lookup address - struct addrinfo *result; - ret = getaddrinfo(node, (layer == SocketLayer::IP) ? nullptr : service, &hint, &result); - if (!ret) { - if (layer == SocketLayer::IP) { - // We mis-use the sin_port field to store the IP protocol number on RAW sockets - struct sockaddr_in *sin = (struct sockaddr_in *) result->ai_addr; - sin->sin_port = htons(result->ai_protocol); - } + // Lookup address + struct addrinfo *result; + ret = getaddrinfo(node, (layer == SocketLayer::IP) ? nullptr : service, + &hint, &result); + if (!ret) { + if (layer == SocketLayer::IP) { + // We mis-use the sin_port field to store the IP protocol number on RAW sockets + struct sockaddr_in *sin = (struct sockaddr_in *)result->ai_addr; + sin->sin_port = htons(result->ai_protocol); + } - memcpy(sa, result->ai_addr, result->ai_addrlen); - freeaddrinfo(result); - } - } + memcpy(sa, result->ai_addr, result->ai_addrlen); + freeaddrinfo(result); + } + } - free(copy); + free(copy); - return ret; + return ret; } -int villas::node::socket_compare_addr(struct sockaddr *x, struct sockaddr *y) -{ -#define CMP(a, b) if (a != b) return a < b ? -1 : 1 +int villas::node::socket_compare_addr(struct sockaddr *x, struct sockaddr *y) { +#define CMP(a, b) \ + if (a != b) \ + return a < b ? -1 : 1 - union sockaddr_union *xu = (union sockaddr_union *) x; - union sockaddr_union *yu = (union sockaddr_union *) y; + union sockaddr_union *xu = (union sockaddr_union *)x; + union sockaddr_union *yu = (union sockaddr_union *)y; - CMP(x->sa_family, y->sa_family); + CMP(x->sa_family, y->sa_family); - switch (x->sa_family) { - case AF_UNIX: - return strcmp(xu->sun.sun_path, yu->sun.sun_path); + switch (x->sa_family) { + case AF_UNIX: + return strcmp(xu->sun.sun_path, yu->sun.sun_path); - case AF_INET: - CMP(ntohl(xu->sin.sin_addr.s_addr), ntohl(yu->sin.sin_addr.s_addr)); - CMP(ntohs(xu->sin.sin_port), ntohs(yu->sin.sin_port)); + case AF_INET: + CMP(ntohl(xu->sin.sin_addr.s_addr), ntohl(yu->sin.sin_addr.s_addr)); + CMP(ntohs(xu->sin.sin_port), ntohs(yu->sin.sin_port)); - return 0; + return 0; - case AF_INET6: - CMP(ntohs(xu->sin6.sin6_port), ntohs(yu->sin6.sin6_port)); -// CMP(xu->sin6.sin6_flowinfo, yu->sin6.sin6_flowinfo); -// CMP(xu->sin6.sin6_scope_id, yu->sin6.sin6_scope_id); + case AF_INET6: + CMP(ntohs(xu->sin6.sin6_port), ntohs(yu->sin6.sin6_port)); + // CMP(xu->sin6.sin6_flowinfo, yu->sin6.sin6_flowinfo); + // CMP(xu->sin6.sin6_scope_id, yu->sin6.sin6_scope_id); - return memcmp(xu->sin6.sin6_addr.s6_addr, yu->sin6.sin6_addr.s6_addr, sizeof(xu->sin6.sin6_addr.s6_addr)); + return memcmp(xu->sin6.sin6_addr.s6_addr, yu->sin6.sin6_addr.s6_addr, + sizeof(xu->sin6.sin6_addr.s6_addr)); #ifdef WITH_SOCKET_LAYER_ETH - case AF_PACKET: - CMP(ntohs(xu->sll.sll_protocol), ntohs(yu->sll.sll_protocol)); - CMP(xu->sll.sll_ifindex, yu->sll.sll_ifindex); -// CMP(xu->sll.sll_pkttype, yu->sll.sll_pkttype); -// CMP(xu->sll.sll_hatype, yu->sll.sll_hatype); + case AF_PACKET: + CMP(ntohs(xu->sll.sll_protocol), ntohs(yu->sll.sll_protocol)); + CMP(xu->sll.sll_ifindex, yu->sll.sll_ifindex); + // CMP(xu->sll.sll_pkttype, yu->sll.sll_pkttype); + // CMP(xu->sll.sll_hatype, yu->sll.sll_hatype); - CMP(xu->sll.sll_halen, yu->sll.sll_halen); - return memcmp(xu->sll.sll_addr, yu->sll.sll_addr, xu->sll.sll_halen); + CMP(xu->sll.sll_halen, yu->sll.sll_halen); + return memcmp(xu->sll.sll_addr, yu->sll.sll_addr, xu->sll.sll_halen); #endif // WITH_SOCKET_LAYER_ETH - default: - return -1; - } + default: + return -1; + } #undef CMP } diff --git a/lib/stats.cpp b/lib/stats.cpp index e20cb9db0..d6b352dcd 100644 --- a/lib/stats.cpp +++ b/lib/stats.cpp @@ -7,250 +7,243 @@ #include -#include #include +#include +#include #include -#include #include -#include using namespace villas; using namespace villas::node; using namespace villas::utils; std::unordered_map Stats::metrics = { - { Stats::Metric::SMPS_SKIPPED, { "skipped", "samples", "Skipped samples and the distance between them" }}, - { Stats::Metric::SMPS_REORDERED, { "reordered", "samples", "Reordered samples and the distance between them" }}, - { Stats::Metric::GAP_SAMPLE, { "gap_sent", "seconds", "Inter-message timestamps (as sent by remote)" }}, - { Stats::Metric::GAP_RECEIVED, { "gap_received", "seconds", "Inter-message arrival time (as received by this instance)" }}, - { Stats::Metric::OWD, { "owd", "seconds", "One-way-delay (OWD) of received messages" }}, - { Stats::Metric::AGE, { "age", "seconds", "Processing time of packets within the from receive to sent" }}, - { Stats::Metric::SIGNAL_COUNT, { "signal_cnt", "signals", "Number of signals per sample" }}, - { Stats::Metric::RTP_LOSS_FRACTION, { "rtp.loss_fraction", "percent", "Fraction lost since last RTP SR/RR." }}, - { Stats::Metric::RTP_PKTS_LOST, { "rtp.pkts_lost", "packets", "Cumulative number of packets lost" }}, - { Stats::Metric::RTP_JITTER, { "rtp.jitter", "seconds", "Interarrival jitter" }}, + {Stats::Metric::SMPS_SKIPPED, + {"skipped", "samples", "Skipped samples and the distance between them"}}, + {Stats::Metric::SMPS_REORDERED, + {"reordered", "samples", + "Reordered samples and the distance between them"}}, + {Stats::Metric::GAP_SAMPLE, + {"gap_sent", "seconds", "Inter-message timestamps (as sent by remote)"}}, + {Stats::Metric::GAP_RECEIVED, + {"gap_received", "seconds", + "Inter-message arrival time (as received by this instance)"}}, + {Stats::Metric::OWD, + {"owd", "seconds", "One-way-delay (OWD) of received messages"}}, + {Stats::Metric::AGE, + {"age", "seconds", + "Processing time of packets within the from receive to sent"}}, + {Stats::Metric::SIGNAL_COUNT, + {"signal_cnt", "signals", "Number of signals per sample"}}, + {Stats::Metric::RTP_LOSS_FRACTION, + {"rtp.loss_fraction", "percent", "Fraction lost since last RTP SR/RR."}}, + {Stats::Metric::RTP_PKTS_LOST, + {"rtp.pkts_lost", "packets", "Cumulative number of packets lost"}}, + {Stats::Metric::RTP_JITTER, + {"rtp.jitter", "seconds", "Interarrival jitter"}}, }; std::unordered_map Stats::types = { - { Stats::Type::LAST, { "last", SignalType::FLOAT }}, - { Stats::Type::HIGHEST, { "highest", SignalType::FLOAT }}, - { Stats::Type::LOWEST, { "lowest", SignalType::FLOAT }}, - { Stats::Type::MEAN, { "mean", SignalType::FLOAT }}, - { Stats::Type::VAR, { "var", SignalType::FLOAT }}, - { Stats::Type::STDDEV, { "stddev", SignalType::FLOAT }}, - { Stats::Type::TOTAL, { "total", SignalType::INTEGER }} -}; + {Stats::Type::LAST, {"last", SignalType::FLOAT}}, + {Stats::Type::HIGHEST, {"highest", SignalType::FLOAT}}, + {Stats::Type::LOWEST, {"lowest", SignalType::FLOAT}}, + {Stats::Type::MEAN, {"mean", SignalType::FLOAT}}, + {Stats::Type::VAR, {"var", SignalType::FLOAT}}, + {Stats::Type::STDDEV, {"stddev", SignalType::FLOAT}}, + {Stats::Type::TOTAL, {"total", SignalType::INTEGER}}}; std::vector Stats::columns = { - { 10, TableColumn::Alignment::LEFT, "Node", "%s" }, - { 10, TableColumn::Alignment::RIGHT, "Recv", "%ju", "pkts" }, - { 10, TableColumn::Alignment::RIGHT, "Sent", "%ju", "pkts" }, - { 10, TableColumn::Alignment::RIGHT, "Drop", "%ju", "pkts" }, - { 10, TableColumn::Alignment::RIGHT, "Skip", "%ju", "pkts" }, - { 10, TableColumn::Alignment::RIGHT, "OWD last", "%lf", "secs" }, - { 10, TableColumn::Alignment::RIGHT, "OWD mean", "%lf", "secs" }, - { 10, TableColumn::Alignment::RIGHT, "Rate last", "%lf", "pkt/sec" }, - { 10, TableColumn::Alignment::RIGHT, "Rate mean", "%lf", "pkt/sec" }, - { 10, TableColumn::Alignment::RIGHT, "Age mean", "%lf", "secs" }, - { 10, TableColumn::Alignment::RIGHT, "Age Max", "%lf", "sec" }, - { 8, TableColumn::Alignment::RIGHT, "Signals", "%ju", "signals" } -}; + {10, TableColumn::Alignment::LEFT, "Node", "%s"}, + {10, TableColumn::Alignment::RIGHT, "Recv", "%ju", "pkts"}, + {10, TableColumn::Alignment::RIGHT, "Sent", "%ju", "pkts"}, + {10, TableColumn::Alignment::RIGHT, "Drop", "%ju", "pkts"}, + {10, TableColumn::Alignment::RIGHT, "Skip", "%ju", "pkts"}, + {10, TableColumn::Alignment::RIGHT, "OWD last", "%lf", "secs"}, + {10, TableColumn::Alignment::RIGHT, "OWD mean", "%lf", "secs"}, + {10, TableColumn::Alignment::RIGHT, "Rate last", "%lf", "pkt/sec"}, + {10, TableColumn::Alignment::RIGHT, "Rate mean", "%lf", "pkt/sec"}, + {10, TableColumn::Alignment::RIGHT, "Age mean", "%lf", "secs"}, + {10, TableColumn::Alignment::RIGHT, "Age Max", "%lf", "sec"}, + {8, TableColumn::Alignment::RIGHT, "Signals", "%ju", "signals"}}; -enum Stats::Format Stats::lookupFormat(const std::string &str) -{ - if (str == "human") - return Format::HUMAN; - else if (str == "json") - return Format::JSON; - else if (str == "matlab") - return Format::MATLAB; +enum Stats::Format Stats::lookupFormat(const std::string &str) { + if (str == "human") + return Format::HUMAN; + else if (str == "json") + return Format::JSON; + else if (str == "matlab") + return Format::MATLAB; - throw std::invalid_argument("Invalid format"); + throw std::invalid_argument("Invalid format"); } -enum Stats::Metric Stats::lookupMetric(const std::string &str) -{ - for (auto m : metrics) { - if (str == m.second.name) - return m.first; - } +enum Stats::Metric Stats::lookupMetric(const std::string &str) { + for (auto m : metrics) { + if (str == m.second.name) + return m.first; + } - throw std::invalid_argument("Invalid stats metric"); + throw std::invalid_argument("Invalid stats metric"); } -enum Stats::Type Stats::lookupType(const std::string &str) -{ - for (auto t : types) { - if (str == t.second.name) - return t.first; - } +enum Stats::Type Stats::lookupType(const std::string &str) { + for (auto t : types) { + if (str == t.second.name) + return t.first; + } - throw std::invalid_argument("Invalid stats type"); + throw std::invalid_argument("Invalid stats type"); } -Stats::Stats(int buckets, int warmup) : - logger(logging.get("stats")) -{ - for (auto m : metrics) { - histograms.emplace( - std::piecewise_construct, - std::forward_as_tuple(m.first), - std::forward_as_tuple(buckets, warmup) - ); - } +Stats::Stats(int buckets, int warmup) : logger(logging.get("stats")) { + for (auto m : metrics) { + histograms.emplace(std::piecewise_construct, std::forward_as_tuple(m.first), + std::forward_as_tuple(buckets, warmup)); + } } -void Stats::update(enum Metric m, double val) -{ - histograms[m].put(val); +void Stats::update(enum Metric m, double val) { histograms[m].put(val); } + +void Stats::reset() { + for (auto m : metrics) + histograms[m.first].reset(); } -void Stats::reset() -{ - for (auto m : metrics) - histograms[m.first].reset(); +json_t *Stats::toJson() const { + json_t *obj = json_object(); + + for (auto m : metrics) { + const Hist &h = histograms.at(m.first); + + json_object_set_new(obj, m.second.name, h.toJson()); + } + + return obj; } -json_t * Stats::toJson() const -{ - json_t *obj = json_object(); +void Stats::printHeader(enum Format fmt) { + switch (fmt) { + case Format::HUMAN: + setupTable(); + table->header(); + break; - for (auto m : metrics) { - const Hist &h = histograms.at(m.first); - - json_object_set_new(obj, m.second.name, h.toJson()); - } - - return obj; + default: { + } + } } -void Stats::printHeader(enum Format fmt) -{ - switch (fmt) { - case Format::HUMAN: - setupTable(); - table->header(); - break; - - default: { } - } +void Stats::setupTable() { + if (!table) { + auto logger = logging.get("stats"); + table = std::make_shared
(logger, columns); + } } -void Stats::setupTable() -{ - if (!table) { - auto logger = logging.get("stats"); - table = std::make_shared
(logger, columns); - } +void Stats::printPeriodic(FILE *f, enum Format fmt, node::Node *n) const { + switch (fmt) { + case Format::HUMAN: + setupTable(); + table->row(11, n->getNameShort().c_str(), + (uintmax_t)histograms.at(Metric::OWD).getTotal(), + (uintmax_t)histograms.at(Metric::AGE).getTotal(), + (uintmax_t)histograms.at(Metric::SMPS_REORDERED).getTotal(), + (uintmax_t)histograms.at(Metric::SMPS_SKIPPED).getTotal(), + (double)histograms.at(Metric::OWD).getLast(), + (double)histograms.at(Metric::OWD).getMean(), + (double)1.0 / histograms.at(Metric::GAP_RECEIVED).getLast(), + (double)1.0 / histograms.at(Metric::GAP_RECEIVED).getMean(), + (double)histograms.at(Metric::AGE).getMean(), + (double)histograms.at(Metric::AGE).getHighest(), + (uintmax_t)histograms.at(Metric::SIGNAL_COUNT).getLast()); + break; + + case Format::JSON: { + json_t *json_stats = json_pack( + "{ s: s, s: i, s: i, s: i, s: i, s: f, s: f, s: f, s: f, s: f, s: f, " + "s: i }", + "node", n->getNameShort().c_str(), "recv", + histograms.at(Metric::OWD).getTotal(), "sent", + histograms.at(Metric::AGE).getTotal(), "dropped", + histograms.at(Metric::SMPS_REORDERED).getTotal(), "skipped", + histograms.at(Metric::SMPS_SKIPPED).getTotal(), "owd_last", + 1.0 / histograms.at(Metric::OWD).getLast(), "owd_mean", + 1.0 / histograms.at(Metric::OWD).getMean(), "rate_last", + 1.0 / histograms.at(Metric::GAP_SAMPLE).getLast(), "rate_mean", + 1.0 / histograms.at(Metric::GAP_SAMPLE).getMean(), "age_mean", + histograms.at(Metric::AGE).getMean(), "age_max", + histograms.at(Metric::AGE).getHighest(), "signals", + histograms.at(Metric::SIGNAL_COUNT).getLast()); + json_dumpf(json_stats, f, 0); + break; + } + + default: { + } + } } -void Stats::printPeriodic(FILE *f, enum Format fmt, node::Node *n) const -{ - switch (fmt) { - case Format::HUMAN: - setupTable(); - table->row(11, - n->getNameShort().c_str(), - (uintmax_t) histograms.at(Metric::OWD).getTotal(), - (uintmax_t) histograms.at(Metric::AGE).getTotal(), - (uintmax_t) histograms.at(Metric::SMPS_REORDERED).getTotal(), - (uintmax_t) histograms.at(Metric::SMPS_SKIPPED).getTotal(), - (double) histograms.at(Metric::OWD).getLast(), - (double) histograms.at(Metric::OWD).getMean(), - (double) 1.0 / histograms.at(Metric::GAP_RECEIVED).getLast(), - (double) 1.0 / histograms.at(Metric::GAP_RECEIVED).getMean(), - (double) histograms.at(Metric::AGE).getMean(), - (double) histograms.at(Metric::AGE).getHighest(), - (uintmax_t) histograms.at(Metric::SIGNAL_COUNT).getLast() - ); - break; +void Stats::print(FILE *f, enum Format fmt, int verbose) const { + switch (fmt) { + case Format::HUMAN: + for (auto m : metrics) { + logger->info("{}: {}", m.second.name, m.second.desc); + histograms.at(m.first).print(logger, verbose); + } + break; - case Format::JSON: { - json_t *json_stats = json_pack("{ s: s, s: i, s: i, s: i, s: i, s: f, s: f, s: f, s: f, s: f, s: f, s: i }", - "node", n->getNameShort().c_str(), - "recv", histograms.at(Metric::OWD).getTotal(), - "sent", histograms.at(Metric::AGE).getTotal(), - "dropped", histograms.at(Metric::SMPS_REORDERED).getTotal(), - "skipped", histograms.at(Metric::SMPS_SKIPPED).getTotal(), - "owd_last", 1.0 / histograms.at(Metric::OWD).getLast(), - "owd_mean", 1.0 / histograms.at(Metric::OWD).getMean(), - "rate_last", 1.0 / histograms.at(Metric::GAP_SAMPLE).getLast(), - "rate_mean", 1.0 / histograms.at(Metric::GAP_SAMPLE).getMean(), - "age_mean", histograms.at(Metric::AGE).getMean(), - "age_max", histograms.at(Metric::AGE).getHighest(), - "signals", histograms.at(Metric::SIGNAL_COUNT).getLast() - ); - json_dumpf(json_stats, f, 0); - break; - } + case Format::JSON: + json_dumpf(toJson(), f, 0); + fflush(f); + break; - default: { } - } + default: { + } + } } -void Stats::print(FILE *f, enum Format fmt, int verbose) const -{ - switch (fmt) { - case Format::HUMAN: - for (auto m : metrics) { - logger->info("{}: {}", m.second.name, m.second.desc); - histograms.at(m.first).print(logger, verbose); - } - break; +union SignalData Stats::getValue(enum Metric sm, enum Type st) const { + const Hist &h = histograms.at(sm); + union SignalData d; - case Format::JSON: - json_dumpf(toJson(), f, 0); - fflush(f); - break; + switch (st) { + case Type::TOTAL: + d.i = h.getTotal(); + break; - default: { } - } + case Type::LAST: + d.f = h.getLast(); + break; + + case Type::HIGHEST: + d.f = h.getHighest(); + break; + + case Type::LOWEST: + d.f = h.getLowest(); + break; + + case Type::MEAN: + d.f = h.getMean(); + break; + + case Type::STDDEV: + d.f = h.getStddev(); + break; + + case Type::VAR: + d.f = h.getVar(); + break; + + default: + d.f = -1; + } + + return d; } -union SignalData Stats::getValue(enum Metric sm, enum Type st) const -{ - const Hist &h = histograms.at(sm); - union SignalData d; - - switch (st) { - case Type::TOTAL: - d.i = h.getTotal(); - break; - - case Type::LAST: - d.f = h.getLast(); - break; - - case Type::HIGHEST: - d.f = h.getHighest(); - break; - - case Type::LOWEST: - d.f = h.getLowest(); - break; - - case Type::MEAN: - d.f = h.getMean(); - break; - - case Type::STDDEV: - d.f = h.getStddev(); - break; - - case Type::VAR: - d.f = h.getVar(); - break; - - default: - d.f = -1; - } - - return d; -} - -const Hist & Stats::getHistogram(enum Metric sm) const -{ - return histograms.at(sm); +const Hist &Stats::getHistogram(enum Metric sm) const { + return histograms.at(sm); } std::shared_ptr
Stats::table = std::shared_ptr
(); diff --git a/lib/super_node.cpp b/lib/super_node.cpp index 670ece9e1..8cda7a3b3 100644 --- a/lib/super_node.cpp +++ b/lib/super_node.cpp @@ -9,535 +9,510 @@ #include #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef WITH_NETEM - #include +#include #endif using namespace villas; using namespace villas::node; -SuperNode::SuperNode() : - state(State::INITIALIZED), - idleStop(-1), +SuperNode::SuperNode() + : state(State::INITIALIZED), idleStop(-1), #ifdef WITH_API - api(this), + api(this), #endif #ifdef WITH_WEB - #ifdef WITH_API - web(&api), - #else - web(), - #endif +#ifdef WITH_API + web(&api), +#else + web(), #endif - priority(0), - affinity(0), - hugepages(DEFAULT_NR_HUGEPAGES), - statsRate(1.0), - task(CLOCK_REALTIME), - started(time_now()) -{ - int ret; +#endif + priority(0), affinity(0), hugepages(DEFAULT_NR_HUGEPAGES), statsRate(1.0), + task(CLOCK_REALTIME), started(time_now()) { + int ret; - char hname[128]; - ret = gethostname(hname, sizeof(hname)); - if (ret) - throw SystemError("Failed to determine hostname"); + char hname[128]; + ret = gethostname(hname, sizeof(hname)); + if (ret) + throw SystemError("Failed to determine hostname"); - // Default UUID is derived from hostname - uuid::generateFromString(uuid, hname); + // Default UUID is derived from hostname + uuid::generateFromString(uuid, hname); #ifdef WITH_NETEM - kernel::nl::init(); // Fill link cache -#endif // WITH_NETEM + kernel::nl::init(); // Fill link cache +#endif // WITH_NETEM - logger = logging.get("super_node"); + logger = logging.get("super_node"); } -void SuperNode::parse(const std::string &u) -{ - config.root = config.load(u); +void SuperNode::parse(const std::string &u) { + config.root = config.load(u); - parse(config.root); + parse(config.root); } -void SuperNode::parse(json_t *root) -{ - int ret; +void SuperNode::parse(json_t *root) { + int ret; - assert(state == State::PARSED || - state == State::INITIALIZED || - state == State::CHECKED); + assert(state == State::PARSED || state == State::INITIALIZED || + state == State::CHECKED); - const char *uuid_str = nullptr; + const char *uuid_str = nullptr; - json_t *json_nodes = nullptr; - json_t *json_paths = nullptr; - json_t *json_logging = nullptr; - json_t *json_http = nullptr; + json_t *json_nodes = nullptr; + json_t *json_paths = nullptr; + json_t *json_logging = nullptr; + json_t *json_http = nullptr; - json_error_t err; + json_error_t err; - idleStop = 1; + idleStop = 1; - ret = json_unpack_ex(root, &err, 0, "{ s?: F, s?: o, s?: o, s?: o, s?: o, s?: i, s?: i, s?: i, s?: b, s?: s }", - "stats", &statsRate, - "http", &json_http, - "logging", &json_logging, - "nodes", &json_nodes, - "paths", &json_paths, - "hugepages", &hugepages, - "affinity", &affinity, - "priority", &priority, - "idle_stop", &idleStop, - "uuid", &uuid_str - ); - if (ret) - throw ConfigError(root, err, "node-config", "Unpacking top-level config failed"); + ret = + json_unpack_ex(root, &err, 0, + "{ s?: F, s?: o, s?: o, s?: o, s?: o, s?: i, s?: i, s?: " + "i, s?: b, s?: s }", + "stats", &statsRate, "http", &json_http, "logging", + &json_logging, "nodes", &json_nodes, "paths", &json_paths, + "hugepages", &hugepages, "affinity", &affinity, "priority", + &priority, "idle_stop", &idleStop, "uuid", &uuid_str); + if (ret) + throw ConfigError(root, err, "node-config", + "Unpacking top-level config failed"); - if (uuid_str) { - ret = uuid_parse(uuid_str, uuid); - if (ret) - throw ConfigError(root, "node-config-uuid", "Failed to parse UUID: {}", uuid_str); - } + if (uuid_str) { + ret = uuid_parse(uuid_str, uuid); + if (ret) + throw ConfigError(root, "node-config-uuid", "Failed to parse UUID: {}", + uuid_str); + } #ifdef WITH_WEB - if (json_http) - web.parse(json_http); + if (json_http) + web.parse(json_http); #endif // WITH_WEB - if (json_logging) - logging.parse(json_logging); + if (json_logging) + logging.parse(json_logging); - // Parse nodes - if (json_nodes) { - if (!json_is_object(json_nodes)) - throw ConfigError(json_nodes, "node-config-nodes", "Setting 'nodes' must be a group with node name => group mappings."); + // Parse nodes + if (json_nodes) { + if (!json_is_object(json_nodes)) + throw ConfigError( + json_nodes, "node-config-nodes", + "Setting 'nodes' must be a group with node name => group mappings."); - const char *node_name; - json_t *json_node; - json_object_foreach(json_nodes, node_name, json_node) { - uuid_t node_uuid; - const char *node_type; - const char *node_uuid_str = nullptr; + const char *node_name; + json_t *json_node; + json_object_foreach(json_nodes, node_name, json_node) { + uuid_t node_uuid; + const char *node_type; + const char *node_uuid_str = nullptr; - ret = Node::isValidName(node_name); - if (!ret) - throw RuntimeError("Invalid name for node: {}", node_name); + ret = Node::isValidName(node_name); + if (!ret) + throw RuntimeError("Invalid name for node: {}", node_name); - ret = json_unpack_ex(json_node, &err, 0, "{ s: s, s?: s }", - "type", &node_type, - "uuid", &node_uuid_str - ); - if (ret) - throw ConfigError(root, err, "node-config-node-type", "Failed to parse type of node '{}'", node_name); + ret = json_unpack_ex(json_node, &err, 0, "{ s: s, s?: s }", "type", + &node_type, "uuid", &node_uuid_str); + if (ret) + throw ConfigError(root, err, "node-config-node-type", + "Failed to parse type of node '{}'", node_name); - if (node_uuid_str) { - ret = uuid_parse(uuid_str, uuid); - if (ret) - throw ConfigError(json_node, "node-config-node-uuid", "Failed to parse UUID: {}", uuid_str); - } - else - // Generate UUID from node name and super-node UUID - uuid::generateFromString(node_uuid, node_name, uuid::toString(uuid)); + if (node_uuid_str) { + ret = uuid_parse(uuid_str, uuid); + if (ret) + throw ConfigError(json_node, "node-config-node-uuid", + "Failed to parse UUID: {}", uuid_str); + } else + // Generate UUID from node name and super-node UUID + uuid::generateFromString(node_uuid, node_name, uuid::toString(uuid)); - auto *n = NodeFactory::make(node_type, node_uuid, node_name); - if (!n) - throw MemoryAllocationError(); + auto *n = NodeFactory::make(node_type, node_uuid, node_name); + if (!n) + throw MemoryAllocationError(); - ret = n->parse(json_node); - if (ret) { - auto config_id = fmt::format("node-config-node-{}", node_type); - throw ConfigError(json_node, config_id, "Failed to parse configuration of node '{}'", node_name); - } + ret = n->parse(json_node); + if (ret) { + auto config_id = fmt::format("node-config-node-{}", node_type); + throw ConfigError(json_node, config_id, + "Failed to parse configuration of node '{}'", + node_name); + } - nodes.push_back(n); - } - } + nodes.push_back(n); + } + } - // Parse paths - if (json_paths) { - if (!json_is_array(json_paths)) - logger->warn("Setting 'paths' must be a list of objects"); + // Parse paths + if (json_paths) { + if (!json_is_array(json_paths)) + logger->warn("Setting 'paths' must be a list of objects"); - size_t i; - json_t *json_path; - json_array_foreach(json_paths, i, json_path) { -parse: auto *p = new Path(); - if (!p) - throw MemoryAllocationError(); + size_t i; + json_t *json_path; + json_array_foreach(json_paths, i, json_path) { + parse: + auto *p = new Path(); + if (!p) + throw MemoryAllocationError(); - p->parse(json_path, nodes, uuid); + p->parse(json_path, nodes, uuid); - paths.push_back(p); + paths.push_back(p); - if (p->isReversed()) { - // Only simple paths can be reversed - ret = p->isSimple(); - if (!ret) - throw RuntimeError("Complex paths can not be reversed!"); + if (p->isReversed()) { + // Only simple paths can be reversed + ret = p->isSimple(); + if (!ret) + throw RuntimeError("Complex paths can not be reversed!"); - // Parse a second time with in/out reversed - json_path = json_copy(json_path); + // Parse a second time with in/out reversed + json_path = json_copy(json_path); - json_t *json_in = json_object_get(json_path, "in"); - json_t *json_out = json_object_get(json_path, "out"); + json_t *json_in = json_object_get(json_path, "in"); + json_t *json_out = json_object_get(json_path, "out"); - if (json_equal(json_in, json_out)) - throw RuntimeError("Can not reverse path with identical in/out nodes!"); + if (json_equal(json_in, json_out)) + throw RuntimeError( + "Can not reverse path with identical in/out nodes!"); - json_object_set(json_path, "reverse", json_false()); - json_object_set(json_path, "in", json_out); - json_object_set(json_path, "out", json_in); + json_object_set(json_path, "reverse", json_false()); + json_object_set(json_path, "in", json_out); + json_object_set(json_path, "out", json_in); - goto parse; - } - } - } + goto parse; + } + } + } - state = State::PARSED; + state = State::PARSED; } -void SuperNode::check() -{ - int ret; +void SuperNode::check() { + int ret; - assert(state == State::INITIALIZED || - state == State::PARSED || - state == State::CHECKED); + assert(state == State::INITIALIZED || state == State::PARSED || + state == State::CHECKED); - for (auto *n : nodes) { - ret = n->check(); - if (ret) - throw RuntimeError("Invalid configuration for node {}", n->getName()); - } + for (auto *n : nodes) { + ret = n->check(); + if (ret) + throw RuntimeError("Invalid configuration for node {}", n->getName()); + } - for (auto *p : paths) - p->check(); + for (auto *p : paths) + p->check(); - state = State::CHECKED; + state = State::CHECKED; } -void SuperNode::prepareNodeTypes() -{ - int ret; +void SuperNode::prepareNodeTypes() { + int ret; - for (auto *n : nodes) { - auto *nf = n->getFactory(); + for (auto *n : nodes) { + auto *nf = n->getFactory(); - if (nf->getState() == State::STARTED) - continue; + if (nf->getState() == State::STARTED) + continue; - ret = nf->start(this); - if (ret) - throw RuntimeError("Failed to start node-type: {}", n->getFactory()->getName()); - } + ret = nf->start(this); + if (ret) + throw RuntimeError("Failed to start node-type: {}", + n->getFactory()->getName()); + } } -void SuperNode::startInterfaces() -{ +void SuperNode::startInterfaces() { #ifdef WITH_NETEM - int ret; + int ret; - for (auto *i : interfaces) { - ret = i->start(); - if (ret) - throw RuntimeError("Failed to start network interface: {}", i->getName()); - } + for (auto *i : interfaces) { + ret = i->start(); + if (ret) + throw RuntimeError("Failed to start network interface: {}", i->getName()); + } #endif // WITH_NETEM } -void SuperNode::startNodes() -{ - int ret; +void SuperNode::startNodes() { + int ret; - for (auto *n : nodes) { - if (!n->isEnabled()) - continue; + for (auto *n : nodes) { + if (!n->isEnabled()) + continue; - ret = n->start(); - if (ret) - throw RuntimeError("Failed to start node: {}", n->getName()); - } + ret = n->start(); + if (ret) + throw RuntimeError("Failed to start node: {}", n->getName()); + } } -void SuperNode::startPaths() -{ - for (auto *p : paths) { - if (!p->isEnabled()) - continue; +void SuperNode::startPaths() { + for (auto *p : paths) { + if (!p->isEnabled()) + continue; - p->start(); - } + p->start(); + } } -void SuperNode::prepareNodes() -{ - int ret; +void SuperNode::prepareNodes() { + int ret; - for (auto *n : nodes) { - if (!n->isEnabled()) - continue; + for (auto *n : nodes) { + if (!n->isEnabled()) + continue; - ret = n->prepare(); - if (ret) - throw RuntimeError("Failed to prepare node: {}", n->getName()); - } + ret = n->prepare(); + if (ret) + throw RuntimeError("Failed to prepare node: {}", n->getName()); + } } -void SuperNode::preparePaths() -{ - for (auto *p : paths) { - if (!p->isEnabled()) - continue; +void SuperNode::preparePaths() { + for (auto *p : paths) { + if (!p->isEnabled()) + continue; - p->prepare(nodes); - } + p->prepare(nodes); + } } -void SuperNode::prepare() -{ - int ret; +void SuperNode::prepare() { + int ret; - assert(state == State::CHECKED); + assert(state == State::CHECKED); - ret = memory::init(hugepages); - if (ret) - throw RuntimeError("Failed to initialize memory system"); + ret = memory::init(hugepages); + if (ret) + throw RuntimeError("Failed to initialize memory system"); - kernel::rt::init(priority, affinity); + kernel::rt::init(priority, affinity); - prepareNodeTypes(); - prepareNodes(); - preparePaths(); + prepareNodeTypes(); + prepareNodes(); + preparePaths(); - for (auto *n : nodes) { - if (n->sources.size() == 0 && - n->destinations.size() == 0) { - logger->info("Node {} is not used by any path. Disabling...", n->getName()); - n->setEnabled(false); - } - } + for (auto *n : nodes) { + if (n->sources.size() == 0 && n->destinations.size() == 0) { + logger->info("Node {} is not used by any path. Disabling...", + n->getName()); + n->setEnabled(false); + } + } - state = State::PREPARED; + state = State::PREPARED; } -void SuperNode::start() -{ - assert(state == State::PREPARED); +void SuperNode::start() { + assert(state == State::PREPARED); #ifdef WITH_API - api.start(); + api.start(); #endif #ifdef WITH_WEB - web.start(); + web.start(); #endif - startInterfaces(); - startNodes(); - startPaths(); + startInterfaces(); + startNodes(); + startPaths(); - if (statsRate > 0) // A rate <0 will disable the periodic stats - task.setRate(statsRate); + if (statsRate > 0) // A rate <0 will disable the periodic stats + task.setRate(statsRate); - Stats::printHeader(Stats::Format::HUMAN); + Stats::printHeader(Stats::Format::HUMAN); - state = State::STARTED; + state = State::STARTED; } -void SuperNode::stopPaths() -{ - for (auto *p : paths) { - if (p->getState() == State::STARTED || - p->getState() == State::PAUSED) - p->stop(); - } +void SuperNode::stopPaths() { + for (auto *p : paths) { + if (p->getState() == State::STARTED || p->getState() == State::PAUSED) + p->stop(); + } } -void SuperNode::stopNodes() -{ - int ret; +void SuperNode::stopNodes() { + int ret; - for (auto *n : nodes) { - if (n->getState() == State::STARTED || - n->getState() == State::PAUSED || - n->getState() == State::STOPPING) { - ret = n->stop(); - if (ret) - throw RuntimeError("Failed to stop node: {}", n->getName()); - } - } + for (auto *n : nodes) { + if (n->getState() == State::STARTED || n->getState() == State::PAUSED || + n->getState() == State::STOPPING) { + ret = n->stop(); + if (ret) + throw RuntimeError("Failed to stop node: {}", n->getName()); + } + } } -void SuperNode::stopNodeTypes() -{ - int ret; +void SuperNode::stopNodeTypes() { + int ret; - for (auto *n : nodes) { - auto *nf = n->getFactory(); + for (auto *n : nodes) { + auto *nf = n->getFactory(); - if (nf->getState() != State::STARTED) - continue; + if (nf->getState() != State::STARTED) + continue; - ret = nf->stop(); - if (ret) - throw RuntimeError("Failed to stop node-type: {}", n->getFactory()->getName()); - } + ret = nf->stop(); + if (ret) + throw RuntimeError("Failed to stop node-type: {}", + n->getFactory()->getName()); + } } -void SuperNode::stopInterfaces() -{ +void SuperNode::stopInterfaces() { #ifdef WITH_NETEM - int ret; + int ret; - for (auto *i : interfaces) { - ret = i->stop(); - if (ret) - throw RuntimeError("Failed to stop interface: {}", i->getName()); - } + for (auto *i : interfaces) { + ret = i->stop(); + if (ret) + throw RuntimeError("Failed to stop interface: {}", i->getName()); + } #endif // WITH_NETEM } -void SuperNode::stop() -{ - stopNodes(); - stopPaths(); - stopNodeTypes(); - stopInterfaces(); +void SuperNode::stop() { + stopNodes(); + stopPaths(); + stopNodeTypes(); + stopInterfaces(); #ifdef WITH_API - api.stop(); + api.stop(); #endif #ifdef WITH_WEB - web.stop(); + web.stop(); #endif - state = State::STOPPED; + state = State::STOPPED; } -void SuperNode::run() -{ - int ret; +void SuperNode::run() { + int ret; - while (state == State::STARTED) { - task.wait(); + while (state == State::STARTED) { + task.wait(); - ret = periodic(); - if (ret) - state = State::STOPPING; - } + ret = periodic(); + if (ret) + state = State::STOPPING; + } } -SuperNode::~SuperNode() -{ - assert(state == State::INITIALIZED || - state == State::PARSED || - state == State::CHECKED || - state == State::STOPPED || - state == State::PREPARED); +SuperNode::~SuperNode() { + assert(state == State::INITIALIZED || state == State::PARSED || + state == State::CHECKED || state == State::STOPPED || + state == State::PREPARED); - for (auto *p : paths) - delete p; + for (auto *p : paths) + delete p; - for (auto *n : nodes) - delete n; + for (auto *n : nodes) + delete n; } -int SuperNode::periodic() -{ - int started = 0; +int SuperNode::periodic() { + int started = 0; - for (auto *p : paths) { - if (p->getState() == State::STARTED) { - started++; + for (auto *p : paths) { + if (p->getState() == State::STARTED) { + started++; #ifdef WITH_HOOKS - p->hooks.periodic(); + p->hooks.periodic(); #endif // WITH_HOOKS - } - } + } + } - for (auto *n : nodes) { - if (n->getState() == State::STARTED) { + for (auto *n : nodes) { + if (n->getState() == State::STARTED) { #ifdef WITH_HOOKS - n->in.hooks.periodic(); - n->out.hooks.periodic(); + n->in.hooks.periodic(); + n->out.hooks.periodic(); #endif // WITH_HOOKS - } - } + } + } - if (idleStop > 0 && state == State::STARTED && started == 0) { - logger->info("No more active paths. Stopping super-node"); + if (idleStop > 0 && state == State::STARTED && started == 0) { + logger->info("No more active paths. Stopping super-node"); - return -1; - } + return -1; + } - return 0; + return 0; } #ifdef WITH_GRAPHVIZ -static -void set_attr(void *ptr, const std::string &key, const std::string &value, bool html = false) { - Agraph_t *g = agraphof(ptr); +static void set_attr(void *ptr, const std::string &key, + const std::string &value, bool html = false) { + Agraph_t *g = agraphof(ptr); - char *d = (char *) ""; - char *k = (char *) key.c_str(); - char *v = (char *) value.c_str(); - char *vd = html ? agstrdup_html(g, v) : agstrdup(g, v); + char *d = (char *)""; + char *k = (char *)key.c_str(); + char *v = (char *)value.c_str(); + char *vd = html ? agstrdup_html(g, v) : agstrdup(g, v); - agsafeset(ptr, k, vd, d); + agsafeset(ptr, k, vd, d); } -graph_t * SuperNode::getGraph() -{ - Agraph_t *g; - Agnode_t *m; +graph_t *SuperNode::getGraph() { + Agraph_t *g; + Agnode_t *m; - g = agopen((char *) "g", Agdirected, 0); + g = agopen((char *)"g", Agdirected, 0); - std::map nodeMap; + std::map nodeMap; - for (auto *n : nodes) { - nodeMap[n] = agnode(g, (char *) n->getNameShort().c_str(), 1); + for (auto *n : nodes) { + nodeMap[n] = agnode(g, (char *)n->getNameShort().c_str(), 1); - set_attr(nodeMap[n], "shape", "ellipse"); - set_attr(nodeMap[n], "tooltip", fmt::format("type={}, uuid={}", n->getFactory()->getName(), uuid::toString(n->getUuid()).c_str())); - // set_attr(nodeMap[n], "fixedsize", "true"); - // set_attr(nodeMap[n], "width", "0.15"); - // set_attr(nodeMap[n], "height", "0.15"); - } + set_attr(nodeMap[n], "shape", "ellipse"); + set_attr(nodeMap[n], "tooltip", + fmt::format("type={}, uuid={}", n->getFactory()->getName(), + uuid::toString(n->getUuid()).c_str())); + // set_attr(nodeMap[n], "fixedsize", "true"); + // set_attr(nodeMap[n], "width", "0.15"); + // set_attr(nodeMap[n], "height", "0.15"); + } - unsigned i = 0; - for (auto *p : paths) { - auto name = fmt::format("path_{}", i++); + unsigned i = 0; + for (auto *p : paths) { + auto name = fmt::format("path_{}", i++); - m = agnode(g, (char *) name.c_str(), 1); + m = agnode(g, (char *)name.c_str(), 1); - set_attr(m, "shape", "box"); - set_attr(m, "tooltip", fmt::format("uuid={}", uuid::toString(p->getUuid()).c_str())); + set_attr(m, "shape", "box"); + set_attr(m, "tooltip", + fmt::format("uuid={}", uuid::toString(p->getUuid()).c_str())); - for (auto ps : p->sources) - agedge(g, nodeMap[ps->getNode()], m, nullptr, 1); + for (auto ps : p->sources) + agedge(g, nodeMap[ps->getNode()], m, nullptr, 1); - for (auto pd : p->destinations) - agedge(g, m, nodeMap[pd->getNode()], nullptr, 1); - } - - return g; + for (auto pd : p->destinations) + agedge(g, m, nodeMap[pd->getNode()], nullptr, 1); + } + return g; } #endif // WITH_GRAPHVIZ diff --git a/lib/usb.cpp b/lib/usb.cpp index ed3cd3499..6c3f3dd79 100644 --- a/lib/usb.cpp +++ b/lib/usb.cpp @@ -5,146 +5,131 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include using namespace villas; using namespace villas::usb; -static -struct libusb_context *context = nullptr; +static struct libusb_context *context = nullptr; -static -int context_users = 0; +static int context_users = 0; -static -Logger logger; +static Logger logger; -static -enum libusb_log_level spdlog_to_libusb_log_level(Log::Level lvl) -{ - switch (lvl) { - case Log::Level::trace: - case Log::Level::debug: - return LIBUSB_LOG_LEVEL_DEBUG; +static enum libusb_log_level spdlog_to_libusb_log_level(Log::Level lvl) { + switch (lvl) { + case Log::Level::trace: + case Log::Level::debug: + return LIBUSB_LOG_LEVEL_DEBUG; - case Log::Level::info: - return LIBUSB_LOG_LEVEL_INFO; + case Log::Level::info: + return LIBUSB_LOG_LEVEL_INFO; - case Log::Level::warn: - return LIBUSB_LOG_LEVEL_WARNING; + case Log::Level::warn: + return LIBUSB_LOG_LEVEL_WARNING; - case Log::Level::err: - case Log::Level::critical: - return LIBUSB_LOG_LEVEL_ERROR; + case Log::Level::err: + case Log::Level::critical: + return LIBUSB_LOG_LEVEL_ERROR; - default: - case Log::Level::off: - return LIBUSB_LOG_LEVEL_NONE; - - } + default: + case Log::Level::off: + return LIBUSB_LOG_LEVEL_NONE; + } } -static -Log::Level libusb_to_spdlog_log_level(enum libusb_log_level lvl) -{ - switch (lvl) { - case LIBUSB_LOG_LEVEL_ERROR: - return Log::Level::err; +static Log::Level libusb_to_spdlog_log_level(enum libusb_log_level lvl) { + switch (lvl) { + case LIBUSB_LOG_LEVEL_ERROR: + return Log::Level::err; - case LIBUSB_LOG_LEVEL_WARNING: - return Log::Level::warn; + case LIBUSB_LOG_LEVEL_WARNING: + return Log::Level::warn; - case LIBUSB_LOG_LEVEL_INFO: - return Log::Level::info; + case LIBUSB_LOG_LEVEL_INFO: + return Log::Level::info; - case LIBUSB_LOG_LEVEL_DEBUG: - return Log::Level::debug; + case LIBUSB_LOG_LEVEL_DEBUG: + return Log::Level::debug; - case LIBUSB_LOG_LEVEL_NONE: - default: - return Log::Level::off; - } + case LIBUSB_LOG_LEVEL_NONE: + default: + return Log::Level::off; + } } -static -void log_cb(struct libusb_context *ctx, enum libusb_log_level lvl, const char *str) -{ - auto level = libusb_to_spdlog_log_level(lvl); +static void log_cb(struct libusb_context *ctx, enum libusb_log_level lvl, + const char *str) { + auto level = libusb_to_spdlog_log_level(lvl); - logger->log(level, str); + logger->log(level, str); } -void villas::usb::detach(struct libusb_device_handle *handle, int iface) -{ - int ret; +void villas::usb::detach(struct libusb_device_handle *handle, int iface) { + int ret; - ret = libusb_detach_kernel_driver(handle, iface); - if (ret != LIBUSB_SUCCESS) - throw Error(ret, "Failed to detach USB device from kernel driver"); + ret = libusb_detach_kernel_driver(handle, iface); + if (ret != LIBUSB_SUCCESS) + throw Error(ret, "Failed to detach USB device from kernel driver"); } -struct libusb_context * villas::usb::init() -{ - int ret; - struct libusb_context *ctx; +struct libusb_context *villas::usb::init() { + int ret; + struct libusb_context *ctx; - logger = logging.get("usb"); + logger = logging.get("usb"); - ret = libusb_init(&ctx); - if (ret) - throw Error(ret, "Failed to initialize libusb context"); + ret = libusb_init(&ctx); + if (ret) + throw Error(ret, "Failed to initialize libusb context"); - auto lvl = spdlog_to_libusb_log_level(logger->level()); + auto lvl = spdlog_to_libusb_log_level(logger->level()); #if LIBUSBX_API_VERSION < 0x01000106 - libusb_set_debug(ctx, lvl); + libusb_set_debug(ctx, lvl); #else - ret = libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, lvl); - if (ret) - throw Error(ret, "Failed to set libusb log level"); + ret = libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, lvl); + if (ret) + throw Error(ret, "Failed to set libusb log level"); #endif - libusb_set_log_cb(ctx, log_cb, LIBUSB_LOG_CB_GLOBAL); + libusb_set_log_cb(ctx, log_cb, LIBUSB_LOG_CB_GLOBAL); - return ctx; + return ctx; } -void villas::usb::deinit_context(struct libusb_context *ctx) -{ - context_users--; +void villas::usb::deinit_context(struct libusb_context *ctx) { + context_users--; - if (context_users == 0) { - libusb_exit(ctx); - context = nullptr; - } + if (context_users == 0) { + libusb_exit(ctx); + context = nullptr; + } } -struct libusb_context * villas::usb::get_context() -{ - if (context == nullptr) - context = init(); +struct libusb_context *villas::usb::get_context() { + if (context == nullptr) + context = init(); - context_users++; + context_users++; - return context; + return context; } -bool Device::match(const Filter *flt) const -{ - return (flt->bus < 0 || flt->bus == getBus()) && - (flt->port < 0 || flt->port == getPort()) && - (flt->vendor_id < 0 || flt->vendor_id == getDescriptor().idVendor) && - (flt->product_id < 0 || flt->product_id == getDescriptor().idProduct); +bool Device::match(const Filter *flt) const { + return (flt->bus < 0 || flt->bus == getBus()) && + (flt->port < 0 || flt->port == getPort()) && + (flt->vendor_id < 0 || flt->vendor_id == getDescriptor().idVendor) && + (flt->product_id < 0 || flt->product_id == getDescriptor().idProduct); } -std::string Device::getStringDescriptor(uint8_t desc_id) const -{ - int ret; - unsigned char buf[256]; +std::string Device::getStringDescriptor(uint8_t desc_id) const { + int ret; + unsigned char buf[256]; - ret = libusb_get_string_descriptor_ascii(handle, desc_id, buf, sizeof(buf)); - if (ret != LIBUSB_SUCCESS) - throw RuntimeError("Failed to get USB string descriptor"); + ret = libusb_get_string_descriptor_ascii(handle, desc_id, buf, sizeof(buf)); + if (ret != LIBUSB_SUCCESS) + throw RuntimeError("Failed to get USB string descriptor"); - return (char *) buf; + return (char *)buf; } diff --git a/lib/web.cpp b/lib/web.cpp index 5c95d2455..b3e6d2251 100644 --- a/lib/web.cpp +++ b/lib/web.cpp @@ -7,17 +7,17 @@ #include -#include -#include -#include -#include #include #include +#include +#include #include #include +#include +#include #ifdef WITH_NODE_WEBRTC - #include +#include #endif using namespace villas; @@ -28,267 +28,242 @@ lws_callback_function villas::node::websocket_protocol_cb; // List of libwebsockets protocols. lws_protocols protocols[] = { - { - .name = "http", - .callback = lws_callback_http_dummy, - .per_session_data_size = 0, - .rx_buffer_size = 1024 - }, + {.name = "http", + .callback = lws_callback_http_dummy, + .per_session_data_size = 0, + .rx_buffer_size = 1024}, #ifdef WITH_API - { - .name = "http-api", - .callback = api::Session::protocolCallback, - .per_session_data_size = sizeof(api::Session), - .rx_buffer_size = 1024 - }, + {.name = "http-api", + .callback = api::Session::protocolCallback, + .per_session_data_size = sizeof(api::Session), + .rx_buffer_size = 1024}, #endif // WITH_API #ifdef WITH_NODE_WEBSOCKET - { - .name = "live", - .callback = websocket_protocol_cb, - .per_session_data_size = sizeof(websocket_connection), - .rx_buffer_size = 0 - }, + {.name = "live", + .callback = websocket_protocol_cb, + .per_session_data_size = sizeof(websocket_connection), + .rx_buffer_size = 0}, #endif // WITH_NODE_WEBSOCKET #ifdef WITH_NODE_WEBRTC - { - .name = "webrtc-signaling", - .callback = webrtc::SignalingClient::protocolCallbackStatic, - .per_session_data_size = sizeof(webrtc::SignalingClient), - .rx_buffer_size = 0 - }, + {.name = "webrtc-signaling", + .callback = webrtc::SignalingClient::protocolCallbackStatic, + .per_session_data_size = sizeof(webrtc::SignalingClient), + .rx_buffer_size = 0}, #endif - { - .name = nullptr, - } -}; + { + .name = nullptr, + }}; // List of libwebsockets mounts. -static -lws_http_mount mounts[] = { +static lws_http_mount mounts[] = { #ifdef WITH_API - { - .mount_next = nullptr, // linked-list "next" - .mountpoint = "/api/v2", // mountpoint URL - .origin = "http-api", // protocol - .def = nullptr, - .protocol = "http-api", - .cgienv = nullptr, - .extra_mimetypes = nullptr, - .interpret = nullptr, - .cgi_timeout = 0, - .cache_max_age = 0, - .auth_mask = 0, - .cache_reusable = 0, - .cache_revalidate = 0, - .cache_intermediaries = 0, - .origin_protocol = LWSMPRO_CALLBACK, // dynamic - .mountpoint_len = 7 // char count - } + { + .mount_next = nullptr, // linked-list "next" + .mountpoint = "/api/v2", // mountpoint URL + .origin = "http-api", // protocol + .def = nullptr, + .protocol = "http-api", + .cgienv = nullptr, + .extra_mimetypes = nullptr, + .interpret = nullptr, + .cgi_timeout = 0, + .cache_max_age = 0, + .auth_mask = 0, + .cache_reusable = 0, + .cache_revalidate = 0, + .cache_intermediaries = 0, + .origin_protocol = LWSMPRO_CALLBACK, // dynamic + .mountpoint_len = 7 // char count + } #endif // WITH_API }; // List of libwebsockets extensions. -static -const lws_extension extensions[] = { +static const lws_extension extensions[] = { #ifdef LWS_DEFLATE_FOUND - { - .name = "permessage-deflate", - .callback = lws_extension_callback_pm_deflate, - .client_offer = "permessage-deflate" - }, - { - .name = "deflate-frame", - .callback = lws_extension_callback_pm_deflate, - .client_offer = "deflate_frame" - }, + {.name = "permessage-deflate", + .callback = lws_extension_callback_pm_deflate, + .client_offer = "permessage-deflate"}, + {.name = "deflate-frame", + .callback = lws_extension_callback_pm_deflate, + .client_offer = "deflate_frame"}, #endif // LWS_DEFLATE_FOUND - { nullptr /* terminator */ } -}; + {nullptr /* terminator */}}; void Web::lwsLogger(int lws_lvl, const char *msg) { - char *nl; + char *nl; - nl = (char *) strchr(msg, '\n'); - if (nl) - *nl = 0; + nl = (char *)strchr(msg, '\n'); + if (nl) + *nl = 0; - // Decrease severity for some errors - if (strstr(msg, "Unable to open") == msg) - lws_lvl = LLL_WARN; + // Decrease severity for some errors + if (strstr(msg, "Unable to open") == msg) + lws_lvl = LLL_WARN; - Logger logger = logging.get("lws"); + Logger logger = logging.get("lws"); - switch (lws_lvl) { - case LLL_ERR: - logger->error("{}", msg); - break; + switch (lws_lvl) { + case LLL_ERR: + logger->error("{}", msg); + break; - case LLL_WARN: - logger->warn("{}", msg); - break; + case LLL_WARN: + logger->warn("{}", msg); + break; - case LLL_NOTICE: - case LLL_INFO: - logger->info("{}", msg); - break; + case LLL_NOTICE: + case LLL_INFO: + logger->info("{}", msg); + break; - default: // Everything else is debug - logger->debug("{}", msg); - } + default: // Everything else is debug + logger->debug("{}", msg); + } } int Web::lwsLogLevel(Log::Level lvl) { - int lwsLvl = 0; + int lwsLvl = 0; - switch (lvl) { - case Log::Level::trace: - lwsLvl |= LLL_THREAD | LLL_USER | LLL_LATENCY | LLL_CLIENT | LLL_EXT | LLL_HEADER | LLL_PARSER; - case Log::Level::debug: - lwsLvl |= LLL_DEBUG | LLL_NOTICE | LLL_INFO; - case Log::Level::info: - case Log::Level::warn: - lwsLvl |= LLL_WARN; - case Log::Level::err: - lwsLvl |= LLL_ERR; - case Log::Level::critical: - case Log::Level::off: - default: { } - } + switch (lvl) { + case Log::Level::trace: + lwsLvl |= LLL_THREAD | LLL_USER | LLL_LATENCY | LLL_CLIENT | LLL_EXT | + LLL_HEADER | LLL_PARSER; + case Log::Level::debug: + lwsLvl |= LLL_DEBUG | LLL_NOTICE | LLL_INFO; + case Log::Level::info: + case Log::Level::warn: + lwsLvl |= LLL_WARN; + case Log::Level::err: + lwsLvl |= LLL_ERR; + case Log::Level::critical: + case Log::Level::off: + default: { + } + } - return lwsLvl; + return lwsLvl; } -void Web::worker() -{ - logger->info("Started worker"); +void Web::worker() { + logger->info("Started worker"); - while (running) { - lws_service(context, 0); + while (running) { + lws_service(context, 0); - while (!writables.empty()) { - auto *wsi = writables.pop(); + while (!writables.empty()) { + auto *wsi = writables.pop(); - lws_callback_on_writable(wsi); - } - } + lws_callback_on_writable(wsi); + } + } - logger->info("Stopped worker"); + logger->info("Stopped worker"); } -Web::Web(Api *a) : - state(State::INITIALIZED), - logger(logging.get("web")), - context(nullptr), - vhost(nullptr), - port(getuid() > 0 ? 8080 : 80), - api(a) -{ - lws_set_log_level(lwsLogLevel(logging.getLevel()), lwsLogger); +Web::Web(Api *a) + : state(State::INITIALIZED), logger(logging.get("web")), context(nullptr), + vhost(nullptr), port(getuid() > 0 ? 8080 : 80), api(a) { + lws_set_log_level(lwsLogLevel(logging.getLevel()), lwsLogger); } -Web::~Web() -{ - if (state == State::STARTED) - stop(); +Web::~Web() { + if (state == State::STARTED) + stop(); } -int Web::parse(json_t *json) -{ - int ret, enabled = 1; - const char *cert = nullptr; - const char *pkey = nullptr; - json_error_t err; +int Web::parse(json_t *json) { + int ret, enabled = 1; + const char *cert = nullptr; + const char *pkey = nullptr; + json_error_t err; - ret = json_unpack_ex(json, &err, JSON_STRICT, "{ s?: s, s?: s, s?: i, s?: b }", - "ssl_cert", &cert, - "ssl_private_key", &pkey, - "port", &port, - "enabled", &enabled - ); - if (ret) - throw ConfigError(json, err, "node-config-http"); + ret = json_unpack_ex( + json, &err, JSON_STRICT, "{ s?: s, s?: s, s?: i, s?: b }", "ssl_cert", + &cert, "ssl_private_key", &pkey, "port", &port, "enabled", &enabled); + if (ret) + throw ConfigError(json, err, "node-config-http"); - if (cert) - ssl_cert = cert; + if (cert) + ssl_cert = cert; - if (pkey) - ssl_private_key = pkey; + if (pkey) + ssl_private_key = pkey; - if (!enabled) - port = CONTEXT_PORT_NO_LISTEN; + if (!enabled) + port = CONTEXT_PORT_NO_LISTEN; - state = State::PARSED; + state = State::PARSED; - return 0; + return 0; } -void Web::start() -{ - // Start server - lws_context_creation_info ctx_info; +void Web::start() { + // Start server + lws_context_creation_info ctx_info; - memset(&ctx_info, 0, sizeof(ctx_info)); + memset(&ctx_info, 0, sizeof(ctx_info)); - ctx_info.port = port; - ctx_info.protocols = protocols; + ctx_info.port = port; + ctx_info.protocols = protocols; #ifndef LWS_WITHOUT_EXTENSIONS - ctx_info.extensions = extensions; + ctx_info.extensions = extensions; #endif - ctx_info.ssl_cert_filepath = ssl_cert.empty() ? nullptr : ssl_cert.c_str(); - ctx_info.ssl_private_key_filepath = ssl_private_key.empty() ? nullptr : ssl_private_key.c_str(); - ctx_info.gid = -1; - ctx_info.uid = -1; - ctx_info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctx_info.user = (void *) this; + ctx_info.ssl_cert_filepath = ssl_cert.empty() ? nullptr : ssl_cert.c_str(); + ctx_info.ssl_private_key_filepath = + ssl_private_key.empty() ? nullptr : ssl_private_key.c_str(); + ctx_info.gid = -1; + ctx_info.uid = -1; + ctx_info.options = + LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctx_info.user = (void *)this; #if LWS_LIBRARY_VERSION_NUMBER <= 3000000 - // See: https://github.com/warmcat/libwebsockets/issues/1249 - ctx_info.max_http_header_pool = 1024; + // See: https://github.com/warmcat/libwebsockets/issues/1249 + ctx_info.max_http_header_pool = 1024; #endif - ctx_info.mounts = mounts; + ctx_info.mounts = mounts; - logger->info("Starting sub-system"); + logger->info("Starting sub-system"); - context = lws_create_context(&ctx_info); - if (context == nullptr) - throw RuntimeError("Failed to initialize server context"); + context = lws_create_context(&ctx_info); + if (context == nullptr) + throw RuntimeError("Failed to initialize server context"); - for (int tries = 10; tries > 0; tries--) { - vhost = lws_create_vhost(context, &ctx_info); - if (vhost) - break; + for (int tries = 10; tries > 0; tries--) { + vhost = lws_create_vhost(context, &ctx_info); + if (vhost) + break; - ctx_info.port++; - logger->warn("Failed to setup vhost. Trying another port: {}", ctx_info.port); - } + ctx_info.port++; + logger->warn("Failed to setup vhost. Trying another port: {}", + ctx_info.port); + } - if (vhost == nullptr) - throw RuntimeError("Failed to initialize virtual host"); + if (vhost == nullptr) + throw RuntimeError("Failed to initialize virtual host"); - // Start thread - running = true; - thread = std::thread(&Web::worker, this); + // Start thread + running = true; + thread = std::thread(&Web::worker, this); - state = State::STARTED; + state = State::STARTED; } -void Web::stop() -{ - assert(state == State::STARTED); +void Web::stop() { + assert(state == State::STARTED); - logger->info("Stopping sub-system"); + logger->info("Stopping sub-system"); - running = false; - lws_cancel_service(context); - thread.join(); + running = false; + lws_cancel_service(context); + thread.join(); - lws_context_destroy(context); + lws_context_destroy(context); - state = State::STOPPED; + state = State::STOPPED; } -void Web::callbackOnWritable(lws *wsi) -{ - writables.push(wsi); - lws_cancel_service(context); +void Web::callbackOnWritable(lws *wsi) { + writables.push(wsi); + lws_cancel_service(context); } diff --git a/plugins/example_hook.cpp b/plugins/example_hook.cpp index 0ab18dfca..1c56ce885 100644 --- a/plugins/example_hook.cpp +++ b/plugins/example_hook.cpp @@ -14,19 +14,17 @@ namespace node { class ExampleHook : public Hook { public: - using Hook::Hook; + using Hook::Hook; - virtual - void restart() - { - logger->info("The path {} restarted!", path->toString()); - } + virtual void restart() { + logger->info("The path {} restarted!", path->toString()); + } }; // Register hook static char n[] = "example"; static char d[] = "This is just a simple example hook"; -static HookPlugin p; +static HookPlugin p; } // namespace node } // namespace villas diff --git a/src/villas-compare.cpp b/src/villas-compare.cpp index 6305ede22..09fa071b7 100644 --- a/src/villas-compare.cpp +++ b/src/villas-compare.cpp @@ -10,14 +10,14 @@ #include -#include -#include -#include -#include -#include -#include #include +#include +#include #include +#include +#include +#include +#include using namespace villas; @@ -28,251 +28,250 @@ namespace tools { class CompareSide { public: - std::string path; - std::string dtypes; - std::string format; + std::string path; + std::string dtypes; + std::string format; - struct Sample *sample; + struct Sample *sample; - Format *formatter; + Format *formatter; - FILE *stream; + FILE *stream; - CompareSide(const CompareSide&) = delete; - CompareSide & operator=(const CompareSide&) = delete; + CompareSide(const CompareSide &) = delete; + CompareSide &operator=(const CompareSide &) = delete; - CompareSide(const std::string &pth, const std::string &fmt, const std::string &dt, struct Pool *p) : - path(pth), - dtypes(dt), - format(fmt) - { - json_t *json_format; - json_error_t err; + CompareSide(const std::string &pth, const std::string &fmt, + const std::string &dt, struct Pool *p) + : path(pth), dtypes(dt), format(fmt) { + json_t *json_format; + json_error_t err; - // Try parsing format config as JSON - json_format = json_loads(format.c_str(), 0, &err); - formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(format); - if (!formatter) - throw RuntimeError("Failed to initialize formatter"); + // Try parsing format config as JSON + json_format = json_loads(format.c_str(), 0, &err); + formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(format); + if (!formatter) + throw RuntimeError("Failed to initialize formatter"); - formatter->start(dtypes); + formatter->start(dtypes); - stream = fopen(path.c_str(), "r"); - if (!stream) - throw SystemError("Failed to open file: {}", path); + stream = fopen(path.c_str(), "r"); + if (!stream) + throw SystemError("Failed to open file: {}", path); - sample = sample_alloc(p); - if (!sample) - throw RuntimeError("Failed to allocate samples"); - } + sample = sample_alloc(p); + if (!sample) + throw RuntimeError("Failed to allocate samples"); + } - ~CompareSide() noexcept(false) - { - int ret __attribute((unused)); + ~CompareSide() noexcept(false) { + int ret __attribute((unused)); - ret = fclose(stream); + ret = fclose(stream); - delete formatter; + delete formatter; - sample_decref(sample); - } + sample_decref(sample); + } }; class Compare : public Tool { public: - Compare(int argc, char *argv[]) : - Tool(argc, argv, "test-cmp"), - pool(), - epsilon(1e-6), - format("villas.human"), - dtypes("64f"), - flags((int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_TS_ORIGIN) - { - int ret; + Compare(int argc, char *argv[]) + : Tool(argc, argv, "test-cmp"), pool(), epsilon(1e-6), + format("villas.human"), dtypes("64f"), + flags((int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_TS_ORIGIN) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } protected: - struct Pool pool; + struct Pool pool; - double epsilon; - std::string format; - std::string dtypes; - int flags; + double epsilon; + std::string format; + std::string dtypes; + int flags; - std::vector filenames; + std::vector filenames; - void usage() - { - std::cout << "Usage: villas-compare [OPTIONS] FILE1 FILE2 ... FILEn" << std::endl - << " FILE a list of files to compare" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -d LVL adjust the debug level" << std::endl - << " -e EPS set epsilon for floating point comparisons to EPS" << std::endl - << " -v ignore data values" << std::endl - << " -T ignore timestamp" << std::endl - << " -s ignore sequence no" << std::endl - << " -f FMT file format for all files" << std::endl - << " -t DT the data-type format string" << std::endl - << " -h show this usage information" << std::endl - << " -V show the version of the tool" << std::endl << std::endl - << "Return codes:" << std::endl - << " 0 files are equal" << std::endl - << " 1 file length not equal" << std::endl - << " 2 sequence no not equal" << std::endl - << " 3 timestamp not equal" << std::endl - << " 4 number of values is not equal" << std::endl - << " 5 data is not equal" << std::endl << std::endl; + void usage() { + std::cout << "Usage: villas-compare [OPTIONS] FILE1 FILE2 ... FILEn" + << std::endl + << " FILE a list of files to compare" << std::endl + << " OPTIONS is one or more of the following options:" + << std::endl + << " -d LVL adjust the debug level" << std::endl + << " -e EPS set epsilon for floating point comparisons to EPS" + << std::endl + << " -v ignore data values" << std::endl + << " -T ignore timestamp" << std::endl + << " -s ignore sequence no" << std::endl + << " -f FMT file format for all files" << std::endl + << " -t DT the data-type format string" << std::endl + << " -h show this usage information" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl + << "Return codes:" << std::endl + << " 0 files are equal" << std::endl + << " 1 file length not equal" << std::endl + << " 2 sequence no not equal" << std::endl + << " 3 timestamp not equal" << std::endl + << " 4 number of values is not equal" << std::endl + << " 5 data is not equal" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - // Parse Arguments - int c; - char *endptr; - while ((c = getopt (argc, argv, "he:vTsf:t:Vd:")) != -1) { - switch (c) { - case 'e': - epsilon = strtod(optarg, &endptr); - goto check; + void parse() { + // Parse Arguments + int c; + char *endptr; + while ((c = getopt(argc, argv, "he:vTsf:t:Vd:")) != -1) { + switch (c) { + case 'e': + epsilon = strtod(optarg, &endptr); + goto check; - case 'v': - flags &= ~(int) SampleFlags::HAS_DATA; - break; + case 'v': + flags &= ~(int)SampleFlags::HAS_DATA; + break; - case 'T': - flags &= ~(int) SampleFlags::HAS_TS_ORIGIN; - break; + case 'T': + flags &= ~(int)SampleFlags::HAS_TS_ORIGIN; + break; - case 's': - flags &= ~(int) SampleFlags::HAS_SEQUENCE; - break; + case 's': + flags &= ~(int)SampleFlags::HAS_SEQUENCE; + break; - case 'f': - format = optarg; - break; + case 'f': + format = optarg; + break; - case 't': - dtypes = optarg; - break; + case 't': + dtypes = optarg; + break; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: if (optarg == endptr) - throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg); - } + check: + if (optarg == endptr) + throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, + optarg); + } - if (argc - optind < 2) { - usage(); - exit(EXIT_FAILURE); - } + if (argc - optind < 2) { + usage(); + exit(EXIT_FAILURE); + } - // Open files - for (int i = 0; i < argc - optind; i++) - filenames.push_back(argv[optind + i]); - } + // Open files + for (int i = 0; i < argc - optind; i++) + filenames.push_back(argv[optind + i]); + } - int main() - { - int ret, rc = 0, line, failed; - unsigned eofs; + int main() { + int ret, rc = 0, line, failed; + unsigned eofs; - ret = pool_init(&pool, filenames.size(), SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory::heap); - if (ret) - throw RuntimeError("Failed to initialize pool"); + ret = pool_init(&pool, filenames.size(), + SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory::heap); + if (ret) + throw RuntimeError("Failed to initialize pool"); - // Open files - std::vector sides; - for (auto filename : filenames) { - auto *s = new CompareSide(filename, format, dtypes, &pool); - if (!s) - throw MemoryAllocationError(); + // Open files + std::vector sides; + for (auto filename : filenames) { + auto *s = new CompareSide(filename, format, dtypes, &pool); + if (!s) + throw MemoryAllocationError(); - sides.push_back(s); - } + sides.push_back(s); + } - line = 0; - while (true) { - // Read next sample from all files -retry: eofs = 0; - for (auto side : sides) { - ret = feof(side->stream); - if (ret) - eofs++; - } + line = 0; + while (true) { + // Read next sample from all files + retry: + eofs = 0; + for (auto side : sides) { + ret = feof(side->stream); + if (ret) + eofs++; + } - if (eofs) { - if (eofs == sides.size()) - ret = 0; - else { - std::cout << "length unequal" << std::endl; - rc = 1; - } + if (eofs) { + if (eofs == sides.size()) + ret = 0; + else { + std::cout << "length unequal" << std::endl; + rc = 1; + } - goto out; - } + goto out; + } - failed = 0; - for (auto side : sides) { - ret = side->formatter->scan(side->stream, side->sample); - if (ret <= 0) - failed++; - } - if (failed) - goto retry; + failed = 0; + for (auto side : sides) { + ret = side->formatter->scan(side->stream, side->sample); + if (ret <= 0) + failed++; + } + if (failed) + goto retry; - // We compare all files against the first one - for (auto side : sides) { - ret = sample_cmp(sides[0]->sample, side->sample, epsilon, flags); - if (ret) { - rc = ret; - goto out; - } - } + // We compare all files against the first one + for (auto side : sides) { + ret = sample_cmp(sides[0]->sample, side->sample, epsilon, flags); + if (ret) { + rc = ret; + goto out; + } + } - line++; - } + line++; + } -out: for (auto side : sides) - delete side; + out: + for (auto side : sides) + delete side; - ret = pool_destroy(&pool); - if (ret) - throw RuntimeError("Failed to destroy pool"); + ret = pool_destroy(&pool); + if (ret) + throw RuntimeError("Failed to destroy pool"); - return rc; - } + return rc; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Compare t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Compare t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-conf2json.cpp b/src/villas-conf2json.cpp index aea969fc2..9217321f6 100644 --- a/src/villas-conf2json.cpp +++ b/src/villas-conf2json.cpp @@ -5,15 +5,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include +#include #include #include -#include #include +#include namespace villas { namespace node { @@ -22,69 +22,65 @@ namespace tools { class Config2Json : public Tool { public: - Config2Json(int argc, char *argv[]) : - Tool(argc, argv, "conf2json") - { } + Config2Json(int argc, char *argv[]) : Tool(argc, argv, "conf2json") {} protected: + void usage() { + std::cout << "Usage: conf2json input.conf > output.json" << std::endl + << std::endl; - void usage() - { - std::cout << "Usage: conf2json input.conf > output.json" << std::endl << std::endl; + printCopyright(); + } - printCopyright(); - } + int main() { + int ret; + config_t cfg; + config_setting_t *cfg_root; + json_t *json; - int main() - { - int ret; - config_t cfg; - config_setting_t *cfg_root; - json_t *json; + if (argc != 2) { + usage(); + exit(EXIT_FAILURE); + } - if (argc != 2) { - usage(); - exit(EXIT_FAILURE); - } + FILE *f = fopen(argv[1], "r"); + if (f == nullptr) + return -1; - FILE *f = fopen(argv[1], "r"); - if (f == nullptr) - return -1; + const char *confdir = dirname(argv[1]); - const char *confdir = dirname(argv[1]); + config_init(&cfg); - config_init(&cfg); + config_set_include_dir(&cfg, confdir); - config_set_include_dir(&cfg, confdir); + ret = config_read(&cfg, f); + if (ret != CONFIG_TRUE) + return -2; - ret = config_read(&cfg, f); - if (ret != CONFIG_TRUE) - return -2; + cfg_root = config_root_setting(&cfg); - cfg_root = config_root_setting(&cfg); + json = config_to_json(cfg_root); + if (!json) + return -3; - json = config_to_json(cfg_root); - if (!json) - return -3; + ret = json_dumpf(json, stdout, JSON_INDENT(2)); + fflush(stdout); + if (ret) + return ret; - ret = json_dumpf(json, stdout, JSON_INDENT(2)); fflush(stdout); - if (ret) - return ret; + json_decref(json); + config_destroy(&cfg); - json_decref(json); - config_destroy(&cfg); - - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Config2Json t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Config2Json t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-convert.cpp b/src/villas-convert.cpp index 14d248c95..89b28166e 100644 --- a/src/villas-convert.cpp +++ b/src/villas-convert.cpp @@ -8,16 +8,16 @@ #include #include -#include -#include -#include +#include #include #include -#include -#include -#include +#include #include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; @@ -29,144 +29,139 @@ namespace tools { class Convert : public Tool { public: - Convert(int argc, char *argv[]) : - Tool(argc, argv, "convert"), - dtypes("64f") - { - int ret; + Convert(int argc, char *argv[]) : Tool(argc, argv, "convert"), dtypes("64f") { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); - for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) { - dirs[i].name = i == 0 ? "in" : "out"; - dirs[i].format = "villas.human"; - } - } + for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) { + dirs[i].name = i == 0 ? "in" : "out"; + dirs[i].format = "villas.human"; + } + } protected: - std::string dtypes; + std::string dtypes; - struct { - std::string name; - std::string format; - Format *formatter; - } dirs[2]; + struct { + std::string name; + std::string format; + Format *formatter; + } dirs[2]; - void usage() - { - std::cout << "Usage: villas-convert [OPTIONS]" << std::endl - << " OPTIONS are:" << std::endl - << " -i FMT set the input format" << std::endl - << " -o FMT set the output format" << std::endl - << " -t DT the data-type format string" << std::endl - << " -d LVL set debug log level to LVL" << std::endl - << " -h show this usage information" << std::endl - << " -V show the version of the tool" << std::endl << std::endl; + void usage() { + std::cout << "Usage: villas-convert [OPTIONS]" << std::endl + << " OPTIONS are:" << std::endl + << " -i FMT set the input format" << std::endl + << " -o FMT set the output format" << std::endl + << " -t DT the data-type format string" << std::endl + << " -d LVL set debug log level to LVL" << std::endl + << " -h show this usage information" << std::endl + << " -V show the version of the tool" + << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - // Parse optional command line arguments - int c; - while ((c = getopt(argc, argv, "Vhd:i:o:t:")) != -1) { - switch (c) { - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + void parse() { + // Parse optional command line arguments + int c; + while ((c = getopt(argc, argv, "Vhd:i:o:t:")) != -1) { + switch (c) { + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'i': - dirs[0].format = optarg; - break; + case 'i': + dirs[0].format = optarg; + break; - case 'o': - dirs[1].format = optarg; - break; + case 'o': + dirs[1].format = optarg; + break; - case 't': - dtypes = optarg; - break; + case 't': + dtypes = optarg; + break; - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } + } - if (argc != optind) { - usage(); - exit(EXIT_FAILURE); - } - } + if (argc != optind) { + usage(); + exit(EXIT_FAILURE); + } + } - int main() - { - int ret; + int main() { + int ret; - for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) { - json_t *json_format; - json_error_t err; - std::string format = dirs[i].format; + for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) { + json_t *json_format; + json_error_t err; + std::string format = dirs[i].format; - // Try parsing format config as JSON - json_format = json_loads(format.c_str(), 0, &err); - dirs[i].formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(format); - if (!dirs[i].formatter) - throw RuntimeError("Failed to initialize format: {}", dirs[i].name); + // Try parsing format config as JSON + json_format = json_loads(format.c_str(), 0, &err); + dirs[i].formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(format); + if (!dirs[i].formatter) + throw RuntimeError("Failed to initialize format: {}", dirs[i].name); - dirs[i].formatter->start(dtypes); - } + dirs[i].formatter->start(dtypes); + } - // Line based formats are processed sample-by-sample - // while for others, we process them in chunks of 128 samples - auto isLine = dynamic_cast(dirs[0].formatter) != nullptr; - auto cnt = isLine ? 1 : 128; + // Line based formats are processed sample-by-sample + // while for others, we process them in chunks of 128 samples + auto isLine = dynamic_cast(dirs[0].formatter) != nullptr; + auto cnt = isLine ? 1 : 128; - // Initialize memory - struct Pool pool; - ret = pool_init(&pool, cnt, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory::heap); - if (ret) - throw RuntimeError("Failed to allocate memory for pool."); + // Initialize memory + struct Pool pool; + ret = pool_init(&pool, cnt, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), + &memory::heap); + if (ret) + throw RuntimeError("Failed to allocate memory for pool."); - struct Sample *smps[cnt]; - ret = sample_alloc_many(&pool, smps, cnt); - if (ret < 0) - throw MemoryAllocationError(); + struct Sample *smps[cnt]; + ret = sample_alloc_many(&pool, smps, cnt); + if (ret < 0) + throw MemoryAllocationError(); - while (!feof(stdin)) { - ret = dirs[0].formatter->scan(stdin, smps, cnt); - if (ret == 0) - continue; - else if (ret < 0) - break; + while (!feof(stdin)) { + ret = dirs[0].formatter->scan(stdin, smps, cnt); + if (ret == 0) + continue; + else if (ret < 0) + break; - dirs[1].formatter->print(stdout, smps, ret); - } + dirs[1].formatter->print(stdout, smps, ret); + } - for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) - delete dirs[i].formatter; + for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) + delete dirs[i].formatter; - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Convert t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Convert t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-graph.cpp b/src/villas-graph.cpp index cc368c6cd..77116880b 100644 --- a/src/villas-graph.cpp +++ b/src/villas-graph.cpp @@ -7,22 +7,22 @@ #include -#include #include +#include +#include #include #include -#include using namespace villas; struct GVC_s { - GVCOMMON_t common; + GVCOMMON_t common; - char *config_path; - bool config_found; + char *config_path; + bool config_found; - char **input_filenames; // gvParseArgs + char **input_filenames; // gvParseArgs }; namespace villas { @@ -32,105 +32,95 @@ namespace tools { class Graph : public Tool { public: - Graph(int argc, char *argv[]) : - Tool(argc, argv, "graph", { SIGUSR1, SIGINT }), - gvc(nullptr), - graph(nullptr) - { - int ret; + Graph(int argc, char *argv[]) + : Tool(argc, argv, "graph", {SIGUSR1, SIGINT}), gvc(nullptr), + graph(nullptr) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); - this->argv[0] = (char *) "neato"; // Default layout engine + this->argv[0] = (char *)"neato"; // Default layout engine - gvc = gvContext(); - } + gvc = gvContext(); + } - ~Graph() - { - gvFreeContext(gvc); - } + ~Graph() { gvFreeContext(gvc); } protected: - GVC_t *gvc; - graph_t *graph; + GVC_t *gvc; + graph_t *graph; - std::string configFilename; + std::string configFilename; - void usage() - { - std::cout << "Usage: villas-graph [OPTIONS]" << std::endl - << "For OPTIONS see dot(1)."; + void usage() { + std::cout << "Usage: villas-graph [OPTIONS]" << std::endl + << "For OPTIONS see dot(1)."; - printCopyright(); - } + printCopyright(); + } - void parse() - { - gvParseArgs(gvc, argc, argv); + void parse() { + gvParseArgs(gvc, argc, argv); - std::list filenames; - int i; - for (i = 0; gvc->input_filenames[i]; i++) - filenames.emplace_back(gvc->input_filenames[i]); + std::list filenames; + int i; + for (i = 0; gvc->input_filenames[i]; i++) + filenames.emplace_back(gvc->input_filenames[i]); - if (i == 0) - throw RuntimeError("No configuration file given!"); + if (i == 0) + throw RuntimeError("No configuration file given!"); - configFilename = filenames.front(); - } + configFilename = filenames.front(); + } - virtual - void handler(int signal, siginfo_t *siginfp, void *) - { + virtual void handler(int signal, siginfo_t *siginfp, void *) { #ifndef _WIN32 - switch (signal) { - case SIGINT: - // If interrupted we try to produce a partial rendering before exiting - if (graph) - gvRenderJobs(gvc, graph); - break; + switch (signal) { + case SIGINT: + // If interrupted we try to produce a partial rendering before exiting + if (graph) + gvRenderJobs(gvc, graph); + break; - case SIGUSR1: - // Note that we don't call gvFinalize() so that we don't start event-driven - // devices like -Tgtk or -Txlib */ - exit(gvFreeContext(gvc)); - break; + case SIGUSR1: + // Note that we don't call gvFinalize() so that we don't start event-driven + // devices like -Tgtk or -Txlib */ + exit(gvFreeContext(gvc)); + break; - default: { } - } + default: { + } + } #endif // _WIN32 - } + } - int main() - { - int ret; + int main() { + int ret; - villas::node::SuperNode sn; + villas::node::SuperNode sn; - sn.parse(configFilename); - sn.check(); - sn.prepare(); + sn.parse(configFilename); + sn.check(); + sn.prepare(); - graph = sn.getGraph(); + graph = sn.getGraph(); - ret = gvLayoutJobs(gvc, graph); // Take layout engine from command line - if (ret) - return ret; + ret = gvLayoutJobs(gvc, graph); // Take layout engine from command line + if (ret) + return ret; - return gvRenderJobs(gvc, graph); - } + return gvRenderJobs(gvc, graph); + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - node::tools::Graph t(argc, argv); +int main(int argc, char *argv[]) { + node::tools::Graph t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-hook.cpp b/src/villas-hook.cpp index 240ff0a32..97b41782e 100644 --- a/src/villas-hook.cpp +++ b/src/villas-hook.cpp @@ -5,25 +5,25 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include -#include -#include -#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include #include +#include #include #include +#include +#include +#include +#include +#include +#include using namespace villas; using namespace villas::node; @@ -36,286 +36,276 @@ namespace tools { class Hook : public Tool { public: - Hook(int argc, char *argv[]) : - Tool(argc, argv, "hook"), - stop(false), - input_format("villas.human"), - dtypes("64f"), - p(), - input(), - output(), - cnt(1) - { - int ret; + Hook(int argc, char *argv[]) + : Tool(argc, argv, "hook"), stop(false), input_format("villas.human"), + dtypes("64f"), p(), input(), output(), cnt(1) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); - config = json_object(); - } + config = json_object(); + } - ~Hook() - { - json_decref(config); - } + ~Hook() { json_decref(config); } protected: + std::atomic stop; - std::atomic stop; + std::string hook; - std::string hook; + std::string output_format; + std::string input_format; + std::string dtypes; - std::string output_format; - std::string input_format; - std::string dtypes; + struct Pool p; + Format *input; + Format *output; - struct Pool p; - Format *input; - Format *output; + int cnt; - int cnt; + json_t *config; - json_t *config; + void handler(int signal, siginfo_t *sinfo, void *ctx) { stop = true; } - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - stop = true; - } + void usage() { + std::cout << "Usage: villas-hook [OPTIONS] NAME" << std::endl + << " NAME the name of the hook function" << std::endl + << " PARAM* a string of configuration settings for the hook" + << std::endl + << " OPTIONS is one or more of the following options:" + << std::endl + << " -c CONFIG a JSON file containing just the hook " + "configuration" + << std::endl + << " -f FMT the input data format" << std::endl + << " -F FMT the output data format (defaults to " + "input format)" + << std::endl + << " -t DT the data-type format string" << std::endl + << " -d LVL set debug level to LVL" << std::endl + << " -v CNT process CNT smps at once" << std::endl + << " -o PARAM=VALUE provide parameters for hook configuration" + << std::endl + << " -h show this help" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl; - void usage() - { - std::cout << "Usage: villas-hook [OPTIONS] NAME" << std::endl - << " NAME the name of the hook function" << std::endl - << " PARAM* a string of configuration settings for the hook" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -c CONFIG a JSON file containing just the hook configuration" << std::endl - << " -f FMT the input data format" << std::endl - << " -F FMT the output data format (defaults to input format)" << std::endl - << " -t DT the data-type format string" << std::endl - << " -d LVL set debug level to LVL" << std::endl - << " -v CNT process CNT smps at once" << std::endl - << " -o PARAM=VALUE provide parameters for hook configuration" << std::endl - << " -h show this help" << std::endl - << " -V show the version of the tool" << std::endl << std::endl; + std::cout << "Supported hooks:" << std::endl; + for (Plugin *p : registry->lookup()) + std::cout << " - " << *p << ": " << p->getDescription() << std::endl; + std::cout << std::endl; - std::cout << "Supported hooks:" << std::endl; - for (Plugin *p : registry->lookup()) - std::cout << " - " << *p << ": " << p->getDescription() << std::endl; - std::cout << std::endl; + std::cout << "Supported IO formats:" << std::endl; + for (Plugin *p : registry->lookup()) + std::cout << " - " << *p << ": " << p->getDescription() << std::endl; + std::cout << std::endl; - std::cout << "Supported IO formats:" << std::endl; - for (Plugin *p : registry->lookup()) - std::cout << " - " << *p << ": " << p->getDescription() << std::endl; - std::cout << std::endl; + std::cout << "Example:" << std::endl + << " villas-signal random | villas-hook skip_first seconds=10" + << std::endl + << std::endl; - std::cout << "Example:" << std::endl - << " villas-signal random | villas-hook skip_first seconds=10" << std::endl - << std::endl; + printCopyright(); + } - printCopyright(); - } + void parse() { + int ret; + std::string file; - void parse() - { - int ret; - std::string file; + // Parse optional command line arguments + int c; + char *endptr; + while ((c = getopt(argc, argv, "Vhv:d:f:F:t:o:c:")) != -1) { + switch (c) { + case 'c': + file = optarg; + break; - // Parse optional command line arguments - int c; - char *endptr; - while ((c = getopt(argc, argv, "Vhv:d:f:F:t:o:c:")) != -1) { - switch (c) { - case 'c': - file = optarg; - break; + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'f': + input_format = optarg; + break; - case 'f': - input_format = optarg; - break; + case 'F': + output_format = optarg; + break; - case 'F': - output_format = optarg; - break; + case 't': + dtypes = optarg; + break; - case 't': - dtypes = optarg; - break; + case 'v': + cnt = strtoul(optarg, &endptr, 0); + goto check; - case 'v': - cnt = strtoul(optarg, &endptr, 0); - goto check; + case 'd': + logging.setLevel(optarg); + break; - case 'd': - logging.setLevel(optarg); - break; + case 'o': + ret = json_object_extend_str(config, optarg); + if (ret) + throw RuntimeError("Invalid option: {}", optarg); + break; - case 'o': - ret = json_object_extend_str(config, optarg); - if (ret) - throw RuntimeError("Invalid option: {}", optarg); - break; + case '?': + case 'h': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - case '?': - case 'h': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + continue; - continue; + check: + if (optarg == endptr) + throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, + optarg); + } -check: if (optarg == endptr) - throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg); + if (output_format.empty()) + output_format = input_format; - } + if (!file.empty()) { + json_error_t err; + json_t *j = json_load_file(file.c_str(), 0, &err); + if (!j) + throw JanssonParseError(err); - if (output_format.empty()) - output_format = input_format; + json_object_update_missing(config, j); + } - if (!file.empty()) { - json_error_t err; - json_t *j = json_load_file(file.c_str(), 0, &err); - if (!j) - throw JanssonParseError(err); + if (argc < optind + 1) { + usage(); + exit(EXIT_FAILURE); + } - json_object_update_missing(config, j); - } + hook = argv[optind]; + } - if (argc < optind + 1) { - usage(); - exit(EXIT_FAILURE); - } + int main() { + int ret, recv, sent; + struct Sample *smps[cnt]; - hook = argv[optind]; - } + if (cnt < 1) + throw RuntimeError("Vectorize option must be greater than 0"); - int main() - { - int ret, recv, sent; - struct Sample *smps[cnt]; + ret = pool_init(&p, 10 * cnt, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH)); + if (ret) + throw RuntimeError("Failed to initilize memory pool"); - if (cnt < 1) - throw RuntimeError("Vectorize option must be greater than 0"); + // Initialize IO + struct desc { + std::string dir; + std::string format; + Format **formatter; + }; + std::list descs = {{"in", input_format.c_str(), &input}, + {"out", output_format.c_str(), &output}}; - ret = pool_init(&p, 10 * cnt, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH)); - if (ret) - throw RuntimeError("Failed to initilize memory pool"); + for (auto &d : descs) { + json_t *json_format; + json_error_t err; - // Initialize IO - struct desc { - std::string dir; - std::string format; - Format **formatter; - }; - std::list descs = { - { "in", input_format.c_str(), &input }, - { "out", output_format.c_str(), &output } - }; + // Try parsing format config as JSON + json_format = json_loads(d.format.c_str(), 0, &err); + (*d.formatter) = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(d.format); + if (!(*d.formatter)) + throw RuntimeError("Failed to initialize {} IO", d.dir); - for (auto &d : descs) { - json_t *json_format; - json_error_t err; + (*d.formatter)->start(dtypes, (int)SampleFlags::HAS_ALL); + } - // Try parsing format config as JSON - json_format = json_loads(d.format.c_str(), 0, &err); - (*d.formatter) = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(d.format); - if (!(*d.formatter)) - throw RuntimeError("Failed to initialize {} IO", d.dir); + // Initialize hook + auto hf = plugin::registry->lookup(hook); + if (!hf) + throw RuntimeError("Unknown hook function '{}'", hook); - (*d.formatter)->start(dtypes, (int) SampleFlags::HAS_ALL); - } + auto h = hf->make(nullptr, nullptr); + if (!h) + throw RuntimeError("Failed to initialize hook"); - // Initialize hook - auto hf = plugin::registry->lookup(hook); - if (!hf) - throw RuntimeError("Unknown hook function '{}'", hook); + h->parse(config); + h->check(); + h->prepare(input->getSignals()); + h->start(); - auto h = hf->make(nullptr, nullptr); - if (!h) - throw RuntimeError("Failed to initialize hook"); + while (!stop && !feof(stdin)) { + ret = sample_alloc_many(&p, smps, cnt); + if (ret != cnt) + throw RuntimeError("Failed to allocate {} smps from pool", cnt); - h->parse(config); - h->check(); - h->prepare(input->getSignals()); - h->start(); + recv = input->scan(stdin, smps, cnt); + if (recv < 0) + throw RuntimeError("Failed to read from stdin"); - while (!stop && !feof(stdin)) { - ret = sample_alloc_many(&p, smps, cnt); - if (ret != cnt) - throw RuntimeError("Failed to allocate {} smps from pool", cnt); + timespec now = time_now(); - recv = input->scan(stdin, smps, cnt); - if (recv < 0) - throw RuntimeError("Failed to read from stdin"); + logger->debug("Read {} smps from stdin", recv); - timespec now = time_now(); + unsigned send = 0; + for (int processed = 0; processed < recv; processed++) { + struct Sample *smp = smps[processed]; - logger->debug("Read {} smps from stdin", recv); + if (!(smp->flags & (int)SampleFlags::HAS_TS_RECEIVED)) { + smp->ts.received = now; + smp->flags |= (int)SampleFlags::HAS_TS_RECEIVED; + } - unsigned send = 0; - for (int processed = 0; processed < recv; processed++) { - struct Sample *smp = smps[processed]; + auto ret = h->process(smp); + switch (ret) { + using Reason = node::Hook::Reason; + case Reason::ERROR: + throw RuntimeError("Failed to process samples"); - if (!(smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)){ - smp->ts.received = now; - smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED; - } + case Reason::OK: + smps[send++] = smp; + break; - auto ret = h->process(smp); - switch (ret) { - using Reason = node::Hook::Reason; - case Reason::ERROR: - throw RuntimeError("Failed to process samples"); + case Reason::SKIP_SAMPLE: + break; - case Reason::OK: - smps[send++] = smp; - break; + case Reason::STOP_PROCESSING: + goto stop; + } - case Reason::SKIP_SAMPLE: - break; + smp->signals = h->getSignals(); + } - case Reason::STOP_PROCESSING: - goto stop; - } + stop: + sent = output->print(stdout, smps, send); + if (sent < 0) + throw RuntimeError("Failed to write to stdout"); - smp->signals = h->getSignals(); - } + sample_free_many(smps, cnt); + } -stop: sent = output->print(stdout, smps, send); - if (sent < 0) - throw RuntimeError("Failed to write to stdout"); + h->stop(); - sample_free_many(smps, cnt); - } + for (auto &d : descs) + delete (*d.formatter); - h->stop(); + sample_free_many(smps, cnt); - for (auto &d : descs) - delete (*d.formatter); + ret = pool_destroy(&p); + if (ret) + throw RuntimeError("Failed to destroy memory pool"); - sample_free_many(smps, cnt); - - ret = pool_destroy(&p); - if (ret) - throw RuntimeError("Failed to destroy memory pool"); - - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Hook t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Hook t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-node.cpp b/src/villas-node.cpp index ca2212075..5886777f9 100644 --- a/src/villas-node.cpp +++ b/src/villas-node.cpp @@ -8,34 +8,34 @@ #include #include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include +#include +#include #include -#include -#include #include +#include +#include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef WITH_NODE_OPAL - #include +#include #endif using namespace villas; @@ -49,168 +49,172 @@ namespace tools { class Node : public Tool { public: - Node(int argc, char *argv[]) : - Tool(argc, argv, "node") - { } + Node(int argc, char *argv[]) : Tool(argc, argv, "node") {} protected: - SuperNode sn; + SuperNode sn; - std::string uri; - bool showCapabilities = false; + std::string uri; + bool showCapabilities = false; - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - switch (signal) { - case SIGALRM: - logger->info("Reached timeout. Terminating..."); - break; + void handler(int signal, siginfo_t *sinfo, void *ctx) { + switch (signal) { + case SIGALRM: + logger->info("Reached timeout. Terminating..."); + break; - default: - logger->info("Received {} signal. Terminating...", strsignal(signal)); - } + default: + logger->info("Received {} signal. Terminating...", strsignal(signal)); + } - sn.setState(State::STOPPING); - } + sn.setState(State::STOPPING); + } - void usage() - { - std::cout << "Usage: villas-node [OPTIONS] [CONFIG]" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -h show this usage information" << std::endl - << " -d LVL set logging level" << std::endl - << " -C show capabilities in JSON format" << std::endl - << " -V show the version of the tool" << std::endl << std::endl - << " CONFIG is the path to an optional configuration file" << std::endl - << " if omitted, VILLASnode will start without a configuration" << std::endl - << " and wait for provisioning over the web interface." << std::endl << std::endl + void usage() { + std::cout + << "Usage: villas-node [OPTIONS] [CONFIG]" << std::endl + << " OPTIONS is one or more of the following options:" << std::endl + << " -h show this usage information" << std::endl + << " -d LVL set logging level" << std::endl + << " -C show capabilities in JSON format" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl + << " CONFIG is the path to an optional configuration file" << std::endl + << " if omitted, VILLASnode will start without a configuration" + << std::endl + << " and wait for provisioning over the web interface." + << std::endl + << std::endl #ifdef WITH_NODE_OPAL - << "Usage: villas-node OPAL_ASYNC_SHMEM_NAME OPAL_ASYNC_SHMEM_SIZE OPAL_PRINT_SHMEM_NAME" << std::endl - << " This type of invocation is used by OPAL-RT Asynchronous processes." << std::endl - << " See in the RT-LAB User Guide for more information." << std::endl << std::endl + << "Usage: villas-node OPAL_ASYNC_SHMEM_NAME OPAL_ASYNC_SHMEM_SIZE " + "OPAL_PRINT_SHMEM_NAME" + << std::endl + << " This type of invocation is used by OPAL-RT Asynchronous " + "processes." + << std::endl + << " See in the RT-LAB User Guide for more information." << std::endl + << std::endl #endif // WITH_NODE_OPAL - << "Supported node-types:" << std::endl; - for (auto p : registry->lookup()) { - if (!p->isHidden()) - std::cout << " - " << std::left << std::setw(18) << p->getName() << p->getDescription() << std::endl; - } - std::cout << std::endl; + << "Supported node-types:" << std::endl; + for (auto p : registry->lookup()) { + if (!p->isHidden()) + std::cout << " - " << std::left << std::setw(18) << p->getName() + << p->getDescription() << std::endl; + } + std::cout << std::endl; - std::cout << "Supported IO formats:" << std::endl; - for (auto p : registry->lookup()) { - if (!p->isHidden()) - std::cout << " - " << std::left << std::setw(18) << p->getName() << p->getDescription() << std::endl; - } - std::cout << std::endl; + std::cout << "Supported IO formats:" << std::endl; + for (auto p : registry->lookup()) { + if (!p->isHidden()) + std::cout << " - " << std::left << std::setw(18) << p->getName() + << p->getDescription() << std::endl; + } + std::cout << std::endl; #ifdef WITH_HOOKS - std::cout << "Supported hooks:" << std::endl; - for (auto p : registry->lookup()) { - if (!p->isHidden()) - std::cout << " - " << std::left << std::setw(18) << p->getName() << p->getDescription() << std::endl; - } - std::cout << std::endl; + std::cout << "Supported hooks:" << std::endl; + for (auto p : registry->lookup()) { + if (!p->isHidden()) + std::cout << " - " << std::left << std::setw(18) << p->getName() + << p->getDescription() << std::endl; + } + std::cout << std::endl; #endif // WITH_HOOKS #ifdef WITH_API - std::cout << "Supported API commands:" << std::endl; - for (auto p : registry->lookup()) { - if (!p->isHidden()) - std::cout << " - " << std::left << std::setw(18) << p->getName() << p->getDescription() << std::endl; - } - std::cout << std::endl; + std::cout << "Supported API commands:" << std::endl; + for (auto p : registry->lookup()) { + if (!p->isHidden()) + std::cout << " - " << std::left << std::setw(18) << p->getName() + << p->getDescription() << std::endl; + } + std::cout << std::endl; #endif // WITH_API - printCopyright(); - } + printCopyright(); + } - void parse() - { - // Check arguments + void parse() { + // Check arguments #ifdef WITH_NODE_OPAL - if (argc != 4) { - usage(); - exit(EXIT_FAILURE); - } + if (argc != 4) { + usage(); + exit(EXIT_FAILURE); + } - opal_register_region(argc, argv); + opal_register_region(argc, argv); - uri = "villas-node.conf"; + uri = "villas-node.conf"; #else - // Parse optional command line arguments - int c; - while ((c = getopt(argc, argv, "hCVd:")) != -1) { - switch (c) { - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + // Parse optional command line arguments + int c; + while ((c = getopt(argc, argv, "hCVd:")) != -1) { + switch (c) { + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'C': - showCapabilities = true; - break; + case 'C': + showCapabilities = true; + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; - } + continue; + } - if (argc == optind + 1) - uri = argv[optind]; - else if (argc != optind) { - usage(); - exit(EXIT_FAILURE); - } + if (argc == optind + 1) + uri = argv[optind]; + else if (argc != optind) { + usage(); + exit(EXIT_FAILURE); + } #endif // ENABLE_OPAL_ASYNC - } + } - int main() - { - return showCapabilities - ? capabilities() - : daemon(); - } + int main() { return showCapabilities ? capabilities() : daemon(); } - int capabilities() { - auto *json_caps = getCapabilities(); + int capabilities() { + auto *json_caps = getCapabilities(); - json_dumpf(json_caps, stdout, JSON_INDENT(4)); + json_dumpf(json_caps, stdout, JSON_INDENT(4)); - return 0; - } + return 0; + } - int daemon() { - if (!uri.empty()) - sn.parse(uri); - else - logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance."); + int daemon() { + if (!uri.empty()) + sn.parse(uri); + else + logger->warn("No configuration file specified. Starting unconfigured. " + "Use the API to configure this instance."); - sn.check(); - sn.prepare(); - sn.start(); - sn.run(); - sn.stop(); + sn.check(); + sn.prepare(); + sn.start(); + sn.run(); + sn.stop(); - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Node t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Node t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-pipe.cpp b/src/villas-pipe.cpp index d7b2baa0d..14d575e46 100644 --- a/src/villas-pipe.cpp +++ b/src/villas-pipe.cpp @@ -7,28 +7,27 @@ #include #include -#include #include +#include -#include -#include #include +#include +#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include +#include +#include #include #include -#include +#include +#include +#include #include +#include +#include +#include #include +#include namespace villas { namespace node { @@ -39,482 +38,485 @@ class Pipe; class PipeDirection { protected: - struct Pool pool; - Node *node; - Format *formatter; + struct Pool pool; + Node *node; + Format *formatter; - std::thread thread; - Logger logger; + std::thread thread; + Logger logger; + + bool stop; + bool enabled; + int limit; + int count; - bool stop; - bool enabled; - int limit; - int count; public: - PipeDirection(Node *n, Format *fmt, bool en, int lim, const std::string &name) : - node(n), - formatter(fmt), - stop(false), - enabled(en), - limit(lim), - count(0) - { - auto loggerName = fmt::format("pipe:{}", name); - logger = logging.get(loggerName); + PipeDirection(Node *n, Format *fmt, bool en, int lim, const std::string &name) + : node(n), formatter(fmt), stop(false), enabled(en), limit(lim), + count(0) { + auto loggerName = fmt::format("pipe:{}", name); + logger = logging.get(loggerName); - // Initialize memory - unsigned pool_size = LOG2_CEIL(MAX(node->out.vectorize, node->in.vectorize)); + // Initialize memory + unsigned pool_size = + LOG2_CEIL(MAX(node->out.vectorize, node->in.vectorize)); - int ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), node->getMemoryType()); - if (ret < 0) - throw RuntimeError("Failed to allocate memory for pool."); - } + int ret = pool_init(&pool, pool_size, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), + node->getMemoryType()); + if (ret < 0) + throw RuntimeError("Failed to allocate memory for pool."); + } - ~PipeDirection() - { - int ret __attribute__((unused)); + ~PipeDirection() { + int ret __attribute__((unused)); - ret = pool_destroy(&pool); - } + ret = pool_destroy(&pool); + } - virtual - void run() = 0; + virtual void run() = 0; - void startThread() - { - stop = false; + void startThread() { + stop = false; - if (enabled) - thread = std::thread(&PipeDirection::run, this); - } + if (enabled) + thread = std::thread(&PipeDirection::run, this); + } - void stopThread() - { - stop = true; + void stopThread() { + stop = true; - if (enabled) { - // We send a SIGUSR2 to the threads to unblock their blocking read() syscalls - pthread_kill(thread.native_handle(), SIGUSR2); - thread.join(); - } - } + if (enabled) { + // We send a SIGUSR2 to the threads to unblock their blocking read() syscalls + pthread_kill(thread.native_handle(), SIGUSR2); + thread.join(); + } + } }; class PipeSendDirection : public PipeDirection { - friend Pipe; + friend Pipe; public: - PipeSendDirection(Node *n, Format *i, bool en = true, int lim = -1) : - PipeDirection(n, i, en, lim, "send") - { } + PipeSendDirection(Node *n, Format *i, bool en = true, int lim = -1) + : PipeDirection(n, i, en, lim, "send") {} - virtual - void run() - { - logger->debug("Send thread started"); + virtual void run() { + logger->debug("Send thread started"); - unsigned last_sequenceno = 0; - int scanned, sent, allocated; + unsigned last_sequenceno = 0; + int scanned, sent, allocated; - struct Sample *smps[node->out.vectorize]; + struct Sample *smps[node->out.vectorize]; - while (!stop) { - allocated = sample_alloc_many(&pool, smps, node->out.vectorize); - if (allocated < 0) - throw RuntimeError("Failed to get {} samples out of send pool.", node->out.vectorize); - else if (allocated < (int) node->out.vectorize) - logger->warn("Send pool underrun"); + while (!stop) { + allocated = sample_alloc_many(&pool, smps, node->out.vectorize); + if (allocated < 0) + throw RuntimeError("Failed to get {} samples out of send pool.", + node->out.vectorize); + else if (allocated < (int)node->out.vectorize) + logger->warn("Send pool underrun"); - scanned = formatter->scan(stdin, smps, allocated); - if (scanned < 0) { - if (!stop) - logger->warn("Failed to read from stdin"); - } + scanned = formatter->scan(stdin, smps, allocated); + if (scanned < 0) { + if (!stop) + logger->warn("Failed to read from stdin"); + } - // Fill in missing sequence numbers - for (int i = 0; i < scanned; i++) { - if (smps[i]->flags & (int) SampleFlags::HAS_SEQUENCE) - last_sequenceno = smps[i]->sequence; - else - smps[i]->sequence = last_sequenceno++; - } + // Fill in missing sequence numbers + for (int i = 0; i < scanned; i++) { + if (smps[i]->flags & (int)SampleFlags::HAS_SEQUENCE) + last_sequenceno = smps[i]->sequence; + else + smps[i]->sequence = last_sequenceno++; + } - sent = node->write(smps, scanned); + sent = node->write(smps, scanned); - sample_decref_many(smps, allocated); + sample_decref_many(smps, allocated); - count += sent; - if (limit > 0 && count >= limit) - goto leave_limit; + count += sent; + if (limit > 0 && count >= limit) + goto leave_limit; - if (feof(stdin)) - goto leave_eof; - } + if (feof(stdin)) + goto leave_eof; + } - goto leave; + goto leave; -leave_eof: - logger->info("Reached end-of-file."); - raise(SIGUSR1); - goto leave; + leave_eof: + logger->info("Reached end-of-file."); + raise(SIGUSR1); + goto leave; -leave_limit: - logger->info("Reached send limit."); - raise(SIGUSR1); + leave_limit: + logger->info("Reached send limit."); + raise(SIGUSR1); -leave: - logger->debug("Send thread stopped"); - } + leave: + logger->debug("Send thread stopped"); + } }; class PipeReceiveDirection : public PipeDirection { - friend Pipe; + friend Pipe; public: - PipeReceiveDirection(Node *n, Format *i, bool en = true, int lim = -1) : - PipeDirection(n, i, en, lim, "recv") - { } + PipeReceiveDirection(Node *n, Format *i, bool en = true, int lim = -1) + : PipeDirection(n, i, en, lim, "recv") {} - virtual - void run() - { - logger->debug("Receive thread started"); + virtual void run() { + logger->debug("Receive thread started"); - int recv, allocated = 0; - struct Sample *smps[node->in.vectorize]; + int recv, allocated = 0; + struct Sample *smps[node->in.vectorize]; - while (!stop) { - allocated = sample_alloc_many(&pool, smps, node->in.vectorize); - if (allocated < 0) - throw RuntimeError("Failed to allocate {} samples from receive pool.", node->in.vectorize); - else if (allocated < (int) node->in.vectorize) - logger->warn("Receive pool underrun: allocated only {} of {} samples", allocated, node->in.vectorize); + while (!stop) { + allocated = sample_alloc_many(&pool, smps, node->in.vectorize); + if (allocated < 0) + throw RuntimeError("Failed to allocate {} samples from receive pool.", + node->in.vectorize); + else if (allocated < (int)node->in.vectorize) + logger->warn("Receive pool underrun: allocated only {} of {} samples", + allocated, node->in.vectorize); - recv = node->read(smps, allocated); - if (recv < 0) { - if (node->getState() == State::STOPPING || stop) { - sample_decref_many(smps, allocated); - goto leave; - } + recv = node->read(smps, allocated); + if (recv < 0) { + if (node->getState() == State::STOPPING || stop) { + sample_decref_many(smps, allocated); + goto leave; + } - logger->warn("Failed to receive samples from node {}: reason={}", node->getName(), recv); - } else - formatter->print(stdout, smps, recv); + logger->warn("Failed to receive samples from node {}: reason={}", + node->getName(), recv); + } else + formatter->print(stdout, smps, recv); - sample_decref_many(smps, allocated); + sample_decref_many(smps, allocated); - count += recv; - if (limit > 0 && count >= limit) - goto leave_limit; - } + count += recv; + if (limit > 0 && count >= limit) + goto leave_limit; + } - goto leave; + goto leave; -leave_limit: - logger->info("Reached receive limit."); - raise(SIGUSR1); + leave_limit: + logger->info("Reached receive limit."); + raise(SIGUSR1); -leave: - logger->debug("Receive thread stopped"); - } + leave: + logger->debug("Receive thread stopped"); + } }; class Pipe : public Tool { public: - Pipe(int argc, char *argv[]) : - Tool(argc, argv, "pipe"), - stop(false), - formatter(), - timeout(0), - reverse(false), - format("villas.human"), - dtypes("64f"), - config_cli(json_object()) - { - send.enabled = true; - send.limit = -1; + Pipe(int argc, char *argv[]) + : Tool(argc, argv, "pipe"), stop(false), formatter(), timeout(0), + reverse(false), format("villas.human"), dtypes("64f"), + config_cli(json_object()) { + send.enabled = true; + send.limit = -1; - recv.enabled = true; - recv.limit = -1; + recv.enabled = true; + recv.limit = -1; - int ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + int ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } - ~Pipe() - { - json_decref(config_cli); - } + ~Pipe() { json_decref(config_cli); } protected: - std::atomic stop; + std::atomic stop; - SuperNode sn; // The global configuration - Format *formatter; + SuperNode sn; // The global configuration + Format *formatter; - int timeout; - bool reverse; - std::string format; - std::string dtypes; - std::string uri; - std::string nodestr; + int timeout; + bool reverse; + std::string format; + std::string dtypes; + std::string uri; + std::string nodestr; - json_t *config_cli; + json_t *config_cli; - struct { - int limit; - bool enabled; - std::unique_ptr dir; + struct { + int limit; + bool enabled; + std::unique_ptr dir; - } recv; + } recv; - struct { - int limit; - bool enabled; - std::unique_ptr dir; - } send; + struct { + int limit; + bool enabled; + std::unique_ptr dir; + } send; - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - logger->debug("Received {} signal.", strsignal(signal)); + void handler(int signal, siginfo_t *sinfo, void *ctx) { + logger->debug("Received {} signal.", strsignal(signal)); - switch (signal) { - case SIGALRM: - logger->info("Reached timeout."); - stop = true; - break; + switch (signal) { + case SIGALRM: + logger->info("Reached timeout."); + stop = true; + break; - case SIGUSR1: - if (recv.dir->enabled) { - if (recv.dir->limit < 0 && feof(stdin)) - stop = true; + case SIGUSR1: + if (recv.dir->enabled) { + if (recv.dir->limit < 0 && feof(stdin)) + stop = true; - if (recv.dir->limit > 0 && recv.dir->count >= recv.dir->limit) - stop = true; - } + if (recv.dir->limit > 0 && recv.dir->count >= recv.dir->limit) + stop = true; + } - if (send.dir->enabled && send.dir->limit > 0) { - if (send.dir->count >= send.dir->limit) - stop = true; - } - break; + if (send.dir->enabled && send.dir->limit > 0) { + if (send.dir->count >= send.dir->limit) + stop = true; + } + break; - default: - stop = true; - break; - } - } + default: + stop = true; + break; + } + } - void usage() - { - std::cout << "Usage: villas-pipe [OPTIONS] CONFIG NODE" << std::endl - << " CONFIG path to a configuration file" << std::endl - << " NODE the name of the node to which samples are sent and received from" << std::endl - << " OPTIONS are:" << std::endl - << " -f FMT set the format" << std::endl - << " -t DT the data-type format string" << std::endl - << " -o OPTION=VALUE overwrite options in config file" << std::endl - << " -x swap read / write endpoints" << std::endl - << " -s only read data from stdin and send it to node" << std::endl - << " -r only read data from node and write it to stdout" << std::endl - << " -T NUM terminate after NUM seconds" << std::endl - << " -L NUM terminate after NUM samples sent" << std::endl - << " -l NUM terminate after NUM samples received" << std::endl - << " -h show this usage information" << std::endl - << " -d set logging level" << std::endl - << " -V show the version of the tool" << std::endl << std::endl; + void usage() { + std::cout + << "Usage: villas-pipe [OPTIONS] CONFIG NODE" << std::endl + << " CONFIG path to a configuration file" << std::endl + << " NODE the name of the node to which samples are sent and " + "received from" + << std::endl + << " OPTIONS are:" << std::endl + << " -f FMT set the format" << std::endl + << " -t DT the data-type format string" << std::endl + << " -o OPTION=VALUE overwrite options in config file" << std::endl + << " -x swap read / write endpoints" << std::endl + << " -s only read data from stdin and send it to node" + << std::endl + << " -r only read data from node and write it to " + "stdout" + << std::endl + << " -T NUM terminate after NUM seconds" << std::endl + << " -L NUM terminate after NUM samples sent" << std::endl + << " -l NUM terminate after NUM samples received" + << std::endl + << " -h show this usage information" << std::endl + << " -d set logging level" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - int c, ret; - char *endptr; - while ((c = getopt(argc, argv, "Vhxrsd:l:L:T:f:t:o:")) != -1) { - switch (c) { - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + void parse() { + int c, ret; + char *endptr; + while ((c = getopt(argc, argv, "Vhxrsd:l:L:T:f:t:o:")) != -1) { + switch (c) { + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'f': - format = optarg; - break; + case 'f': + format = optarg; + break; - case 't': - dtypes = optarg; - break; + case 't': + dtypes = optarg; + break; - case 'x': - reverse = true; - break; + case 'x': + reverse = true; + break; - case 's': - recv.enabled = false; // send only - break; + case 's': + recv.enabled = false; // send only + break; - case 'r': - send.enabled = false; // receive only - break; + case 'r': + send.enabled = false; // receive only + break; - case 'l': - recv.limit = strtoul(optarg, &endptr, 10); - goto check; + case 'l': + recv.limit = strtoul(optarg, &endptr, 10); + goto check; - case 'L': - send.limit = strtoul(optarg, &endptr, 10); - goto check; + case 'L': + send.limit = strtoul(optarg, &endptr, 10); + goto check; - case 'T': - timeout = strtoul(optarg, &endptr, 10); - goto check; + case 'T': + timeout = strtoul(optarg, &endptr, 10); + goto check; - case 'o': - ret = json_object_extend_str(config_cli, optarg); - if (ret) - throw RuntimeError("Invalid option: {}", optarg); - break; + case 'o': + ret = json_object_extend_str(config_cli, optarg); + if (ret) + throw RuntimeError("Invalid option: {}", optarg); + break; - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: if (optarg == endptr) - throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg); - } + check: + if (optarg == endptr) + throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, + optarg); + } - if (argc != optind + 2) { - usage(); - exit(EXIT_FAILURE); - } + if (argc != optind + 2) { + usage(); + exit(EXIT_FAILURE); + } - uri = argv[optind]; - nodestr = argv[optind+1]; - } + uri = argv[optind]; + nodestr = argv[optind + 1]; + } - int main() - { - int ret; - Node *node; - json_t *json_format; - json_error_t err; + int main() { + int ret; + Node *node; + json_t *json_format; + json_error_t err; - logger->info("Logging level: {}", logging.getLevelName()); + logger->info("Logging level: {}", logging.getLevelName()); - if (!uri.empty()) - sn.parse(uri); - else - logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance."); + if (!uri.empty()) + sn.parse(uri); + else + logger->warn("No configuration file specified. Starting unconfigured. " + "Use the API to configure this instance."); - // Try parsing format config as JSON - json_format = json_loads(format.c_str(), 0, &err); - formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(format); - if (!formatter) - throw RuntimeError("Failed to initialize formatter"); + // Try parsing format config as JSON + json_format = json_loads(format.c_str(), 0, &err); + formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(format); + if (!formatter) + throw RuntimeError("Failed to initialize formatter"); - formatter->start(dtypes); + formatter->start(dtypes); - node = sn.getNode(nodestr); - if (!node) - throw RuntimeError("Node {} does not exist!", nodestr); + node = sn.getNode(nodestr); + if (!node) + throw RuntimeError("Node {} does not exist!", nodestr); - if (recv.enabled && !(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_READ)) - throw RuntimeError("Node {} can not receive data. Consider using send-only mode by using '-s' option", nodestr); + if (recv.enabled && !(node->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_READ)) + throw RuntimeError("Node {} can not receive data. Consider using " + "send-only mode by using '-s' option", + nodestr); - if (send.enabled && !(node->getFactory()->getFlags() & (int) NodeFactory::Flags::SUPPORTS_WRITE)) - throw RuntimeError("Node {} can not send data. Consider using receive-only mode by using '-r' option", nodestr); + if (send.enabled && !(node->getFactory()->getFlags() & + (int)NodeFactory::Flags::SUPPORTS_WRITE)) + throw RuntimeError("Node {} can not send data. Consider using " + "receive-only mode by using '-r' option", + nodestr); #if defined(WITH_NODE_WEBSOCKET) && defined(WITH_WEB) - // Only start web subsystem if villas-pipe is used with a websocket node - if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::REQUIRES_WEB) { - Web *w = sn.getWeb(); - w->start(); - } + // Only start web subsystem if villas-pipe is used with a websocket node + if (node->getFactory()->getFlags() & + (int)NodeFactory::Flags::REQUIRES_WEB) { + Web *w = sn.getWeb(); + w->start(); + } #endif // WITH_NODE_WEBSOCKET - if (reverse) - node->reverse(); + if (reverse) + node->reverse(); - ret = node->getFactory()->start(&sn); - if (ret) - throw RuntimeError("Failed to intialize node type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->start(&sn); + if (ret) + throw RuntimeError("Failed to intialize node type {}: reason={}", + node->getFactory()->getName(), ret); - sn.startInterfaces(); + sn.startInterfaces(); - ret = node->check(); - if (ret) - throw RuntimeError("Invalid node configuration"); + ret = node->check(); + if (ret) + throw RuntimeError("Invalid node configuration"); - ret = node->prepare(); - if (ret) - throw RuntimeError("Failed to prepare node {}: reason={}", node->getName(), ret); + ret = node->prepare(); + if (ret) + throw RuntimeError("Failed to prepare node {}: reason={}", + node->getName(), ret); - ret = node->start(); - if (ret) - throw RuntimeError("Failed to start node {}: reason={}", node->getName(), ret); + ret = node->start(); + if (ret) + throw RuntimeError("Failed to start node {}: reason={}", node->getName(), + ret); - recv.dir = std::make_unique(node, formatter, recv.enabled, recv.limit); - send.dir = std::make_unique(node, formatter, send.enabled, send.limit); + recv.dir = std::make_unique(node, formatter, + recv.enabled, recv.limit); + send.dir = std::make_unique(node, formatter, + send.enabled, send.limit); - recv.dir->startThread(); - send.dir->startThread(); + recv.dir->startThread(); + send.dir->startThread(); - // Arm timeout timer - alarm(timeout); + // Arm timeout timer + alarm(timeout); - while (!stop) - usleep(0.1e6); + while (!stop) + usleep(0.1e6); - /* We are stopping the node here in order to unblock the receiving threads + /* We are stopping the node here in order to unblock the receiving threads * Node::read() call and allow it to be joined(). */ - ret = node->stop(); - if (ret) - throw RuntimeError("Failed to stop node {}: reason={}", node->getName(), ret); + ret = node->stop(); + if (ret) + throw RuntimeError("Failed to stop node {}: reason={}", node->getName(), + ret); - recv.dir->stopThread(); - send.dir->stopThread(); + recv.dir->stopThread(); + send.dir->stopThread(); - sn.stopInterfaces(); + sn.stopInterfaces(); - ret = node->getFactory()->stop(); - if (ret) - throw RuntimeError("Failed to stop node type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->stop(); + if (ret) + throw RuntimeError("Failed to stop node type {}: reason={}", + node->getFactory()->getName(), ret); #if defined(WITH_NODE_WEBSOCKET) && defined(WITH_WEB) - // Only start web subsystem if villas-pipe is used with a websocket node - if (node->getFactory()->getFlags() & (int) NodeFactory::Flags::REQUIRES_WEB) { - Web *w = sn.getWeb(); - w->stop(); - } + // Only start web subsystem if villas-pipe is used with a websocket node + if (node->getFactory()->getFlags() & + (int)NodeFactory::Flags::REQUIRES_WEB) { + Web *w = sn.getWeb(); + w->stop(); + } #endif // WITH_NODE_WEBSOCKET - delete formatter; + delete formatter; - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Pipe t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Pipe t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-relay.cpp b/src/villas-relay.cpp index 3dc8e108a..a78efeb10 100644 --- a/src/villas-relay.cpp +++ b/src/villas-relay.cpp @@ -16,11 +16,11 @@ #include #include -#include #include +#include +#include #include #include -#include #include #include @@ -33,493 +33,449 @@ namespace villas { namespace node { namespace tools { -RelaySession::RelaySession(Relay *r, Identifier sid) : - identifier(sid), - connects(0) -{ - auto loggerName = fmt::format("relay:{}", sid); - logger = villas::logging.get(loggerName); +RelaySession::RelaySession(Relay *r, Identifier sid) + : identifier(sid), connects(0) { + auto loggerName = fmt::format("relay:{}", sid); + logger = villas::logging.get(loggerName); - logger->info("Session created: {}", identifier); + logger->info("Session created: {}", identifier); - sessions[sid] = this; + sessions[sid] = this; - created = time(nullptr); + created = time(nullptr); - uuid::generateFromString(uuid, identifier, r->uuid); + uuid::generateFromString(uuid, identifier, r->uuid); } -RelaySession::~RelaySession() -{ - logger->info("Session destroyed: {}", identifier); +RelaySession::~RelaySession() { + logger->info("Session destroyed: {}", identifier); - sessions.erase(identifier); + sessions.erase(identifier); } -RelaySession * RelaySession::get(Relay *r, lws *wsi) -{ - char uri[64]; +RelaySession *RelaySession::get(Relay *r, lws *wsi) { + char uri[64]; - /* We use the URI to associate this connection to a session + /* We use the URI to associate this connection to a session * Example: ws://example.com/node_1 * Will select the session with the name 'node_1' */ - // Get path of incoming request - lws_hdr_copy(wsi, uri, sizeof(uri), WSI_TOKEN_GET_URI); - if (strlen(uri) <= 1) - throw InvalidUrlException(); + // Get path of incoming request + lws_hdr_copy(wsi, uri, sizeof(uri), WSI_TOKEN_GET_URI); + if (strlen(uri) <= 1) + throw InvalidUrlException(); - Identifier sid = uri + 1; + Identifier sid = uri + 1; - auto it = sessions.find(sid); - if (it == sessions.end()) { - auto *rs = new RelaySession(r, sid); - if (!rs) - throw MemoryAllocationError(); + auto it = sessions.find(sid); + if (it == sessions.end()) { + auto *rs = new RelaySession(r, sid); + if (!rs) + throw MemoryAllocationError(); - return rs; - } - else { - auto logger = logging.get("villas-relay"); - logger->info("Found existing session: {}", sid); + return rs; + } else { + auto logger = logging.get("villas-relay"); + logger->info("Found existing session: {}", sid); - return it->second; - } + return it->second; + } } -json_t * RelaySession::toJson() const -{ - json_t *json_connections = json_array(); +json_t *RelaySession::toJson() const { + json_t *json_connections = json_array(); - for (auto it : connections) { - auto conn = it.second; + for (auto it : connections) { + auto conn = it.second; - json_array_append(json_connections, conn->toJson()); - } + json_array_append(json_connections, conn->toJson()); + } - return json_pack("{ s: s, s: s, s: o, s: I, s: i }", - "identifier", identifier.c_str(), - "uuid", uuid::toString(uuid).c_str(), - "connections", json_connections, - "created", created, - "connects", connects - ); + return json_pack("{ s: s, s: s, s: o, s: I, s: i }", "identifier", + identifier.c_str(), "uuid", uuid::toString(uuid).c_str(), + "connections", json_connections, "created", created, + "connects", connects); } std::map RelaySession::sessions; -RelayConnection::RelayConnection(Relay *r, lws *w, bool lo) : - wsi(w), - currentFrame(std::make_shared()), - outgoingFrames(), - bytes_recv(0), - bytes_sent(0), - frames_recv(0), - frames_sent(0), - loopback(lo) -{ - session = RelaySession::get(r, wsi); - session->connections[wsi] = this; - session->connects++; +RelayConnection::RelayConnection(Relay *r, lws *w, bool lo) + : wsi(w), currentFrame(std::make_shared()), outgoingFrames(), + bytes_recv(0), bytes_sent(0), frames_recv(0), frames_sent(0), + loopback(lo) { + session = RelaySession::get(r, wsi); + session->connections[wsi] = this; + session->connects++; - lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), ip, sizeof(ip)); + lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), ip, + sizeof(ip)); - created = time(nullptr); + created = time(nullptr); - session->logger->info("New connection established: {} ({})", name, ip); + session->logger->info("New connection established: {} ({})", name, ip); } -RelayConnection::~RelayConnection() -{ - session->logger->info("Connection closed: {} ({})", name, ip); +RelayConnection::~RelayConnection() { + session->logger->info("Connection closed: {} ({})", name, ip); - session->connections.erase(wsi); + session->connections.erase(wsi); - if (session->connections.empty()) - delete session; + if (session->connections.empty()) + delete session; } -json_t * RelayConnection::toJson() const -{ - return json_pack("{ s: s, s: s, s: I, s: I, s: I, s: I, s: I }", - "name", name, - "ip", ip, - "created", created, - "bytes_recv", bytes_recv, - "bytes_sent", bytes_sent, - "frames_recv", frames_recv, - "frames_sent", frames_sent - ); +json_t *RelayConnection::toJson() const { + return json_pack("{ s: s, s: s, s: I, s: I, s: I, s: I, s: I }", "name", name, + "ip", ip, "created", created, "bytes_recv", bytes_recv, + "bytes_sent", bytes_sent, "frames_recv", frames_recv, + "frames_sent", frames_sent); } -void RelayConnection::write() -{ - if (outgoingFrames.empty()) - return; +void RelayConnection::write() { + if (outgoingFrames.empty()) + return; - auto fr = outgoingFrames.front(); + auto fr = outgoingFrames.front(); - int ret = lws_write(wsi, fr->data(), fr->size(), LWS_WRITE_BINARY); - if (ret < 0) - return; + int ret = lws_write(wsi, fr->data(), fr->size(), LWS_WRITE_BINARY); + if (ret < 0) + return; - bytes_sent += fr->size(); - frames_sent++; + bytes_sent += fr->size(); + frames_sent++; - outgoingFrames.pop(); + outgoingFrames.pop(); - if (outgoingFrames.size() > 0) - lws_callback_on_writable(wsi); + if (outgoingFrames.size() > 0) + lws_callback_on_writable(wsi); } -void RelayConnection::read(void *in, size_t len) -{ - currentFrame->insert(currentFrame->end(), (uint8_t *) in, (uint8_t *) in + len); +void RelayConnection::read(void *in, size_t len) { + currentFrame->insert(currentFrame->end(), (uint8_t *)in, (uint8_t *)in + len); - bytes_recv += len; + bytes_recv += len; - if (lws_is_final_fragment(wsi)) { - frames_recv++; - session->logger->debug("Received frame, relaying to {} connections", session->connections.size() - (loopback ? 0 : 1)); + if (lws_is_final_fragment(wsi)) { + frames_recv++; + session->logger->debug("Received frame, relaying to {} connections", + session->connections.size() - (loopback ? 0 : 1)); - for (auto p : session->connections) { - auto c = p.second; + for (auto p : session->connections) { + auto c = p.second; - /* We skip the current connection in order + /* We skip the current connection in order * to avoid receiving our own data */ - if (loopback == false && c == this) - continue; + if (loopback == false && c == this) + continue; - c->outgoingFrames.push(currentFrame); + c->outgoingFrames.push(currentFrame); - lws_callback_on_writable(c->wsi); - } + lws_callback_on_writable(c->wsi); + } - currentFrame = std::make_shared(); - } + currentFrame = std::make_shared(); + } } -Relay::Relay(int argc, char *argv[]) : - Tool(argc, argv, "relay"), - stop(false), - context(nullptr), - vhost(nullptr), - loopback(false), - port(8088), - protocol("live") -{ - int ret; +Relay::Relay(int argc, char *argv[]) + : Tool(argc, argv, "relay"), stop(false), context(nullptr), vhost(nullptr), + loopback(false), port(8088), protocol("live") { + int ret; - char hname[128]; - ret = gethostname(hname, sizeof(hname)); - if (ret) - throw SystemError("Failed to get hostname"); + char hname[128]; + ret = gethostname(hname, sizeof(hname)); + if (ret) + throw SystemError("Failed to get hostname"); - hostname = hname; + hostname = hname; - // Default UUID is derived from hostname - uuid::generateFromString(uuid, hname); + // Default UUID is derived from hostname + uuid::generateFromString(uuid, hname); - ret = memory::init(0); - if (ret) - throw RuntimeError("Failed to initialize memory"); + ret = memory::init(0); + if (ret) + throw RuntimeError("Failed to initialize memory"); - // Initialize logging - lws_set_log_level(Web::lwsLogLevel(logging.getLevel()), Web::lwsLogger); + // Initialize logging + lws_set_log_level(Web::lwsLogLevel(logging.getLevel()), Web::lwsLogger); - protocols = { - { - .name = "http", - .callback = lws_callback_http_dummy, - .per_session_data_size = 0, - .rx_buffer_size = 1024 - }, - { - .name = "http-api", - .callback = httpProtocolCallback, - .per_session_data_size = 0, - .rx_buffer_size = 1024 - }, - { - .name = "live", - .callback = protocolCallback, - .per_session_data_size = sizeof(RelayConnection), - .rx_buffer_size = 0 - }, - { nullptr /* terminator */ } - }; + protocols = {{.name = "http", + .callback = lws_callback_http_dummy, + .per_session_data_size = 0, + .rx_buffer_size = 1024}, + {.name = "http-api", + .callback = httpProtocolCallback, + .per_session_data_size = 0, + .rx_buffer_size = 1024}, + {.name = "live", + .callback = protocolCallback, + .per_session_data_size = sizeof(RelayConnection), + .rx_buffer_size = 0}, + {nullptr /* terminator */}}; } -int Relay::httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - int ret; +int Relay::httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + int ret; - lws_context *ctx = lws_get_context(wsi); - void *user_ctx = lws_context_user(ctx); + lws_context *ctx = lws_get_context(wsi); + void *user_ctx = lws_context_user(ctx); - Relay *r = reinterpret_cast(user_ctx); + Relay *r = reinterpret_cast(user_ctx); - switch (reason) { - case LWS_CALLBACK_HTTP: { - unsigned char buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *end = &buf[sizeof(buf) - LWS_PRE - 1], *p = start; + switch (reason) { + case LWS_CALLBACK_HTTP: { + unsigned char buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], + *end = &buf[sizeof(buf) - LWS_PRE - 1], + *p = start; - if (lws_add_http_common_headers(wsi, HTTP_STATUS_OK, - "application/json", - LWS_ILLEGAL_HTTP_CONTENT_LEN, // no content len - &p, end)) - return 1; + if (lws_add_http_common_headers( + wsi, HTTP_STATUS_OK, "application/json", + LWS_ILLEGAL_HTTP_CONTENT_LEN, // no content len + &p, end)) + return 1; - if (lws_finalize_write_http_header(wsi, start, &p, end)) - return 1; + if (lws_finalize_write_http_header(wsi, start, &p, end)) + return 1; - // Write the body separately - lws_callback_on_writable(wsi); + // Write the body separately + lws_callback_on_writable(wsi); - return 0; - } + return 0; + } - case LWS_CALLBACK_HTTP_WRITEABLE: { - size_t len; - std::vector buf; - json_t *json_sessions, *json_body; + case LWS_CALLBACK_HTTP_WRITEABLE: { + size_t len; + std::vector buf; + json_t *json_sessions, *json_body; - json_sessions = json_array(); - for (auto it : RelaySession::sessions) { - auto &session = it.second; + json_sessions = json_array(); + for (auto it : RelaySession::sessions) { + auto &session = it.second; - json_array_append(json_sessions, session->toJson()); - } + json_array_append(json_sessions, session->toJson()); + } - json_body = json_pack("{ s: o, s: s, s: s, s: s, s: { s: b, s: i, s: s } }", - "sessions", json_sessions, - "version", PROJECT_VERSION_STR, - "hostname", r->hostname.c_str(), - "uuid", uuid::toString(r->uuid).c_str(), - "options", - "loopback", r->loopback, - "port", r->port, - "protocol", r->protocol.c_str() - ); - if (!json_body) - return -1; + json_body = json_pack("{ s: o, s: s, s: s, s: s, s: { s: b, s: i, s: s } }", + "sessions", json_sessions, "version", + PROJECT_VERSION_STR, "hostname", r->hostname.c_str(), + "uuid", uuid::toString(r->uuid).c_str(), "options", + "loopback", r->loopback, "port", r->port, "protocol", + r->protocol.c_str()); + if (!json_body) + return -1; - len = 1024; - do { - buf.resize(LWS_PRE + len); + len = 1024; + do { + buf.resize(LWS_PRE + len); - len = json_dumpb(json_body, buf.data() + LWS_PRE, buf.size() - LWS_PRE, JSON_INDENT(4)); - if (len == 0) - return -1; - } while (len > buf.size() - LWS_PRE); + len = json_dumpb(json_body, buf.data() + LWS_PRE, buf.size() - LWS_PRE, + JSON_INDENT(4)); + if (len == 0) + return -1; + } while (len > buf.size() - LWS_PRE); - ret = lws_write(wsi, (unsigned char *)(buf.data() + LWS_PRE), len, LWS_WRITE_HTTP_FINAL); - if (ret < 0) - return ret; + ret = lws_write(wsi, (unsigned char *)(buf.data() + LWS_PRE), len, + LWS_WRITE_HTTP_FINAL); + if (ret < 0) + return ret; - r->logger->info("Handled API request"); + r->logger->info("Handled API request"); - return -1; - } + return -1; + } - default: - break; - } + default: + break; + } - return lws_callback_http_dummy(wsi, reason, user, in, len); + return lws_callback_http_dummy(wsi, reason, user, in, len); } -int Relay::protocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) -{ - lws_context *ctx = lws_get_context(wsi); - void *user_ctx = lws_context_user(ctx); +int Relay::protocolCallback(lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + lws_context *ctx = lws_get_context(wsi); + void *user_ctx = lws_context_user(ctx); - Relay *r = reinterpret_cast(user_ctx); - RelayConnection *c = reinterpret_cast(user); + Relay *r = reinterpret_cast(user_ctx); + RelayConnection *c = reinterpret_cast(user); - switch (reason) { + switch (reason) { - case LWS_CALLBACK_ESTABLISHED: - try { - new (c) RelayConnection(r, wsi, r->loopback); - } - catch (const InvalidUrlException &e) { - lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (unsigned char *) "Invalid URL", strlen("Invalid URL")); + case LWS_CALLBACK_ESTABLISHED: + try { + new (c) RelayConnection(r, wsi, r->loopback); + } catch (const InvalidUrlException &e) { + lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, + (unsigned char *)"Invalid URL", strlen("Invalid URL")); - return -1; - } - break; + return -1; + } + break; - case LWS_CALLBACK_CLOSED: - c->~RelayConnection(); - break; + case LWS_CALLBACK_CLOSED: + c->~RelayConnection(); + break; - case LWS_CALLBACK_SERVER_WRITEABLE: - c->write(); - break; + case LWS_CALLBACK_SERVER_WRITEABLE: + c->write(); + break; - case LWS_CALLBACK_RECEIVE: - c->read(in, len); - break; + case LWS_CALLBACK_RECEIVE: + c->read(in, len); + break; - default: - break; - } + default: + break; + } - return 0; + return 0; } -void Relay::usage() -{ - std::cout << "Usage: villas-relay [OPTIONS]" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -d LVL set debug level" << std::endl - << " -p PORT the port number to listen on" << std::endl - << " -P PROT the websocket protocol" << std::endl - << " -l enable loopback of own data" << std::endl - << " -u UUID unique instance id" << std::endl - << " -V show version and exit" << std::endl - << " -h show usage and exit" << std::endl << std::endl; +void Relay::usage() { + std::cout << "Usage: villas-relay [OPTIONS]" << std::endl + << " OPTIONS is one or more of the following options:" << std::endl + << " -d LVL set debug level" << std::endl + << " -p PORT the port number to listen on" << std::endl + << " -P PROT the websocket protocol" << std::endl + << " -l enable loopback of own data" << std::endl + << " -u UUID unique instance id" << std::endl + << " -V show version and exit" << std::endl + << " -h show usage and exit" << std::endl + << std::endl; - printCopyright(); + printCopyright(); } -void Relay::parse() -{ - int ret; - char c, *endptr; - while ((c = getopt (argc, argv, "hVp:P:ld:u:")) != -1) { - switch (c) { - case 'd': - logging.setLevel(optarg); - lws_set_log_level(Web::lwsLogLevel(logging.getLevel()), Web::lwsLogger); - break; +void Relay::parse() { + int ret; + char c, *endptr; + while ((c = getopt(argc, argv, "hVp:P:ld:u:")) != -1) { + switch (c) { + case 'd': + logging.setLevel(optarg); + lws_set_log_level(Web::lwsLogLevel(logging.getLevel()), Web::lwsLogger); + break; - case 'p': - port = strtoul(optarg, &endptr, 10); - goto check; + case 'p': + port = strtoul(optarg, &endptr, 10); + goto check; - case 'P': - protocol = optarg; - break; + case 'P': + protocol = optarg; + break; - case 'l': - loopback = true; - break; + case 'l': + loopback = true; + break; - case 'u': - ret = uuid_parse(optarg, uuid); - if (ret) { - logger->error("Failed to parse UUID: {}", optarg); - exit(EXIT_FAILURE); - } - break; + case 'u': + ret = uuid_parse(optarg, uuid); + if (ret) { + logger->error("Failed to parse UUID: {}", optarg); + exit(EXIT_FAILURE); + } + break; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: - if (optarg == endptr) { - logger->error("Failed to parse parse option argument '-{} {}'", c, optarg); - exit(EXIT_FAILURE); - } - } + check: + if (optarg == endptr) { + logger->error("Failed to parse parse option argument '-{} {}'", c, + optarg); + exit(EXIT_FAILURE); + } + } - if (argc - optind < 0) { - usage(); - exit(EXIT_FAILURE); - } + if (argc - optind < 0) { + usage(); + exit(EXIT_FAILURE); + } } int Relay::main() { - // Start server - lws_context_creation_info ctx_info = { 0 }; + // Start server + lws_context_creation_info ctx_info = {0}; - protocols[2].name = protocol.c_str(); + protocols[2].name = protocol.c_str(); - ctx_info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - ctx_info.gid = -1; - ctx_info.uid = -1; - ctx_info.protocols = protocols.data(); + ctx_info.options = + LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + ctx_info.gid = -1; + ctx_info.uid = -1; + ctx_info.protocols = protocols.data(); #ifndef LWS_WITHOUT_EXTENSIONS - ctx_info.extensions = extensions.data(); + ctx_info.extensions = extensions.data(); #endif - ctx_info.port = port; - ctx_info.mounts = &mount; - ctx_info.user = (void *) this; + ctx_info.port = port; + ctx_info.mounts = &mount; + ctx_info.user = (void *)this; - auto lwsLogger = logging.get("lws"); + auto lwsLogger = logging.get("lws"); - context = lws_create_context(&ctx_info); - if (context == nullptr) { - lwsLogger->error("Failed to initialize server context"); - exit(EXIT_FAILURE); - } + context = lws_create_context(&ctx_info); + if (context == nullptr) { + lwsLogger->error("Failed to initialize server context"); + exit(EXIT_FAILURE); + } - vhost = lws_create_vhost(context, &ctx_info); - if (vhost == nullptr) { - lwsLogger->error("Failed to initialize virtual host"); - exit(EXIT_FAILURE); - } + vhost = lws_create_vhost(context, &ctx_info); + if (vhost == nullptr) { + lwsLogger->error("Failed to initialize virtual host"); + exit(EXIT_FAILURE); + } - while (!stop) - lws_service(context, 100); + while (!stop) + lws_service(context, 100); - return 0; + return 0; } const std::vector Relay::extensions = { #ifdef LWS_DEFLATE_FOUND - { - "permessage-deflate", - lws_extension_callback_pm_deflate, - "permessage-deflate" - }, - { - "deflate-frame", - lws_extension_callback_pm_deflate, - "deflate_frame" - }, + {"permessage-deflate", lws_extension_callback_pm_deflate, + "permessage-deflate"}, + {"deflate-frame", lws_extension_callback_pm_deflate, "deflate_frame"}, #endif // LWS_DEFLATE_FOUND - { nullptr /* terminator */ } -}; + {nullptr /* terminator */}}; const lws_http_mount Relay::mount = { - .mount_next = nullptr, // linked-list "next" - .mountpoint = "/api/v1", // mountpoint URL - .origin = nullptr, // protocol - .def = nullptr, - .protocol = "http-api", - .cgienv = nullptr, - .extra_mimetypes = nullptr, - .interpret = nullptr, - .cgi_timeout = 0, - .cache_max_age = 0, - .auth_mask = 0, - .cache_reusable = 0, - .cache_revalidate = 0, - .cache_intermediaries = 0, - .origin_protocol = LWSMPRO_CALLBACK, // dynamic - .mountpoint_len = 7, // char count - .basic_auth_login_file = nullptr, + .mount_next = nullptr, // linked-list "next" + .mountpoint = "/api/v1", // mountpoint URL + .origin = nullptr, // protocol + .def = nullptr, + .protocol = "http-api", + .cgienv = nullptr, + .extra_mimetypes = nullptr, + .interpret = nullptr, + .cgi_timeout = 0, + .cache_max_age = 0, + .auth_mask = 0, + .cache_reusable = 0, + .cache_revalidate = 0, + .cache_intermediaries = 0, + .origin_protocol = LWSMPRO_CALLBACK, // dynamic + .mountpoint_len = 7, // char count + .basic_auth_login_file = nullptr, }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Relay t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Relay t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-relay.hpp b/src/villas-relay.hpp index c33b35197..069dd1bb1 100644 --- a/src/villas-relay.hpp +++ b/src/villas-relay.hpp @@ -5,8 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include @@ -23,142 +23,130 @@ class Relay; class RelaySession; class RelayConnection; -class InvalidUrlException { }; +class InvalidUrlException {}; typedef std::string Identifier; class Frame : public std::vector { public: - Frame() { - reserve(LWS_PRE); - // lws_write() requires LWS_PRE bytes in front of the payload - insert(end(), LWS_PRE, 0); - } + Frame() { + reserve(LWS_PRE); + // lws_write() requires LWS_PRE bytes in front of the payload + insert(end(), LWS_PRE, 0); + } - uint8_t * data() { - return std::vector::data() + LWS_PRE; - } + uint8_t *data() { return std::vector::data() + LWS_PRE; } - size_type size() { - return std::vector::size() - LWS_PRE; - } + size_type size() { return std::vector::size() - LWS_PRE; } }; class RelaySession { - friend RelayConnection; - friend Relay; + friend RelayConnection; + friend Relay; protected: - time_t created; - uuid_t uuid; + time_t created; + uuid_t uuid; - Identifier identifier; - Logger logger; + Identifier identifier; + Logger logger; - std::map connections; + std::map connections; - int connects; + int connects; - static - std::map sessions; + static std::map sessions; public: - static - RelaySession * get(Relay *r, lws *wsi); + static RelaySession *get(Relay *r, lws *wsi); - RelaySession(Relay *r, Identifier sid); + RelaySession(Relay *r, Identifier sid); - ~RelaySession(); + ~RelaySession(); - json_t * toJson() const; + json_t *toJson() const; }; class RelayConnection { protected: - lws *wsi; + lws *wsi; - std::shared_ptr currentFrame; + std::shared_ptr currentFrame; - std::queue> outgoingFrames; + std::queue> outgoingFrames; - RelaySession *session; + RelaySession *session; - char name[128]; - char ip[128]; + char name[128]; + char ip[128]; - size_t created; - size_t bytes_recv; - size_t bytes_sent; + size_t created; + size_t bytes_recv; + size_t bytes_sent; - size_t frames_recv; - size_t frames_sent; + size_t frames_recv; + size_t frames_sent; - bool loopback; + bool loopback; public: - RelayConnection(Relay *r, lws *w, bool lo); - ~RelayConnection(); + RelayConnection(Relay *r, lws *w, bool lo); + ~RelayConnection(); - json_t * toJson() const; + json_t *toJson() const; - void write(); - void read(void *in, size_t len); + void write(); + void read(void *in, size_t len); }; class Relay : public Tool { public: - friend RelaySession; + friend RelaySession; - Relay(int argc, char *argv[]); + Relay(int argc, char *argv[]); protected: - std::atomic stop; + std::atomic stop; - // The libwebsockets server context. - lws_context *context; + // The libwebsockets server context. + lws_context *context; - // The libwebsockets vhost. - lws_vhost *vhost; + // The libwebsockets vhost. + lws_vhost *vhost; - bool loopback; - int port; - std::string protocol; - std::string hostname; + bool loopback; + int port; + std::string protocol; + std::string hostname; - uuid_t uuid; + uuid_t uuid; - // List of libwebsockets protocols. - std::vector protocols; + // List of libwebsockets protocols. + std::vector protocols; - // List of libwebsockets extensions. - static - const std::vector extensions; + // List of libwebsockets extensions. + static const std::vector extensions; - static - const lws_http_mount mount; + static const lws_http_mount mount; - static - void loggerCallback(int level, const char *msg); + static void loggerCallback(int level, const char *msg); - static - int httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); - static - int protocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int protocolCallback(lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); - void usage(); + void usage(); - void parse(); + void parse(); - int main(); + int main(); - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - stop = true; - } + void handler(int signal, siginfo_t *sinfo, void *ctx) { stop = true; } }; } // namespace tools diff --git a/src/villas-signal.cpp b/src/villas-signal.cpp index b50f34de5..2794333ce 100644 --- a/src/villas-signal.cpp +++ b/src/villas-signal.cpp @@ -5,23 +5,23 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include #include -#include +#include -#include -#include -#include #include #include +#include #include +#include +#include +#include #include #include -#include -#include -#include +#include +#include using namespace villas; @@ -32,294 +32,287 @@ namespace tools { class Signal : public Tool { public: - Signal(int argc, char *argv[]) : - Tool(argc, argv, "signal"), - stop(false), - node(), - formatter(nullptr), - pool(), - format("villas.human") - { - int ret; + Signal(int argc, char *argv[]) + : Tool(argc, argv, "signal"), stop(false), node(), formatter(nullptr), + pool(), format("villas.human") { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } protected: - std::atomic stop; + std::atomic stop; - Node *node; - Format *formatter; - struct Pool pool; + Node *node; + Format *formatter; + struct Pool pool; - std::string format; + std::string format; - void usage() - { - std::cout << "Usage: villas-signal [OPTIONS] SIGNAL" << std::endl - << " SIGNAL is on of the following signal types:" << std::endl - << " mixed" << std::endl - << " random" << std::endl - << " sine" << std::endl - << " triangle" << std::endl - << " square" << std::endl - << " ramp" << std::endl - << " constants" << std::endl - << " counter" << std::endl << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -d LVL set debug level" << std::endl - << " -f FMT set the format" << std::endl - << " -v NUM specifies how many values a message should contain" << std::endl - << " -r HZ how many messages per second" << std::endl - << " -n non real-time mode. do not throttle output." << std::endl - << " -F HZ the frequency of the signal" << std::endl - << " -a FLT the amplitude" << std::endl - << " -D FLT the standard deviation for 'random' signals" << std::endl - << " -o OFF the DC bias" << std::endl - << " -l NUM only send LIMIT messages and stop" << std::endl << std::endl; + void usage() { + std::cout + << "Usage: villas-signal [OPTIONS] SIGNAL" << std::endl + << " SIGNAL is on of the following signal types:" << std::endl + << " mixed" << std::endl + << " random" << std::endl + << " sine" << std::endl + << " triangle" << std::endl + << " square" << std::endl + << " ramp" << std::endl + << " constants" << std::endl + << " counter" << std::endl + << std::endl + << " OPTIONS is one or more of the following options:" << std::endl + << " -d LVL set debug level" << std::endl + << " -f FMT set the format" << std::endl + << " -v NUM specifies how many values a message should contain" + << std::endl + << " -r HZ how many messages per second" << std::endl + << " -n non real-time mode. do not throttle output." + << std::endl + << " -F HZ the frequency of the signal" << std::endl + << " -a FLT the amplitude" << std::endl + << " -D FLT the standard deviation for 'random' signals" + << std::endl + << " -o OFF the DC bias" << std::endl + << " -l NUM only send LIMIT messages and stop" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - json_t * parse_cli(int argc, char *argv[]) - { - // Default values - double rate = 10; - double frequency = 1; - double amplitude = 1; - double stddev = 0.02; - double offset = 0; - double phase = 0.0; - double pulse_low = 0.0; - double pulse_high = 1.0; - double pulse_width = 1.0; + json_t *parse_cli(int argc, char *argv[]) { + // Default values + double rate = 10; + double frequency = 1; + double amplitude = 1; + double stddev = 0.02; + double offset = 0; + double phase = 0.0; + double pulse_low = 0.0; + double pulse_high = 1.0; + double pulse_width = 1.0; - std::string type; - int rt = 1; - int values = 1; - int limit = -1; + std::string type; + int rt = 1; + int values = 1; + int limit = -1; - // Parse optional command line arguments - int c; - char *endptr; - while ((c = getopt(argc, argv, "v:r:F:f:l:a:D:no:d:hVp:")) != -1) { - switch (c) { - case 'n': - rt = 0; - break; + // Parse optional command line arguments + int c; + char *endptr; + while ((c = getopt(argc, argv, "v:r:F:f:l:a:D:no:d:hVp:")) != -1) { + switch (c) { + case 'n': + rt = 0; + break; - case 'f': - format = optarg; - break; + case 'f': + format = optarg; + break; - case 'l': - limit = strtoul(optarg, &endptr, 10); - goto check; + case 'l': + limit = strtoul(optarg, &endptr, 10); + goto check; - case 'v': - values = strtoul(optarg, &endptr, 10); - goto check; + case 'v': + values = strtoul(optarg, &endptr, 10); + goto check; - case 'r': - rate = strtof(optarg, &endptr); - goto check; + case 'r': + rate = strtof(optarg, &endptr); + goto check; - case 'o': - offset = strtof(optarg, &endptr); - goto check; + case 'o': + offset = strtof(optarg, &endptr); + goto check; - case 'F': - frequency = strtof(optarg, &endptr); - goto check; + case 'F': + frequency = strtof(optarg, &endptr); + goto check; - case 'a': - amplitude = strtof(optarg, &endptr); - goto check; + case 'a': + amplitude = strtof(optarg, &endptr); + goto check; - case 'D': - stddev = strtof(optarg, &endptr); - goto check; + case 'D': + stddev = strtof(optarg, &endptr); + goto check; - case 'p': - phase = strtof(optarg, &endptr); - goto check; + case 'p': + phase = strtof(optarg, &endptr); + goto check; - case 'w': - pulse_width = strtof(optarg, &endptr); - goto check; + case 'w': + pulse_width = strtof(optarg, &endptr); + goto check; - case 'L': - pulse_low = strtof(optarg, &endptr); - goto check; + case 'L': + pulse_low = strtof(optarg, &endptr); + goto check; - case 'H': - pulse_high = strtof(optarg, &endptr); - goto check; + case 'H': + pulse_high = strtof(optarg, &endptr); + goto check; - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: if (optarg == endptr) - logger->warn("Failed to parse parse option argument '-{} {}'", c, optarg); - } + check: + if (optarg == endptr) + logger->warn("Failed to parse parse option argument '-{} {}'", c, + optarg); + } - if (argc != optind + 1) - return nullptr; + if (argc != optind + 1) + return nullptr; - type = argv[optind]; + type = argv[optind]; - json_t *json_signals = json_array(); + json_t *json_signals = json_array(); - for (int i = 0; i < values; i++) { - json_t *json_signal = json_pack("{ s: s, s: f, s: f, s: f, s: f, s: f, s: f, s: f, s: f }", - "signal", strdup(type.c_str()), - "frequency", frequency, - "amplitude", amplitude, - "stddev", stddev, - "offset", offset, - "pulse_width", pulse_width, - "pulse_low", pulse_low, - "pulse_high", pulse_high, - "phase", phase - ); + for (int i = 0; i < values; i++) { + json_t *json_signal = json_pack( + "{ s: s, s: f, s: f, s: f, s: f, s: f, s: f, s: f, s: f }", "signal", + strdup(type.c_str()), "frequency", frequency, "amplitude", amplitude, + "stddev", stddev, "offset", offset, "pulse_width", pulse_width, + "pulse_low", pulse_low, "pulse_high", pulse_high, "phase", phase); - json_array_append_new(json_signals, json_signal); - } + json_array_append_new(json_signals, json_signal); + } - return json_pack("{ s: s, s: f, s: b, s: i, s: { s: o } }", - "type", "signal", - "rate", rate, - "realtime", rt, - "limit", limit, - "in", - "signals", json_signals - ); - } + return json_pack("{ s: s, s: f, s: b, s: i, s: { s: o } }", "type", + "signal", "rate", rate, "realtime", rt, "limit", limit, + "in", "signals", json_signals); + } - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - switch (signal) { - case SIGALRM: - logger->info("Reached timeout. Terminating..."); - break; + void handler(int signal, siginfo_t *sinfo, void *ctx) { + switch (signal) { + case SIGALRM: + logger->info("Reached timeout. Terminating..."); + break; - default: - logger->info("Received {} signal. Terminating...", strsignal(signal)); - } + default: + logger->info("Received {} signal. Terminating...", strsignal(signal)); + } - stop = true; - } + stop = true; + } - int main() - { - int ret; - json_t *json, *json_format; - json_error_t err; + int main() { + int ret; + json_t *json, *json_format; + json_error_t err; - struct Sample *t; + struct Sample *t; - node = NodeFactory::make("signal.v2"); - if (!node) - throw MemoryAllocationError(); + node = NodeFactory::make("signal.v2"); + if (!node) + throw MemoryAllocationError(); - json = parse_cli(argc, argv); - if (!json) { - usage(); - exit(EXIT_FAILURE); - } + json = parse_cli(argc, argv); + if (!json) { + usage(); + exit(EXIT_FAILURE); + } - ret = node->parse(json); - if (ret) { - usage(); - exit(EXIT_FAILURE); - } + ret = node->parse(json); + if (ret) { + usage(); + exit(EXIT_FAILURE); + } - ret = node->getFactory()->start(nullptr); - if (ret) - throw RuntimeError("Failed to intialize node type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->start(nullptr); + if (ret) + throw RuntimeError("Failed to intialize node type {}: reason={}", + node->getFactory()->getName(), ret); - ret = node->check(); - if (ret) - throw RuntimeError("Failed to verify node configuration"); + ret = node->check(); + if (ret) + throw RuntimeError("Failed to verify node configuration"); - ret = node->prepare(); - if (ret) - throw RuntimeError("Failed to prepare node {}: reason={}", node->getName(), ret); + ret = node->prepare(); + if (ret) + throw RuntimeError("Failed to prepare node {}: reason={}", + node->getName(), ret); - // Try parsing format config as JSON - json_format = json_loads(format.c_str(), 0, &err); - formatter = json_format - ? FormatFactory::make(json_format) - : FormatFactory::make(format); - if (!formatter) - throw RuntimeError("Failed to initialize output"); + // Try parsing format config as JSON + json_format = json_loads(format.c_str(), 0, &err); + formatter = json_format ? FormatFactory::make(json_format) + : FormatFactory::make(format); + if (!formatter) + throw RuntimeError("Failed to initialize output"); - formatter->start(node->getInputSignals(), ~(int) SampleFlags::HAS_OFFSET); + formatter->start(node->getInputSignals(), ~(int)SampleFlags::HAS_OFFSET); - ret = pool_init(&pool, 16, SAMPLE_LENGTH(node->getInputSignals()->size()), &memory::heap); - if (ret) - throw RuntimeError("Failed to initialize pool"); + ret = pool_init(&pool, 16, SAMPLE_LENGTH(node->getInputSignals()->size()), + &memory::heap); + if (ret) + throw RuntimeError("Failed to initialize pool"); - ret = node->start(); - if (ret) - throw RuntimeError("Failed to start node {}: reason={}", node->getName(), ret); + ret = node->start(); + if (ret) + throw RuntimeError("Failed to start node {}: reason={}", node->getName(), + ret); - while (!stop && node->getState() == State::STARTED) { - t = sample_alloc(&pool); + while (!stop && node->getState() == State::STARTED) { + t = sample_alloc(&pool); -retry: ret = node->read(&t, 1); - if (ret == 0) - goto retry; - else if (ret < 0) - goto out; + retry: + ret = node->read(&t, 1); + if (ret == 0) + goto retry; + else if (ret < 0) + goto out; - formatter->print(stdout, t); - fflush(stdout); + formatter->print(stdout, t); + fflush(stdout); -out: sample_decref(t); - } + out: + sample_decref(t); + } - ret = node->stop(); - if (ret) - throw RuntimeError("Failed to stop node"); + ret = node->stop(); + if (ret) + throw RuntimeError("Failed to stop node"); - ret = node->getFactory()->stop(); - if (ret) - throw RuntimeError("Failed to de-intialize node type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->stop(); + if (ret) + throw RuntimeError("Failed to de-intialize node type {}: reason={}", + node->getFactory()->getName(), ret); - delete node; - delete formatter; + delete node; + delete formatter; - ret = pool_destroy(&pool); - if (ret) - throw RuntimeError("Failed to destroy pool"); + ret = pool_destroy(&pool); + if (ret) + throw RuntimeError("Failed to destroy pool"); - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::Signal t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::Signal t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-test-config.cpp b/src/villas-test-config.cpp index e48976a00..ae618c666 100644 --- a/src/villas-test-config.cpp +++ b/src/villas-test-config.cpp @@ -8,13 +8,13 @@ #include #include -#include -#include #include -#include -#include -#include +#include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; @@ -26,93 +26,90 @@ namespace tools { class TestConfig : public Tool { public: - TestConfig(int argc, char *argv[]) : - Tool(argc, argv, "test-config"), - check(false), - dump(false) - { - int ret; + TestConfig(int argc, char *argv[]) + : Tool(argc, argv, "test-config"), check(false), dump(false) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } protected: - std::string uri; + std::string uri; - bool check; - bool dump; + bool check; + bool dump; - void usage() - { - std::cout << "Usage: villas-test-config [OPTIONS] CONFIG" << std::endl - << " CONFIG is the path to an optional configuration file" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -d LVL set debug level" << std::endl - << " -V show version and exit" << std::endl - << " -c perform plausability checks on config" << std::endl - << " -D dump config in JSON format" << std::endl - << " -h show usage and exit" << std::endl << std::endl; + void usage() { + std::cout << "Usage: villas-test-config [OPTIONS] CONFIG" << std::endl + << " CONFIG is the path to an optional configuration file" + << std::endl + << " OPTIONS is one or more of the following options:" + << std::endl + << " -d LVL set debug level" << std::endl + << " -V show version and exit" << std::endl + << " -c perform plausability checks on config" + << std::endl + << " -D dump config in JSON format" << std::endl + << " -h show usage and exit" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - int c; - while ((c = getopt (argc, argv, "hcVD")) != -1) { - switch (c) { - case 'c': - check = true; - break; + void parse() { + int c; + while ((c = getopt(argc, argv, "hcVD")) != -1) { + switch (c) { + case 'c': + check = true; + break; - case 'D': - dump = true; - break; + case 'D': + dump = true; + break; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } + } - if (argc - optind < 1) { - usage(); - exit(EXIT_FAILURE); - } + if (argc - optind < 1) { + usage(); + exit(EXIT_FAILURE); + } - uri = argv[optind]; - } + uri = argv[optind]; + } - int main() - { - SuperNode sn; + int main() { + SuperNode sn; - sn.parse(uri); + sn.parse(uri); - // if (check) - // sn.check(); + // if (check) + // sn.check(); - // if (dump) - // json_dumpf(sn.getConfig(), stdout, JSON_INDENT(2)); + // if (dump) + // json_dumpf(sn.getConfig(), stdout, JSON_INDENT(2)); - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::TestConfig t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::TestConfig t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-test-rtt.cpp b/src/villas-test-rtt.cpp index ffd3d09ae..6f2174289 100644 --- a/src/villas-test-rtt.cpp +++ b/src/villas-test-rtt.cpp @@ -5,29 +5,29 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include #include #include -#include -#include -#include -#include -#include #include -#include +#include +#include +#include -#include -#include -#include #include +#include +#include #include #include -#include -#include -#include +#include #include -#include +#include +#include +#include +#include -#define CLOCK_ID CLOCK_MONOTONIC +#define CLOCK_ID CLOCK_MONOTONIC using namespace villas; using namespace villas::node; @@ -39,211 +39,212 @@ namespace tools { class TestRtt : public Tool { public: - TestRtt(int argc, char *argv[]) : - Tool(argc, argv, "test-rtt"), - stop(false), - fd(STDOUT_FILENO), - count(-1), - hist_warmup(100), - hist_buckets(20) - { - int ret; + TestRtt(int argc, char *argv[]) + : Tool(argc, argv, "test-rtt"), stop(false), fd(STDOUT_FILENO), count(-1), + hist_warmup(100), hist_buckets(20) { + int ret; - ret = memory::init(DEFAULT_NR_HUGEPAGES); - if (ret) - throw RuntimeError("Failed to initialize memory"); - } + ret = memory::init(DEFAULT_NR_HUGEPAGES); + if (ret) + throw RuntimeError("Failed to initialize memory"); + } protected: - std::atomic stop; + std::atomic stop; - std::string uri; - std::string nodestr; + std::string uri; + std::string nodestr; - SuperNode sn; + SuperNode sn; - /* File descriptor for Matlab results. + /* File descriptor for Matlab results. * This allows you to write Matlab results in a seperate log file: * * ./test etc/example.conf rtt -f 3 3>> measurement_results.m */ - int fd; + int fd; - // Amount of messages which should be sent (default: -1 for unlimited) - int count; + // Amount of messages which should be sent (default: -1 for unlimited) + int count; - Hist::cnt_t hist_warmup; - int hist_buckets; + Hist::cnt_t hist_warmup; + int hist_buckets; - void handler(int signal, siginfo_t *sinfo, void *ctx) - { - stop = true; - } + void handler(int signal, siginfo_t *sinfo, void *ctx) { stop = true; } - void usage() - { - std::cout << "Usage: villas-test-rtt [OPTIONS] CONFIG NODE" << std::endl - << " CONFIG path to a configuration file" << std::endl - << " NODE name of the node which shoud be used" << std::endl - << " OPTIONS is one or more of the following options:" << std::endl - << " -c CNT send CNT messages" << std::endl - << " -f FD use file descriptor FD for result output instead of stdout" << std::endl - << " -b BKTS number of buckets for histogram" << std::endl - << " -w WMUP duration of histogram warmup phase" << std::endl - << " -h show this usage information" << std::endl - << " -V show the version of the tool" << std::endl << std::endl; + void usage() { + std::cout << "Usage: villas-test-rtt [OPTIONS] CONFIG NODE" << std::endl + << " CONFIG path to a configuration file" << std::endl + << " NODE name of the node which shoud be used" << std::endl + << " OPTIONS is one or more of the following options:" + << std::endl + << " -c CNT send CNT messages" << std::endl + << " -f FD use file descriptor FD for result output instead " + "of stdout" + << std::endl + << " -b BKTS number of buckets for histogram" << std::endl + << " -w WMUP duration of histogram warmup phase" << std::endl + << " -h show this usage information" << std::endl + << " -V show the version of the tool" << std::endl + << std::endl; - printCopyright(); - } + printCopyright(); + } - void parse() - { - // Parse Arguments - int c; - char *endptr; - while ((c = getopt (argc, argv, "w:hr:f:c:b:Vd:")) != -1) { - switch (c) { - case 'c': - count = strtoul(optarg, &endptr, 10); - goto check; + void parse() { + // Parse Arguments + int c; + char *endptr; + while ((c = getopt(argc, argv, "w:hr:f:c:b:Vd:")) != -1) { + switch (c) { + case 'c': + count = strtoul(optarg, &endptr, 10); + goto check; - case 'f': - fd = strtoul(optarg, &endptr, 10); - goto check; + case 'f': + fd = strtoul(optarg, &endptr, 10); + goto check; - case 'w': - hist_warmup = strtoul(optarg, &endptr, 10); - goto check; + case 'w': + hist_warmup = strtoul(optarg, &endptr, 10); + goto check; - case 'b': - hist_buckets = strtoul(optarg, &endptr, 10); - goto check; + case 'b': + hist_buckets = strtoul(optarg, &endptr, 10); + goto check; - case 'V': - printVersion(); - exit(EXIT_SUCCESS); + case 'V': + printVersion(); + exit(EXIT_SUCCESS); - case 'd': - logging.setLevel(optarg); - break; + case 'd': + logging.setLevel(optarg); + break; - case 'h': - case '?': - usage(); - exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); - } + case 'h': + case '?': + usage(); + exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS); + } - continue; + continue; -check: if (optarg == endptr) - throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg); - } + check: + if (optarg == endptr) + throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, + optarg); + } - if (argc != optind + 2) { - usage(); - exit(EXIT_FAILURE); - } + if (argc != optind + 2) { + usage(); + exit(EXIT_FAILURE); + } - uri = argv[optind]; - nodestr = argv[optind + 1]; - } + uri = argv[optind]; + nodestr = argv[optind + 1]; + } - int main() - { - int ret; + int main() { + int ret; - Hist hist(hist_buckets, hist_warmup); - struct timespec send, recv; + Hist hist(hist_buckets, hist_warmup); + struct timespec send, recv; - struct Sample *smp_send = (struct Sample *) new char[SAMPLE_LENGTH(2)]; - struct Sample *smp_recv = (struct Sample *) new char[SAMPLE_LENGTH(2)]; + struct Sample *smp_send = (struct Sample *)new char[SAMPLE_LENGTH(2)]; + struct Sample *smp_recv = (struct Sample *)new char[SAMPLE_LENGTH(2)]; - if (!smp_send || !smp_recv) - throw MemoryAllocationError(); + if (!smp_send || !smp_recv) + throw MemoryAllocationError(); - Node *node; + Node *node; - if (!uri.empty()) - sn.parse(uri); - else - logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance."); + if (!uri.empty()) + sn.parse(uri); + else + logger->warn("No configuration file specified. Starting unconfigured. " + "Use the API to configure this instance."); - node = sn.getNode(nodestr); - if (!node) - throw RuntimeError("There's no node with the name '{}'", nodestr); + node = sn.getNode(nodestr); + if (!node) + throw RuntimeError("There's no node with the name '{}'", nodestr); - ret = node->getFactory()->start(&sn); - if (ret) - throw RuntimeError("Failed to start node-type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->start(&sn); + if (ret) + throw RuntimeError("Failed to start node-type {}: reason={}", + node->getFactory()->getName(), ret); - ret = node->prepare(); - if (ret) - throw RuntimeError("Failed to prepare node {}: reason={}", node->getName(), ret); + ret = node->prepare(); + if (ret) + throw RuntimeError("Failed to prepare node {}: reason={}", + node->getName(), ret); - ret = node->start(); - if (ret) - throw RuntimeError("Failed to start node {}: reason={}", node->getName(), ret); + ret = node->start(); + if (ret) + throw RuntimeError("Failed to start node {}: reason={}", node->getName(), + ret); - // Print header - fprintf(stdout, "%17s%5s%10s%10s%10s%10s%10s\n", "timestamp", "seq", "rtt", "min", "max", "mean", "stddev"); + // Print header + fprintf(stdout, "%17s%5s%10s%10s%10s%10s%10s\n", "timestamp", "seq", "rtt", + "min", "max", "mean", "stddev"); - while (!stop && (count < 0 || count--)) { - clock_gettime(CLOCK_ID, &send); + while (!stop && (count < 0 || count--)) { + clock_gettime(CLOCK_ID, &send); - node->write(&smp_send, 1); // Ping - node->read(&smp_recv, 1); // Pong + node->write(&smp_send, 1); // Ping + node->read(&smp_recv, 1); // Pong - clock_gettime(CLOCK_ID, &recv); + clock_gettime(CLOCK_ID, &recv); - double rtt = time_delta(&recv, &send); + double rtt = time_delta(&recv, &send); - if (rtt < 0) - logger->warn("Negative RTT: {}", rtt); + if (rtt < 0) + logger->warn("Negative RTT: {}", rtt); - hist.put(rtt); + hist.put(rtt); - smp_send->sequence++; + smp_send->sequence++; - fprintf(stdout, "%10lld.%06lld%5" PRIu64 "%10.3f%10.3f%10.3f%10.3f%10.3f\n", - (long long) recv.tv_sec, - (long long) recv.tv_nsec / 1000, smp_send->sequence, - 1e3 * rtt, 1e3 * hist.getLowest(), 1e3 * hist.getHighest(), - 1e3 * hist.getMean(), 1e3 * hist.getStddev()); - } + fprintf(stdout, + "%10lld.%06lld%5" PRIu64 "%10.3f%10.3f%10.3f%10.3f%10.3f\n", + (long long)recv.tv_sec, (long long)recv.tv_nsec / 1000, + smp_send->sequence, 1e3 * rtt, 1e3 * hist.getLowest(), + 1e3 * hist.getHighest(), 1e3 * hist.getMean(), + 1e3 * hist.getStddev()); + } - struct stat st; - if (!fstat(fd, &st)) { - FILE *f = fdopen(fd, "w"); - hist.dumpMatlab(f); - fclose(f); - } - else - throw RuntimeError("Invalid file descriptor: {}", fd); + struct stat st; + if (!fstat(fd, &st)) { + FILE *f = fdopen(fd, "w"); + hist.dumpMatlab(f); + fclose(f); + } else + throw RuntimeError("Invalid file descriptor: {}", fd); - hist.print(logger, true); + hist.print(logger, true); - ret = node->stop(); - if (ret) - throw RuntimeError("Failed to stop node {}: reason={}", node->getName(), ret); + ret = node->stop(); + if (ret) + throw RuntimeError("Failed to stop node {}: reason={}", node->getName(), + ret); - ret = node->getFactory()->stop(); - if (ret) - throw RuntimeError("Failed to stop node-type {}: reason={}", node->getFactory()->getName(), ret); + ret = node->getFactory()->stop(); + if (ret) + throw RuntimeError("Failed to stop node-type {}: reason={}", + node->getFactory()->getName(), ret); - delete smp_send; - delete smp_recv; + delete smp_send; + delete smp_recv; - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::TestRtt t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::TestRtt t(argc, argv); - return t.run(); + return t.run(); } diff --git a/src/villas-zmq-keygen.cpp b/src/villas-zmq-keygen.cpp index c666a6c33..886016ff3 100644 --- a/src/villas-zmq-keygen.cpp +++ b/src/villas-zmq-keygen.cpp @@ -5,14 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include -#include +#include +#include #include +#include #if ZMQ_VERSION_MAJOR < 4 || (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR <= 1) - #include +#include #endif namespace villas { @@ -22,42 +22,41 @@ namespace tools { class ZmqKeygen : public Tool { public: - ZmqKeygen(int argc, char *argv[]) : - Tool(argc, argv, "zmq-keygen") - { } + ZmqKeygen(int argc, char *argv[]) : Tool(argc, argv, "zmq-keygen") {} protected: - int main() - { - int ret; - char public_key[41]; - char secret_key[41]; + int main() { + int ret; + char public_key[41]; + char secret_key[41]; - ret = zmq_curve_keypair(public_key, secret_key); - if (ret) { - if (zmq_errno() == ENOTSUP) - std::cout << "To use " << argv[0] << ", please install libsodium and then rebuild libzmq." << std::endl; + ret = zmq_curve_keypair(public_key, secret_key); + if (ret) { + if (zmq_errno() == ENOTSUP) + std::cout << "To use " << argv[0] + << ", please install libsodium and then rebuild libzmq." + << std::endl; - exit(EXIT_FAILURE); - } + exit(EXIT_FAILURE); + } - std::cout << "# Copy these lines to your 'zeromq' node-configuration" << std::endl; - std::cout << "curve = {" << std::endl; - std::cout << "\tpublic_key = \"" << public_key << "\";" << std::endl; - std::cout << "\tsecret_key = \"" << secret_key << "\";" << std::endl; - std::cout << "}" << std::endl; + std::cout << "# Copy these lines to your 'zeromq' node-configuration" + << std::endl; + std::cout << "curve = {" << std::endl; + std::cout << "\tpublic_key = \"" << public_key << "\";" << std::endl; + std::cout << "\tsecret_key = \"" << secret_key << "\";" << std::endl; + std::cout << "}" << std::endl; - return 0; - } + return 0; + } }; } // namespace tools } // namespace node } // namespace villas -int main(int argc, char *argv[]) -{ - villas::node::tools::ZmqKeygen t(argc, argv); +int main(int argc, char *argv[]) { + villas::node::tools::ZmqKeygen t(argc, argv); - return t.run(); + return t.run(); } diff --git a/tests/unit/config.cpp b/tests/unit/config.cpp index ab126d6ee..cdb0f5ba2 100644 --- a/tests/unit/config.cpp +++ b/tests/unit/config.cpp @@ -5,73 +5,71 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include -#include #include +#include using namespace villas::node; // cppcheck-suppress syntaxError -Test(config, env) -{ - const char *cfg_f = "test = \"${MY_ENV_VAR}\"\n"; +Test(config, env) { + const char *cfg_f = "test = \"${MY_ENV_VAR}\"\n"; - std::FILE *f = std::tmpfile(); - std::fputs(cfg_f, f); - std::rewind(f); + std::FILE *f = std::tmpfile(); + std::fputs(cfg_f, f); + std::rewind(f); - auto c = Config(); + auto c = Config(); - char env[] = "MY_ENV_VAR=mobydick"; - putenv(env); + char env[] = "MY_ENV_VAR=mobydick"; + putenv(env); - auto *r = c.load(f); - cr_assert_not_null(r); + auto *r = c.load(f); + cr_assert_not_null(r); - auto *j = json_object_get(r, "test"); - cr_assert_not_null(j); + auto *j = json_object_get(r, "test"); + cr_assert_not_null(j); - cr_assert(json_is_string(j)); - cr_assert_str_eq("mobydick", json_string_value(j)); + cr_assert(json_is_string(j)); + cr_assert_str_eq("mobydick", json_string_value(j)); } -Test(config, include) -{ - const char *cfg_f2 = "magic = 1234\n"; +Test(config, include) { + const char *cfg_f2 = "magic = 1234\n"; - char f2_fn_tpl[] = "/tmp/villas.unit-test.XXXXXX"; - int f2_fd = mkstemp(f2_fn_tpl); + char f2_fn_tpl[] = "/tmp/villas.unit-test.XXXXXX"; + int f2_fd = mkstemp(f2_fn_tpl); - std::FILE *f2 = fdopen(f2_fd, "w"); - std::fputs(cfg_f2, f2); - std::rewind(f2); + std::FILE *f2 = fdopen(f2_fd, "w"); + std::fputs(cfg_f2, f2); + std::rewind(f2); - auto cfg_f1 = fmt::format("subval = \"@include {}\"\n", f2_fn_tpl); + auto cfg_f1 = fmt::format("subval = \"@include {}\"\n", f2_fn_tpl); - std::FILE *f1 = std::tmpfile(); - std::fputs(cfg_f1.c_str(), f1); - std::rewind(f1); + std::FILE *f1 = std::tmpfile(); + std::fputs(cfg_f1.c_str(), f1); + std::rewind(f1); - auto env = fmt::format("INCLUDE_FILE={}", f2_fn_tpl).c_str(); - putenv((char *) env); + auto env = fmt::format("INCLUDE_FILE={}", f2_fn_tpl).c_str(); + putenv((char *)env); - auto c = Config(); + auto c = Config(); - auto *r = c.load(f1); - cr_assert_not_null(r); + auto *r = c.load(f1); + cr_assert_not_null(r); - auto *j = json_object_get(r, "subval"); - cr_assert_not_null(j); + auto *j = json_object_get(r, "subval"); + cr_assert_not_null(j); - auto *j2 = json_object_get(j, "magic"); - cr_assert_not_null(j2); + auto *j2 = json_object_get(j, "magic"); + cr_assert_not_null(j2); - cr_assert(json_is_integer(j2)); - cr_assert_eq(json_number_value(j2), 1234); + cr_assert(json_is_integer(j2)); + cr_assert_eq(json_number_value(j2), 1234); - std::fclose(f2); - std::remove(f2_fn_tpl); + std::fclose(f2); + std::remove(f2_fn_tpl); } diff --git a/tests/unit/config_json.cpp b/tests/unit/config_json.cpp index f0592f17d..268385d82 100644 --- a/tests/unit/config_json.cpp +++ b/tests/unit/config_json.cpp @@ -12,97 +12,95 @@ #include #include -#include #include +#include using namespace villas::node; const char *cfg_example = "test : \n" - "{\n" - " hallo = 1L;\n" - "};\n" - "liste = ( 1.1, 2L, 3L, 4L, \n" - " {\n" - " objekt : \n" - " {\n" - " key = \"value\";\n" - " };\n" - " } );\n"; + "{\n" + " hallo = 1L;\n" + "};\n" + "liste = ( 1.1, 2L, 3L, 4L, \n" + " {\n" + " objekt : \n" + " {\n" + " key = \"value\";\n" + " };\n" + " } );\n"; const char *json_example = "{\n" - " \"test\": {\n" - " \"hallo\": 1\n" - " },\n" - " \"liste\": [\n" - " 1.1000000000000001,\n" - " 2,\n" - " 3,\n" - " 4,\n" - " {\n" - " \"objekt\": {\n" - " \"key\": \"value\"\n" - " }\n" - " }\n" - " ]\n" - "}"; + " \"test\": {\n" + " \"hallo\": 1\n" + " },\n" + " \"liste\": [\n" + " 1.1000000000000001,\n" + " 2,\n" + " 3,\n" + " 4,\n" + " {\n" + " \"objekt\": {\n" + " \"key\": \"value\"\n" + " }\n" + " }\n" + " ]\n" + "}"; // cppcheck-suppress syntaxError -Test(config, config_to_json) -{ - int ret; - config_t cfg; - config_setting_t *cfg_root; - json_t *json; +Test(config, config_to_json) { + int ret; + config_t cfg; + config_setting_t *cfg_root; + json_t *json; - config_init(&cfg); + config_init(&cfg); - ret = config_read_string(&cfg, cfg_example); - cr_assert_eq(ret, CONFIG_TRUE); + ret = config_read_string(&cfg, cfg_example); + cr_assert_eq(ret, CONFIG_TRUE); - cfg_root = config_root_setting(&cfg); + cfg_root = config_root_setting(&cfg); - json = config_to_json(cfg_root); - cr_assert_not_null(json); + json = config_to_json(cfg_root); + cr_assert_not_null(json); - char *str = json_dumps(json, JSON_INDENT(2)); + char *str = json_dumps(json, JSON_INDENT(2)); - //printf("%s\n", str); + //printf("%s\n", str); - json_decref(json); + json_decref(json); - cr_assert_str_eq(str, json_example); + cr_assert_str_eq(str, json_example); - config_destroy(&cfg); + config_destroy(&cfg); } -Test(config, json_to_config) -{ - config_t cfg; - config_setting_t *cfg_root; - json_t *json; +Test(config, json_to_config) { + config_t cfg; + config_setting_t *cfg_root; + json_t *json; - // For config_write() - FILE *f; - char str[1024]; + // For config_write() + FILE *f; + char str[1024]; - config_init(&cfg); + config_init(&cfg); - cfg_root = config_root_setting(&cfg); + cfg_root = config_root_setting(&cfg); - json = json_loads(json_example, 0, nullptr); - cr_assert_not_null(json); + json = json_loads(json_example, 0, nullptr); + cr_assert_not_null(json); - json_to_config(json, cfg_root); + json_to_config(json, cfg_root); - //config_write(&cfg, stdout); + //config_write(&cfg, stdout); - f = fmemopen(str, sizeof(str), "w+"); - config_write(&cfg, f); - fclose(f); + f = fmemopen(str, sizeof(str), "w+"); + config_write(&cfg, f); + fclose(f); - cr_assert_str_eq(str, cfg_example); + cr_assert_str_eq(str, cfg_example); - json_decref(json); + json_decref(json); } #endif // WITH_CONFIG diff --git a/tests/unit/format.cpp b/tests/unit/format.cpp index 95dbeb2f4..54abc41bb 100644 --- a/tests/unit/format.cpp +++ b/tests/unit/format.cpp @@ -5,350 +5,381 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include #include #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include #include "helpers.hpp" using namespace villas; using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); #define NUM_VALUES 10 -using string = std::basic_string, criterion::allocator>; +using string = + std::basic_string, criterion::allocator>; struct Param { public: - Param(const char *f, int c, int b) : - fmt(f), cnt(c), bits(b) - {} + Param(const char *f, int c, int b) : fmt(f), cnt(c), bits(b) {} - string fmt; - int cnt; - int bits; + string fmt; + int cnt; + int bits; }; -void fill_sample_data(SignalList::Ptr signals, struct Sample *smps[], unsigned cnt) -{ - struct timespec delta, now; +void fill_sample_data(SignalList::Ptr signals, struct Sample *smps[], + unsigned cnt) { + struct timespec delta, now; - now = time_now(); - delta = time_from_double(50e-6); + now = time_now(); + delta = time_from_double(50e-6); - for (unsigned i = 0; i < cnt; i++) { - struct Sample *smp = smps[i]; + for (unsigned i = 0; i < cnt; i++) { + struct Sample *smp = smps[i]; - smps[i]->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA | (int) SampleFlags::HAS_TS_ORIGIN; - smps[i]->length = signals->size(); - smps[i]->sequence = 235 + i; - smps[i]->ts.origin = now; - smps[i]->signals = signals; + smps[i]->flags = (int)SampleFlags::HAS_SEQUENCE | + (int)SampleFlags::HAS_DATA | + (int)SampleFlags::HAS_TS_ORIGIN; + smps[i]->length = signals->size(); + smps[i]->sequence = 235 + i; + smps[i]->ts.origin = now; + smps[i]->signals = signals; - for (size_t j = 0; j < signals->size(); j++) { - auto sig = signals->getByIndex(j); - auto *data = &smp->data[j]; + for (size_t j = 0; j < signals->size(); j++) { + auto sig = signals->getByIndex(j); + auto *data = &smp->data[j]; - switch (sig->type) { - case SignalType::BOOLEAN: - data->b = j * 0.1 + i * 100; - break; + switch (sig->type) { + case SignalType::BOOLEAN: + data->b = j * 0.1 + i * 100; + break; - case SignalType::COMPLEX: { - // TODO: Port to proper C++ - std::complex z = { j * 0.1f, i * 100.0f }; - memcpy(&data->z, &z, sizeof(data->z)); - break; - } + case SignalType::COMPLEX: { + // TODO: Port to proper C++ + std::complex z = {j * 0.1f, i * 100.0f}; + memcpy(&data->z, &z, sizeof(data->z)); + break; + } - case SignalType::FLOAT: - data->f = j * 0.1 + i * 100; - break; + case SignalType::FLOAT: + data->f = j * 0.1 + i * 100; + break; - case SignalType::INTEGER: - data->i = j + i * 1000; - break; + case SignalType::INTEGER: + data->i = j + i * 1000; + break; - default: { } - } - } + default: { + } + } + } - now = time_add(&now, &delta); - } + now = time_add(&now, &delta); + } } -void cr_assert_eq_sample(struct Sample *a, struct Sample *b, int flags) -{ - cr_assert_eq(a->length, b->length, "a->length=%d, b->length=%d", a->length, b->length); +void cr_assert_eq_sample(struct Sample *a, struct Sample *b, int flags) { + cr_assert_eq(a->length, b->length, "a->length=%d, b->length=%d", a->length, + b->length); - if (flags & (int) SampleFlags::HAS_SEQUENCE) - cr_assert_eq(a->sequence, b->sequence); + if (flags & (int)SampleFlags::HAS_SEQUENCE) + cr_assert_eq(a->sequence, b->sequence); - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { - cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec); - cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec); - } + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) { + cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec); + cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec); + } - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned j = 0; j < MIN(a->length, b->length); j++) { - cr_assert_eq(sample_format(a, j), sample_format(b, j)); + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned j = 0; j < MIN(a->length, b->length); j++) { + cr_assert_eq(sample_format(a, j), sample_format(b, j)); - switch (sample_format(b, j)) { - case SignalType::FLOAT: - cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3, "Sample data mismatch at index %d: %f != %f", j, a->data[j].f, b->data[j].f); - break; + switch (sample_format(b, j)) { + case SignalType::FLOAT: + cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3, + "Sample data mismatch at index %d: %f != %f", j, + a->data[j].f, b->data[j].f); + break; - case SignalType::INTEGER: - cr_assert_eq(a->data[j].i, b->data[j].i, "Sample data mismatch at index %d: %lld != %lld", j, a->data[j].i, b->data[j].i); - break; + case SignalType::INTEGER: + cr_assert_eq(a->data[j].i, b->data[j].i, + "Sample data mismatch at index %d: %lld != %lld", j, + a->data[j].i, b->data[j].i); + break; - case SignalType::BOOLEAN: - cr_assert_eq(a->data[j].b, b->data[j].b, "Sample data mismatch at index %d: %s != %s", j, a->data[j].b ? "true" : "false", b->data[j].b ? "true" : "false"); - break; + case SignalType::BOOLEAN: + cr_assert_eq(a->data[j].b, b->data[j].b, + "Sample data mismatch at index %d: %s != %s", j, + a->data[j].b ? "true" : "false", + b->data[j].b ? "true" : "false"); + break; - case SignalType::COMPLEX: { - auto ca = * (std::complex *) &a->data[j].z; - auto cb = * (std::complex *) &b->data[j].z; + case SignalType::COMPLEX: { + auto ca = *(std::complex *)&a->data[j].z; + auto cb = *(std::complex *)&b->data[j].z; - cr_assert_float_eq(std::abs(ca - cb), 0, 1e-6, "Sample data mismatch at index %d: %f+%fi != %f+%fi", j, ca.real(), ca.imag(), cb.real(), cb.imag()); - break; - } + cr_assert_float_eq(std::abs(ca - cb), 0, 1e-6, + "Sample data mismatch at index %d: %f+%fi != %f+%fi", + j, ca.real(), ca.imag(), cb.real(), cb.imag()); + break; + } - default: { } - } - } - } + default: { + } + } + } + } } -void cr_assert_eq_sample_raw(struct Sample *a, struct Sample *b, int flags, int bits) -{ - cr_assert_eq(a->length, b->length); +void cr_assert_eq_sample_raw(struct Sample *a, struct Sample *b, int flags, + int bits) { + cr_assert_eq(a->length, b->length); - if (flags & (int) SampleFlags::HAS_SEQUENCE) - cr_assert_eq(a->sequence, b->sequence); + if (flags & (int)SampleFlags::HAS_SEQUENCE) + cr_assert_eq(a->sequence, b->sequence); - if (flags & (int) SampleFlags::HAS_TS_ORIGIN) { - cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec); - cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec); - } + if (flags & (int)SampleFlags::HAS_TS_ORIGIN) { + cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec); + cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec); + } - if (flags & (int) SampleFlags::HAS_DATA) { - for (unsigned j = 0; j < MIN(a->length, b->length); j++) { - cr_assert_eq(sample_format(a, j), sample_format(b, j)); + if (flags & (int)SampleFlags::HAS_DATA) { + for (unsigned j = 0; j < MIN(a->length, b->length); j++) { + cr_assert_eq(sample_format(a, j), sample_format(b, j)); - switch (sample_format(b, j)) { - case SignalType::FLOAT: - if (bits != 8 && bits != 16) - cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3, "Sample data mismatch at index %d: %f != %f", j, a->data[j].f, b->data[j].f); - break; + switch (sample_format(b, j)) { + case SignalType::FLOAT: + if (bits != 8 && bits != 16) + cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3, + "Sample data mismatch at index %d: %f != %f", j, + a->data[j].f, b->data[j].f); + break; - case SignalType::INTEGER: - cr_assert_eq(a->data[j].i, b->data[j].i, "Sample data mismatch at index %d: %lld != %lld", j, a->data[j].i, b->data[j].i); - break; + case SignalType::INTEGER: + cr_assert_eq(a->data[j].i, b->data[j].i, + "Sample data mismatch at index %d: %lld != %lld", j, + a->data[j].i, b->data[j].i); + break; - case SignalType::BOOLEAN: - cr_assert_eq(a->data[j].b, b->data[j].b, "Sample data mismatch at index %d: %s != %s", j, a->data[j].b ? "true" : "false", b->data[j].b ? "true" : "false"); - break; + case SignalType::BOOLEAN: + cr_assert_eq(a->data[j].b, b->data[j].b, + "Sample data mismatch at index %d: %s != %s", j, + a->data[j].b ? "true" : "false", + b->data[j].b ? "true" : "false"); + break; - case SignalType::COMPLEX: - if (bits != 8 && bits != 16) { - auto ca = * (std::complex *) &a->data[j].z; - auto cb = * (std::complex *) &b->data[j].z; + case SignalType::COMPLEX: + if (bits != 8 && bits != 16) { + auto ca = *(std::complex *)&a->data[j].z; + auto cb = *(std::complex *)&b->data[j].z; - cr_assert_float_eq(std::abs(ca - cb), 0, 1e-6, "Sample data mismatch at index %d: %f+%fi != %f+%fi", j, ca.real(), ca.imag(), cb.real(), cb.imag()); - } - break; + cr_assert_float_eq( + std::abs(ca - cb), 0, 1e-6, + "Sample data mismatch at index %d: %f+%fi != %f+%fi", j, + ca.real(), ca.imag(), cb.real(), cb.imag()); + } + break; - default: { } - } - } - } + default: { + } + } + } + } } -ParameterizedTestParameters(format, lowlevel) -{ - static - criterion::parameters params; +ParameterizedTestParameters(format, lowlevel) { + static criterion::parameters params; - params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); - params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64); - params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0); - params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0); - params.emplace_back("{ \"type\": \"csv\" }", 10, 0); - params.emplace_back("{ \"type\": \"tsv\" }", 10, 0); - params.emplace_back("{ \"type\": \"json\" }", 10, 0); - // params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names - // params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0); + params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); + params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); + params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64); + params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0); + params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0); + params.emplace_back("{ \"type\": \"csv\" }", 10, 0); + params.emplace_back("{ \"type\": \"tsv\" }", 10, 0); + params.emplace_back("{ \"type\": \"json\" }", 10, 0); + // params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names + // params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0); #ifdef PROTOBUF_FOUND - params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0 ); + params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0); #endif - return params; + return params; } // cppcheck-suppress unknownMacro -ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) -{ - int ret; - unsigned cnt; - char buf[8192]; - size_t wbytes, rbytes; +ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) { + int ret; + unsigned cnt; + char buf[8192]; + size_t wbytes, rbytes; - Logger logger = logging.get("test:format:lowlevel"); + Logger logger = logging.get("test:format:lowlevel"); - logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt); + logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt); - struct Pool pool; - Format *fmt; - struct Sample *smps[p->cnt]; - struct Sample *smpt[p->cnt]; + struct Pool pool; + Format *fmt; + struct Sample *smps[p->cnt]; + struct Sample *smpt[p->cnt]; - ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES)); - cr_assert_eq(ret, 0); + ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES)); + cr_assert_eq(ret, 0); - auto signals = std::make_shared(NUM_VALUES, SignalType::FLOAT); + auto signals = std::make_shared(NUM_VALUES, SignalType::FLOAT); - ret = sample_alloc_many(&pool, smps, p->cnt); - cr_assert_eq(ret, p->cnt); + ret = sample_alloc_many(&pool, smps, p->cnt); + cr_assert_eq(ret, p->cnt); - ret = sample_alloc_many(&pool, smpt, p->cnt); - cr_assert_eq(ret, p->cnt); + ret = sample_alloc_many(&pool, smpt, p->cnt); + cr_assert_eq(ret, p->cnt); - fill_sample_data(signals, smps, p->cnt); + fill_sample_data(signals, smps, p->cnt); - json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr); - cr_assert_not_null(json_format); + json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr); + cr_assert_not_null(json_format); - fmt = FormatFactory::make(json_format); - cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", p->fmt.c_str()); + fmt = FormatFactory::make(json_format); + cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", + p->fmt.c_str()); - fmt->start(signals, (int) SampleFlags::HAS_ALL); + fmt->start(signals, (int)SampleFlags::HAS_ALL); - cnt = fmt->sprint(buf, sizeof(buf), &wbytes, smps, p->cnt); - cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt); + cnt = fmt->sprint(buf, sizeof(buf), &wbytes, smps, p->cnt); + cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt); - cnt = fmt->sscan(buf, wbytes, &rbytes, smpt, p->cnt); - cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt); + cnt = fmt->sscan(buf, wbytes, &rbytes, smpt, p->cnt); + cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt); - cr_assert_eq(rbytes, wbytes, "rbytes != wbytes: %#zx != %#zx", rbytes, wbytes); + cr_assert_eq(rbytes, wbytes, "rbytes != wbytes: %#zx != %#zx", rbytes, + wbytes); - for (unsigned i = 0; i < cnt; i++) { - if (p->bits) - cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits); - else - cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags()); - } + for (unsigned i = 0; i < cnt; i++) { + if (p->bits) + cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits); + else + cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags()); + } - sample_free_many(smps, p->cnt); - sample_free_many(smpt, p->cnt); + sample_free_many(smps, p->cnt); + sample_free_many(smpt, p->cnt); - ret = pool_destroy(&pool); - cr_assert_eq(ret, 0); + ret = pool_destroy(&pool); + cr_assert_eq(ret, 0); } -ParameterizedTestParameters(format, highlevel) -{ - static - criterion::parameters params; +ParameterizedTestParameters(format, highlevel) { + static criterion::parameters params; - params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); - params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64); - params.emplace_back("{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64); - params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0); - params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0); - params.emplace_back("{ \"type\": \"csv\" }", 10, 0); - params.emplace_back("{ \"type\": \"tsv\" }", 10, 0); - params.emplace_back("{ \"type\": \"json\" }", 10, 0); - // params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names - // params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0); + params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32); + params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32); + params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64); + params.emplace_back( + "{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64); + params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0); + params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0); + params.emplace_back("{ \"type\": \"csv\" }", 10, 0); + params.emplace_back("{ \"type\": \"tsv\" }", 10, 0); + params.emplace_back("{ \"type\": \"json\" }", 10, 0); + // params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names + // params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0); #ifdef PROTOBUF_FOUND - params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0 ); + params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0); #endif - return params; + return params; } -ParameterizedTest(Param *p, format, highlevel, .init = init_memory) -{ - int ret, cnt; - char *retp; +ParameterizedTest(Param *p, format, highlevel, .init = init_memory) { + int ret, cnt; + char *retp; - Logger logger = logging.get("test:format:highlevel"); + Logger logger = logging.get("test:format:highlevel"); - logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt); + logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt); - struct Sample *smps[p->cnt]; - struct Sample *smpt[p->cnt]; + struct Sample *smps[p->cnt]; + struct Sample *smpt[p->cnt]; - struct Pool pool; - Format *fmt; + struct Pool pool; + Format *fmt; - ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES)); - cr_assert_eq(ret, 0); + ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES)); + cr_assert_eq(ret, 0); - ret = sample_alloc_many(&pool, smps, p->cnt); - cr_assert_eq(ret, p->cnt); + ret = sample_alloc_many(&pool, smps, p->cnt); + cr_assert_eq(ret, p->cnt); - ret = sample_alloc_many(&pool, smpt, p->cnt); - cr_assert_eq(ret, p->cnt); + ret = sample_alloc_many(&pool, smpt, p->cnt); + cr_assert_eq(ret, p->cnt); - auto signals = std::make_shared(NUM_VALUES, SignalType::FLOAT); + auto signals = std::make_shared(NUM_VALUES, SignalType::FLOAT); - fill_sample_data(signals, smps, p->cnt); + fill_sample_data(signals, smps, p->cnt); - // Open a file for testing the formatter - char *fn, dir[64]; - strncpy(dir, "/tmp/villas.XXXXXX", sizeof(dir)); + // Open a file for testing the formatter + char *fn, dir[64]; + strncpy(dir, "/tmp/villas.XXXXXX", sizeof(dir)); - retp = mkdtemp(dir); - cr_assert_not_null(retp); + retp = mkdtemp(dir); + cr_assert_not_null(retp); - ret = asprintf(&fn, "%s/file", dir); - cr_assert_gt(ret, 0); + ret = asprintf(&fn, "%s/file", dir); + cr_assert_gt(ret, 0); - json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr); - cr_assert_not_null(json_format); + json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr); + cr_assert_not_null(json_format); - fmt = FormatFactory::make(json_format); - cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", p->fmt.c_str()); + fmt = FormatFactory::make(json_format); + cr_assert_not_null(fmt, "Failed to create formatter of type '%s'", + p->fmt.c_str()); - fmt->start(signals, (int) SampleFlags::HAS_ALL); + fmt->start(signals, (int)SampleFlags::HAS_ALL); - auto *stream = fopen(fn, "w+"); - cr_assert_not_null(stream); + auto *stream = fopen(fn, "w+"); + cr_assert_not_null(stream); - cnt = fmt->print(stream, smps, p->cnt); - cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt); + cnt = fmt->print(stream, smps, p->cnt); + cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt); - ret = fflush(stream); - cr_assert_eq(ret, 0); + ret = fflush(stream); + cr_assert_eq(ret, 0); #if 0 // Show the file contents char cmd[128]; @@ -359,34 +390,34 @@ ParameterizedTest(Param *p, format, highlevel, .init = init_memory) system(cmd); #endif - rewind(stream); + rewind(stream); - cnt = fmt->scan(stream, smpt, p->cnt); - cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt); + cnt = fmt->scan(stream, smpt, p->cnt); + cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt); - for (int i = 0; i < cnt; i++) { - if (p->bits) - cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits); - else - cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags()); - } + for (int i = 0; i < cnt; i++) { + if (p->bits) + cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits); + else + cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags()); + } - ret = fclose(stream); - cr_assert_eq(ret, 0); + ret = fclose(stream); + cr_assert_eq(ret, 0); - delete fmt; + delete fmt; - ret = unlink(fn); - cr_assert_eq(ret, 0); + ret = unlink(fn); + cr_assert_eq(ret, 0); - ret = rmdir(dir); - cr_assert_eq(ret, 0); + ret = rmdir(dir); + cr_assert_eq(ret, 0); - free(fn); + free(fn); - sample_free_many(smps, p->cnt); - sample_free_many(smpt, p->cnt); + sample_free_many(smps, p->cnt); + sample_free_many(smpt, p->cnt); - ret = pool_destroy(&pool); - cr_assert_eq(ret, 0); + ret = pool_destroy(&pool); + cr_assert_eq(ret, 0); } diff --git a/tests/unit/helpers.cpp b/tests/unit/helpers.cpp index a5df1d0d1..f7569fe5d 100644 --- a/tests/unit/helpers.cpp +++ b/tests/unit/helpers.cpp @@ -11,10 +11,9 @@ #include "helpers.hpp" -char * cr_strdup(const char *str) -{ - char *ptr = (char *) cr_malloc(strlen(str) + 1); - if (ptr) - strcpy(ptr, str); - return ptr; +char *cr_strdup(const char *str) { + char *ptr = (char *)cr_malloc(strlen(str) + 1); + if (ptr) + strcpy(ptr, str); + return ptr; } diff --git a/tests/unit/helpers.hpp b/tests/unit/helpers.hpp index da2079c99..0d01b7919 100644 --- a/tests/unit/helpers.hpp +++ b/tests/unit/helpers.hpp @@ -7,4 +7,4 @@ #pragma once -char * cr_strdup(const char *str); +char *cr_strdup(const char *str); diff --git a/tests/unit/json.cpp b/tests/unit/json.cpp index 5314948f5..9aef6ba73 100644 --- a/tests/unit/json.cpp +++ b/tests/unit/json.cpp @@ -8,81 +8,69 @@ #include #include -#include #include +#include #include "helpers.hpp" using namespace villas::node; struct param { - char *argv[32]; - char *json; + char *argv[32]; + char *json; }; // cppcheck-suppress syntaxError -ParameterizedTestParameters(json, json_load_cli) -{ - const auto d = cr_strdup; +ParameterizedTestParameters(json, json_load_cli) { + const auto d = cr_strdup; - static - criterion::parameters params = { - // Combined long option - { - .argv = { d("dummy"), d("--option=value") }, - .json = d("{ \"option\" : \"value\" }") - }, - // Separated long option - { - .argv = { d("dummy"), d("--option"), d("value") }, - .json = d("{ \"option\" : \"value\" }") - }, - // All kinds of data types - { - .argv = { d("dummy"), d("--integer"), d("1"), d("--real"), d("1.1"), d("--bool"), d("true"), d("--null"), d("null"), d("--string"), d("hello world") }, - .json = d("{ \"integer\" : 1, \"real\" : 1.1, \"bool\" : true, \"null\" : null, \"string\" : \"hello world\" }") - }, - // Array generation - { - .argv = { d("dummy"), d("--bool"), d("true"), d("--bool"), d("false") }, - .json = d("{ \"bool\" : [ true, false ] }") - }, - // Dots in the option name generate sub objects - { - .argv = { d("dummy"), d("--sub.option"), d("value") }, - .json = d("{ \"sub\" : { \"option\" : \"value\" } }") - }, - // Nesting is possible - { - .argv = { d("dummy"), d("--sub.sub.option"), d("value") }, - .json = d("{ \"sub\" : { \"sub\" : { \"option\" : \"value\" } } }") - }, - // Multiple subgroups are merged - { - .argv = { d("dummy"), d("--sub.sub.option"), d("value1"), d("--sub.option"), d("value2") }, - .json = d("{ \"sub\" : { \"option\" : \"value2\", \"sub\" : { \"option\" : \"value1\" } } }") - } - }; + static criterion::parameters params = { + // Combined long option + {.argv = {d("dummy"), d("--option=value")}, + .json = d("{ \"option\" : \"value\" }")}, + // Separated long option + {.argv = {d("dummy"), d("--option"), d("value")}, + .json = d("{ \"option\" : \"value\" }")}, + // All kinds of data types + {.argv = {d("dummy"), d("--integer"), d("1"), d("--real"), d("1.1"), + d("--bool"), d("true"), d("--null"), d("null"), d("--string"), + d("hello world")}, + .json = d("{ \"integer\" : 1, \"real\" : 1.1, \"bool\" : true, \"null\" " + ": null, \"string\" : \"hello world\" }")}, + // Array generation + {.argv = {d("dummy"), d("--bool"), d("true"), d("--bool"), d("false")}, + .json = d("{ \"bool\" : [ true, false ] }")}, + // Dots in the option name generate sub objects + {.argv = {d("dummy"), d("--sub.option"), d("value")}, + .json = d("{ \"sub\" : { \"option\" : \"value\" } }")}, + // Nesting is possible + {.argv = {d("dummy"), d("--sub.sub.option"), d("value")}, + .json = d("{ \"sub\" : { \"sub\" : { \"option\" : \"value\" } } }")}, + // Multiple subgroups are merged + {.argv = {d("dummy"), d("--sub.sub.option"), d("value1"), + d("--sub.option"), d("value2")}, + .json = d("{ \"sub\" : { \"option\" : \"value2\", \"sub\" : { " + "\"option\" : \"value1\" } } }")}}; - return params; + return params; } -ParameterizedTest(struct param *p, json, json_load_cli) -{ - json_error_t err; - json_t *json, *cli; +ParameterizedTest(struct param *p, json, json_load_cli) { + json_error_t err; + json_t *json, *cli; - json = json_loads(p->json, 0, &err); - cr_assert_not_null(json); + json = json_loads(p->json, 0, &err); + cr_assert_not_null(json); - int argc = 0; - while (p->argv[argc]) argc++; + int argc = 0; + while (p->argv[argc]) + argc++; - cli = json_load_cli(argc, (const char **) p->argv); - cr_assert_not_null(cli); + cli = json_load_cli(argc, (const char **)p->argv); + cr_assert_not_null(cli); - //json_dumpf(json, stdout, JSON_INDENT(2)); putc('\n', stdout); - //json_dumpf(cli, stdout, JSON_INDENT(2)); putc('\n', stdout); + //json_dumpf(json, stdout, JSON_INDENT(2)); putc('\n', stdout); + //json_dumpf(cli, stdout, JSON_INDENT(2)); putc('\n', stdout); - cr_assert(json_equal(json, cli)); + cr_assert(json_equal(json, cli)); } diff --git a/tests/unit/main.cpp b/tests/unit/main.cpp index 299241578..87dc0489f 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/main.cpp @@ -9,8 +9,7 @@ using namespace villas::node; -void init_memory() -{ - int ret __attribute__((unused)); - ret = memory::init(DEFAULT_NR_HUGEPAGES); +void init_memory() { + int ret __attribute__((unused)); + ret = memory::init(DEFAULT_NR_HUGEPAGES); } diff --git a/tests/unit/mapping.cpp b/tests/unit/mapping.cpp index 52417f254..bf85feb32 100644 --- a/tests/unit/mapping.cpp +++ b/tests/unit/mapping.cpp @@ -7,80 +7,79 @@ #include +#include #include #include -#include -#include #include +#include using namespace villas; using namespace villas::node; // cppcheck-suppress syntaxError -Test(mapping, parse_nodes) -{ - int ret; - MappingEntry m; +Test(mapping, parse_nodes) { + int ret; + MappingEntry m; - ret = m.parseString("apple.ts.origin"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "apple"); - cr_assert_eq(m.type, MappingEntry::Type::TIMESTAMP); - cr_assert_eq(m.timestamp.type, MappingEntry::TimestampType::ORIGIN); + ret = m.parseString("apple.ts.origin"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "apple"); + cr_assert_eq(m.type, MappingEntry::Type::TIMESTAMP); + cr_assert_eq(m.timestamp.type, MappingEntry::TimestampType::ORIGIN); - ret = m.parseString("cherry.stats.owd.mean"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "cherry"); - cr_assert_eq(m.type, MappingEntry::Type::STATS); - cr_assert_eq(m.stats.metric, Stats::Metric::OWD); - cr_assert_eq(m.stats.type, Stats::Type::MEAN); + ret = m.parseString("cherry.stats.owd.mean"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "cherry"); + cr_assert_eq(m.type, MappingEntry::Type::STATS); + cr_assert_eq(m.stats.metric, Stats::Metric::OWD); + cr_assert_eq(m.stats.type, Stats::Type::MEAN); - ret = m.parseString("carrot.data[1-2]"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "1"); - cr_assert_str_eq(m.data.last, "2"); + ret = m.parseString("carrot.data[1-2]"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "1"); + cr_assert_str_eq(m.data.last, "2"); - ret = m.parseString("carrot"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_eq(m.data.first, nullptr); - cr_assert_eq(m.data.last, nullptr); + ret = m.parseString("carrot"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_eq(m.data.first, nullptr); + cr_assert_eq(m.data.last, nullptr); - ret = m.parseString("carrot.data[sole]"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_eq(m.data.last, nullptr); + ret = m.parseString("carrot.data[sole]"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_eq(m.data.last, nullptr); - ret = m.parseString("carrot.sole"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_eq(m.data.last, nullptr); + ret = m.parseString("carrot.sole"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_eq(m.data.last, nullptr); - ret = m.parseString("carrot.data.sole"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_eq(m.data.last, nullptr); + ret = m.parseString("carrot.data.sole"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_eq(m.data.last, nullptr); - ret = m.parseString("carrot.data[sole-mio]"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_str_eq(m.data.last, "mio"); + ret = m.parseString("carrot.data[sole-mio]"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_str_eq(m.data.last, "mio"); - ret = m.parseString("carrot[sole-mio]"); - cr_assert_eq(ret, 0); - cr_assert_str_eq(m.nodeName.c_str(), "carrot"); - cr_assert_eq(m.type, MappingEntry::Type::DATA); - cr_assert_str_eq(m.data.first, "sole"); - cr_assert_str_eq(m.data.last, "mio"); + ret = m.parseString("carrot[sole-mio]"); + cr_assert_eq(ret, 0); + cr_assert_str_eq(m.nodeName.c_str(), "carrot"); + cr_assert_eq(m.type, MappingEntry::Type::DATA); + cr_assert_str_eq(m.data.first, "sole"); + cr_assert_str_eq(m.data.last, "mio"); } diff --git a/tests/unit/memory.cpp b/tests/unit/memory.cpp index 8731d231a..5b575145d 100644 --- a/tests/unit/memory.cpp +++ b/tests/unit/memory.cpp @@ -10,97 +10,102 @@ #include -#include -#include #include +#include #include using namespace villas; using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); #define PAGESIZE (1 << 12) #define HUGEPAGESIZE (1 << 21) TheoryDataPoints(memory, aligned) = { - DataPoints(size_t, 1, 32, 55, 1 << 10, PAGESIZE, HUGEPAGESIZE), - DataPoints(size_t, 1, 8, PAGESIZE, PAGESIZE), - DataPoints(struct memory::Type *, &memory::heap, &memory::mmap_hugetlb, &memory::mmap_hugetlb) -}; + DataPoints(size_t, 1, 32, 55, 1 << 10, PAGESIZE, HUGEPAGESIZE), + DataPoints(size_t, 1, 8, PAGESIZE, PAGESIZE), + DataPoints(struct memory::Type *, &memory::heap, &memory::mmap_hugetlb, + &memory::mmap_hugetlb)}; // cppcheck-suppress unknownMacro -Theory((size_t len, size_t align, struct memory::Type *mt), memory, aligned, .init = init_memory) { - int ret; - void *ptr; +Theory((size_t len, size_t align, struct memory::Type *mt), memory, aligned, + .init = init_memory) { + int ret; + void *ptr; - if (!utils::isPrivileged() && mt == &memory::mmap_hugetlb) - cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are running in an unprivileged environment."); + if (!utils::isPrivileged() && mt == &memory::mmap_hugetlb) + cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are " + "running in an unprivileged environment."); - ptr = memory::alloc_aligned(len, align, mt); - cr_assert_not_null(ptr, "Failed to allocate memory"); + ptr = memory::alloc_aligned(len, align, mt); + cr_assert_not_null(ptr, "Failed to allocate memory"); - cr_assert(IS_ALIGNED(ptr, align), "Memory at %p is not alligned to %#zx byte bounary", ptr, align); + cr_assert(IS_ALIGNED(ptr, align), + "Memory at %p is not alligned to %#zx byte bounary", ptr, align); - if (mt == &memory::mmap_hugetlb) { - cr_assert(IS_ALIGNED(ptr, HUGEPAGESIZE), "Memory at %p is not alligned to %#x byte bounary", ptr, HUGEPAGESIZE); - } + if (mt == &memory::mmap_hugetlb) { + cr_assert(IS_ALIGNED(ptr, HUGEPAGESIZE), + "Memory at %p is not alligned to %#x byte bounary", ptr, + HUGEPAGESIZE); + } - ret = memory::free(ptr); - cr_assert_eq(ret, 0, "Failed to release memory: ret=%d, ptr=%p, len=%zu: %s", ret, ptr, len, strerror(errno)); + ret = memory::free(ptr); + cr_assert_eq(ret, 0, "Failed to release memory: ret=%d, ptr=%p, len=%zu: %s", + ret, ptr, len, strerror(errno)); } Test(memory, manager, .init = init_memory) { - size_t total_size; - size_t max_block; + size_t total_size; + size_t max_block; - int ret; - void *p, *p1, *p2, *p3; - struct memory::Type *m; + int ret; + void *p, *p1, *p2, *p3; + struct memory::Type *m; - total_size = 1 << 10; - max_block = total_size - sizeof(struct memory::Type) - sizeof(struct memory::Block); + total_size = 1 << 10; + max_block = + total_size - sizeof(struct memory::Type) - sizeof(struct memory::Block); - p = memory::alloc(total_size, &memory::heap); - cr_assert_not_null(p); + p = memory::alloc(total_size, &memory::heap); + cr_assert_not_null(p); - m = memory::managed(p, total_size); - cr_assert_not_null(m); + m = memory::managed(p, total_size); + cr_assert_not_null(m); - p1 = memory::alloc(16, m); - cr_assert_not_null(p1); + p1 = memory::alloc(16, m); + cr_assert_not_null(p1); - p2 = memory::alloc(32, m); - cr_assert_not_null(p2); + p2 = memory::alloc(32, m); + cr_assert_not_null(p2); - ret = memory::free(p1); - cr_assert(ret == 0); + ret = memory::free(p1); + cr_assert(ret == 0); - p1 = memory::alloc_aligned(128, 128, m); - cr_assert_not_null(p1); - cr_assert(IS_ALIGNED(p1, 128)); + p1 = memory::alloc_aligned(128, 128, m); + cr_assert_not_null(p1); + cr_assert(IS_ALIGNED(p1, 128)); - p3 = memory::alloc_aligned(128, 256, m); - cr_assert(p3); - cr_assert(IS_ALIGNED(p3, 256)); + p3 = memory::alloc_aligned(128, 256, m); + cr_assert(p3); + cr_assert(IS_ALIGNED(p3, 256)); - ret = memory::free(p2); - cr_assert(ret == 0); + ret = memory::free(p2); + cr_assert(ret == 0); - ret = memory::free(p1); - cr_assert(ret == 0); + ret = memory::free(p1); + cr_assert(ret == 0); - ret = memory::free(p3); - cr_assert(ret == 0); + ret = memory::free(p3); + cr_assert(ret == 0); - p1 = memory::alloc(max_block, m); - cr_assert_not_null(p1); + p1 = memory::alloc(max_block, m); + cr_assert_not_null(p1); - ret = memory::free(p1); - cr_assert(ret == 0); + ret = memory::free(p1); + cr_assert(ret == 0); - ret = memory::free(p); - cr_assert(ret == 0); + ret = memory::free(p); + cr_assert(ret == 0); } diff --git a/tests/unit/pool.cpp b/tests/unit/pool.cpp index 87b7b43e1..de98f8a88 100644 --- a/tests/unit/pool.cpp +++ b/tests/unit/pool.cpp @@ -11,72 +11,69 @@ #include #include +#include #include #include -#include using namespace villas; using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); struct param { - int thread_count; - int pool_size; - size_t block_size; - struct memory::Type *mt; + int thread_count; + int pool_size; + size_t block_size; + struct memory::Type *mt; }; -ParameterizedTestParameters(pool, basic) -{ - static - std::vector params; +ParameterizedTestParameters(pool, basic) { + static std::vector params; - params.clear(); - params.push_back({ 1, 4096, 150, &memory::heap }); - params.push_back({ 1, 128, 8, &memory::mmap }); - params.push_back({ 1, 4, 8192, &memory::mmap_hugetlb }); - params.push_back({ 1, 1 << 13, 4, &memory::mmap_hugetlb }); + params.clear(); + params.push_back({1, 4096, 150, &memory::heap}); + params.push_back({1, 128, 8, &memory::mmap}); + params.push_back({1, 4, 8192, &memory::mmap_hugetlb}); + params.push_back({1, 1 << 13, 4, &memory::mmap_hugetlb}); - return cr_make_param_array(struct param, params.data(), params.size()); + return cr_make_param_array(struct param, params.data(), params.size()); } // cppcheck-suppress unknownMacro -ParameterizedTest(struct param *p, pool, basic, .init = init_memory) -{ - int ret; - struct Pool pool; - void *ptr, *ptrs[p->pool_size]; +ParameterizedTest(struct param *p, pool, basic, .init = init_memory) { + int ret; + struct Pool pool; + void *ptr, *ptrs[p->pool_size]; - logging.setLevel("trace"); + logging.setLevel("trace"); - if (!utils::isPrivileged() && p->mt == &memory::mmap_hugetlb) - cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are running in an unprivileged environment."); + if (!utils::isPrivileged() && p->mt == &memory::mmap_hugetlb) + cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are " + "running in an unprivileged environment."); - ret = pool_init(&pool, p->pool_size, p->block_size, p->mt); - cr_assert_eq(ret, 0, "Failed to create pool"); + ret = pool_init(&pool, p->pool_size, p->block_size, p->mt); + cr_assert_eq(ret, 0, "Failed to create pool"); - ptr = pool_get(&pool); - cr_assert_neq(ptr, nullptr); + ptr = pool_get(&pool); + cr_assert_neq(ptr, nullptr); - memset(ptr, 1, p->block_size); // check that we dont get a seg fault + memset(ptr, 1, p->block_size); // check that we dont get a seg fault - int i; - for (i = 1; i < p->pool_size; i++) { - ptrs[i] = pool_get(&pool); + int i; + for (i = 1; i < p->pool_size; i++) { + ptrs[i] = pool_get(&pool); - if (ptrs[i] == nullptr) - break; - } + if (ptrs[i] == nullptr) + break; + } - if (i < p->pool_size) - cr_assert_neq(ptrs[i], nullptr); + if (i < p->pool_size) + cr_assert_neq(ptrs[i], nullptr); - ptr = pool_get(&pool); - cr_assert_eq(ptr, nullptr); + ptr = pool_get(&pool); + cr_assert_eq(ptr, nullptr); - ret = pool_destroy(&pool); - cr_assert_eq(ret, 0, "Failed to destroy pool"); + ret = pool_destroy(&pool); + cr_assert_eq(ret, 0, "Failed to destroy pool"); } diff --git a/tests/unit/queue.cpp b/tests/unit/queue.cpp index 9c5341ac5..4c21fef4c 100644 --- a/tests/unit/queue.cpp +++ b/tests/unit/queue.cpp @@ -5,341 +5,321 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include #include +#include #include #include +#include +#include #include #include -#include -#include -#include -#include #include +#include +#include +#include +#include using namespace villas; using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); -#define SIZE (1 << 10) +#define SIZE (1 << 10) -static -struct CQueue q; +static struct CQueue q; #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0 -static -pthread_barrier_t barrier; +static pthread_barrier_t barrier; #endif struct param { - int iter_count; - int queue_size; - int thread_count; - bool many; - int batch_size; - struct memory::Type *mt; - volatile int start; - struct CQueue queue; + int iter_count; + int queue_size; + int thread_count; + bool many; + int batch_size; + struct memory::Type *mt; + volatile int start; + struct CQueue queue; }; /* Get thread id as integer * In contrast to pthread_t which is an opaque type */ #ifdef __linux__ - #include +#include #endif -uint64_t thread_get_id() -{ +uint64_t thread_get_id() { #ifdef __MACH__ - uint64_t id; - pthread_threadid_np(pthread_self(), &id); - return id; + uint64_t id; + pthread_threadid_np(pthread_self(), &id); + return id; #elif defined(SYS_gettid) - return (int) syscall(SYS_gettid); + return (int)syscall(SYS_gettid); #endif - return -1; + return -1; } // Sleep, do nothing -__attribute__((always_inline)) static inline -void nop() -{ - __asm__("rep nop;"); +__attribute__((always_inline)) static inline void nop() { __asm__("rep nop;"); } + +static void *producer(void *ctx) { + int ret; + struct param *p = (struct param *)ctx; + + srand((unsigned)time(0) + thread_get_id()); + size_t nops = rand() % 1000; + + // Wait for global start signal + while (p->start == 0) + sched_yield(); + + // Wait for a random time + for (size_t i = 0; i != nops; i += 1) + nop(); + + // Enqueue + for (intptr_t count = 0; count < p->iter_count; count++) { + do { + ret = queue_push(&p->queue, (void *)count); + sched_yield(); + } while (ret != 1); + } + + return nullptr; } -static -void * producer(void *ctx) -{ - int ret; - struct param *p = (struct param *) ctx; +static void *consumer(void *ctx) { + int ret; + struct param *p = (struct param *)ctx; - srand((unsigned) time(0) + thread_get_id()); - size_t nops = rand() % 1000; + srand((unsigned)time(0) + thread_get_id()); + size_t nops = rand() % 1000; - // Wait for global start signal - while (p->start == 0) - sched_yield(); + // Wait for global start signal + while (p->start == 0) + sched_yield(); - // Wait for a random time - for (size_t i = 0; i != nops; i += 1) - nop(); + // Wait for a random time + for (size_t i = 0; i != nops; i += 1) + nop(); - // Enqueue - for (intptr_t count = 0; count < p->iter_count; count++) { - do { - ret = queue_push(&p->queue, (void *) count); - sched_yield(); - } while (ret != 1); - } + // Dequeue + for (intptr_t count = 0; count < p->iter_count; count++) { + intptr_t ptr; - return nullptr; -} + do { + ret = queue_pull(&p->queue, (void **)&ptr); + } while (ret != 1); -static -void * consumer(void *ctx) -{ - int ret; - struct param *p = (struct param *) ctx; + //logger->info("consumer: {}", count); - srand((unsigned) time(0) + thread_get_id()); - size_t nops = rand() % 1000; + //cr_assert_eq((intptr_t) ptr, count); + } - // Wait for global start signal - while (p->start == 0) - sched_yield(); - - // Wait for a random time - for (size_t i = 0; i != nops; i += 1) - nop(); - - // Dequeue - for (intptr_t count = 0; count < p->iter_count; count++) { - intptr_t ptr; - - do { - ret = queue_pull(&p->queue, (void **) &ptr); - } while (ret != 1); - - //logger->info("consumer: {}", count); - - //cr_assert_eq((intptr_t) ptr, count); - } - - return nullptr; + return nullptr; } #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0 -void * producer_consumer(void *ctx) -{ - struct param *p = (struct param *) ctx; +void *producer_consumer(void *ctx) { + struct param *p = (struct param *)ctx; - srand((unsigned) time(0) + thread_get_id()); - size_t nops = rand() % 1000; + srand((unsigned)time(0) + thread_get_id()); + size_t nops = rand() % 1000; - // Wait for global start signal - while (p->start == 0) - sched_yield(); + // Wait for global start signal + while (p->start == 0) + sched_yield(); - // Wait for a random time - for (size_t i = 0; i != nops; i += 1) - nop(); + // Wait for a random time + for (size_t i = 0; i != nops; i += 1) + nop(); - for (int iter = 0; iter < p->iter_count; ++iter) { - pthread_barrier_wait(&barrier); + for (int iter = 0; iter < p->iter_count; ++iter) { + pthread_barrier_wait(&barrier); - for (intptr_t i = 0; i < p->batch_size; i++) { - void *ptr = (void *) (iter * p->batch_size + i); - while (!queue_push(&p->queue, ptr)) - sched_yield(); // queue full, let other threads proceed - } + for (intptr_t i = 0; i < p->batch_size; i++) { + void *ptr = (void *)(iter * p->batch_size + i); + while (!queue_push(&p->queue, ptr)) + sched_yield(); // queue full, let other threads proceed + } - for (intptr_t i = 0; i < p->batch_size; i++) { - void *ptr; - while (!queue_pull(&p->queue, &ptr)) - sched_yield(); // queue empty, let other threads proceed - } - } + for (intptr_t i = 0; i < p->batch_size; i++) { + void *ptr; + while (!queue_pull(&p->queue, &ptr)) + sched_yield(); // queue empty, let other threads proceed + } + } - return 0; + return 0; } -void * producer_consumer_many(void *ctx) -{ - struct param *p = (struct param *) ctx; +void *producer_consumer_many(void *ctx) { + struct param *p = (struct param *)ctx; - srand((unsigned) time(0) + thread_get_id()); - size_t nops = rand() % 1000; + srand((unsigned)time(0) + thread_get_id()); + size_t nops = rand() % 1000; - // Wait for global start signal - while (p->start == 0) - sched_yield(); + // Wait for global start signal + while (p->start == 0) + sched_yield(); - // Wait for a random time - for (size_t i = 0; i != nops; i += 1) - nop(); + // Wait for a random time + for (size_t i = 0; i != nops; i += 1) + nop(); - void *ptrs[p->batch_size]; + void *ptrs[p->batch_size]; - for (int iter = 0; iter < p->iter_count; ++iter) { - for (intptr_t i = 0; i < p->batch_size; i++) - ptrs[i] = (void *) (iter * p->batch_size + i); + for (int iter = 0; iter < p->iter_count; ++iter) { + for (intptr_t i = 0; i < p->batch_size; i++) + ptrs[i] = (void *)(iter * p->batch_size + i); - pthread_barrier_wait(&barrier); + pthread_barrier_wait(&barrier); - int pushed = 0; - do { - pushed += queue_push_many(&p->queue, &ptrs[pushed], p->batch_size - pushed); - if (pushed != p->batch_size) - sched_yield(); // queue full, let other threads proceed - } while (pushed < p->batch_size); + int pushed = 0; + do { + pushed += + queue_push_many(&p->queue, &ptrs[pushed], p->batch_size - pushed); + if (pushed != p->batch_size) + sched_yield(); // queue full, let other threads proceed + } while (pushed < p->batch_size); - int pulled = 0; - do { - pulled += queue_pull_many(&p->queue, &ptrs[pulled], p->batch_size - pulled); - if (pulled != p->batch_size) - sched_yield(); // queue empty, let other threads proceed - } while (pulled < p->batch_size); - } + int pulled = 0; + do { + pulled += + queue_pull_many(&p->queue, &ptrs[pulled], p->batch_size - pulled); + if (pulled != p->batch_size) + sched_yield(); // queue empty, let other threads proceed + } while (pulled < p->batch_size); + } - return 0; + return 0; } #endif // _POSIX_BARRIERS -Test(queue, single_threaded, .init = init_memory) -{ - int ret; - struct param p; +Test(queue, single_threaded, .init = init_memory) { + int ret; + struct param p; - p.iter_count = 1 << 8; - p.queue_size = 1 << 10; - p.start = 1; // we start immeadiatly + p.iter_count = 1 << 8; + p.queue_size = 1 << 10; + p.start = 1; // we start immeadiatly - ret = queue_init(&p.queue, p.queue_size, &memory::heap); - cr_assert_eq(ret, 0, "Failed to create queue"); + ret = queue_init(&p.queue, p.queue_size, &memory::heap); + cr_assert_eq(ret, 0, "Failed to create queue"); - producer(&p); - consumer(&p); + producer(&p); + consumer(&p); - cr_assert_eq(queue_available(&q), 0); + cr_assert_eq(queue_available(&q), 0); - ret = queue_destroy(&p.queue); - cr_assert_eq(ret, 0, "Failed to create queue"); + ret = queue_destroy(&p.queue); + cr_assert_eq(ret, 0, "Failed to create queue"); } #if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0 -ParameterizedTestParameters(queue, multi_threaded) -{ - static - struct param params[] = { - { - .iter_count = 1 << 12, - .queue_size = 1 << 9, - .thread_count = 32, - .many = true, - .batch_size = 10, - .mt = &memory::heap - }, { - .iter_count = 1 << 8, - .queue_size = 1 << 9, - .thread_count = 4, - .many = true, - .batch_size = 100, - .mt = &memory::heap - }, { - .iter_count = 1 << 16, - .queue_size = 1 << 14, - .thread_count = 16, - .many = true, - .batch_size = 100, - .mt = &memory::heap - }, { - .iter_count = 1 << 8, - .queue_size = 1 << 9, - .thread_count = 4, - .many = true, - .batch_size = 10, - .mt = &memory::heap - }, { - .iter_count = 1 << 16, - .queue_size = 1 << 9, - .thread_count = 16, - .many = false, - .batch_size = 10, - .mt = &memory::mmap_hugetlb - } - }; +ParameterizedTestParameters(queue, multi_threaded) { + static struct param params[] = {{.iter_count = 1 << 12, + .queue_size = 1 << 9, + .thread_count = 32, + .many = true, + .batch_size = 10, + .mt = &memory::heap}, + {.iter_count = 1 << 8, + .queue_size = 1 << 9, + .thread_count = 4, + .many = true, + .batch_size = 100, + .mt = &memory::heap}, + {.iter_count = 1 << 16, + .queue_size = 1 << 14, + .thread_count = 16, + .many = true, + .batch_size = 100, + .mt = &memory::heap}, + {.iter_count = 1 << 8, + .queue_size = 1 << 9, + .thread_count = 4, + .many = true, + .batch_size = 10, + .mt = &memory::heap}, + {.iter_count = 1 << 16, + .queue_size = 1 << 9, + .thread_count = 16, + .many = false, + .batch_size = 10, + .mt = &memory::mmap_hugetlb}}; - return cr_make_param_array(struct param, params, ARRAY_LEN(params)); + return cr_make_param_array(struct param, params, ARRAY_LEN(params)); } -ParameterizedTest(struct param *p, queue, multi_threaded, .timeout = 20, .init = init_memory) -{ - int ret, cycpop; - struct Tsc tsc; +ParameterizedTest(struct param *p, queue, multi_threaded, .timeout = 20, + .init = init_memory) { + int ret, cycpop; + struct Tsc tsc; - Logger logger = logging.get("test:queue:multi_threaded"); + Logger logger = logging.get("test:queue:multi_threaded"); - if (!utils::isPrivileged() && p->mt == &memory::mmap_hugetlb) - cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are running in an unprivileged environment."); + if (!utils::isPrivileged() && p->mt == &memory::mmap_hugetlb) + cr_skip_test("Skipping memory_mmap_hugetlb tests allocatpr because we are " + "running in an unprivileged environment."); - pthread_t threads[p->thread_count]; + pthread_t threads[p->thread_count]; - p->start = 0; + p->start = 0; - ret = queue_init(&p->queue, p->queue_size, p->mt); - cr_assert_eq(ret, 0, "Failed to create queue"); + ret = queue_init(&p->queue, p->queue_size, p->mt); + cr_assert_eq(ret, 0, "Failed to create queue"); - uint64_t start_tsc_time, end_tsc_time; + uint64_t start_tsc_time, end_tsc_time; - pthread_barrier_init(&barrier, nullptr, p->thread_count); + pthread_barrier_init(&barrier, nullptr, p->thread_count); - for (int i = 0; i < p->thread_count; ++i) - pthread_create(&threads[i], nullptr, p->many ? producer_consumer_many : producer_consumer, p); + for (int i = 0; i < p->thread_count; ++i) + pthread_create(&threads[i], nullptr, + p->many ? producer_consumer_many : producer_consumer, p); - sleep(0.2); + sleep(0.2); - ret = tsc_init(&tsc); - cr_assert(!ret); + ret = tsc_init(&tsc); + cr_assert(!ret); - start_tsc_time = tsc_now(&tsc); - p->start = 1; + start_tsc_time = tsc_now(&tsc); + p->start = 1; - for (int i = 0; i < p->thread_count; ++i) - pthread_join(threads[i], nullptr); + for (int i = 0; i < p->thread_count; ++i) + pthread_join(threads[i], nullptr); - end_tsc_time = tsc_now(&tsc); - cycpop = (end_tsc_time - start_tsc_time) / p->iter_count; + end_tsc_time = tsc_now(&tsc); + cycpop = (end_tsc_time - start_tsc_time) / p->iter_count; - if (cycpop < 400) - logger->debug("Cycles/op: {}", cycpop); - else - logger->warn("Cycles/op are very high ({}). Are you running on a hypervisor?", cycpop); + if (cycpop < 400) + logger->debug("Cycles/op: {}", cycpop); + else + logger->warn( + "Cycles/op are very high ({}). Are you running on a hypervisor?", + cycpop); - ret = queue_available(&q); - cr_assert_eq(ret, 0); + ret = queue_available(&q); + cr_assert_eq(ret, 0); - ret = queue_destroy(&p->queue); - cr_assert_eq(ret, 0, "Failed to destroy queue"); + ret = queue_destroy(&p->queue); + cr_assert_eq(ret, 0, "Failed to destroy queue"); - ret = pthread_barrier_destroy(&barrier); - cr_assert_eq(ret, 0, "Failed to destroy barrier"); + ret = pthread_barrier_destroy(&barrier); + cr_assert_eq(ret, 0, "Failed to destroy barrier"); } #endif // _POSIX_BARRIERS -Test(queue, init_destroy, .init = init_memory) -{ - int ret; - struct CQueue q; +Test(queue, init_destroy, .init = init_memory) { + int ret; + struct CQueue q; - ret = queue_init(&q, 1024, &memory::heap); - cr_assert_eq(ret, 0); // Should succeed + ret = queue_init(&q, 1024, &memory::heap); + cr_assert_eq(ret, 0); // Should succeed - ret = queue_destroy(&q); - cr_assert_eq(ret, 0); // Should succeed + ret = queue_destroy(&q); + cr_assert_eq(ret, 0); // Should succeed } diff --git a/tests/unit/queue_signalled.cpp b/tests/unit/queue_signalled.cpp index 04b265328..3f440e523 100644 --- a/tests/unit/queue_signalled.cpp +++ b/tests/unit/queue_signalled.cpp @@ -8,148 +8,142 @@ #include #include -#include #include +#include -#include #include #include +#include using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); #define NUM_ELEM 1000 struct param { - enum QueueSignalledMode mode; - int flags; - bool polled; + enum QueueSignalledMode mode; + int flags; + bool polled; }; -static -void * producer(void * ctx) -{ - int ret; - struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; +static void *producer(void *ctx) { + int ret; + struct CQueueSignalled *q = (struct CQueueSignalled *)ctx; - for (intptr_t i = 0; i < NUM_ELEM; i++) { - ret = queue_signalled_push(q, (void *) i); - if (ret != 1) - return (void *) 1; // Indicates an error to the parent thread + for (intptr_t i = 0; i < NUM_ELEM; i++) { + ret = queue_signalled_push(q, (void *)i); + if (ret != 1) + return (void *)1; // Indicates an error to the parent thread - usleep(0.1e-3 * 1e6); // 1 ms - } + usleep(0.1e-3 * 1e6); // 1 ms + } - return nullptr; + return nullptr; } -static -void * consumer(void * ctx) -{ - int ret; - struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; +static void *consumer(void *ctx) { + int ret; + struct CQueueSignalled *q = (struct CQueueSignalled *)ctx; - void *data[NUM_ELEM]; + void *data[NUM_ELEM]; - for (intptr_t i = 0; i < NUM_ELEM;) { - ret = queue_signalled_pull_many(q, data, ARRAY_LEN(data)); - if (ret <= 0) - return (void *) 1; // Indicates an error to the parent thread + for (intptr_t i = 0; i < NUM_ELEM;) { + ret = queue_signalled_pull_many(q, data, ARRAY_LEN(data)); + if (ret <= 0) + return (void *)1; // Indicates an error to the parent thread - for (intptr_t j = 0; j < ret; j++, i++) { - if ((intptr_t) data[j] != i) - return (void *) 2; // Indicates an error to the parent thread - } - } + for (intptr_t j = 0; j < ret; j++, i++) { + if ((intptr_t)data[j] != i) + return (void *)2; // Indicates an error to the parent thread + } + } - return nullptr; + return nullptr; } - void * polled_consumer(void *ctx) -{ - int ret, fd; - struct CQueueSignalled *q = (struct CQueueSignalled *) ctx; +void *polled_consumer(void *ctx) { + int ret, fd; + struct CQueueSignalled *q = (struct CQueueSignalled *)ctx; - fd = queue_signalled_fd(q); - cr_assert_geq(fd, 0); + fd = queue_signalled_fd(q); + cr_assert_geq(fd, 0); - struct pollfd pfd = { - .fd = fd, - .events = POLLIN - }; + struct pollfd pfd = {.fd = fd, .events = POLLIN}; - for (intptr_t i = 0; i < NUM_ELEM; i++) { -again: ret = poll(&pfd, 1, -1); - if (ret < 0) - return (void *) 3; - else if (ret == 0) - goto again; + for (intptr_t i = 0; i < NUM_ELEM; i++) { + again: + ret = poll(&pfd, 1, -1); + if (ret < 0) + return (void *)3; + else if (ret == 0) + goto again; - void *p; - ret = queue_signalled_pull(q, &p); - if (ret != 1) - return (void *) 1; // Indicates an error to the parent thread + void *p; + ret = queue_signalled_pull(q, &p); + if (ret != 1) + return (void *)1; // Indicates an error to the parent thread - if ((intptr_t) p != i) - return (void *) 2; // Indicates an error to the parent thread - } + if ((intptr_t)p != i) + return (void *)2; // Indicates an error to the parent thread + } - return nullptr; + return nullptr; } -ParameterizedTestParameters(queue_signalled, simple) -{ - static - struct param params[] = { - { QueueSignalledMode::AUTO, 0, false }, - { QueueSignalledMode::PTHREAD, 0, false }, - { QueueSignalledMode::PTHREAD, 0, false }, - { QueueSignalledMode::PTHREAD, (int) QueueSignalledFlags::PROCESS_SHARED, false }, - { QueueSignalledMode::POLLING, 0, false }, +ParameterizedTestParameters(queue_signalled, simple) { + static struct param params[] = { + {QueueSignalledMode::AUTO, 0, false}, + {QueueSignalledMode::PTHREAD, 0, false}, + {QueueSignalledMode::PTHREAD, 0, false}, + {QueueSignalledMode::PTHREAD, (int)QueueSignalledFlags::PROCESS_SHARED, + false}, + {QueueSignalledMode::POLLING, 0, false}, #if defined(__linux__) && defined(HAS_EVENTFD) - { QueueSignalledMode::EVENTFD, 0, false }, - { QueueSignalledMode::EVENTFD, 0, true } + {QueueSignalledMode::EVENTFD, 0, false}, + {QueueSignalledMode::EVENTFD, 0, true} #endif - }; + }; - return cr_make_param_array(struct param, params, ARRAY_LEN(params)); + return cr_make_param_array(struct param, params, ARRAY_LEN(params)); } // cppcheck-suppress unknownMacro -ParameterizedTest(struct param *param, queue_signalled, simple, .timeout = 5, .init = init_memory) -{ - int ret; - void *r1, *r2; - struct CQueueSignalled q; +ParameterizedTest(struct param *param, queue_signalled, simple, .timeout = 5, + .init = init_memory) { + int ret; + void *r1, *r2; + struct CQueueSignalled q; - pthread_t t1, t2; + pthread_t t1, t2; - ret = queue_signalled_init(&q, LOG2_CEIL(NUM_ELEM), &memory::heap, param->mode, param->flags); - cr_assert_eq(ret, 0, "Failed to initialize queue: mode=%d, flags=%#x, ret=%d", (int) param->mode, param->flags, ret); + ret = queue_signalled_init(&q, LOG2_CEIL(NUM_ELEM), &memory::heap, + param->mode, param->flags); + cr_assert_eq(ret, 0, "Failed to initialize queue: mode=%d, flags=%#x, ret=%d", + (int)param->mode, param->flags, ret); - ret = pthread_create(&t1, nullptr, producer, &q); - cr_assert_eq(ret, 0); + ret = pthread_create(&t1, nullptr, producer, &q); + cr_assert_eq(ret, 0); - ret = pthread_create(&t2, nullptr, param->polled ? polled_consumer : consumer, &q); - cr_assert_eq(ret, 0); + ret = pthread_create(&t2, nullptr, param->polled ? polled_consumer : consumer, + &q); + cr_assert_eq(ret, 0); - ret = pthread_join(t1, &r1); - cr_assert_eq(ret, 0); + ret = pthread_join(t1, &r1); + cr_assert_eq(ret, 0); - ret = pthread_join(t2, &r2); - cr_assert_eq(ret, 0); + ret = pthread_join(t2, &r2); + cr_assert_eq(ret, 0); - cr_assert_null(r1, "Producer failed: %p", r1); - cr_assert_null(r2, "Consumer failed: %p", r2); + cr_assert_null(r1, "Producer failed: %p", r1); + cr_assert_null(r2, "Consumer failed: %p", r2); - ret = queue_signalled_available(&q); - cr_assert_eq(ret, 0); + ret = queue_signalled_available(&q); + cr_assert_eq(ret, 0); - ret = queue_signalled_close(&q); - cr_assert_eq(ret, 0); + ret = queue_signalled_close(&q); + cr_assert_eq(ret, 0); - ret = queue_signalled_destroy(&q); - cr_assert_eq(ret, 0); + ret = queue_signalled_destroy(&q); + cr_assert_eq(ret, 0); } diff --git a/tests/unit/signal.cpp b/tests/unit/signal.cpp index e7f5438a9..6ad47b812 100644 --- a/tests/unit/signal.cpp +++ b/tests/unit/signal.cpp @@ -11,65 +11,64 @@ using namespace villas::node; -extern -void init_memory(); +extern void init_memory(); // cppcheck-suppress unknownMacro Test(signal_data, parse, .init = init_memory) { - int ret; - enum SignalType type; - union SignalData sd; - const char *str; - char *end; + int ret; + enum SignalType type; + union SignalData sd; + const char *str; + char *end; - str = "1"; - type = SignalType::INTEGER; + str = "1"; + type = SignalType::INTEGER; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_eq(sd.i, 1); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_eq(sd.i, 1); - str = "1.2"; - type = SignalType::FLOAT; + str = "1.2"; + type = SignalType::FLOAT; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_float_eq(sd.f, 1.2, 1e-6); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_float_eq(sd.f, 1.2, 1e-6); - str = "1"; - type = SignalType::BOOLEAN; + str = "1"; + type = SignalType::BOOLEAN; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_eq(sd.b, 1); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_eq(sd.b, 1); - str = "1"; - type = SignalType::COMPLEX; + str = "1"; + type = SignalType::COMPLEX; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_float_eq(std::real(sd.z), 1, 1e-6); - cr_assert_float_eq(std::imag(sd.z), 0, 1e-6); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_float_eq(std::real(sd.z), 1, 1e-6); + cr_assert_float_eq(std::imag(sd.z), 0, 1e-6); - str = "-1-3i"; - type = SignalType::COMPLEX; + str = "-1-3i"; + type = SignalType::COMPLEX; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_float_eq(std::real(sd.z), -1, 1e-6); - cr_assert_float_eq(std::imag(sd.z), -3, 1e-6); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_float_eq(std::real(sd.z), -1, 1e-6); + cr_assert_float_eq(std::imag(sd.z), -3, 1e-6); - str = "-3i"; - type = SignalType::COMPLEX; + str = "-3i"; + type = SignalType::COMPLEX; - ret = sd.parseString(type, str, &end); - cr_assert_eq(ret, 0); - cr_assert_eq(end, str + strlen(str)); - cr_assert_float_eq(std::real(sd.z), 0, 1e-6); - cr_assert_float_eq(std::imag(sd.z), -3, 1e-6); + ret = sd.parseString(type, str, &end); + cr_assert_eq(ret, 0); + cr_assert_eq(end, str + strlen(str)); + cr_assert_float_eq(std::real(sd.z), 0, 1e-6); + cr_assert_float_eq(std::imag(sd.z), -3, 1e-6); }