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