#
 SVRSRCS = filed.c authenticate.c backup.c estimate.c \
-         filed_conf.c job.c \
+         filed_conf.c heartbeat.c job.c \
          restore.c status.c verify.c verify_vol.c
 SVROBJS = filed.o authenticate.o backup.o estimate.o \
-         filed_conf.o job.o \
+         filed_conf.o heartbeat.o job.o \
          restore.o status.o verify.o verify_vol.o
 
 # these are the objects that are changed by the .configure process
 
 
 static int save_file(FF_PKT *ff_pkt, void *pkt);
 
-#define HB_TIME  (20*60)
-/* 
- * Listen on the SD socket for heartbeat signals.
- * Send heartbeats to the Director every HB_TIME
- *   seconds.
- */
-static void *heartbeat_thread(void *arg)
-{
-   int32_t n;
-   JCR *jcr = (JCR *)arg;
-   BSOCK *sd, *dir;
-   time_t last_heartbeat = time(NULL);
-   time_t now;
-
-   pthread_detach(pthread_self());
-
-   /* Get our own local copy */
-   sd = dup_bsock(jcr->store_bsock);
-   dir = dup_bsock(jcr->dir_bsock);
-
-   jcr->duped_sd = sd;
-
-   /* Hang reading the socket to the SD, and every time we get
-    *  a heartbeat, we simply send it on to the Director to
-    *  keep him alive.
-    */
-   for ( ; !is_bnet_stop(sd); ) {
-      n = bnet_wait_data_intr(sd, 60);
-      now = time(NULL);
-      if (now-last_heartbeat >= HB_TIME) {
-        bnet_sig(dir, BNET_HEARTBEAT);
-        last_heartbeat = now;
-      }
-      if (n == 1) {                  /* input waiting */
-        bnet_recv(sd);               /* read it -- probably heartbeat */
-      }
-   }
-   bnet_close(sd);
-   bnet_close(dir);
-   jcr->duped_sd = NULL;
-   return NULL;
-}
-
-/* Startup the heartbeat thread -- see above */
-static void start_heartbeat_monitor(JCR *jcr)
-{
-   jcr->duped_sd = NULL;
-   pthread_create(&jcr->heartbeat_id, NULL, heartbeat_thread, (void *)jcr);
-}
-
-/* Terminate the heartbeat thread */
-static void stop_heartbeat_monitor(JCR *jcr) 
-{
-   while (jcr->duped_sd == NULL) {
-      bmicrosleep(0, 50);            /* avoid race */
-   }
-   jcr->duped_sd->timed_out = 1;      /* set timed_out to terminate read */
-   jcr->duped_sd->terminated = 1;     /* set to terminate read */
-
-   while (jcr->duped_sd) {
-      pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL); /* make heartbeat thread go away */
-      bmicrosleep(0, 20);
-   }
-}
-
 /* 
  * Find all the requested files and send them
  * to the Storage daemon. 
 
 #endif
 
 extern int win32_client;              /* Are we running on Windows? */
+
+extern CLIENT *me;                    /* "Global" Client resource */
 
  *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
  *
  *   2. The generic config  scanner in lib/parse_config.c and 
- *     lib/parse_config.h.
- *     These files contain the parser code, some utility
- *     routines, and the common store routines (name, int,
- *     string).
+ *      lib/parse_config.h.
+ *      These files contain the parser code, some utility
+ *      routines, and the common store routines (name, int,
+ *      string).
  *
  *   3. The daemon specific file, which contains the Resource
- *     definitions as well as any specific store routines
- *     for the resource records.
+ *      definitions as well as any specific store routines
+ *      for the resource records.
  *
  *     Kern Sibbald, September MM
  *
    {"fdport",      store_pint,  ITEM(res_client.FDport),  0, ITEM_DEFAULT, 9102},
    {"fdaddress",   store_str,   ITEM(res_client.FDaddr),  0, 0, 0},
    {"workingdirectory",  store_dir, ITEM(res_client.working_directory), 0, ITEM_REQUIRED, 0}, 
