diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-02-14 12:55:04 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-02-14 15:31:19 +0200 |
commit | a744738cb14e7d0c9cb5d4ea6d64247db5a8822c (patch) | |
tree | e8359c41040a8aa9ff338d7ba1d141da7f318f53 | |
parent | 4263bf8b57b7d8a0b5f73a586c55e9ee2a07b6ca (diff) | |
download | ping903-a744738cb14e7d0c9cb5d4ea6d64247db5a8822c.tar.gz ping903-a744738cb14e7d0c9cb5d4ea6d64247db5a8822c.tar.bz2 |
Version 0.2v0.2
* NEWS: Update.
* README: Update.
* THANKS: Update.
* doc/ping903.8: Spell checking.
* doc/ping903q.1: Likewise.
* src/Makefile.am: Distribute ping903.conf
* src/ping903.h (HOST_STAT_INIT)
(HOST_STAT_VALID,HOST_STAT_PENDING)
(HOST_STAT_INVALID): New constants.
(host_stat): New member "status".
(host_stat_is_valid): Rewrite using status.
* src/ping903q.c: "status" is string now. Handle particular values.
* src/pinger.c: Maintain current status of each host_stat structure in
the status member.
(host_stat): Mark object as valid.
(host_reset): Update status.
(get_host_stat): Report object validity in the "validity" member,
and its current status in "status" (string).
* src/json.c: Implement json_value_copy.
* src/json.h (json_value_copy): New proto.
* src/ping903.c (ept_config): Return particular setting, if
so requested.
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | README | 357 | ||||
-rw-r--r-- | THANKS | 2 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | doc/ping903.8 | 6 | ||||
-rw-r--r-- | doc/ping903q.1 | 2 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/json.c | 126 | ||||
-rw-r--r-- | src/json.h | 1 | ||||
-rw-r--r-- | src/ping903.c | 29 | ||||
-rw-r--r-- | src/ping903.h | 11 | ||||
-rw-r--r-- | src/ping903q.c | 12 | ||||
-rw-r--r-- | src/pinger.c | 24 |
13 files changed, 557 insertions, 26 deletions
@@ -1,9 +1,12 @@ -Ping903 -- history of user-visible changes. 2020-02-07 +Ping903 -- history of user-visible changes. 2020-02-14 See the end of file for copying conditions. -Please send Ping903 bug reports to <gray@gnu.org.ua> +Please send Ping903 bug reports to <gray@gnu.org> + +Version 0.2, 2020-02-14 + +* Initial release -No news is good news. ========================================================================= Copyright information: @@ -1 +1,356 @@ -FIXME: Nothing so far
\ No newline at end of file +Ping903 README +See the end of file for copying conditions. + +* Overview + +Ping903 is designed to periodically monitor a very large number of +remote hosts using ICMP ECHO packets. The system is built using the +client-server architecture. The main component (ping903) is a daemon +that sits in memory and wakes up periodically to send certain number +of ICMP echo packets to a preconfigured number of hosts and to collect +replies. The round-trip statistics it collects is made available via +REST API. + +The daemon reads its settings from a plain text configuration file. +Most settings have sensible defaults, the only thing that the user +must supply is a list of IP addresses to monitor. This list is +referred to in this document as "ip-list". + +A simple command line client utility (ping903q) allows the user to +communicate with the daemon, obtaining the needed information about +each host in particular, or all monitored hosts at once. This utility +can operate in several modes. In particular, it can be used as +Nagios external check tool, instead of the standard check_ping tool. + +* Installation + +To build ping903 you will need GNU Libmicrohttpd library[3]. It is +available for download from http://ftp.gnu.org/gnu/libmicrohttpd. + +When building from source package, usual incantations apply: + + ./configure + make + make install + +This will install the package under /usr/local. That is, the server +will be installed as /usr/local/sbin/ping903, the client program as +/usr/local/bin/ping903q, etc. You can give a number of options to +./configure in order to customize your installation, in particular to +alter the default installation paths. For example, to install to the +/usr file hierarchy, use + + ./configure --prefix=/usr + +Please refer to the INSTALL document in this directory for a +discussion of available options to configure and their effect. + +After installing the package, copy the file src/ping903.conf to +/etc/ping903.conf and edit it to your liking. This file contains +configuration settings that control the behavior of the server daemon +and, to a certain extent, that of a query tool. The file contains +short annotations before each statement to help you navigate in it. +You will find a detailed discussion of the configuration file in the +manpage ping903.conf(5). What follows is a short outline intended +for quick start: + +At the very beginning you can leave most settings at their default +values. The only statement that you must provide in your +configuration is + + ip-list FILENAME + +Replace FILENAME with the name of the file with IP addresses to +monitor. In this file, each IP address must occupy a separate line. +Empty lines, leading and trailing whitespace and comments are ignored. +Comments are introduced by a hash sign (#) appearing as the first +non-whitespace character on a line. + +You are not required to keep all your IP addresses in a single file. +If necessary, you can scatter them among several files and list each +of them in a separate ip-list statement. + +Normally, the ip-list file should contain IP addresses of the hosts to +monitor. It is OK, however, to use symbolic DNS names, too. If a +hostname resolves to a single A record such usage is equivalent to +placing that IP in the ip-list. However, if the hostnames resolves to +multiple IPs, only first one will be used. + +By default, the server will wake up each minute and send 10 echo +requests within 1 second intervals to each registered IP. If the +number of collected replies is less than 7, the IP will be declared as +dead ("alive": false, in the returned JSON). Otherwise it is +considered alive ("alive": true). + +The following settings control these parameters: + + probe-interval N + Interval between wake-ups in seconds. + Default N=60. + + ping-count N + Number of ICMP packets to send within each probe. + Default N=10. + + ping-interval N + Interval in seconds between two sequential echo requests. + Default N=1. + + tolerance N + Maximum number of lost requests after which the host is considered + dead. + Default N=3. + +Another statement worth your attention is "listen". It configures the +IP address and port on which the server will listen for incoming HTTP +requests. The default is localhost:8080. Change this if this port is +already occupied on your system. + +The access to the HTTP interface is protected by the default access +control library (the files /etc/hosts.allow and /etc/hosts.deny). +Refer to hosts_access(3) for details. + +When you have configured the daemon, start it. Just run ping903. +Check if there are no errors (on the standard error and in the +syslog channel "daemon"). To verify if it is operational, run + + curl http://localhost:8080/config + +This should return the running configuration. + +Within next probe-interval seconds the server will collect enough +statistics to answer your queries. You can request information about +any particular IP from your ip-list by running + + ping903q IP + +This will return the current status of the IP, e.g. + + $ ping903q 203.0.113.1 + 203.0.113.1 is alive + +To get the detailed statistics use the -v option. The result will be +formatted in a ping(8)-like manner: + + $ ping903q -v 203.0.113.1 + 203.0.113.1 is alive + --- 203.0.113.1 ping statistics --- + 10 packets transmitted, 10 received, 0% packet loss, time 9414ms + rtt min/avg/max/mdev = 41.212/41.265/41.374/0.046 ms + +You can check the current status of all hosts by running + + $ ping903q + +without arguments. Note, that depending on your settings the output +can be huge. + +Please refer to ping903q(1), for a detailed discussion of the tool. + +* Nagios external check + +The ping903q tool can be used as a Nagios external check program. The +following snipped illustrates the simple Nagios configuration that +makes use of it: + + # Define the check_ping903 command + define command { + command_name check_ping903 + command_line /usr/bin/ping903q -r -H $HOSTADDRESS$ -w $ARG1$ -c $ARG2$ + } + + # Define the service using the new command + define service { + host_name server.example.net + address 203.0.113.1 + service_description Server status + check_command check_ping903!200.0,20%!600.0,60% + check_interval 5 + retry_interval 1 + } + +* Installation from a git clone + +If you are building from a clone of the Git repository, you will need +GNU autotools to bootstrap the package first. Run + + ./bootstrap + +in the top level source directory. This will create the configure +script and populate the directory with the missing files. Then proceed +as described above. + +* REST API + +The default channel for communication with the ping903 daemon is the +HTTP socket open on localhost port 8080. Only GET requests are +allowed. The following endpoints are provided: + +** /host/NAME + +NAME is the IP address or hostname. The server will look up this +string in the list of configured hosts and, if found, return the +statistics information for that host. Note that NAME is treated as a +character string and must coincide exactly with the IP or hostname as +it was supplied in configuration. In particular, if a host was +specified by its symbolic DNS name in the configuration, exactly that +name must be used in URL to obtain statistics for that host. If you +wish to use IP, see the </ip> or </match> endpoints, discussed below. + +On success a JSON object is returned. The following keys are defined +in that object: + +- "name": string + +The IP or hostname of the host under which it was supplied in the +ip-list. + +- "validity": boolean + +Status of this record. If false, the data has not been collected yet +or the host is unreachable. More detailed information is available in +the "status" member (see below). If "validity" is false, only the +following keys are warranted to be present in the object: "name", +"validity", "status", and "xmit-timestamp". If it is true, full +statistics is available as described below. + +- "status": string + +Detailed status of the object. Following values are defined: + + "init" + Initial state: data are being collected ("validity":false). + "valid" + The object is valid and its statistics is reliable ("validity": true). + "pending" + The object is valid, it contains reliable statistics. The host + is being probed at the moment and the object will be updated + soon ("validity": true). + "invalid" + Host is unreachable. No statistics available ("validity": false). + +- "xmit-timestamp": number + +Time (the number of seconds since the Epoch) when the last ICMP +ECHO request was transmitted. + +- "start-timestamp": number + +Time when the recent probe sequence was initiated. + +- "stop-timestamp": number + +Time when the recent probe sequence was finished. + +- "xmit": number + +Number of ICMP ECHO requests transmitted during the probe. + +- "recv": number + +Number of ICMP ECHO responses received during the probe. + +- "loss": number + +Percentage of lost packets. + +- "tmin": number + +Minimal round-trip time observed during the probe. + +- "tmax": number + +Maximal round-trip time observed during the probe. + +- "avg": number + +Average round-trip time. + +- "stddev": number + +Standard deviation of round-trip times. + +- "alive": boolean + +Host status computed as a result of the probe. It is true, if the +difference between "xmit" and "recv" parameters is less than the +"tolerance" configuration setting, and false otherwise. + +Example of the returned JSON for a reachable host: + + { + "alive":true, + "avg":25.85150, + "loss":0.00000, + "name":"203.0.113.1", + "recv":10.00000, + "start-timestamp":1581666176.01285, + "status":true, + "stddev":0.03201, + "stop-timestamp":1581666185.27210, + "tmax":25.91400, + "tmin":25.81200, + "xmit":10.00000, + "xmit-timestamp":1581666185.24628 + } + +Example of the returned JSON for an unreachable host: + + { + "name":"203.0.113.2", + "status":false, + "xmit-timestamp":1581666176.01373 + } + +** /host + +Return statistics for all monitored hosts. The result is returned as +an array of JSON objects described above. + +This is an experimental endpoint. Be careful with it, as it may cause +considerable strain on the server. + +** /ip/ADDR + +Request statistics about a particular IP address. The response is the +same as for </host/NAME>. Use this API if hostnames are used in your +ip-list and you need to request statistics using an IP as opposed to +the hostname. + +** /match/NAME-OR-IP + +Return host names that correspond to NAME-OR-IP (a JSON array of +strings). If no matches found, empty array is returned. Multiple +entries can be returned if NAME-OR-IP is a hostname that has multiple +DNS A records, several of which are registered in the ip-list. + +** /config + +Return current server configuration as a JSON object. + +** /config/KEYWORD + +Return the value of a particular configuration setting. + +* Copyright information: + +Copyright (C) 2020 Sergey Poznyakoff + + Permission is granted to anyone to make or distribute verbatim copies + of this document as received, in any medium, provided that the + copyright notice and this permission notice are preserved, + thus giving the recipient permission to redistribute in turn. + + Permission is granted to distribute modified versions + of this document, or of portions of it, + under the above conditions, provided also that they + carry prominent notices stating who last changed them. + +Local Variables: +mode: outline +paragraph-separate: "[ ]*$" +version-control: never +End: + + + @@ -1 +1 @@ -FIXME: Nothing so far
\ No newline at end of file +Thanks to Peter Markeloff for urging me to write the tool. diff --git a/configure.ac b/configure.ac index 906d459..3105332 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ # along with Ping903. If not, see <http://www.gnu.org/licenses/>. AC_PREREQ([2.69]) -AC_INIT([Ping903], [0.1], [gray@gnu.org], +AC_INIT([Ping903], [0.2], [gray@gnu.org], [ping903], [https://puszcza.gnu.org.ua/projects/ping903/]) AC_CONFIG_SRCDIR([src/main.c]) diff --git a/doc/ping903.8 b/doc/ping903.8 index b18bd54..0649aa2 100644 --- a/doc/ping903.8 +++ b/doc/ping903.8 @@ -13,7 +13,7 @@ .\" .\" You should have received a copy of the GNU General Public License .\" along with Ping903. If not, see <http://www.gnu.org/licenses/>. -.TH PING903 8 "February 13, 2020" "PING903" "System Administration" +.TH PING903 8 "February 14, 2020" "PING903" "System Administration" .SH NAME ping903 \- high-performance ICMP monitoring daemon .SH SYNOPSIS @@ -28,7 +28,7 @@ predefined number of ICMP requests sent with certain interval between them. Probes are repeated periodically. .PP The round-trip statistics is collected for each host and is available -for querying via RESTful API. A separate querying utility +for querying via REST API. A separate querying utility .BR ping903q (1) is provided, which allows the user to request the information about each particular host, or all monitored hosts at once. @@ -44,7 +44,7 @@ The monitoring process, in turn, is responsible for periodic polling of the configured hosts, maintaining the statistics information and answering the REST requests. .PP -The progam logs its activities using syslog channel \fBdaemon\fR. +The program logs its activities using syslog channel \fBdaemon\fR. .PP The list of IP addresses to monitor is supplied by an \fIip\-list\fR file specified in the configuration. Probes for each IP from the list diff --git a/doc/ping903q.1 b/doc/ping903q.1 index 326ca81..ab57518 100644 --- a/doc/ping903q.1 +++ b/doc/ping903q.1 @@ -105,7 +105,7 @@ Print program version, copyright information, and exit. .B \-v Turn on verbose output. .SS Options specific for Nagios check mode -The presense of any of these options switches \fBping903q\fR to Nagios +The presence of any of these options switches \fBping903q\fR to Nagios check mode. For this mode to succeed, all three options must be specified. .TP \fB\-H \fIHOST\fR diff --git a/src/Makefile.am b/src/Makefile.am index cc6f1ff..3fcec9f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,3 +34,5 @@ LDADD = ./libping903.a noinst_LIBRARIES = libping903.a libping903_a_SOURCES = json.c json.h mem.c logger.c defs.h +EXTRA_DIST = ping903.conf + @@ -86,6 +86,12 @@ json_value_create(int type) typedef void (*json_format_fun)(struct json_format *, struct json_value *, size_t); typedef void (*json_free_fun)(struct json_value *); +typedef int (*json_copy_fun)(struct json_value *, struct json_value **); + +static int json_copy_generic(struct json_value *, struct json_value **); +static int json_copy_string(struct json_value *, struct json_value **); +static int json_copy_array(struct json_value *, struct json_value **); +static int json_copy_object(struct json_value *, struct json_value **); static void json_format_null(struct json_format *, struct json_value *, size_t level); @@ -108,21 +114,27 @@ static void json_free_object(struct json_value *); static struct json_value_meth { json_format_fun format_fun; json_free_fun free_fun; + json_copy_fun copy_fun; } json_value_meth[] = { - [json_null] = { json_format_null, NULL }, - [json_bool] = { json_format_bool, NULL }, - [json_number] = { json_format_number, NULL }, - [json_string] = { json_format_string, json_free_string }, - [json_array] = { json_format_array, json_free_array }, - [json_object] = { json_format_object, json_free_object } + [json_null] = { json_format_null, NULL, json_copy_generic }, + [json_bool] = { json_format_bool, NULL, json_copy_generic }, + [json_number] = { json_format_number, NULL, json_copy_generic }, + [json_string] = { json_format_string, json_free_string, json_copy_string }, + [json_array] = { json_format_array, json_free_array, json_copy_array }, + [json_object] = { json_format_object, json_free_object, json_copy_object } }; static inline int +is_valid_type(int type) +{ + return type >= 0 + && type < sizeof(json_value_meth) / sizeof(json_value_meth[0]); +} + +static inline int is_valid_value(struct json_value *obj) { - return obj - && obj->type >= 0 - && obj->type < sizeof(json_value_meth)/sizeof(json_value_meth[0]); + return obj && is_valid_type(obj->type); } void @@ -136,6 +148,17 @@ json_value_free(struct json_value *obj) } int +json_value_copy(struct json_value *val, struct json_value **new_val) +{ + if (is_valid_value(val)) + return json_value_meth[val->type].copy_fun(val, new_val); + else { + errno = EINVAL; + return -1; + } +} + +int json_value_format(struct json_value *obj, struct json_format *fmt, size_t level) { ++level; @@ -151,6 +174,30 @@ json_value_format(struct json_value *obj, struct json_format *fmt, size_t level) return -1; } +static int +json_copy_generic(struct json_value *val, struct json_value **ret_val) +{ + struct json_value *p; + + if (!val) { + p = json_new_null(); + if (!p) + return -1; + } else if (is_valid_type(val->type)) { + p = json_value_create(val->type); + if (p) + memcpy(&p->v, &val->v, sizeof(p->v)); + } else { + errno = EINVAL; + } + + if (!p) + return -1; + + *ret_val = p; + return 0; +} + /* Null value */ struct json_value * json_new_null(void) @@ -220,6 +267,20 @@ json_free_string(struct json_value *val) free(val->v.s); } +static int +json_copy_string(struct json_value *val, struct json_value **ret_val) +{ + struct json_value *newval = json_value_create(json_string); + if (!newval) + return -1; + if ((newval->v.s = strdup(val->v.s)) == NULL) { + free(newval); + return -1; + } + *ret_val = newval; + return 0; +} + enum { ESCAPE, UNESCAPE }; static int @@ -286,6 +347,32 @@ json_free_array(struct json_value *val) free(val->v.a); } +static int +json_copy_array(struct json_value *val, struct json_value **ret_val) +{ + struct json_value *newval; + size_t i; + + newval = json_new_array(); + if (!newval) + return -1; + if (!(newval->v.a->ov = + calloc(val->v.a->oc, sizeof(val->v.a->ov[0])))) { + free(newval); + return -1; + } + newval->v.a->oc = newval->v.a->on = val->v.a->oc; + for (i = 0; i < val->v.a->oc; i++) { + if (json_value_copy(val->v.a->ov[i], &newval->v.a->ov[i])) { + newval->v.a->oc = i; + json_value_free(newval); + return -1; + } + } + *ret_val = newval; + return 0; +} + int json_array_expand(struct json_value *jv) { @@ -411,6 +498,27 @@ json_free_object(struct json_value *val) } static int +json_copy_object(struct json_value *val, struct json_value **ret_val) +{ + struct json_value *newval; + struct json_pair *p; + + if (!(newval = json_new_object())) + return -1; + for (p = val->v.o->head; p; p = p->next) { + struct json_value *elt = NULL; + + if (json_value_copy(p->v, &elt) + || json_object_set(newval, p->k, elt)) { + json_value_free(elt); + json_value_free(newval); + return -1; + } + } + return 0; +} + +static int json_object_lookup_or_install(struct json_object *obj, char const *name, int install, struct json_pair **retval) @@ -51,6 +51,7 @@ struct json_format int json_value_format(struct json_value *obj, struct json_format *fmt, size_t level); void json_value_free(struct json_value *); +int json_value_copy(struct json_value *val, struct json_value **new_val); void *json_2nrealloc(void *p, size_t *pn, size_t s); diff --git a/src/ping903.c b/src/ping903.c index 99e3a80..4e5310f 100644 --- a/src/ping903.c +++ b/src/ping903.c @@ -263,10 +263,37 @@ ept_config(struct MHD_Connection *conn, { struct json_value *val; + while (*suffix == '/') + suffix++; + val = config_to_json(); if (!val) return http_error(conn, method, url, MHD_HTTP_INTERNAL_SERVER_ERROR); + + if (*suffix) { + struct json_value *jv, *cp; + int ret; + + if (json_object_get(val, suffix, &jv)) { + ret = http_error(conn, method, url, + (errno == ENOENT) + ? MHD_HTTP_NOT_FOUND + : MHD_HTTP_INTERNAL_SERVER_ERROR); + json_value_free(val); + return ret; + } + + if (json_value_copy(jv, &cp)) { + ret = http_error(conn, method, url, + MHD_HTTP_INTERNAL_SERVER_ERROR); + json_value_free(val); + return ret; + } + json_value_free(val); + val = cp; + } + return httpd_json_response(conn, url, method, val); } @@ -375,7 +402,7 @@ struct endpoint { }; static struct endpoint endpoint[] = { - { "/config", EPT_EXACT, MHD_HTTP_METHOD_GET, ept_config }, + { "/config", EPT_PREFIX, MHD_HTTP_METHOD_GET, ept_config }, { "/host", EPT_PREFIX, MHD_HTTP_METHOD_GET, ept_host_stat }, { "/ip", EPT_PREFIX, MHD_HTTP_METHOD_GET, ept_ip_stat }, { "/match", EPT_PREFIX, MHD_HTTP_METHOD_GET, ept_ip_match }, diff --git a/src/ping903.h b/src/ping903.h index 57123a1..5d8dd5b 100644 --- a/src/ping903.h +++ b/src/ping903.h @@ -61,7 +61,16 @@ int cf_syslog_facility(int mode, union cf_callback_arg *arg, void *data); char *get_remote_ip(struct MHD_Connection *conn); +enum { + HOST_STAT_INIT, /* Initial state: data are being collected */ + HOST_STAT_VALID, /* The record is valid */ + HOST_STAT_PENDING, /* The record is valid; new data are being + collected */ + HOST_STAT_INVALID /* The record is invalid (host unreachable) */ +}; + struct host_stat { + int status; struct timeval start_tv; struct timeval stop_tv; unsigned long xmit_count; @@ -73,7 +82,7 @@ struct host_stat { }; static inline int host_stat_is_valid(struct host_stat const *hs) { - return hs->start_tv.tv_sec > 0; + return hs->status == HOST_STAT_VALID || hs->status == HOST_STAT_PENDING; } typedef struct hostaddr { diff --git a/src/ping903q.c b/src/ping903q.c index 7007745..b8a1053 100644 --- a/src/ping903q.c +++ b/src/ping903q.c @@ -417,14 +417,18 @@ print_host_status(struct json_value *obj, void *unused) jv = ejson_get(obj, "name", json_string); name = jv->v.s; - jv = ejson_get(obj, "status", json_bool); - if (!jv->v.b) { + jv = ejson_get(obj, "status", json_string); + if (strcmp(jv->v.s, "init") == 0) { + printf("%s: no data available yet; try later\n", name); + return EX_NAGIOS_UNKNOWN; + } else if (strcmp(jv->v.s, "invalid") == 0) { printf("no response from %s\n", name); return EX_NAGIOS_CRITICAL; } + /* Status values "pending" and "valid" are OK */ alive = ejson_get(obj, "alive", json_bool)->v.b; - printf("%s %s\n", name, alive ? "alive" : "not alive"); + printf("%s is %s\n", name, alive ? "alive" : "not alive"); if (verbose) { double xmit = ejson_get(obj, "xmit", json_number)->v.n; double recv = ejson_get(obj, "recv", json_number)->v.n; @@ -673,7 +677,7 @@ nagios_check(struct json_value *obj, void *data) jv = ejson_get(obj, "status", json_bool); if (!jv->v.b) { - printf("PING CRITICAL - Packet loss = 100%"); + printf("PING CRITICAL - Packet loss = 100%%"); print_perfdata(cd->cth.round_trip, 100.0, cd); exit(EX_NAGIOS_CRITICAL); } diff --git a/src/pinger.c b/src/pinger.c index 8ce22d1..b722fcf 100644 --- a/src/pinger.c +++ b/src/pinger.c @@ -343,6 +343,7 @@ host_stat(HOSTADDR *host, struct timeval const *tv) host->stat_last.avg = avg; host->stat_last.stddev = nsqrt(vari, 0.0005); } + host->stat_last.status = HOST_STAT_VALID; } /* Reset runtime statistics counters */ @@ -355,6 +356,18 @@ host_reset(HOSTADDR *host) host->tmax = 0; host->tsum = 0; host->tsumsq = 0; + switch (host->stat_last.status) { + case HOST_STAT_INIT: + break; + case HOST_STAT_VALID: + host->stat_last.status = HOST_STAT_PENDING; + break; + case HOST_STAT_PENDING: + host->stat_last.status = HOST_STAT_INVALID; + break; + case HOST_STAT_INVALID: + break; + } } static inline double @@ -369,6 +382,12 @@ get_host_stat(HOSTADDR *host, struct json_value **retval) struct json_value *obj, *v; struct host_stat const *st = &host->stat_last; double ts; + static char const *host_stat_status[] = { + "init", + "valid", + "pending", + "invalid" + }; if (!(obj = json_new_object())) goto err; @@ -377,8 +396,11 @@ get_host_stat(HOSTADDR *host, struct json_value **retval) || json_object_set(obj, "name", v)) goto err; if (!(v = json_new_bool(host_stat_is_valid(st))) - || json_object_set(obj, "status", v)) + || json_object_set(obj, "validity", v)) goto err; + if (!(v = json_new_string(host_stat_status[st->status])) + || json_object_set(obj, "status", v)) + goto err; ts = timeval_to_double(&host->xmit_tv); if (!(v = json_new_number(ts)) || json_object_set(obj, "xmit-timestamp", v)) |