]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/newvol.c
kes Modify new volume algorithm to use max MediaId for generating next
[bacula/bacula] / bacula / src / dird / newvol.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-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 -- newvol.c -- creates new Volumes in
31  *    catalog Media table from the LabelFormat specification.
32  *
33  *     Kern Sibbald, May MMI
34  *
35  *    This routine runs as a thread and must be thread reentrant.
36  *
37  *  Basic tasks done here:
38  *      If possible create a new Media entry
39  *
40  *   Version $Id$
41  */
42
43 #include "bacula.h"
44 #include "dird.h"
45
46 /* Forward referenced functions */
47 static bool create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
48 static bool perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
49
50
51 /*
52  * Automatic Volume name creation using the LabelFormat
53  *
54  *  The media record must have the PoolId filled in when
55  *   calling this routine.
56  */
57 bool newVolume(JCR *jcr, MEDIA_DBR *mr)
58 {
59    POOL_DBR pr;
60
61    memset(&pr, 0, sizeof(pr));
62
63    /* See if we can create a new Volume */
64    db_lock(jcr->db);
65    pr.PoolId = mr->PoolId;
66    if (!db_get_pool_record(jcr, jcr->db, &pr)) {
67       goto bail_out;
68    }
69    if (pr.MaxVols == 0 || pr.NumVols < pr.MaxVols) {
70       memset(mr, 0, sizeof(MEDIA_DBR));
71       set_pool_dbr_defaults_in_media_dbr(mr, &pr);
72       jcr->VolumeName[0] = 0;
73       bstrncpy(mr->MediaType, jcr->wstore->media_type, sizeof(mr->MediaType));
74       if (generate_job_event(jcr, "NewVolume") == 1 && jcr->VolumeName[0] &&
75           is_volume_name_legal(NULL, jcr->VolumeName)) {
76          bstrncpy(mr->VolumeName, jcr->VolumeName, sizeof(mr->VolumeName));
77       /* Check for special characters */
78       } else if (pr.LabelFormat[0] && pr.LabelFormat[0] != '*') {
79          if (is_volume_name_legal(NULL, pr.LabelFormat)) {
80             /* No special characters, so apply simple algorithm */
81             if (!create_simple_name(jcr, mr, &pr)) {
82                goto bail_out;
83             }
84          } else {  /* try full substitution */
85             /* Found special characters, so try substitution */
86             if (!perform_full_name_substitution(jcr, mr, &pr)) {
87                goto bail_out;
88             }
89             if (!is_volume_name_legal(NULL, mr->VolumeName)) {
90                Jmsg(jcr, M_ERROR, 0, _("Illegal character in Volume name \"%s\"\n"),
91                   mr->VolumeName);
92                goto bail_out;
93             }
94          }
95       } else {                                       
96          goto bail_out;
97       }
98       pr.NumVols++;
99       mr->Enabled = 1;
100       if (db_create_media_record(jcr, jcr->db, mr) &&
101          db_update_pool_record(jcr, jcr->db, &pr)) {
102          db_unlock(jcr->db);
103          Jmsg(jcr, M_INFO, 0, _("Created new Volume \"%s\" in catalog.\n"), mr->VolumeName);
104          Dmsg1(90, "Created new Volume=%s\n", mr->VolumeName);
105          return true;
106       } else {
107          Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
108       }
109    }
110 bail_out:
111    db_unlock(jcr->db);
112    return false;
113 }
114
115 static bool create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
116 {
117    char name[MAXSTRING];
118    char num[20];
119    db_int64_ctx ctx;
120    POOL_MEM query(PM_MESSAGE);
121    char ed1[50];
122
123    /* See if volume already exists */
124    mr->VolumeName[0] = 0;
125    bstrncpy(name, pr->LabelFormat, sizeof(name));
126    ctx.value = 0;
127    Mmsg(query, "SELECT MAX(MediaId) FROM Media,POOL WHERE Pool.PoolId=%s", 
128         edit_int64(pr->PoolId, ed1));
129    if (!db_sql_query(jcr->db, query.c_str(), db_int64_handler, (void *)&ctx)) {
130       Jmsg(jcr, M_WARNING, 0, _("SQL failed, but ignored. ERR=%s\n"), db_strerror(jcr->db));
131       ctx.value = pr->NumVols+1;
132    }
133    for (int i=(int)ctx.value+1; i<(int)ctx.value+100; i++) {
134       MEDIA_DBR tmr;
135       memset(&tmr, 0, sizeof(tmr));
136       sprintf(num, "%04d", i);
137       bstrncpy(tmr.VolumeName, name, sizeof(tmr.VolumeName));
138       bstrncat(tmr.VolumeName, num, sizeof(tmr.VolumeName));
139       if (db_get_media_record(jcr, jcr->db, &tmr)) {
140          Jmsg(jcr, M_WARNING, 0,
141              _("Wanted to create Volume \"%s\", but it already exists. Trying again.\n"),
142              tmr.VolumeName);
143          continue;
144       }
145       bstrncpy(mr->VolumeName, name, sizeof(mr->VolumeName));
146       bstrncat(mr->VolumeName, num, sizeof(mr->VolumeName));
147       break;                    /* Got good name */
148    }
149    if (mr->VolumeName[0] == 0) {
150       Jmsg(jcr, M_ERROR, 0, _("Too many failures. Giving up creating Volume name.\n"));
151       return false;
152    }
153    return true;
154 }
155
156 /*
157  * Perform full substitution on Label
158  */
159 static bool perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
160 {
161    bool ok = false;
162    POOLMEM *label = get_pool_memory(PM_FNAME);
163    jcr->NumVols = pr->NumVols;
164    if (variable_expansion(jcr, pr->LabelFormat, &label)) {
165       bstrncpy(mr->VolumeName, label, sizeof(mr->VolumeName));
166       ok = true;
167    }
168    free_pool_memory(label);
169    return ok;
170 }