]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/autoprune.c
More pruning cleanup
[bacula/bacula] / bacula / src / dird / autoprune.c
1 /*
2  *
3  *   Bacula Director -- Automatic Pruning
4  *      Applies retention periods
5  *
6  *     Kern Sibbald, May MMII
7  *
8  *   Version $Id$
9  */
10 /*
11    Bacula® - The Network Backup Solution
12
13    Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
14
15    The main author of Bacula is Kern Sibbald, with contributions from
16    many others, a complete list can be found in the file AUTHORS.
17    This program is Free Software; you can redistribute it and/or
18    modify it under the terms of version two of the GNU General Public
19    License as published by the Free Software Foundation plus additions
20    that are listed in the file LICENSE.
21
22    This program is distributed in the hope that it will be useful, but
23    WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25    General Public License for more details.
26
27    You should have received a copy of the GNU General Public License
28    along with this program; if not, write to the Free Software
29    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30    02110-1301, USA.
31
32    Bacula® is a registered trademark of John Walker.
33    The licensor of Bacula is the Free Software Foundation Europe
34    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
35    Switzerland, email:ftf@fsfeurope.org.
36 */
37
38 #include "bacula.h"
39 #include "dird.h"
40 #include "ua.h"
41
42 /* Forward referenced functions */
43
44
45 /*
46  * Auto Prune Jobs and Files. This is called at the end of every
47  *   Job.  We do not prune volumes here.
48  */
49 void do_autoprune(JCR *jcr)
50 {
51    UAContext *ua;
52    CLIENT *client;
53    bool pruned;
54
55    if (!jcr->client) {                /* temp -- remove me */
56       return;
57    }
58
59    ua = new_ua_context(jcr);
60
61    client = jcr->client;
62
63    if (jcr->job->PruneJobs || jcr->client->AutoPrune) {
64       Jmsg(jcr, M_INFO, 0, _("Begin pruning Jobs.\n"));
65       prune_jobs(ua, client, jcr->JobType);
66       pruned = true;
67    } else {
68       pruned = false;
69    }
70
71    if (jcr->job->PruneFiles || jcr->client->AutoPrune) {
72       Jmsg(jcr, M_INFO, 0, _("Begin pruning Files.\n"));
73       prune_files(ua, client);
74       pruned = true;
75    }
76    if (pruned) {
77       Jmsg(jcr, M_INFO, 0, _("End auto prune.\n\n"));
78    }
79
80    free_ua_context(ua);
81    return;
82 }
83
84 /*
85  * Prune at least on Volume in current Pool. This is called from
86  *   catreq.c when the Storage daemon is asking for another
87  *   volume and no appendable volumes are available.
88  *
89  *  Return: false if nothing pruned
90  *          true if pruned, and mr is set to pruned volume
91  */
92 bool prune_volumes(JCR *jcr, MEDIA_DBR *mr) 
93 {
94    int count;
95    int i;
96    uint32_t *ids = NULL;
97    int num_ids = 0;
98    struct del_ctx del;
99    UAContext *ua;
100    bool ok = false;
101
102    Dmsg1(050, "Prune volumes PoolId=%d\n", jcr->jr.PoolId);
103    if (!jcr->job->PruneVolumes && !jcr->pool->AutoPrune) {
104       Dmsg0(100, "AutoPrune not set in Pool.\n");
105       return 0;
106    }
107    memset(&del, 0, sizeof(del));
108    del.max_ids = 1000;
109    del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
110
111    ua = new_ua_context(jcr);
112
113    db_lock(jcr->db);
114
115    /* Get the List of all media ids in the current Pool */
116    if (!db_get_media_ids(jcr, jcr->db, mr, &num_ids, &ids)) {
117       Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
118       goto bail_out;
119    }
120
121    /* Visit each Volume and Prune it */
122    for (i=0; i<num_ids; i++) {
123       MEDIA_DBR lmr;
124       memset(&lmr, 0, sizeof(lmr));
125       lmr.MediaId = ids[i];
126       Dmsg1(150, "Get record MediaId=%d\n", (int)lmr.MediaId);
127       if (!db_get_media_record(jcr, jcr->db, &lmr)) {
128          Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
129          continue;
130       }
131       /* Prune only Volumes from current Pool */
132       if (mr->PoolId != lmr.PoolId) {
133          continue;
134       }
135       /* Don't prune archived volumes */
136       if (lmr.Enabled == 2) {
137          continue;
138       }
139       /* Prune only Volumes with status "Full", or "Used" */
140       if (strcmp(lmr.VolStatus, "Full")   == 0 ||
141           strcmp(lmr.VolStatus, "Used")   == 0) {
142          Dmsg2(050, "Add prune list MediaId=%d Volume %s\n", (int)lmr.MediaId, lmr.VolumeName);
143          count = get_prune_list_for_volume(ua, &lmr, &del);
144          Dmsg1(050, "Num pruned = %d\n", count);
145          if (count != 0) {
146             purge_job_list_from_catalog(ua, del);
147             del.num_ids = 0;             /* reset count */
148          }
149          ok = is_volume_purged(ua, &lmr);
150          if (ok) {
151             Dmsg2(050, "Vol=%s MediaId=%d purged.\n", lmr.VolumeName, (int)lmr.MediaId);
152             mr = &lmr;             /* struct copy */
153             break;
154          }
155       }
156    }
157
158 bail_out:
159    db_unlock(jcr->db);
160    free_ua_context(ua);
161    if (ids) {
162       free(ids);
163    }
164    if (del.JobId) {
165       free(del.JobId);
166    }
167    return ok;
168 }