aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2020-02-27 08:52:08 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2020-02-27 09:37:24 +0200
commitf162128427e54f18046bf234403f402d7fc5393e (patch)
treebfcefd39e4f425d8f3931473bc98415f19b0042c
parentdd6380a70bd223424e4195add16b6ace45841e48 (diff)
downloadping903-f162128427e54f18046bf234403f402d7fc5393e.tar.gz
ping903-f162128427e54f18046bf234403f402d7fc5393e.tar.bz2
Process updates asynchronously.
Instead of directly modifying the host list, update requests are queued and applied to the list at the start of the next ping cycle. This speed ups updates and avoids their adverse effect on non-destructive get requests. * README: Document changes. * doc/ping903.conf.5: Document the http-backlog-size parameter. * src/ping903.c (http_response_detail): New function. (ept_ip_delete, ept_ip_put, ept_ip_post) (ept_host_stat, ept_ip_stat): Provide meanungful error descriptions. * src/ping903.h: Definitions for the Update and Get error codes. * src/pinger.c: Queue update requests and commit them to the main host list at the beginning of the ping cycle. (update_mutex): New variable. (check_host,update_add) (update_commit): New functions. (hostlist_updated): Remove variable. (get_hostname_stat,get_ipaddr_stat,get_all_host_stat) (get_all_hosts,get_host_matches): Return meaningful error codes. (pinger_host_delete_by_name,pinger_host_add_name) (pinger_hostlist_set): Operate on the update request queue instead of the main host list. Return meaningful error codes. (start_probe): Remove. (p903_scheduler): Commit updates at the beginning of the cycle. Lock the list using sendq_mutex. (p903_saver): Call update_commit.
-rw-r--r--README14
-rw-r--r--doc/ping903.conf.59
-rw-r--r--src/ping903.c150
-rw-r--r--src/ping903.h19
-rw-r--r--src/pinger.c329
5 files changed, 375 insertions, 146 deletions
diff --git a/README b/README
index 2b78c51..688d431 100644
--- a/README
+++ b/README
@@ -381,7 +381,16 @@ element of the "ip-list" array, the "index" attribute contains the
** PUT /config/ip-list/IP
Adds IP to the current IP list. Returns HTTP status 201 (Created) on
-success. If such an IP is already in the list, returns 403 (Forbidden).
+success. On error, the following codes can be returned:
+ - 403 (Forbidden)
+ The entry for this IP address already exists or (if a hostname is
+ given) the argument cannot be resolved to a IPv4 address. If the
+ Content-Type of the response is "application/json", the "message"
+ attribute of the returned JSON object supplies an explanation of
+ the error.
+ - 500 (Internal server error)
+
+If such an IP is already in the list, returns .
** DELETE /config/ip-list/IP-OR-HOSTNAME
@@ -389,6 +398,9 @@ Deletes IP-OR-HOSTNAME from the IP list. Returns 200 (OK) on success.
If IP-OR-HOSTNAME was not found in the IP list or is immutable,
returns 404 (Not found).
+All update requests are queued and take effect at the beginning of the
+next ping probe.
+
* Copyright information:
diff --git a/doc/ping903.conf.5 b/doc/ping903.conf.5
index c6bcb69..7c29de9 100644
--- a/doc/ping903.conf.5
+++ b/doc/ping903.conf.5
@@ -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.CONF 5 "February 13, 2020" "PING903.CONF" "File Formats Manual"
+.TH PING903.CONF 5 "February 27, 2020" "PING903.CONF" "File Formats Manual"
.SH NAME
ping903.conf \- configuration file for high-performance ICMP monitoring daemon
.SH DESCRIPTION
@@ -107,6 +107,13 @@ To summarize, possible arguments are:
Default is \fB0.0.0.0:8080\fR.
.TP
+\fBhttp\-backlog\-size \fIN\fR
+Configures the size of the
+.BR listen(2)
+backlog queue. Default is the platform-dependent value
+.BR SOMAXCONN ,
+(128 on most GNU/Linux systems).
+.TP
\fBaccess\-log \fIBOOL\fR
Enable apache-style HTTPD access logging. Valid \fIBOOL\fR values are:
.BR 1 ,
diff --git a/src/ping903.c b/src/ping903.c
index 7bfc77a..aa7d745 100644
--- a/src/ping903.c
+++ b/src/ping903.c
@@ -181,6 +181,40 @@ http_response(struct MHD_Connection *conn,
MHD_destroy_response(resp);
return ret;
}
+
+static int httpd_json_response(struct MHD_Connection *conn,
+ char const *url, char const *method,
+ int status,
+ struct json_value *val);
+
+static int
+http_response_detail(struct MHD_Connection *conn,
+ char const *method, char const *url, int status,
+ char const *message, int index)
+{
+ struct json_value *jv, *errobj = json_new_object();
+ int rc;
+
+ if (!errobj)
+ goto err;
+ if ((jv = json_new_string(message)) == NULL)
+ goto err;
+ if (json_object_set(errobj, "message", jv))
+ goto err;
+ if (index) {
+ if ((jv = json_new_number(index)) == NULL)
+ goto err;
+ if (json_object_set(errobj, "index", jv))
+ goto err;
+ }
+ rc = httpd_json_response(conn, url, method, status, errobj);
+ json_value_free(errobj);
+ return rc;
+err:
+ json_value_free(errobj);
+ return http_response(conn, method, url,
+ MHD_HTTP_INTERNAL_SERVER_ERROR);
+}
struct strbuf {
char *base;
@@ -310,9 +344,22 @@ ept_ip_delete(struct MHD_Connection *conn,
suffix++;
if (!*suffix)
return http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
- if (pinger_host_delete_by_name(suffix))
- return http_response(conn, method, url, MHD_HTTP_NOT_FOUND);
- return http_response(conn, method, url, MHD_HTTP_OK);
+ switch (pinger_host_delete_by_name(suffix)) {
+ case UPD_OK:
+ ret = http_response(conn, method, url, MHD_HTTP_OK);
+ break;
+
+ case UPD_EXISTS:
+ ret = http_response_detail(conn, method, url,
+ MHD_HTTP_NOT_FOUND,
+ "No such host", 0);
+ break;
+
+ default:
+ ret = http_response(conn, method, url,
+ MHD_HTTP_INTERNAL_SERVER_ERROR);
+ }
+ return ret;
}
static int
@@ -326,9 +373,27 @@ ept_ip_put(struct MHD_Connection *conn,
suffix++;
if (!*suffix)
return http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
- if (pinger_host_add_name(suffix))
- //FIXME
- return http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
+ switch (pinger_host_add_name(suffix)) {
+ case UPD_OK:
+ break;
+
+ case UPD_NORESOLV:
+ return http_response_detail(conn, method, url,
+ MHD_HTTP_FORBIDDEN,
+ "Hostname does not resolve",
+ 0);
+
+ case UPD_NOMEM:
+ return http_response(conn, method, url,
+ MHD_HTTP_INTERNAL_SERVER_ERROR);
+
+ case UPD_EXISTS:
+ return http_response_detail(conn, method, url,
+ MHD_HTTP_FORBIDDEN,
+ "Hostname already exists",
+ 0);
+ }
+
return http_response(conn, method, url, MHD_HTTP_CREATED);
}
@@ -344,32 +409,9 @@ ept_ip_post(struct MHD_Connection *conn,
status = pinger_hostlist_set(obj, &err_text, &err_pos);
if (!err_text && !err_pos)
return http_response(conn, method, url, status);
- else {
- struct json_value *jv, *err = json_new_object();
- char *str;
- int rc;
-
- if (!err)
- goto err;
- if ((jv = json_new_string(err_text)) == NULL)
- goto err;
- if (json_object_set(err, "message", jv))
- goto err;
- if (err_pos) {
- if ((jv = json_new_number(err_pos)) == NULL)
- goto err;
- if (json_object_set(err, "index", jv))
- goto err;
- }
- str = json_to_str(err);
- rc = httpd_json_response(conn, url, method, status, err);
- json_value_free(err);
- return rc;
- err:
- json_value_free(err);
- return http_response(conn, method, url,
- MHD_HTTP_INTERNAL_SERVER_ERROR);
- }
+ else
+ return http_response_detail(conn, method, url, status,
+ err_text, err_pos);
}
static int
@@ -378,7 +420,7 @@ ept_host_stat(struct MHD_Connection *conn,
struct json_value *unused)
{
struct json_value *val;
- int rc;
+ int rc, ret;
while (*suffix == '/')
suffix++;
@@ -388,11 +430,23 @@ ept_host_stat(struct MHD_Connection *conn,
} else {
rc = get_hostname_stat(suffix, &val);
}
- if (rc)
- return http_response(conn, method, url,
- MHD_HTTP_INTERNAL_SERVER_ERROR);
+ switch (rc) {
+ case GET_OK:
+ ret = httpd_json_response(conn, url, method, MHD_HTTP_OK, val);
+ break;
+
+ case GET_NOENT:
+ ret = http_response_detail(conn, method, url,
+ MHD_HTTP_NOT_FOUND,
+ "No such host", 0);
+ break;
- return httpd_json_response(conn, url, method, MHD_HTTP_OK, val);
+ default:
+ ret = http_response(conn, method, url,
+ MHD_HTTP_INTERNAL_SERVER_ERROR);
+
+ }
+ return ret;
}
static int
@@ -419,14 +473,24 @@ ept_ip_stat(struct MHD_Connection *conn,
return http_response(conn, method, url,
MHD_HTTP_NOT_FOUND);
rc = get_ipaddr_stat(res->ai_addr, res->ai_addrlen, &val);
- if (rc)
- ret = http_response(conn, method, url,
- MHD_HTTP_INTERNAL_SERVER_ERROR);
- else if (val)
+ switch (rc) {
+ case GET_OK:
ret = httpd_json_response(conn, url, method,
MHD_HTTP_OK, val);
- else
- ret = http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
+ break;
+
+ case GET_NOENT:
+ ret = http_response_detail(conn, method, url,
+ MHD_HTTP_NOT_FOUND,
+ "No host matches IP", 0);
+ break;
+
+ default:
+ ret = http_response(conn, method, url,
+ MHD_HTTP_INTERNAL_SERVER_ERROR);
+ break;
+
+ }
freeaddrinfo(res);
return ret;
}
diff --git a/src/ping903.h b/src/ping903.h
index 2c78c1c..396a114 100644
--- a/src/ping903.h
+++ b/src/ping903.h
@@ -62,6 +62,16 @@ int cf_syslog_facility(int mode, union cf_callback_arg *arg, void *data);
void pinger_setup(void);
int pinger_host_add(char const *name, struct sockaddr *addr, socklen_t addrlen);
+
+/* Return codes for pinger update functions */
+enum {
+ UPD_OK, /* Update successful. */
+ UPD_NOMEM, /* Not enough memory. */
+ UPD_EXISTS, /* When adding: such entry already exists. */
+ /* When deleting: such entry does not exist. */
+ UPD_NORESOLV /* Host name does not resolve */
+};
+
int pinger_host_delete_by_name(char const *name);
int pinger_host_add_name(char const *name);
int pinger_hostlist_set(struct json_value *obj, char const **err_text,
@@ -131,6 +141,15 @@ extern size_t data_length;
extern unsigned int httpd_backlog_size;
struct json_value *config_to_json(void);
+
+/* Return codes for get_ function family. */
+enum {
+ GET_OK, /* Success. */
+ GET_NOMEM, /* Not enough memory. */
+ GET_NOENT /* Requested entry not found. */
+ /* Obviously, this is never returned by get_all_*
+ functions. */
+};
int get_hostname_stat(char const *name, struct json_value **retval);
int get_ipaddr_stat(struct sockaddr *sa, int salen, struct json_value **retval);
int get_all_hosts(struct json_value **);
diff --git a/src/pinger.c b/src/pinger.c
index 54fe4d2..96a55ae 100644
--- a/src/pinger.c
+++ b/src/pinger.c
@@ -224,9 +224,19 @@ hostlist_locate(HOSTLIST *list, char const *name)
}
static HOSTLIST *hostlist;
-static pthread_rwlock_t hostlist_rwlock = PTHREAD_RWLOCK_INITIALIZER;
static HOSTPING *conf_hostping_tail;
-static int hostlist_updated;
+static pthread_rwlock_t hostlist_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+
+typedef enum update_type {
+ UPDATE_APPEND,
+ UPDATE_REPLACE,
+ UPDATE_DELETE
+} UPDATE_TYPE;
+
+static pthread_mutex_t update_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int check_host(char const *name);
+static int update_add(UPDATE_TYPE t, void *data);
+static void update_commit(void);
void
pinger_setup(void)
@@ -243,7 +253,6 @@ pinger_host_add(char const *name, struct sockaddr *addr, socklen_t addrlen)
if (!hp)
return -1;
hostlist_add(hostlist, hp);
- hostlist_updated = 1;
return 0;
}
@@ -418,7 +427,7 @@ get_hostping_stat(HOSTPING *host, struct json_value **retval)
hostping_unlock(host);
*retval = obj;
- return 0;
+ return GET_OK;
err:
hostping_unlock(host);
@@ -426,14 +435,14 @@ get_hostping_stat(HOSTPING *host, struct json_value **retval)
json_value_free(v);
json_value_free(obj);
- return -1;
+ return GET_NOMEM;
}
int
get_hostname_stat(char const *name, struct json_value **retval)
{
HOSTPING *hp;
- int rc = 0;
+ int rc = GET_NOENT;
*retval = NULL;
pthread_rwlock_rdlock(&hostlist_rwlock);
@@ -451,7 +460,7 @@ int
get_ipaddr_stat(struct sockaddr *sa, int salen, struct json_value **retval)
{
HOSTPING *hp;
- int rc;
+ int rc = GET_NOENT;
*retval = NULL;
pthread_rwlock_rdlock(&hostlist_rwlock);
@@ -463,7 +472,7 @@ get_ipaddr_stat(struct sockaddr *sa, int salen, struct json_value **retval)
}
}
pthread_rwlock_unlock(&hostlist_rwlock);
- return 0;
+ return rc;
}
int
@@ -471,25 +480,25 @@ get_all_host_stat(struct json_value **retval)
{
struct json_value *ar;
HOSTPING *hp;
- int rc = 0;
+ int rc = GET_OK;
if (!(ar = json_new_array()))
- return -1;
+ return GET_NOMEM;
pthread_rwlock_rdlock(&hostlist_rwlock);
FOR_EACH_HOSTPING(hp) {
struct json_value *v;
if (get_hostping_stat(hp, &v)) {
- rc = -1;
+ rc = GET_NOMEM;
break;
}
if (json_array_append(ar, v)) {
json_value_free(v);
- rc = -1;
+ rc = GET_NOMEM;
break;
}
}
pthread_rwlock_unlock(&hostlist_rwlock);
- if (rc == 0)
+ if (rc == GET_OK)
*retval = ar;
else
json_value_free(ar);
@@ -501,26 +510,26 @@ get_all_hosts(struct json_value **retval)
{
struct json_value *ar;
HOSTPING *hp;
- int rc = 0;
+ int rc = GET_OK;
if (!(ar = json_new_array()))
- return -1;
+ return GET_NOMEM;
pthread_rwlock_rdlock(&hostlist_rwlock);
FOR_EACH_HOSTPING(hp) {
struct json_value *jv;
jv = json_new_string(hp->name);
if (!jv) {
- rc = -1;
+ rc = GET_NOMEM;
break;
}
if (json_array_append(ar, jv)) {
json_value_free(jv);
- rc = -1;
+ rc = GET_NOMEM;
break;
}
}
pthread_rwlock_unlock(&hostlist_rwlock);
- if (rc == 0)
+ if (rc == GET_OK)
*retval = ar;
else
json_value_free(ar);
@@ -578,11 +587,11 @@ get_host_matches(struct addrinfo **aip, struct json_value **retval)
}
}
}
-
+
ret = 0;
*retval = ar;
ar = NULL;
-err:
+err:
pthread_rwlock_unlock(&hostlist_rwlock);
if (ai_tail) {
ai_tail->ai_next = ai;
@@ -596,19 +605,23 @@ int
pinger_host_delete_by_name(char const *name)
{
HOSTPING *hp;
- int rc = -1;
-
- pthread_rwlock_wrlock(&hostlist_rwlock);
- FOR_EACH_LOCAL_HOSTPING(hp) {
- if (strcmp(hp->name, name) == 0) {
- hostlist_remove(hostlist, hp);
- hostping_free(hp);
- hostlist_updated = 1;
- rc = 0;
- break;
+ int rc;
+
+ pthread_mutex_lock(&update_mutex);
+ if (check_host(name)) {
+ char *cp = strdup(name);
+ if (cp) {
+ if (update_add(UPDATE_DELETE, cp) == 0)
+ rc = UPD_OK;
+ else {
+ rc = UPD_NOMEM;
+ free(cp);
+ }
}
+ } else {
+ rc = UPD_EXISTS;
}
- pthread_rwlock_unlock(&hostlist_rwlock);
+ pthread_mutex_unlock(&update_mutex);
return rc;
}
@@ -618,29 +631,34 @@ pinger_host_add_name(char const *name)
int rc = 0;
struct addrinfo hints, *res;
HOSTPING *hp;
-
- pthread_rwlock_rdlock(&hostlist_rwlock);
- FOR_EACH_HOSTPING(hp) {
- if (strcmp(hp->name, name) == 0) {
- rc = -1;
- break;
- }
- }
- pthread_rwlock_unlock(&hostlist_rwlock);
- if (rc)
- return rc;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
rc = getaddrinfo(name, NULL, &hints, &res);
if (rc) {
- return -2;
+ return UPD_NORESOLV;
}
-
- pthread_rwlock_wrlock(&hostlist_rwlock);
- rc = pinger_host_add(name, res->ai_addr, res->ai_addrlen);
- pthread_rwlock_unlock(&hostlist_rwlock);
+
+ pthread_mutex_lock(&update_mutex);
+ if (check_host(name) == 0) {
+ rc = UPD_NOMEM;
+ hp = hostping_create(name, res->ai_addr, res->ai_addrlen);
+ if (hp) {
+ HOSTLIST *hl = hostlist_create();
+ if (hl) {
+ hostlist_add(hl, hp);
+ if (update_add(UPDATE_APPEND, hl) == 0)
+ rc = UPD_OK;
+ else
+ hostlist_free(hl);
+ } else
+ hostping_free(hp);
+ }
+ } else {
+ rc = UPD_EXISTS;
+ }
+ pthread_mutex_unlock(&update_mutex);
freeaddrinfo(res);
return rc;
}
@@ -649,7 +667,7 @@ int
pinger_hostlist_set(struct json_value *obj, char const **err_text,
int *err_pos)
{
- int append;
+ int mode = UPDATE_APPEND;
struct json_value *ar;
HOSTLIST *tmp = NULL;
HOSTPING *hp;
@@ -673,9 +691,9 @@ pinger_hostlist_set(struct json_value *obj, char const **err_text,
0);
}
if (strcmp(jv->v.s, "append") == 0)
- append = 1;
+ mode = UPDATE_APPEND;
else if (strcmp(jv->v.s, "replace") == 0)
- append = 0;
+ mode = UPDATE_REPLACE;
else
RETERR(MHD_HTTP_BAD_REQUEST, "\"mode\": invalid value",
0);
@@ -685,7 +703,7 @@ pinger_hostlist_set(struct json_value *obj, char const **err_text,
"\"ip-list\" attribute missing",
0);
} else if (obj->type == json_array) {
- append = 0;
+ mode = UPDATE_APPEND;
ar = obj;
} else {
RETERR(MHD_HTTP_BAD_REQUEST, "bad object type", 0);
@@ -718,39 +736,163 @@ pinger_hostlist_set(struct json_value *obj, char const **err_text,
RETERR(MHD_HTTP_INTERNAL_SERVER_ERROR, NULL, i + 1);
hostlist_add(tmp, hp);
}
-
- pthread_rwlock_wrlock(&hostlist_rwlock);
- if (append) {
- hostlist_concat(hostlist, tmp);
- hostlist_free(tmp);
- } else if (conf_hostping_tail) {
- hp = conf_hostping_tail->next;
- if (tmp->head)
- tmp->head->prev = conf_hostping_tail;
- conf_hostping_tail->next = tmp->head;
- hostlist->tail = tmp->tail;
- hostlist->count += tmp->count;
- while (hp) {
- HOSTPING *next = hp->next;
- hostping_free(hp);
- hp = next;
- hostlist->count--;
- }
- free(tmp);
+
+ if (update_add(mode, tmp)) {
+ RETERR(MHD_HTTP_INTERNAL_SERVER_ERROR, NULL, 0);
} else {
- hostlist_free(hostlist);
- hostlist = tmp;
+ *err_text = NULL;
+ *err_pos = 0;
+ return MHD_HTTP_OK;
}
- hostlist_updated = 1;
- pthread_rwlock_unlock(&hostlist_rwlock);
- *err_text = NULL;
- *err_pos = 0;
- return MHD_HTTP_OK;
err:
hostlist_free(tmp);
return ret;
}
+typedef struct update_entry {
+ enum update_type type;
+ struct update_entry *next;
+ union {
+ void *ptr;
+ HOSTLIST *hlist;
+ char *name;
+ } v;
+} UPDATE_ENTRY;
+
+static UPDATE_ENTRY *update_head, *update_tail;
+
+static void save_local_ip_list(void);
+
+static int
+update_add(UPDATE_TYPE t, void *data)
+{
+ UPDATE_ENTRY *uent = malloc(sizeof(*uent));
+
+ if (!uent)
+ return -1;
+
+ uent->type = t;
+ uent->v.ptr = data;
+ uent->next = NULL;
+
+ if (uent->type == UPDATE_REPLACE) {
+ while (update_head) {
+ UPDATE_ENTRY *next = update_head->next;
+ switch (update_head->type) {
+ case UPDATE_APPEND:
+ case UPDATE_REPLACE:
+ hostlist_free(update_head->v.hlist);
+ break;
+ case UPDATE_DELETE:
+ free(update_head->v.name);
+ }
+ free(update_head);
+ update_head = next;
+ }
+ update_tail = NULL;
+ }
+
+ if (update_tail)
+ update_tail->next = uent;
+ else
+ update_head = uent;
+ update_tail = uent;
+ return 0;
+}
+
+static void
+update_commit(void)
+{
+ HOSTPING *hp;
+ int upd;
+
+ pthread_mutex_lock(&update_mutex);
+ pthread_rwlock_wrlock(&hostlist_rwlock);
+ upd = update_head != NULL;
+ while (update_head) {
+ UPDATE_ENTRY *next = update_head->next;
+ switch (update_head->type) {
+ case UPDATE_APPEND:
+ hostlist_concat(hostlist, update_head->v.hlist);
+ hostlist_free(update_head->v.hlist);
+ break;
+
+ case UPDATE_REPLACE:
+ if (conf_hostping_tail) {
+ HOSTLIST *tmp = update_head->v.hlist;
+
+ hp = conf_hostping_tail->next;
+ if (tmp->head)
+ tmp->head->prev = conf_hostping_tail;
+ conf_hostping_tail->next = tmp->head;
+ hostlist->tail = tmp->tail;
+ hostlist->count += tmp->count;
+ while (hp) {
+ HOSTPING *next = hp->next;
+ hostping_free(hp);
+ hp = next;
+ hostlist->count--;
+ }
+ free(tmp);
+ } else {
+ hostlist_free(hostlist);
+ hostlist = update_head->v.hlist;
+ }
+ break;
+
+ case UPDATE_DELETE:
+ FOR_EACH_LOCAL_HOSTPING(hp) {
+ if (strcmp(hp->name, update_head->v.name) == 0) {
+ hostlist_remove(hostlist, hp);
+ hostping_free(hp);
+ break;
+ }
+ }
+ free(update_head->v.name);
+ }
+
+ free(update_head);
+ update_head = next;
+ }
+ update_tail = NULL;
+ if (upd)
+ save_local_ip_list();
+ pthread_rwlock_unlock(&hostlist_rwlock);
+ pthread_mutex_unlock(&update_mutex);
+}
+
+static int
+check_host(char const *name)
+{
+ HOSTPING *hp;
+ UPDATE_ENTRY *uent;
+ int found;
+
+ FOR_EACH_HOSTPING(hp) {
+ if (strcmp(hp->name, name) == 0)
+ return 1;
+ }
+ found = 0;
+ for (uent = update_head; uent; uent = uent->next) {
+ switch (update_head->type) {
+ case UPDATE_APPEND:
+ case UPDATE_REPLACE:
+ for (hp = uent->v.hlist->head; hp; hp = hp->next) {
+ if (strcmp(hp->name, name) == 0) {
+ found++;
+ break;
+ }
+ }
+ break;
+ case UPDATE_DELETE:
+ if (strcmp(uent->v.name, name) == 0)
+ found--;
+ }
+ }
+ return found;
+}
+
+
static int ping_fd;
static pthread_mutex_t sendq_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -835,7 +977,6 @@ p903_init(void)
if (hostlist->count == 0) {
info("no IP addresses configured, starting anyway");
}
- hostlist_updated = 0;
proto = getprotobyname("icmp");
if (!proto) {
@@ -981,15 +1122,6 @@ send_echo(HOSTPING *host, unsigned char *ping_buffer)
}
}
-static void
-start_probe(void)
-{
- pthread_mutex_lock(&sendq_mutex);
- send_p = 1;
- pthread_cond_broadcast(&sendq_cond);
- pthread_mutex_unlock(&sendq_mutex);
-}
-
static void hostping_commit(HOSTPING *host);
void *
@@ -1023,7 +1155,6 @@ p903_sender(void *p)
send_count = 0;
}
clock_gettime(CLOCK_MONOTONIC, &ts);
- pthread_rwlock_rdlock(&hostlist_rwlock);
FOR_EACH_HOSTPING(hp) {
struct timespec nts;
clock_gettime(CLOCK_MONOTONIC, &nts);
@@ -1040,7 +1171,6 @@ p903_sender(void *p)
TIMER_ABSTIME, &nts,
NULL);
}
- pthread_rwlock_unlock(&hostlist_rwlock);
send_count++;
if (send_count == ping_count)
send_p = 0;
@@ -1223,8 +1353,6 @@ save_local_ip_list(void)
HOSTPING *hp;
size_t i;
- if (!hostlist_updated)
- return;
info("saving mutable IP address list");
fp = fopen(LOCAL_IP_LIST_FILE, "w");
if (!fp) {
@@ -1243,8 +1371,6 @@ save_local_ip_list(void)
fprintf(fp, "%s\n", hp->name);
}
fclose(fp);
-
- hostlist_updated = 0;
}
void *
@@ -1252,16 +1378,19 @@ p903_scheduler(void *p)
{
while (1) {
HOSTPING *hp;
-
- pthread_rwlock_rdlock(&hostlist_rwlock);
+
+ pthread_mutex_lock(&sendq_mutex);
/* Reset all statistics */
FOR_EACH_HOSTPING(hp) {
hostping_reset(hp);
}
- save_local_ip_list();
- pthread_rwlock_unlock(&hostlist_rwlock);
+ /* Commit updates */
+ update_commit();
- start_probe();
+ send_p = 1;
+ pthread_cond_broadcast(&sendq_cond);
+ pthread_mutex_unlock(&sendq_mutex);
+
sleep(probe_interval);
if (verbose)
info("total sent=%u, received=%u",
@@ -1273,9 +1402,7 @@ p903_scheduler(void *p)
void *
p903_saver(void *p)
{
- pthread_rwlock_rdlock(&hostlist_rwlock);
- save_local_ip_list();
- pthread_rwlock_unlock(&hostlist_rwlock);
+ update_commit();
return NULL;
}

Return to:

Send suggestions and report system problems to the System administrator.