]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/jcr.c
Fix segfault with print_memory_pool_stats()
[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_ErrorTerminated:
849    case JS_FatalError:
850    case JS_Canceled:
851    case JS_Incomplete:
852       priority = 10;
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 void set_jcr_job_status(JCR *jcr, int JobStatus)
866 {
867    jcr->setJobStatus(JobStatus);
868 }
869
870 void JCR::setJobStatus(int newJobStatus)
871 {
872    JCR *jcr = this;
873    int priority, old_priority;
874    int oldJobStatus = jcr->JobStatus;
875    priority = get_status_priority(newJobStatus);
876    old_priority = get_status_priority(oldJobStatus);
877    
878    Dmsg2(800, "set_jcr_job_status(%s, %c)\n", Job, newJobStatus);
879
880    /* Update wait_time depending on newJobStatus and oldJobStatus */
881    update_wait_time(jcr, newJobStatus);
882
883    /*
884     * For a set of errors, ... keep the current status
885     *   so it isn't lost. For all others, set it.
886     */
887    Dmsg2(800, "OnEntry JobStatus=%c newJobstatus=%c\n", oldJobStatus, newJobStatus);
888    /*
889     * If status priority is > than proposed new status, change it.
890     * If status priority == new priority and both are zero, take
891     *   the new status. 
892     * If it is not zero, then we keep the first non-zero "error" that
893     *   occurred.
894     */
895    if (priority > old_priority || (
896        priority == 0 && old_priority == 0)) {
897       Dmsg4(800, "Set new stat. old: %c,%d new: %c,%d\n",
898          jcr->JobStatus, old_priority, newJobStatus, priority);
899       jcr->JobStatus = newJobStatus;     /* replace with new status */
900    }
901
902    if (oldJobStatus != jcr->JobStatus) {
903       Dmsg2(800, "leave set_job_status old=%c new=%c\n", oldJobStatus, newJobStatus);
904 //    generate_plugin_event(jcr, bEventStatusChange, NULL);
905    }
906 }
907
908 #ifdef TRACE_JCR_CHAIN
909 static int lock_count = 0;
910 #endif
911
912 /*
913  * Lock the chain
914  */
915 #ifdef TRACE_JCR_CHAIN
916 static void b_lock_jcr_chain(const char *fname, int line)
917 #else
918 static void lock_jcr_chain()
919 #endif
920 {
921 #ifdef TRACE_JCR_CHAIN
922    Dmsg3(dbglvl, "Lock jcr chain %d from %s:%d\n", ++lock_count, fname, line);
923 #endif
924    P(jcr_lock);
925 }
926
927 /*
928  * Unlock the chain
929  */
930 #ifdef TRACE_JCR_CHAIN
931 static void b_unlock_jcr_chain(const char *fname, int line)
932 #else
933 static void unlock_jcr_chain()
934 #endif
935 {
936 #ifdef TRACE_JCR_CHAIN
937    Dmsg3(dbglvl, "Unlock jcr chain %d from %s:%d\n", lock_count--, fname, line);
938 #endif
939    V(jcr_lock);
940 }
941
942 /*
943  * Start walk of jcr chain
944  * The proper way to walk the jcr chain is:
945  *    JCR *jcr;
946  *    foreach_jcr(jcr) {
947  *      ...
948  *    }
949  *    endeach_jcr(jcr);
950  *
951  *  It is possible to leave out the endeach_jcr(jcr), but
952  *   in that case, the last jcr referenced must be explicitly
953  *   released with:
954  *
955  *    free_jcr(jcr);
956  *  
957  */
958 JCR *jcr_walk_start() 
959 {
960    JCR *jcr;
961    lock_jcr_chain();
962    jcr = (JCR *)jcrs->first();
963    if (jcr) {
964       jcr->inc_use_count();
965       if (jcr->JobId > 0) {
966          Dmsg3(dbglvl, "Inc walk_start jid=%u use_count=%d Job=%s\n", 
967             jcr->JobId, jcr->use_count(), jcr->Job);
968       }
969    }
970    unlock_jcr_chain();
971    return jcr;
972 }
973
974 /*
975  * Get next jcr from chain, and release current one
976  */
977 JCR *jcr_walk_next(JCR *prev_jcr)
978 {
979    JCR *jcr;
980
981    lock_jcr_chain();
982    jcr = (JCR *)jcrs->next(prev_jcr);
983    if (jcr) {
984       jcr->inc_use_count();
985       if (jcr->JobId > 0) {
986          Dmsg3(dbglvl, "Inc walk_next jid=%u use_count=%d Job=%s\n", 
987             jcr->JobId, jcr->use_count(), jcr->Job);
988       }
989    }
990    unlock_jcr_chain();
991    if (prev_jcr) {
992       free_jcr(prev_jcr);
993    }
994    return jcr;
995 }
996
997 /*
998  * Release last jcr referenced
999  */
1000 void jcr_walk_end(JCR *jcr)
1001 {
1002    if (jcr) {
1003       if (jcr->JobId > 0) {
1004          Dmsg3(dbglvl, "Free walk_end jid=%u use_count=%d Job=%s\n", 
1005             jcr->JobId, jcr->use_count(), jcr->Job);
1006       }
1007       free_jcr(jcr);
1008    }
1009 }
1010
1011 /*
1012  * Return number of Jobs
1013  */
1014 int job_count()
1015 {
1016    JCR *jcr;
1017    int count = 0;
1018
1019    lock_jcr_chain();
1020    for (jcr = (JCR *)jcrs->first(); (jcr = (JCR *)jcrs->next(jcr)); ) {
1021       if (jcr->JobId > 0) {
1022          count++;
1023       }
1024    }
1025    unlock_jcr_chain();
1026    return count;
1027 }
1028
1029
1030 /*
1031  * Setup to call the timeout check routine every 30 seconds
1032  *  This routine will check any timers that have been enabled.
1033  */
1034 bool init_jcr_subsystem(void)
1035 {
1036    watchdog_t *wd = new_watchdog();
1037
1038    wd->one_shot = false;
1039    wd->interval = 30;   /* FIXME: should be configurable somewhere, even
1040                          if only with a #define */
1041    wd->callback = jcr_timeout_check;
1042
1043    register_watchdog(wd);
1044
1045    return true;
1046 }
1047
1048 static void jcr_timeout_check(watchdog_t *self)
1049 {
1050    JCR *jcr;
1051    BSOCK *bs;
1052    time_t timer_start;
1053
1054    Dmsg0(dbglvl, "Start JCR timeout checks\n");
1055
1056    /* Walk through all JCRs checking if any one is
1057     * blocked for more than specified max time.
1058     */
1059    foreach_jcr(jcr) {
1060       Dmsg2(dbglvl, "jcr_timeout_check JobId=%u jcr=0x%x\n", jcr->JobId, jcr);
1061       if (jcr->JobId == 0) {
1062          continue;
1063       }
1064       bs = jcr->store_bsock;
1065       if (bs) {
1066          timer_start = bs->timer_start;
1067          if (timer_start && (watchdog_time - timer_start) > bs->timeout) {
1068             bs->timer_start = 0;      /* turn off timer */
1069             bs->set_timed_out();
1070             Qmsg(jcr, M_ERROR, 0, _(
1071 "Watchdog sending kill after %d secs to thread stalled reading Storage daemon.\n"),
1072                  watchdog_time - timer_start);
1073             jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
1074          }
1075       }
1076       bs = jcr->file_bsock;
1077       if (bs) {
1078          timer_start = bs->timer_start;
1079          if (timer_start && (watchdog_time - timer_start) > bs->timeout) {
1080             bs->timer_start = 0;      /* turn off timer */
1081             bs->set_timed_out();
1082             Qmsg(jcr, M_ERROR, 0, _(
1083 "Watchdog sending kill after %d secs to thread stalled reading File daemon.\n"),
1084                  watchdog_time - timer_start);
1085             jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
1086          }
1087       }
1088       bs = jcr->dir_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 Director.\n"),
1096                  watchdog_time - timer_start);
1097             jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
1098          }
1099       }
1100    }
1101    endeach_jcr(jcr);
1102
1103    Dmsg0(dbglvl, "Finished JCR timeout checks\n");
1104 }
1105
1106 /* 
1107  * Return next JobId from comma separated list   
1108  *
1109  * Returns:
1110  *   1 if next JobId returned
1111  *   0 if no more JobIds are in list
1112  *  -1 there is an error
1113  */
1114 int get_next_jobid_from_list(char **p, uint32_t *JobId)
1115 {
1116    const int maxlen = 30;
1117    char jobid[maxlen+1];
1118    char *q = *p;
1119
1120    jobid[0] = 0;
1121    for (int i=0; i<maxlen; i++) {
1122       if (*q == 0) {
1123          break;
1124       } else if (*q == ',') {
1125          q++;
1126          break;
1127       }
1128       jobid[i] = *q++;
1129       jobid[i+1] = 0;
1130    }
1131    if (jobid[0] == 0) {
1132       return 0;
1133    } else if (!is_a_number(jobid)) {
1134       return -1;                      /* error */
1135    }
1136    *p = q;
1137    *JobId = str_to_int64(jobid);
1138    return 1;
1139 }
1140
1141 /*
1142  * Timeout signal comes here
1143  */
1144 extern "C" void timeout_handler(int sig)
1145 {
1146    return;                            /* thus interrupting the function */
1147 }
1148
1149 /* Used to display specific daemon information after a fatal signal 
1150  * (like B_DB in the director)
1151  */
1152 #define MAX_DBG_HOOK 10
1153 static dbg_jcr_hook_t *dbg_jcr_hooks[MAX_DBG_HOOK];
1154 static int dbg_jcr_handler_count;
1155
1156 void dbg_jcr_add_hook(dbg_jcr_hook_t *hook)
1157 {
1158    ASSERT(dbg_jcr_handler_count < MAX_DBG_HOOK);
1159    dbg_jcr_hooks[dbg_jcr_handler_count++] = hook;
1160 }
1161
1162 /*
1163  * !!! WARNING !!! 
1164  *
1165  * This function should be used ONLY after a fatal signal. We walk through the
1166  * JCR chain without doing any lock, Bacula should not be running.
1167  */
1168 void dbg_print_jcr(FILE *fp)
1169 {
1170    char buf1[128], buf2[128], buf3[128], buf4[128];
1171    if (!jcrs) {
1172       return;
1173    }
1174
1175    fprintf(fp, "Attempt to dump current JCRs. njcrs=%d\n", jcrs->size());
1176
1177    for (JCR *jcr = (JCR *)jcrs->first(); jcr ; jcr = (JCR *)jcrs->next(jcr)) {
1178       fprintf(fp, "threadid=%p JobId=%d JobStatus=%c jcr=%p name=%s\n", 
1179               (void *)jcr->my_thread_id, (int)jcr->JobId, jcr->JobStatus, jcr, jcr->Job);
1180       fprintf(fp, "threadid=%p killable=%d JobId=%d JobStatus=%c "
1181                   "jcr=%p name=%s\n",
1182               (void *)jcr->my_thread_id, jcr->is_killable(),
1183               (int)jcr->JobId, jcr->JobStatus, jcr, jcr->Job);
1184       fprintf(fp, "\tuse_count=%i\n", jcr->use_count());
1185       fprintf(fp, "\tJobType=%c JobLevel=%c\n",
1186               jcr->getJobType(), jcr->getJobLevel());
1187       bstrftime(buf1, sizeof(buf1), jcr->sched_time);
1188       bstrftime(buf2, sizeof(buf2), jcr->start_time);
1189       bstrftime(buf3, sizeof(buf3), jcr->end_time);
1190       bstrftime(buf4, sizeof(buf4), jcr->wait_time);
1191       fprintf(fp, "\tsched_time=%s start_time=%s\n\tend_time=%s wait_time=%s\n",
1192               buf1, buf2, buf3, buf4);
1193       fprintf(fp, "\tdb=%p db_batch=%p batch_started=%i\n", 
1194               jcr->db, jcr->db_batch, jcr->batch_started);
1195       
1196       /*
1197        * Call all the jcr debug hooks
1198        */
1199       for(int i=0; i < dbg_jcr_handler_count; i++) {
1200          dbg_jcr_hook_t *hook = dbg_jcr_hooks[i];
1201          hook(jcr, fp);
1202       }
1203    }
1204 }