diff --git a/documentation/Configuration.md b/documentation/Configuration.md index 3e5e73c3b..4b7fcb212 100644 --- a/documentation/Configuration.md +++ b/documentation/Configuration.md @@ -9,13 +9,13 @@ The configuration file consists of three sections: The global section consists of some global configuration parameters: -#### `debug` +#### `debug` *(integer)* `debug` expects an integer number (0-10) which determines the verbosity of debug messages during the execution of the server. Use this with care! Producing a lot of IO might decrease the performance of the server. Omitting this setting or setting it to zero will disable debug messages completely. -#### `stats` +#### `stats` *(float)* `stats` specifies the rate in which statistics about the actives paths will be printed to the screen. Setting this value to 5, will print 5 lines per second. @@ -25,19 +25,19 @@ A line of includes information such as: - Messages sent - Messaged dropped -#### `affinity` +#### `affinity` *(integer)* The `affinity` setting allows to restrict the exeuction of the daemon to certain CPU cores. This technique, also called 'pinning', improves the determinism of the server by isolating the daemon processes on exclusive cores. -#### `priority` +#### `priority` *(integer)* The `priority` setting allows to adjust the scheduling priority of the deamon processes. By default, the daemon uses a real-time optimized FIFO scheduling algorithm. ## Nodes -The node section is a **directory** of nodes (clients) which are connected to the S2SS instance. +The node section is a **directory** of nodes (clients) which are connected to the S2SS instance. The directory is indexed by the name of the node: nodes = { @@ -49,7 +49,7 @@ The directory is indexed by the name of the node: There are multiple diffrent type of nodes. But all types have the following settings in common: -#### `type` +#### `type` *("socket" | "gtfpga" | "file" | "ngsi")* `type` sets the type of the node. This should be one of: - `socket` which refers to a [Socket](socket) node. @@ -62,16 +62,65 @@ Take a look a the specific pages for details. ## Paths -The path section consists of a **list** of paths. +The path section consists of a **list** of paths: + + paths = [ + { + in = "rtds", + out = "broker", + reverse = false, + poolsize = 32, + msgsize = 16, + combine = 4, + hook = [ "print", "ts" ] + } + ] + Every path is allowed to have the following settings: +##### `in` & `out` *(string)* + The `in` and `out` settings expect the name of the source and destination node. + The `out` setting itself is allowed to be list of nodes. This enables 1-to-n distribution of simulation data. +##### `enabled` *(boolean)* + The optional `enabled` setting can be used to temporarily disable a path. If omitted, the path is enabled by default. +##### `reverse` *(boolean)* + By default, the path is unidirectional. Meaning, that it only forwards samples from the source to the destination. Sometimes a bidirectional path is needed. This can be accomplished by setting `reverse` to `true`. + +##### `combine` *(integer)* + +This setting allows to send multiple samples in a single message to the destination nodes. Currently this is only supported by the `file` and `socket` node-types. + +The value of this setting determines how many samples will be combined into one packet. + +**Important:** Please make sure that the value of this setting is smaller or equal to the `poolsize` setting of this path. + +##### `rate` *(float)* + +A non-zero value for this setting will change this path to an asynchronous mode. +In this mode S2SS will send with a fixed rate to all destination nodes. +It will always send the latest value it received, possible skipping values which have been received in between. +If `combine` is larger than 1, it will send the last `combine` samples at once. + +**Important:** Please note that there is no correlation between the time of arrival and time of departure in this mode. It might increase the latency of this path by up to `1 / rate` seconds! + +##### `poolsize` *(integer)* + +Every path manages a circular buffer to keep a history of past samples. This setting specifies the size of this circular buffer. + +**Important:** There are some hook functions (or the `combine` setting) which require a minimum poolsize (for example the finite-impulse-response `fir` hook). + +##### `hook` *(list of strings)* + +A list of hook functions which will be executed for this path. + +Please consult the hook chapter of this documentation for more details. diff --git a/server/src/ngsi.c b/server/src/ngsi.c index 460e1fc01..1b599bf47 100644 --- a/server/src/ngsi.c +++ b/server/src/ngsi.c @@ -89,7 +89,7 @@ static size_t ngsi_request_writer(void *contents, size_t size, size_t nmemb, voi static int ngsi_request(CURL *handle, json_t *content, json_t **response) { struct ngsi_response chunk = { 0 }; - long code; + char *post = json_dumps(content, JSON_INDENT(4)); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ngsi_request_writer); @@ -103,8 +103,12 @@ static int ngsi_request(CURL *handle, json_t *content, json_t **response) if (ret) error("HTTP request failed: %s", curl_easy_strerror(ret)); + long code; + double time; + curl_easy_getinfo(handle, CURLINFO_TOTAL_TIME, &time); curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &code); + debug(20, "Request to context broker completed in %.4f seconds", time); debug(20, "Response from context broker (code=%ld):\n%s", code, chunk.data); json_error_t err; @@ -184,6 +188,11 @@ void ngsi_prepare_context(struct node *n, config_setting_t *mapping) "type", "integer", "value", j )); + json_array_append(metadatas, json_pack("{ s: s, s: s, s: o }", + "name", "timestamp", + "type", "date", + "value", json_date(NULL) + )); if (i->structure == NGSI_CHILDREN) { json_array_append_new(attributes, json_pack("{ s: s, s: s, s: s }", @@ -337,18 +346,17 @@ int ngsi_write(struct node *n, struct msg *pool, int poolsize, int first, int cn /* Update context */ for (int j = 0; j < MIN(i->context_len, m->length); j++) { json_t *attribute = i->context_map[j]; - json_t *value = json_object_get(attribute, "value"); json_t *metadatas = json_object_get(attribute, "metadatas"); + + /* Update timestamp */ + json_t *metadata_ts = json_lookup(metadatas, "name", "timestamp"); + json_object_set(metadata_ts, "value", json_date(&MSG_TS(m))); - json_t *timestamp = json_lookup(metadatas, "name", "timestamp"); - json_object_update(timestamp, json_pack("{ s: s, s: s, s: o }", - "name", "timestamp", - "type", "date", - "value", json_date(&MSG_TS(m)) - )); - + /* Update value */ char new[64]; snprintf(new, sizeof(new), "%f", m->data[j].f); /** @todo for now we only support floating point values */ + + json_t *value = json_object_get(attribute, "value"); json_string_set(value, new); }