X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fnext_vol.c;h=cb4a3397e31e2eb0a954f045ea0d790d26e76d8b;hb=bfb9e1ab0ca4934e55c5a0338312536558a0fa97;hp=8b54e67949ec35cc0128acc104d584c6f214290b;hpb=2463c676ecc3bc7e357b40bbdb1090e356d86031;p=bacula%2Fbacula diff --git a/bacula/src/dird/next_vol.c b/bacula/src/dird/next_vol.c index 8b54e67949..cb4a3397e3 100644 --- a/bacula/src/dird/next_vol.c +++ b/bacula/src/dird/next_vol.c @@ -1,12 +1,12 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2001-2008 Free Software Foundation Europe e.V. + Copyright (C) 2001-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. This program is Free Software; you can redistribute it and/or - modify it under the terms of version two of the GNU General Public + modify it under the terms of version three of the GNU Affero General Public License as published by the Free Software Foundation and included in the file LICENSE. @@ -15,12 +15,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software 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. @@ -33,15 +33,18 @@ * Kern Sibbald, March MMI * - * Version $Id$ */ #include "bacula.h" #include "dird.h" +static int const dbglvl = 50; /* debug level */ + /* * 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 * jcr->pool @@ -57,7 +60,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, STORE *store = jcr->wstore; bstrncpy(mr->MediaType, store->media_type, sizeof(mr->MediaType)); - Dmsg3(050, "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 @@ -76,13 +79,13 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, ok = db_find_next_volume(jcr, jcr->db, index, InChanger, mr); if (!ok) { - Dmsg4(050, "after find_next_vol ok=%d index=%d InChanger=%d Vstat=%s\n", + 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(050, "find_recycled_volume ok=%d FW=%d\n", ok, mr->FirstWritten); + Dmsg2(dbglvl, "find_recycled_volume ok=%d FW=%d\n", ok, mr->FirstWritten); if (!ok) { /* * 3. Try recycling any purged volume @@ -93,31 +96,29 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, * 4. Try pruning Volumes */ if (prune) { - Dmsg0(150, "Call prune_volumes\n"); - ok = prune_volumes(jcr, InChanger, mr); + Dmsg0(dbglvl, "Call prune_volumes\n"); + prune_volumes(jcr, InChanger, mr); + } + ok = recycle_oldest_purged_volume(jcr, InChanger, mr); + if (!ok && create) { + 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(dbglvl, "after get scratch volume ok=%d index=%d InChanger=%d Vstat=%s\n", + ok, index, InChanger, mr->VolStatus); + } + /* + * If we are using an Autochanger and have not found + * a volume, retry looking for any volume. + */ + if (!ok && InChanger) { + InChanger = false; + continue; /* retry again accepting any volume */ } - if (!ok) { - ok = recycle_oldest_purged_volume(jcr, InChanger, mr); - if (!ok && create) { - Dmsg4(050, "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(050, "after get scratch volume ok=%d index=%d InChanger=%d Vstat=%s\n", - ok, index, InChanger, mr->VolStatus); - } - /* - * If we are using an Autochanger and have not found - * a volume, retry looking for any volume. - */ - if (!ok && InChanger) { - InChanger = false; - continue; /* retry again accepting any volume */ - } - } - } + } } @@ -132,14 +133,14 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, */ if (!ok && (jcr->pool->purge_oldest_volume || jcr->pool->recycle_oldest_volume)) { - Dmsg2(050, "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 */ ok = db_find_next_volume(jcr, jcr->db, -1, InChanger, mr); - Dmsg1(050, "Find oldest=%d\n", ok); + Dmsg1(dbglvl, "Find oldest=%d Volume\n", ok); if (ok && prune) { UAContext *ua; - Dmsg0(050, "Try purge.\n"); + Dmsg0(dbglvl, "Try purge Volume.\n"); /* * 7. Try to purging oldest volume only if not UA calling us. */ @@ -157,12 +158,12 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, free_ua_context(ua); if (ok) { ok = recycle_volume(jcr, mr); - Dmsg1(050, "Recycle after purge oldest=%d\n", ok); + Dmsg1(dbglvl, "Recycle after purge oldest=%d\n", ok); } } } } - Dmsg2(050, "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)) { @@ -177,7 +178,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, break; } /* end for loop */ db_unlock(jcr->db); - Dmsg1(050, "return ok=%d find_next_vol\n", ok); + Dmsg1(dbglvl, "return ok=%d find_next_vol\n", ok); return ok; } @@ -188,6 +189,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) { bool expired = false; + char ed1[50]; /* * Check limits and expirations if "Append" and it has been used * i.e. mr->VolJobs > 0 @@ -196,8 +198,9 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) if (strcmp(mr->VolStatus, "Append") == 0 && mr->VolJobs > 0) { /* First handle Max Volume Bytes */ if ((mr->MaxVolBytes > 0 && mr->VolBytes >= mr->MaxVolBytes)) { - Jmsg(jcr, M_INFO, 0, _("Max Volume bytes exceeded. " - "Marking Volume \"%s\" as Full.\n"), mr->VolumeName); + Jmsg(jcr, M_INFO, 0, _("Max Volume bytes=%s exceeded. " + "Marking Volume \"%s\" as Full.\n"), + edit_uint64_with_commas(mr->MaxVolBytes, ed1), mr->VolumeName); bstrncpy(mr->VolStatus, "Full", sizeof(mr->VolStatus)); expired = true; @@ -210,17 +213,19 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) /* Now see if Max Jobs written to volume */ } else if (mr->MaxVolJobs > 0 && mr->MaxVolJobs <= mr->VolJobs) { - Jmsg(jcr, M_INFO, 0, _("Max Volume jobs exceeded. " - "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); - Dmsg3(100, "MaxVolJobs=%d JobId=%d Vol=%s\n", mr->MaxVolJobs, + 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(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; /* Now see if Max Files written to volume */ } else if (mr->MaxVolFiles > 0 && mr->MaxVolFiles <= mr->VolFiles) { - Jmsg(jcr, M_INFO, 0, _("Max Volume files exceeded. " - "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); + Jmsg(jcr, M_INFO, 0, _("Max Volume files=%s exceeded. " + "Marking Volume \"%s\" as Used.\n"), + edit_uint64_with_commas(mr->MaxVolFiles, ed1), mr->VolumeName); bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); expired = true; @@ -229,8 +234,9 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) utime_t now = time(NULL); /* See if Vol Use has expired */ if (mr->VolUseDuration <= (now - mr->FirstWritten)) { - Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. " - "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); + Jmsg(jcr, M_INFO, 0, _("Max configured use duration=%s sec. exceeded. " + "Marking Volume \"%s\" as Used.\n"), + edit_uint64_with_commas(mr->VolUseDuration, ed1), mr->VolumeName); bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); expired = true; } @@ -238,11 +244,13 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) } if (expired) { /* Need to update media */ + Dmsg1(dbglvl, "Vol=%s has expired update media record\n", mr->VolumeName); 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(dbglvl, "Vol=%s expired=%d\n", mr->VolumeName, expired); return expired; } @@ -297,8 +305,16 @@ void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, const char **r * it now possible to reuse it for the job that it is currently * needed for? */ - if ((mr->LastWritten + mr->VolRetention) < (utime_t)time(NULL) - && mr->Recycle && jcr->pool->recycle_current_volume + if (!mr->Recycle) { + *reason = _("volume has recycling disabled"); + return; + } + /* + * 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)) { /* @@ -341,9 +357,13 @@ bool get_scratch_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) P(mutex); /* * Get Pool record for Scratch Pool + * choose between ScratchPoolId and Scratch + * db_get_pool_record will first try ScratchPoolId, + * and then try the pool named Scratch */ memset(&spr, 0, sizeof(spr)); 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;