- Document problems with Verify and pruning.
- Document how to use multiple databases.
- For FreeBSD typical /dev/nrsa0 and for mtx /dev/pass1
+- VXA drives have a "cleaning required"
+ indicator, but Exabyte recommends preventive cleaning after every 75
+ hours of operation.
+- Lookup HP cleaning recommendations.
+- Lookup HP tape replacement recommendations (see trouble shooting autochanger)
Testing to do: (painful)
- blocksize recognition code.
- multiple simultaneous Volumes
- Test if rewind at end of tape waits for tape to rewind.
+- Test cancel at EOM.
- Figure out how to use ssh or stunnel to protect Bacula communications.
For 1.31 release:
- Finish WIN32_DATA stream code (bextract, check if can handle stream)
- Default duration with no qualifier is sec should be 1 day
-- Find a solution for the multiple FileSet problem (when it is changed).
- Add date?
+- Find a solution for the multiple FileSet problem (when it is changed). Add date?
- Cancel waiting for Client connect in SD if FD goes away.
- Testing Tibs job erred and hung director on Storage resource. This was
because there were a whole pile of jobs hanging around in the SD
- File the Automatically selected: xxx
to say Automatically selected Pool: xxx
- Should Bacula make an Append tape as Purged when purging?
-- Shell expansion failes for working_directory in SD from time to tim.
+- Shell expansion fails for working_directory in SD from time to time.
- Possibly update all client records at startup.
-- Volume names with spaces get jammed into the catalog with 0x1
- i.e. the SD bashes the Volume but they are not unbased by Dir.
- jerom-dir: MonthlySave.2003-05-10_17.12.01 Error: Unable to get Media
- record for Volume Tape^A1: ERR=sql_get.c:788 Media record for Volume
- "Tape^A1" not found.
- jerom-sd: MonthlySave.2003-05-10_17.12.01 Error: Error updating Volume
- Info: 1991 Catalog Request failed: sql_get.c:788 Media record for Volume
- "Tape^A1" not found.
-
-- Cancellation caused JobMedia error:
- babylon5-dir: Last FULL backup time not found. Doing FULL backup.
- babylon5-dir: Start Backup JobId 416, Job=Zocalo_Save.2003-05-19_02.15.06
- babylon5-sd: End of media on Volume VXA-V17-Inc-001 Bytes=31,982,900,672 Blocks=495,781.
- babylon5-sd: Job Zocalo_Save.2003-05-19_02.15.06 waiting. Cannot find any appendable volumes.
- babylon5-sd: Someone woke me up, but I cannot find any appendable volumes
- for Job=Zocalo_Save.2003-05-19_02.15.06.
- babylon5-sd: Zocalo_Save.2003-05-19_02.15.06 Fatal error: Job
- Zocalo_Save.2003-05-19_02.15.06 canceled while waiting for mount on
- Storage Device "Ecrix_VXA-1".
- babylon5-sd: Zocalo_Save.2003-05-19_02.15.06 Fatal error: Cannot fixup device
- error. Job Zocalo_Save.2003-05-19_02.15.06 canceled while waiting for
- mount on Storage Device "Ecrix_VXA-1".
-
- babylon5-dir: Zocalo_Save.2003-05-19_02.15.06 Error: Catalog error creating
- JobMedia record. sql_create.c:125 Create JobMedia failed. Record already
- exists.
- babylon5-sd: Zocalo_Save.2003-05-19_02.15.06 Error: Error creating JobMedia
- record: 1991 Update JobMedia error
-
- babylon5-sd: Zocalo_Save.2003-05-19_02.15.06 Error: askdir.c:158 NULL Volume
- name. This shouldn't happen!!!
- zocalo-fd: Zocalo_Save.2003-05-19_02.15.06 Error: bnet.c:310 Write error
- sending to Storage daemon:babylon5:9103: ERR=Broken pipe
-
-
-- ChangeServiceConfig2A does not exist on WinNT (ADVAPI32.DLL).
- Implement MTIOCERRSTAT on FreeBSD to clear tape error conditions.
Much like xxx_conf.c scan table.
keyword, handler(store_routine), store_address, code, flags, default.
-- Fix "access not allowed" for backup of files on WinXP.
-- Check for existence of all new Win32 API's. See LoadLibrary in
- winservice.cpp
- Examine Bare Metal restore problem (a FD crash exists somewhere ...).
- Test multiple simultaneous Volumes
- Document FInclude ...
- Implement timeout in response() when it should come quickly.
- Implement console @echo command.
-- Bug: fix access problems on files restored on WinXP.
- Implement a Slot priority (loaded/not loaded).
- Implement "vacation" Incremental only saves.
- Implement single pane restore (much like the Gftp panes).
records -- one per Job, maybe a JCR or some other structure with
a block and a record.
- Figure out how to do a bare metal Windows restore
-- Put system type returned by FD into catalog.
- Possibly add email to Watchdog if drive is unmounted too
long and a job is waiting on the drive.
- Use read_record.c in SD code.
- Document what characters can go into Volume names.
- Getting the following on all directories on Win32
19-May-2003 01:14 tibs-fd: Could not access c:/cygwin/home/kern/rxvt: ERR=Permission denied
+- Cancellation caused JobMedia error:
+ babylon5-dir: Last FULL backup time not found. Doing FULL backup.
+ babylon5-dir: Start Backup JobId 416, Job=Zocalo_Save.2003-05-19_02.15.06
+ babylon5-sd: End of media on Volume VXA-V17-Inc-001 Bytes=31,982,900,672 Blocks=495,781.
+ babylon5-sd: Job Zocalo_Save.2003-05-19_02.15.06 waiting. Cannot find any appendable volumes.
+ babylon5-sd: Someone woke me up, but I cannot find any appendable volumes
+ for Job=Zocalo_Save.2003-05-19_02.15.06.
+ babylon5-sd: Zocalo_Save.2003-05-19_02.15.06 Fatal error: Job
+ Zocalo_Save.2003-05-19_02.15.06 canceled while waiting for mount on
+ Storage Device "Ecrix_VXA-1".
+ babylon5-sd: Zocalo_Save.2003-05-19_02.15.06 Fatal error: Cannot fixup device
+ error. Job Zocalo_Save.2003-05-19_02.15.06 canceled while waiting for
+ mount on Storage Device "Ecrix_VXA-1".
+
+ babylon5-dir: Zocalo_Save.2003-05-19_02.15.06 Error: Catalog error creating
+ JobMedia record. sql_create.c:125 Create JobMedia failed. Record already
+ exists.
+ babylon5-sd: Zocalo_Save.2003-05-19_02.15.06 Error: Error creating JobMedia
+ record: 1991 Update JobMedia error
+
+ babylon5-sd: Zocalo_Save.2003-05-19_02.15.06 Error: askdir.c:158 NULL Volume
+ name. This shouldn't happen!!!
+ zocalo-fd: Zocalo_Save.2003-05-19_02.15.06 Error: bnet.c:310 Write error
+ sending to Storage daemon:babylon5:9103: ERR=Broken pipe
+- Volume names with spaces get jammed into the catalog with 0x1
+ i.e. the SD bashes the Volume but they are not unbased by Dir.
+ jerom-dir: MonthlySave.2003-05-10_17.12.01 Error: Unable to get Media
+ record for Volume Tape^A1: ERR=sql_get.c:788 Media record for Volume
+ "Tape^A1" not found.
+ jerom-sd: MonthlySave.2003-05-10_17.12.01 Error: Error updating Volume
+ Info: 1991 Catalog Request failed: sql_get.c:788 Media record for Volume
+ "Tape^A1" not found.
+- ChangeServiceConfig2A does not exist on WinNT (ADVAPI32.DLL).
+- Fix "access not allowed" for backup of files on WinXP.
+- Check for existence of all new Win32 API's. See LoadLibrary in
+ winservice.cpp
+- Count errors during restore and print them in the Job report.
+- Bug: fix access problems on files restored on WinXP.
+- Put system type returned by FD into catalog.
static char OKbackup[] = "2000 OK backup\n";
static char OKstore[] = "2000 OK storage\n";
static char OKlevel[] = "2000 OK level\n";
-static char EndBackup[] = "2801 End Backup Job TermCode=%d JobFiles=%u ReadBytes=%" lld " JobBytes=%" lld "\n";
+static char EndBackup[] = "2801 End Backup Job TermCode=%d JobFiles=%u ReadBytes=%" lld " JobBytes=%" lld " Errors=%u\n";
/* Forward referenced functions */
/* Wait for Client to terminate */
while ((n = bget_dirmsg(fd)) >= 0) {
if (sscanf(fd->msg, EndBackup, &jcr->FDJobStatus, &jcr->JobFiles,
- &jcr->ReadBytes, &jcr->JobBytes) == 4) {
+ &jcr->ReadBytes, &jcr->JobBytes, &jcr->Errors) == 5) {
fd_ok = TRUE;
set_jcr_job_status(jcr, jcr->FDJobStatus);
Dmsg1(100, "FDStatus=%c\n", (char)jcr->JobStatus);
Volume Session Id: %d\n\
Volume Session Time: %d\n\
Last Volume Bytes: %s\n\
+Non-fatal FD errors: %d\n\
FD termination status: %s\n\
SD termination status: %s\n\
Termination: %s\n\n"),
jcr->VolSessionId,
jcr->VolSessionTime,
edit_uint64_with_commas(mr.VolBytes, ec3),
+ jcr->Errors,
fd_term_msg,
sd_term_msg,
term_msg);
static char OKstore[] = "2000 OK storage\n";
static char OKsession[] = "2000 OK session\n";
static char OKbootstrap[] = "2000 OK bootstrap\n";
-static char EndRestore[] = "2800 End Job TermCode=%d JobFiles=%u JobBytes=%" lld "\n";
+static char EndRestore[] = "2800 End Job TermCode=%d JobFiles=%u JobBytes=%" lld " Errors=%u\n";
/* Forward referenced functions */
static void restore_cleanup(JCR *jcr, int status);
while (bget_dirmsg(fd) >= 0) {
Dmsg1(100, "dird<filed: %s\n", fd->msg);
if (sscanf(fd->msg, EndRestore, &jcr->FDJobStatus, &jcr->JobFiles,
- &jcr->JobBytes) == 3) {
+ &jcr->JobBytes, &jcr->Errors) == 4) {
ok = TRUE;
}
}
}
bstrftime(sdt, sizeof(sdt), jcr->jr.StartTime);
bstrftime(edt, sizeof(edt), jcr->jr.EndTime);
- kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
+ if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
+ kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
+ } else {
+ kbps = 0;
+ }
if (kbps < 0.05) {
kbps = 0;
}
Files Restored: %s\n\
Bytes Restored: %s\n\
Rate: %.1f KB/s\n\
+Non-fatal Errors: %d\n\
FD termination status: %s\n\
Termination: %s\n\n"),
edt,
edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec1),
edit_uint64_with_commas(jcr->jr.JobBytes, ec2),
(float)kbps,
+ jcr->Errors,
fd_term_msg,
term_msg);
static char OKjob[] = "2000 OK Job " FDHOST "," DISTNAME "," DISTVER;
static char OKsetdebug[] = "2000 OK setdebug=%d\n";
static char BADjob[] = "2901 Bad Job\n";
-static char EndRestore[] = "2800 End Job TermCode=%d JobFiles=%u JobBytes=%" lld "\n";
-static char EndBackup[] = "2801 End Backup Job TermCode=%d JobFiles=%u ReadBytes=%" lld " JobBytes=%" lld "\n";
+static char EndRestore[] = "2800 End Job TermCode=%d JobFiles=%u JobBytes=%s Errors=%u\n";
+static char EndBackup[] = "2801 End Backup Job TermCode=%d JobFiles=%u ReadBytes=%s JobBytes=%s Errors=%u\n";
/* Responses received from Storage Daemon */
static char OK_end[] = "3000 OK end\n";
BSOCK *sd = jcr->store_bsock;
int ok = 0;
int SDJobStatus;
+ char ed1[50], ed2[50];
set_jcr_job_status(jcr, JS_Blocked);
jcr->JobType = JT_BACKUP;
cleanup:
- bnet_fsend(dir, EndBackup, jcr->JobStatus, jcr->JobFiles, jcr->ReadBytes, jcr->JobBytes);
+ bnet_fsend(dir, EndBackup, jcr->JobStatus, jcr->JobFiles,
+ edit_uint64(jcr->ReadBytes, ed1),
+ edit_uint64(jcr->JobBytes, ed2), jcr->Errors);
return 0; /* return and stop command loop */
}
BSOCK *sd = jcr->store_bsock;
POOLMEM *where;
char replace;
+ char ed1[50];
/*
* Scan WHERE (base directory for restore) from command
bail_out:
/* Send termination status back to Dir */
bnet_fsend(dir, EndRestore, jcr->JobStatus, jcr->num_files_examined,
- jcr->JobBytes);
+ edit_uint64(jcr->JobBytes, ed1), jcr->Errors);
/* Inform Director that we are done */
bnet_sig(dir, BNET_TERMINATE);
int session_opened;
DEV_RECORD rec; /* Read/Write record */
long Ticket; /* ticket for this job */
- uint32_t VolFirstFile; /* First file index this Volume */
+ uint32_t VolFirstIndex; /* First file index this Volume */
uint32_t FileIndex; /* Current File Index */
uint32_t EndFile; /* End file written */
uint32_t StartFile; /* Start write file */
len = sprintf(rbuf, "%s: %s Fatal error: ", my_name, job);
if (jcr) {
set_jcr_job_status(jcr, JS_FatalError);
+ jcr->Errors++;
}
break;
case M_ERROR:
if (dev->num_writers == 0) {
Dmsg0(100, "dir_create_jobmedia_record. Release\n");
dir_create_jobmedia_record(jcr);
- weof_dev(dev, 1);
+ if (dev_can_write(dev)) {
+ weof_dev(dev, 1);
+ }
dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
/* Note! do volume update before close, which zaps VolCatInfo */
* file. 1. for the Attributes, 2. for the file data if any,
* and 3. for the MD5 if any.
*/
- jcr->VolFirstFile = 0;
+ jcr->VolFirstIndex = 0;
time(&jcr->run_time); /* start counting time for rates */
for (last_file_index = 0; ok && !job_canceled(jcr); ) {
char info[100];
}
if (file_index != last_file_index) {
jcr->JobFiles = file_index;
- if (jcr->VolFirstFile == 0) {
- jcr->VolFirstFile = file_index;
+ if (jcr->VolFirstIndex == 0) {
+ jcr->VolFirstIndex = file_index;
}
last_file_index = file_index;
}
Dmsg1(200, "Write session label JobStatus=%d\n", jcr->JobStatus);
- if (!write_session_label(jcr, block, EOS_LABEL)) {
- Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
- strerror_dev(dev));
- set_jcr_job_status(jcr, JS_ErrorTerminated);
- ok = FALSE;
- }
- /* Write out final block of this session */
- if (!write_block_to_device(jcr, dev, block)) {
- Pmsg0(000, _("Set ok=FALSE after write_block_to_device.\n"));
- set_jcr_job_status(jcr, JS_ErrorTerminated);
- ok = FALSE;
+ /*
+ * If !OK, check if we can still write. This may not be the case
+ * if we are at the end of the tape or we got a fatal I/O error.
+ */
+ if (ok || dev_can_write(dev)) {
+ if (!write_session_label(jcr, block, EOS_LABEL)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
+ strerror_dev(dev));
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ ok = FALSE;
+ }
+ /* Write out final block of this session */
+ if (!write_block_to_device(jcr, dev, block)) {
+ Pmsg0(000, _("Set ok=FALSE after write_block_to_device.\n"));
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ ok = FALSE;
+ }
}
Dmsg1(200, "release device JobStatus=%d\n", jcr->JobStatus);
{
BSOCK *dir = jcr->dir_bsock;
+ if (jcr->VolFirstIndex == 0) {
+ return 1; /* nothing written to tape */
+ }
+
bnet_fsend(dir, Create_job_media, jcr->Job,
- jcr->VolFirstFile, jcr->JobFiles,
+ jcr->VolFirstIndex, jcr->JobFiles,
jcr->StartFile, jcr->EndFile,
jcr->StartBlock, jcr->EndBlock);
Dmsg1(100, "create_jobmedia(): %s", dir->msg);
/* dump_block(block, "before write"); */
if (dev->state & ST_WEOT) {
Dmsg0(100, "return write_block_to_dev with ST_WEOT\n");
- Jmsg(&dev->errmsg, M_FATAL, 0, _("Cannot write block. Device at EOF.\n"));
+ Jmsg(&dev->errmsg, M_FATAL, 0, _("Cannot write block. Device at EOM.\n"));
return 0;
}
wlen = block->binbuf;
}
/* Reset some JCR variables */
for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
- mjcr->VolFirstFile = mjcr->FileIndex = 0;
+ mjcr->VolFirstIndex = mjcr->FileIndex = 0;
mjcr->StartBlock = mjcr->EndBlock = 0;
mjcr->StartFile = mjcr->EndFile = 0;
}
ar.Stream = rec->Stream;
ar.FileIndex = rec->FileIndex;
ar.attr = ap;
- if (mjcr->VolFirstFile == 0) {
- mjcr->VolFirstFile = rec->FileIndex;
+ if (mjcr->VolFirstIndex == 0) {
+ mjcr->VolFirstIndex = rec->FileIndex;
}
mjcr->FileIndex = rec->FileIndex;
mjcr->JobFiles++;
memset(&jmr, 0, sizeof(jmr));
jmr.JobId = mjcr->JobId;
jmr.MediaId = mr.MediaId;
- jmr.FirstIndex = mjcr->VolFirstFile;
+ jmr.FirstIndex = mjcr->VolFirstIndex;
jmr.LastIndex = mjcr->FileIndex;
jmr.StartFile = mjcr->StartFile;
jmr.EndFile = mjcr->EndFile;
/*
* Get Data from File daemon, write to device
*/
- jcr->VolFirstFile = 0;
+ jcr->VolFirstIndex = 0;
time(&jcr->run_time); /* start counting time for rates */
for (file_index = 0; ok && !job_canceled(jcr); ) {
uint64_t *lp;
return (dev->state & ST_TAPE) ? 1 : 0;
}
+
+/*
+ * return 1 if the device is read for write, and 0 otherwise
+ * This is meant for checking at the end of a job to see
+ * if we still have a tape (perhaps not if at end of tape
+ * and the job is canceled).
+ */
+int
+dev_can_write(DEVICE *dev)
+{
+ if ((dev->state & ST_OPENED) && (dev->state & ST_APPEND) &&
+ (dev->state & ST_LABEL) && !(dev->state & ST_WEOT)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
char *
dev_name(DEVICE *dev)
{
unblock_device(dev);
return 0;
}
+ mjcr->VolFirstIndex = 0; /* prevent writing jobmedia second time */
}
strcpy(dev->VolCatInfo.VolCatStatus, "Full");
mjcr->StartBlock = (uint32_t)dev->file_addr;
mjcr->StartFile = (uint32_t)(dev->file_addr >> 32);
}
- mjcr->VolFirstFile = mjcr->JobFiles;
+ /* Set first FirstIndex for new Volume */
+ mjcr->VolFirstIndex = mjcr->JobFiles;
mjcr->run_time += time(NULL) - wait_time; /* correct run time */
}
unblock_device(dev);
dev->state &= ~(ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
- jcr->VolFirstFile = jcr->JobFiles; /* first update of Vol FileIndex */
+ jcr->VolFirstIndex = jcr->JobFiles; /* first update of Vol FileIndex */
for ( ;; ) {
int vol_label_status;
autochanger = autoload_device(jcr, dev, 1, NULL);
void attach_jcr_to_device(DEVICE *dev, JCR *jcr);
void detach_jcr_from_device(DEVICE *dev, JCR *jcr);
JCR *next_attached_jcr(DEVICE *dev, JCR *jcr);
+int dev_can_write(DEVICE *dev);
/* Get info about device */