]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/heartbeat.c
- Fix compile problems on Win32
[bacula/bacula] / bacula / src / filed / heartbeat.c
1 /*
2  *  Bacula File Daemon heartbeat routines
3  *    Listens for heartbeats coming from the SD
4  *    If configured, sends heartbeats to Dir
5  *
6  *    Kern Sibbald, May MMIII
7  *
8  *   Version $Id$
9  *
10  */
11 /*
12    Copyright (C) 2003-2005 Kern Sibbald
13
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License
16    version 2 as ammended with additional clauses defined in the
17    file LICENSE in the main source directory.
18
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
22    the file LICENSE for additional details.
23
24  */
25
26 #include "bacula.h"
27 #include "filed.h"
28
29 #define WAIT_INTERVAL 10
30
31 extern "C" void *sd_heartbeat_thread(void *arg);
32 extern "C" void *dir_heartbeat_thread(void *arg);
33 extern bool no_signals;
34
35 /*
36  * Listen on the SD socket for heartbeat signals.
37  * Send heartbeats to the Director every HB_TIME
38  *   seconds.
39  */
40 extern "C" void *sd_heartbeat_thread(void *arg)
41 {
42    int32_t n;
43    JCR *jcr = (JCR *)arg;
44    BSOCK *sd, *dir;
45    time_t last_heartbeat = time(NULL);
46    time_t now;
47
48    pthread_detach(pthread_self());
49
50    /* Get our own local copy */
51    sd = dup_bsock(jcr->store_bsock);
52 #ifndef WIN32
53    int oflags;
54    if ((oflags = fcntl(sd->fd, F_GETFL, 0)) != -1) {
55       fcntl(sd->fd, F_SETFL, oflags|O_NONBLOCK);
56    }
57 #endif
58    dir = dup_bsock(jcr->dir_bsock);
59
60    jcr->hb_bsock = sd;
61    jcr->hb_dir_bsock = dir;
62
63    /* Hang reading the socket to the SD, and every time we get
64     *   a heartbeat or we get a wait timeout (1 minute), we
65     *   check to see if we need to send a heartbeat to the
66     *   Director.
67     */
68    for ( ; !is_bnet_stop(sd); ) {
69       n = bnet_wait_data_intr(sd, WAIT_INTERVAL);
70       if (me->heartbeat_interval) {
71          now = time(NULL);
72          if (now-last_heartbeat >= me->heartbeat_interval) {
73             bnet_sig(dir, BNET_HEARTBEAT);
74             last_heartbeat = now;
75          }
76       }
77       if (is_bnet_stop(sd)) {
78          break;
79       }
80       if (n == 1) {                   /* input waiting */
81          bnet_recv(sd);               /* read it -- probably heartbeat from sd */
82          if (sd->msglen <= 0) {
83             Dmsg1(100, "Got BNET_SIG %d from SD\n", sd->msglen);
84          } else {
85             Dmsg2(100, "Got %d bytes from SD. MSG=%s\n", sd->msglen, sd->msg);
86          }
87       }
88    }
89    bnet_close(sd);
90    bnet_close(dir);
91    jcr->hb_bsock = NULL;
92    jcr->hb_dir_bsock = NULL;
93    return NULL;
94 }
95
96 /* Startup the heartbeat thread -- see above */
97 void start_heartbeat_monitor(JCR *jcr)
98 {
99    /*
100     * If no signals are set, do not start the heartbeat because
101     * it gives a constant stream of TIMEOUT_SIGNAL signals that
102     * make debugging impossible.
103     */
104    if (!no_signals) {
105       jcr->hb_bsock = NULL;
106       jcr->hb_dir_bsock = NULL;
107       pthread_create(&jcr->heartbeat_id, NULL, sd_heartbeat_thread, (void *)jcr);
108    }
109 }
110
111 /* Terminate the heartbeat thread. Used for both SD and DIR */
112 void stop_heartbeat_monitor(JCR *jcr)
113 {
114    int cnt = 0;
115    if (no_signals) {
116       return;
117    }
118    /* Wait max 10 secs for heartbeat thread to start */
119    while (jcr->hb_bsock == NULL && cnt++ < 200) {
120       bmicrosleep(0, 50000);         /* wait for start */
121    }
122    if (!jcr->hb_bsock) {
123    }
124
125    if (jcr->hb_bsock) {
126       jcr->hb_bsock->timed_out = 1;   /* set timed_out to terminate read */
127       jcr->hb_bsock->terminated = 1;  /* set to terminate read */
128    }
129    if (jcr->hb_dir_bsock) {
130       jcr->hb_dir_bsock->timed_out = 1;   /* set timed_out to terminate read */
131       jcr->hb_dir_bsock->terminated = 1;  /* set to terminate read */
132    }
133    pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL);  /* make heartbeat thread go away */
134    bmicrosleep(0, 50000);
135    cnt = 0;
136    /* Wait max 100 secs for heartbeat thread to stop */
137    while (jcr->hb_bsock && cnt++ < 200) {
138       pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL);  /* make heartbeat thread go away */
139       bmicrosleep(0, 500000);
140    }
141    if (jcr->hb_bsock) {
142    }
143 }
144
145 /*
146  * Thread for sending heartbeats to the Director when there
147  *   is no SD monitoring needed -- e.g. restore and verify Vol
148  *   both do their own read() on the SD socket.
149  */
150 extern "C" void *dir_heartbeat_thread(void *arg)
151 {
152    JCR *jcr = (JCR *)arg;
153    BSOCK *dir;
154    time_t last_heartbeat = time(NULL);
155
156    pthread_detach(pthread_self());
157
158    /* Get our own local copy */
159    dir = dup_bsock(jcr->dir_bsock);
160
161    jcr->hb_bsock = dir;
162
163    for ( ; !is_bnet_stop(dir); ) {
164       time_t now, next;
165
166       now = time(NULL);
167       next = now - last_heartbeat;
168       if (next >= me->heartbeat_interval) {
169          bnet_sig(dir, BNET_HEARTBEAT);
170          last_heartbeat = now;
171       }
172       bmicrosleep(next, 0);
173    }
174    bnet_close(dir);
175    jcr->hb_bsock = NULL;
176    return NULL;
177 }
178
179 /*
180  * Same as above but we don't listen to the SD
181  */
182 void start_dir_heartbeat(JCR *jcr)
183 {
184    if (me->heartbeat_interval) {
185       pthread_create(&jcr->heartbeat_id, NULL, dir_heartbeat_thread, (void *)jcr);
186    }
187 }
188
189 void stop_dir_heartbeat(JCR *jcr)
190 {
191    if (me->heartbeat_interval) {
192       stop_heartbeat_monitor(jcr);
193    }
194 }