]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/heartbeat.c
409b4013af667ce67a0cf228823a93d023c73b8e
[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) 2000-2003 Kern Sibbald and John Walker
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 as
16    published by the Free Software Foundation; either version 2 of
17    the License, or (at your option) any later version.
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 GNU
22    General Public License for more details.
23
24    You should have received a copy of the GNU General Public
25    License along with this program; if not, write to the Free
26    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27    MA 02111-1307, USA.
28
29  */
30
31 #include "bacula.h"
32 #include "filed.h"
33
34 /* 
35  * Listen on the SD socket for heartbeat signals.
36  * Send heartbeats to the Director every HB_TIME
37  *   seconds.
38  */
39 static void *sd_heartbeat_thread(void *arg)
40 {
41    int32_t n;
42    JCR *jcr = (JCR *)arg;
43    BSOCK *sd, *dir;
44    time_t last_heartbeat = time(NULL);
45    time_t now;
46
47    pthread_detach(pthread_self());
48
49    /* Get our own local copy */
50    sd = dup_bsock(jcr->store_bsock);
51    dir = dup_bsock(jcr->dir_bsock);
52
53    jcr->hb_bsock = sd;
54
55    /* Hang reading the socket to the SD, and every time we get
56     *   a heartbeat, we simply send it on to the Director to
57     *   keep him alive.
58     */
59    for ( ; !is_bnet_stop(sd); ) {
60       n = bnet_wait_data_intr(sd, 60);
61       if (me->heartbeat_interval) {
62          now = time(NULL);
63          if (now-last_heartbeat >= me->heartbeat_interval) {
64             bnet_sig(dir, BNET_HEARTBEAT);
65             last_heartbeat = now;
66          }
67       }
68       if (n == 1) {                   /* input waiting */
69          bnet_recv(sd);               /* read it -- probably heartbeat from sd */
70 /*       Dmsg1(000, "Got %d from SD\n", sd->msglen); */
71       }
72    }
73    bnet_close(sd);
74    bnet_close(dir);
75    jcr->hb_bsock = NULL;
76    return NULL;
77 }
78
79 /* Startup the heartbeat thread -- see above */
80 void start_heartbeat_monitor(JCR *jcr)
81 {
82    jcr->hb_bsock = NULL;
83    pthread_create(&jcr->heartbeat_id, NULL, sd_heartbeat_thread, (void *)jcr);
84 }
85
86 /* Terminate the heartbeat thread. Used for both SD and DIR */
87 void stop_heartbeat_monitor(JCR *jcr) 
88 {
89    /* Wait for heartbeat thread to start */
90    while (jcr->hb_bsock == NULL) {
91       bmicrosleep(0, 50);             /* avoid race */
92    }
93    jcr->hb_bsock->timed_out = 1;      /* set timed_out to terminate read */
94    jcr->hb_bsock->terminated = 1;     /* set to terminate read */
95
96    /* Wait for heartbeat thread to stop */
97    while (jcr->hb_bsock) {
98       pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL);  /* make heartbeat thread go away */
99       bmicrosleep(0, 500);
100    }
101 }
102
103 /*
104  * Thread for sending heartbeats to the Director when there
105  *   is no SD monitoring needed -- e.g. restore and verify Vol
106  *   both do their own read() on the SD socket.
107  */
108 static void *dir_heartbeat_thread(void *arg)
109 {
110    JCR *jcr = (JCR *)arg;
111    BSOCK *dir;
112    time_t last_heartbeat = time(NULL);
113
114    pthread_detach(pthread_self());
115
116    /* Get our own local copy */
117    dir = dup_bsock(jcr->dir_bsock);
118
119    jcr->hb_bsock = dir;
120
121    for ( ; !is_bnet_stop(dir); ) {
122       time_t now, next;
123
124       now = time(NULL);
125       next = now - last_heartbeat;
126       if (next >= me->heartbeat_interval) {
127          bnet_sig(dir, BNET_HEARTBEAT);
128          last_heartbeat = now;
129       }
130       bmicrosleep(next, 0);
131    }
132    bnet_close(dir);
133    jcr->hb_bsock = NULL;
134    return NULL;
135 }
136 /*
137  * Same as above but we don't listen to the SD
138  */
139 void start_dir_heartbeat(JCR *jcr)
140 {
141    if (me->heartbeat_interval) {
142       pthread_create(&jcr->heartbeat_id, NULL, dir_heartbeat_thread, (void *)jcr);
143    }
144 }
145
146 void stop_dir_heartbeat(JCR *jcr)
147 {
148    if (me->heartbeat_interval) {
149       stop_heartbeat_monitor(jcr);
150    }
151 }