/* * Run a File daemon Job -- File daemon already authorized * Director sends us this command. * * Basic task here is: * - Read a command from the File daemon * - Execute it * */ void run_job(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; char ec1[30]; dir->set_jcr(jcr); Dmsg1(120, "Start run Job=%s\n", jcr->Job); dir->fsend(Job_start, jcr->Job); jcr->start_time = time(NULL); jcr->run_time = jcr->start_time; jcr->sendJobStatus(JS_Running); do_fd_commands(jcr); jcr->end_time = time(NULL); dequeue_messages(jcr); /* send any queued messages */ jcr->setJobStatus(JS_Terminated); generate_plugin_event(jcr, bsdEventJobEnd); dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors); dir->signal(BNET_EOD); /* send EOD to Director daemon */ free_plugins(jcr); /* release instantiated plugins */ }
/* * Free the Job Control Record if no one is still using it. * Called from main free_jcr() routine in src/lib/jcr.c so * that we can do our Director specific cleanup of the jcr. */ void dird_free_jcr(JCR *jcr) { Dmsg0(200, "Start dird free_jcr\n"); dird_free_jcr_pointers(jcr); if (jcr->term_wait_inited) { pthread_cond_destroy(&jcr->term_wait); jcr->term_wait_inited = false; } if (jcr->nextrun_ready_inited) { pthread_cond_destroy(&jcr->nextrun_ready); jcr->nextrun_ready_inited = false; } if (jcr->db_batch) { db_sql_close_pooled_connection(jcr, jcr->db_batch); jcr->db_batch = NULL; jcr->batch_started = false; } if (jcr->db) { db_sql_close_pooled_connection(jcr, jcr->db); jcr->db = NULL; } if (jcr->restore_tree_root) { free_tree(jcr->restore_tree_root); } if (jcr->bsr) { free_bsr(jcr->bsr); jcr->bsr = NULL; } free_and_null_pool_memory(jcr->stime); free_and_null_pool_memory(jcr->fname); free_and_null_pool_memory(jcr->res.pool_source); free_and_null_pool_memory(jcr->res.npool_source); free_and_null_pool_memory(jcr->res.rpool_source); free_and_null_pool_memory(jcr->res.wstore_source); free_and_null_pool_memory(jcr->res.rstore_source); free_and_null_pool_memory(jcr->res.catalog_source); /* * Delete lists setup to hold storage pointers */ free_rwstorage(jcr); jcr->job_end_push.destroy(); if (jcr->JobId != 0) { write_state_file(director->working_directory, "bareos-dir", get_first_port_host_order(director->DIRaddrs)); } free_plugins(jcr); /* release instantiated plugins */ Dmsg0(200, "End dird free_jcr\n"); }
int wsman_plugins_unload(WsManListenerH *listener) { free_plugins(listener->plugins); // list_destroy(listener->plugins); return 0; }
bool finish_cmd(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; char ec1[30]; /* * See if the Job has a certain protocol. Some protocols allow the * finish cmd some do not (Native backup for example does NOT) */ switch (jcr->getJobProtocol()) { case PT_NDMP: Dmsg1(200, "Finish_cmd: %s", jcr->dir_bsock->msg); jcr->end_time = time(NULL); dequeue_messages(jcr); /* send any queued messages */ jcr->setJobStatus(JS_Terminated); switch (jcr->getJobType()) { case JT_BACKUP: end_of_ndmp_backup(jcr); break; case JT_RESTORE: end_of_ndmp_restore(jcr); break; default: break; } generate_plugin_event(jcr, bsdEventJobEnd); dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors); dir->signal(BNET_EOD); /* send EOD to Director daemon */ free_plugins(jcr); /* release instantiated plugins */ Dmsg2(800, "Done jid=%d %p\n", jcr->JobId, jcr); return false; /* Continue DIR session ? */ default: Dmsg1(200, "Finish_cmd: %s", jcr->dir_bsock->msg); Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s tries to use finish cmd while not part of protocol.\n"), (uint32_t)jcr->JobId, jcr->Job); return false; /* Continue DIR session ? */ } }
/* * Free the Job Control Record if no one is still using it. * Called from main free_jcr() routine in src/lib/jcr.c so * that we can do our Director specific cleanup of the jcr. */ void dird_free_jcr(JCR *jcr) { Dmsg0(200, "Start dird free_jcr\n"); dird_free_jcr_pointers(jcr); if (jcr->term_wait_inited) { pthread_cond_destroy(&jcr->term_wait); jcr->term_wait_inited = false; } if (jcr->db_batch) { db_close_database(jcr, jcr->db_batch); jcr->db_batch = NULL; jcr->batch_started = false; } if (jcr->db) { db_close_database(jcr, jcr->db); jcr->db = NULL; } free_and_null_pool_memory(jcr->stime); free_and_null_pool_memory(jcr->fname); free_and_null_pool_memory(jcr->pool_source); free_and_null_pool_memory(jcr->catalog_source); free_and_null_pool_memory(jcr->rpool_source); free_and_null_pool_memory(jcr->wstore_source); free_and_null_pool_memory(jcr->rstore_source); /* Delete lists setup to hold storage pointers */ free_rwstorage(jcr); jcr->job_end_push.destroy(); if (jcr->JobId != 0) write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs)); free_plugins(jcr); /* release instantiated plugins */ Dmsg0(200, "End dird free_jcr\n"); }
void plug_sys_free(void) { free_plugins(); }
/* * Read Data and commit to new job. */ bool do_mac_run(JCR *jcr) { DEVICE *dev; char ec1[50]; const char *Type; bool ok = true; BSOCK *dir = jcr->dir_bsock; switch(jcr->getJobType()) { case JT_MIGRATE: Type = "Migration"; break; case JT_ARCHIVE: Type = "Archive"; break; case JT_COPY: Type = "Copy"; break; case JT_BACKUP: Type = "Virtual Backup"; break; default: Type = "Unknown"; break; } Dmsg0(20, "Start read data.\n"); if (jcr->NumReadVolumes == 0) { Jmsg(jcr, M_FATAL, 0, _("No Volume names found for %s.\n"), Type); goto bail_out; } /* * Check autoinflation/autodeflation settings. */ check_auto_xflation(jcr); /* * See if we perform both read and write or read only. */ if (jcr->remote_replicate) { BSOCK *sd; if (!jcr->read_dcr) { Jmsg(jcr, M_FATAL, 0, _("Read device not properly initialized.\n")); goto bail_out; } Dmsg1(100, "read_dcr=%p\n", jcr->read_dcr); Dmsg3(200, "Found %d volumes names for %s. First=%s\n", jcr->NumReadVolumes, Type, jcr->VolList->VolumeName); /* * Ready devices for reading. */ if (!acquire_device_for_read(jcr->read_dcr)) { ok = false; goto bail_out; } Dmsg2(200, "===== After acquire pos %u:%u\n", jcr->read_dcr->dev->file, jcr->read_dcr->dev->block_num); jcr->sendJobStatus(JS_Running); /* * Set network buffering. */ sd = jcr->store_bsock; if (!sd->set_buffer_size(me->max_network_buffer_size, BNET_SETBUF_WRITE)) { Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size SD->SD.\n")); ok = false; goto bail_out; } /* * Let the remote SD know we are about to start the replication. */ sd->fsend(start_replicate); Dmsg1(110, ">stored: %s", sd->msg); /* * Expect to receive back the Ticket number. */ if (bget_msg(sd) >= 0) { Dmsg1(110, "<stored: %s", sd->msg); if (sscanf(sd->msg, OK_start_replicate, &jcr->Ticket) != 1) { Jmsg(jcr, M_FATAL, 0, _("Bad response to start replicate: %s\n"), sd->msg); goto bail_out; } Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket); } else { Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to start replicate command\n")); goto bail_out; } /* * Let the remote SD know we are now really going to send the data. */ sd->fsend(replicate_data, jcr->Ticket); Dmsg1(110, ">stored: %s", sd->msg); /* * Expect to get response to the replicate data cmd from Storage daemon */ if (!response(jcr, sd, OK_data, "replicate data")) { ok = false; goto bail_out; } /* * Read all data and send it to remote SD. */ ok = read_records(jcr->read_dcr, clone_record_to_remote_sd, mount_next_read_volume); /* * Send the last EOD to close the last data transfer and a next EOD to * signal the remote we are done. */ if (!sd->signal(BNET_EOD) || !sd->signal(BNET_EOD)) { if (!jcr->is_job_canceled()) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); } goto bail_out; } /* * Expect to get response that the replicate data succeeded. */ if (!response(jcr, sd, OK_replicate, "replicate data")) { ok = false; goto bail_out; } /* * End replicate session. */ sd->fsend(end_replicate); Dmsg1(110, ">stored: %s", sd->msg); /* * Expect to get response to the end replicate cmd from Storage daemon */ if (!response(jcr, sd, OK_end_replicate, "end replicate")) { ok = false; goto bail_out; } /* Inform Storage daemon that we are done */ sd->signal(BNET_TERMINATE); } else { if (!jcr->read_dcr || !jcr->dcr) { Jmsg(jcr, M_FATAL, 0, _("Read and write devices not properly initialized.\n")); goto bail_out; } Dmsg2(100, "read_dcr=%p write_dcr=%p\n", jcr->read_dcr, jcr->dcr); Dmsg3(200, "Found %d volumes names for %s. First=%s\n", jcr->NumReadVolumes, Type, jcr->VolList->VolumeName); /* * Ready devices for reading and writing. */ if (!acquire_device_for_read(jcr->read_dcr) || !acquire_device_for_append(jcr->dcr)) { ok = false; goto bail_out; } Dmsg2(200, "===== After acquire pos %u:%u\n", jcr->dcr->dev->file, jcr->dcr->dev->block_num); jcr->sendJobStatus(JS_Running); if (!begin_data_spool(jcr->dcr) ) { ok = false; goto bail_out; } if (!begin_attribute_spool(jcr)) { ok = false; goto bail_out; } jcr->dcr->VolFirstIndex = jcr->dcr->VolLastIndex = 0; jcr->run_time = time(NULL); set_start_vol_position(jcr->dcr); jcr->JobFiles = 0; /* * Read all data and make a local clone of it. */ ok = read_records(jcr->read_dcr, clone_record_internally, mount_next_read_volume); } bail_out: if (!ok) { jcr->setJobStatus(JS_ErrorTerminated); } if (!jcr->remote_replicate && jcr->dcr) { /* * Don't use time_t for job_elapsed as time_t can be 32 or 64 bits, * and the subsequent Jmsg() editing will break */ int32_t job_elapsed; dev = jcr->dcr->dev; Dmsg1(100, "ok=%d\n", ok); if (ok || dev->can_write()) { /* * Flush out final partial block of this session */ if (!jcr->dcr->write_block_to_device()) { Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"), dev->print_name(), dev->bstrerror()); Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n")); ok = false; } Dmsg2(200, "Flush block to device pos %u:%u\n", dev->file, dev->block_num); } if (!ok) { discard_data_spool(jcr->dcr); } else { /* * Note: if commit is OK, the device will remain blocked */ commit_data_spool(jcr->dcr); } job_elapsed = time(NULL) - jcr->run_time; if (job_elapsed <= 0) { job_elapsed = 1; } Jmsg(jcr, M_INFO, 0, _("Elapsed time=%02d:%02d:%02d, Transfer rate=%s Bytes/second\n"), job_elapsed / 3600, job_elapsed % 3600 / 60, job_elapsed % 60, edit_uint64_with_suffix(jcr->JobBytes / job_elapsed, ec1)); /* * Release the device -- and send final Vol info to DIR */ release_device(jcr->dcr); if (!ok || job_canceled(jcr)) { discard_attribute_spool(jcr); } else { commit_attribute_spool(jcr); } } if (jcr->read_dcr) { if (!release_device(jcr->read_dcr)) { ok = false; } } jcr->sendJobStatus(); /* update director */ Dmsg0(30, "Done reading.\n"); jcr->end_time = time(NULL); dequeue_messages(jcr); /* send any queued messages */ if (ok) { jcr->setJobStatus(JS_Terminated); } generate_plugin_event(jcr, bsdEventJobEnd); dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors); Dmsg4(100, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, ec1); dir->signal(BNET_EOD); /* send EOD to Director daemon */ free_plugins(jcr); /* release instantiated plugins */ return false; /* Continue DIR session ? */ }
/* * Run a Storage daemon replicate Job -- Wait for remote Storage daemon * to connect and authenticate it we then will get a wakeup sign using * the job_start_wait conditional * * Director sends us this command. * * Basic task here is: * - Read a command from the Storage daemon * - Execute it */ bool do_listen_run(JCR *jcr) { char ec1[30]; int errstat = 0; struct timeval tv; struct timezone tz; struct timespec timeout; BSOCK *dir = jcr->dir_bsock; jcr->sendJobStatus(JS_WaitSD); /* wait for SD to connect */ gettimeofday(&tv, &tz); timeout.tv_nsec = tv.tv_usec * 1000; timeout.tv_sec = tv.tv_sec + me->client_wait; Dmsg3(50, "%s waiting %d sec for SD to contact SD key=%s\n", jcr->Job, (int)(timeout.tv_sec-time(NULL)), jcr->sd_auth_key); Dmsg2(800, "Wait SD for jid=%d %p\n", jcr->JobId, jcr); /* * Wait for the Storage daemon to contact us to start the Job, * when he does, we will be released, unless the 30 minutes expires. */ P(mutex); while (!jcr->authenticated && !job_canceled(jcr)) { errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout); if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) { break; } Dmsg1(800, "=== Auth cond errstat=%d\n", errstat); } Dmsg3(50, "Auth=%d canceled=%d errstat=%d\n", jcr->authenticated, job_canceled(jcr), errstat); V(mutex); Dmsg2(800, "Auth fail or cancel for jid=%d %p\n", jcr->JobId, jcr); Dmsg1(120, "Start run Job=%s\n", jcr->Job); dir->fsend(Job_start, jcr->Job); jcr->start_time = time(NULL); jcr->run_time = jcr->start_time; jcr->sendJobStatus(JS_Running); /* * See if we need to limit the inbound bandwidth. */ if (me->max_bandwidth_per_job && jcr->store_bsock) { jcr->store_bsock->set_bwlimit(me->max_bandwidth_per_job); if (me->allow_bw_bursting) { jcr->store_bsock->set_bwlimit_bursting(); } } do_sd_commands(jcr); jcr->end_time = time(NULL); dequeue_messages(jcr); /* send any queued messages */ jcr->setJobStatus(JS_Terminated); generate_plugin_event(jcr, bsdEventJobEnd); dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors); dir->signal(BNET_EOD); /* send EOD to Director daemon */ free_plugins(jcr); /* release instantiated plugins */ /* * After a listen cmd we are done e.g. return false. */ return false; }