/*
Bacula® - The Network Backup Solution
- Copyright (C) 2001-2010 Free Software Foundation Europe e.V.
+ Copyright (C) 2001-2012 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.
#include "bacula.h"
#include "dird.h"
+static int const dbglvl = 50; /* debug level */
+
+/* Set storage id if possible */
+void set_storageid_in_mr(STORE *store, MEDIA_DBR *mr)
+{
+ if (store != NULL) {
+ mr->StorageId = store->StorageId;
+ }
+}
+
/*
* Items needed:
* mr.PoolId must be set
- * mr.StorageId should also be set
* mr.ScratchPoolId could be set (used if create==true)
* jcr->wstore
* jcr->db
STORE *store = jcr->wstore;
bstrncpy(mr->MediaType, store->media_type, sizeof(mr->MediaType));
- Dmsg3(100, "find_next_vol_for_append: JobId=%u PoolId=%d, MediaType=%s\n",
+ Dmsg3(dbglvl, "find_next_vol_for_append: JobId=%u PoolId=%d, MediaType=%s\n",
(uint32_t)jcr->JobId, (int)mr->PoolId, mr->MediaType);
/*
* If we are using an Autochanger, restrict Volume
/*
* 1. Look for volume with "Append" status.
*/
+ set_storageid_in_mr(store, mr); /* put StorageId in new record */
ok = db_find_next_volume(jcr, jcr->db, index, InChanger, mr);
if (!ok) {
- Dmsg4(150, "after find_next_vol ok=%d index=%d InChanger=%d Vstat=%s\n",
+ /*
+ * No volume found, apply algorithm
+ */
+ Dmsg4(dbglvl, "after find_next_vol ok=%d index=%d InChanger=%d Vstat=%s\n",
ok, index, InChanger, mr->VolStatus);
/*
* 2. Try finding a recycled volume
*/
- ok = find_recycled_volume(jcr, InChanger, mr);
- Dmsg2(150, "find_recycled_volume ok=%d FW=%d\n", ok, mr->FirstWritten);
+ ok = find_recycled_volume(jcr, InChanger, mr, store);
+ set_storageid_in_mr(store, mr); /* put StorageId in new record */
+ Dmsg2(dbglvl, "find_recycled_volume ok=%d FW=%d\n", ok, mr->FirstWritten);
if (!ok) {
/*
* 3. Try recycling any purged volume
*/
- ok = recycle_oldest_purged_volume(jcr, InChanger, mr);
+ ok = recycle_oldest_purged_volume(jcr, InChanger, mr, store);
+ set_storageid_in_mr(store, mr); /* put StorageId in new record */
if (!ok) {
/*
* 4. Try pruning Volumes
*/
if (prune) {
- Dmsg0(150, "Call prune_volumes\n");
- prune_volumes(jcr, InChanger, mr);
+ Dmsg0(dbglvl, "Call prune_volumes\n");
+ prune_volumes(jcr, InChanger, mr, store);
}
- ok = recycle_oldest_purged_volume(jcr, InChanger, mr);
+ ok = recycle_oldest_purged_volume(jcr, InChanger, mr, store);
+ set_storageid_in_mr(store, mr); /* put StorageId in new record */
if (!ok && create) {
- Dmsg4(150, "after prune volumes_vol ok=%d index=%d InChanger=%d Vstat=%s\n",
+ Dmsg4(dbglvl, "after prune volumes_vol ok=%d index=%d InChanger=%d Vstat=%s\n",
ok, index, InChanger, mr->VolStatus);
/*
* 5. Try pulling a volume from the Scratch pool
*/
- ok = get_scratch_volume(jcr, InChanger, mr);
- Dmsg4(150, "after get scratch volume ok=%d index=%d InChanger=%d Vstat=%s\n",
+ ok = get_scratch_volume(jcr, InChanger, mr, store);
+ set_storageid_in_mr(store, mr); /* put StorageId in new record */
+ Dmsg4(dbglvl, "after get scratch volume ok=%d index=%d InChanger=%d Vstat=%s\n",
ok, index, InChanger, mr->VolStatus);
}
/*
/*
* 6. Try "creating" a new Volume
*/
- ok = newVolume(jcr, mr);
+ ok = newVolume(jcr, mr, store);
}
/*
* Look at more drastic ways to find an Appendable Volume
*/
if (!ok && (jcr->pool->purge_oldest_volume ||
jcr->pool->recycle_oldest_volume)) {
- Dmsg2(200, "No next volume found. PurgeOldest=%d\n RecyleOldest=%d",
+ Dmsg2(dbglvl, "No next volume found. PurgeOldest=%d\n RecyleOldest=%d",
jcr->pool->purge_oldest_volume, jcr->pool->recycle_oldest_volume);
/* Find oldest volume to recycle */
+ set_storageid_in_mr(store, mr); /* update storage id */
ok = db_find_next_volume(jcr, jcr->db, -1, InChanger, mr);
- Dmsg1(200, "Find oldest=%d Volume\n", ok);
+ set_storageid_in_mr(store, mr); /* update storageid */
+ Dmsg1(dbglvl, "Find oldest=%d Volume\n", ok);
if (ok && prune) {
UAContext *ua;
- Dmsg0(200, "Try purge Volume.\n");
+ Dmsg0(dbglvl, "Try purge Volume.\n");
/*
* 7. Try to purging oldest volume only if not UA calling us.
*/
free_ua_context(ua);
if (ok) {
ok = recycle_volume(jcr, mr);
- Dmsg1(400, "Recycle after purge oldest=%d\n", ok);
+ Dmsg1(dbglvl, "Recycle after purge oldest=%d\n", ok);
}
}
}
}
- Dmsg2(100, "VolJobs=%d FirstWritten=%d\n", mr->VolJobs, mr->FirstWritten);
+ Dmsg2(dbglvl, "VolJobs=%d FirstWritten=%d\n", mr->VolJobs, mr->FirstWritten);
if (ok) {
/* If we can use the volume, check if it is expired */
if (has_volume_expired(jcr, mr)) {
break;
} /* end for loop */
db_unlock(jcr->db);
- Dmsg1(150, "return ok=%d find_next_vol\n", ok);
+ Dmsg1(dbglvl, "return ok=%d find_next_vol\n", ok);
return ok;
}
Jmsg(jcr, M_INFO, 0, _("Max Volume jobs=%s exceeded. "
"Marking Volume \"%s\" as Used.\n"),
edit_uint64_with_commas(mr->MaxVolJobs, ed1), mr->VolumeName);
- Dmsg3(100, "MaxVolJobs=%d JobId=%d Vol=%s\n", mr->MaxVolJobs,
+ Dmsg3(dbglvl, "MaxVolJobs=%d JobId=%d Vol=%s\n", mr->MaxVolJobs,
(uint32_t)jcr->JobId, mr->VolumeName);
bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
expired = true;
}
if (expired) {
/* Need to update media */
- Dmsg1(150, "Vol=%s has expired update media record\n", mr->VolumeName);
+ Dmsg1(dbglvl, "Vol=%s has expired update media record\n", mr->VolumeName);
+ set_storageid_in_mr(NULL, mr);
if (!db_update_media_record(jcr, jcr->db, mr)) {
Jmsg(jcr, M_ERROR, 0, _("Catalog error updating volume \"%s\". ERR=%s"),
mr->VolumeName, db_strerror(jcr->db));
}
}
- Dmsg2(150, "Vol=%s expired=%d\n", mr->VolumeName, expired);
+ Dmsg2(dbglvl, "Vol=%s expired=%d\n", mr->VolumeName, expired);
return expired;
}
*reason = _("volume has recycling disabled");
return;
}
- if ((mr->LastWritten + mr->VolRetention) < (utime_t)time(NULL)
+ /*
+ * Check retention period from last written, but recycle to within
+ * a minute to try to catch close calls ...
+ */
+ if ((mr->LastWritten + mr->VolRetention - 60) < (utime_t)time(NULL)
&& jcr->pool->recycle_current_volume
&& (strcmp(mr->VolStatus, "Full") == 0 ||
strcmp(mr->VolStatus, "Used") == 0)) {
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-bool get_scratch_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr)
+bool get_scratch_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr,
+ STORE *store)
{
MEDIA_DBR smr; /* for searching scratch pool */
POOL_DBR spr, pr;
bstrncpy(spr.Name, "Scratch", sizeof(spr.Name));
spr.PoolId = mr->ScratchPoolId;
if (db_get_pool_record(jcr, jcr->db, &spr)) {
- memset(&smr, 0, sizeof(smr));
smr.PoolId = spr.PoolId;
if (InChanger) {
smr.StorageId = mr->StorageId; /* want only Scratch Volumes in changer */
* recycling any existing purged volumes, then
* try to take the oldest volume.
*/
+ set_storageid_in_mr(store, &smr); /* put StorageId in new record */
if (db_find_next_volume(jcr, jcr->db, 1, InChanger, &smr)) {
found = true;
- } else if (find_recycled_volume(jcr, InChanger, &smr)) {
+ } else if (find_recycled_volume(jcr, InChanger, &smr, store)) {
found = true;
- } else if (recycle_oldest_purged_volume(jcr, InChanger, &smr)) {
+ } else if (recycle_oldest_purged_volume(jcr, InChanger, &smr, store)) {
found = true;
}
goto bail_out;
}
- memcpy(mr, &smr, sizeof(MEDIA_DBR));
+ mr->copy(&smr);
+ set_storageid_in_mr(store, mr);
/* Set default parameters from current pool */
set_pool_dbr_defaults_in_media_dbr(mr, &pr);