/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
This program is Free Software; you can redistribute it and/or
modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation plus additions
- that are listed in the file LICENSE.
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ Bacula® is a registered trademark of Kern Sibbald.
The licensor of Bacula is the Free Software Foundation Europe
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
#include "bacula.h" /* pull in global headers */
#include "stored.h" /* pull in Storage Deamon headers */
-//static bool double_jcr_wait_time(JCR *jcr);
-
+const int dbglvl = 400;
/*
* Wait for SysOp to mount a tape on a specific device
JCR *jcr = dcr->jcr;
dev->dlock();
- Dmsg1(100, "Enter blocked=%s\n", dev->print_blocked());
- unmounted = is_device_unmounted(dev);
+ Dmsg1(dbglvl, "Enter blocked=%s\n", dev->print_blocked());
+ /*
+ * Since we want to mount a tape, make sure current one is
+ * not marked as using this drive.
+ */
+ volume_unused(dcr);
+
+ unmounted = dev->is_device_unmounted();
dev->poll = false;
/*
* Wait requested time (dev->rem_wait_sec). However, we also wake up every
}
if (!unmounted) {
- Dmsg1(400, "blocked=%s\n", dev->print_blocked());
+ Dmsg1(dbglvl, "blocked=%s\n", dev->print_blocked());
dev->dev_prev_blocked = dev->blocked();
dev->set_blocked(BST_WAITING_FOR_SYSOP); /* indicate waiting for mount */
}
for ( ; !job_canceled(jcr); ) {
- time_t now, start;
+ time_t now, start, total_waited;
gettimeofday(&tv, &tz);
timeout.tv_nsec = tv.tv_usec * 1000;
timeout.tv_sec = tv.tv_sec + add_wait;
- 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);
+ Dmsg4(dbglvl, "I'm going to sleep on device %s. HB=%d rem_wait=%d add_wait=%d\n",
+ dev->print_name(), (int)me->heartbeat_interval, dev->rem_wait_sec, add_wait);
start = time(NULL);
+
/* Wait required time */
stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->m_mutex, &timeout);
- Dmsg2(400, "Wokeup from sleep on device stat=%d blocked=%s\n", stat,
- dev->print_blocked());
+ Dmsg2(dbglvl, "Wokeup from sleep on device stat=%d blocked=%s\n", stat,
+ dev->print_blocked());
now = time(NULL);
+ total_waited = now - first_start;
dev->rem_wait_sec -= (now - start);
/* Note, this always triggers the first time. We want that. */
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");
+ jcr->file_bsock->signal(BNET_HEARTBEAT);
+ Dmsg0(dbglvl, "Send heartbeat to FD.\n");
}
if (jcr->dir_bsock) {
- bnet_sig(jcr->dir_bsock, BNET_HEARTBEAT);
+ jcr->dir_bsock->signal(BNET_HEARTBEAT);
}
last_heartbeat = now;
}
break;
}
-
if (dev->rem_wait_sec <= 0) { /* on exceeding wait time return */
- Dmsg0(400, "Exceed wait time.\n");
+ Dmsg0(dbglvl, "Exceed wait time.\n");
stat = W_TIMEOUT;
break;
}
/*
* Check if user unmounted the device while we were waiting
*/
- unmounted = is_device_unmounted(dev);
+ unmounted = dev->is_device_unmounted();
if (!unmounted && dev->vol_poll_interval &&
- (now - first_start >= dev->vol_poll_interval)) {
- Dmsg1(400, "In wait blocked=%s\n", dev->print_blocked());
+ (total_waited >= dev->vol_poll_interval)) {
+ Dmsg1(dbglvl, "poll return 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->blocked() == BST_MOUNT) { /* mount request ? */
+ Dmsg0(dbglvl, "Mounted return.\n");
stat = W_MOUNT;
break;
}
* If we did not timeout, then some event happened, so
* return to check if state changed.
*/
- if (stat != 0) {
+ if (stat != ETIMEDOUT) {
+ berrno be;
+ Dmsg2(dbglvl, "Wake return. stat=%d. ERR=%s\n", stat, be.bstrerror(stat));
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.
+ * that was due to a heartbeat, because any other reason would
+ * have caused us to return, so update the wait counters and continue.
*/
- add_wait = dev->wait_sec - (now - start);
- if (add_wait < 0) {
- add_wait = 0;
- }
+ 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 - total_waited) {
+ add_wait = dev->vol_poll_interval - total_waited;
+ }
+ if (add_wait < 0) {
+ add_wait = 0;
+ }
}
if (!unmounted) {
dev->set_blocked(dev->dev_prev_blocked); /* restore entry state */
- Dmsg1(400, "set %s\n", dev->print_blocked());
+ Dmsg1(dbglvl, "set %s\n", dev->print_blocked());
}
- Dmsg1(400, "Exit blocked=%s\n", dev->print_blocked());
+ Dmsg1(dbglvl, "Exit blocked=%s\n", dev->print_blocked());
dev->dunlock();
return stat;
}
const int max_wait_time = 1 * 60; /* wait 1 minute */
char ed1[50];
- Dmsg0(100, "Enter wait_for_device\n");
+ Dmsg0(dbglvl, "Enter wait_for_device\n");
P(device_release_mutex);
if (++retries % 5 == 0) {
timeout.tv_nsec = tv.tv_usec * 1000;
timeout.tv_sec = tv.tv_sec + max_wait_time;
- Dmsg1(100, "JobId=%u going to wait for a device.\n", (uint32_t)jcr->JobId);
+ Dmsg0(dbglvl, "Going to wait for a device.\n");
/* Wait required time */
stat = pthread_cond_timedwait(&wait_device_release, &device_release_mutex, &timeout);
- Dmsg2(100, "JobId=%u wokeup from sleep on device stat=%d\n", (uint32_t)jcr->JobId, stat);
-
+ Dmsg1(dbglvl, "Wokeup from sleep on device stat=%d\n", stat);
V(device_release_mutex);
- Dmsg2(100, "JobId=%u return from wait_device ok=%d\n", (uint32_t)jcr->JobId, ok);
+ Dmsg1(dbglvl, "Return from wait_device ok=%d\n", ok);
return ok;
}