Beispiel #1
33
static void do_close(JCR *jcr)
{
    release_device(jcr->dcr);
    free_attr(attr);
    free_record(rec);
    free_jcr(jcr);
    dev->term();
}
Beispiel #2
0
/*
 * After receiving a connection (in dircmd.c) if it is
 * from the Storage daemon, this routine is called.
 */
void *handle_stored_connection(BSOCK *sd, char *job_name)
{
   JCR *jcr;

/*
 * With the following bmicrosleep on, running the
 * SD under the debugger fails.
 */
// bmicrosleep(0, 50000);             /* wait 50 millisecs */
   if (!(jcr = get_jcr_by_full_name(job_name))) {
      Jmsg1(NULL, M_FATAL, 0, _("SD connect failed: Job name not found: %s\n"), job_name);
      Dmsg1(3, "**** Job \"%s\" not found.\n", job_name);
      sd->close();
      delete sd;
      return NULL;
   }

   Dmsg1(50, "Found Job %s\n", job_name);

   if (jcr->authenticated) {
      Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s already authenticated.\n"),
         (uint32_t)jcr->JobId, jcr->Job);
      Dmsg2(50, "Hey!!!! JobId %u Job %s already authenticated.\n",
         (uint32_t)jcr->JobId, jcr->Job);
      sd->close();
      delete sd;
      free_jcr(jcr);
      return NULL;
   }

   jcr->store_bsock = sd;
   jcr->store_bsock->set_jcr(jcr);

   /*
    * Authenticate the Storage daemon
    */
   if (jcr->authenticated || !authenticate_storagedaemon(jcr)) {
      Dmsg1(50, "Authentication failed Job %s\n", jcr->Job);
      Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate Storage daemon\n"));
   } else {
      jcr->authenticated = true;
      Dmsg2(50, "OK Authentication jid=%u Job %s\n", (uint32_t)jcr->JobId, jcr->Job);
   }

   if (!jcr->authenticated) {
      jcr->setJobStatus(JS_ErrorTerminated);
   }

   pthread_cond_signal(&jcr->job_start_wait); /* wake waiting job */
   free_jcr(jcr);

   return NULL;
}
Beispiel #3
0
/*
 * After receiving a connection (in dircmd.c) if it is
 *   from the File daemon, this routine is called.
 */
void handle_filed_connection(BSOCK *fd, char *job_name, int fd_version,
        int sd_version)
{
   JCR *jcr;

   if (!(jcr=get_jcr_by_full_name(job_name))) {
      Jmsg1(NULL, M_FATAL, 0, _("FD connect failed: Job name not found: %s\n"), job_name);
      Dmsg1(3, "**** Job \"%s\" not found.\n", job_name);
      fd->destroy();
      return;
   }

   Dmsg1(100, "Found Filed Job %s\n", job_name);

   if (jcr->authenticated) {
      Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s already authenticated.\n"),
         (uint32_t)jcr->JobId, jcr->Job);
      Dmsg2(050, "Hey!!!! JobId %u Job %s already authenticated.\n",
         (uint32_t)jcr->JobId, jcr->Job);
      fd->destroy();
      free_jcr(jcr);
      return;
   }

   jcr->file_bsock = fd;
   jcr->file_bsock->set_jcr(jcr);
   jcr->FDVersion = fd_version;
   jcr->SDVersion = sd_version;
   Dmsg2(050, "fd_version=%d sd_version=%d\n", fd_version, sd_version);

   /*
    * Authenticate the File daemon
    */
   if (jcr->authenticated || !authenticate_filed(jcr)) {
      Dmsg1(50, "Authentication failed Job %s\n", jcr->Job);
      Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate File daemon\n"));
   } else {
      jcr->authenticated = true;
      Dmsg2(050, "OK Authentication jid=%u Job %s\n", (uint32_t)jcr->JobId, jcr->Job);
   }

   if (!jcr->authenticated) {
      jcr->setJobStatus(JS_ErrorTerminated);
   }
   Dmsg3(050, "=== Auth OK, unblock Job %s jid=%d sd_ver=%d\n", job_name, jcr->JobId, sd_version);
   if (sd_version > 0) {
      jcr->sd_client = true;
   }
   pthread_cond_signal(&jcr->job_start_wait); /* wake waiting job */
   free_jcr(jcr);
   return;
}
Beispiel #4
0
/*
 * Cancel a running job on a storage daemon. Used by the interactive cancel
 * command to cancel a JobId on a Storage Daemon this can be used when the
 * Director already removed the Job and thinks it finished but the Storage
 * Daemon still thinks its active.
 */
