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