]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/heartbeat.c
Fix possible race in heartbeat; set gnome-console default size
[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 #ifdef HAVE_CYGWIN
35 /* pthread_kill() dies on Cygwin, so disable it */
36 #define pthread_kill(x, y)
37 /* Use shorter wait interval on Cygwin because no kill */
38 #define WAIT_INTERVAL 10
39  
40 #else   /* Unix systems */
41 #define WAIT_INTERVAL 60
42 #endif
43
44 /* 
45  * Listen on the SD socket for heartbeat signals.
46  * Send heartbeats to the Director every HB_TIME
47  *   seconds.
48  */
49 static void *sd_heartbeat_thread(void *arg)
50 {
51    int32_t n;
52    JCR *jcr = (JCR *)arg;
53    BSOCK *sd, *dir;
54    time_t last_heartbeat = time(NULL);
55    time_t now;
56
57    pthread_detach(pthread_self());
58
59    /* Get our own local copy */
60    sd = dup_bsock(jcr->store_bsock);
61    dir = dup_bsock(jcr->dir_bsock);
62
63    jcr->hb_bsock = sd;
64
65    /* Hang reading the socket to the SD, and every time we get
66     *   a heartbeat, we simply send it on to the Director to
67     *   keep him alive.
68     */
69    for ( ; !is_bnet_stop(sd); ) {
70       n = bnet_wait_data_intr(sd, WAIT_INTERVAL);
71       if (me->heartbeat_interval) {
72          now = time(NULL);
73          if (now-last_heartbeat >= me->heartbeat_interval) {
74             bnet_sig(dir, BNET_HEARTBEAT);
75             last_heartbeat = now;
76          }
77       }
78       if (n == 1) {                   /* input waiting */
79          bnet_recv(sd);               /* read it -- probably heartbeat from sd */
80          Dmsg1(100, "Got %d from SD\n", sd->msglen);     
81       }
82    }
83    bnet_close(sd);
84    bnet_close(dir);
85    jcr->hb_bsock = NULL;
86    return NULL;
87 }
88
89 /* Startup the heartbeat thread -- see above */
90 void start_heartbeat_monitor(JCR *jcr)
91 {
92    jcr->hb_bsock = NULL;
93    pthread_create(&jcr->heartbeat_id, NULL, sd_heartbeat_thread, (void *)jcr);
94 }
95
96 /* Terminate the heartbeat thread. Used for both SD and DIR */
97 void stop_heartbeat_monitor(JCR *jcr) 
98 {
99    int cnt = 0;
100    /* Wait max 10 secs for heartbeat thread to start */
101    while (jcr->hb_bsock == NULL && cnt++ < 200) {
102       bmicrosleep(0, 50);             /* avoid race */
103    }
104
105    if (jcr->hb_bsock) {
106       jcr->hb_bsock->timed_out = 1;   /* set timed_out to terminate read */
107       jcr->hb_bsock->terminated = 1;  /* set to terminate read */
108    }
109    cnt = 0;
110    /* Wait max 100 secs for heartbeat thread to stop */
111    while (jcr->hb_bsock && cnt++ < 200) {
112       /* Naturally, Cygwin 1.3.20 craps out on the following */
113       pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL);  /* make heartbeat thread go away */
114       bmicrosleep(0, 500);
115    }
116 }
117
118 /*
119  * Thread for sending heartbeats to the Director when there
120  *   is no SD monitoring needed -- e.g. restore and verify Vol
121  *   both do their own read() on the SD socket.
122  */
123 static void *dir_heartbeat_thread(void *arg)
124 {
125    JCR *jcr = (JCR *)arg;
126    BSOCK *dir;
127    time_t last_heartbeat = time(NULL);
128
129    pthread_detach(pthread_self());
130
131    /* Get our own local copy */
132    dir = dup_bsock(jcr->dir_bsock);
133
134    jcr->hb_bsock = dir;
135
136    for ( ; !is_bnet_stop(dir); ) {
137       time_t now, next;
138
139       now = time(NULL);
140       next = now - last_heartbeat;
141       if (next >= me->heartbeat_interval) {
142          bnet_sig(dir, BNET_HEARTBEAT);
143          last_heartbeat = now;
144       }
145       bmicrosleep(next, 0);
146    }
147    bnet_close(dir);
148    jcr->hb_bsock = NULL;
149    return NULL;
150 }
151 /*
152  * Same as above but we don't listen to the SD
153  */
154 void start_dir_heartbeat(JCR *jcr)
155 {
156    if (me->heartbeat_interval) {
157       pthread_create(&jcr->heartbeat_id, NULL, dir_heartbeat_thread, (void *)jcr);
158    }
159 }
160
161 void stop_dir_heartbeat(JCR *jcr)
162 {
163    if (me->heartbeat_interval) {
164       stop_heartbeat_monitor(jcr);
165    }
166 }