]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/jcr.c
3ec16c2bb07cf8ae23b88c724ec22da375b87429
[bacula/bacula] / bacula / src / lib / jcr.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  * Manipulation routines for Job Control Records and
21  *  handling of last_jobs_list.
22  *
23  *  Kern E. Sibbald, December 2000
24  *
25  *  These routines are thread safe.
26  *
27  *  The job list routines were re-written in May 2005 to
28  *  eliminate the global lock while traversing the list, and
29  *  to use the dlist subroutines.  The locking is now done
30  *  on the list each time the list is modified or traversed.
31  *  That is it is "micro-locked" rather than globally locked.
32  *  The result is that there is one lock/unlock for each entry
33  *  in the list while traversing it rather than a single lock
34  *  at the beginning of a traversal and one at the end.  This
35  *  incurs slightly more overhead, but effectively eliminates
36  *  the possibilty of race conditions.  In addition, with the
37  *  exception of the global locking of the list during the
38  *  re-reading of the config file, no recursion is needed.
39  *
40  */
41
42 #include "bacula.h"
43 #include "jcr.h"
44
45 const int dbglvl = 3400;
46
47 /* External variables we reference */
48
49 /* External referenced functions */
50 void free_bregexps(alist *bregexps);
51
52 /* Forward referenced functions */
53 extern "C" void timeout_handler(int sig);
54 static void jcr_timeout_check(watchdog_t *self);
55 #ifdef TRACE_JCR_CHAIN
56 static void b_lock_jcr_chain(const char *filen, int line);
57 static void b_unlock_jcr_chain(const char *filen, int line);
58 #define lock_jcr_chain() b_lock_jcr_chain(__FILE__, __LINE__);
59 #define unlock_jcr_chain() b_unlock_jcr_chain(__FILE__, __LINE__);
60 #else
61 static void lock_jcr_chain();
62 static void unlock_jcr_chain();
63 #endif
64
65
66 int num_jobs_run;
67 dlist *last_jobs = NULL;
68 const int max_last_jobs = 10;
69
70 static dlist *jcrs = NULL;            /* JCR chain */
71 static pthread_mutex_t jcr_lock = PTHREAD_MUTEX_INITIALIZER;
72
73 static pthread_mutex_t job_start_mutex = PTHREAD_MUTEX_INITIALIZER;
74
75 static pthread_mutex_t last_jobs_mutex = PTHREAD_MUTEX_INITIALIZER;
76
77 static pthread_key_t jcr_key;         /* Pointer to jcr for each thread */
78
79 pthread_once_t key_once = PTHREAD_ONCE_INIT;
80
81 static char Job_status[]     = "Status Job=%s JobStatus=%d\n";
82
83
84 void lock_jobs()
85 {
86    P(job_start_mutex);
87 }
88
89 void unlock_jobs()
90 {
91    V(job_start_mutex);
92 }
93
94 void init_last_jobs_list()
95 {
96    JCR *jcr = NULL;
97    struct s_last_job *job_entry = NULL;
98    if (!last_jobs) {
99       last_jobs = New(dlist(job_entry, &job_entry->link));
100    }
101    if (!jcrs) {
102       jcrs = New(dlist(jcr, &jcr->link));
103    }
104 }
105
106 void term_last_jobs_list()
107 {
108    if (last_jobs) {
109       lock_last_jobs_list();
110       while (!last_jobs->empty()) {
111          void *je = last_jobs->first();
112          last_jobs->remove(je);
113          free(je);
114       }
115       delete last_jobs;
116       last_jobs = NULL;
117       unlock_last_jobs_list();
118    }
119    if (jcrs) {
120       delete jcrs;
121       jcrs = NULL;
122    }
123 }
124
125 bool read_last_jobs_list(int fd, uint64_t addr)
126 {
127    struct s_last_job *je, job;
128    uint32_t num;
129    bool ok = true;
130
131    Dmsg1(100, "read_last_jobs seek to %d\n", (int)addr);
132    if (addr == 0 || lseek(fd, (boffset_t)addr, SEEK_SET) < 0) {
133       return false;
134    }
135    if (read(fd, &num, sizeof(num)) != sizeof(num)) {
136       return false;
137    }
138    Dmsg1(100, "Read num_items=%d\n", num);
139    if (num > 4 * max_last_jobs) {  /* sanity check */
140       return false;
141    }
142    lock_last_jobs_list();
143    for ( ; num; num--) {
144       if (read(fd, &job, sizeof(job)) != sizeof(job)) {
145          berrno be;
146          Pmsg1(000, "Read job entry. ERR=%s\n", be.bstrerror());
147          ok = false;
148          break;
149       }
150       if (job.JobId > 0) {
151          je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
152          memcpy((char *)je, (char *)&job, sizeof(job));
153          if (!last_jobs) {
154             init_last_jobs_list();
155          }
156          last_jobs->append(je);
157          if (last_jobs->size() > max_last_jobs) {
158             je = (struct s_last_job *)last_jobs->first();
159             last_jobs->remove(je);
160             free(je);
161          }
162       }
163    }
164    unlock_last_jobs_list();
165    return ok;
166 }
167
168 uint64_t write_last_jobs_list(int fd, uint64_t addr)
169 {
170    struct s_last_job *je;
171    uint32_t num;
172    ssize_t stat;
173
174    Dmsg1(100, "write_last_jobs seek to %d\n", (int)addr);
175    if (lseek(fd, (boffset_t)addr, SEEK_SET) < 0) {
176       return 0;
177    }
178    if (last_jobs) {
179       lock_last_jobs_list();
180       /* First record is number of entires */
181       num = last_jobs->size();
182       if (write(fd, &num, sizeof(num)) != sizeof(num)) {
183          berrno be;
184          Pmsg1(000, "Error writing num_items: ERR=%s\n", be.bstrerror());
185          goto bail_out;
186       }
187       foreach_dlist(je, last_jobs) {
188          if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) {
189             berrno be;
190             Pmsg1(000, "Error writing job: ERR=%s\n", be.bstrerror());
191             goto bail_out;
192          }
193       }
194       unlock_last_jobs_list();
195    }
196    /* Return current address */
197    stat = lseek(fd, 0, SEEK_CUR);
198    if (stat < 0) {
199       stat = 0;
200    }
201    return stat;
202
203 bail_out:
204    unlock_last_jobs_list();
205    return 0;
206 }
207
208 void lock_last_jobs_list()
209 {
210    P(last_jobs_mutex);
211 }
212
213 void unlock_last_jobs_list()
214 {
215    V(last_jobs_mutex);
216 }
217
218 /* Get an ASCII representation of the Operation being performed as an english Noun */
219 const char *JCR::get_OperationName()
220 {
221    switch(m_JobType) {
222    case JT_BACKUP:
223       return _("Backup");
224    case JT_VERIFY:
225       return _("Verifying");
226    case JT_RESTORE:
227       return _("Restoring");
228    case JT_ARCHIVE:
229       return _("Archiving");
230    case JT_COPY:
231       return _("Copying");
232    case JT_MIGRATE:
233       return _("Migration");
234    case JT_SCAN:
235       return _("Scanning");
236    default:
237       return _("Unknown operation");
238    }
239 }
240
241 /* Get an ASCII representation of the Action being performed either an english Verb or Adjective */
242 const char *JCR::get_ActionName(bool past)
243 {
244    switch(m_JobType) {
245    case JT_BACKUP:
246       return _("backup");
247    case JT_VERIFY:
248       return (past == true) ? _("verified") : _("verify");
249    case JT_RESTORE:
250       return (past == true) ? _("restored") : _("restore");
251    case JT_ARCHIVE:
252       return (past == true) ? _("archived") : _("archive");
253    case JT_COPY:
254       return (past == true) ? _("copied") : _("copy");
255    case JT_MIGRATE:
256       return (past == true) ? _("migrated") : _("migrate");
257    case JT_SCAN:
258       return (past == true) ? _("scanned") : _("scan");
259    default:
260       return _("unknown action");
261    }
262 }
263
264 bool JCR::JobReads()
265 {
266    switch (m_JobType) {
267    case JT_VERIFY:
268    case JT_RESTORE:
269    case JT_COPY:
270    case JT_MIGRATE:
271       return true;
272    case JT_BACKUP:
273       if (m_JobLevel == L_VIRTUAL_FULL) {
274          return true;
275       }
276       break;
277    default:
278       break;
279    }
280    return false;
281 }
282
283 /*
284  * Push a subroutine address into the job end callback stack
285  */
286 void job_end_push(JCR *jcr, void job_end_cb(JCR *jcr,void *), void *ctx)
287 {
288    jcr->job_end_push.append((void *)job_end_cb);
289    jcr->job_end_push.append(ctx);
290 }
291
292 /* Pop each job_end subroutine and call it */
293 static void job_end_pop(JCR *jcr)
294 {
295    void (*job_end_cb)(JCR *jcr, void *ctx);
296    void *ctx;
297    for (int i=jcr->job_end_push.size()-1; i > 0; ) {
298       ctx = jcr->job_end_push.get(i--);
299       job_end_cb = (void (*)(JCR *,void *))jcr->job_end_push.get(i--);
300       job_end_cb(jcr, ctx);
301    }
302 }
303
304 /*
305  * Create thread key for thread specific data
306  */
307 void create_jcr_key()
308 {
309    int status = pthread_key_create(&jcr_key, NULL);
310    if (status != 0) {
311       berrno be;
312       Jmsg1(NULL, M_ABORT, 0, _("pthread key create failed: ERR=%s\n"),
313             be.bstrerror(status));
314    }
315 }
316
317 /*
318  * Create a Job Control Record and link it into JCR chain
319  * Returns newly allocated JCR
320  * Note, since each daemon has a different JCR, he passes
321  *  us the size.
322  */
323 JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
324 {
325    JCR *jcr;
326    MQUEUE_ITEM *item = NULL;
327    int status;
328
329    Dmsg0(dbglvl, "Enter new_jcr\n");
330    status = pthread_once(&key_once, create_jcr_key);
331    if (status != 0) {
332       berrno be;
333       Jmsg1(NULL, M_ABORT, 0, _("pthread_once failed. ERR=%s\n"), be.bstrerror(status));
334    }
335    jcr = (JCR *)malloc(size);
336    memset(jcr, 0, size);
337    /* Note for the director, this value is changed in jobq.c */
338    jcr->my_thread_id = pthread_self();
339    jcr->msg_queue = New(dlist(item, &item->link));
340    if ((status = pthread_mutex_init(&jcr->msg_queue_mutex, NULL)) != 0) {
341       berrno be;
342       Jmsg(NULL, M_ABORT, 0, _("Could not init msg_queue mutex. ERR=%s\n"),
343          be.bstrerror(status));
344    }
345    jcr->job_end_push.init(1, false);
346    jcr->sched_time = time(NULL);
347    jcr->initial_sched_time = jcr->sched_time;
348    jcr->daemon_free_jcr = daemon_free_jcr;    /* plug daemon free routine */
349    jcr->init_mutex();
350    jcr->inc_use_count();
351    jcr->VolumeName = get_pool_memory(PM_FNAME);
352    jcr->VolumeName[0] = 0;
353    jcr->errmsg = get_pool_memory(PM_MESSAGE);
354    jcr->errmsg[0] = 0;
355    jcr->comment = get_pool_memory(PM_FNAME);
356    jcr->comment[0] = 0;
357    /* Setup some dummy values */
358    bstrncpy(jcr->Job, "*System*", sizeof(jcr->Job));
359    jcr->JobId = 0;
360    jcr->setJobType(JT_SYSTEM);           /* internal job until defined */
361    jcr->setJobLevel(L_NONE);
362    jcr->setJobStatus(JS_Created);        /* ready to run */
363 #ifndef HAVE_WIN32
364    struct sigaction sigtimer;
365    sigtimer.sa_flags = 0;
366    sigtimer.sa_handler = timeout_handler;
367    sigfillset(&sigtimer.sa_mask);
368    sigaction(TIMEOUT_SIGNAL, &sigtimer, NULL);
369 #endif
370
371    /*
372     * Locking jobs is a global lock that is needed
373     * so that the Director can stop new jobs from being
374     * added to the jcr chain while it processes a new
375     * conf file and does the job_end_push().
376     */
377    lock_jobs();
378    lock_jcr_chain();
379    if (!jcrs) {
380       jcrs = New(dlist(jcr, &jcr->link));
381    }
382    jcrs->append(jcr);
383    unlock_jcr_chain();
384    unlock_jobs();
385
386    return jcr;
387 }
388
389
390 /*
391  * Remove a JCR from the chain
392  * NOTE! The chain must be locked prior to calling
393  *       this routine.
394  */
395 static void remove_jcr(JCR *jcr)
396 {
397    Dmsg0(dbglvl, "Enter remove_jcr\n");
398    if (!jcr) {
399       Emsg0(M_ABORT, 0, _("NULL jcr.\n"));
400    }
401    jcrs->remove(jcr);
402    Dmsg0(dbglvl, "Leave remove_jcr\n");
403 }
404
405 /*
406  * Free stuff common to all JCRs.  N.B. Be careful to include only
407  *  generic stuff in the common part of the jcr.
408  */
409 static void free_common_jcr(JCR *jcr)
410 {
411    /* Uses jcr lock/unlock */
412    remove_jcr_from_tsd(jcr);
413    jcr->set_killable(false);
414
415    jcr->destroy_mutex();
416
417    if (jcr->msg_queue) {
418       delete jcr->msg_queue;
419       jcr->msg_queue = NULL;
420       pthread_mutex_destroy(&jcr->msg_queue_mutex);
421    }
422
423    /* do this after closing messages */
424    if (jcr->client_name) {
425       free_pool_memory(jcr->client_name);
426       jcr->client_name = NULL;
427    }
428
429    if (jcr->attr) {
430       free_pool_memory(jcr->attr);
431       jcr->attr = NULL;
432    }
433
434    if (jcr->sd_auth_key) {
435       free(jcr->sd_auth_key);
436       jcr->sd_auth_key = NULL;
437    }
438    if (jcr->VolumeName) {
439       free_pool_memory(jcr->VolumeName);
440       jcr->VolumeName = NULL;
441    }
442
443    free_bsock(jcr->dir_bsock);
444
445    if (jcr->errmsg) {
446       free_pool_memory(jcr->errmsg);
447       jcr->errmsg = NULL;
448    }
449    if (jcr->where) {
450       free(jcr->where);
451       jcr->where = NULL;
452    }
453    if (jcr->RegexWhere) {
454       free(jcr->RegexWhere);
455       jcr->RegexWhere = NULL;
456    }
457    if (jcr->where_bregexp) {
458       free_bregexps(jcr->where_bregexp);
459       delete jcr->where_bregexp;
460       jcr->where_bregexp = NULL;
461    }
462    if (jcr->cached_path) {
463       free_pool_memory(jcr->cached_path);
464       jcr->cached_path = NULL;
465       jcr->cached_pnl = 0;
466    }
467    if (jcr->id_list) {
468       free_guid_list(jcr->id_list);
469       jcr->id_list = NULL;
470    }
471    if (jcr->comment) {
472       free_pool_memory(jcr->comment);
473       jcr->comment = NULL;
474    }
475    free(jcr);
476 }
477
478 /*
479  * Global routine to free a jcr
480  */
481 #ifdef DEBUG
482 void b_free_jcr(const char *file, int line, JCR *jcr)
483 {
484    struct s_last_job *je;
485
486    Dmsg3(dbglvl, "Enter free_jcr jid=%u from %s:%d\n", jcr->JobId, file, line);
487
488 #else
489
490 void free_jcr(JCR *jcr)
491 {
492    struct s_last_job *je;
493
494    Dmsg3(dbglvl, "Enter free_jcr jid=%u use_count=%d Job=%s\n",
495          jcr->JobId, jcr->use_count(), jcr->Job);
496
497 #endif
498
499    lock_jcr_chain();
500    jcr->dec_use_count();              /* decrement use count */
501    ASSERT2(jcr->use_count() >= 0, "JCR use_count < 0");
502    //    Jmsg2(jcr, M_ERROR, 0, _("JCR use_count=%d JobId=%d\n"),
503    //      jcr->use_count(), jcr->JobId);
504    //}
505    if (jcr->JobId > 0) {
506       Dmsg3(dbglvl, "Dec free_jcr jid=%u use_count=%d Job=%s\n",
507          jcr->JobId, jcr->use_count(), jcr->Job);
508    }
509    if (jcr->use_count() > 0) {          /* if in use */
510       unlock_jcr_chain();
511       return;
512    }
513    if (jcr->JobId > 0) {
514       Dmsg3(dbglvl, "remove jcr jid=%u use_count=%d Job=%s\n",
515             jcr->JobId, jcr->use_count(), jcr->Job);
516    }
517    jcr->exiting = true;
518    remove_jcr(jcr);                   /* remove Jcr from chain */
519    unlock_jcr_chain();
520
521    dequeue_messages(jcr);
522    close_msg(jcr);                    /* close messages for this job */
523    job_end_pop(jcr);                  /* pop and call hooked routines */
524
525    Dmsg1(dbglvl, "End job=%d\n", jcr->JobId);
526
527    /* Keep some statistics */
528    switch (jcr->getJobType()) {
529    case JT_BACKUP:
530    case JT_VERIFY:
531    case JT_RESTORE:
532    case JT_MIGRATE:
533    case JT_COPY:
534    case JT_ADMIN:
535       /* Keep list of last jobs, but not Console where JobId==0 */
536       if (jcr->JobId > 0) {
537          lock_last_jobs_list();
538          num_jobs_run++;
539          je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
540          memset(je, 0, sizeof(struct s_last_job));  /* zero in case unset fields */
541          je->Errors = jcr->JobErrors;
542          je->JobType = jcr->getJobType();
543          je->JobId = jcr->JobId;
544          je->VolSessionId = jcr->VolSessionId;
545          je->VolSessionTime = jcr->VolSessionTime;
546          bstrncpy(je->Job, jcr->Job, sizeof(je->Job));
547          je->JobFiles = jcr->JobFiles;
548          je->JobBytes = jcr->JobBytes;
549          je->JobStatus = jcr->JobStatus;
550          je->JobLevel = jcr->getJobLevel();
551          je->start_time = jcr->start_time;
552          je->end_time = time(NULL);
553
554          if (!last_jobs) {
555             init_last_jobs_list();
556          }
557          last_jobs->append(je);
558          if (last_jobs->size() > max_last_jobs) {
559             je = (struct s_last_job *)last_jobs->first();
560             last_jobs->remove(je);
561             free(je);
562          }
563          unlock_last_jobs_list();
564       }
565       break;
566    default:
567       break;
568    }
569
570    if (jcr->daemon_free_jcr) {
571       jcr->daemon_free_jcr(jcr);      /* call daemon free routine */
572    }
573
574    free_common_jcr(jcr);
575    close_msg(NULL);                   /* flush any daemon messages */
576    Dmsg0(dbglvl, "Exit free_jcr\n");
577 }
578
579 /*
580  * Remove jcr from thread specific data, but
581  *   but make sure it is us who are attached.
582  */
583 void remove_jcr_from_tsd(JCR *jcr)
584 {
585    JCR *tjcr = get_jcr_from_tsd();
586    if (tjcr == jcr) {
587       set_jcr_in_tsd(INVALID_JCR);
588    }
589 }
590
591 void JCR::set_killable(bool killable)
592 {
593    lock();
594    my_thread_killable = killable;
595    unlock();
596 }
597
598 /*
599  * Put this jcr in the thread specifc data
600  *  if update_thread_info is true and the jcr is valide,
601  *  we update the my_thread_id in the JCR
602  */
603 void set_jcr_in_tsd(JCR *jcr)
604 {
605    int status = pthread_setspecific(jcr_key, (void *)jcr);
606    if (status != 0) {
607       berrno be;
608       Jmsg1(jcr, M_ABORT, 0, _("pthread_setspecific failed: ERR=%s\n"),
609             be.bstrerror(status));
610    }
611 }
612
613 void JCR::my_thread_send_signal(int sig)
614 {
615    lock_jcr_chain();   /* use global lock */
616    this->lock();
617    if (this->exiting) {
618       goto get_out;
619    }
620    if (this->is_killable() &&
621        !pthread_equal(this->my_thread_id, pthread_self()))
622    {
623       Dmsg1(800, "Send kill to jid=%d\n", this->JobId);
624       pthread_kill(this->my_thread_id, sig);
625       this->exiting = true;
626
627    } else if (!this->is_killable()) {
628       Dmsg1(10, "Warning, can't send kill to jid=%d\n", this->JobId);
629    }
630 get_out:
631    this->unlock();
632    unlock_jcr_chain();
633 }
634
635 /*
636  * Give me the jcr that is attached to this thread
637  */
638 JCR *get_jcr_from_tsd()
639 {
640    JCR *jcr = (JCR *)pthread_getspecific(jcr_key);
641 // printf("get_jcr_from_tsd: jcr=%p\n", jcr);
642    /* set any INVALID_JCR to NULL which the rest of Bacula understands */
643    if (jcr == INVALID_JCR) {
644       jcr = NULL;
645    }
646    return jcr;
647 }
648
649
650 /*
651  * Find which JobId corresponds to the current thread
652  */
653 uint32_t get_jobid_from_tsd()
654 {
655    JCR *jcr;
656    uint32_t JobId = 0;
657    jcr = get_jcr_from_tsd();
658 // printf("get_jobid_from_tsr: jcr=%p\n", jcr);
659    if (jcr) {
660       JobId = (uint32_t)jcr->JobId;
661    }
662    return JobId;
663 }
664
665 /*
666  * Given a JobId, find the JCR
667  *   Returns: jcr on success
668  *            NULL on failure
669  */
670 JCR *get_jcr_by_id(uint32_t JobId)
671 {
672    JCR *jcr;
673
674    foreach_jcr(jcr) {
675       if (jcr->JobId == JobId) {
676          jcr->inc_use_count();
677          Dmsg3(dbglvl, "Inc get_jcr jid=%u use_count=%d Job=%s\n",
678             jcr->JobId, jcr->use_count(), jcr->Job);
679          break;
680       }
681    }
682    endeach_jcr(jcr);
683    return jcr;
684 }
685
686 /*
687  * Given a thread id, find the JobId
688  *   Returns: JobId on success
689  *            0 on failure
690  */
691 uint32_t get_jobid_from_tid(pthread_t tid)
692 {
693    JCR *jcr = NULL;
694    bool found = false;
695
696    foreach_jcr(jcr) {
697       if (pthread_equal(jcr->my_thread_id, tid)) {
698          found = true;
699          break;
700       }
701    }
702    endeach_jcr(jcr);
703    if (found) {
704       return jcr->JobId;
705    }
706    return 0;
707 }
708
709
710 /*
711  * Given a SessionId and SessionTime, find the JCR
712  *   Returns: jcr on success
713  *            NULL on failure
714  */
715 JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
716 {
717    JCR *jcr;
718
719    foreach_jcr(jcr) {
720       if (jcr->VolSessionId == SessionId &&
721           jcr->VolSessionTime == SessionTime) {
722          jcr->inc_use_count();
723          Dmsg3(dbglvl, "Inc get_jcr jid=%u use_count=%d Job=%s\n",
724             jcr->JobId, jcr->use_count(), jcr->Job);
725          break;
726       }
727    }
728    endeach_jcr(jcr);
729    return jcr;
730 }
731
732
733 /*
734  * Given a Job, find the JCR
735  *  compares on the number of characters in Job
736  *  thus allowing partial matches.
737  *   Returns: jcr on success
738  *            NULL on failure
739  */
740 JCR *get_jcr_by_partial_name(char *Job)
741 {
742    JCR *jcr;
743    int len;
744
745    if (!Job) {
746       return NULL;
747    }
748    len = strlen(Job);
749    foreach_jcr(jcr) {
750       if (strncmp(Job, jcr->Job, len) == 0) {
751          jcr->inc_use_count();
752          Dmsg3(dbglvl, "Inc get_jcr jid=%u use_count=%d Job=%s\n",
753             jcr->JobId, jcr->use_count(), jcr->Job);
754          break;
755       }
756    }
757    endeach_jcr(jcr);
758    return jcr;
759 }
760
761
762 /*
763  * Given a Job, find the JCR
764  *  requires an exact match of names.
765  *   Returns: jcr on success
766  *            NULL on failure
767  */
768 JCR *get_jcr_by_full_name(char *Job)
769 {
770    JCR *jcr;
771
772    if (!Job) {
773       return NULL;
774    }
775    foreach_jcr(jcr) {
776       if (strcmp(jcr->Job, Job) == 0) {
777          jcr->inc_use_count();
778          Dmsg3(dbglvl, "Inc get_jcr jid=%u use_count=%d Job=%s\n",
779             jcr->JobId, jcr->use_count(), jcr->Job);
780          break;
781       }
782    }
783    endeach_jcr(jcr);
784    return jcr;
785 }
786
787 static void update_wait_time(JCR *jcr, int newJobStatus)
788 {
789    bool enter_in_waittime;
790    int oldJobStatus = jcr->JobStatus;
791
792    switch (newJobStatus) {
793    case JS_WaitFD:
794    case JS_WaitSD:
795    case JS_WaitMedia:
796    case JS_WaitMount:
797    case JS_WaitStoreRes:
798    case JS_WaitJobRes:
799    case JS_WaitClientRes:
800    case JS_WaitMaxJobs:
801    case JS_WaitPriority:
802       enter_in_waittime = true;
803       break;
804    default:
805       enter_in_waittime = false; /* not a Wait situation */
806       break;
807    }
808
809    /*
810     * If we were previously waiting and are not any more
811     *   we want to update the wait_time variable, which is
812     *   the start of waiting.
813     */
814    switch (oldJobStatus) {
815    case JS_WaitFD:
816    case JS_WaitSD:
817    case JS_WaitMedia:
818    case JS_WaitMount:
819    case JS_WaitStoreRes:
820    case JS_WaitJobRes:
821    case JS_WaitClientRes:
822    case JS_WaitMaxJobs:
823    case JS_WaitPriority:
824       if (!enter_in_waittime) { /* we get out the wait time */
825          jcr->wait_time_sum += (time(NULL) - jcr->wait_time);
826          jcr->wait_time = 0;
827       }
828       break;
829
830    /* if wait state is new, we keep current time for watchdog MaxWaitTime */
831    default:
832       if (enter_in_waittime) {
833          jcr->wait_time = time(NULL);
834       }
835       break;
836    }
837 }
838
839 /*
840  * Priority runs from 0 (lowest) to 10 (highest)
841  */
842 static int get_status_priority(int JobStatus)
843 {
844    int priority = 0;
845    switch (JobStatus) {
846    case JS_Incomplete:
847       priority = 10;
848       break;
849    case JS_ErrorTerminated:
850    case JS_FatalError:
851    case JS_Canceled:
852       priority = 9;
853       break;
854    case JS_Error:
855       priority = 8;
856       break;
857    case JS_Differences:
858       priority = 7;
859       break;
860    }
861    return priority;
862 }
863
864 /*
865  * Send Job status to Director
866  */
867 bool JCR::sendJobStatus()
868 {
869    if (dir_bsock) {
870       return dir_bsock->fsend(Job_status, Job, JobStatus);
871    }
872    return true;
873 }
874
875 /*
876  * Set and send Job status to Director
877  */
878 bool JCR::sendJobStatus(int aJobStatus)
879 {
880    if (!is_JobStatus(aJobStatus)) {
881       setJobStatus(aJobStatus);
882       if (dir_bsock) {
883          return dir_bsock->fsend(Job_status, Job, JobStatus);
884       }
885    }
886    return true;
887 }
888
889 void JCR::setJobStarted()
890 {
891    job_started = true;
892    job_started_time = time(NULL);
893 }
894
895 void JCR::setJobStatus(int newJobStatus)
896 {
897    int priority, old_priority;
898    int oldJobStatus = JobStatus;
899    priority = get_status_priority(newJobStatus);
900    old_priority = get_status_priority(oldJobStatus);
901
902    Dmsg2(800, "set_jcr_job_status(%s, %c)\n", Job, newJobStatus);
903
904    /* Update wait_time depending on newJobStatus and oldJobStatus */
905    update_wait_time(this, newJobStatus);
906
907    /*
908     * For a set of errors, ... keep the current status
909     *   so it isn't lost. For all others, set it.
910     */
911    Dmsg2(800, "OnEntry JobStatus=%c newJobstatus=%c\n", oldJobStatus, newJobStatus);
912    /*
913     * If status priority is > than proposed new status, change it.
914     * If status priority == new priority and both are zero, take
915     *   the new status.
916     * If it is not zero, then we keep the first non-zero "error" that
917     *   occurred.
918     */
919    if (priority > old_priority || (
920        priority == 0 && old_priority == 0)) {
921       Dmsg4(800, "Set new stat. old: %c,%d new: %c,%d\n",
922          JobStatus, old_priority, newJobStatus, priority);
923       JobStatus = newJobStatus;     /* replace with new status */
924    }
925
926    if (oldJobStatus != JobStatus) {
927       Dmsg2(800, "leave setJobStatus old=%c new=%c\n", oldJobStatus, newJobStatus);
928 //    generate_plugin_event(this, bEventStatusChange, NULL);
929    }
930 }
931
932 #ifdef TRACE_JCR_CHAIN
933 static int lock_count = 0;
934 #endif
935
936 /*
937  * Lock the chain
938  */
939 #ifdef TRACE_JCR_CHAIN
940 static void b_lock_jcr_chain(const char *fname, int line)
941 #else
942 static void lock_jcr_chain()
943 #endif
944 {
945 #ifdef TRACE_JCR_CHAIN
946    Dmsg3(dbglvl, "Lock jcr chain %d from %s:%d\n", ++lock_count, fname, line);
947 #endif
948    P(jcr_lock);
949 }
950
951 /*
952  * Unlock the chain
953  */
954 #ifdef TRACE_JCR_CHAIN
955 static void b_unlock_jcr_chain(const char *fname, int line)
956 #else
957 static void unlock_jcr_chain()
958 #endif
959 {
960 #ifdef TRACE_JCR_CHAIN
961    Dmsg3(dbglvl, "Unlock jcr chain %d from %s:%d\n", lock_count--, fname, line);
962 #endif
963    V(jcr_lock);
964 }
965
966 /*
967  * Start walk of jcr chain
968  * The proper way to walk the jcr chain is:
969  *    JCR *jcr;
970  *    foreach_jcr(jcr) {
971  *      ...
972  *    }
973  *    endeach_jcr(jcr);
974  *
975  *  It is possible to leave out the endeach_jcr(jcr), but
976  *   in that case, the last jcr referenced must be explicitly
977  *   released with:
978  *
979  *    free_jcr(jcr);
980  *
981  */
982 JCR *jcr_walk_start()
983 {
984    JCR *jcr;
985    lock_jcr_chain();
986    jcr = (JCR *)jcrs->first();
987    if (jcr) {
988       jcr->inc_use_count();
989       if (jcr->JobId > 0) {
990          Dmsg3(dbglvl, "Inc walk_start jid=%u use_count=%d Job=%s\n",
991             jcr->JobId, jcr->use_count(), jcr->Job);
992       }
993    }
994    unlock_jcr_chain();
995    return jcr;
996 }
997
998 /*
999  * Get next jcr from chain, and release current one
1000  */
1001 JCR *jcr_walk_next(JCR *prev_jcr)
1002 {
1003    JCR *jcr;
1004
1005    lock_jcr_chain();
1006    jcr = (JCR *)jcrs->next(prev_jcr);
1007    if (jcr) {
1008       jcr->inc_use_count();
1009       if (jcr->JobId > 0) {
1010          Dmsg3(dbglvl, "Inc walk_next jid=%u use_count=%d Job=%s\n",
1011             jcr->JobId, jcr->use_count(), jcr->Job);
1012       }
1013    }
1014    unlock_jcr_chain();
1015    if (prev_jcr) {
1016       free_jcr(prev_jcr);
1017    }
1018    return jcr;
1019 }
1020
1021 /*
1022  * Release last jcr referenced
1023  */
1024 void jcr_walk_end(JCR *jcr)
1025 {
1026    if (jcr) {
1027       if (jcr->JobId > 0) {
1028          Dmsg3(dbglvl, "Free walk_end jid=%u use_count=%d Job=%s\n",
1029             jcr->JobId, jcr->use_count(), jcr->Job);
1030       }
1031       free_jcr(jcr);
1032    }
1033 }
1034
1035 /*
1036  * Return number of Jobs
1037  */
1038 int job_count()
1039 {
1040    JCR *jcr;
1041    int count = 0;
1042
1043    lock_jcr_chain();
1044    for (jcr = (JCR *)jcrs->first(); (jcr = (JCR *)jcrs->next(jcr)); ) {
1045       if (jcr->JobId > 0) {
1046          count++;
1047       }
1048    }
1049    unlock_jcr_chain();
1050    return count;
1051 }
1052
1053
1054 /*
1055  * Setup to call the timeout check routine every 30 seconds
1056  *  This routine will check any timers that have been enabled.
1057  */
1058 bool init_jcr_subsystem(void)
1059 {
1060    watchdog_t *wd = new_watchdog();
1061
1062    wd->one_shot = false;
1063    wd->interval = 30;   /* FIXME: should be configurable somewhere, even
1064                          if only with a #define */
1065    wd->callback = jcr_timeout_check;
1066
1067    register_watchdog(wd);
1068
1069    return true;
1070 }
1071
1072 static void jcr_timeout_check(watchdog_t *self)
1073 {
1074    JCR *jcr;
1075    BSOCK *bs;
1076    time_t timer_start;
1077
1078    Dmsg0(dbglvl, "Start JCR timeout checks\n");
1079
1080    /* Walk through all JCRs checking if any one is
1081     * blocked for more than specified max time.
1082     */
1083    foreach_jcr(jcr) {
1084       Dmsg2(dbglvl, "jcr_timeout_check JobId=%u jcr=0x%x\n", jcr->JobId, jcr);
1085       if (jcr->JobId == 0) {
1086          continue;
1087       }
1088       bs = jcr->store_bsock;
1089       if (bs) {
1090          timer_start = bs->timer_start;
1091          if (timer_start && (watchdog_time - timer_start) > bs->timeout) {
1092             bs->timer_start = 0;      /* turn off timer */
1093             bs->set_timed_out();
1094             Qmsg(jcr, M_ERROR, 0, _(
1095 "Watchdog sending kill after %d secs to thread stalled reading Storage daemon.\n"),
1096                  (int)(watchdog_time - timer_start));
1097             jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
1098          }
1099       }
1100       bs = jcr->file_bsock;
1101       if (bs) {
1102          timer_start = bs->timer_start;
1103          if (timer_start && (watchdog_time - timer_start) > bs->timeout) {
1104             bs->timer_start = 0;      /* turn off timer */
1105             bs->set_timed_out();
1106             Qmsg(jcr, M_ERROR, 0, _(
1107 "Watchdog sending kill after %d secs to thread stalled reading File daemon.\n"),
1108                  (int)(watchdog_time - timer_start));
1109             jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
1110          }
1111       }
1112       bs = jcr->dir_bsock;
1113       if (bs) {
1114          timer_start = bs->timer_start;
1115          if (timer_start && (watchdog_time - timer_start) > bs->timeout) {
1116             bs->timer_start = 0;      /* turn off timer */
1117             bs->set_timed_out();
1118             Qmsg(jcr, M_ERROR, 0, _(
1119 "Watchdog sending kill after %d secs to thread stalled reading Director.\n"),
1120                  (int)(watchdog_time - timer_start));
1121             jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
1122          }
1123       }
1124    }
1125    endeach_jcr(jcr);
1126
1127    Dmsg0(dbglvl, "Finished JCR timeout checks\n");
1128 }
1129
1130 /*
1131  * Return next JobId from comma separated list
1132  *
1133  * Returns:
1134  *   1 if next JobId returned
1135  *   0 if no more JobIds are in list
1136  *  -1 there is an error
1137  */
1138 int get_next_jobid_from_list(char **p, uint32_t *JobId)
1139 {
1140    const int maxlen = 30;
1141    char jobid[maxlen+1];
1142    char *q = *p;
1143
1144    jobid[0] = 0;
1145    for (int i=0; i<maxlen; i++) {
1146       if (*q == 0) {
1147          break;
1148       } else if (*q == ',') {
1149          q++;
1150          break;
1151       }
1152       jobid[i] = *q++;
1153       jobid[i+1] = 0;
1154    }
1155    if (jobid[0] == 0) {
1156       return 0;
1157    } else if (!is_a_number(jobid)) {
1158       return -1;                      /* error */
1159    }
1160    *p = q;
1161    *JobId = str_to_int64(jobid);
1162    return 1;
1163 }
1164
1165 /*
1166  * Timeout signal comes here
1167  */
1168 extern "C" void timeout_handler(int sig)
1169 {
1170    return;                            /* thus interrupting the function */
1171 }
1172
1173 /* Used to display specific daemon information after a fatal signal
1174  * (like BDB in the director)
1175  */
1176 #define MAX_DBG_HOOK 10
1177 static dbg_jcr_hook_t *dbg_jcr_hooks[MAX_DBG_HOOK];
1178 static int dbg_jcr_handler_count;
1179
1180 void dbg_jcr_add_hook(dbg_jcr_hook_t *hook)
1181 {
1182    ASSERT(dbg_jcr_handler_count < MAX_DBG_HOOK);
1183    dbg_jcr_hooks[dbg_jcr_handler_count++] = hook;
1184 }
1185
1186 /* on win32, the pthread_t is a struct, so we don't display it */
1187 #ifdef HAVE_MINGW_W64
1188 # define get_threadid(a) (void *)0
1189 #else
1190 # define get_threadid(a) (void *)(a)
1191 #endif
1192 /*
1193  * !!! WARNING !!!
1194  *
1195  * This function should be used ONLY after a fatal signal. We walk through the
1196  * JCR chain without doing any lock, Bacula should not be running.
1197  */
1198 void dbg_print_jcr(FILE *fp)
1199 {
1200    char buf1[128], buf2[128], buf3[128], buf4[128];
1201
1202    if (!jcrs) {
1203       return;
1204    }
1205
1206    fprintf(fp, "Attempt to dump current JCRs. njcrs=%d\n", jcrs->size());
1207
1208    for (JCR *jcr = (JCR *)jcrs->first(); jcr ; jcr = (JCR *)jcrs->next(jcr)) {
1209       fprintf(fp, "threadid=%p JobId=%d JobStatus=%c jcr=%p name=%s\n",
1210               get_threadid(jcr->my_thread_id), (int)jcr->JobId, jcr->JobStatus, jcr, jcr->Job);
1211       fprintf(fp, "\tuse_count=%i killable=%d\n",
1212               jcr->use_count(), jcr->is_killable());
1213       fprintf(fp, "\tJobType=%c JobLevel=%c\n",
1214               jcr->getJobType(), jcr->getJobLevel());
1215       bstrftime(buf1, sizeof(buf1), jcr->sched_time);
1216       bstrftime(buf2, sizeof(buf2), jcr->start_time);
1217       bstrftime(buf3, sizeof(buf3), jcr->end_time);
1218       bstrftime(buf4, sizeof(buf4), jcr->wait_time);
1219       fprintf(fp, "\tsched_time=%s start_time=%s\n\tend_time=%s wait_time=%s\n",
1220               buf1, buf2, buf3, buf4);
1221       fprintf(fp, "\tdb=%p db_batch=%p batch_started=%i\n",
1222               jcr->db, jcr->db_batch, jcr->batch_started);
1223
1224       /*
1225        * Call all the jcr debug hooks
1226        */
1227       for(int i=0; i < dbg_jcr_handler_count; i++) {
1228          dbg_jcr_hook_t *hook = dbg_jcr_hooks[i];
1229          hook(jcr, fp);
1230       }
1231    }
1232 }