]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/jcr.c
Attempt to fix duplicate job kill seg fault
[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 two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of 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    garbage_collect_memory_pool();
580    Dmsg0(dbglvl, "Exit free_jcr\n");
581 }
582
583 /*
584  * Remove jcr from thread specific data, but
585  *   but make sure it is us who are attached.
586  */
587 void remove_jcr_from_tsd(JCR *jcr)
588 {
589    JCR *tjcr = get_jcr_from_tsd();
590    if (tjcr == jcr) { 
591       set_jcr_in_tsd(INVALID_JCR);
592    }
593 }
594
595 void JCR::set_killable(bool killable)
596 {
597    JCR *jcr = this;
598    jcr->lock();
599    jcr->my_thread_killable = killable;
600    if (killable) {
601       jcr->my_thread_id = pthread_self();
602    } else {
603       memset(&jcr->my_thread_id, 0, sizeof(jcr->my_thread_id));
604    }
605    jcr->unlock();
606 }
607
608 /*
609  * Put this jcr in the thread specifc data
610  *  if update_thread_info is true and the jcr is valide,
611  *  we update the my_thread_id in the JCR
612  */
613 void set_jcr_in_tsd(JCR *jcr)
614 {
615    int status = pthread_setspecific(jcr_key, (void *)jcr);
616    if (status != 0) {
617       berrno be;
618       Jmsg1(jcr, M_ABORT, 0, _("pthread_setspecific failed: ERR=%s\n"), 
619             be.bstrerror(status));
620    }
621 }
622
623 void JCR::my_thread_send_signal(int sig)
624 {
625    this->lock();
626    if (this->is_killable() &&
627        !pthread_equal(this->my_thread_id, pthread_self()))
628    {
629       Dmsg1(800, "Send kill to jid=%d\n", this->JobId);
630       pthread_kill(this->my_thread_id, sig);
631
632    } else if (!this->is_killable()) {
633       Dmsg1(10, "Warning, can't send kill to jid=%d\n", this->JobId);
634    }
635    this->unlock();
636 }
637
638 /*
639  * Give me the jcr that is attached to this thread
640  */
641 JCR *get_jcr_from_tsd()
642 {
643    JCR *jcr = (JCR *)pthread_getspecific(jcr_key);
644 // printf("get_jcr_from_tsd: jcr=%p\n", jcr);
645    /* set any INVALID_JCR to NULL which the rest of Bacula understands */
646    if (jcr == INVALID_JCR) {
647       jcr = NULL;
648    }
649    return jcr;
650 }
651
652  
653 /*
654  * Find which JobId corresponds to the current thread
655  */
656 uint32_t get_jobid_from_tsd()
657 {
658    JCR *jcr;
659    uint32_t JobId = 0;
660    jcr = get_jcr_from_tsd();
661 // printf("get_jobid_from_tsr: jcr=%p\n", jcr);
662    if (jcr) {
663       JobId = (uint32_t)jcr->JobId;
664    }
665    return JobId;
666 }
667
668 /*
669  * Given a JobId, find the JCR
670  *   Returns: jcr on success
671  *            NULL on failure
672  */
673 JCR *get_jcr_by_id(uint32_t JobId)
674 {
675    JCR *jcr;
676
677    foreach_jcr(jcr) {
678       if (jcr->JobId == JobId) {
679          jcr->inc_use_count();
680          Dmsg3(dbglvl, "Inc get_jcr jid=%u use_count=%d Job=%s\n", 
681             jcr->JobId, jcr->use_count(), jcr->Job);
682          break;
683       }
684    }
685    endeach_jcr(jcr);
686    return jcr;
687 }
688
689 /*
690  * Given a thread id, find the JobId
691  *   Returns: JobId on success
692  *            0 on failure
693  */
694 uint32_t get_jobid_from_tid(pthread_t tid)
695 {
696    JCR *jcr = NULL;
697    bool found = false;
698
699    foreach_jcr(jcr) {
700       if (pthread_equal(jcr->my_thread_id, tid)) {
701          found = true;
702          break;
703       }
704    }
705    endeach_jcr(jcr);
706    if (found) {
707       return jcr->JobId;
708    }
709    return 0;
710 }
711
712
713 /*
714  * Given a SessionId and SessionTime, find the JCR
715  *   Returns: jcr on success
716  *            NULL on failure
717  */
718 JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
719 {
720    JCR *jcr;
721
722    foreach_jcr(jcr) {
723       if (jcr->VolSessionId == SessionId &&
724           jcr->VolSessionTime == SessionTime) {
725          jcr->inc_use_count();
726          Dmsg3(dbglvl, "Inc get_jcr jid=%u use_count=%d Job=%s\n", 
727             jcr->JobId, jcr->use_count(), jcr->Job);
728          break;
729       }
730    }
731    endeach_jcr(jcr);
732    return jcr;
733 }
734
735
736 /*
737  * Given a Job, find the JCR
738  *  compares on the number of characters in Job
739  *  thus allowing partial matches.
740  *   Returns: jcr on success
741  *            NULL on failure
742  */
743 JCR *get_jcr_by_partial_name(char *Job)
744 {
745    JCR *jcr;
746    int len;
747
748    if (!Job) {
749       return NULL;
750    }
751    len = strlen(Job);
752    foreach_jcr(jcr) {
753       if (strncmp(Job, jcr->Job, len) == 0) {
754          jcr->inc_use_count();
755          Dmsg3(dbglvl, "Inc get_jcr jid=%u use_count=%d Job=%s\n", 
756             jcr->JobId, jcr->use_count(), jcr->Job);
757          break;
758       }
759    }
760    endeach_jcr(jcr);
761    return jcr;
762 }
763
764
765 /*
766  * Given a Job, find the JCR
767  *  requires an exact match of names.
768  *   Returns: jcr on success
769  *            NULL on failure
770  */
771 JCR *get_jcr_by_full_name(char *Job)
772 {
773    JCR *jcr;
774
775    if (!Job) {
776       return NULL;
777    }
778    foreach_jcr(jcr) {
779       if (strcmp(jcr->Job, Job) == 0) {
780          jcr->inc_use_count();
781          Dmsg3(dbglvl, "Inc get_jcr jid=%u use_count=%d Job=%s\n", 
782             jcr->JobId, jcr->use_count(), jcr->Job);
783          break;
784       }
785    }
786    endeach_jcr(jcr);
787    return jcr;
788 }
789
790 static void update_wait_time(JCR *jcr, int newJobStatus)
791 {
792    bool enter_in_waittime;
793    int oldJobStatus = jcr->JobStatus;
794
795    switch (newJobStatus) {
796    case JS_WaitFD:
797    case JS_WaitSD:
798    case JS_WaitMedia:
799    case JS_WaitMount:
800    case JS_WaitStoreRes:
801    case JS_WaitJobRes:
802    case JS_WaitClientRes:
803    case JS_WaitMaxJobs:
804    case JS_WaitPriority:
805       enter_in_waittime = true;
806       break;
807    default:
808       enter_in_waittime = false; /* not a Wait situation */
809       break;
810    }
811    
812    /*
813     * If we were previously waiting and are not any more
814     *   we want to update the wait_time variable, which is
815     *   the start of waiting.
816     */
817    switch (oldJobStatus) {
818    case JS_WaitFD:
819    case JS_WaitSD:
820    case JS_WaitMedia:
821    case JS_WaitMount:
822    case JS_WaitStoreRes:
823    case JS_WaitJobRes:
824    case JS_WaitClientRes:
825    case JS_WaitMaxJobs:
826    case JS_WaitPriority:
827       if (!enter_in_waittime) { /* we get out the wait time */
828          jcr->wait_time_sum += (time(NULL) - jcr->wait_time);
829          jcr->wait_time = 0;
830       }
831       break;
832
833    /* if wait state is new, we keep current time for watchdog MaxWaitTime */
834    default:
835       if (enter_in_waittime) {
836          jcr->wait_time = time(NULL);
837       }
838       break;
839    }
840 }
841
842 /* 
843  * Priority runs from 0 (lowest) to 10 (highest)
844  */
845 static int get_status_priority(int JobStatus)
846 {
847    int priority = 0;
848    switch (JobStatus) {
849    case JS_ErrorTerminated:
850    case JS_FatalError:
851    case JS_Canceled:
852    case JS_Incomplete:
853       priority = 10;
854       break;
855    case JS_Error:
856       priority = 8;
857       break;
858    case JS_Differences:
859       priority = 7;
860       break;
861    }
862    return priority;
863 }
864
865
866 void set_jcr_job_status(JCR *jcr, int JobStatus)
867 {
868    jcr->setJobStatus(JobStatus);
869 }
870
871 void JCR::setJobStatus(int newJobStatus)
872 {
873    JCR *jcr = this;
874    int priority, old_priority;
875    int oldJobStatus = jcr->JobStatus;
876    priority = get_status_priority(newJobStatus);
877    old_priority = get_status_priority(oldJobStatus);
878    
879    Dmsg2(800, "set_jcr_job_status(%s, %c)\n", Job, newJobStatus);
880
881    /* Update wait_time depending on newJobStatus and oldJobStatus */
882    update_wait_time(jcr, newJobStatus);
883
884    /*
885     * For a set of errors, ... keep the current status
886     *   so it isn't lost. For all others, set it.
887     */
888    Dmsg2(800, "OnEntry JobStatus=%c newJobstatus=%c\n", oldJobStatus, newJobStatus);
889    /*
890     * If status priority is > than proposed new status, change it.
891     * If status priority == new priority and both are zero, take
892     *   the new status. 
893     * If it is not zero, then we keep the first non-zero "error" that
894     *   occurred.
895     */
896    if (priority > old_priority || (
897        priority == 0 && old_priority == 0)) {
898       Dmsg4(800, "Set new stat. old: %c,%d new: %c,%d\n",
899          jcr->JobStatus, old_priority, newJobStatus, priority);
900       jcr->JobStatus = newJobStatus;     /* replace with new status */
901    }
902
903    if (oldJobStatus != jcr->JobStatus) {
904       Dmsg2(800, "leave set_job_status old=%c new=%c\n", oldJobStatus, newJobStatus);
905 //    generate_plugin_event(jcr, bEventStatusChange, NULL);
906    }
907 }
908
909 #ifdef TRACE_JCR_CHAIN
910 static int lock_count = 0;
911 #endif
912
913 /*
914  * Lock the chain
915  */
916 #ifdef TRACE_JCR_CHAIN
917 static void b_lock_jcr_chain(const char *fname, int line)
918 #else
919 static void lock_jcr_chain()
920 #endif
921 {
922 #ifdef TRACE_JCR_CHAIN
923    Dmsg3(dbglvl, "Lock jcr chain %d from %s:%d\n", ++lock_count, fname, line);
924 #endif
925    P(jcr_lock);
926 }
927
928 /*
929  * Unlock the chain
930  */
931 #ifdef TRACE_JCR_CHAIN
932 static void b_unlock_jcr_chain(const char *fname, int line)
933 #else
934 static void unlock_jcr_chain()
935 #endif
936 {
937 #ifdef TRACE_JCR_CHAIN
938    Dmsg3(dbglvl, "Unlock jcr chain %d from %s:%d\n", lock_count--, fname, line);
939 #endif
940    V(jcr_lock);
941 }
942
943 /*
944  * Start walk of jcr chain
945  * The proper way to walk the jcr chain is:
946  *    JCR *jcr;
947  *    foreach_jcr(jcr) {
948  *      ...
949  *    }
950  *    endeach_jcr(jcr);
951  *
952  *  It is possible to leave out the endeach_jcr(jcr), but
953  *   in that case, the last jcr referenced must be explicitly
954  *   released with:
955  *
956  *    free_jcr(jcr);
957  *  
958  */
959 JCR *jcr_walk_start() 
960 {
961    JCR *jcr;
962    lock_jcr_chain();
963    jcr = (JCR *)jcrs->first();
964    if (jcr) {
965       jcr->inc_use_count();
966       if (jcr->JobId > 0) {
967          Dmsg3(dbglvl, "Inc walk_start jid=%u use_count=%d Job=%s\n", 
968             jcr->JobId, jcr->use_count(), jcr->Job);
969       }
970    }
971    unlock_jcr_chain();
972    return jcr;
973 }
974
975 /*
976  * Get next jcr from chain, and release current one
977  */
978 JCR *jcr_walk_next(JCR *prev_jcr)
979 {
980    JCR *jcr;
981
982    lock_jcr_chain();
983    jcr = (JCR *)jcrs->next(prev_jcr);
984    if (jcr) {
985       jcr->inc_use_count();
986       if (jcr->JobId > 0) {
987          Dmsg3(dbglvl, "Inc walk_next jid=%u use_count=%d Job=%s\n", 
988             jcr->JobId, jcr->use_count(), jcr->Job);
989       }
990    }
991    unlock_jcr_chain();
992    if (prev_jcr) {
993       free_jcr(prev_jcr);
994    }
995    return jcr;
996 }
997
998 /*
999  * Release last jcr referenced
1000  */
1001 void jcr_walk_end(JCR *jcr)
1002 {
1003    if (jcr) {
1004       if (jcr->JobId > 0) {
1005          Dmsg3(dbglvl, "Free walk_end jid=%u use_count=%d Job=%s\n", 
1006             jcr->JobId, jcr->use_count(), jcr->Job);
1007       }
1008       free_jcr(jcr);
1009    }
1010 }
1011
1012 /*
1013  * Return number of Jobs
1014  */
1015 int job_count()
1016 {
1017    JCR *jcr;
1018    int count = 0;
1019
1020    lock_jcr_chain();
1021    for (jcr = (JCR *)jcrs->first(); (jcr = (JCR *)jcrs->next(jcr)); ) {
1022       if (jcr->JobId > 0) {
1023          count++;
1024       }
1025    }
1026    unlock_jcr_chain();
1027    return count;
1028 }
1029
1030
1031 /*
1032  * Setup to call the timeout check routine every 30 seconds
1033  *  This routine will check any timers that have been enabled.
1034  */
1035 bool init_jcr_subsystem(void)
1036 {
1037    watchdog_t *wd = new_watchdog();
1038
1039    wd->one_shot = false;
1040    wd->interval = 30;   /* FIXME: should be configurable somewhere, even
1041                          if only with a #define */
1042    wd->callback = jcr_timeout_check;
1043
1044    register_watchdog(wd);
1045
1046    return true;
1047 }
1048
1049 static void jcr_timeout_check(watchdog_t *self)
1050 {
1051    JCR *jcr;
1052    BSOCK *bs;
1053    time_t timer_start;
1054
1055    Dmsg0(dbglvl, "Start JCR timeout checks\n");
1056
1057    /* Walk through all JCRs checking if any one is
1058     * blocked for more than specified max time.
1059     */
1060    foreach_jcr(jcr) {
1061       Dmsg2(dbglvl, "jcr_timeout_check JobId=%u jcr=0x%x\n", jcr->JobId, jcr);
1062       if (jcr->JobId == 0) {
1063          continue;
1064       }
1065       bs = jcr->store_bsock;
1066       if (bs) {
1067          timer_start = bs->timer_start;
1068          if (timer_start && (watchdog_time - timer_start) > bs->timeout) {
1069             bs->timer_start = 0;      /* turn off timer */
1070             bs->set_timed_out();
1071             Qmsg(jcr, M_ERROR, 0, _(
1072 "Watchdog sending kill after %d secs to thread stalled reading Storage daemon.\n"),
1073                  watchdog_time - timer_start);
1074             jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
1075          }
1076       }
1077       bs = jcr->file_bsock;
1078       if (bs) {
1079          timer_start = bs->timer_start;
1080          if (timer_start && (watchdog_time - timer_start) > bs->timeout) {
1081             bs->timer_start = 0;      /* turn off timer */
1082             bs->set_timed_out();
1083             Qmsg(jcr, M_ERROR, 0, _(
1084 "Watchdog sending kill after %d secs to thread stalled reading File daemon.\n"),
1085                  watchdog_time - timer_start);
1086             jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
1087          }
1088       }
1089       bs = jcr->dir_bsock;
1090       if (bs) {
1091          timer_start = bs->timer_start;
1092          if (timer_start && (watchdog_time - timer_start) > bs->timeout) {
1093             bs->timer_start = 0;      /* turn off timer */
1094             bs->set_timed_out();
1095             Qmsg(jcr, M_ERROR, 0, _(
1096 "Watchdog sending kill after %d secs to thread stalled reading Director.\n"),
1097                  watchdog_time - timer_start);
1098             jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
1099          }
1100       }
1101    }
1102    endeach_jcr(jcr);
1103
1104    Dmsg0(dbglvl, "Finished JCR timeout checks\n");
1105 }
1106
1107 /* 
1108  * Return next JobId from comma separated list   
1109  *
1110  * Returns:
1111  *   1 if next JobId returned
1112  *   0 if no more JobIds are in list
1113  *  -1 there is an error
1114  */
1115 int get_next_jobid_from_list(char **p, uint32_t *JobId)
1116 {
1117    const int maxlen = 30;
1118    char jobid[maxlen+1];
1119    char *q = *p;
1120
1121    jobid[0] = 0;
1122    for (int i=0; i<maxlen; i++) {
1123       if (*q == 0) {
1124          break;
1125       } else if (*q == ',') {
1126          q++;
1127          break;
1128       }
1129       jobid[i] = *q++;
1130       jobid[i+1] = 0;
1131    }
1132    if (jobid[0] == 0) {
1133       return 0;
1134    } else if (!is_a_number(jobid)) {
1135       return -1;                      /* error */
1136    }
1137    *p = q;
1138    *JobId = str_to_int64(jobid);
1139    return 1;
1140 }
1141
1142 /*
1143  * Timeout signal comes here
1144  */
1145 extern "C" void timeout_handler(int sig)
1146 {
1147    return;                            /* thus interrupting the function */
1148 }
1149
1150 /* Used to display specific daemon information after a fatal signal 
1151  * (like B_DB in the director)
1152  */
1153 #define MAX_DBG_HOOK 10
1154 static dbg_jcr_hook_t *dbg_jcr_hooks[MAX_DBG_HOOK];
1155 static int dbg_jcr_handler_count;
1156
1157 void dbg_jcr_add_hook(dbg_jcr_hook_t *hook)
1158 {
1159    ASSERT(dbg_jcr_handler_count < MAX_DBG_HOOK);
1160    dbg_jcr_hooks[dbg_jcr_handler_count++] = hook;
1161 }
1162
1163 /*
1164  * !!! WARNING !!! 
1165  *
1166  * This function should be used ONLY after a fatal signal. We walk through the
1167  * JCR chain without doing any lock, Bacula should not be running.
1168  */
1169 void dbg_print_jcr(FILE *fp)
1170 {
1171    char buf1[128], buf2[128], buf3[128], buf4[128];
1172    if (!jcrs) {
1173       return;
1174    }
1175
1176    fprintf(fp, "Attempt to dump current JCRs. njcrs=%d\n", jcrs->size());
1177
1178    for (JCR *jcr = (JCR *)jcrs->first(); jcr ; jcr = (JCR *)jcrs->next(jcr)) {
1179       fprintf(fp, "threadid=%p JobId=%d JobStatus=%c jcr=%p name=%s\n", 
1180               (void *)jcr->my_thread_id, (int)jcr->JobId, jcr->JobStatus, jcr, jcr->Job);
1181       fprintf(fp, "threadid=%p killable=%d JobId=%d JobStatus=%c "
1182                   "jcr=%p name=%s\n",
1183               (void *)jcr->my_thread_id, jcr->is_killable(),
1184               (int)jcr->JobId, jcr->JobStatus, jcr, jcr->Job);
1185       fprintf(fp, "\tuse_count=%i\n", jcr->use_count());
1186       fprintf(fp, "\tJobType=%c JobLevel=%c\n",
1187               jcr->getJobType(), jcr->getJobLevel());
1188       bstrftime(buf1, sizeof(buf1), jcr->sched_time);
1189       bstrftime(buf2, sizeof(buf2), jcr->start_time);
1190       bstrftime(buf3, sizeof(buf3), jcr->end_time);
1191       bstrftime(buf4, sizeof(buf4), jcr->wait_time);
1192       fprintf(fp, "\tsched_time=%s start_time=%s\n\tend_time=%s wait_time=%s\n",
1193               buf1, buf2, buf3, buf4);
1194       fprintf(fp, "\tdb=%p db_batch=%p batch_started=%i\n", 
1195               jcr->db, jcr->db_batch, jcr->batch_started);
1196       
1197       /*
1198        * Call all the jcr debug hooks
1199        */
1200       for(int i=0; i < dbg_jcr_handler_count; i++) {
1201          dbg_jcr_hook_t *hook = dbg_jcr_hooks[i];
1202          hook(jcr, fp);
1203       }
1204    }
1205 }