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