bool cancel_storage_daemon_job(UAContext *ua, STORERES *store, char *JobId)
{
   BSOCK *sd;
   JCR *control_jcr;

   control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);

   control_jcr->res.wstore = store;
   if (!connect_to_storage_daemon(control_jcr, 10, me->SDConnectTimeout, true)) {
      ua->error_msg(_("Failed to connect to Storage daemon.\n"));
   }

   Dmsg0(200, "Connected to storage daemon\n");
   sd = control_jcr->store_bsock;
   sd->fsend("cancel Job=%s\n", JobId);
   while (sd->recv() >= 0) {
      ua->send_msg("%s", sd->msg);
   }
   sd->signal(BNET_TERMINATE);
   sd->close();
   control_jcr->store_bsock = NULL;

   free_jcr(control_jcr);

   return true;
}
Beispiel #5
0
/*
 * Release last jcr referenced
 */
void jcr_walk_end(JCR *jcr)
{
    if (jcr) {
        if (jcr->JobId > 0) {
            Dmsg3(dbglvl, "Free walk_end jid=%u use_count=%d Job=%s\n",
                  jcr->JobId, jcr->use_count(), jcr->Job);
        }
        free_jcr(jcr);
    }
}
Beispiel #6
0
static void do_extract(char *devname)
{
   struct stat statp;

   enable_backup_privileges(NULL, 1);

   jcr = setup_jcr("bextract", devname, bsr, director, VolumeName, 1); /* acquire for read */
   if (!jcr) {
      exit(1);
   }
   dev = jcr->read_dcr->dev;
   if (!dev) {
      exit(1);
   }
   dcr = jcr->read_dcr;

   /* Make sure where directory exists and that it is a directory */
   if (stat(where, &statp) < 0) {
      berrno be;
      Emsg2(M_ERROR_TERM, 0, _("Cannot stat %s. It must exist. ERR=%s\n"),
         where, be.bstrerror());
   }
   if (!S_ISDIR(statp.st_mode)) {
      Emsg1(M_ERROR_TERM, 0, _("%s must be a directory.\n"), where);
   }

   free(jcr->where);
   jcr->where = bstrdup(where);
   attr = new_attr(jcr);

   compress_buf = get_memory(compress_buf_size);

   acl_data.last_fname = get_pool_memory(PM_FNAME);
   xattr_data.last_fname = get_pool_memory(PM_FNAME);

   read_records(dcr, record_cb, mount_next_read_volume);
   /* If output file is still open, it was the last one in the
    * archive since we just hit an end of file, so close the file.
    */
   if (is_bopen(&bfd)) {
      set_attributes(jcr, attr, &bfd);
   }
   free_attr(attr);

   free_pool_memory(acl_data.last_fname);
   free_pool_memory(xattr_data.last_fname);

   clean_device(jcr->dcr);
   dev->term();
   free_dcr(dcr);
   free_jcr(jcr);

   printf(_("%u files restored.\n"), num_files);
   return;
}
Beispiel #7
0
void cancel_storage_daemon_job(JCR *jcr)
{
   if (jcr->sd_canceled) { 
      return;                   /* cancel only once */
   }

   UAContext *ua = new_ua_context(jcr);
   JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
   BSOCK *sd;

   ua->jcr = control_jcr;
   if (jcr->store_bsock) {
      if (!ua->jcr->wstorage) {
         if (jcr->rstorage) {
            copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
         } else {
            copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
         }
      } else {
         USTORE store;
         if (jcr->rstorage) {
            store.store = jcr->rstore;
         } else {
            store.store = jcr->wstore;
         }
         set_wstorage(ua->jcr, &store);
      }

      if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
         goto bail_out;
      }
      Dmsg0(200, "Connected to storage daemon\n");
      sd = ua->jcr->store_bsock;
      sd->fsend("cancel Job=%s\n", jcr->Job);
      while (sd->recv() >= 0) {
      }
      sd->signal(BNET_TERMINATE);
      sd->close();
      ua->jcr->store_bsock = NULL;
      jcr->sd_canceled = true;
      jcr->store_bsock->set_timed_out();
      jcr->store_bsock->set_terminated();
      sd_msg_thread_send_signal(jcr, TIMEOUT_SIGNAL);
      jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
   }
bail_out:
   free_jcr(control_jcr);
   free_ua_context(ua);
}
Beispiel #8
0
/*
 * Get next jcr from chain, and release current one
 */
