static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
static bool use_storage_cmd(JCR *jcr);
static void queue_reserve_message(JCR *jcr);
+static void pop_reserve_messages(JCR *jcr);
/* Requests from the Director daemon */
static char use_storage[] = "use storage=%127s media_type=%127s "
void unreserve_device(DCR *dcr)
{
DEVICE *dev = dcr->dev;
- dev->dlock();
if (dcr->reserved_device) {
dcr->reserved_device = false;
dev->reserved_device--;
}
volume_unused(dcr);
- dev->dunlock();
}
/*
* explicitly read in this drive. This allows the SD to remember
* where the tapes are or last were.
*/
- if (dev->is_tape()) {
+ if (dev->is_tape() || dev->is_autochanger()) {
return true;
} else {
return free_volume(dev);
}
lock_volumes();
foreach_dlist(vol, vol_list) {
- Dmsg3(dbglvl, "jid=%u Unreleased Volume=%s dev=%p\n", jid(), vol->vol_name, vol->dev);
+ if (vol->dev) {
+ Dmsg3(dbglvl, "jid=%u free vol_list Volume=%s dev=%s\n", jid(),
+ vol->vol_name, vol->dev->print_name());
+ } else {
+ Dmsg3(dbglvl, "jid=%u free vol_list Volume=%s dev=%p\n", jid(),
+ vol->vol_name, vol->dev);
+ }
free(vol->vol_name);
vol->vol_name = NULL;
}
int Copy, Stripe;
DIRSTORE *store;
RCTX rctx;
- char *msg;
- alist *msgs;
alist *dirstore;
memset(&rctx, 0, sizeof(RCTX));
* use_device for each device that it wants to use.
*/
dirstore = New(alist(10, not_owned_by_alist));
- msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
+ jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
do {
Dmsg2(dbglvl, "jid=%u <dird: %s", jid(), dir->msg);
ok = sscanf(dir->msg, use_storage, store_name.c_str(),
}
init_jcr_device_wait_timers(jcr);
+ jcr->dcr = new_dcr(jcr, NULL, NULL); /* get a dcr */
+ if (!jcr->dcr) {
+ BSOCK *dir = jcr->dir_bsock;
+ dir->fsend(_("3939 Could not get dcr\n"));
+ Dmsg1(dbglvl, ">dird: %s", dir->msg);
+ ok = false;
+ }
/*
* At this point, we have a list of all the Director's Storage
* resources indicated for this Job, which include Pool, PoolType,
int repeat = 0;
bool fail = false;
rctx.notify_dir = true;
+
lock_reservations();
for ( ; !fail && !job_canceled(jcr); ) {
- while ((msg = (char *)msgs->pop())) {
- free(msg);
- }
+ pop_reserve_messages(jcr);
rctx.suitable_device = false;
rctx.have_volume = false;
rctx.VolumeName[0] = 0;
rctx.any_drive = false;
if (!jcr->PreferMountedVols) {
- /* Look for unused drives in autochangers */
+ /*
+ * Here we try to find a drive that is not used.
+ * This will maximize the use of available drives.
+ *
+ */
rctx.num_writers = 20000000; /* start with impossible number */
rctx.low_use_drive = NULL;
rctx.PreferMountedVols = false;
break;
}
}
- /* Look for an exact match all drives */
+ /*
+ * Now we look for a drive that may or may not be in
+ * use.
+ */
+ /* Look for an exact Volume match all drives */
rctx.PreferMountedVols = true;
rctx.exact_match = true;
rctx.autochanger_only = false;
Dmsg2(dbglvl, "jid=%u >dird: %s", jid(), dir->msg);
}
- release_msgs(jcr);
+ release_reserve_messages(jcr);
return ok;
}
-void release_msgs(JCR *jcr)
+
+/*
+ * Walk through the autochanger resources and check if
+ * the volume is in one of them.
+ *
+ * Returns: true if volume is in device
+ * false otherwise
+ */
+static bool is_vol_in_autochanger(RCTX &rctx, VOLRES *vol)
{
- alist *msgs = jcr->reserve_msgs;
- char *msg;
+ AUTOCHANGER *changer = vol->dev->device->changer_res;
- if (!msgs) {
- return;
- }
- lock_reservations();
- while ((msg = (char *)msgs->pop())) {
- free(msg);
- }
- delete msgs;
- jcr->reserve_msgs = NULL;
- unlock_reservations();
+ /* Find resource, and make sure we were able to open it */
+ if (strcmp(rctx.device_name, changer->hdr.name) == 0) {
+ Dmsg2(dbglvl, "jid=%u Found changer device %s\n",
+ (int)rctx.jcr->JobId, vol->dev->device->hdr.name);
+ return true;
+ }
+ Dmsg2(dbglvl, "jid=%u Incorrect changer device %s\n",
+ (int)rctx.jcr->JobId, changer->hdr.name);
+ return false;
}
/*
DIRSTORE *store;
char *device_name;
alist *dirstore;
+ DCR *dcr = jcr->dcr;
if (rctx.append) {
dirstore = jcr->write_store;
rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
rctx.autochanger_only);
+ /*
+ * If the appropriate conditions of this if are met, namely that
+ * we are appending and the user wants mounted drive (or we
+ * force try a mounted drive because they are all busy), we
+ * start by looking at all the Volumes in the volume list.
+ */
if (!vol_list->empty() && rctx.append && rctx.PreferMountedVols) {
dlist *temp_vol_list, *save_vol_list;
VOLRES *vol = NULL;
unlock_volumes();
/* Look through reserved volumes for one we can use */
+ Dmsg1(dbglvl, "jid=%u look for vol in vol list\n", (int)rctx.jcr->JobId);
foreach_dlist(vol, temp_vol_list) {
if (!vol->dev) {
+ Dmsg2(dbglvl, "jid=%u vol=%s no dev\n", (int)rctx.jcr->JobId, vol->vol_name);
continue;
}
+ /* Check with Director if this Volume is OK */
+ bstrncpy(dcr->VolumeName, vol->vol_name, sizeof(dcr->VolumeName));
+ if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
+ continue;
+ }
+
+ Dmsg2(dbglvl, "jid=%u vol=%s OK for this job\n", (int)rctx.jcr->JobId, vol->vol_name);
foreach_alist(store, dirstore) {
+ int stat;
rctx.store = store;
foreach_alist(device_name, store->device) {
- int stat;
- if (strcmp(device_name, vol->dev->device->hdr.name) != 0) {
- continue;
- }
+ /* Found a device, try to use it */
rctx.device_name = device_name;
rctx.device = vol->dev->device;
+
+ if (vol->dev->is_autochanger()) {
+ Dmsg2(dbglvl, "jid=%u vol=%s is in changer\n", (int)rctx.jcr->JobId,
+ vol->vol_name);
+ if (!is_vol_in_autochanger(rctx, vol)) {
+ continue;
+ }
+ } else if (strcmp(device_name, vol->dev->device->hdr.name) != 0) {
+ Dmsg3(dbglvl, "jid=%u device=%s not suitable want %s\n", (int)rctx.jcr->JobId,
+ vol->dev->device->hdr.name, device_name);
+ continue;
+ }
+
bstrncpy(rctx.VolumeName, vol->vol_name, sizeof(rctx.VolumeName));
rctx.have_volume = true;
/* Try reserving this device and volume */
break;
}
}
+ if (ok) {
+ break;
+ }
} /* end for loop over reserved volumes */
+
lock_volumes();
save_vol_list = vol_list;
vol_list = temp_vol_list;
unlock_volumes();
}
if (ok) {
- Dmsg2(dbglvl, "jid=%u got vol %s in reserved volums list\n", (int)rctx.jcr->JobId,
+ Dmsg2(dbglvl, "jid=%u got vol %s from in-use vols list\n", (int)rctx.jcr->JobId,
rctx.VolumeName);
return true;
}
foreach_res(changer, R_AUTOCHANGER) {
Dmsg2(dbglvl, "jid=%u Try match changer res=%s\n", (int)rctx.jcr->JobId, changer->hdr.name);
/* Find resource, and make sure we were able to open it */
- if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
+ if (strcmp(rctx.device_name, changer->hdr.name) == 0) {
/* Try each device in this AutoChanger */
foreach_alist(rctx.device, changer->device) {
Dmsg2(dbglvl, "jid=%u Try changer device %s\n", (int)rctx.jcr->JobId,
foreach_res(rctx.device, R_DEVICE) {
Dmsg2(dbglvl, "jid=%u Try match res=%s\n", (int)rctx.jcr->JobId, rctx.device->hdr.name);
/* Find resource, and make sure we were able to open it */
- if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
+ if (strcmp(rctx.device_name, rctx.device->hdr.name) == 0) {
stat = reserve_device(rctx);
if (stat != 1) { /* try another device */
continue;
rctx.suitable_device = true;
Dmsg2(dbglvl, "jid=%u try reserve %s\n", rctx.jcr->JobId, rctx.device->hdr.name);
- dcr = new_dcr(rctx.jcr, rctx.device->dev);
+ rctx.jcr->dcr = dcr = new_dcr(rctx.jcr, rctx.jcr->dcr, rctx.device->dev);
if (!dcr) {
BSOCK *dir = rctx.jcr->dir_bsock;
dir->fsend(_("3926 Could not get dcr for device: %s\n"), rctx.device_name);
bail_out:
rctx.have_volume = false;
- free_dcr(dcr);
+// free_dcr(dcr);
Dmsg1(dbglvl, "jid=%u Not OK.\n", (int)rctx.jcr->JobId);
return 0;
}
return 0;
}
+
+
+
/*
- * search_lock is already set on entering this routine
+ * Queue a reservation error or failure message for this jcr
*/
static void queue_reserve_message(JCR *jcr)
{
int i;
- alist *msgs = jcr->reserve_msgs;
+ alist *msgs;
char *msg;
+ jcr->lock();
+
+ msgs = jcr->reserve_msgs;
if (!msgs) {
- return;
+ goto bail_out;
}
/*
* Look for duplicate message. If found, do
for (i=msgs->size()-1; i >= 0; i--) {
msg = (char *)msgs->get(i);
if (!msg) {
- return;
+ goto bail_out;
}
/* Comparison based on 4 digit message number */
if (strncmp(msg, jcr->errmsg, 4) == 0) {
- return;
+ goto bail_out;
}
}
/* Message unique, so insert it */
jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
+
+bail_out:
+ jcr->unlock();
}
/*
alist *msgs;
char *msg;
- lock_reservations();
+ jcr->lock();
msgs = jcr->reserve_msgs;
if (!msgs || msgs->size() == 0) {
goto bail_out;
}
bail_out:
- unlock_reservations();
+ jcr->unlock();
+}
+
+/*
+ * Pop and release any reservations messages
+ */
+static void pop_reserve_messages(JCR *jcr)
+{
+ alist *msgs;
+ char *msg;
+
+ jcr->lock();
+ msgs = jcr->reserve_msgs;
+ if (!msgs) {
+ goto bail_out;
+ }
+ while ((msg = (char *)msgs->pop())) {
+ free(msg);
+ }
+bail_out:
+ jcr->unlock();
+}
+
+/*
+ * Also called from acquire.c
+ */
+void release_reserve_messages(JCR *jcr)
+{
+ pop_reserve_messages(jcr);
+ jcr->lock();
+ if (!jcr->reserve_msgs) {
+ goto bail_out;
+ }
+ delete jcr->reserve_msgs;
+ jcr->reserve_msgs = NULL;
+
+bail_out:
+ jcr->unlock();
}