- Eric fixed RunScripts, which I (Kern) had broken in the last beta.
- Correct Client migration SQL as pointed out by Marc.
+New Features in 1.40.0 (beginning of release info)
+- There is a new cross-compiled Win32 File daemon that now has all the features
+ that were previously only in the Unix versions.
+
+ To install the 1.39.18 Win32 FD, you *must* first stop any
+ previous version that is running in a DOS shell with:
+
+ net stop bacula
+
+ or select the 'Close Bacula' menu item from the Bacula tray icon,
+ you should then save your bacula-fd.conf file, and either
+ uninstall (using Uninstall.bat in the c:\bacula directory) or
+ remove the old installation by manually in a DOS shell in the
+ Bacula directory enter:
+
+ bacula-fd /remove
+
+ after that you can proceed with the installation. My experience
+ is that it does not properly create the new bacula-fd.conf file, so
+ copy the one saved to the directory you chose to install Bacula,
+ or to the directory chosen by the Installer to put the bacula-fd.conf
+ file. Then you can start Bacula in a DOS shell with:
+
+ net start baculafd
+
+ or use the Windows Control Panel->Administrative Tools->Component
+ Services menu item. The document has been updated (not completely).
+ For installation details, please see:
+ http://www.bacula.org/dev-manual/Windows_Version_Bacula.html
+
+
==========================================
Warning for version 1.39.18 and greater:
- The "Accept Any Volume" directive has been removed. It was never
implemented. Bacula will always accept any valid tape that is in
the drive for appending.
-- To install the 1.39.18 Win32 FD, you *must* first stop any
- previous version that is running in a DOS shell with:
-
- net stop bacula
-
- or select the 'Close Bacula' menu item from the Bacula tray icon,
- you should then save your bacula-fd.conf file, and either
- uninstall (using Uninstall.bat in the c:\bacula directory) or
- remove the old installation by manually in a DOS shell in the
- Bacula directory enter:
-
- bacula-fd /remove
-
- after that you can proceed with the installation. My experience
- is that it does not properly create the new bacula-fd.conf file, so
- copy the one saved to the directory you chose to install Bacula,
- or to the directory chosen by the Installer to put the bacula-fd.conf
- file. Then you can start Bacula in a DOS shell with:
-
- net start baculafd
-
- or use the Windows Control Panel->Administrative Tools->Component
- Services menu item.
A Lot of New features for 1.39.18:
self.pid = 0
print
signal.signal(signal.SIGTERM, oldsig)
+ if not os.WIFEXITED(status):
+ raise DVDError(0, cmd + " process did not exit correctly, signal/status " + str(status))
if os.WEXITSTATUS(status) != 0:
raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
stop_child_timer(bpipe->timer_id);
}
free(bpipe);
- Dmsg2(800, "returning stat=%d,%d\n", stat & ~(b_errno_exit|b_errno_signal), stat);
+ Dmsg2(200, "returning stat=%d,%d\n", stat & ~(b_errno_exit|b_errno_signal), stat);
return stat;
}
break;
} else if (stat1 != 0) {
Dmsg1(900, "Run program fgets stat=%d\n", stat1);
- if (bpipe->timer_id) {
- Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
- if (bpipe->timer_id->killed) {
- pm_strcat(tmp, _("Program killed by Bacula watchdog (timeout)\n"));
- stat1 = ETIME;
- break;
- }
+ if (bpipe->timer_id && bpipe->timer_id->killed) {
+ Dmsg1(250, "Run program saw fgets killed=%d\n", bpipe->timer_id->killed);
+ break;
}
}
}
+ /*
+ * We always check whether the timer killed the program. We would see
+ * an eof even when it does so we just have to trust the killed flag
+ * and set the timer values to avoid edge cases where the program ends
+ * just as the timer kills it.
+ */
+ if (bpipe->timer_id && bpipe->timer_id->killed) {
+ Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
+ pm_strcat(tmp, _("Program killed by Bacula watchdog (timeout)\n"));
+ stat1 = ETIME;
+ }
int len = sizeof_pool_memory(results) - 1;
bstrncpy(results, tmp, len);
Dmsg3(1900, "resadr=0x%x reslen=%d res=%s\n", results, strlen(results), results);
POOLMEM *changer;
if (!dev->is_autochanger()) {
- Dmsg0(200, "======== NOT AUTOCHANGER ======\n");
+ Dmsg0(200, "== NOT AUTOCHANGER ==\n");
return 0;
}
slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
if (dev->is_dvd()) {
if (!dvd_write_part(dcr)) { /* write last part */
+ dev->VolCatInfo.VolCatErrors++;
+ Jmsg(dcr->jcr, M_FATAL, 0, _("Error writing final part to DVD. "
+ "This Volume may not be readable.\n%s"),
+ dev->errmsg);
ok = false;
+ Dmsg0(100, "dvd_write_part error.\n");
}
dev->VolCatInfo.VolCatParts = dev->num_dvd_parts;
}
if (mount_dvd(this, 1)) {
Dmsg0(99, "DVD device mounted.\n");
if ((num_dvd_parts == 0) && (!truncating)) {
+#ifdef needed
/*
* If we can mount the device, and we are not truncating the DVD,
* we usually want to abort. There is one exception, if there is
clear_opened();
return;
}
+#endif
truncated_dvd = true;
}
} else {
omode = OPEN_READ_ONLY;
make_mounted_dvd_filename(this, archive_name);
} else {
+ omode = OPEN_READ_WRITE;
make_spooled_dvd_filename(this, archive_name);
}
set_mode(omode);
dev_errno = EIO; /* Interpreted as no device present by acquire.c:acquire_device_for_read(). */
Dmsg1(29, "open failed: %s", errmsg);
+ /* Previous open failed. See if we can recover */
if ((omode == OPEN_READ_ONLY || omode == OPEN_READ_WRITE) &&
(part > num_dvd_parts)) {
- /* If the last part (on spool), doesn't exists when accessing,
+ /* If the last part (on spool), doesn't exist when accessing,
* create it. In read/write mode a write will be allowed (higher
* level software thinks that we are extending a pre-existing
* media. Reads for READ_ONLY will report immediately an EOF
* Sometimes it is better to finish with an EOF than with an error. */
Dmsg1(29, "Creating last part on spool: %s\n", archive_name.c_str());
+ omode = CREATE_READ_WRITE;
set_mode(CREATE_READ_WRITE);
fd = ::open(archive_name.c_str(), mode, 0640);
set_mode(omode);
}
-
- /* We don't need it. Only the last part is on spool */
- /*if (omode == OPEN_READ_ONLY) {
- make_spooled_dvd_filename(this, archive_name);
- fd = ::open(archive_name.c_str(), mode, 0640); // try on spool
- }*/
}
Dmsg1(100, "after open fd=%d\n", fd);
if (fd >= 0) {
+ if (omode == OPEN_READ_WRITE || omode == CREATE_READ_WRITE) {
+ set_append();
+ }
/* Get size of file */
if (fstat(fd, &filestat) < 0) {
berrno be;
part_size = filestat.st_size;
dev_errno = 0;
update_pos_dev(this); /* update position */
-
- /* NB: It seems this code is wrong... part number is incremented in open_next_part, not here */
-
- /* Check if just created Volume part */
-/*
- * if (omode == OPEN_READ_WRITE && (part == 0 || part_size == 0)) {
- * part++;
- * num_dvd_parts = part;
- * VolCatInfo.VolCatParts = num_dvd_parts;
- * } else {
- * if (part == 0) { // we must have opened the first part
- * part++;
- * }
- * }
- */
-
}
}
}
/* Restore Volume header record */
memcpy(&dev->VolHdr, &VolHdr, sizeof(dev->VolHdr));
dev->set_labeled(); /* all next parts are "labeled" */
- if (dev->part > dev->num_dvd_parts) { /* set append if new part created */
- dev->set_append();
- }
return dev->fd;
}
Dmsg0(400, "open dev() failed\n");
return -1;
}
- if (dev->part > dev->num_dvd_parts) { /* created new part */
- dev->set_append();
- }
Dmsg2(400, "Leave open_first_part state=%s append=%d\n", dev->is_open()?"open":"not open", dev->can_append());
return dev->fd;
{
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
- bool can_write = true;
if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
- /* If device is DVD, attempt to create it */
- if (!dev->is_dvd()) {
- return false;
- }
- if (dev->open(dcr, CREATE_READ_WRITE) < 0) {
- /* We forge on for a DVD but don't do any writing */
- can_write = false;
- }
+ return false;
}
Dmsg2(190, "set append found freshly labeled volume. fd=%d dev=%x\n", dev->fd, dev);
dev->VolHdr.LabelType = VOL_LABEL; /* set Volume label */
dev->set_append();
- if (can_write) {
- if (!write_volume_label_to_block(dcr)) {
- Dmsg0(200, "Error from write volume label.\n");
- return false;
- }
+ if (!write_volume_label_to_block(dcr)) {
+ Dmsg0(200, "Error from write volume label.\n");
+ return false;
}
/*
* If we are not dealing with a streaming device,
* We do not write the block now if this is an ANSI label. This
* avoids re-writing the ANSI label, which we do not want to do.
*/
- if (can_write && !dev_cap(dev, CAP_STREAM)) {
+ if (!dev_cap(dev, CAP_STREAM)) {
if (!dev->rewind(dcr)) {
- Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device %s: ERR=%s\n"),
+ Jmsg2(jcr, M_FATAL, 0, _("Rewind error on device %s: ERR=%s\n"),
dev->print_name(), dev->bstrerror());
+ return false;
}
if (recycle) {
if (!dev->truncate(dcr)) {
- Jmsg2(jcr, M_WARNING, 0, _("Truncate error on device %s: ERR=%s\n"),
+ Jmsg2(jcr, M_FATAL, 0, _("Truncate error on device %s: ERR=%s\n"),
dev->print_name(), dev->bstrerror());
+ return false;
}
}
* End writing real Volume label (from pre-labeled tape), or recycling
* the volume.
*/
- Dmsg0(200, "OK from rewite vol label.\n");
+ Dmsg0(200, "OK from rewrite vol label.\n");
return true;
}
bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
dev->VolHdr.VerNum = BaculaTapeVersion;
- if (dev->is_dvd() && dvdnow) {
+ if (dev->is_dvd()) {
/* We do not want to re-label a DVD so write VOL_LABEL now */
dev->VolHdr.LabelType = VOL_LABEL;
} else {
if (vol->dcr == dcr && (vol->dev == NULL ||
strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
vol_list->remove(vol);
- Dmsg1(100, "free_unused_olume %s\n", vol->vol_name);
+ Dmsg1(100, "free_unused_volume %s\n", vol->vol_name);
free(vol->vol_name);
free(vol);
break;
Technical notes on version 1.39
General:
+30Aug06
+kes Apply dvd-handler patch from Richard Mortimer.
+kes Apply dvd error check patch from Richard Mortimer.
+kes Apply bpipe race patch from Richard Mortimer.
+kes Rework how DVD labels are handled and set append only
+ when part > num_dvd_parts.
27Aug06
kes Rework many features of DVD writing and reading. Added many error
messages. Most importantly changed part to represent the current