-   {"piddirectory",  store_dir,     ITEM(res_client.pid_directory), 0, ITEM_REQUIRED, 0}, 
-   {"subsysdirectory",  store_dir,  ITEM(res_client.subsys_directory), 0, ITEM_REQUIRED, 0}, 
-   {"requiressl",  store_yesno,     ITEM(res_client.require_ssl),1, ITEM_DEFAULT, 0},
-   {"maximumconcurrentjobs", store_pint,  ITEM(res_client.MaxConcurrentJobs), 0, ITEM_DEFAULT, 3},
+   {"piddirectory",  store_dir,     ITEM(res_client.pid_directory),     0, ITEM_REQUIRED, 0}, 
+   {"subsysdirectory",  store_dir,  ITEM(res_client.subsys_directory),  0, ITEM_REQUIRED, 0}, 
+   {"requiressl",  store_yesno,     ITEM(res_client.require_ssl),       1, ITEM_DEFAULT, 0},
+   {"maximumconcurrentjobs", store_pint,  ITEM(res_client.MaxConcurrentJobs), 0, ITEM_DEFAULT, 5},
    {"messages",      store_res, ITEM(res_client.messages), R_MSGS, 0, 0},
+   {"heartbeatinterval", store_time, ITEM(res_client.heartbeat_interval), 0, ITEM_DEFAULT, 20*60},
    {NULL, NULL, NULL, 0, 0, 0} 
 };
 
    {"filedaemon",    cli_items,   R_CLIENT,    NULL},
    {"client",        cli_items,   R_CLIENT,    NULL}, /* alias for filedaemon */
    {"messages",      msgs_items,  R_MSGS,      NULL},
-   {NULL,           NULL,        0,           NULL}
+   {NULL,            NULL,        0,           NULL}
 };
 
 
       sendit(sock, "No record for %d %s\n", type, res_to_str(type));
       return;
    }
-   if (type < 0) {                   /* no recursion */
+   if (type < 0) {                    /* no recursion */
       type = - type;
       recurse = 0;
    }
    switch (type) {
       case R_DIRECTOR:
          sendit(sock, "Director: name=%s password=%s\n", reshdr->name, 
-                res->res_dir.password);
-        break;
+                 res->res_dir.password);
+         break;
       case R_CLIENT:
          sendit(sock, "Client: name=%s FDport=%d\n", reshdr->name,
-                res->res_client.FDport);
-        break;
+                 res->res_client.FDport);
+         break;
       case R_MSGS:
          sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
-        if (res->res_msgs.mail_cmd) 
+         if (res->res_msgs.mail_cmd) 
             sendit(sock, "      mailcmd=%s\n", res->res_msgs.mail_cmd);
-        if (res->res_msgs.operator_cmd) 
+         if (res->res_msgs.operator_cmd) 
             sendit(sock, "      opcmd=%s\n", res->res_msgs.operator_cmd);
-        break;
+         break;
       default:
          sendit(sock, "Unknown resource type %d\n", type);
    }
 
    switch (type) {
       case R_DIRECTOR:
-        if (res->res_dir.password) {
-           free(res->res_dir.password);
-        }
-        if (res->res_dir.address) {
-           free(res->res_dir.address);
-        }
-        break;
+         if (res->res_dir.password) {
+            free(res->res_dir.password);
+         }
+         if (res->res_dir.address) {
+            free(res->res_dir.address);
+         }
+         break;
       case R_CLIENT:
-        if (res->res_client.working_directory) {
-           free(res->res_client.working_directory);
-        }
-        if (res->res_client.pid_directory) {
-           free(res->res_client.pid_directory);
-        }
-        if (res->res_client.subsys_directory) {
-           free(res->res_client.subsys_directory);
-        }
-        if (res->res_client.FDaddr) {
-           free(res->res_client.FDaddr);
-        }
-        break;
+         if (res->res_client.working_directory) {
+            free(res->res_client.working_directory);
+         }
+         if (res->res_client.pid_directory) {
+            free(res->res_client.pid_directory);
+         }
+         if (res->res_client.subsys_directory) {
+            free(res->res_client.subsys_directory);
+         }
+         if (res->res_client.FDaddr) {
+            free(res->res_client.FDaddr);
+         }
+         break;
       case R_MSGS:
-        if (res->res_msgs.mail_cmd)
-           free(res->res_msgs.mail_cmd);
-        if (res->res_msgs.operator_cmd)
-           free(res->res_msgs.operator_cmd);
-        free_msgs_res((MSGS *)res);  /* free message resource */
-        res = NULL;
-        break;
+         if (res->res_msgs.mail_cmd)
+            free(res->res_msgs.mail_cmd);
+         if (res->res_msgs.operator_cmd)
+            free(res->res_msgs.operator_cmd);
+         free_msgs_res((MSGS *)res);  /* free message resource */
+         res = NULL;
+         break;
       default:
          printf("Unknown resource type %d\n", type);
    }
     */
    for (i=0; items[i].name; i++) {
       if (items[i].flags & ITEM_REQUIRED) {
-           if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {  
+            if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {  
                Emsg2(M_ABORT, 0, _("%s item is required in %s resource, but not found.\n"),
-                items[i].name, resources[rindex]);
-            }
+                 items[i].name, resources[rindex]);
+             }
       }
    }
 
     */
    if (pass == 2) {
       switch (type) {
-        /* Resources not containing a resource */
-        case R_MSGS:
-        case R_DIRECTOR:
-           break;
+         /* Resources not containing a resource */
+         case R_MSGS:
+         case R_DIRECTOR:
+            break;
 
-        /* Resources containing another resource */
-        case R_CLIENT:
-           if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_dir.hdr.name)) == NULL) {
+         /* Resources containing another resource */
+         case R_CLIENT:
+            if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_dir.hdr.name)) == NULL) {
                Emsg1(M_ABORT, 0, "Cannot find Client resource %s\n", res_all.res_dir.hdr.name);
-           }
-           res->res_client.messages = res_all.res_client.messages;
-           break;
-        default:
+            }
+            res->res_client.messages = res_all.res_client.messages;
+            break;
+         default:
             Emsg1(M_ERROR, 0, _("Unknown resource type %d\n"), type);
