#include #include #include #include #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->drop_buffers = 0; 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"); roof_config_node_get(performance, root, object, "performance"); } 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"); roof_config_node_get(cfg->drop_buffers, performance, int, "drop_buffers"); } 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; if (cfg->buffer_size < 4) { cfg->drop_buffers = 0; } else if (cfg->drop_buffers >= cfg->buffer_size) { cfg->drop_buffers = cfg->buffer_size / 2; } return cfg; }