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