-           error = 1;
-           break;
+            error = 1;
+            break;
       }
       /* Note, the resoure name was already saved during pass 1,
        * so here, we can just release it.
        */
       if (res_all.res_dir.hdr.name) {
-        free(res_all.res_dir.hdr.name);
-        res_all.res_dir.hdr.name = NULL;
+         free(res_all.res_dir.hdr.name);
+         res_all.res_dir.hdr.name = NULL;
       }
       if (res_all.res_dir.hdr.desc) {
-        free(res_all.res_dir.hdr.desc);
-        res_all.res_dir.hdr.desc = NULL;
+         free(res_all.res_dir.hdr.desc);
+         res_all.res_dir.hdr.desc = NULL;
       }
       return;
    }
    /* The following code is only executed on pass 1 */
    switch (type) {
       case R_DIRECTOR:
-        size = sizeof(DIRRES);
-        break;
+         size = sizeof(DIRRES);
+         break;
       case R_CLIENT:
-        size = sizeof(CLIENT);
-        break;
+         size = sizeof(CLIENT);
+         break;
       case R_MSGS:
-        size = sizeof(MSGS);
-        break;
+         size = sizeof(MSGS);
+         break;
       default:
          printf(_("Unknown resource type %d\n"), type);
-        error = 1;
-        size = 1;
-        break;
+         error = 1;
+         size = 1;
+         break;
    }
    /* Common */
    if (!error) {
       res = (URES *)malloc(size);
       memcpy(res, &res_all, size);
       if (!resources[rindex].res_head) {
-        resources[rindex].res_head = (RES *)res; /* store first entry */
+         resources[rindex].res_head = (RES *)res; /* store first entry */
       } else {
-        RES *next;
-        /* Add new res to end of chain */
-        for (next=resources[rindex].res_head; next->next; next=next->next)
-           { }
-        next->next = (RES *)res;
+         RES *next;
+         /* Add new res to end of chain */
+         for (next=resources[rindex].res_head; next->next; next=next->next)
+            { }
+         next->next = (RES *)res;
          Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
-              res->res_dir.hdr.name);
+               res->res_dir.hdr.name);
       }
    }
 }
 
 /*
  * Resource codes -- they must be sequential for indexing   
  */
-#define R_FIRST                      1001
+#define R_FIRST                       1001
 
-#define R_DIRECTOR                   1001
-#define R_CLIENT                     1002
-#define R_MSGS                       1003
+#define R_DIRECTOR                    1001
+#define R_CLIENT                      1002
+#define R_MSGS                        1003
 
-#define R_LAST                       R_MSGS
+#define R_LAST                        R_MSGS
 
 /*
  * Some resource attributes
  */
