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