summaryrefslogtreecommitdiffstats
path: root/hbeat.c
diff options
context:
space:
mode:
Diffstat (limited to 'hbeat.c')
-rw-r--r--hbeat.c122
1 files changed, 122 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;
+}