]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
kes Move the checking of the database in initializion of the Director
[bacula/bacula] / bacula / src / dird / job.c
1 /*
2  *
3  *   Bacula Director Job processing routines
4  *
5  *     Kern Sibbald, October MM
6  *
7  *    Version $Id$
8  */
9 /*
10    Bacula® - The Network Backup Solution
11
12    Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
13
14    The main author of Bacula is Kern Sibbald, with contributions from
15    many others, a complete list can be found in the file AUTHORS.
16    This program is Free Software; you can redistribute it and/or
17    modify it under the terms of version two of the GNU General Public
18    License as published by the Free Software Foundation plus additions
19    that are listed in the file LICENSE.
20
21    This program is distributed in the hope that it will be useful, but
22    WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24    General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program; if not, write to the Free Software
28    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29    02110-1301, USA.
30
31    Bacula® is a registered trademark of John Walker.
32    The licensor of Bacula is the Free Software Foundation Europe
33    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
34    Switzerland, email:ftf@fsfeurope.org.
35 */
36
37 #include "bacula.h"
38 #include "dird.h"
39
40 /* Forward referenced subroutines */
41 static void *job_thread(void *arg);
42 static void job_monitor_watchdog(watchdog_t *self);
43 static void job_monitor_destructor(watchdog_t *self);
44 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr);
45 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr);
46
47 /* Imported subroutines */
48 extern void term_scheduler();
49 extern void term_ua_server();
50
51 /* Imported variables */
52
53 jobq_t job_queue;
54
55 void init_job_server(int max_workers)
56 {
57    int stat;
58    watchdog_t *wd;
59
60    if ((stat = jobq_init(&job_queue, max_workers, job_thread)) != 0) {
61       berrno be;
62       Emsg1(M_ABORT, 0, _("Could not init job queue: ERR=%s\n"), be.strerror(stat));
63    }
64    wd = new_watchdog();
65    wd->callback = job_monitor_watchdog;
66    wd->destructor = job_monitor_destructor;
67    wd->one_shot = false;
68    wd->interval = 60;
69    wd->data = new_control_jcr("*JobMonitor*", JT_SYSTEM);
70    register_watchdog(wd);
71 }
72
73 void term_job_server()
74 {
75    jobq_destroy(&job_queue);          /* ignore any errors */
76 }
77
78 /*
79  * Run a job -- typically called by the scheduler, but may also
80  *              be called by the UA (Console program).
81  *
82  *  Returns: 0 on failure
83  *           JobId on success
84  *
85  */
86 JobId_t run_job(JCR *jcr)
87 {
88    int stat;
89    if (setup_job(jcr)) {
90       Dmsg0(200, "Add jrc to work queue\n");
91       /* Queue the job to be run */
92       if ((stat = jobq_add(&job_queue, jcr)) != 0) {
93          berrno be;
94          Jmsg(jcr, M_FATAL, 0, _("Could not add job queue: ERR=%s\n"), be.strerror(stat));
95          return 0;
96       }
97       return jcr->JobId;
98    }
99    return 0;
100 }            
101
102 bool setup_job(JCR *jcr) 
103 {
104    int errstat;
105
106    jcr->lock();
107    sm_check(__FILE__, __LINE__, true);
108    init_msg(jcr, jcr->messages);
109
110    /* Initialize termination condition variable */
111    if ((errstat = pthread_cond_init(&jcr->term_wait, NULL)) != 0) {
112       berrno be;
113       Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.strerror(errstat));
114       goto bail_out;
115    }
116    jcr->term_wait_inited = true;
117
118    create_unique_job_name(jcr, jcr->job->name());
119    set_jcr_job_status(jcr, JS_Created);
120    jcr->unlock();
121
122    /*
123     * Open database
124     */
125    Dmsg0(50, "Open database\n");
126    jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
127                             jcr->catalog->db_password, jcr->catalog->db_address,
128                             jcr->catalog->db_port, jcr->catalog->db_socket,
129                             jcr->catalog->mult_db_connections);
130    if (!jcr->db || !db_open_database(jcr, jcr->db)) {
131       Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
132                  jcr->catalog->db_name);
133       if (jcr->db) {
134          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
135       }
136       goto bail_out;
137    }
138    Dmsg0(50, "DB opened\n");
139
140    if (!jcr->fname) {
141       jcr->fname = get_pool_memory(PM_FNAME);
142    }
143    if (!jcr->pool_source) {
144       jcr->pool_source = get_pool_memory(PM_MESSAGE);
145       pm_strcpy(jcr->pool_source, _("unknown source"));
146    }
147    Dmsg2(500, "pool=%s (From %s)\n", jcr->pool->name(), jcr->pool_source);
148    if (jcr->JobType == JT_MIGRATE) {
149       if (!jcr->rpool_source) {
150          jcr->rpool_source = get_pool_memory(PM_MESSAGE);
151          pm_strcpy(jcr->rpool_source, _("unknown source"));
152       }
153    }
154
155    /*
156     * Create Job record
157     */
158    init_jcr_job_record(jcr);
159    if (!get_or_create_client_record(jcr)) {
160       goto bail_out;
161    }
162
163    if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
164       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
165       goto bail_out;
166    }
167    jcr->JobId = jcr->jr.JobId;
168    Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
169        jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
170
171    generate_daemon_event(jcr, "JobStart");
172
173    if (job_canceled(jcr)) {
174       goto bail_out;
175    }
176
177    /*
178     * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
179     *  this allows us to setup a proper job start record for restarting
180     *  in case of later errors.
181     */
182    switch (jcr->JobType) {
183    case JT_BACKUP:
184       if (!do_backup_init(jcr)) {
185          backup_cleanup(jcr, JS_ErrorTerminated);
186       }
187       break;
188    case JT_VERIFY:
189       if (!do_verify_init(jcr)) {
190          verify_cleanup(jcr, JS_ErrorTerminated);
191       }
192       break;
193    case JT_RESTORE:
194       if (!do_restore_init(jcr)) {
195          restore_cleanup(jcr, JS_ErrorTerminated);
196       }
197       break;
198    case JT_ADMIN:
199       if (!do_admin_init(jcr)) {
200          admin_cleanup(jcr, JS_ErrorTerminated);
201       }
202       break;
203    case JT_MIGRATE:
204       if (!do_migration_init(jcr)) { 
205          migration_cleanup(jcr, JS_ErrorTerminated);
206       }
207       break;
208    default:
209       Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
210       set_jcr_job_status(jcr, JS_ErrorTerminated);
211       break;
212    }
213
214    generate_job_event(jcr, "JobInit");
215    return true;
216
217 bail_out:
218    return false;
219 }
220
221 void update_job_end(JCR *jcr, int TermCode)
222 {
223    dequeue_messages(jcr);             /* display any queued messages */
224    set_jcr_job_status(jcr, TermCode);
225    run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
226    update_job_end_record(jcr);
227 }
228
229 /*
230  * This is the engine called by jobq.c:jobq_add() when we were pulled
231  *  from the work queue.
232  *  At this point, we are running in our own thread and all
233  *    necessary resources are allocated -- see jobq.c
234  */
235 static void *job_thread(void *arg)
236 {
237    JCR *jcr = (JCR *)arg;
238
239    jcr->my_thread_id = pthread_self();
240    pthread_detach(jcr->my_thread_id);
241    sm_check(__FILE__, __LINE__, true);
242
243    Dmsg0(200, "=====Start Job=========\n");
244    set_jcr_job_status(jcr, JS_Running);   /* this will be set only if no error */
245    jcr->start_time = time(NULL);      /* set the real start time */
246    jcr->jr.StartTime = jcr->start_time;
247
248    if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
249        (utime_t)(jcr->start_time - jcr->sched_time)) {
250       set_jcr_job_status(jcr, JS_Canceled);
251       Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
252    }
253
254    /* TODO : check if it is used somewhere */
255    if (jcr->job->RunScripts == NULL) {
256       Dmsg0(200, "Warning, job->RunScripts is empty\n");
257       jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
258    }
259
260    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
261       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
262    }
263
264    /* Run any script BeforeJob on dird */
265    run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
266
267    if (job_canceled(jcr)) {
268       update_job_end(jcr, jcr->JobStatus);
269
270    } else {
271       /*
272        * We re-update the job start record so that the start
273        *  time is set after the run before job.  This avoids
274        *  that any files created by the run before job will
275        *  be saved twice.  They will be backed up in the current
276        *  job, but not in the next one unless they are changed.
277        *  Without this, they will be backed up in this job and
278        *  in the next job run because in that case, their date
279        *   is after the start of this run.
280        */
281       jcr->start_time = time(NULL);
282       jcr->jr.StartTime = jcr->start_time;
283       if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
284          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
285       }
286       generate_job_event(jcr, "JobRun");
287
288       switch (jcr->JobType) {
289       case JT_BACKUP:
290          if (do_backup(jcr)) {
291             do_autoprune(jcr);
292          } else {
293             backup_cleanup(jcr, JS_ErrorTerminated);
294          }
295          break;
296       case JT_VERIFY:
297          if (do_verify(jcr)) {
298             do_autoprune(jcr);
299          } else {
300             verify_cleanup(jcr, JS_ErrorTerminated);
301          }
302          break;
303       case JT_RESTORE:
304          if (do_restore(jcr)) {
305             do_autoprune(jcr);
306          } else {
307             restore_cleanup(jcr, JS_ErrorTerminated);
308          }
309          break;
310       case JT_ADMIN:
311          if (do_admin(jcr)) {
312             do_autoprune(jcr);
313          } else {
314             admin_cleanup(jcr, JS_ErrorTerminated);
315          }
316          break;
317       case JT_MIGRATE:
318       case JT_COPY:
319       case JT_ARCHIVE:
320          if (do_migration(jcr)) {
321             do_autoprune(jcr);
322          } else {
323             migration_cleanup(jcr, JS_ErrorTerminated);
324          }
325          break;
326       default:
327          Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
328          break;
329       }
330
331       /* Send off any queued messages */
332       if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
333          dequeue_messages(jcr);
334       }
335    }
336
337    generate_daemon_event(jcr, "JobEnd");
338    Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
339    sm_check(__FILE__, __LINE__, true);
340    return NULL;
341 }
342
343
344 /*
345  * Cancel a job -- typically called by the UA (Console program), but may also
346  *              be called by the job watchdog.
347  *
348  *  Returns: true  if cancel appears to be successful
349  *           false on failure. Message sent to ua->jcr.
350  */
351 bool cancel_job(UAContext *ua, JCR *jcr)
352 {
353    BSOCK *sd, *fd;
354    char ed1[50];
355
356    set_jcr_job_status(jcr, JS_Canceled);
357
358    switch (jcr->JobStatus) {
359    case JS_Created:
360    case JS_WaitJobRes:
361    case JS_WaitClientRes:
362    case JS_WaitStoreRes:
363    case JS_WaitPriority:
364    case JS_WaitMaxJobs:
365    case JS_WaitStartTime:
366       bsendmsg(ua, _("JobId %s, Job %s marked to be canceled.\n"),
367               edit_uint64(jcr->JobId, ed1), jcr->Job);
368       jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
369       return true;
370
371    default:
372       /* Cancel File daemon */
373       if (jcr->file_bsock) {
374          ua->jcr->client = jcr->client;
375          if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
376             bsendmsg(ua, _("Failed to connect to File daemon.\n"));
377             return 0;
378          }
379          Dmsg0(200, "Connected to file daemon\n");
380          fd = ua->jcr->file_bsock;
381          bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
382          while (bnet_recv(fd) >= 0) {
383             bsendmsg(ua, "%s", fd->msg);
384          }
385          bnet_sig(fd, BNET_TERMINATE);
386          bnet_close(fd);
387          ua->jcr->file_bsock = NULL;
388       }
389
390       /* Cancel Storage daemon */
391       if (jcr->store_bsock) {
392          if (!ua->jcr->wstorage) {
393             if (jcr->rstorage) {
394                copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
395             } else {
396                copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
397             }
398          } else {
399             USTORE store;
400             if (jcr->rstorage) {
401                store.store = jcr->rstore;
402             } else {
403                store.store = jcr->wstore;
404             }
405             set_wstorage(ua->jcr, &store);
406          }
407
408          if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
409             bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
410             return false;
411          }
412          Dmsg0(200, "Connected to storage daemon\n");
413          sd = ua->jcr->store_bsock;
414          bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
415          while (bnet_recv(sd) >= 0) {
416             bsendmsg(ua, "%s", sd->msg);
417          }
418          bnet_sig(sd, BNET_TERMINATE);
419          bnet_close(sd);
420          ua->jcr->store_bsock = NULL;
421       }
422    }
423
424    return true;
425 }
426
427
428 static void job_monitor_destructor(watchdog_t *self)
429 {
430    JCR *control_jcr = (JCR *)self->data;
431
432    free_jcr(control_jcr);
433 }
434
435 static void job_monitor_watchdog(watchdog_t *self)
436 {
437    JCR *control_jcr, *jcr;
438
439    control_jcr = (JCR *)self->data;
440
441    Dmsg1(800, "job_monitor_watchdog %p called\n", self);
442
443    foreach_jcr(jcr) {
444       bool cancel = false;
445
446       if (jcr->JobId == 0 || job_canceled(jcr)) {
447          Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
448          continue;
449       }
450
451       /* check MaxWaitTime */
452       if (job_check_maxwaittime(control_jcr, jcr)) {
453          set_jcr_job_status(jcr, JS_Canceled);
454          Jmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
455          cancel = true;
456       /* check MaxRunTime */
457       } else if (job_check_maxruntime(control_jcr, jcr)) {
458          set_jcr_job_status(jcr, JS_Canceled);
459          Jmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
460          cancel = true;
461       }
462
463       if (cancel) {
464          Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
465          UAContext *ua = new_ua_context(jcr);
466          ua->jcr = control_jcr;
467          cancel_job(ua, jcr);
468          free_ua_context(ua);
469          Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
470       }
471
472    }
473    /* Keep reference counts correct */
474    endeach_jcr(jcr);
475 }
476
477 /*
478  * Check if the maxwaittime has expired and it is possible
479  *  to cancel the job.
480  */
481 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
482 {
483    bool cancel = false;
484    JOB *job = jcr->job;
485
486    if (job_canceled(jcr)) {
487       return false;                /* already canceled */
488    }
489    if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
490        job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
491       return false;
492    } 
493    if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
494          (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
495       cancel = true;
496    } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
497          (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
498       cancel = true;
499    } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
500          (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
501       cancel = true;
502    } else if (job->MaxWaitTime != 0 &&
503          (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
504       cancel = true;
505    }
506
507    return cancel;
508 }
509
510 /*
511  * Check if maxruntime has expired and if the job can be
512  *   canceled.
513  */
514 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
515 {
516    if (jcr->job->MaxRunTime == 0 || job_canceled(jcr)) {
517       return false;
518    }
519    if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
520       Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
521             jcr, jcr->Job, jcr->job->MaxRunTime);
522       return false;
523    }
524
525    return true;
526 }
527
528 /*
529  * Get or create a Pool record with the given name.
530  * Returns: 0 on error
531  *          poolid if OK
532  */
533 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
534 {
535    POOL_DBR pr;
536
537    memset(&pr, 0, sizeof(pr));
538    bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
539    Dmsg1(010, "get_or_create_pool=%s\n", pool_name);
540
541    while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
542       /* Try to create the pool */
543       if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
544          Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
545             db_strerror(jcr->db));
546          return 0;
547       } else {
548          Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
549       }
550    }
551    return pr.PoolId;
552 }
553
554 void apply_pool_overrides(JCR *jcr)
555 {
556    if (jcr->run_pool_override) {
557       pm_strcpy(jcr->pool_source, _("Run pool override"));
558    }
559    /*
560     * Apply any level related Pool selections
561     */
562    switch (jcr->JobLevel) {
563    case L_FULL:
564       if (jcr->full_pool) {
565          jcr->pool = jcr->full_pool;
566          if (jcr->run_full_pool_override) {
567             pm_strcpy(jcr->pool_source, _("Run FullPool override"));
568          } else {
569             pm_strcpy(jcr->pool_source, _("Job FullPool override"));
570          }
571       }
572       break;
573    case L_INCREMENTAL:
574       if (jcr->inc_pool) {
575          jcr->pool = jcr->inc_pool;
576          if (jcr->run_inc_pool_override) {
577             pm_strcpy(jcr->pool_source, _("Run IncPool override"));
578          } else {
579             pm_strcpy(jcr->pool_source, _("Job IncPool override"));
580          }
581       }
582       break;
583    case L_DIFFERENTIAL:
584       if (jcr->diff_pool) {
585          jcr->pool = jcr->diff_pool;
586          if (jcr->run_diff_pool_override) {
587             pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
588          } else {
589             pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
590          }
591       }
592       break;
593    }
594 }
595
596
597 /*
598  * Get or create a Client record for this Job
599  */
600 bool get_or_create_client_record(JCR *jcr)
601 {
602    CLIENT_DBR cr;
603
604    memset(&cr, 0, sizeof(cr));
605    bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
606    cr.AutoPrune = jcr->client->AutoPrune;
607    cr.FileRetention = jcr->client->FileRetention;
608    cr.JobRetention = jcr->client->JobRetention;
609    if (!jcr->client_name) {
610       jcr->client_name = get_pool_memory(PM_NAME);
611    }
612    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
613    if (!db_create_client_record(jcr, jcr->db, &cr)) {
614       Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
615          db_strerror(jcr->db));
616       return false;
617    }
618    jcr->jr.ClientId = cr.ClientId;
619    if (cr.Uname[0]) {
620       if (!jcr->client_uname) {
621          jcr->client_uname = get_pool_memory(PM_NAME);
622       }
623       pm_strcpy(jcr->client_uname, cr.Uname);
624    }
625    Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
626       jcr->jr.ClientId);
627    return true;
628 }
629
630 bool get_or_create_fileset_record(JCR *jcr)
631 {
632    FILESET_DBR fsr;
633    /*
634     * Get or Create FileSet record
635     */
636    memset(&fsr, 0, sizeof(FILESET_DBR));
637    bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
638    if (jcr->fileset->have_MD5) {
639       struct MD5Context md5c;
640       unsigned char digest[MD5HashSize];
641       memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
642       MD5Final(digest, &md5c);
643       /*
644        * Keep the flag (last arg) set to false otherwise old FileSets will
645        * get new MD5 sums and the user will get Full backups on everything
646        */
647       bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
648       bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
649    } else {
650       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
651    }
652    if (!jcr->fileset->ignore_fs_changes ||
653        !db_get_fileset_record(jcr, jcr->db, &fsr)) {
654       if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
655          Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
656             fsr.FileSet, db_strerror(jcr->db));
657          return false;
658       }
659    }
660    jcr->jr.FileSetId = fsr.FileSetId;
661    bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
662    Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
663       jcr->jr.FileSetId);
664    return true;
665 }
666
667 void init_jcr_job_record(JCR *jcr)
668 {
669    jcr->jr.SchedTime = jcr->sched_time;
670    jcr->jr.StartTime = jcr->start_time;
671    jcr->jr.EndTime = 0;               /* perhaps rescheduled, clear it */
672    jcr->jr.JobType = jcr->JobType;
673    jcr->jr.JobLevel = jcr->JobLevel;
674    jcr->jr.JobStatus = jcr->JobStatus;
675    jcr->jr.JobId = jcr->JobId;
676    bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
677    bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
678 }
679
680 /*
681  * Write status and such in DB
682  */
683 void update_job_end_record(JCR *jcr)
684 {
685    jcr->jr.EndTime = time(NULL);
686    jcr->end_time = jcr->jr.EndTime;
687    jcr->jr.JobId = jcr->JobId;
688    jcr->jr.JobStatus = jcr->JobStatus;
689    jcr->jr.JobFiles = jcr->JobFiles;
690    jcr->jr.JobBytes = jcr->JobBytes;
691    jcr->jr.VolSessionId = jcr->VolSessionId;
692    jcr->jr.VolSessionTime = jcr->VolSessionTime;
693    jcr->jr.JobErrors = jcr->Errors;
694    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr)) {
695       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
696          db_strerror(jcr->db));
697    }
698 }
699
700 /*
701  * Takes base_name and appends (unique) current
702  *   date and time to form unique job name.
703  *
704  *  Returns: unique job name in jcr->Job
705  *    date/time in jcr->start_time
706  */
707 void create_unique_job_name(JCR *jcr, const char *base_name)
708 {
709    /* Job start mutex */
710    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
711    static time_t last_start_time = 0;
712    time_t now;
713    struct tm tm;
714    char dt[MAX_TIME_LENGTH];
715    char name[MAX_NAME_LENGTH];
716    char *p;
717
718    /* Guarantee unique start time -- maximum one per second, and
719     * thus unique Job Name
720     */
721    P(mutex);                          /* lock creation of jobs */
722    now = time(NULL);
723    while (now == last_start_time) {
724       bmicrosleep(0, 500000);
725       now = time(NULL);
726    }
727    last_start_time = now;
728    V(mutex);                          /* allow creation of jobs */
729    jcr->start_time = now;
730    /* Form Unique JobName */
731    (void)localtime_r(&now, &tm);
732    /* Use only characters that are permitted in Windows filenames */
733    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
734    bstrncpy(name, base_name, sizeof(name));
735    name[sizeof(name)-22] = 0;          /* truncate if too long */
736    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
737    /* Convert spaces into underscores */
738    for (p=jcr->Job; *p; p++) {
739       if (*p == ' ') {
740          *p = '_';
741       }
742    }
743 }
744
745 /* Called directly from job rescheduling */
746 void dird_free_jcr_pointers(JCR *jcr)
747 {
748    if (jcr->sd_auth_key) {
749       free(jcr->sd_auth_key);
750       jcr->sd_auth_key = NULL;
751    }
752    if (jcr->where) {
753       free(jcr->where);
754       jcr->where = NULL;
755    }
756    if (jcr->file_bsock) {
757       Dmsg0(200, "Close File bsock\n");
758       bnet_close(jcr->file_bsock);
759       jcr->file_bsock = NULL;
760    }
761    if (jcr->store_bsock) {
762       Dmsg0(200, "Close Store bsock\n");
763       bnet_close(jcr->store_bsock);
764       jcr->store_bsock = NULL;
765    }
766    if (jcr->fname) {
767       Dmsg0(200, "Free JCR fname\n");
768       free_pool_memory(jcr->fname);
769       jcr->fname = NULL;
770    }
771    if (jcr->RestoreBootstrap) {
772       free(jcr->RestoreBootstrap);
773       jcr->RestoreBootstrap = NULL;
774    }
775    if (jcr->client_uname) {
776       free_pool_memory(jcr->client_uname);
777       jcr->client_uname = NULL;
778    }
779    if (jcr->attr) {
780       free_pool_memory(jcr->attr);
781       jcr->attr = NULL;
782    }
783    if (jcr->ar) {
784       free(jcr->ar);
785       jcr->ar = NULL;
786    }
787 }
788
789 /*
790  * Free the Job Control Record if no one is still using it.
791  *  Called from main free_jcr() routine in src/lib/jcr.c so
792  *  that we can do our Director specific cleanup of the jcr.
793  */
794 void dird_free_jcr(JCR *jcr)
795 {
796    Dmsg0(200, "Start dird free_jcr\n");
797
798    dird_free_jcr_pointers(jcr);
799    if (jcr->term_wait_inited) {
800       pthread_cond_destroy(&jcr->term_wait);
801       jcr->term_wait_inited = false;
802    }
803    if (jcr->db) {
804       db_close_database(jcr, jcr->db);
805       jcr->db = NULL;
806    }
807    if (jcr->db_batch) {
808       db_close_database(jcr, jcr->db_batch);
809       jcr->db_batch = NULL;
810    }
811    if (jcr->stime) {
812       Dmsg0(200, "Free JCR stime\n");
813       free_pool_memory(jcr->stime);
814       jcr->stime = NULL;
815    }
816    if (jcr->fname) {
817       Dmsg0(200, "Free JCR fname\n");
818       free_pool_memory(jcr->fname);
819       jcr->fname = NULL;
820    }
821    if (jcr->pool_source) {
822       free_pool_memory(jcr->pool_source);
823       jcr->pool_source = NULL;
824    }
825    if (jcr->rpool_source) {
826       free_pool_memory(jcr->rpool_source);
827       jcr->rpool_source = NULL;
828    }
829    if (jcr->wstore_source) {
830       free_pool_memory(jcr->wstore_source);
831       jcr->wstore_source = NULL;
832    }
833    if (jcr->rstore_source) {
834       free_pool_memory(jcr->rstore_source);
835       jcr->rstore_source = NULL;
836    }
837
838    /* Delete lists setup to hold storage pointers */
839    free_rwstorage(jcr);
840
841    jcr->job_end_push.destroy();
842    Dmsg0(200, "End dird free_jcr\n");
843 }
844
845 /* 
846  * The Job storage definition must be either in the Job record
847  *  or in the Pool record.  The Pool record overrides the Job 
848  *  record.
849  */
850 void get_job_storage(USTORE *store, JOB *job, RUN *run) 
851 {
852    if (run && run->pool && run->pool->storage) {
853       store->store = (STORE *)run->pool->storage->first();
854       pm_strcpy(store->store_source, _("Run pool override"));
855       return;
856    }
857    if (run && run->storage) {
858       store->store = run->storage;
859       pm_strcpy(store->store_source, _("Run storage override"));
860       return;
861    }
862    if (job->pool->storage) {
863       store->store = (STORE *)job->pool->storage->first();
864       pm_strcpy(store->store_source, _("Pool resource"));
865    } else {
866       store->store = (STORE *)job->storage->first();
867       pm_strcpy(store->store_source, _("Job resource"));
868    }
869 }
870
871 /*
872  * Set some defaults in the JCR necessary to
873  * run. These items are pulled from the job
874  * definition as defaults, but can be overridden
875  * later either by the Run record in the Schedule resource,
876  * or by the Console program.
877  */
878 void set_jcr_defaults(JCR *jcr, JOB *job)
879 {
880    jcr->job = job;
881    jcr->JobType = job->JobType;
882    switch (jcr->JobType) {
883    case JT_ADMIN:
884    case JT_RESTORE:
885       jcr->JobLevel = L_NONE;
886       break;
887    case JT_MIGRATE:
888       if (!jcr->rpool_source) {
889          jcr->rpool_source = get_pool_memory(PM_MESSAGE);
890          pm_strcpy(jcr->rpool_source, _("unknown source"));
891       }
892       /* Fall-through wanted */
893    default:
894       jcr->JobLevel = job->JobLevel;
895       break;
896    }
897    if (!jcr->fname) {
898       jcr->fname = get_pool_memory(PM_FNAME);
899    }
900    if (!jcr->pool_source) {
901       jcr->pool_source = get_pool_memory(PM_MESSAGE);
902       pm_strcpy(jcr->pool_source, _("unknown source"));
903    }
904
905    jcr->JobPriority = job->Priority;
906    /* Copy storage definitions -- deleted in dir_free_jcr above */
907    if (job->storage) {
908       copy_rwstorage(jcr, job->storage, _("Job resource"));
909    } else {
910       copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
911    }
912    jcr->client = job->client;
913    if (!jcr->client_name) {
914       jcr->client_name = get_pool_memory(PM_NAME);
915    }
916    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
917    pm_strcpy(jcr->pool_source, _("Job resource"));
918    jcr->pool = job->pool;
919    jcr->full_pool = job->full_pool;
920    jcr->inc_pool = job->inc_pool;
921    jcr->diff_pool = job->diff_pool;
922    jcr->catalog = job->client->catalog;
923    jcr->fileset = job->fileset;
924    jcr->messages = job->messages;
925    jcr->spool_data = job->spool_data;
926    jcr->write_part_after_job = job->write_part_after_job;
927    if (jcr->RestoreBootstrap) {
928       free(jcr->RestoreBootstrap);
929       jcr->RestoreBootstrap = NULL;
930    }
931    /* This can be overridden by Console program */
932    if (job->RestoreBootstrap) {
933       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
934    }
935    /* This can be overridden by Console program */
936    jcr->verify_job = job->verify_job;
937    /* If no default level given, set one */
938    if (jcr->JobLevel == 0) {
939       switch (jcr->JobType) {
940       case JT_VERIFY:
941          jcr->JobLevel = L_VERIFY_CATALOG;
942          break;
943       case JT_BACKUP:
944          jcr->JobLevel = L_INCREMENTAL;
945          break;
946       case JT_RESTORE:
947       case JT_ADMIN:
948          jcr->JobLevel = L_NONE;
949          break;
950       default:
951          jcr->JobLevel = L_FULL;
952          break;
953       }
954    }
955 }
956
957 /* 
958  * Copy the storage definitions from an alist to the JCR
959  */
960 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
961 {
962    switch(jcr->JobType) {
963    case JT_RESTORE:
964    case JT_VERIFY:
965    case JT_MIGRATE:
966       copy_rstorage(jcr, storage, where);
967       break;
968    default:
969       copy_wstorage(jcr, storage, where);
970       break;
971    }
972 }
973
974
975 /* Set storage override */
976 void set_rwstorage(JCR *jcr, USTORE *store)
977 {
978    if (!store) {
979       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
980       return;
981    }
982    switch(jcr->JobType) {
983    case JT_RESTORE:
984    case JT_VERIFY:
985    case JT_MIGRATE:
986       set_rstorage(jcr, store);
987       break;
988    default:
989       set_wstorage(jcr, store);
990       break;
991    }
992 }
993
994 void free_rwstorage(JCR *jcr)
995 {
996    free_rstorage(jcr);
997    free_wstorage(jcr);
998 }
999
1000 /* 
1001  * Copy the storage definitions from an alist to the JCR
1002  */
1003 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1004 {
1005    if (storage) {
1006       STORE *st;
1007       if (jcr->rstorage) {
1008          delete jcr->rstorage;
1009       }
1010       jcr->rstorage = New(alist(10, not_owned_by_alist));
1011       foreach_alist(st, storage) {
1012          jcr->rstorage->append(st);
1013       }
1014       if (!jcr->rstore_source) {
1015          jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1016       }
1017       pm_strcpy(jcr->rstore_source, where);
1018       if (jcr->rstorage) {
1019          jcr->rstore = (STORE *)jcr->rstorage->first();
1020       }
1021    }
1022 }
1023
1024
1025 /* Set storage override */
1026 void set_rstorage(JCR *jcr, USTORE *store)
1027 {
1028    STORE *storage;
1029
1030    if (!store->store) {
1031       return;
1032    }
1033    if (!jcr->rstorage) {
1034       jcr->rstorage = New(alist(10, not_owned_by_alist));
1035    }
1036    jcr->rstore = store->store;
1037    if (!jcr->rstore_source) {
1038       jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1039    }
1040    pm_strcpy(jcr->rstore_source, store->store_source);
1041    foreach_alist(storage, jcr->rstorage) {
1042       if (store->store == storage) {
1043          return;
1044       }
1045    }
1046    /* Store not in list, so add it */
1047    jcr->rstorage->prepend(store->store);
1048 }
1049
1050 void free_rstorage(JCR *jcr)
1051 {
1052    if (jcr->rstorage) {
1053       delete jcr->rstorage;
1054       jcr->rstorage = NULL;
1055    }
1056    jcr->rstore = NULL;
1057 }
1058
1059 /* 
1060  * Copy the storage definitions from an alist to the JCR
1061  */
1062 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1063 {
1064    if (storage) {
1065       STORE *st;
1066       if (jcr->wstorage) {
1067          delete jcr->wstorage;
1068       }
1069       jcr->wstorage = New(alist(10, not_owned_by_alist));
1070       foreach_alist(st, storage) {
1071          Dmsg1(50, "storage=%s\n", st->name());
1072          jcr->wstorage->append(st);
1073       }
1074       if (!jcr->wstore_source) {
1075          jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1076       }
1077       pm_strcpy(jcr->wstore_source, where);
1078       if (jcr->wstorage) {
1079          jcr->wstore = (STORE *)jcr->wstorage->first();
1080          Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1081       }
1082    }
1083 }
1084
1085
1086 /* Set storage override */
1087 void set_wstorage(JCR *jcr, USTORE *store)
1088 {
1089    STORE *storage;
1090
1091    if (!store->store) {
1092       return;
1093    }
1094    if (!jcr->wstorage) {
1095       jcr->wstorage = New(alist(10, not_owned_by_alist));
1096    }
1097    jcr->wstore = store->store;
1098    if (!jcr->wstore_source) {
1099       jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1100    }
1101    pm_strcpy(jcr->wstore_source, store->store_source);
1102    Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1103    foreach_alist(storage, jcr->wstorage) {
1104       if (store->store == storage) {
1105          return;
1106       }
1107    }
1108    /* Store not in list, so add it */
1109    jcr->wstorage->prepend(store->store);
1110 }
1111
1112 void free_wstorage(JCR *jcr)
1113 {
1114    if (jcr->wstorage) {
1115       delete jcr->wstorage;
1116       jcr->wstorage = NULL;
1117    }
1118    jcr->wstore = NULL;
1119 }
1120
1121 void create_clones(JCR *jcr)
1122 {
1123    /*
1124     * Fire off any clone jobs (run directives)
1125     */
1126    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1127    if (!jcr->cloned && jcr->job->run_cmds) {
1128       char *runcmd;
1129       JOB *job = jcr->job;
1130       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1131       UAContext *ua = new_ua_context(jcr);
1132       ua->batch = true;
1133       foreach_alist(runcmd, job->run_cmds) {
1134          cmd = edit_job_codes(jcr, cmd, runcmd, "");              
1135          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1136          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1137          parse_ua_args(ua);                 /* parse command */
1138          int stat = run_cmd(ua, ua->cmd);
1139          if (stat == 0) {
1140             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1141          } else {
1142             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1143          }
1144       }
1145       free_ua_context(ua);
1146       free_pool_memory(cmd);
1147    }
1148 }
1149
1150 bool create_restore_bootstrap_file(JCR *jcr)
1151 {
1152    RESTORE_CTX rx;
1153    UAContext *ua;
1154    memset(&rx, 0, sizeof(rx));
1155    rx.bsr = new_bsr();
1156    rx.JobIds = "";                       
1157    rx.bsr->JobId = jcr->previous_jr.JobId;
1158    ua = new_ua_context(jcr);
1159    complete_bsr(ua, rx.bsr);
1160    rx.bsr->fi = new_findex();
1161    rx.bsr->fi->findex = 1;
1162    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1163    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1164    if (jcr->ExpectedFiles == 0) {
1165       free_ua_context(ua);
1166       free_bsr(rx.bsr);
1167       return false;
1168    }
1169    free_ua_context(ua);
1170    free_bsr(rx.bsr);
1171    jcr->needs_sd = true;
1172    return true;
1173 }