]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/jcr.c
This commit was manufactured by cvs2svn to create tag
[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    jobs = jcr;
67    V(mutex);
68    return jcr;
69 }
70
71
72 /*
73  * Remove a JCR from the chain
74  * NOTE! The chain must be locked prior to calling
75  *       this routine.
76  */
77 static void remove_jcr(JCR *jcr)
78 {
79    Dmsg0(150, "Enter remove_jcr\n");
80    if (!jcr) {
81       Emsg0(M_ABORT, 0, "NULL jcr.\n");
82    }
83    if (!jcr->prev) {                  /* if no prev */
84       jobs = jcr->next;               /* set new head */
85    } else {
86       jcr->prev->next = jcr->next;    /* update prev */
87    }
88    if (jcr->next) {
89       jcr->next->prev = jcr->prev;
90    }
91    Dmsg0(150, "Leave remove_jcr\n");
92 }
93
94 /*
95  * Free stuff common to all JCRs
96  */
97 static void free_common_jcr(JCR *jcr)
98 {
99    /* Keep some statistics */
100    switch (jcr->JobType) {
101       case JT_BACKUP:
102       case JT_VERIFY:
103       case JT_RESTORE:
104          last_job.NumJobs++;
105          last_job.JobType = jcr->JobType;
106          last_job.JobId = jcr->JobId;
107          last_job.VolSessionId = jcr->VolSessionId;
108          last_job.VolSessionTime = jcr->VolSessionTime;
109          strcpy(last_job.Job, jcr->Job);
110          last_job.JobFiles = jcr->JobFiles;
111          last_job.JobBytes = jcr->JobBytes;
112          last_job.JobStatus = jcr->JobStatus;
113          last_job.start_time = jcr->start_time;
114          last_job.end_time = time(NULL);
115          break;
116       default:
117          break;
118    }
119    pthread_mutex_destroy(&jcr->mutex);
120
121    close_msg(jcr);                    /* close messages for this job */
122
123    /* do this after closing messages */
124    if (jcr->client_name) {
125       free(jcr->client_name);
126       jcr->client_name = NULL;
127    }
128
129    if (jcr->sd_auth_key) {
130       Dmsg0(200, "Free JCR sd_auth_key\n");
131       free(jcr->sd_auth_key);
132       jcr->sd_auth_key = NULL;
133    }
134    if (jcr->VolumeName) {
135       free_pool_memory(jcr->VolumeName);
136       jcr->VolumeName = NULL;
137    }
138
139    if (jcr->dir_bsock) {
140       bnet_close(jcr->dir_bsock);
141       jcr->dir_bsock = NULL;
142    }
143    if (jcr->errmsg) {
144       free_pool_memory(jcr->errmsg);
145       jcr->errmsg = NULL;
146    }
147    free(jcr);
148 }
149
150 /* 
151  * Global routine to free a jcr
152  */
153 void free_jcr(JCR *jcr)
154 {
155    Dmsg0(200, "Enter free_jcr\n");
156    P(mutex);
157    jcr->use_count--;                  /* decrement use count */
158    Dmsg1(200, "Decrement jcr use_count=%d\n", jcr->use_count);
159    if (jcr->use_count > 0) {          /* if in use */
160       V(mutex);
161       Dmsg1(200, "jcr use_count=%d\n", jcr->use_count);
162       return;
163    }
164    remove_jcr(jcr);
165    V(mutex);
166    jcr->daemon_free_jcr(jcr);         /* call daemon free routine */
167    free_common_jcr(jcr);
168    Dmsg0(200, "Exit free_jcr\n");
169 }
170
171
172 /* 
173  * Global routine to free a jcr
174  *  JCR chain is already locked
175  */
176 void free_locked_jcr(JCR *jcr)
177 {
178    jcr->use_count--;                  /* decrement use count */
179    Dmsg1(200, "Decrement jcr use_count=%d\n", jcr->use_count);
180    if (jcr->use_count > 0) {          /* if in use */
181       return;
182    }
183    remove_jcr(jcr);
184    jcr->daemon_free_jcr(jcr);         /* call daemon free routine */
185    free_common_jcr(jcr);
186 }
187
188
189
190
191 /*
192  * Given a JobId, find the JCR      
193  *   Returns: jcr on success
194  *            NULL on failure
195  */
196 JCR *get_jcr_by_id(uint32_t JobId)
197 {
198    JCR *jcr;       
199
200    P(mutex);
201    for (jcr = jobs; jcr; jcr=jcr->next) {
202       if (jcr->JobId == JobId) {
203          jcr->use_count++;
204          Dmsg1(200, "Increment jcr use_count=%d\n", jcr->use_count);
205          break;
206       }
207    }
208    V(mutex);
209    return jcr; 
210 }
211
212
213
214 /*
215  * Given a Job, find the JCR      
216  *  compares on the number of characters in Job
217  *  thus allowing partial matches.
218  *   Returns: jcr on success
219  *            NULL on failure
220  */
221 JCR *get_jcr_by_partial_name(char *Job)
222 {
223    JCR *jcr;       
224    int len;
225
226    P(mutex);
227    len = strlen(Job);
228    for (jcr = jobs; jcr; jcr=jcr->next) {
229       if (strncmp(Job, jcr->Job, len) == 0) {
230          jcr->use_count++;
231          Dmsg1(200, "Increment jcr use_count=%d\n", jcr->use_count);
232          break;
233       }
234    }
235    V(mutex);
236    return jcr; 
237 }
238
239
240 /*
241  * Given a Job, find the JCR      
242  *  requires an exact match of names.
243  *   Returns: jcr on success
244  *            NULL on failure
245  */
246 JCR *get_jcr_by_full_name(char *Job)
247 {
248    JCR *jcr;       
249
250    P(mutex);
251    for (jcr = jobs; jcr; jcr=jcr->next) {
252       if (strcmp(jcr->Job, Job) == 0) {
253          jcr->use_count++;
254          Dmsg1(200, "Increment jcr use_count=%d\n", jcr->use_count);
255          break;
256       }
257    }
258    V(mutex);
259    return jcr; 
260 }
261
262 /* 
263  * Lock the chain
264  */
265 void lock_jcr_chain()
266 {
267    P(mutex);
268 }
269
270 /*
271  * Unlock the chain
272  */
273 void unlock_jcr_chain()
274 {
275    V(mutex);
276 }
277
278
279 JCR *get_next_jcr(JCR *jcr)
280 {
281    JCR *rjcr;
282
283    if (jcr == NULL) {
284       rjcr = jobs;
285    } else {
286       rjcr = jcr->next;
287    }
288    if (rjcr) {
289       rjcr->use_count++;
290       Dmsg1(200, "Increment jcr use_count=%d\n", rjcr->use_count);
291    }
292    return rjcr;
293 }