-#define R_NAME                       1020
-#define R_ADDRESS                    1021
-#define R_PASSWORD                   1022
-#define R_TYPE                       1023
+#define R_NAME                        1020
+#define R_ADDRESS                     1021
+#define R_PASSWORD                    1022
+#define R_TYPE                        1023
 
 
 /* Definition of the contents of each Resource */
 struct s_res_dir {
-   RES  hdr;
-   char *password;                   /* Director password */
-   char *address;                    /* Director address or zero */
-   int enable_ssl;                   /* Use SSL for this Director */
+   RES   hdr;
+   char *password;                    /* Director password */
+   char *address;                     /* Director address or zero */
+   int enable_ssl;                    /* Use SSL for this Director */
 };
 typedef struct s_res_dir DIRRES;
 
 struct s_res_client {
-   RES  hdr;
-   int  FDport;                      /* where we listen for Directors */ 
-   char *FDaddr;                     /* bind address */
+   RES   hdr;
+   int   FDport;                      /* where we listen for Directors */ 
+   char *FDaddr;                      /* bind address */
    char *working_directory;
    char *pid_directory;
    char *subsys_directory;
-   int require_ssl;                  /* Require SSL on all connections */
+   int require_ssl;                   /* Require SSL on all connections */
    struct s_res_msgs *messages;       /* daemon message handler */
    int MaxConcurrentJobs;
+   utime_t heartbeat_interval;        /* Interval to send heartbeats to Dir */
 };
 typedef struct s_res_client CLIENT;
 
  * resource structure definitions.
  */
 union u_res {
-   struct s_res_dir    res_dir;
-   struct s_res_client res_client;
-   struct s_res_msgs   res_msgs;
+   struct s_res_dir     res_dir;
+   struct s_res_client  res_client;
+   struct s_res_msgs    res_msgs;
    RES hdr;
 };
 
 
--- /dev/null
+/*
+ *  Bacula File Daemon heartbeat routines
+ *    Listens for heartbeats coming from the SD
+ *    If configured, sends heartbeats to Dir
+ *
+ *    Kern Sibbald, May MMIII
+ *
+ *   Version $Id$
+ *
+ */
+/*
+   Copyright (C) 2000-2003 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "filed.h"
+
+/* 
+ * Listen on the SD socket for heartbeat signals.
+ * Send heartbeats to the Director every HB_TIME
+ *   seconds.
+ */
+static void *heartbeat_thread(void *arg)
+{
+   int32_t n;
+   JCR *jcr = (JCR *)arg;
+   BSOCK *sd, *dir;
+   time_t last_heartbeat = time(NULL);
+   time_t now;
+
+   pthread_detach(pthread_self());
+
+   /* Get our own local copy */
+   sd = dup_bsock(jcr->store_bsock);
+   dir = dup_bsock(jcr->dir_bsock);
+
+   jcr->duped_sd = sd;
+
+   /* Hang reading the socket to the SD, and every time we get
+    *  a heartbeat, we simply send it on to the Director to
+    *  keep him alive.
+    */
+   for ( ; !is_bnet_stop(sd); ) {
+      n = bnet_wait_data_intr(sd, 60);
+      if (me->heartbeat_interval) {
+        now = time(NULL);
+        if (now-last_heartbeat >= me->heartbeat_interval) {
+           bnet_sig(dir, BNET_HEARTBEAT);
+           last_heartbeat = now;
+        }
+      }
+      if (n == 1) {                  /* input waiting */
+        bnet_recv(sd);               /* read it -- probably heartbeat from sd */
+         Dmsg1(000, "Got %d from SD\n", sd->msglen);
+      }
+   }
+   bnet_close(sd);
+   bnet_close(dir);
+   jcr->duped_sd = NULL;
+   return NULL;
+}
+
+/* Startup the heartbeat thread -- see above */
+void start_heartbeat_monitor(JCR *jcr)
+{
+   jcr->duped_sd = NULL;
+   pthread_create(&jcr->heartbeat_id, NULL, heartbeat_thread, (void *)jcr);
+}
+
+/* Terminate the heartbeat thread */
+void stop_heartbeat_monitor(JCR *jcr) 
+{
+   /* Wait for heartbeat thread to start */
+   while (jcr->duped_sd == NULL) {
+      bmicrosleep(0, 50);            /* avoid race */
+   }
+   jcr->duped_sd->timed_out = 1;      /* set timed_out to terminate read */
+   jcr->duped_sd->terminated = 1;     /* set to terminate read */
+
+   /* Wait for heartbeat thread to stop */
+   while (jcr->duped_sd) {
+      pthread_kill(jcr->heartbeat_id, TIMEOUT_SIGNAL); /* make heartbeat thread go away */
+      bmicrosleep(0, 20);
+   }
+}
 
 extern int authenticate_storagedaemon(JCR *jcr);
 extern int make_estimate(JCR *jcr);
 
+/* From heartbeat.c */
+void start_heartbeat_monitor(JCR *jcr);
+void stop_heartbeat_monitor(JCR *jcr);
 
    return 1;
 }
 
