/*
Bacula® - The Network Backup Solution
- Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
+ Copyright (C) 2002-2010 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.
Dmsg1(50, "Media Type change. New read device %s chosen.\n", dev->print_name());
bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
- bstrncpy(dcr->VolCatInfo.VolCatName, vol->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
+ dcr->setVolCatName(vol->VolumeName);
bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
dcr->VolCatInfo.Slot = vol->Slot;
dcr->VolCatInfo.InChanger = vol->Slot > 0;
* we need to recycle the tape.
*/
if (dev->num_writers == 0) {
- memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
+ dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
}
have_vol = dcr->is_tape_position_ok();
}
* This job is done, so release the device. From a Unix standpoint,
* the device remains open.
*
- * Note, if we are spooling, we may enter with the device blocked.
- * However, in all cases, unblock the device when leaving.
+ * Note, if we were spooling, we may enter with the device blocked.
+ * We unblock at the end, only if it was us who blocked the
+ * device.
*
*/
bool release_device(DCR *dcr)
DEVICE *dev = dcr->dev;
bool ok = true;
char tbuf[100];
+ int was_blocked = BST_NOT_BLOCKED;
- lock_volumes();
dev->dlock();
if (!dev->is_blocked()) {
block_device(dev, BST_RELEASING);
- } else if (dev->blocked() == BST_DESPOOLING) {
+ } else {
+ was_blocked = dev->blocked();
dev->set_blocked(BST_RELEASING);
}
+ lock_volumes();
Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
/* if device is reserved, job never started, so release the reserve here */
Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
if (dev->is_labeled()) {
Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
- dev->VolCatInfo.VolCatName, dev->print_name());
+ dev->getVolCatName(), dev->print_name());
if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
- dcr->VolCatInfo.VolCatName, jcr->Job);
+ dcr->getVolCatName(), jcr->Job);
}
/* If no more writers, and no errors, and wrote something, write an EOF */
if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
/* Note! do volume update before close, which zaps VolCatInfo */
dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
- dev->VolCatInfo.VolCatName, dev->print_name());
+ dev->getVolCatName(), dev->print_name());
}
if (dev->num_writers == 0) { /* if not being used */
volume_unused(dcr); /* we obviously are not using the volume */
char line[MAXSTRING];
alert = get_pool_memory(PM_FNAME);
alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
- bpipe = open_bpipe(alert, 0, "r");
+ /* Wait maximum 5 minutes */
+ bpipe = open_bpipe(alert, 60 * 5, "r");
if (bpipe) {
while (fgets(line, sizeof(line), bpipe->rfd)) {
Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
(uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
pthread_cond_broadcast(&wait_device_release);
- dev->dunblock(true);
unlock_volumes();
+
+ /*
+ * If we are the thread that blocked the device, then unblock it
+ */
+ if (pthread_equal(dev->no_wait_id, pthread_self())) {
+ dev->dunblock(true);
+ } else {
+ /* Otherwise, reset the prior block status and unlock */
+ dev->set_blocked(was_blocked);
+ dev->dunlock();
+ }
+
if (dcr->keep_dcr) {
detach_dcr_from_dev(dcr);
} else {
/* Detach this dcr only if attached */
if (dcr->attached_to_dev && dev) {
- dev->dlock();
dcr->unreserve_device();
+ dev->dlock();
dcr->dev->attached_dcrs->remove(dcr); /* detach dcr from device */
// remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
dev->dunlock();
* for disaster recovery, we must "simulate" reading the catalog
*/
bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
- bstrncpy(dcr->VolCatInfo.VolCatName, vol->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
+ dcr->setVolCatName(vol->VolumeName);
bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
dcr->VolCatInfo.Slot = vol->Slot;
dcr->VolCatInfo.InChanger = vol->Slot > 0;