summaryrefslogtreecommitdiffstats
path: root/hbeat.c
blob: e0255a3bd28b3f691de85fba9f6696963ece30cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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;	
}