For 1.28 release:
+- Add count output to restore.
+- Need a verbose mode in restore, perhaps to bsr.
+- Should we dump a SOS when starting a new tape?
+- bscan without -v is too quiet -- perhaps show jobs.
+- Get rid of bscan.c:534 error message (one time only).
+- Print some statistics when get EOF on device in bscan -- feedback
+ to let user know it is working.
- Add code to put VolFile in bsr for restore command.
- Add code to reject whole blocks if not wanted on restore.
- Add watchdog timeout for child processes start_child_timer()
- Make BSR accept count (total files to be restored).
- Add code to fast seek to proper place on tape/file when doing Restore.
- Replace popen() and pclose() -- fail safe and timeout, no SIG dep.
-
int db_get_file_attributes_record(B_DB *mdb, char *fname, FILE_DBR *fdbr)
{ return 0; }
+int db_get_job_volume_parameters(B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams)
+{ return 0; }
#endif /* HAVE_BACULA_DB */
-void db_list_files_for_job(B_DB *mdb, uint32_t jobid, DB_LIST_HANDLER *sendit, void *ctx) {}
+void db_list_files_for_job(B_DB *mdb, uint32_t jobid, DB_LIST_HANDLER *sendit, void *ctx)
+{ }
+
+void db_list_client_records(B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx)
+{ }
+
#endif /* HAVE_BACULA_DB */
uint32_t EndBlock; /* last block */
} JOBMEDIA_DBR;
+/* Volume Parameter structure */
+typedef struct {
+ char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
+ uint32_t StartFile; /* File for start of data */
+ uint32_t EndFile; /* End file on Volume */
+ uint32_t StartBlock; /* start block on tape */
+ uint32_t EndBlock; /* last block */
+} VOL_PARAMS;
+
/* Attributes record -- NOT same as in database because
* in general, this "record" creates multiple database
int db_get_num_pool_records(B_DB *mdb);
int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t **ids);
int db_get_media_ids(B_DB *mdb, int *num_ids, uint32_t **ids);
+int db_get_job_volume_parameters(B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams);
/* list.c */
void db_list_media_records(B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit, void *ctx);
void db_list_jobmedia_records(B_DB *mdb, uint32_t JobId, DB_LIST_HANDLER *sendit, void *ctx);
int db_list_sql_query(B_DB *mdb, char *query, DB_LIST_HANDLER *sendit, void *ctx, int verbose);
+void db_list_client_records(B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx);
/* update.c */
int db_update_job_start_record(B_DB *db, JOB_DBR *jr);
return stat;
}
+/*
+ * Find Volume parameters for a give JobId
+ * Returns: 0 on error or no Volumes found
+ * number of volumes on success
+ * List of Volumes and start/end file/blocks (malloced structure!)
+ *
+ * Returns: number of volumes on success
+ */
+int db_get_job_volume_parameters(B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams)
+{
+ SQL_ROW row;
+ int stat = 0;
+ int i;
+ VOL_PARAMS *Vols = NULL;
+
+ db_lock(mdb);
+ Mmsg(&mdb->cmd,
+"SELECT VolumeName,StartFile,EndFile,StartBlock,EndBlock"
+" FROM JobMedia,Media WHERE JobMedia.JobId=%u"
+" AND JobMedia.MediaId=Media.MediaId", JobId);
+
+ Dmsg1(130, "VolNam=%s\n", mdb->cmd);
+ if (QUERY_DB(mdb, mdb->cmd)) {
+ mdb->num_rows = sql_num_rows(mdb);
+ Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
+ if (mdb->num_rows <= 0) {
+ Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
+ stat = 0;
+ } else {
+ stat = mdb->num_rows;
+ if (stat > 0) {
+ *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
+ }
+ for (i=0; i < stat; i++) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
+ Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
+ Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
+ stat = 0;
+ break;
+ } else {
+ bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
+ Vols[i].StartFile = atoi(row[1]);
+ Vols[i].EndFile = atoi(row[2]);
+ Vols[i].StartBlock = atoi(row[3]);
+ Vols[i].EndBlock = atoi(row[4]);
+ }
+ }
+ }
+ sql_free_result(mdb);
+ }
+ db_unlock(mdb);
+ return stat;
+}
+
+
/*
* Get the number of pool records
db_unlock(mdb);
}
+void
+db_list_client_records(B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx)
+{
+ Mmsg(&mdb->cmd, "SELECT ClientId,Name,FileRetention,JobRetention "
+"FROM Client ORDER BY ClientId");
+
+ db_lock(mdb);
+ if (!QUERY_DB(mdb, mdb->cmd)) {
+ db_unlock(mdb);
+ return;
+ }
+
+ list_result(mdb, sendit, ctx);
+
+ sql_free_result(mdb);
+ db_unlock(mdb);
+}
+
+
void
db_list_media_records(B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit, void *ctx)
{
* list pools - list pool records
* list jobtotals - list totals for all jobs
* list media - list media for given pool
+ * list clients - list clients
*
*/
int listcmd(UAContext *ua, char *cmd)
} else if (strcasecmp(ua->argk[i], _("pools")) == 0) {
db_list_pool_records(ua->db, prtit, ua);
+ } else if (strcasecmp(ua->argk[i], _("clients")) == 0) {
+ db_list_client_records(ua->db, prtit, ua);
+
+
/* List MEDIA or VOLUMES */
} else if (strcasecmp(ua->argk[i], _("media")) == 0 ||
strcasecmp(ua->argk[i], _("volumes")) == 0) {
uint32_t JobId; /* JobId this bsr */
uint32_t VolSessionId;
uint32_t VolSessionTime;
+ uint32_t StartFile;
+ uint32_t EndFile;
+ uint32_t StartBlock;
+ uint32_t EndBlock;
char *VolumeName; /* Volume name */
RBSR_FINDEX *fi; /* File indexes this JobId */
} RBSR;
static int complete_bsr(UAContext *ua, RBSR *bsr)
{
JOB_DBR jr;
- POOLMEM *VolumeNames;
+ VOL_PARAMS *VolParams;
+ int count = 0;
if (bsr) {
- VolumeNames = get_pool_memory(PM_MESSAGE);
memset(&jr, 0, sizeof(jr));
jr.JobId = bsr->JobId;
if (!db_get_job_record(ua->db, &jr)) {
}
bsr->VolSessionId = jr.VolSessionId;
bsr->VolSessionTime = jr.VolSessionTime;
- if (!db_get_job_volume_names(ua->db, bsr->JobId, &VolumeNames)) {
- bsendmsg(ua, _("Unable to get Job Volumes. ERR=%s\n"), db_strerror(ua->db));
- free_pool_memory(VolumeNames);
+ if ((count=db_get_job_volume_parameters(ua->db, bsr->JobId, &VolParams)) == 0) {
+ bsendmsg(ua, _("Unable to get Job Volume Parameters. ERR=%s\n"), db_strerror(ua->db));
+ free((char *)VolParams);
return 0;
}
- bsr->VolumeName = bstrdup(VolumeNames);
- free_pool_memory(VolumeNames);
+ bsr->VolumeName = bstrdup(VolParams[0].VolumeName);
+ bsr->StartFile = VolParams[0].StartFile;
+ bsr->EndFile = VolParams[0].EndFile;
+ bsr->StartBlock = VolParams[0].StartBlock;
+ bsr->EndBlock = VolParams[0].EndBlock;
+ free((char *)VolParams);
return complete_bsr(ua, bsr->next);
}
return 1;
}
fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
+ fprintf(fd, "VolFile=%u-%u\n", bsr->StartFile, bsr->EndFile);
write_findex(ua, bsr->fi, fd);
write_bsr(ua, bsr->next, fd);
}
/* Find next Volume, if any */
vol = jcr->VolList;
+ if (!vol) {
+ Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job cancelled.\n"));
+ goto get_out;
+ }
jcr->CurVolume++;
for (int i=1; i<jcr->CurVolume; i++) {
vol = vol->next;
Pmsg1(000, "VOL_LABEL: OK for Volume: %s\n", mr.VolumeName);
break;
case SOS_LABEL:
-
mr.VolJobs++;
unser_session_label(&label, rec);
memset(&jr, 0, sizeof(jr));
create_fileset_record(db, &fsr);
jr.FileSetId = fsr.FileSetId;
-
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
+ rec->VolSessionId, rec->VolSessionTime);
break;
}
;
}
strcat(lname, lp); /* "save" link name */
-
-
if (verbose > 1) {
decode_stat(ap, &statp);
print_ls_output(fname, lname, type, &statp);
}
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
- Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
+ if (mr.VolJobs > 0) {
+ Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
+ rec->VolSessionId, rec->VolSessionTime);
+ }
return;
}
fr.JobId = mjcr->JobId;
} else if (rec->Stream == STREAM_FILE_DATA) {
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
- Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
+ if (mr.VolJobs > 0) {
+ Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for File Data record.\n"),
+ rec->VolSessionId, rec->VolSessionTime);
+ }
return;
}
mjcr->JobBytes += rec->data_len;
} else if (rec->Stream == STREAM_SPARSE_DATA) {
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
- Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
+ if (mr.VolJobs > 0) {
+ Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Sparse Data record.\n"),
+ rec->VolSessionId, rec->VolSessionTime);
+ }
return;
}
mjcr->JobBytes += rec->data_len - sizeof(uint64_t);
} else if (rec->Stream == STREAM_GZIP_DATA) {
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
- Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
+ if (mr.VolJobs > 0) {
+ Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for GZIP Data record.\n"),
+ rec->VolSessionId, rec->VolSessionTime);
+ }
return;
}
mjcr->JobBytes += rec->data_len; /* No correct, we should expand it */
} else if (rec->Stream == STREAM_SPARSE_GZIP_DATA) {
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
- Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
+ if (mr.VolJobs > 0) {
+ Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Sparse GZIP Data record.\n"),
+ rec->VolSessionId, rec->VolSessionTime);
+ }
return;
}
mjcr->JobBytes += rec->data_len - sizeof(uint64_t); /* No correct, we should expand it */
Pmsg1(0, _("Could not update job start record. ERR=%s\n"), db_strerror(db));
return mjcr;
}
- if (verbose) {
- Pmsg2(000, _("Created new JobId=%u record for original JobId=%u\n"), jr->JobId,
+ Pmsg2(000, _("Created new JobId=%u record for original JobId=%u\n"), jr->JobId,
label->JobId);
- }
mjcr->JobId = jr->JobId; /* set new JobId */
return mjcr;
}
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
if (!mjcr) {
- Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
- rec->VolSessionId, rec->VolSessionTime);
+ if (mr.VolJobs > 0) {
+ Pmsg2(000, _("Could not find SessId=%d SessTime=%d for MD5 record.\n"),
+ rec->VolSessionId, rec->VolSessionTime);
+ }
return 0;
}
if (!match_volume(bsr, bsr->volume, volrec, 1)) {
goto no_match;
}
- if (!match_volfile(bsr, bsr->volfile, rec, 1)) {
- goto no_match;
- }
+ /* Not yet working */
+// if (!match_volfile(bsr, bsr->volfile, rec, 1)) {
+// goto no_match;
+// }
if (!match_sesstime(bsr, bsr->sesstime, rec, 1)) {
goto no_match;
}