]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/heartbeat.c
Add a test for error return from bnet_wait... in heartbeat.c
[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 amended 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 (n < 0 || 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       Dmsg2(100, "wait_intr=%d stop=%d\n", n, is_bnet_stop(sd));
89    }
90    bnet_close(sd);
91    bnet_close(dir);
92    jcr->hb_bsock = NULL;
93    jcr->hb_dir_bsock = NULL;
94    return NULL;
95 }
96
97 /* Startup the heartbeat thread -- see above */
98 void start_heartbeat_monitor(JCR *jcr)
99 {
100    /*
101     * If no signals are set, do not start the heartbeat because
102     * it gives a constant stream of TIMEOUT_SIGNAL signals that
103     * make debugging impossible.
104     */
105    if (!no_signals) {
106       jcr->hb_bsock = NULL;
107       jcr->hb_dir_bsock = NULL;
108       pthread_create(&jcr->heartbeat_id, NULL, sd_heartbeat_thread, (void *)jcr);
109    }
110 }
111
112 /* Terminate the heartbeat thread. Used for both SD and DIR */
113 void stop_heartbeat_monitor(JCR *jcr)
114 {
115    int cnt = 0;
116    if (no_signals) {
117       return;
118    }
119    /* Wait max 10 secs for heartbeat thread to start */
120    while (jcr->hb_bsock == NULL && cnt++ < 200) {
121       bmicrosleep(0, 50000);         /* wait for start */
122    }
123    if (!jcr->hb_bsock) {
124    }
125
126    if (jcr->hb_bsock) {
127       jcr->hb_bsock->timed_out = 1;   /* set timed_out to terminate read */
128       jcr->hb_bsock->terminated = 1;  /* set to terminate read */
129    }
130    if (jcr->hb_dir_bsock) {
131       jcr->hb_dir_bsock->timed_out = 1;   /* set timed_out to terminate read */
132       jcr->hb_dir_bsock->terminated = 1;  /* set to terminate read */
133    }
134    pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL);  /* make heartbeat thread go away */
135    bmicrosleep(0, 50000);
136    cnt = 0;
137    /* Wait max 100 secs for heartbeat thread to stop */
138    while (jcr->hb_bsock && cnt++ < 200) {
139       pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL);  /* make heartbeat thread go away */
140       bmicrosleep(0, 500000);
141    }
142    if (jcr->hb_bsock) {
143    }
144 }
145
146 /*
147  * Thread for sending heartbeats to the Director when there
148  *   is no SD monitoring needed -- e.g. restore and verify Vol
149  *   both do their own read() on the SD socket.
150  */
151 extern "C" void *dir_heartbeat_thread(void *arg)
152 {
153    JCR *jcr = (JCR *)arg;
154    BSOCK *dir;
155    time_t last_heartbeat = time(NULL);
156
157    pthread_detach(pthread_self());
158
159    /* Get our own local copy */
160    dir = dup_bsock(jcr->dir_bsock);
161
162    jcr->hb_bsock = dir;
163
164    for ( ; !is_bnet_stop(dir); ) {
165       time_t now, next;
166
167       now = time(NULL);
168       next = now - last_heartbeat;
169       if (next >= me->heartbeat_interval) {
170          bnet_sig(dir, BNET_HEARTBEAT);
171          last_heartbeat = now;
172       }
173       bmicrosleep(next, 0);
174    }
175    bnet_close(dir);
176    jcr->hb_bsock = NULL;
177    return NULL;
178 }
179
180 /*
181  * Same as above but we don't listen to the SD
182  */
183 void start_dir_heartbeat(JCR *jcr)
184 {
185    if (me->heartbeat_interval) {
186       pthread_create(&jcr->heartbeat_id, NULL, dir_heartbeat_thread, (void *)jcr);
187    }
188 }
189
190 void stop_dir_heartbeat(JCR *jcr)
191 {
192    if (me->heartbeat_interval) {
193       stop_heartbeat_monitor(jcr);
194    }
195 }