*/
bool do_vbackup_init(JCR *jcr)
{
+ char *p;
+
if (!get_or_create_fileset_record(jcr)) {
Dmsg1(dbglevel, "JobId=%d no FileSet\n", (int)jcr->JobId);
return false;
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);
+ Jmsg(jcr, M_FATAL, 0, _("Could not get or create a Pool record.\n"));
+ return false;
+ }
/*
* Note, at this point, pool is the pool for this job. We
* transfer it to rpool (read pool), and a bit later,
jcr->rpool = jcr->pool; /* save read pool */
pm_strcpy(jcr->rpool_source, jcr->pool_source);
+ /* If pool storage specified, use it for restore */
+ copy_rstorage(jcr, jcr->pool->storage, _("Pool resource"));
Dmsg2(dbglevel, "Read pool=%s (From %s)\n", jcr->rpool->name(), jcr->rpool_source);
return false;
}
+ /*
+ * Now we find the last job that ran and store it's info in
+ * the previous_jr record. We will set our times to the
+ * values from that job so that anything changed after that
+ * time will be picked up on the next backup.
+ */
+ p = strrchr(jobids, ','); /* find last jobid */
+ if (p != NULL) {
+ p++;
+ } else {
+ p = jobids;
+ }
+ memset(&jcr->previous_jr, 0, sizeof(jcr->previous_jr));
+ jcr->previous_jr.JobId = str_to_int64(p);
+ if (!db_get_job_record(jcr, jcr->db, &jcr->previous_jr)) {
+ Jmsg(jcr, M_FATAL, 0, _("Error getting Job record for previous Job: ERR=%s"),
+ db_strerror(jcr->db));
+ return false;
+ }
+
if (!create_bootstrap_file(jcr, jobids)) {
Jmsg(jcr, M_FATAL, 0, _("Could not get or create the FileSet record.\n"));
free_pool_memory(jobids);
return false;
}
}
-
if (!set_migration_wstorage(jcr, jcr->pool)) {
return false;
}
Dmsg2(dbglevel, "Write pool=%s read rpool=%s\n", jcr->pool->name(), jcr->rpool->name());
- create_clones(jcr);
+// create_clones(jcr);
return true;
}
/*
- * Do a backup of the specified FileSet
+ * Do a virtual backup, which consolidates all previous backups into
+ * a sort of synthetic Full.
*
* Returns: false on failure
* true on success
char ed1[100];
BSOCK *sd;
+ Dmsg2(100, "rstorage=%p wstorage=%p\n", jcr->rstorage, jcr->wstorage);
+ Dmsg2(100, "Read store=%s, write store=%s\n",
+ ((STORE *)jcr->rstorage->first())->name(),
+ ((STORE *)jcr->wstorage->first())->name());
+ /* ***FIXME*** we really should simply verify that the pools are different */
+ if (((STORE *)jcr->rstorage->first())->name() == ((STORE *)jcr->wstorage->first())->name()) {
+ Jmsg(jcr, M_FATAL, 0, _("Read storage \"%s\" same as write storage.\n"),
+ ((STORE *)jcr->rstorage->first())->name());
+ return false;
+ }
+
/* Print Job Start message */
- Jmsg(jcr, M_INFO, 0, _("Start Vbackup JobId %s, Job=%s\n"),
+ Jmsg(jcr, M_INFO, 0, _("Start Virtual Backup JobId %s, Job=%s\n"),
edit_uint64(jcr->JobId, ed1), jcr->Job);
/*
return false;
}
sd = jcr->store_bsock;
+
/*
* Now start a job with the Storage daemon
*/
- Dmsg2(100, "rstorage=%p wstorage=%p\n", jcr->rstorage, jcr->wstorage);
- Dmsg2(100, "Read store=%s, write store=%s\n",
- ((STORE *)jcr->rstorage->first())->name(),
- ((STORE *)jcr->wstorage->first())->name());
- if (((STORE *)jcr->rstorage->first())->name() == ((STORE *)jcr->wstorage->first())->name()) {
- Jmsg(jcr, M_FATAL, 0, _("Read storage \"%s\" same as write storage.\n"),
- ((STORE *)jcr->rstorage->first())->name());
- return false;
- }
if (!start_storage_daemon_job(jcr, jcr->rstorage, jcr->wstorage)) {
return false;
}
jcr->jr.JobTDate = jcr->start_time;
set_jcr_job_status(jcr, JS_Running);
- /* Update job start record for this migration control job */
+ /* Update job start record */
if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
return false;
CLIENT_DBR cr;
double kbps, compression;
utime_t RunTime;
+ POOL_MEM query(PM_MESSAGE);
Dmsg2(100, "Enter backup_cleanup %d %c\n", TermCode, TermCode);
memset(&mr, 0, sizeof(mr));
jcr->JobBytes = jcr->SDJobBytes;
update_job_end(jcr, TermCode);
-#ifdef xxx
- /* ***FIXME*** set to time of last incremental */
/* Update final items to set them to the previous job's values */
Mmsg(query, "UPDATE Job SET StartTime='%s',EndTime='%s',"
"JobTDate=%s WHERE JobId=%s",
jcr->previous_jr.cStartTime, jcr->previous_jr.cEndTime,
edit_uint64(jcr->previous_jr.JobTDate, ec1),
- edit_uint64(mig_jcr->jr.JobId, ec2));
- db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
-#endif
+ edit_uint64(jcr->JobId, ec3));
+ db_sql_query(jcr->db, query.c_str(), NULL, NULL);
if (!db_get_job_record(jcr, jcr->db, &jcr->jr)) {
Jmsg(jcr, M_WARNING, 0, _("Error getting Job record for Job report: ERR=%s"),
ok_out:
if (jcr->dcr) {
dev = jcr->dcr->dev;
+ Dmsg1(100, "ok=%d\n", ok);
if (ok || dev->can_write()) {
/* Flush out final partial block of this session */
if (!write_block_to_device(jcr->dcr)) {
generate_daemon_event(jcr, "JobEnd");
dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
edit_uint64(jcr->JobBytes, ec1));
- Dmsg4(200, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, ec1);
+ Dmsg4(100, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, ec1);
dir->signal(BNET_EOD); /* send EOD to Director daemon */
DEVICE *dev = jcr->dcr->dev;
char buf1[100], buf2[100];
int32_t stream;
+ uint32_t last_VolSessionId = 0;
+ uint32_t last_VolSessionTime = 0;
+ int32_t last_FileIndex = 0;
/* If label and not for us, discard it */
if (rec->FileIndex < 0 && rec->match_stat <= 0) {
case EOM_LABEL:
return true; /* don't write vol labels */
}
+ /*
+ * For normal migration jobs, FileIndex values are sequential because
+ * we are dealing with one job. However, for Vbackup (consolidation),
+ * we will be getting records from multiple jobs and writing them back
+ * out, so we need to ensure that the output FileIndex is sequential.
+ * We do so by detecting a FileIndex change and incrementing the
+ * JobFiles, which we then use as the output FileIndex.
+ */
+ if (rec->VolSessionId != last_VolSessionId ||
+ rec->VolSessionTime != last_VolSessionTime ||
+ (rec->FileIndex > 0 && rec->FileIndex != last_FileIndex)) {
+ jcr->JobFiles++;
+ last_VolSessionId = rec->VolSessionId;
+ last_VolSessionTime = rec->VolSessionTime;
+ last_FileIndex = rec->FileIndex;
+ rec->FileIndex = jcr->JobFiles; /* set sequential output FileIndex */
+ }
/*
* Modify record SessionId and SessionTime to correspond to
* output.
Dmsg2(200, "===== Wrote block new pos %u:%u\n", dev->file, dev->block_num);
}
jcr->JobBytes += rec->data_len; /* increment bytes this job */
- if (rec->FileIndex > 0) {
- jcr->JobFiles = rec->FileIndex;
- } else {
+ if (rec->FileIndex <= 0) {
return true; /* don't send LABELs to Dir */
}
Dmsg5(500, "wrote_record JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",