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