Notes (Kern): I am not at all in favor of this until NDMP becomes
an Open Standard or until there are Open Source libraries
that interface to it.
+
+Item n: make changing "spooldata=yes|no" possible for
+ manual/interactive jobs
+
+Origin: Marc Schiffbauer <marc@schiffbauer.net>
+
+Date: 12 April 2007)
+
+Status: NEW
+
+What: Make it possible to modify the spooldata option
+ for a job when being run from within the console.
+ Currently it is possible to modify the backup level
+ and the spooldata setting in a Schedule resource.
+ It is also possible to modify the backup level when using
+ the "run" command in the console.
+ But it is currently not possible to to the same
+ with "spooldata=yes|no" like:
+
+ run job=MyJob level=incremental spooldata=yes
+
+Why: In some situations it would be handy to be able to switch
+ spooldata on or off for interactive/manual jobs based on
+ which data the admin expects or how fast the LAN/WAN
+ connection currently is.
+
+Notes: ./.
+
============= Empty Feature Request form ===========
Item n: One line summary ...
Date: Date submitted
Dmsg1(400, "alert status=%d\n", status);
free_pool_memory(alert);
}
+ pthread_cond_broadcast(&dev->wait_next_vol);
+ Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId);
+ pthread_cond_broadcast(&wait_device_release);
dcr->dev_locked = false; /* set no longer locked */
dev->dunlock();
if (jcr->read_dcr == dcr) {
jcr->dcr = NULL;
}
free_dcr(dcr);
+ Dmsg2(100, "===== Device %s released by JobId=%u\n", dev->print_name(),
+ (uint32_t)jcr->JobId);
return ok;
}
*/
DCR *new_dcr(JCR *jcr, DEVICE *dev)
{
+ if (jcr) Dmsg2(100, "enter new_dcr JobId=%u dev=%p\n", (uint32_t)jcr->JobId, dev);
DCR *dcr = (DCR *)malloc(sizeof(DCR));
memset(dcr, 0, sizeof(DCR));
dcr->jcr = jcr;
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
- if (!dcr->attached_to_dev && dev->is_open() && jcr && jcr->JobType != JT_SYSTEM) {
+ if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
+ if (!dcr->attached_to_dev && dev->initiated && jcr && jcr->JobType != JT_SYSTEM) {
dev->attached_dcrs->append(dcr); /* attach dcr to device */
dcr->attached_to_dev = true;
+ Dmsg1(500, "JobId=%u attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
}
}
void detach_dcr_from_dev(DCR *dcr)
{
+ Dmsg1(500, "JobId=%u enter detach_dcr_from_dev\n", (uint32_t)dcr->jcr->JobId);
unreserve_device(dcr);
/* Detach this dcr only if attached */
dcr->attached_to_dev = false;
// remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
}
- pthread_cond_broadcast(&dcr->dev->wait_next_vol);
- pthread_cond_broadcast(&wait_device_release);
}
/*
Dmsg1(100, ">dird: %s", dir->msg);
bool ok = do_get_volume_info(dcr);
if (ok) {
- if (dcr->any_volume || !is_volume_in_use(dcr)) {
+ if (!is_volume_in_use(dcr)) {
found = true;
break;
} else {
}
if (found) {
Dmsg0(400, "dir_find_next_appendable_volume return true\n");
- reserve_volume(dcr, dcr->VolumeName); /* reserve volume */
+ if (reserve_volume(dcr, dcr->VolumeName) == 0) {
+ Dmsg2(100, "Could not reserve volume %s on %s\n", dcr->VolumeName,
+ dcr->dev->print_name());
+ goto bail_out;
+ }
V(vol_info_mutex);
unlock_reservations();
return true;
}
+
+bail_out:
dcr->VolumeName[0] = 0;
V(vol_info_mutex);
unlock_reservations();
dev->clear_opened();
dev->attached_dcrs = New(dlist(dcr, &dcr->dev_link));
Dmsg2(29, "init_dev: tape=%d dev_name=%s\n", dev->is_tape(), dev->dev_name);
+ dev->initiated = true;
return dev;
}
int openmode; /* parameter passed to open_dev (useful to reopen the device) */
int dev_type; /* device type */
bool autoselect; /* Autoselect in autochanger */
+ bool initiated; /* set when init_dev() called */
int label_type; /* Bacula/ANSI/IBM label types */
uint32_t drive_index; /* Autochanger drive index (base 0) */
int32_t Slot; /* Slot currently in drive (base 1) */
/* If thread waiting on mount, wake him */
if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->waiting_for_mount()) {
pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
+ Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId);
pthread_cond_broadcast(&wait_device_release);
}
if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->waiting_for_mount()) {
pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol);
+ Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId);
pthread_cond_broadcast(&wait_device_release);
}
Jmsg(jcr, M_INFO, 0, _("Job %s marked to be canceled.\n"), jcr->Job);
bnet_fsend(dir, "3001 OK mount. Device=%s\n",
dev->print_name());
pthread_cond_broadcast(&dev->wait_next_vol);
+ Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)dcr->jcr->JobId);
pthread_cond_broadcast(&wait_device_release);
break;
dev->print_name());
}
pthread_cond_broadcast(&dev->wait_next_vol);
+ Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)dcr->jcr->JobId);
pthread_cond_broadcast(&wait_device_release);
break;
}
dev->set_labeled(); /* set has Bacula label */
- reserve_volume(dcr, dev->VolHdr.VolumeName);
+ if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) {
+ Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"),
+ dev->VolHdr.VolumeName, dev->print_name());
+ stat = VOL_NAME_ERROR;
+ goto bail_out;
+ }
/* Compare Volume Names */
Dmsg2(30, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName);
if (debug_level >= 20) {
dump_volume_label(dev);
}
- reserve_volume(dcr, VolName);
+ if (reserve_volume(dcr, VolName) == NULL) {
+ Mmsg2(dcr->jcr->errmsg, _("Could not reserve volume %s on %s\n"),
+ dev->VolHdr.VolumeName, dev->print_name());
+ goto bail_out;
+ }
+
dev->clear_append(); /* remove append since this is PRE_LABEL */
return true;
for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
if (vol->dev == dev) {
Dmsg0(000, "Two Volumes on same device.\n");
- ASSERT(1);
+ ASSERT(0);
dev = vol->dev;
}
}
*
* Return: VOLRES entry on success
- * NULL error
+ * NULL volume busy on another drive
*/
VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
{
* when adding a new volume that no newly scheduled
* job can reserve it.
*/
- lock_reservations();
+// lock_reservations();
P(vol_list_lock);
debug_list_volumes("begin reserve_volume", debug_nolock);
/*
/* Caller wants to switch Volume to another device */
if (!vol->dev->is_busy()) {
/* OK to move it -- I'm not sure this will work */
- Dmsg3(100, "Swap vol=%s from dev=%s to %s\n", VolumeName,
- dev->print_name(), dev->print_name());
+ Dmsg3(100, "==== Swap vol=%s from dev=%s to %s\n", VolumeName,
+ vol->dev->print_name(), dev->print_name());
vol->dev->vol = NULL; /* take vol from old drive */
vol->dev->VolHdr.VolumeName[0] = 0;
vol->dev = dev; /* point vol at new drive */
dev->vol = vol; /* point dev at vol */
dev->VolHdr.VolumeName[0] = 0;
} else {
+ Dmsg3(100, "Volume busy could not swap vol=%s from dev=%s to %s\n", VolumeName,
+ vol->dev->print_name(), dev->print_name());
vol = NULL; /* device busy */
- Dmsg3(100, "Logic ERROR!!!! could not swap vol=%s from dev=%s to %s\n", VolumeName,
- dev->print_name(), dcr->dev->print_name());
- ASSERT(1); /* blow up!!! */
}
}
}
get_out:
debug_list_volumes("end new volume", debug_nolock);
V(vol_list_lock);
- unlock_reservations();
+// unlock_reservations();
return vol;
}
ASSERT(dcr);
- /* Get locks in correct order */
- unlock_reservations();
dev->dlock();
- lock_reservations();
if (is_device_unmounted(dev)) {
Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
ASSERT(dcr);
- /* Get locks in correct order */
- unlock_reservations();
dev->dlock();
- lock_reservations();
/* If device is being read, we cannot write it */
if (dev->can_read()) {
rdev->max_block_size = dcr->dev->max_block_size;
rdev->min_block_size = dcr->dev->min_block_size;
rdev->device = dcr->dev->device;
- rdcr = new_dcr(NULL, rdev);
+ rdcr = new_dcr(jcr, rdev);
rdcr->spool_fd = dcr->spool_fd;
rdcr->jcr = jcr; /* set a valid jcr */
block = dcr->block; /* save block */
/* ***FIXME*** wiffle through all dcrs */
if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->blocked()) {
pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
+ Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId);
pthread_cond_broadcast(&wait_device_release);
}
if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->blocked()) {
/*
* Wait for any device to be released, then we return, so
- * higher level code can rescan possible devices.
+ * higher level code can rescan possible devices. Since there
+ * could be a job waiting for a drive to free up, we wait a maximum
+ * of 1 minute then retry just in case a broadcast was lost, and
+ * we return to rescan the devices.
*
* Returns: true if a device has changed state
* false if the total wait time has expired.
struct timespec timeout;
int stat = 0;
bool ok = true;
- const int wait_time = 5 * 60; /* wait 5 minutes */
+ const int max_wait_time = 1 * 60; /* wait 1 minute */
Dmsg0(100, "Enter wait_for_device\n");
P(device_release_mutex);
gettimeofday(&tv, &tz);
timeout.tv_nsec = tv.tv_usec * 1000;
- timeout.tv_sec = tv.tv_sec + wait_time;
+ timeout.tv_sec = tv.tv_sec + max_wait_time;
- Dmsg0(100, "I'm going to wait for a device.\n");
+ Dmsg1(100, "JobId=%u going to wait for a device.\n", (uint32_t)jcr->JobId);
/* 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);
+ Dmsg2(100, "JobId=%u wokeup from sleep on device stat=%d\n", (uint32_t)jcr->JobId, stat);
V(device_release_mutex);
- Dmsg1(100, "Return from wait_device ok=%d\n", ok);
+ Dmsg2(100, "JobId=%u return from wait_device ok=%d\n", (uint32_t)jcr->JobId, ok);
return ok;
}
#undef VERSION
#define VERSION "2.1.8"
-#define BDATE "12 April 2007"
-#define LSMDATE "12Apr07"
+#define BDATE "14 April 2007"
+#define LSMDATE "14Apr07"
#define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
#define BYEAR "2007" /* year for copyright messages in progs */
Technical notes on version 2.1
General:
+14Apr07
+kes Simplify locking in the reservations system.
+kes Add more debug code in reservations.
+kes Make sure error condition on reserving a volume is handled correctly.
+kes Correct handling of volume_in_use.
+kes Correct handling of initializing a device.
+kes Move handling of broadcasting releasing a device into release_device().
+kes Correct attaching dcr to dev so that it is only done if device
+ is properly initiated.
12Apr07
kes Locking debug level tweaks in SD.
kes Tweak new Volume code.