/*
Bacula® - The Network Backup Solution
- Copyright (C) 2004-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2004-2008 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
/*
*
* Bacula Director -- migrate.c -- responsible for doing
- * migration jobs.
+ * migration and copy jobs.
+ *
+ * Also handles Copy jobs (March MMVIII)
*
* Kern Sibbald, September MMIV
*
apply_pool_overrides(jcr);
+ if (!allow_duplicate_job(jcr)) {
+ return false;
+ }
+
jcr->jr.PoolId = get_or_create_pool_record(jcr, jcr->pool->name());
if (jcr->jr.PoolId == 0) {
Dmsg1(dbglevel, "JobId=%d no PoolId\n", (int)jcr->JobId);
}
/* Print Job Start message */
- Jmsg(jcr, M_INFO, 0, _("Start Migration JobId %s, Job=%s\n"),
+ Jmsg(jcr, M_INFO, 0, _("Start %s JobId %s, Job=%s\n"),
+ jcr->JobType == JT_MIGRATE ? "Migration" : "Copy",
edit_uint64(jcr->JobId, ed1), jcr->Job);
* to avoid two threads from using the BSOCK structure at
* the same time.
*/
- if (!bnet_fsend(sd, "run")) {
+ if (!sd->fsend("run")) {
return false;
}
}
migration_cleanup(jcr, jcr->JobStatus);
- if (mig_jcr) {
+ if (jcr->JobType == JT_MIGRATE && mig_jcr) {
char jobid[50];
UAContext *ua = new_ua_context(jcr);
edit_uint64(jcr->previous_jr.JobId, jobid);
/* Add an item to the list if it is unique */
static void add_unique_id(idpkt *ids, char *item)
{
- char id[30];
+ const int maxlen = 30;
+ char id[maxlen+1];
char *q = ids->list;
/* Walk through current list to see if each item is the same as item */
for ( ; *q; ) {
id[0] = 0;
- for (int i=0; i<(int)sizeof(id); i++) {
+ for (int i=0; i<maxlen; i++) {
if (*q == 0) {
break;
} else if (*q == ',') {
/* Get JobIds when we have selected MediaId */
const char *sql_jobids_from_mediaid =
"SELECT DISTINCT Job.JobId,Job.StartTime FROM JobMedia,Job"
- " WHERE JobMedia.JobId=Job.JobId AND JobMedia.MediaId=%s"
+ " WHERE JobMedia.JobId=Job.JobId AND JobMedia.MediaId IN (%s)"
" AND Job.Type='B'"
" ORDER by Job.StartTime";
edit_uint64(jcr->MigrateJobId, ed1));
Dmsg1(dbglevel, "=============== Migration cmd=%s\n", ua->cmd);
parse_ua_args(ua); /* parse command */
- int jobid = run_cmd(ua, ua->cmd);
+ JobId_t jobid = run_cmd(ua, ua->cmd);
if (jobid == 0) {
Jmsg(jcr, M_ERROR, 0, _("Could not start migration job.\n"));
} else {
- Jmsg(jcr, M_INFO, 0, _("Migration JobId %d started.\n"), jobid);
+ Jmsg(jcr, M_INFO, 0, _("Migration JobId %d started.\n"), (int)jobid);
}
free_ua_context(ua);
}
db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
/* Now mark the previous job as migrated if it terminated normally */
- if (jcr->JobStatus == JS_Terminated) {
+ if (jcr->JobType == JT_MIGRATE && jcr->JobStatus == JS_Terminated) {
Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s",
(char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, ec1));
db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
set_jcr_job_status(jcr, JS_ErrorTerminated);
}
-
update_bootstrap_file(mig_jcr);
if (!db_get_job_volume_names(mig_jcr, mig_jcr->db, mig_jcr->jr.JobId, &mig_jcr->VolumeName)) {
if (mig_jcr->VolumeName[0]) {
/* Find last volume name. Multiple vols are separated by | */
char *p = strrchr(mig_jcr->VolumeName, '|');
- if (!p) {
- p = mig_jcr->VolumeName;
+ if (p) {
+ p++; /* skip | */
+ } else {
+ p = mig_jcr->VolumeName; /* no |, take full name */
}
bstrncpy(mr.VolumeName, p, sizeof(mr.VolumeName));
if (!db_get_media_record(jcr, jcr->db, &mr)) {
break;
}
} else {
- if (jcr->previous_jr.JobId != 0) {
+ if (jcr->JobType == JT_MIGRATE && jcr->previous_jr.JobId != 0) {
/* Mark previous job as migrated */
Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s",
(char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, ec1));
- Dmsg1(000, "Mark: %s\n", query.c_str());
db_sql_query(jcr->db, query.c_str(), NULL, NULL);
}
term_msg = _("%s -- no files to migrate");
" Build OS: %s %s %s\n"
" Prev Backup JobId: %s\n"
" New Backup JobId: %s\n"
-" Migration JobId: %s\n"
-" Migration Job: %s\n"
+" Current JobId: %s\n"
+" Current Job: %s\n"
" Backup Level: %s%s\n"
" Client: %s\n"
" FileSet: \"%s\" %s\n"
" Read Storage: \"%s\" (From %s)\n"
" Write Pool: \"%s\" (From %s)\n"
" Write Storage: \"%s\" (From %s)\n"
+" Catalog: \"%s\" (From %s)\n"
" Start time: %s\n"
" End time: %s\n"
" Elapsed time: %s\n"
jcr->pool->name(), jcr->pool_source,
jcr->wstore?jcr->wstore->name():"*None*",
NPRT(jcr->wstore_source),
+ jcr->catalog->name(), jcr->catalog_source,
sdt,
edt,
edit_utime(RunTime, elapsed, sizeof(elapsed)),
*/
static int get_next_dbid_from_list(char **p, DBId_t *DBId)
{
- char id[30];
+ const int maxlen = 30;
+ char id[maxlen+1];
char *q = *p;
id[0] = 0;
- for (int i=0; i<(int)sizeof(id); i++) {
+ for (int i=0; i<maxlen; i++) {
if (*q == 0) {
break;
} else if (*q == ',') {