summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hbeat.c122
-rw-r--r--hbeat.h9
-rw-r--r--hbeat_test.c24
3 files changed, 155 insertions, 0 deletions
diff --git a/hbeat.c b/hbeat.c
new file mode 100644
index 0000000..e0255a3
--- /dev/null
+++ b/hbeat.c
@@ -0,0 +1,122 @@
+/*
+ * hbeat.c --
+ *
+ * Simple heartbeating.
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "btime.h"
+#include "hbeat.h"
+
+
+struct hbeat_s {
+ char *host;
+ int max_timeout;
+ enum {HOST_ALIVE, HOST_QUIET, HOST_TIMEOUT, HOST_REBOOT} rhost_state;
+ unsigned int last_rhost_btime;
+ time_t start_quiet_time;
+};
+
+
+/*
+ * hbeat_init --
+ *
+ * Init a heartbeat to host, with max_timeout as supplied.
+ *
+ * Returns:
+ * A hbeat handle, or NULL on error;
+ */
+
+hbeat_t
+hbeat_init(const char *host, int max_timeout)
+{
+ struct hbeat_s *hbeatp;
+
+ hbeatp = malloc(sizeof *hbeatp);
+ if (!hbeatp) {
+ return NULL;
+ }
+
+ hbeatp->host = strdup(host);
+ hbeatp->max_timeout = max_timeout;
+ hbeatp->rhost_state = HOST_ALIVE;
+ hbeatp->last_rhost_btime = 0;
+ hbeatp->start_quiet_time = 0;
+
+ return hbeatp;
+}
+
+
+/*
+ * hbeat_free --
+ *
+ * Free a hbeat handle.
+ */
+
+void
+hbeat_free(hbeat_t hbh)
+{
+ struct hbeat_s *hbeatp = hbh;
+
+ free(hbeatp->host);
+ free(hbeatp);
+}
+
+
+/*
+ * hbeat --
+ *
+ * Attempt to contact host in the hbeat handle, run the hbeat
+ * "state machine" to decide if we the host is still "alive."
+ *
+ * Returns:
+ * 1 if host has been active or responded withing max_timeout secs.
+ * 0 if host is dead, no response for > max_timeout secs.
+ */
+
+unsigned int
+hbeat(hbeat_t hbh)
+{
+ struct hbeat_s *hbeatp = hbh;
+ unsigned int hbeat;
+ time_t current_time;
+
+ /* User disabled heart beating */
+ if (!hbeatp->max_timeout) {
+ return 1;
+ }
+
+ hbeat = btime(hbeatp->host);
+ current_time = time(NULL);
+
+ if (!hbeat && (hbeatp->rhost_state == HOST_QUIET)) {
+ if (current_time - hbeatp->start_quiet_time
+ > hbeatp->max_timeout) {
+ hbeatp->rhost_state = HOST_TIMEOUT;
+ return 0;
+ }
+ } else {
+ hbeatp->rhost_state = HOST_QUIET;
+ hbeatp->start_quiet_time = time(NULL);
+ }
+
+ if (hbeat) {
+ if (hbeatp->last_rhost_btime == 0) {
+ hbeatp->last_rhost_btime = hbeat;
+ hbeatp->rhost_state = HOST_ALIVE;
+ hbeatp->start_quiet_time = 0;
+ }
+
+ if (abs(hbeat - hbeatp->last_rhost_btime) > 5) {
+ hbeatp->rhost_state = HOST_REBOOT;
+ return 0;
+ }
+ }
+
+ return 1;
+}
diff --git a/hbeat.h b/hbeat.h
new file mode 100644
index 0000000..1a7b4b8
--- /dev/null
+++ b/hbeat.h
@@ -0,0 +1,9 @@
+/*
+ * hbeat.h
+ */
+
+typedef void * hbeat_t;
+
+extern hbeat_t hbeat_init(const char *host, int max_timeout);
+void hbeat_free(hbeat_t hbh);
+unsigned int hbeat(hbeat_t hbh);
diff --git a/hbeat_test.c b/hbeat_test.c
new file mode 100644
index 0000000..8ea00ee
--- /dev/null
+++ b/hbeat_test.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include "hbeat.h"
+
+int
+main(void)
+{
+ hbeat_t hb;
+ int i;
+ int timeout_max = 10;
+
+ hb = hbeat_init("link-13", timeout_max);
+
+ for (i = 0; i < 10; i++) {
+ printf("hbeat() = %d\n", hbeat(hb));
+ sleep(1);
+ }
+
+ hbeat_free(hb);
+
+ return 0;
+}
+
+
+