JCR *jcr_walk_next(JCR *prev_jcr)
{
    JCR *jcr;

    lock_jcr_chain();
    jcr = (JCR *)jcrs->next(prev_jcr);
    if (jcr) {
        jcr->inc_use_count();
        if (jcr->JobId > 0) {
            Dmsg3(dbglvl, "Inc walk_next jid=%u use_count=%d Job=%s\n",
                  jcr->JobId, jcr->use_count(), jcr->Job);
        }
    }
    unlock_jcr_chain();
    if (prev_jcr) {
        free_jcr(prev_jcr);
    }
    return jcr;
}
Beispiel #9
0
static PyObject *job_cancel(PyObject *self, PyObject *args)
{
   JobId_t JobId = 0;
   JCR *jcr;
   bool found = false;

   if (!PyArg_ParseTuple(args, "i:cancel", &JobId)) {
      Dmsg0(000, "Parse tuple error in job_write\n");
      return NULL;
   }
   foreach_jcr(jcr) {
      if (jcr->JobId == 0) {
         continue;
      }
      if (jcr->JobId == JobId) {
         found = true;
         break;
      }
   }
   /* endeach_jcr(jcr) not needed because freed below */

   if (!found) {
      /* ***FIXME*** raise exception */
      return NULL;
   }
// PyEval_ReleaseLock();
   UAContext *ua = new_ua_context(jcr);
   ua->batch = true;
   if (!cancel_job(ua, jcr)) {
      /* ***FIXME*** raise exception */
      return NULL;
   }
   free_ua_context(ua);
   free_jcr(jcr);
// PyEval_AcquireLock();   
   Py_INCREF(Py_None);
   return Py_None;
}
Beispiel #10
0
/*
 * Cancel a running job on a storage daemon. System invoked
 * non interactive version this builds a ua context and calls
 * the interactive one with the silent flag set.
 */
void cancel_storage_daemon_job(JCR *jcr)
{
   UAContext *ua;
   JCR *control_jcr;

   if (jcr->sd_canceled) {
      return;                   /* cancel only once */
   }

   ua = new_ua_context(jcr);
   control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);

   ua->jcr = control_jcr;
   if (jcr->store_bsock) {
      if (!cancel_storage_daemon_job(ua, jcr, true)) {
         goto bail_out;
      }
   }

