From: Kern Sibbald Date: Sat, 26 Mar 2005 14:53:13 +0000 (+0000) Subject: - Add wait.c (oops forgot previously). X-Git-Tag: Release-1.38.0~583 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=e8dc8f1ab3d2c376b2dd469a7ca0da4fa946242c;p=bacula%2Fbacula - Add wait.c (oops forgot previously). - Move all the reserve/acquire_device_for_read/append to have only a DCR as the argument. - Rework the reserve_device_for_append() in stored to wait if the drive is not available. Note! This is a short term solution. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1900 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 83ce8d80a6..64053c7e56 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -28,6 +28,8 @@ #include "bacula.h" /* pull in global headers */ #include "stored.h" /* pull in Storage Deamon headers */ +static int can_reserve_drive(DCR *dcr); + /* * Create a new Device Control Record and attach * it to the device (if this is a real job). @@ -53,8 +55,8 @@ DCR *new_dcr(JCR *jcr, DEVICE *dev) dcr->max_spool_size = dev->device->max_spool_size; /* Attach this dcr only if dev is initialized */ if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) { - dev->attached_dcrs->append(dcr); -// jcr->dcrs->append(dcr); + dev->attached_dcrs->append(dcr); /* attach dcr to device */ +// jcr->dcrs->append(dcr); /* put dcr in list for Job */ } return dcr; } @@ -111,8 +113,8 @@ void free_dcr(DCR *dcr) /* Detach this dcr only if the dev is initialized */ if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) { - dev->attached_dcrs->remove(dcr); -// remove_dcr_from_dcrs(dcr); + dev->attached_dcrs->remove(dcr); /* detach dcr from device */ +// remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */ } if (dcr->block) { free_block(dcr->block); @@ -134,9 +136,10 @@ void free_dcr(DCR *dcr) * starting the job. If the device is not available, the DIR * can wait (to be implemented 1/05). */ -bool reserve_device_for_read(JCR *jcr, DEVICE *dev) +bool reserve_device_for_read(DCR *dcr) { - DCR *dcr = jcr->dcr; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; bool first; ASSERT(dcr); @@ -179,26 +182,20 @@ bool reserve_device_for_read(JCR *jcr, DEVICE *dev) * Returns: NULL if failed for any reason * dcr if successful */ -DCR *acquire_device_for_read(JCR *jcr, DEVICE *dev) +DCR *acquire_device_for_read(DCR *dcr) { + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; bool vol_ok = false; bool tape_previously_mounted; bool tape_initially_mounted; VOL_LIST *vol; bool try_autochanger = true; int i; - DCR *dcr = jcr->dcr; int vol_label_status; dev->block(BST_DOING_ACQUIRE); - init_device_wait_timers(dcr); - - tape_previously_mounted = dev->can_read() || - dev->can_append() || - dev->is_labeled(); - tape_initially_mounted = tape_previously_mounted; - if (dev->num_writers > 0) { Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"), dev->num_writers, jcr->JobId); @@ -215,8 +212,19 @@ DCR *acquire_device_for_read(JCR *jcr, DEVICE *dev) for (i=1; iCurVolume; i++) { vol = vol->next; } + if (!vol) { + goto get_out; /* should not happen */ + } bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName)); + init_device_wait_timers(dcr); + + tape_previously_mounted = dev->can_read() || + dev->can_append() || + dev->is_labeled(); + tape_initially_mounted = tape_previously_mounted; + + /* Volume info is always needed because of VolParts */ Dmsg0(200, "dir_get_volume_info\n"); if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) { @@ -355,24 +363,71 @@ get_out: * the first tor reserve the device, we put the pool * name and pool type in the device record. */ -bool reserve_device_for_append(JCR *jcr, DEVICE *dev) +bool reserve_device_for_append(DCR *dcr) { - DCR *dcr = jcr->dcr; + JCR *jcr = dcr->jcr; + DEVICE *dev = dcr->dev; bool ok = false; + bool first; ASSERT(dcr); - dev->block(BST_DOING_ACQUIRE); - if (dev->can_read()) { - Jmsg(jcr, M_WARNING, 0, _("Device %s is busy reading.\n"), dev->print_name()); - goto bail_out; + + Mmsg2(jcr->errmsg, _("Device %s is busy reading. Job %d canceled.\n"), + dev->print_name(), jcr->JobId); + for (first=true; dev->can_read(); first=false) { + dev->unblock(); + if (!wait_for_device(dcr, jcr->errmsg, first)) { + return false; + } + dev->block(BST_DOING_ACQUIRE); } - if (device_is_unmounted(dev)) { - Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"), - dev->print_name()); - goto bail_out; + + + Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), + dev->print_name()); + for (first=true; device_is_unmounted(dev); first=false) { + dev->unblock(); + if (!wait_for_device(dcr, jcr->errmsg, first)) { + return false; + } + dev->block(BST_DOING_ACQUIRE); } + Dmsg1(190, "reserve_append device is %s\n", dev_is_tape(dev)?"tape":"disk"); + + for ( ;; ) { + switch (can_reserve_drive(dcr)) { + case 0: + /* ****FIXME**** Make wait */ + goto bail_out; + case -1: + goto bail_out; /* error */ + default: + break; /* OK, reserve drive */ + } + break; + } + + + dev->reserved_device++; + dcr->reserved_device = true; + ok = true; + +bail_out: + dev->unblock(); + return ok; +} + +/* + * Returns: 1 if drive can be reserved + * 0 if we should wait + * -1 on error + */ +static int can_reserve_drive(DCR *dcr) +{ + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; /* * First handle the case that the drive is not yet in append mode */ @@ -386,7 +441,7 @@ bool reserve_device_for_append(JCR *jcr, DEVICE *dev) } else { /* Drive not suitable for us */ Jmsg(jcr, M_WARNING, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name()); - goto bail_out; + return 0; /* wait */ } } else { /* Device is available but not yet reserved, reserve it for us */ @@ -394,7 +449,7 @@ bool reserve_device_for_append(JCR *jcr, DEVICE *dev) bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type)); dev->PoolId = dcr->PoolId; } - goto do_reserve; + return 1; /* reserve drive */ } /* @@ -409,21 +464,14 @@ bool reserve_device_for_append(JCR *jcr, DEVICE *dev) } else { /* Drive not suitable for us */ Jmsg(jcr, M_WARNING, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name()); - goto bail_out; + return 0; /* wait */ } } else { Pmsg0(000, "Logic error!!!! Should not get here.\n"); - goto bail_out; /* should not get here */ + Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n")); + return -1; /* error, should not get here */ } - -do_reserve: - dev->reserved_device++; - dcr->reserved_device = true; - ok = true; - -bail_out: - dev->unblock(); - return ok; + return 1; /* reserve drive */ } /* @@ -435,16 +483,14 @@ bail_out: * Note, normally reserve_device_for_append() is called * before this routine. */ -DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev) +DCR *acquire_device_for_append(DCR *dcr) { bool release = false; bool recycle = false; bool do_mount = false; - DCR *dcr = jcr->dcr; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; - if (!dcr) { - dcr = new_dcr(jcr, dev); - } dev->block(BST_DOING_ACQUIRE); Dmsg1(190, "acquire_append device is %s\n", dev_is_tape(dev)?"tape":"disk"); diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index 877c0a671c..40db5cd2bb 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -61,7 +61,7 @@ bool do_append_data(JCR *jcr) return false; } - if (!acquire_device_for_append(jcr, dev)) { + if (!acquire_device_for_append(dcr)) { set_jcr_job_status(jcr, JS_ErrorTerminated); return false; } diff --git a/bacula/src/stored/bcopy.c b/bacula/src/stored/bcopy.c index 8a6b7bd35c..74ef4b640c 100644 --- a/bacula/src/stored/bcopy.c +++ b/bacula/src/stored/bcopy.c @@ -172,7 +172,7 @@ int main (int argc, char *argv[]) exit(1); } unlock_device(out_dev); - if (!acquire_device_for_append(out_jcr, out_dev)) { + if (!acquire_device_for_append(out_jcr->dcr)) { free_jcr(in_jcr); exit(1); } diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 72baeb5ec5..b1e257489b 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -336,7 +336,7 @@ static bool open_the_device() } } Pmsg1(000, "open_dev %s OK\n", dev->print_name()); - dev->state |= ST_APPEND; + dev->set_append(); /* put volume in append mode */ unlock_device(dev); free_block(block); return true; @@ -1794,7 +1794,7 @@ static void fillcmd() * subroutine. */ Dmsg0(100, "just before acquire_device\n"); - if (!acquire_device_for_append(jcr, dev)) { + if (!acquire_device_for_append(dcr)) { set_jcr_job_status(jcr, JS_ErrorTerminated); return; } @@ -2058,7 +2058,7 @@ static void do_unfill() close_dev(dev); dev->state &= ~(ST_READ|ST_APPEND); dev->num_writers = 0; - if (!acquire_device_for_read(jcr, dev)) { + if (!acquire_device_for_read(dcr)) { Pmsg1(-1, "%s", dev->errmsg); goto bail_out; } @@ -2118,8 +2118,8 @@ static void do_unfill() get_cmd(_("Mount second tape. Press enter when ready: ")); } - dev->state &= ~ST_READ; - if (!acquire_device_for_read(jcr, dev)) { + dev->clear_read(); + if (!acquire_device_for_read(dcr)) { Pmsg1(-1, "%s", dev->errmsg); goto bail_out; } @@ -2697,8 +2697,8 @@ static bool my_mount_next_read_volume(DCR *dcr) jcr->bsr = NULL; create_vol_list(jcr); close_dev(dev); - dev->state &= ~ST_READ; - if (!acquire_device_for_read(jcr, dev)) { + dev->clear_read(); + if (!acquire_device_for_read(dcr)) { Pmsg2(0, "Cannot open Dev=%s, Vol=%s\n", dev->print_name(), dcr->VolumeName); return false; } diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index 619e69909c..47b42a5146 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -171,7 +171,7 @@ static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeN create_vol_list(jcr); if (mode) { /* read only access? */ - if (!acquire_device_for_read(jcr, dev)) { + if (!acquire_device_for_read(dcr)) { return NULL; } } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 356f12d883..da15d3f943 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -452,7 +452,7 @@ static bool read_label(DCR *dcr) steal_device_lock(dev, &hold, BST_DOING_ACQUIRE); dcr->VolumeName[0] = 0; - dev->state &= ~ST_LABEL; /* force read of label */ + dev->clear_labeled(); /* force read of label */ switch (read_dev_volume_label(dcr)) { case VOL_OK: bnet_fsend(dir, _("3001 Mounted Volume: %s\n"), dev->VolHdr.VolName); @@ -878,7 +878,7 @@ static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot) goto bail_out; /* error */ } - dev->state &= ~ST_LABEL; /* force read of label */ + dev->clear_labeled(); /* force read of label */ switch (read_dev_volume_label(dcr)) { case VOL_OK: /* DO NOT add quotes around the Volume name. It is scanned in the DIR */ diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index a6600c2ab1..6c2ae1a454 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -311,9 +311,9 @@ static bool use_device_cmd(JCR *jcr) dcr->PoolId = PoolId; jcr->dcr = dcr; if (append == SD_APPEND) { - ok = reserve_device_for_append(jcr, device->dev); + ok = reserve_device_for_append(dcr); } else { - ok = reserve_device_for_read(jcr, device->dev); + ok = reserve_device_for_read(dcr); } if (!ok) { bnet_fsend(dir, _("3927 Could not reserve device: %s\n"), dev_name.c_str()); @@ -364,9 +364,9 @@ static bool use_device_cmd(JCR *jcr) bstrncpy(dcr->dev_name, dev_name, name_len); jcr->dcr = dcr; if (append == SD_APPEND) { - ok = reserve_device_for_append(jcr, device->dev); + ok = reserve_device_for_append(dcr); } else { - ok = reserve_device_for_read(jcr, device->dev); + ok = reserve_device_for_read(dcr); } if (!ok) { Jmsg(jcr, M_WARNING, 0, _("Could not reserve device: %s\n"), dev_name.c_str()); diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 7b0c0e672d..0cf2ce80a4 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -407,7 +407,7 @@ bool mount_next_read_volume(DCR *dcr) if (jcr->NumVolumes > 1 && jcr->CurVolume < jcr->NumVolumes) { close_dev(dev); dev->clear_read(); - if (!acquire_device_for_read(jcr, dev)) { + if (!acquire_device_for_read(dcr)) { Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev->print_name(), dcr->VolumeName); return false; diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index fc3b9999e4..4e64cc54c7 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,10 +28,10 @@ uint32_t new_VolSessionId(); /* From acquire.c */ -bool reserve_device_for_append(JCR *jcr, DEVICE *dev); -DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev); -bool reserve_device_for_read(JCR *jcr, DEVICE *dev); -DCR *acquire_device_for_read(JCR *jcr, DEVICE *dev); +bool reserve_device_for_append(DCR *dcr); +DCR *acquire_device_for_append(DCR *dcr); +bool reserve_device_for_read(DCR *dcr); +DCR *acquire_device_for_read(DCR *dcr); bool release_device(DCR *dcr); DCR *new_dcr(JCR *jcr, DEVICE *dev); void free_dcr(DCR *dcr); diff --git a/bacula/src/stored/read.c b/bacula/src/stored/read.c index b6f5525c07..7b3569d605 100644 --- a/bacula/src/stored/read.c +++ b/bacula/src/stored/read.c @@ -67,7 +67,7 @@ bool do_read_data(JCR *jcr) jcr->VolList->VolumeName); /* Ready device for reading */ - if (!acquire_device_for_read(jcr, dcr->dev)) { + if (!acquire_device_for_read(dcr)) { free_vol_list(jcr); bnet_fsend(fd, FD_error); return false; diff --git a/bacula/src/stored/wait.c b/bacula/src/stored/wait.c new file mode 100644 index 0000000000..92d7fd0aab --- /dev/null +++ b/bacula/src/stored/wait.c @@ -0,0 +1,270 @@ +/* + * Subroutines to handle waiting for operator intervention + * or waiting for a Device to be released + * + * Code for wait_for_sysop() pulled from askdir.c + * + * Kern Sibbald, March 2005 + * + * Version $Id$ + */ +/* + Copyright (C) 2000-2005 Kern Sibbald + + 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" /* pull in global headers */ +#include "stored.h" /* pull in Storage Deamon headers */ + +static bool double_jcr_wait_time(JCR *jcr); + + +/* + * Wait for SysOp to mount a tape on a specific device + * + * Returns: status from pthread_cond_timedwait() + */ +int wait_for_sysop(DCR *dcr) +{ + struct timeval tv; + struct timezone tz; + struct timespec timeout; + time_t last_heartbeat = 0; + time_t first_start = time(NULL); + int stat = 0; + int add_wait; + bool unmounted; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; + + P(dev->mutex); + unmounted = (dev->dev_blocked == BST_UNMOUNTED) || + (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); + + dev->poll = false; + /* + * Wait requested time (dev->rem_wait_sec). However, we also wake up every + * HB_TIME seconds and send a heartbeat to the FD and the Director + * to keep stateful firewalls from closing them down while waiting + * for the operator. + */ + add_wait = dev->rem_wait_sec; + if (me->heartbeat_interval && add_wait > me->heartbeat_interval) { + add_wait = me->heartbeat_interval; + } + /* If the user did not unmount the tape and we are polling, ensure + * that we poll at the correct interval. + */ + if (!unmounted && dev->vol_poll_interval && add_wait > dev->vol_poll_interval) { + add_wait = dev->vol_poll_interval; + } + + if (!unmounted) { + dev->dev_prev_blocked = dev->dev_blocked; + dev->dev_blocked = BST_WAITING_FOR_SYSOP; /* indicate waiting for mount */ + } + + for ( ; !job_canceled(jcr); ) { + time_t now, start; + + gettimeofday(&tv, &tz); + timeout.tv_nsec = tv.tv_usec * 1000; + timeout.tv_sec = tv.tv_sec + add_wait; + + Dmsg3(400, "I'm going to sleep on device %s. HB=%d wait=%d\n", dev->print_name(), + (int)me->heartbeat_interval, dev->wait_sec); + start = time(NULL); + /* Wait required time */ + stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->mutex, &timeout); + Dmsg1(400, "Wokeup from sleep on device stat=%d\n", stat); + + now = time(NULL); + dev->rem_wait_sec -= (now - start); + + /* Note, this always triggers the first time. We want that. */ + 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(400, "Send heartbeat to FD.\n"); + } + if (jcr->dir_bsock) { + bnet_sig(jcr->dir_bsock, BNET_HEARTBEAT); + } + last_heartbeat = now; + } + } + + /* + * Check if user unmounted the device while we were waiting + */ + unmounted = (dev->dev_blocked == BST_UNMOUNTED) || + (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); + + if (stat != ETIMEDOUT) { /* we blocked the device */ + break; /* on error return */ + } + if (dev->rem_wait_sec <= 0) { /* on exceeding wait time return */ + Dmsg0(400, "Exceed wait time.\n"); + break; + } + + if (!unmounted && dev->vol_poll_interval && + (now - first_start >= dev->vol_poll_interval)) { + Dmsg1(400, "In wait blocked=%s\n", edit_blocked_reason(dev)); + dev->poll = true; /* returning a poll event */ + break; + } + /* + * Check if user mounted the device while we were waiting + */ + if (dev->dev_blocked == BST_MOUNT) { /* mount request ? */ + stat = 0; + break; + } + + add_wait = dev->wait_sec - (now - start); + if (add_wait < 0) { + add_wait = 0; + } + if (me->heartbeat_interval && add_wait > me->heartbeat_interval) { + add_wait = me->heartbeat_interval; + } + } + + if (!unmounted) { + dev->dev_blocked = dev->dev_prev_blocked; /* restore entry state */ + } + V(dev->mutex); + return stat; +} + + +/* + * Wait for Device to be released + * + */ +bool wait_for_device(DCR *dcr, const char *msg, bool first) +{ + struct timeval tv; + struct timezone tz; + struct timespec timeout; +// time_t last_heartbeat = 0; + int stat = 0; + int add_wait; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; + bool ok = false; + + P(device_release_mutex); + + if (first) { + Jmsg(jcr, M_MOUNT, 0, msg); + } + + /* + * Wait requested time (dev->rem_wait_sec). However, we also wake up every + * HB_TIME seconds and send a heartbeat to the FD and the Director + * to keep stateful firewalls from closing them down while waiting + * for the operator. + */ + add_wait = jcr->rem_wait_sec; + if (me->heartbeat_interval && add_wait > me->heartbeat_interval) { + add_wait = me->heartbeat_interval; + } + + for ( ; !job_canceled(jcr); ) { + time_t now, start; + + gettimeofday(&tv, &tz); + timeout.tv_nsec = tv.tv_usec * 1000; + timeout.tv_sec = tv.tv_sec + add_wait; + + Dmsg3(000, "I'm going to sleep on device %s. HB=%d wait=%d\n", dev->print_name(), + (int)me->heartbeat_interval, dev->wait_sec); + start = time(NULL); + /* Wait required time */ + stat = pthread_cond_timedwait(&wait_device_release, &device_release_mutex, &timeout); + Dmsg1(000, "Wokeup from sleep on device stat=%d\n", stat); + + now = time(NULL); + jcr->rem_wait_sec -= (now - start); + +#ifdef needed + /* Note, this always triggers the first time. We want that. */ + 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(400, "Send heartbeat to FD.\n"); + } + if (jcr->dir_bsock) { + bnet_sig(jcr->dir_bsock, BNET_HEARTBEAT); + } + last_heartbeat = now; + } + } +#endif + + if (stat != ETIMEDOUT) { /* if someone woke us up */ + ok = true; + break; /* allow caller to examine device */ + } + if (jcr->rem_wait_sec <= 0) { /* on exceeding wait time return */ + Dmsg0(400, "Exceed wait time.\n"); + if (!double_jcr_wait_time(jcr)) { + break; /* give up */ + } + Jmsg(jcr, M_MOUNT, 0, msg); + } + + add_wait = jcr->wait_sec - (now - start); + if (add_wait < 0) { + add_wait = 0; + } + if (me->heartbeat_interval && add_wait > me->heartbeat_interval) { + add_wait = me->heartbeat_interval; + } + } + + V(device_release_mutex); + Dmsg1(000, "Return from wait_device ok=%d\n", ok); + return ok; +} + +/* + * The jcr timers are used for waiting on any device + * + * Returns: true if time doubled + * false if max time expired + */ +static bool double_jcr_wait_time(JCR *jcr) +{ + jcr->wait_sec *= 2; /* double wait time */ + if (jcr->wait_sec > jcr->max_wait) { /* but not longer than maxtime */ + jcr->wait_sec = jcr->max_wait; + } + jcr->num_wait++; + jcr->rem_wait_sec = jcr->wait_sec; + if (jcr->num_wait >= jcr->max_num_wait) { + return false; + } + return true; +} diff --git a/bacula/src/version.h b/bacula/src/version.h index c855e405c7..78b66093c2 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION #define VERSION "1.37.8" -#define BDATE "25 March 2005" -#define LSMDATE "25Mar05" +#define BDATE "26 March 2005" +#define LSMDATE "26Mar05" /* Debug flags */ #undef DEBUG