]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/jcr.c
DB changes for Retention Periods
[bacula/bacula] / bacula / src / lib / jcr.c
1 /*
2  * Manipulation routines for Job Control Records
3  *
4  *  Kern E. Sibbald, December 2000
5  *
6  *  These routines are thread safe.
7  *
8  */
9 /*
10    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of
15    the License, or (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20    General Public License for more details.
21
22    You should have received a copy of the GNU General Public
23    License along with this program; if not, write to the Free
24    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25    MA 02111-1307, USA.
26
27  */
28
29 #include "bacula.h"
30 #include "jcr.h"
31
32 struct s_last_job last_job;           /* last job run by this daemon */
33
34 static JCR *jobs = NULL;              /* pointer to JCR chain */
35 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
36
37 /*
38  * Create a Job Control Record and link it into JCR chain
39  * Returns newly allocated JCR
40  * Note, since each daemon has a different JCR, he passes
41  *  us the size.
42  */
43 JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
44 {
45    JCR *jcr;
46
47    Dmsg0(200, "Enter new_jcr\n");
48    jcr = (JCR *) malloc(size);
49    memset(jcr, 0, size);
50    jcr->my_thread_id = pthread_self();
51    P(mutex);
52    jcr->sched_time = time(NULL);
53    jcr->daemon_free_jcr = daemon_free_jcr;    /* plug daemon free routine */
54    jcr->prev = NULL;
55    jcr->next = jobs;
56    if (jobs) {
57       jobs->prev = jcr;
58    }
59    jcr->use_count = 1;
60    pthread_mutex_init(&(jcr->mutex), NULL);
61    jcr->JobStatus = JS_Created;       /* ready to run */
62    jcr->VolumeName = (char *) get_pool_memory(PM_FNAME);
63    jcr->VolumeName[0] = 0;
64    jcr->errmsg = (char *) get_pool_memory(PM_MESSAGE);
65    jcr->errmsg[0] = 0;
66    init_msg(jcr);                     /* init job message chain */
67    jobs = jcr;
68    V(mutex);
69    return jcr;
70 }
71
72
73 /*
74  * Remove a JCR from the chain
75  * NOTE! The chain must be locked prior to calling
76  *       this routine.
77  */
78 static void remove_jcr(JCR *jcr)
79 {
80    Dmsg0(150, "Enter remove_jcr\n");
81    if (!jcr) {
82       Emsg0(M_ABORT, 0, "NULL jcr.\n");
83    }
84    if (!jcr->prev) {                  /* if no prev */
85       jobs = jcr->next;               /* set new head */
86    } else {
87       jcr->prev->next = jcr->next;    /* update prev */
88    }
89    if (jcr->next) {
90       jcr->next->prev = jcr->prev;
91    }
92    Dmsg0(150, "Leave remove_jcr\n");
93 }
94
95 /*
96  * Free stuff common to all JCRs
97  */
98 static void free_common_jcr(JCR *jcr)
99 {
100    /* Keep some statistics */
101    switch (jcr->JobType) {
102       case JT_BACKUP:
103       case JT_VERIFY:
104       case JT_RESTORE:
105          last_job.NumJobs++;
106          last_job.JobType = jcr->JobType;
107          last_job.JobId = jcr->JobId;
108          last_job.VolSessionId = jcr->VolSessionId;
109          last_job.VolSessionTime = jcr->VolSessionTime;
110          strcpy(last_job.Job, jcr->Job);
111          last_job.JobFiles = jcr->JobFiles;
112          last_job.JobBytes = jcr->JobBytes;
113          last_job.JobStatus = jcr->JobStatus;
114          last_job.start_time = jcr->start_time;
115          last_job.end_time = time(NULL);
116          break;
117       default:
118          break;
119    }
120    pthread_mutex_destroy(&jcr->mutex);
121
122    close_msg(jcr);                    /* close messages for this job */
123
124    /* do this after closing messages */
125    if (jcr->client_name) {
126       free(jcr->client_name);
127       jcr->client_name = NULL;
128    }
129
130    if (jcr->sd_auth_key) {
131       Dmsg0(200, "Free JCR sd_auth_key\n");
132       free(jcr->sd_auth_key);
133       jcr->sd_auth_key = NULL;
134    }
135    if (jcr->VolumeName) {
136       free_pool_memory(jcr->VolumeName);
137       jcr->VolumeName = NULL;
138    }
139
140    if (jcr->dir_bsock) {
141       bnet_close(jcr->dir_bsock);
142       jcr->dir_bsock = NULL;
143    }
144    if (jcr->errmsg) {
145       free_pool_memory(jcr->errmsg);
146       jcr->errmsg = NULL;
147    }
148    free(jcr);
149 }
150
151 /* 
152  * Global routine to free a jcr
153  */
154 void free_jcr(JCR *jcr)
155 {
156    Dmsg0(200, "Enter free_jcr\n");
157    P(mutex);
158    jcr->use_count--;                  /* decrement use count */
159    Dmsg1(200, "Decrement jcr use_count=%d\n", jcr->use_count);
160    if (jcr->use_count > 0) {          /* if in use */
161       V(mutex);
162       Dmsg1(200, "jcr use_count=%d\n", jcr->use_count);
163       return;
164    }
165    remove_jcr(jcr);
166    V(mutex);
167    jcr->daemon_free_jcr(jcr);         /* call daemon free routine */
168    free_common_jcr(jcr);
169    Dmsg0(200, "Exit free_jcr\n");
170 }
171
172
173 /* 
174  * Global routine to free a jcr
175  *  JCR chain is already locked
176  */
177 void free_locked_jcr(JCR *jcr)
178 {
179    jcr->use_count--;                  /* decrement use count */
180    Dmsg1(200, "Decrement jcr use_count=%d\n", jcr->use_count);
181    if (jcr->use_count > 0) {          /* if in use */
182       return;
183    }
184    remove_jcr(jcr);
185    jcr->daemon_free_jcr(jcr);         /* call daemon free routine */
186    free_common_jcr(jcr);
187 }
188
189
190
191
192 /*
193  * Given a JobId, find the JCR      
194  *   Returns: jcr on success
195  *            NULL on failure
196  */
197 JCR *get_jcr_by_id(uint32_t JobId)
198 {
199    JCR *jcr;       
200
201    P(mutex);
202    for (jcr = jobs; jcr; jcr=jcr->next) {
203       if (jcr->JobId == JobId) {
204          jcr->use_count++;
205          Dmsg1(200, "Increment jcr use_count=%d\n", jcr->use_count);
206          break;
207       }
208    }
209    V(mutex);
210    return jcr; 
211 }
212
213
214
215 /*
216  * Given a Job, find the JCR      
217  *  compares on the number of characters in Job
218  *  thus allowing partial matches.
219  *   Returns: jcr on success
220  *            NULL on failure
221  */
222 JCR *get_jcr_by_partial_name(char *Job)
223 {
224    JCR *jcr;       
225    int len;
226
227    P(mutex);
228    len = strlen(Job);
229    for (jcr = jobs; jcr; jcr=jcr->next) {
230       if (strncmp(Job, jcr->Job, len) == 0) {
231          jcr->use_count++;
232          Dmsg1(200, "Increment jcr use_count=%d\n", jcr->use_count);
233          break;
234       }
235    }
236    V(mutex);
237    return jcr; 
238 }
239
240
241 /*
242  * Given a Job, find the JCR      
243  *  requires an exact match of names.
244  *   Returns: jcr on success
245  *            NULL on failure
246  */
247 JCR *get_jcr_by_full_name(char *Job)
248 {
249    JCR *jcr;       
250
251    P(mutex);
252    for (jcr = jobs; jcr; jcr=jcr->next) {
253       if (strcmp(jcr->Job, Job) == 0) {
254          jcr->use_count++;
255          Dmsg1(200, "Increment jcr use_count=%d\n", jcr->use_count);
256          break;
257       }
258    }
259    V(mutex);
260    return jcr; 
261 }
262
263 /* 
264  * Lock the chain
265  */
266 void lock_jcr_chain()
267 {
268    P(mutex);
269 }
270
271 /*
272  * Unlock the chain
273  */
274 void unlock_jcr_chain()
275 {
276    V(mutex);
277 }
278
279
280 JCR *get_next_jcr(JCR *jcr)
281 {
282    JCR *rjcr;
283
284    if (jcr == NULL) {
285       rjcr = jobs;
286    } else {
287       rjcr = jcr->next;
288    }
289    if (rjcr) {
290       rjcr->use_count++;
291       Dmsg1(200, "Increment jcr use_count=%d\n", rjcr->use_count);
292    }
293    return rjcr;
294 }