void *connect_thread(void *arg) { pthread_detach(pthread_self()); set_jcr_in_tsd(INVALID_JCR); /* Permit MaxConsoleConnect console connections */ bnet_thread_server((dlist*)arg, director->MaxConsoleConnect, &ua_workq, handle_UA_client_request); return NULL; }
/* * Create a Job Control Record and link it into JCR chain * Returns newly allocated JCR * Note, since each daemon has a different JCR, he passes * us the size. */ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) { JCR *jcr; MQUEUE_ITEM *item = NULL; struct sigaction sigtimer; int status; Dmsg0(dbglvl, "Enter new_jcr\n"); status = pthread_once(&key_once, create_jcr_key); if (status != 0) { berrno be; Jmsg1(NULL, M_ABORT, 0, _("pthread_once failed. ERR=%s\n"), be.bstrerror(status)); } jcr = (JCR *)malloc(size); memset(jcr, 0, size); jcr->my_thread_id = pthread_self(); jcr->msg_queue = New(dlist(item, &item->link)); jcr->job_end_push.init(1, false); jcr->sched_time = time(NULL); jcr->daemon_free_jcr = daemon_free_jcr; /* plug daemon free routine */ jcr->init_mutex(); jcr->inc_use_count(); jcr->VolumeName = get_pool_memory(PM_FNAME); jcr->VolumeName[0] = 0; jcr->errmsg = get_pool_memory(PM_MESSAGE); jcr->errmsg[0] = 0; /* Setup some dummy values */ bstrncpy(jcr->Job, "*System*", sizeof(jcr->Job)); jcr->JobId = 0; jcr->set_JobType(JT_SYSTEM); /* internal job until defined */ jcr->set_JobLevel(L_NONE); set_jcr_job_status(jcr, JS_Created); /* ready to run */ set_jcr_in_tsd(jcr); sigtimer.sa_flags = 0; sigtimer.sa_handler = timeout_handler; sigfillset(&sigtimer.sa_mask); sigaction(TIMEOUT_SIGNAL, &sigtimer, NULL); /* * Locking jobs is a global lock that is needed * so that the Director can stop new jobs from being * added to the jcr chain while it processes a new * conf file and does the job_end_push(). */ lock_jobs(); lock_jcr_chain(); if (!jcrs) { jcrs = New(dlist(jcr, &jcr->link)); } jcrs->append(jcr); unlock_jcr_chain(); unlock_jobs(); return jcr; }
void *connect_thread(void *arg) { pthread_detach(pthread_self()); set_jcr_in_tsd(INVALID_JCR); /* Permit MaxConsoleConnect console connections */ sock_fds = New(alist(10, not_owned_by_alist)); bnet_thread_server_tcp((dlist*)arg, me->MaxConsoleConnect, sock_fds, &ua_workq, me->nokeepalive, handle_UA_client_request); return NULL; }
int main (int argc, char *argv[]) { int ch; bool no_signals = false; bool test_config = false; pthread_t thid; char *uid = NULL; char *gid = NULL; start_heap = sbrk(0); setlocale(LC_ALL, ""); bindtextdomain("bareos", LOCALEDIR); textdomain("bareos"); init_stack_dump(); my_name_is(argc, argv, "bareos-sd"); init_msg(NULL, NULL); daemon_start_time = time(NULL); /* Sanity checks */ if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) { Emsg2(M_ABORT, 0, _("Tape block size (%d) not multiple of system size (%d)\n"), TAPE_BSIZE, B_DEV_BSIZE); } if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) { Emsg1(M_ABORT, 0, _("Tape block size (%d) is not a power of 2\n"), TAPE_BSIZE); } while ((ch = getopt(argc, argv, "c:d:fg:mpstu:v?")) != -1) { switch (ch) { case 'c': /* configuration file */ if (configfile != NULL) { free(configfile); } configfile = bstrdup(optarg); break; case 'd': /* debug level */ if (*optarg == 't') { dbg_timestamp = true; } else { debug_level = atoi(optarg); if (debug_level <= 0) { debug_level = 1; } } break; case 'f': /* run in foreground */ foreground = true; break; case 'g': /* set group id */ gid = optarg; break; case 'm': /* print kaboom output */ prt_kaboom = true; break; case 'p': /* proceed in spite of I/O errors */ forge_on = true; break; case 's': /* no signals */ no_signals = true; break; case 't': test_config = true; break; case 'u': /* set uid */ uid = optarg; break; case 'v': /* verbose */ verbose++; break; case '?': default: usage(); break; } } argc -= optind; argv += optind; if (argc) { if (configfile != NULL) { free(configfile); } configfile = bstrdup(*argv); argc--; argv++; } if (argc) usage(); /* * See if we want to drop privs. */ if (geteuid() == 0) { drop(uid, gid, false); } if (!no_signals) { init_signals(terminate_stored); } if (configfile == NULL) { configfile = bstrdup(CONFIG_FILE); } my_config = new_config_parser(); parse_sd_config(my_config, configfile, M_ERROR_TERM); if (init_crypto() != 0) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n")); } if (!check_resources()) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile); } init_reservations_lock(); if (test_config) { terminate_stored(0); } my_name_is(0, (char **)NULL, me->hdr.name); /* Set our real name */ if (!foreground) { daemon_start(); /* become daemon */ init_stack_dump(); /* pick up new pid */ } create_pid_file(me->pid_directory, "bareos-sd", get_first_port_host_order(me->SDaddrs)); read_state_file(me->working_directory, "bareos-sd", get_first_port_host_order(me->SDaddrs)); read_crypto_cache(me->working_directory, "bareos-sd", get_first_port_host_order(me->SDaddrs)); set_jcr_in_tsd(INVALID_JCR); /* * Make sure on Solaris we can run concurrent, watch dog + servers + misc */ set_thread_concurrency(me->max_concurrent_jobs * 2 + 4); lmgr_init_thread(); /* initialize the lockmanager stack */ load_sd_plugins(me->plugin_directory, me->plugin_names); cleanup_old_files(); /* Ensure that Volume Session Time and Id are both * set and are both non-zero. */ VolSessionTime = (uint32_t)daemon_start_time; if (VolSessionTime == 0) { /* paranoid */ Jmsg0(NULL, M_ABORT, 0, _("Volume Session Time is ZERO!\n")); } /* * Start the device allocation thread */ create_volume_lists(); /* do before device_init */ if (pthread_create(&thid, NULL, device_initialization, NULL) != 0) { berrno be; Emsg1(M_ABORT, 0, _("Unable to create thread. ERR=%s\n"), be.bstrerror()); } start_watchdog(); /* start watchdog thread */ if (me->jcr_watchdog_time) { init_jcr_subsystem(me->jcr_watchdog_time); /* start JCR watchdogs etc. */ } #if HAVE_NDMP /* Seperate thread that handles NDMP connections */ if (me->ndmp_enable) { start_ndmp_thread_server(me->NDMPaddrs, me->max_concurrent_jobs * 2 + 1, &ndmp_workq); } #endif /* Single server used for Director/Storage and File daemon */ sock_fds = New(alist(10, not_owned_by_alist)); bnet_thread_server_tcp(me->SDaddrs, me->max_concurrent_jobs * 2 + 1, sock_fds, &dird_workq, me->nokeepalive, handle_connection_request); exit(1); /* to keep compiler quiet */ }
/* * Handle Director User Agent commands */ static void *handle_UA_client_request(void *arg) { int status; UAContext *ua; JCR *jcr; BSOCK *user = (BSOCK *)arg; pthread_detach(pthread_self()); jcr = new_control_jcr("-Console-", JT_CONSOLE); ua = new_ua_context(jcr); ua->UA_sock = user; set_jcr_in_tsd(INVALID_JCR); user->recv(); /* Get first message */ if (!authenticate_user_agent(ua)) { goto getout; } while (!ua->quit) { if (ua->api) { user->signal(BNET_MAIN_PROMPT); } status = user->recv(); if (status >= 0) { pm_strcpy(ua->cmd, ua->UA_sock->msg); parse_ua_args(ua); if (ua->argc > 0 && ua->argk[0][0] == '.') { do_a_dot_command(ua); } else { do_a_command(ua); } dequeue_messages(ua->jcr); if (!ua->quit) { if (console_msg_pending && acl_access_ok(ua, Command_ACL, "messages")) { if (ua->auto_display_messages) { pm_strcpy(ua->cmd, "messages"); qmessages_cmd(ua, ua->cmd); ua->user_notified_msg_pending = false; } else if (!ua->gui && !ua->user_notified_msg_pending && console_msg_pending) { if (ua->api) { user->signal(BNET_MSGS_PENDING); } else { bsendmsg(ua, _("You have messages.\n")); } ua->user_notified_msg_pending = true; } } if (!ua->api) { user->signal(BNET_EOD); /* send end of command */ } } } else if (is_bnet_stop(user)) { ua->quit = true; } else { /* signal */ user->signal(BNET_POLL); } } getout: close_db(ua); free_ua_context(ua); free_jcr(jcr); user->close(); delete user; return NULL; }
int main (int argc, char *argv[]) { int ch; JCR *jcr; cat_op mode; bool no_signals = false; bool test_config = false; char *uid = NULL; char *gid = NULL; start_heap = sbrk(0); setlocale(LC_ALL, ""); bindtextdomain("bareos", LOCALEDIR); textdomain("bareos"); init_stack_dump(); my_name_is(argc, argv, "bareos-dir"); init_msg(NULL, NULL); /* initialize message handler */ init_reload(); daemon_start_time = time(NULL); console_command = run_console_command; while ((ch = getopt(argc, argv, "c:d:fg:mr:stu:v?")) != -1) { switch (ch) { case 'c': /* specify config file */ if (configfile != NULL) { free(configfile); } configfile = bstrdup(optarg); break; case 'd': /* set debug level */ if (*optarg == 't') { dbg_timestamp = true; } else { debug_level = atoi(optarg); if (debug_level <= 0) { debug_level = 1; } } Dmsg1(10, "Debug level = %d\n", debug_level); break; case 'f': /* run in foreground */ background = false; break; case 'g': /* set group id */ gid = optarg; break; case 'm': /* print kaboom output */ prt_kaboom = true; break; case 'r': /* run job */ if (runjob != NULL) { free(runjob); } if (optarg) { runjob = bstrdup(optarg); } break; case 's': /* turn off signals */ no_signals = true; break; case 't': /* test config */ test_config = true; break; case 'u': /* set uid */ uid = optarg; break; case 'v': /* verbose */ verbose++; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (!no_signals) { init_signals(terminate_dird); } if (argc) { if (configfile != NULL) { free(configfile); } configfile = bstrdup(*argv); argc--; argv++; } if (argc) { usage(); } if (configfile == NULL) { configfile = bstrdup(CONFIG_FILE); } /* * See if we want to drop privs. */ if (geteuid() == 0) { drop(uid, gid, false); /* reduce privileges if requested */ } my_config = new_config_parser(); parse_dir_config(my_config, configfile, M_ERROR_TERM); if (init_crypto() != 0) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n")); goto bail_out; } if (!check_resources()) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile); goto bail_out; } if (!test_config) { /* we don't need to do this block in test mode */ if (background) { daemon_start(); init_stack_dump(); /* grab new pid */ } /* Create pid must come after we are a daemon -- so we have our final pid */ create_pid_file(me->pid_directory, "bareos-dir", get_first_port_host_order(me->DIRaddrs)); read_state_file(me->working_directory, "bareos-dir", get_first_port_host_order(me->DIRaddrs)); } set_jcr_in_tsd(INVALID_JCR); set_thread_concurrency(me->MaxConcurrentJobs * 2 + 4 /* UA */ + 5 /* sched+watchdog+jobsvr+misc */); lmgr_init_thread(); /* initialize the lockmanager stack */ load_dir_plugins(me->plugin_directory, me->plugin_names); /* * If we are in testing mode, we don't try to fix the catalog */ mode = (test_config) ? CHECK_CONNECTION : UPDATE_AND_FIX; if (!check_catalog(mode)) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile); goto bail_out; } if (test_config) { terminate_dird(0); } if (!initialize_sql_pooling()) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile); goto bail_out; } my_name_is(0, NULL, me->name()); /* set user defined name */ cleanup_old_files(); p_db_log_insert = (db_log_insert_func)dir_db_log_insert; #if !defined(HAVE_WIN32) signal(SIGHUP, reload_config); #endif init_console_msg(working_directory); Dmsg0(200, "Start UA server\n"); start_UA_server(me->DIRaddrs); start_watchdog(); /* start network watchdog thread */ if (me->jcr_watchdog_time) { init_jcr_subsystem(me->jcr_watchdog_time); /* start JCR watchdogs etc. */ } init_job_server(me->MaxConcurrentJobs); dbg_jcr_add_hook(db_debug_print); /* used to debug B_DB connexion after fatal signal */ // init_device_resources(); Dmsg0(200, "wait for next job\n"); /* Main loop -- call scheduler to get next job to run */ while ( (jcr = wait_for_next_job(runjob)) ) { run_job(jcr); /* run job */ free_jcr(jcr); /* release jcr */ set_jcr_in_tsd(INVALID_JCR); if (runjob) { /* command line, run a single job? */ break; /* yes, terminate */ } } terminate_dird(0); bail_out: return 0; }
/* * This is the thread that walks the watchdog queue * and when a queue item fires, the callback is * invoked. If it is a one shot, the queue item * is moved to the inactive queue. */ extern "C" void *watchdog_thread(void *arg) { struct timespec timeout; struct timeval tv; struct timezone tz; utime_t next_time; set_jcr_in_tsd(INVALID_JCR); Dmsg0(800, "NicB-reworked watchdog thread entered\n"); while (!quit) { watchdog_t *p; /* * * NOTE. lock_jcr_chain removed, but the message below * was left until we are sure there are no deadlocks. * * We lock the jcr chain here because a good number of the * callback routines lock the jcr chain. We need to lock * it here *before* the watchdog lock because the SD message * thread first locks the jcr chain, then when closing the * job locks the watchdog chain. If the two threads do not * lock in the same order, we get a deadlock -- each holds * the other's needed lock. */ wd_lock(); walk_list: watchdog_time = time(NULL); next_time = watchdog_time + watchdog_sleep_time; foreach_dlist(p, wd_queue) { if (p->next_fire <= watchdog_time) { /* Run the callback */ Dmsg2(3400, "Watchdog callback p=0x%p fire=%d\n", p, p->next_fire); p->callback(p); /* Reschedule (or move to inactive list if it's a one-shot timer) */ if (p->one_shot) { wd_queue->remove(p); wd_inactive->append(p); goto walk_list; } else { p->next_fire = watchdog_time + p->interval; } } if (p->next_fire <= next_time) { next_time = p->next_fire; } } wd_unlock(); /* * Wait sleep time or until someone wakes us */ gettimeofday(&tv, &tz); timeout.tv_nsec = tv.tv_usec * 1000; timeout.tv_sec = tv.tv_sec + next_time - time(NULL); while (timeout.tv_nsec >= 1000000000) { timeout.tv_nsec -= 1000000000; timeout.tv_sec++; } Dmsg1(1900, "pthread_cond_timedwait %d\n", timeout.tv_sec - tv.tv_sec); /* Note, this unlocks mutex during the sleep */ P(timer_mutex); pthread_cond_timedwait(&timer, &timer_mutex, &timeout); V(timer_mutex); } Dmsg0(800, "NicB-reworked watchdog thread exited\n"); return NULL; }
void b_free_jcr(const char *file, int line, JCR *jcr) { struct s_last_job *je; Dmsg3(dbglvl, "Enter free_jcr jid=%u from %s:%d\n", jcr->JobId, file, line); #else void free_jcr(JCR *jcr) { struct s_last_job *je; Dmsg3(dbglvl, "Enter free_jcr jid=%u use_count=%d Job=%s\n", jcr->JobId, jcr->use_count(), jcr->Job); #endif lock_jcr_chain(); jcr->dec_use_count(); /* decrement use count */ if (jcr->use_count() < 0) { Jmsg2(jcr, M_ERROR, 0, _("JCR use_count=%d JobId=%d\n"), jcr->use_count(), jcr->JobId); } if (jcr->JobId > 0) { Dmsg3(dbglvl, "Dec free_jcr jid=%u use_count=%d Job=%s\n", jcr->JobId, jcr->use_count(), jcr->Job); } if (jcr->use_count() > 0) { /* if in use */ unlock_jcr_chain(); return; } if (jcr->JobId > 0) { Dmsg3(dbglvl, "remove jcr jid=%u use_count=%d Job=%s\n", jcr->JobId, jcr->use_count(), jcr->Job); } remove_jcr(jcr); /* remove Jcr from chain */ unlock_jcr_chain(); dequeue_messages(jcr); job_end_pop(jcr); /* pop and call hooked routines */ Dmsg1(dbglvl, "End job=%d\n", jcr->JobId); /* * Keep some statistics */ switch (jcr->getJobType()) { case JT_BACKUP: case JT_VERIFY: case JT_RESTORE: case JT_MIGRATE: case JT_COPY: case JT_ADMIN: /* * Keep list of last jobs, but not Console where JobId==0 */ if (jcr->JobId > 0) { lock_last_jobs_list(); num_jobs_run++; je = (struct s_last_job *)malloc(sizeof(struct s_last_job)); memset(je, 0, sizeof(struct s_last_job)); /* zero in case unset fields */ je->Errors = jcr->JobErrors; je->JobType = jcr->getJobType(); je->JobId = jcr->JobId; je->VolSessionId = jcr->VolSessionId; je->VolSessionTime = jcr->VolSessionTime; bstrncpy(je->Job, jcr->Job, sizeof(je->Job)); je->JobFiles = jcr->JobFiles; je->JobBytes = jcr->JobBytes; je->JobStatus = jcr->JobStatus; je->JobLevel = jcr->getJobLevel(); je->start_time = jcr->start_time; je->end_time = time(NULL); if (!last_jobs) { init_last_jobs_list(); } last_jobs->append(je); if (last_jobs->size() > max_last_jobs) { je = (struct s_last_job *)last_jobs->first(); last_jobs->remove(je); free(je); } unlock_last_jobs_list(); } break; default: break; } close_msg(jcr); /* close messages for this job */ if (jcr->daemon_free_jcr) { jcr->daemon_free_jcr(jcr); /* call daemon free routine */ } free_common_jcr(jcr); close_msg(NULL); /* flush any daemon messages */ Dmsg0(dbglvl, "Exit free_jcr\n"); } /* * Remove jcr from thread specific data, but * but make sure it is us who are attached. */ void remove_jcr_from_tsd(JCR *jcr) { JCR *tjcr = get_jcr_from_tsd(); if (tjcr == jcr) { set_jcr_in_tsd(INVALID_JCR); } }
void *workq_server(void *arg) { struct timespec timeout; workq_t *wq = (workq_t *)arg; workq_ele_t *we; int stat, timedout; Dmsg0(1400, "Start workq_server\n"); P(wq->mutex); set_jcr_in_tsd(INVALID_JCR); for (;;) { struct timeval tv; struct timezone tz; Dmsg0(1400, "Top of for loop\n"); timedout = 0; Dmsg0(1400, "gettimeofday()\n"); gettimeofday(&tv, &tz); timeout.tv_nsec = 0; timeout.tv_sec = tv.tv_sec + 2; while (wq->first == NULL && !wq->quit) { /* * Wait 2 seconds, then if no more work, exit */ Dmsg0(1400, "pthread_cond_timedwait()\n"); #ifdef xxxxxxxxxxxxxxxx_was_HAVE_CYGWIN /* CYGWIN dies with a page fault the second * time that pthread_cond_timedwait() is called * so fake it out. */ P(wq->mutex); stat = ETIMEDOUT; #else stat = pthread_cond_timedwait(&wq->work, &wq->mutex, &timeout); #endif Dmsg1(1400, "timedwait=%d\n", stat); if (stat == ETIMEDOUT) { timedout = 1; break; } else if (stat != 0) { /* This shouldn't happen */ Dmsg0(1400, "This shouldn't happen\n"); wq->num_workers--; V(wq->mutex); return NULL; } } we = wq->first; if (we != NULL) { wq->first = we->next; if (wq->last == we) { wq->last = NULL; } V(wq->mutex); /* Call user's routine here */ Dmsg0(1400, "Calling user engine.\n"); wq->engine(we->data); Dmsg0(1400, "Back from user engine.\n"); free(we); /* release work entry */ Dmsg0(1400, "relock mutex\n"); P(wq->mutex); Dmsg0(1400, "Done lock mutex\n"); } /* * If no more work request, and we are asked to quit, then do it */ if (wq->first == NULL && wq->quit) { wq->num_workers--; if (wq->num_workers == 0) { Dmsg0(1400, "Wake up destroy routine\n"); /* Wake up destroy routine if he is waiting */ pthread_cond_broadcast(&wq->work); } Dmsg0(1400, "Unlock mutex\n"); V(wq->mutex); Dmsg0(1400, "Return from workq_server\n"); return NULL; } Dmsg0(1400, "Check for work request\n"); /* * If no more work requests, and we waited long enough, quit */ Dmsg1(1400, "wq->first==NULL = %d\n", wq->first==NULL); Dmsg1(1400, "timedout=%d\n", timedout); if (wq->first == NULL && timedout) { Dmsg0(1400, "break big loop\n"); wq->num_workers--; break; } Dmsg0(1400, "Loop again\n"); } /* end of big for loop */ Dmsg0(1400, "unlock mutex\n"); V(wq->mutex); Dmsg0(1400, "End workq_server\n"); return NULL; }
/* * Director requests us to start a job * Basic tasks done here: * - We pickup the JobId to be run from the Director. * - We pickup the device, media, and pool from the Director * - Wait for a connection from the File Daemon (FD) * - Accept commands from the FD (i.e. run the job) * - Return when the connection is terminated or * there is an error. */ bool job_cmd(JCR *jcr) { int32_t JobId; char sd_auth_key[200]; char spool_size[30]; char seed[100]; BSOCK *dir = jcr->dir_bsock; POOL_MEM job_name, client_name, job, fileset_name, fileset_md5; int32_t JobType, level, spool_attributes, no_attributes, spool_data; int32_t write_part_after_job, PreferMountedVols; int32_t rerunning; int32_t is_client; int stat; JCR *ojcr; /* * Get JobId and permissions from Director */ Dmsg1(100, "<dird: %s", dir->msg); bstrncpy(spool_size, "0", sizeof(spool_size)); stat = sscanf(dir->msg, jobcmd, &JobId, job.c_str(), job_name.c_str(), client_name.c_str(), &JobType, &level, fileset_name.c_str(), &no_attributes, &spool_attributes, fileset_md5.c_str(), &spool_data, &write_part_after_job, &PreferMountedVols, spool_size, &rerunning, &jcr->VolSessionId, &jcr->VolSessionTime, &is_client, &sd_auth_key); if (stat != 19) { pm_strcpy(jcr->errmsg, dir->msg); dir->fsend(BAD_job, stat, jcr->errmsg); Dmsg1(100, ">dird: %s", dir->msg); jcr->setJobStatus(JS_ErrorTerminated); return false; } jcr->rerunning = rerunning; jcr->sd_client = is_client; if (is_client) { jcr->sd_auth_key = bstrdup(sd_auth_key); } Dmsg3(100, "rerunning=%d VolSesId=%d VolSesTime=%d\n", jcr->rerunning, jcr->VolSessionId, jcr->VolSessionTime); /* * Since this job could be rescheduled, we * check to see if we have it already. If so * free the old jcr and use the new one. */ ojcr = get_jcr_by_full_name(job.c_str()); if (ojcr && !ojcr->authenticated) { Dmsg2(100, "Found ojcr=0x%x Job %s\n", (unsigned)(intptr_t)ojcr, job.c_str()); free_jcr(ojcr); } jcr->JobId = JobId; Dmsg2(800, "Start JobId=%d %p\n", JobId, jcr); set_jcr_in_tsd(jcr); /* * If job rescheduled because previous was incomplete, * the Resched flag is set and VolSessionId and VolSessionTime * are given to us (same as restarted job). */ if (!jcr->rerunning) { jcr->VolSessionId = newVolSessionId(); jcr->VolSessionTime = VolSessionTime; } bstrncpy(jcr->Job, job, sizeof(jcr->Job)); unbash_spaces(job_name); jcr->job_name = get_pool_memory(PM_NAME); pm_strcpy(jcr->job_name, job_name); unbash_spaces(client_name); jcr->client_name = get_pool_memory(PM_NAME); pm_strcpy(jcr->client_name, client_name); unbash_spaces(fileset_name); jcr->fileset_name = get_pool_memory(PM_NAME); pm_strcpy(jcr->fileset_name, fileset_name); jcr->setJobType(JobType); jcr->setJobLevel(level); jcr->no_attributes = no_attributes; jcr->spool_attributes = spool_attributes; jcr->spool_data = spool_data; jcr->spool_size = str_to_int64(spool_size); jcr->write_part_after_job = write_part_after_job; jcr->fileset_md5 = get_pool_memory(PM_NAME); pm_strcpy(jcr->fileset_md5, fileset_md5); jcr->PreferMountedVols = PreferMountedVols; jcr->authenticated = false; /* * Pass back an authorization key for the File daemon */ if (jcr->sd_client) { bstrncpy(sd_auth_key, "xxx", 3); } else { bsnprintf(seed, sizeof(seed), "%p%d", jcr, JobId); make_session_key(sd_auth_key, seed, 1); } dir->fsend(OKjob, jcr->VolSessionId, jcr->VolSessionTime, sd_auth_key); Dmsg2(150, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg); /* If not client, set key, otherwise it is already set */ if (!jcr->sd_client) { jcr->sd_auth_key = bstrdup(sd_auth_key); memset(sd_auth_key, 0, sizeof(sd_auth_key)); } new_plugins(jcr); /* instantiate the plugins */ generate_daemon_event(jcr, "JobStart"); generate_plugin_event(jcr, bsdEventJobStart, (void *)"JobStart"); return true; }