X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fwait.c;h=85555618182e13fad3af5e392d77e8f44a1132ef;hb=b22b260eaa7fb9f122523fff0e324dca5904b97f;hp=92d7fd0aabc9b9ae6c1e8b9d15779e16b9302352;hpb=a3bac04c620c893438a1a84af656e1384f828301;p=bacula%2Fbacula diff --git a/bacula/src/stored/wait.c b/bacula/src/stored/wait.c index 92d7fd0aab..8555561818 100644 --- a/bacula/src/stored/wait.c +++ b/bacula/src/stored/wait.c @@ -9,35 +9,30 @@ * Version $Id$ */ /* - Copyright (C) 2000-2005 Kern Sibbald + Copyright (C) 2000-2006 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. + modify it under the terms of the GNU General Public License + version 2 as amended with additional clauses defined in the + file LICENSE in the main source directory. 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. */ #include "bacula.h" /* pull in global headers */ #include "stored.h" /* pull in Storage Deamon headers */ -static bool double_jcr_wait_time(JCR *jcr); +//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() + * Returns: W_ERROR, W_TIMEOUT, W_POLL, W_MOUNT, or W_WAKE */ int wait_for_sysop(DCR *dcr) { @@ -53,15 +48,15 @@ int wait_for_sysop(DCR *dcr) JCR *jcr = dcr->jcr; P(dev->mutex); - unmounted = (dev->dev_blocked == BST_UNMOUNTED) || - (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); + Dmsg1(100, "Enter blocked=%s\n", dev->print_blocked()); + unmounted = is_device_unmounted(dev); 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. + * 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) { @@ -75,8 +70,9 @@ int wait_for_sysop(DCR *dcr) } if (!unmounted) { + Dmsg1(400, "blocked=%s\n", dev->print_blocked()); dev->dev_prev_blocked = dev->dev_blocked; - dev->dev_blocked = BST_WAITING_FOR_SYSOP; /* indicate waiting for mount */ + dev->set_blocked(BST_WAITING_FOR_SYSOP); /* indicate waiting for mount */ } for ( ; !job_canceled(jcr); ) { @@ -86,178 +82,148 @@ int wait_for_sysop(DCR *dcr) 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); + Dmsg4(400, "I'm going to sleep on device %s. HB=%d wait=%d add_wait=%d\n", + dev->print_name(), (int)me->heartbeat_interval, dev->wait_sec, add_wait); 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); + Dmsg2(400, "Wokeup from sleep on device stat=%d blocked=%s\n", stat, + dev->print_blocked()); 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); + 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; - } + } + 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 (stat == EINVAL) { + berrno be; + Dmsg1(000, "pthread stat=%d\n", stat); + Jmsg1(jcr, M_FATAL, 0, _("pthread timedwait error. ERR=%s\n"), be.strerror(stat)); + stat = W_ERROR; /* error */ + break; } + + if (dev->rem_wait_sec <= 0) { /* on exceeding wait time return */ Dmsg0(400, "Exceed wait time.\n"); - break; + stat = W_TIMEOUT; + break; } + /* + * Check if user unmounted the device while we were waiting + */ + unmounted = is_device_unmounted(dev); + 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; + (now - first_start >= dev->vol_poll_interval)) { + Dmsg1(400, "In wait blocked=%s\n", dev->print_blocked()); + dev->poll = true; /* returning a poll event */ + stat = W_POLL; + break; } /* * Check if user mounted the device while we were waiting */ - if (dev->dev_blocked == BST_MOUNT) { /* mount request ? */ - stat = 0; - break; + if (dev->get_blocked() == BST_MOUNT) { /* mount request ? */ + stat = W_MOUNT; + break; + } + + /* + * If we did not timeout, then some event happened, so + * return to check if state changed. + */ + if (stat != 0) { + stat = W_WAKE; /* someone woke us */ + break; } + /* + * At this point, we know we woke up because of a timeout, + * that was due to a heartbeat, so we just update + * the wait counters and continue. + */ add_wait = dev->wait_sec - (now - start); if (add_wait < 0) { - add_wait = 0; + add_wait = 0; } if (me->heartbeat_interval && add_wait > 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 */ + dev->set_blocked(dev->dev_prev_blocked); /* restore entry state */ + Dmsg1(400, "set %s\n", dev->print_blocked()); } + Dmsg1(400, "Exit blocked=%s\n", dev->print_blocked()); V(dev->mutex); return stat; } /* - * Wait for Device to be released - * + * Wait for any device to be released, then we return, so + * higher level code can rescan possible devices. + * + * Returns: true if a device has changed state + * false if the total wait time has expired. */ -bool wait_for_device(DCR *dcr, const char *msg, bool first) +bool wait_for_device(JCR *jcr, 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; + bool ok = true; + const int wait_time = 5 * 60; /* wait 5 minutes */ + Dmsg0(100, "Enter wait_for_device\n"); 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; + Jmsg(jcr, M_MOUNT, 0, _("Job %s waiting to reserve a device.\n"), jcr->Job); } - for ( ; !job_canceled(jcr); ) { - time_t now, start; + gettimeofday(&tv, &tz); + timeout.tv_nsec = tv.tv_usec * 1000; + timeout.tv_sec = tv.tv_sec + wait_time; - 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 + Dmsg0(100, "I'm going to wait for a device.\n"); - 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); - } + /* Wait required time */ + stat = pthread_cond_timedwait(&wait_device_release, &device_release_mutex, &timeout); + Dmsg1(100, "Wokeup from sleep on device stat=%d\n", stat); - 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); + Dmsg1(100, "Return from wait_device ok=%d\n", ok); return ok; } +#ifdef xxx /* - * The jcr timers are used for waiting on any device - * + * The jcr timers are used for waiting on any device * * Returns: true if time doubled - * false if max time expired + * false if max time expired */ static bool double_jcr_wait_time(JCR *jcr) { - jcr->wait_sec *= 2; /* double wait time */ + 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; } @@ -268,3 +234,4 @@ static bool double_jcr_wait_time(JCR *jcr) } return true; } +#endif