-#define HB_TIME (20*60)   /* send a heatbeat once every 20 minutes while waiting */
-
+/*
+ * Wait for SysOp to mount a tape
+ */
 static int wait_for_sysop(JCR *jcr, DEVICE *dev, int wait_sec)
 {
    struct timeval tv;
     */
    gettimeofday(&tv, &tz);
    timeout.tv_nsec = tv.tv_usec * 1000;
-   timeout.tv_sec = tv.tv_sec + (wait_sec > HB_TIME ? HB_TIME: wait_sec);
+   if (me->heartbeat_interval) {
+      utime_t hb = me->heartbeat_interval;
+      timeout.tv_sec = tv.tv_sec + (wait_sec > hb ? hb : wait_sec);
+   } else {
+      timeout.tv_sec = tv.tv_sec + wait_sec;
+   }  
 
    P(dev->mutex);
    dev_blocked = dev->dev_blocked;
 
    for ( ; !job_canceled(jcr); ) {
       int add_wait;
+      time_t now;
 
       Dmsg1(190, "I'm going to sleep on device %s\n", dev->dev_name);
       stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->mutex, &timeout);
 
+      now = time(NULL);
+
       /* Note, this always triggers the first time. We want that. */
-      time_t now = time(NULL);
-      if (now - last_heartbeat >= HB_TIME) {
-        /* send heartbeats */
-        if (jcr->file_bsock) {
-           bnet_sig(jcr->file_bsock, BNET_HEARTBEAT);
-        }
-        if (jcr->dir_bsock) {
-           bnet_sig(jcr->dir_bsock, BNET_HEARTBEAT);
+      if (me->heartbeat_interval) {
+        if (now - last_heartbeat >= me->heartbeat_interval) {
+           /* send heartbeats */
+           if (jcr->file_bsock) {
+              bnet_sig(jcr->file_bsock, BNET_HEARTBEAT);
+               Dmsg0(000, "Send heartbeat to FD.\n");
+           }
+           if (jcr->dir_bsock) {
+              bnet_sig(jcr->dir_bsock, BNET_HEARTBEAT);
+           }
+           last_heartbeat = now;
         }
-        last_heartbeat = now;
       }
 
       /* Check if we blocked the device */
            break;
         }
         add_wait = wait_sec - (now - start);
-        if (add_wait > HB_TIME) {
-           add_wait = HB_TIME;
+        if (me->heartbeat_interval && add_wait > me->heartbeat_interval) {
+           add_wait = me->heartbeat_interval;
         }
       } else {                       /* Oops someone else has it blocked now */
         add_wait = 10;               /* hang around until he releases it */
 
 
 
 /* Global variables */
-static STORES *me;
+STORES *me;
+
+/* Local variables */
 static DEVICE *dev = NULL;
 static B_DB *db;
 static JCR *bjcr;                    /* jcr for bscan */
 
 #include "jcr.h"
 #include "protos.h"
 #ifdef HAVE_LIBZ
-#include <zlib.h>                     /* compression headers */
+#include <zlib.h>                    /* compression headers */
 #else
 #define uLongf uint32_t
 #endif
 
 #include "findlib/find.h"
 
-extern char errmsg[];                /* general error message */
+extern char errmsg[];                /* general error message */
+
+extern STORES *me;                    /* "Global" daemon resource */
 
 #endif /* __STORED_H_ */
 
    {"piddirectory",          store_dir,  ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
    {"subsysdirectory",       store_dir,  ITEM(res_store.subsys_directory), 0, ITEM_REQUIRED, 0},
    {"requiressl",            store_yesno,ITEM(res_store.require_ssl), 1, ITEM_DEFAULT, 0},
-   {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 3},
+   {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 5},
+   {"heartbeatinterval",     store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 20*60},
    {NULL, NULL, 0, 0, 0, 0} 
 };
 
 
 
  */
 
-#define R_FIRST                      3001
+#define R_FIRST                       3001
 
-#define R_DIRECTOR                   3001
-#define R_STORAGE                    3002
-#define R_DEVICE                     3003
-#define R_MSGS                       3004
+#define R_DIRECTOR                    3001
+#define R_STORAGE                     3002
+#define R_DEVICE                      3003
+#define R_MSGS                        3004
 
-#define R_LAST                       R_MSGS
+#define R_LAST                        R_MSGS
 
 
-#define R_NAME                       3020
-#define R_ADDRESS                    3021
-#define R_PASSWORD                   3022
-#define R_TYPE                       3023
-#define R_BACKUP                     3024
+#define R_NAME                        3020
+#define R_ADDRESS                     3021
+#define R_PASSWORD                    3022
+#define R_TYPE                        3023
+#define R_BACKUP                      3024
 
 /* Definition of the contents of each Resource */
 struct s_res_dir {
-   RES  hdr;
+   RES   hdr;
 
-   char *password;                   /* Director password */
-   char *address;                    /* Director IP address or zero */
-   int enable_ssl;                   /* Use SSL with this Director */
+   char *password;                    /* Director password */
+   char *address;                     /* Director IP address or zero */
+   int enable_ssl;                    /* Use SSL with this Director */
 };
 typedef struct s_res_dir DIRRES;
 
 
 /* Storage daemon "global" definitions */
 struct s_res_store {
-   RES  hdr;
+   RES   hdr;
 
-   char *address;                    /* deprecated */
-   char *SDaddr;                     /* bind address */
-   int  SDport;                      /* Where we listen for Directors */
+   char *address;                     /* deprecated */
+   char *SDaddr;                      /* bind address */
+   int   SDport;                      /* Where we listen for Directors */
    int   SDDport;                     /* "Data" port where we listen for File daemons */
-   char *working_directory;          /* working directory for checkpoints */
+   char *working_directory;           /* working directory for checkpoints */
    char *pid_directory;
    char *subsys_directory;
-   int require_ssl;                  /* Require SSL on all connections */
+   int require_ssl;                   /* Require SSL on all connections */
    uint32_t max_concurrent_jobs;      /* maximum concurrent jobs to run */
    struct s_res_msgs *messages;       /* Daemon message handler */
+   utime_t heartbeat_interval;        /* Interval to send hb to FD */
 };
 typedef struct s_res_store STORES;
 
 /* Device specific definitions */
 struct s_res_dev {
-   RES  hdr;
-
-   char *media_type;                 /* User assigned media type */
-   char *device_name;                /* Archive device name */
-   char *changer_name;               /* Changer device name */
-   char *changer_command;            /* Changer command  -- external program */
-   int cap_bits;                     /* Capabilities of this device */
-   uint32_t max_changer_wait;        /* Changer timeout */
-   uint32_t max_rewind_wait;         /* maximum secs to wait for rewind */
-   uint32_t max_open_wait;           /* maximum secs to wait for open */
-   uint32_t max_open_vols;           /* maximum simultaneous open volumes */
-   uint32_t min_block_size;          /* min block size */
-   uint32_t max_block_size;          /* max block size */
-   uint32_t max_volume_jobs;         /* max jobs to put on one volume */
-   int64_t max_volume_files;         /* max files to put on one volume */
-   int64_t max_volume_size;          /* max bytes to put on one volume */
-   int64_t max_file_size;            /* max file size in bytes */
-   int64_t volume_capacity;          /* advisory capacity */
-   DEVICE *dev;                      /* Pointer to phyical dev -- set at runtime */
+   RES   hdr;
+
+   char *media_type;                  /* User assigned media type */
+   char *device_name;                 /* Archive device name */
+   char *changer_name;                /* Changer device name */
+   char *changer_command;             /* Changer command  -- external program */
+   int  cap_bits;                     /* Capabilities of this device */
+   uint32_t max_changer_wait;         /* Changer timeout */
+   uint32_t max_rewind_wait;          /* maximum secs to wait for rewind */
+   uint32_t max_open_wait;            /* maximum secs to wait for open */
+   uint32_t max_open_vols;            /* maximum simultaneous open volumes */
+   uint32_t min_block_size;           /* min block size */
+   uint32_t max_block_size;           /* max block size */
+   uint32_t max_volume_jobs;          /* max jobs to put on one volume */
+   int64_t max_volume_files;          /* max files to put on one volume */
+   int64_t max_volume_size;           /* max bytes to put on one volume */
+   int64_t max_file_size;             /* max file size in bytes */
+   int64_t volume_capacity;           /* advisory capacity */
+   DEVICE *dev;                       /* Pointer to phyical dev -- set at runtime */
 };
 typedef struct s_res_dev DEVRES;
 
 union u_res {
-   struct s_res_dir    res_dir;
-   struct s_res_store  res_store;
-   struct s_res_dev    res_dev;
-   struct s_res_msgs   res_msgs;
+   struct s_res_dir     res_dir;
+   struct s_res_store   res_store;
+   struct s_res_dev     res_dev;
+   struct s_res_msgs    res_msgs;
    RES hdr;
 };
 typedef union u_res URES;