]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/heartbeat.c
kes Implement build and install of bpipe-fd.so plugin.
[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 Kern Sibbald.
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_started = true;
69    jcr->hb_dir_bsock = dir;
70
71    /* Hang reading the socket to the SD, and every time we get
72     *   a heartbeat or we get a wait timeout (1 minute), we
73     *   check to see if we need to send a heartbeat to the
74     *   Director.
75     */
76    for ( ; !is_bnet_stop(sd); ) {
77       n = bnet_wait_data_intr(sd, WAIT_INTERVAL);
78       if (me->heartbeat_interval) {
79          now = time(NULL);
80          if (now-last_heartbeat >= me->heartbeat_interval) {
81             bnet_sig(dir, BNET_HEARTBEAT);
82             last_heartbeat = now;
83          }
84       }
85       if (n < 0 || is_bnet_stop(sd)) {
86          break;
87       }
88       if (n == 1) {                   /* input waiting */
89          sd->recv();                  /* read it -- probably heartbeat from sd */
90          if (sd->msglen <= 0) {
91             Dmsg1(100, "Got BNET_SIG %d from SD\n", sd->msglen);
92          } else {
93             Dmsg2(100, "Got %d bytes from SD. MSG=%s\n", sd->msglen, sd->msg);
94          }
95       }
96       Dmsg2(100, "wait_intr=%d stop=%d\n", n, is_bnet_stop(sd));
97    }
98    sd->close();
99    dir->close();
100    jcr->hb_bsock = NULL;
101    jcr->hb_started = false;
102    jcr->hb_dir_bsock = NULL;
103    return NULL;
104 }
105
106 /* Startup the heartbeat thread -- see above */
107 void start_heartbeat_monitor(JCR *jcr)
108 {
109    /*
110     * If no signals are set, do not start the heartbeat because
111     * it gives a constant stream of TIMEOUT_SIGNAL signals that
112     * make debugging impossible.
113     */
114    if (!no_signals) {
115       jcr->hb_bsock = NULL;
116       jcr->hb_started = false;
117       jcr->hb_dir_bsock = NULL;
118       pthread_create(&jcr->heartbeat_id, NULL, sd_heartbeat_thread, (void *)jcr);
119    }
120 }
121
122 /* Terminate the heartbeat thread. Used for both SD and DIR */
123 void stop_heartbeat_monitor(JCR *jcr)
124 {
125    int cnt = 0;
126    if (no_signals) {
127       return;
128    }
129    /* Wait max 10 secs for heartbeat thread to start */
130    while (!jcr->hb_started && cnt++ < 200) {
131       bmicrosleep(0, 50000);         /* wait for start */
132    }
133
134    if (jcr->hb_started) {
135       jcr->hb_bsock->set_timed_out();       /* set timed_out to terminate read */
136       jcr->hb_bsock->set_terminated();      /* set to terminate read */
137    }
138    if (jcr->hb_dir_bsock) {
139       jcr->hb_dir_bsock->set_timed_out();     /* set timed_out to terminate read */
140       jcr->hb_dir_bsock->set_terminated();    /* set to terminate read */
141    }
142    Dmsg0(100, "Send kill to heartbeat id\n");
143    pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL);  /* make heartbeat thread go away */
144    bmicrosleep(0, 50000);
145    cnt = 0;
146    /* Wait max 100 secs for heartbeat thread to stop */
147    while (jcr->hb_started && cnt++ < 200) {
148       pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL);  /* make heartbeat thread go away */
149       bmicrosleep(0, 500000);
150    }
151 }
152
153 /*
154  * Thread for sending heartbeats to the Director when there
155  *   is no SD monitoring needed -- e.g. restore and verify Vol
156  *   both do their own read() on the SD socket.
157  */
158 extern "C" void *dir_heartbeat_thread(void *arg)
159 {
160    JCR *jcr = (JCR *)arg;
161    BSOCK *dir;
162    time_t last_heartbeat = time(NULL);
163
164    pthread_detach(pthread_self());
165
166    /* Get our own local copy */
167    dir = dup_bsock(jcr->dir_bsock);
168
169    jcr->hb_bsock = dir;
170    jcr->hb_started = true;
171
172    for ( ; !is_bnet_stop(dir); ) {
173       time_t now, next;
174
175       now = time(NULL);
176       next = now - last_heartbeat;
177       if (next >= me->heartbeat_interval) {
178          dir->signal(BNET_HEARTBEAT);
179          last_heartbeat = now;
180       }
181       bmicrosleep(next, 0);
182    }
183    dir->close();
184    jcr->hb_bsock = NULL;
185    jcr->hb_started = false;
186    return NULL;
187 }
188
189 /*
190  * Same as above but we don't listen to the SD
191  */
192 void start_dir_heartbeat(JCR *jcr)
193 {
194    if (me->heartbeat_interval) {
195       jcr->dir_bsock->set_locking();
196       pthread_create(&jcr->heartbeat_id, NULL, dir_heartbeat_thread, (void *)jcr);
197    }
198 }
199
200 void stop_dir_heartbeat(JCR *jcr)
201 {
202    if (me->heartbeat_interval) {
203       stop_heartbeat_monitor(jcr);
204    }
205 }