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