summaryrefslogtreecommitdiffstats
path: root/src/ufo-roof-config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ufo-roof-config.c')
-rw-r--r--src/ufo-roof-config.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/ufo-roof-config.c b/src/ufo-roof-config.c
new file mode 100644
index 0000000..11f8bd4
--- /dev/null
+++ b/src/ufo-roof-config.c
@@ -0,0 +1,172 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include <json-glib/json-glib.h>
+
+#include <ufo/ufo.h>
+
+#include "ufo-roof-error.h"
+#include "ufo-roof-config.h"
+
+#define roof_config_node_get_with_default(var, parent, type, name, default) do { \
+ JsonNode *node = json_object_get_member(parent, name); \
+ if (node) var = json_node_get_##type(node); \
+ else var = default; \
+ } while(0)
+
+#define roof_config_node_get_string_with_default(var, parent, name, default) do { \
+ const gchar *str; \
+ JsonNode *node = json_object_get_member(parent, name); \
+ if (node) str = json_node_get_string(node); \
+ else str = default; \
+ if (var != str) { \
+ if (var) g_free(var); \
+ var = g_strdup(str); \
+ } \
+ } while(0)
+
+#define roof_config_node_get(var, parent, type, name) \
+ roof_config_node_get_with_default(var, parent, type, name, var)
+
+#define roof_config_node_get_string(var, parent, name) \
+ roof_config_node_get_string_with_default(var, parent, name, var)
+
+
+typedef struct {
+ UfoRoofConfig cfg;
+
+ JsonParser *parser;
+} UfoRoofConfigPrivate;
+
+void ufo_roof_config_free(UfoRoofConfig *cfg) {
+ if (cfg) {
+ UfoRoofConfigPrivate *priv = (UfoRoofConfigPrivate*)cfg;
+
+ if (cfg->path)
+ g_free(cfg->path);
+
+ if (priv->parser)
+ g_object_unref (priv->parser);
+
+ free(cfg);
+ }
+}
+
+UfoRoofConfig *ufo_roof_config_new(const char *config, GError **error) {
+ UfoRoofConfigPrivate *priv;
+ UfoRoofConfig *cfg;
+
+// JsonNode *node;
+ JsonObject *root = NULL;
+ JsonObject *hardware = NULL;
+ JsonObject *network = NULL;
+ JsonObject *performance = NULL;
+ JsonObject *simulation = NULL;
+
+ GError *gerr = NULL;
+
+ priv = (UfoRoofConfigPrivate*)malloc(sizeof(UfoRoofConfigPrivate));
+ if (!priv) roof_new_error(error, "Can't allocate UfoRoofConfig");
+
+ memset(priv, 0, sizeof(UfoRoofConfigPrivate));
+
+ // Set defaults
+ cfg = &priv->cfg;
+
+ cfg->port = 4000;
+ cfg->n_streams = 1;
+ cfg->protocol = "udp";
+ cfg->network_timeout = 10000000;
+ cfg->header_size = 0;
+ cfg->payload_size = 0;
+ cfg->max_packet_size = 0;
+ cfg->max_packets = 100;
+ cfg->dataset_size = 0;
+ cfg->buffer_size = 2;
+ cfg->path = NULL;
+
+ // Read configuration
+ priv->parser = json_parser_new_immutable ();
+ json_parser_load_from_file (priv->parser, config, &gerr);
+
+ if (gerr != NULL) {
+ g_propagate_prefixed_error(error, gerr, "Error parsing JSON file (%s) with ROOF configuration: ", config);
+ ufo_roof_config_free(cfg);
+ return NULL;
+ }
+
+ root = json_node_get_object (json_parser_get_root (priv->parser));
+
+ if (root) {
+ roof_config_node_get(hardware, root, object, "hardware");
+ roof_config_node_get(network, root, object, "network");
+ roof_config_node_get(simulation, root, object, "simulation");
+ }
+
+ if (hardware) {
+ // FIXME: Compute dataset size based on roof hardware
+ }
+
+ if (network) {
+// int max_packet_size = 0;
+
+ roof_config_node_get(cfg->port, network, int, "port");
+ roof_config_node_get(cfg->n_streams, network, int, "streams");
+
+ roof_config_node_get(cfg->max_packet_size, network, int, "max_packet_size");
+ // FIXME: compute payload_size based on sample_size
+ roof_config_node_get(cfg->payload_size, network, int, "payload_size");
+ roof_config_node_get(cfg->header_size, network, int, "header_size");
+ roof_config_node_get(cfg->dataset_size, network, int, "dataset_size");
+ }
+
+ if (performance) {
+ roof_config_node_get(cfg->max_packets, performance, int, "packets_at_once");
+ roof_config_node_get(cfg->buffer_size, performance, int, "buffer_size");
+ }
+
+ if (simulation) {
+ roof_config_node_get_string(cfg->path, simulation, "path");
+ roof_config_node_get(cfg->first_file_number, simulation, int, "first_file_number");
+ }
+
+ // Check configuration consistency
+ if (!cfg->payload_size) {
+ ufo_roof_config_free(cfg);
+ roof_new_error(error, "Packet size is not set");
+ }
+
+ if ((!cfg->header_size)&&(!cfg->path)) {
+ if (!strncmp(cfg->protocol, "udp", 3)) {
+ // Error if 0 implicitely set, use default value otherwise
+ if ((network)&&(json_object_get_member(network, "header_size"))) {
+ ufo_roof_config_free(cfg);
+ roof_new_error(error, "The header with packet ids is required for un-ordered protocols");
+ } else {
+ cfg->header_size = sizeof(uint32_t);
+ }
+ }
+ }
+
+ guint fragments_per_dataset = cfg->dataset_size / cfg->payload_size;
+ guint fragments_per_stream = fragments_per_dataset / cfg->n_streams;
+
+ if ((cfg->dataset_size % cfg->payload_size)||(fragments_per_dataset%cfg->n_streams)) {
+ ufo_roof_config_free(cfg);
+ roof_new_error(error, "Inconsistent ROOF configuration: dataset_size=%u, packet_size=%u, data_streams=%u", cfg->dataset_size, cfg->payload_size, cfg->n_streams);
+ }
+
+ if (cfg->buffer_size * fragments_per_stream < cfg->max_packets) {
+ cfg->max_packets = cfg->buffer_size * fragments_per_stream / 2;
+ }
+
+ // Finalize configuration
+ if (!cfg->max_packet_size)
+ cfg->max_packet_size = cfg->header_size + cfg->payload_size;
+
+ if (!cfg->dataset_size)
+ cfg->dataset_size = cfg->payload_size;
+
+
+ return cfg;
+}