bail_out:
   free_jcr(control_jcr);
   free_ua_context(ua);
}
Beispiel #11
0
static void job_monitor_destructor(watchdog_t *self)
{
   JCR *control_jcr = (JCR *)self->data;

   free_jcr(control_jcr);
}
Beispiel #12
0
Datei: dird.c Projekt: AlD/bareos
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;
}
Beispiel #13
0
void *handle_stored_connection(BSOCK *sd)
{
   JCR *jcr;
   char job_name[MAX_NAME_LENGTH];

   /*
    * Do a sanity check on the message received
    */
   if (sd->msglen < 25 || sd->msglen > 256) {
      Dmsg1(000, "<filed: %s", sd->msg);
      Emsg2(M_ERROR, 0, _("Invalid connection from %s. Len=%d\n"), sd->who(), sd->msglen);
      bmicrosleep(5, 0);   /* make user wait 5 seconds */
      sd->close();
      return NULL;
   }

   if (sscanf(sd->msg, "Hello Storage calling Start Job %127s", job_name) != 1) {
      char addr[64];
      char *who = bnet_get_peer(sd, addr, sizeof(addr)) ? sd->who() : addr;

      sd->msg[100] = 0;
      Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n", sd->who(), sd->msg);
      Jmsg2(NULL, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"), who, sd->msg);
      sd->close();
      return NULL;
   }

   if (!(jcr = get_jcr_by_full_name(job_name))) {
      Jmsg1(NULL, M_FATAL, 0, _("SD connect failed: Job name not found: %s\n"), job_name);
      Dmsg1(3, "**** Job \"%s\" not found.\n", job_name);
      sd->close();
      return NULL;
   }

   Dmsg1(50, "Found Job %s\n", job_name);

   jcr->store_bsock = sd;
   jcr->store_bsock->set_jcr(jcr);

   /*
    * Authenticate the Storage Daemon.
    */
   if (!authenticate_storagedaemon(jcr)) {
      Dmsg1(50, "Authentication failed Job %s\n", jcr->Job);
      Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate File daemon\n"));
      jcr->setJobStatus(JS_ErrorTerminated);
   } else {
      Dmsg2(50, "OK Authentication jid=%u Job %s\n", (uint32_t)jcr->JobId, jcr->Job);
   }

   if (!jcr->max_bandwidth) {
      if (jcr->director->max_bandwidth_per_job) {
         jcr->max_bandwidth = jcr->director->max_bandwidth_per_job;
      } else if (me->max_bandwidth_per_job) {
         jcr->max_bandwidth = me->max_bandwidth_per_job;
      }
   }

   sd->set_bwlimit(jcr->max_bandwidth);
   if (me->allow_bw_bursting) {
      sd->set_bwlimit_bursting();
   }

   free_jcr(jcr);

   return NULL;
}
Beispiel #14
0
int main (int argc, char *argv[])
{
   int ch;
   char *iVolumeName = NULL;
   char *oVolumeName = NULL;
   bool ignore_label_errors = false;
   bool ok;

   setlocale(LC_ALL, "");
   bindtextdomain("bacula", LOCALEDIR);
   textdomain("bacula");
   init_stack_dump();

   my_name_is(argc, argv, "bcopy");
   init_msg(NULL, NULL);

   while ((ch = getopt(argc, argv, "b:c:d:i:o:pvw:?")) != -1) {
      switch (ch) {
      case 'b':
         bsr = parse_bsr(NULL, optarg);
         break;

      case 'c':                    /* specify config 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 'i':                    /* input Volume name */
         iVolumeName = optarg;
         break;

      case 'o':                    /* output Volume name */
         oVolumeName = optarg;
         break;

      case 'p':
         ignore_label_errors = true;
         forge_on = true;
         break;

      case 'v':
         verbose++;
         break;

      case 'w':
         wd = optarg;
         break;

      case '?':
      default:
         usage();

      }
   }
   argc -= optind;
   argv += optind;

   if (argc != 2) {
      Pmsg0(0, _("Wrong number of arguments: \n"));
      usage();
   }

   OSDependentInit();

   working_directory = wd;

   if (configfile == NULL) {
      configfile = bstrdup(CONFIG_FILE);
   }

   config = new_config_parser();
   parse_sd_config(config, configfile, M_ERROR_TERM);

   /* Setup and acquire input device for reading */
   Dmsg0(100, "About to setup input jcr\n");
   in_jcr = setup_jcr("bcopy", argv[0], bsr, iVolumeName, 1); /* read device */
   if (!in_jcr) {
      exit(1);
   }
   in_jcr->ignore_label_errors = ignore_label_errors;
   in_dev = in_jcr->dcr->dev;
   if (!in_dev) {
      exit(1);
   }

   /* Setup output device for writing */
   Dmsg0(100, "About to setup output jcr\n");
   out_jcr = setup_jcr("bcopy", argv[1], bsr, oVolumeName, 0); /* no acquire */
   if (!out_jcr) {
      exit(1);
   }
   out_dev = out_jcr->dcr->dev;
   if (!out_dev) {
      exit(1);
   }
   Dmsg0(100, "About to acquire device for writing\n");
   /* For we must now acquire the device for writing */
   out_dev->r_dlock();
   if (out_dev->open(out_jcr->dcr, OPEN_READ_WRITE) < 0) {
      Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
      out_dev->dunlock();
      exit(1);
   }
   out_dev->dunlock();
   if (!acquire_device_for_append(out_jcr->dcr)) {
      free_jcr(in_jcr);
      exit(1);
   }
   out_block = out_jcr->dcr->block;

   ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume);

   if (ok || out_dev->can_write()) {
      if (!write_block_to_device(out_jcr->dcr)) {
         Pmsg0(000, _("Write of last block failed.\n"));
      }
   }

   Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records);

   free_jcr(in_jcr);
   free_jcr(out_jcr);

   in_dev->term();
   out_dev->term();
   return 0;
}
Beispiel #15
0
int backup_server(char *path) {
	Jcr *jcr = new_write_jcr();
	strcpy(jcr->backup_path, path);
	if (access(jcr->backup_path, 4) != 0) {
		free(jcr);
		puts("This path does not exist or can not be read!");
		return -1;
	}

	if (index_init() == FALSE) {
		return -1;
	}

	jcr->job_id = get_next_job_id();
	if (is_job_existed(jcr->job_id)) {
		printf("job existed!\n");
		free(jcr);
		return FAILURE;
	}

	if (jcr->job_id == 0) {
		destor_stat->simulation_level = simulation_level;
	} else {
		if (simulation_level <= SIMULATION_RECOVERY
				&& destor_stat->simulation_level >= SIMULATION_APPEND
				|| simulation_level >= SIMULATION_APPEND
						&& destor_stat->simulation_level <= SIMULATION_RECOVERY) {
			dprint(
					"the current simulation level is not matched with the destor stat!");
			return FAILURE;
		}
	}

	jcr->job_volume = create_job_volume(jcr->job_id);

	puts("==== backup begin ====");
	puts("==== transfering begin ====");

	struct timeval begin, end;
	gettimeofday(&begin, 0);
	if (backup(jcr) != 0) {
		free(jcr);
		return FAILURE;
	}
	gettimeofday(&end, 0);

	index_destroy();

	jcr->time = end.tv_sec - begin.tv_sec
			+ (double) (end.tv_usec - begin.tv_usec) / (1000 * 1000);
	puts("==== transferring end ====");

	printf("job id: %d\n", jcr->job_id);
	printf("backup path: %s\n", jcr->backup_path);
	printf("number of files: %d\n", jcr->file_num);
	//printf("number of chunks: %d\n", jcr->chunk_num);
	printf("number of dup chunks: %d\n", jcr->number_of_dup_chunks);
	printf("total size: %ld\n", jcr->job_size);
	printf("dedup size: %ld\n", jcr->dedup_size);
	printf("dedup efficiency: %.4f, %.4f\n",
			jcr->job_size != 0 ?
					(double) (jcr->dedup_size) / (double) (jcr->job_size) : 0,
			jcr->job_size / (double) (jcr->job_size - jcr->dedup_size));
	printf("elapsed time: %.3fs\n", jcr->time);
	printf("throughput: %.2fMB/s\n",
			(double) jcr->job_size / (1024 * 1024 * jcr->time));
	printf("zero chunk count: %d\n", jcr->zero_chunk_count);
	printf("zero_chunk_amount: %ld\n", jcr->zero_chunk_amount);
	printf("rewritten_chunk_count: %d\n", jcr->rewritten_chunk_count);
	printf("rewritten_chunk_amount: %ld\n", jcr->rewritten_chunk_amount);
	printf("rewritten rate in amount: %.3f\n",
			jcr->rewritten_chunk_amount / (double) jcr->job_size);
	printf("rewritten rate in count: %.3f\n",
			jcr->rewritten_chunk_count / (double) jcr->chunk_num);

	destor_stat->data_amount += jcr->job_size;
	destor_stat->consumed_capacity += jcr->job_size - jcr->dedup_size;
	destor_stat->saved_capacity += jcr->dedup_size;
	destor_stat->number_of_chunks += jcr->chunk_num;
	destor_stat->number_of_dup_chunks += jcr->number_of_dup_chunks;
	destor_stat->zero_chunk_count += jcr->zero_chunk_count;
	destor_stat->zero_chunk_amount += jcr->zero_chunk_amount;
	destor_stat->rewritten_chunk_count += jcr->rewritten_chunk_count;
	destor_stat->rewritten_chunk_amount += jcr->rewritten_chunk_amount;
	destor_stat->sparse_chunk_count += sparse_chunk_count;
	destor_stat->sparse_chunk_amount += sparse_chunk_amount;
	destor_stat->container_num = container_volume.container_num;
	destor_stat->index_memory_overhead = index_memory_overhead;

	printf("read_time : %.3fs, %.2fMB/s\n", jcr->read_time / 1000000,
			jcr->job_size * 1000000 / jcr->read_time / 1024 / 1024);
	printf("chunk_time : %.3fs, %.2fMB/s\n", jcr->chunk_time / 1000000,
			jcr->job_size * 1000000 / jcr->chunk_time / 1024 / 1024);
	printf("name_time : %.3fs, %.2fMB/s\n", jcr->name_time / 1000000,
			jcr->job_size * 1000000 / jcr->name_time / 1024 / 1024);
	printf("filter_time : %.3fs, %.2fMB/s\n", jcr->filter_time / 1000000,
			jcr->job_size * 1000000 / jcr->filter_time / 1024 / 1024);
	printf("write_time : %.3fs, %.2fMB/s\n", jcr->write_time / 1000000,
			jcr->job_size * 1000000 / jcr->write_time / 1024 / 1024);
	printf("index_search_time : %.3fs, %.2fMB/s\n", search_time / 1000000,
			jcr->job_size * 1000000 / search_time / 1024 / 1024);
	printf("index_update_time : %.3fs, %.2fMB/s\n", update_time / 1000000,
			jcr->job_size * 1000000 / update_time / 1024 / 1024);
	puts("==== backup end ====");

	jcr->job_volume->job.job_id = jcr->job_id;
	jcr->job_volume->job.is_del = FALSE;
	jcr->job_volume->job.file_num = jcr->file_num;
	jcr->job_volume->job.chunk_num = jcr->chunk_num;

	strcpy(jcr->job_volume->job.backup_path, jcr->backup_path);

	update_job_volume_des(jcr->job_volume);
	close_job_volume(jcr->job_volume);
	jcr->job_volume = 0;

	double seek_time = 0.005; //5ms
	double bandwidth = 120 * 1024 * 1024; //120MB/s

	double index_lookup_throughput = jcr->job_size
			/ (index_read_times * seek_time
					+ index_read_entry_counter * 24 / bandwidth) / 1024 / 1024;

	double write_data_throughput = 1.0 * jcr->job_size * bandwidth
			/ (jcr->job_size - jcr->dedup_size) / 1024 / 1024;
	double index_read_throughput = 1.0 * jcr->job_size / 1024 / 1024
			/ (index_read_times * seek_time
					+ index_read_entry_counter * 24 / bandwidth);
	double index_write_throughput = 1.0 * jcr->job_size / 1024 / 1024
			/ (index_write_times * seek_time
					+ index_write_entry_counter * 24 / bandwidth);

	double estimated_throughput = write_data_throughput;
	if (estimated_throughput > index_read_throughput)
		estimated_throughput = index_read_throughput;
	/*if (estimated_throughput > index_write_throughput)
	 estimated_throughput = index_write_throughput;*/

	char logfile[] = "backup.log";
	int fd = open(logfile, O_WRONLY | O_CREAT, S_IRWXU);
	lseek(fd, 0, SEEK_END);
	char buf[512];
	/*
	 * job id,
	 * chunk number,
	 * accumulative consumed capacity,
	 * deduplication ratio,
	 * rewritten ratio,
	 * total container number,
	 * sparse container number,
	 * inherited container number,
	 * throughput,
	 * index memory overhead,
	 * index lookups,
	 * index updates,
	 */
	sprintf(buf, "%d %d %ld %.4f %.4f %d %d %d %.2f %ld %ld %ld\n", jcr->job_id,
			jcr->chunk_num, destor_stat->consumed_capacity,
			jcr->job_size != 0 ?
					(double) (jcr->dedup_size) / (double) (jcr->job_size) : 0,
			jcr->job_size != 0 ?
					(double) (jcr->rewritten_chunk_amount)
							/ (double) (jcr->job_size) :
					0, jcr->total_container_num, jcr->sparse_container_num,
			jcr->inherited_sparse_num,
			(double) jcr->job_size / (1024 * 1024 * jcr->time),
			index_memory_overhead, index_read_times, index_write_times);
	if (write(fd, buf, strlen(buf)) != strlen(buf)) {
	}
	close(fd);
	free_jcr(jcr);
	return SUCCESS;

}
Beispiel #16
0
/*
 * 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;
}
Beispiel #17
0
int main (int argc, char *argv[])
{
   int ch;
   bool ok;
   char *iVolumeName = NULL;
   char *oVolumeName = NULL;
   char *DirectorName = NULL;
   DIRRES *director = NULL;
   bool ignore_label_errors = false;
   DCR *in_dcr, *out_dcr;

   setlocale(LC_ALL, "");
   bindtextdomain("bareos", LOCALEDIR);
   textdomain("bareos");
   init_stack_dump();

   my_name_is(argc, argv, "bcopy");
   lmgr_init_thread();
   init_msg(NULL, NULL);

   while ((ch = getopt(argc, argv, "b:c:D:d:i:o:pvw:?")) != -1) {
      switch (ch) {
      case 'b':
         bsr = parse_bsr(NULL, optarg);
         break;

      case 'c':                    /* specify config file */
         if (configfile != NULL) {
            free(configfile);
         }
         configfile = bstrdup(optarg);
         break;

      case 'D':                    /* specify director name */
         if (DirectorName != NULL) {
            free(DirectorName);
         }
         DirectorName = 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 'i':                    /* input Volume name */
         iVolumeName = optarg;
         break;

      case 'o':                    /* output Volume name */
         oVolumeName = optarg;
         break;

      case 'p':
         ignore_label_errors = true;
         forge_on = true;
         break;

      case 'v':
         verbose++;
         break;

      case 'w':
         wd = optarg;
         break;

      case '?':
      default:
         usage();

      }
   }
   argc -= optind;
   argv += optind;

   if (argc != 2) {
      Pmsg0(0, _("Wrong number of arguments: \n"));
      usage();
   }

   OSDependentInit();

   working_directory = wd;

   if (configfile == NULL) {
      configfile = bstrdup(CONFIG_FILE);
   }

   my_config = new_config_parser();
   parse_sd_config(my_config, configfile, M_ERROR_TERM);

   if (DirectorName) {
      foreach_res(director, R_DIRECTOR) {
         if (bstrcmp(director->hdr.name, DirectorName)) {
            break;
         }
      }
      if (!director) {
         Emsg2(M_ERROR_TERM, 0, _("No Director resource named %s defined in %s. Cannot continue.\n"),
               DirectorName, configfile);
      }
   }

   load_sd_plugins(me->plugin_directory, me->plugin_names);

   read_crypto_cache(me->working_directory, "bareos-sd",
                     get_first_port_host_order(me->SDaddrs));

   /*
    * Setup and acquire input device for reading
    */
   Dmsg0(100, "About to setup input jcr\n");

   in_dcr = New(DCR);
   in_jcr = setup_jcr("bcopy", argv[0], bsr, director, in_dcr, iVolumeName, true); /* read device */
   if (!in_jcr) {
      exit(1);
   }

   in_jcr->ignore_label_errors = ignore_label_errors;

   in_dev = in_jcr->dcr->dev;
   if (!in_dev) {
      exit(1);
   }

   /*
    * Setup output device for writing
    */
   Dmsg0(100, "About to setup output jcr\n");

   out_dcr = New(DCR);
   out_jcr = setup_jcr("bcopy", argv[1], bsr, director, out_dcr, oVolumeName, false); /* write device */
   if (!out_jcr) {
      exit(1);
   }

   out_dev = out_jcr->dcr->dev;
   if (!out_dev) {
      exit(1);
   }

   Dmsg0(100, "About to acquire device for writing\n");

   /*
    * For we must now acquire the device for writing
    */
   out_dev->rLock(false);
   if (!out_dev->open(out_jcr->dcr, OPEN_READ_WRITE)) {
      Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
      out_dev->Unlock();
      exit(1);
   }
   out_dev->Unlock();
   if (!acquire_device_for_append(out_jcr->dcr)) {
      free_jcr(in_jcr);
      exit(1);
   }
   out_block = out_jcr->dcr->block;

   ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume);

   if (ok || out_dev->can_write()) {
      if (!out_jcr->dcr->write_block_to_device()) {
         Pmsg0(000, _("Write of last block failed.\n"));
      }
   }

   Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records);

   in_dev->term();
   out_dev->term();

   free_jcr(in_jcr);
   free_jcr(out_jcr);

   return 0;
}
Beispiel #18
0
int main(int argc, char *const *argv)
{
   FF_PKT *ff;
   char name[1000];
   bool quiet = false;
   int i, ch;
   char *inc = NULL;
   char *exc = NULL;
   FILE *fd;

   setlocale(LC_ALL, "");
   bindtextdomain("bacula", LOCALEDIR);
   textdomain("bacula");
   lmgr_init_thread();

   while ((ch = getopt(argc, argv, "ad:e:i:q?")) != -1) {
      switch (ch) {
      case 'a':                       /* print extended attributes *debug* */
         attrs = 1;
         break;

      case 'd':                       /* set debug level */
         if (*optarg == 't') {
            dbg_timestamp = true;
         } else {
            debug_level = atoi(optarg);
            if (debug_level <= 0) {
               debug_level = 1;
            }
         }
         break;

      case 'e':                       /* exclude patterns */
         exc = optarg;
         break;

      case 'i':                       /* include patterns */
         inc = optarg;
         break;

      case 'q':
         quiet = true;
         break;

      case '?':
      default:
         usage();

      }
   }
   argc -= optind;
   argv += optind;

   jcr = new_jcr(sizeof(JCR), NULL);

   ff = init_find_files();
   if (argc == 0 && !inc) {
      add_fname_to_include_list(ff, 0, "/"); /* default to / */
   } else {
      for (i=0; i < argc; i++) {
         if (strcmp(argv[i], "-") == 0) {
             while (fgets(name, sizeof(name)-1, stdin)) {
                strip_trailing_junk(name);
                add_fname_to_include_list(ff, 0, name);
              }
              continue;
         }
         add_fname_to_include_list(ff, 0, argv[i]);
      }
   }
   if (inc) {
      fd = fopen(inc, "rb");
      if (!fd) {
         printf(_("Could not open include file: %s\n"), inc);
         exit(1);
      }
      while (fgets(name, sizeof(name)-1, fd)) {
         strip_trailing_junk(name);
         add_fname_to_include_list(ff, 0, name);
      }
      fclose(fd);
   }

   if (exc) {
      fd = fopen(exc, "rb");
      if (!fd) {
         printf(_("Could not open exclude file: %s\n"), exc);
         exit(1);
      }
      while (fgets(name, sizeof(name)-1, fd)) {
         strip_trailing_junk(name);
         add_fname_to_exclude_list(ff, name);
      }
      fclose(fd);
   }
   if (quiet) {
      match_files(jcr, ff, count_files);
   } else {
      match_files(jcr, ff, print_file);
   }
   printf(_("Files seen = %d\n"), num_files);
   term_include_exclude_files(ff);
   term_find_files(ff);

   free_jcr(jcr);
   term_last_jobs_list();             /* free jcr chain */
   close_memory_pool();
   lmgr_cleanup_main();
   sm_dump(false);
   exit(0);
}
Beispiel #19
0
static bool list_nextvol(UAContext *ua, int ndays)
{
   JOBRES *job;
   JCR *jcr;
   USTORERES store;
   RUNRES *run;
   utime_t runtime;
   bool found = false;
   MEDIA_DBR mr;
   POOL_DBR pr;

   int i = find_arg_with_value(ua, "job");
   if (i <= 0) {
      if ((job = select_job_resource(ua)) == NULL) {
         return false;
      }
   } else {
      job = (JOBRES *)GetResWithName(R_JOB, ua->argv[i]);
      if (!job) {
         Jmsg(ua->jcr, M_ERROR, 0, _("%s is not a job name.\n"), ua->argv[i]);
         if ((job = select_job_resource(ua)) == NULL) {
            return false;
         }
      }
   }

   jcr = new_jcr(sizeof(JCR), dird_free_jcr);
   for (run=NULL; (run = find_next_run(run, job, runtime, ndays)); ) {
      if (!complete_jcr_for_job(jcr, job, run->pool)) {
         found = false;
         goto get_out;
      }
      if (!jcr->jr.PoolId) {
         ua->error_msg(_("Could not find Pool for Job %s\n"), job->name());
         continue;
      }
      memset(&pr, 0, sizeof(pr));
      pr.PoolId = jcr->jr.PoolId;
      if (!db_get_pool_record(jcr, jcr->db, &pr)) {
         bstrncpy(pr.Name, "*UnknownPool*", sizeof(pr.Name));
      }
      mr.PoolId = jcr->jr.PoolId;
      get_job_storage(&store, job, run);
      set_storageid_in_mr(store.store, &mr);
      /* no need to set ScratchPoolId, since we use fnv_no_create_vol */
      if (!find_next_volume_for_append(jcr, &mr, 1, fnv_no_create_vol, fnv_prune)) {
         ua->error_msg(_("Could not find next Volume for Job %s (Pool=%s, Level=%s).\n"),
            job->name(), pr.Name, level_to_str(run->level));
      } else {
         ua->send_msg(
            _("The next Volume to be used by Job \"%s\" (Pool=%s, Level=%s) will be %s\n"),
            job->name(), pr.Name, level_to_str(run->level), mr.VolumeName);
         found = true;
      }
   }

get_out:
   if (jcr->db) {
      db_sql_close_pooled_connection(jcr, jcr->db);
      jcr->db = NULL;
   }
   free_jcr(jcr);
   if (!found) {
      ua->error_msg(_("Could not find next Volume for Job %s.\n"),
         job->hdr.name);
      return false;
   }
   return true;
}
Beispiel #20
0
/*
 * 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;
}
Beispiel #21
0
/*
 * 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 auth_key[MAX_NAME_LENGTH];
   char seed[MAX_NAME_LENGTH];
   char spool_size[MAX_NAME_LENGTH];
   BSOCK *dir = jcr->dir_bsock;
   POOL_MEM job_name, client_name, job, fileset_name, fileset_md5, backup_format;
   int32_t JobType, level, spool_attributes, no_attributes, spool_data;
   int32_t PreferMountedVols, rerunning, protocol, dumplevel;
   int status;
   uint64_t quota = 0;
   JCR *ojcr;

   /*
    * Get JobId and permissions from Director
    */
   Dmsg1(100, "<dird: %s", dir->msg);
   bstrncpy(spool_size, "0", sizeof(spool_size));
   status = 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, &PreferMountedVols, spool_size, &rerunning,
                   &jcr->VolSessionId, &jcr->VolSessionTime, &quota, &protocol,
                   backup_format.c_str(), &dumplevel);
   if (status != 20) {
      pm_strcpy(jcr->errmsg, dir->msg);
      dir->fsend(BAD_job, status, jcr->errmsg);
      Dmsg1(100, ">dird: %s", dir->msg);
      jcr->setJobStatus(JS_ErrorTerminated);
      return false;
   }

   jcr->rerunning = (rerunning) ? true : false;
   jcr->setJobProtocol(protocol);

   Dmsg4(100, "rerunning=%d VolSesId=%d VolSesTime=%d Protocol=%d\n",
         jcr->rerunning, jcr->VolSessionId, jcr->VolSessionTime, jcr->getJobProtocol());
   /*
    * 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);
   /*
    * 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->fileset_md5 = get_pool_memory(PM_NAME);
   pm_strcpy(jcr->fileset_md5, fileset_md5);
   jcr->PreferMountedVols = PreferMountedVols;
   jcr->RemainingQuota = quota;
   unbash_spaces(backup_format);
   jcr->backup_format = get_pool_memory(PM_NAME);
   pm_strcpy(jcr->backup_format, backup_format);
   jcr->DumpLevel = dumplevel;
   jcr->authenticated = false;

   Dmsg1(50, "Quota set as %llu\n", quota);

   /*
    * Pass back an authorization key for the File daemon
    */
   bsnprintf(seed, sizeof(seed), "%p%d", jcr, JobId);
   make_session_key(auth_key, seed, 1);
   dir->fsend(OK_job, jcr->VolSessionId, jcr->VolSessionTime, auth_key);
   Dmsg2(50, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
   jcr->sd_auth_key = bstrdup(auth_key);
   memset(auth_key, 0, sizeof(auth_key));

   dispatch_new_plugin_options(jcr);
   generate_plugin_event(jcr, bsdEventJobStart, (void *)"JobStart");

   return true;
}