- New communications protocol between DIR and SD to reserve
drives. The DIR and SD are no longer compatible with 1.36 or
lower versions.
-- Preliminary Python Event support has been added. See below for
+- Python Event support has been added. See below for
configuration and details.
- DVD writing support, using parts, and a lot of new directives in
the Device resource of the Storage configuration file.
- Seven new options keywords in a FileSet resource:
ignorecase, fstype, hfsplussupport, wilddir, wildfile, regexdir,
and regexfile. See below for details.
+- Restore of all files for a Job or set of jobs even if the file
+ records have been removed from the catalog.
+- Restore of a directory (non-recursive, i.e. only one level).
+- Support for Unicode filenames on Win32.
+- Support for TLS (ssl) between all the daemon connections.
New Directives:
- New Run directive in Job resource of DIR. It permits
(http://fy.chalmers.se/~appro/linux/DVD+RW/).
- Part files support: File volumes can now be splitted in multiple
files, called "parts".
+
+NOTE THE FOLLOWING IS NOW OUT OF DATE!!!!
- Python scripting support:
A Python script will be called at particular points or conditions
in Bacula called Events. The currently defined Events are called:
AC_PATH_PROG(GROWISOFS, growisofs, growisofs)
AC_PATH_PROG(DVDRWMEDIAINFO, dvd+rw-mediainfo, dvd+rw-mediainfo)
AC_PATH_PROG(PKGCONFIG, pkg-config, pkg-config)
-AC_PATH_PROG(WXCONFIG, wx-config, /opt/gnome/bin/wx-config)
+AC_PATH_PROG(WXCONFIG, wx-config, wx-config)
AC_PATH_PROG(CDRECORD, cdrecord, cdrecord)
AC_PATH_PROG(PIDOF, pidof, pidof)
AC_PROG_AWK
done
done
- test -z "$ac_cv_path_WXCONFIG" && ac_cv_path_WXCONFIG="/opt/gnome/bin/wx-config"
+ test -z "$ac_cv_path_WXCONFIG" && ac_cv_path_WXCONFIG="wx-config"
;;
esac
fi
- Make "update slots" when pointing to Autochanger, remove
all Volumes from other drives. "update slots all-drives"?
+Document:
+- Pruning with Admin job.
For 1.37:
- Python:
- If drive is opened read/write, close it and re-open
read-only if doing a restore, and vice-versa.
-- SD crashes after a tape restore then doing a backup.
-- Implement some way to turn off automatic pruning in Jobs.
-- Implement a way an Admin Job can prune, possibly multiple
- clients -- Python script?
- Implement "NewVolumeEachJob = yes|no" in Dir.
-- Look at Preben's acl.c error handling code.
- Implement Maximum Job Spool Size
- Remove all old Device resource code in Dir and code to pass it
back in SD -- better, rework it to pass back device statistics.
- Check locking of resources -- be sure to lock devices where previously
resources were locked.
- Add global lock on all devices when creating a device structure.
-- Look at adding full Volume and Pool information to a Volume
- label so that bscan can get *all* the info.
- Fix FD JobType to be set before RunBeforeJob in FD.
- Autorestart on crash.
Maybe in 1.37:
+- Look at adding full Volume and Pool information to a Volume
+ label so that bscan can get *all* the info.
- If the user puts "Purge Oldest Volume = yes" or "Recycle Oldest Volume = yes"
and there is only one volume in the pool, refuse to do it -- otherwise
he fills the Volume, then immediately starts reusing it.
- Look at dird_conf.c:1000: warning: `int size'
might be used uninitialized in this function
- Indicate when a Job is purged/pruned during restore.
+- Implement some way to turn off automatic pruning in Jobs.
+- Implement a way an Admin Job can prune, possibly multiple
+ clients -- Python script?
+- Look at Preben's acl.c error handling code.
+- SD crashes after a tape restore then doing a backup.
+
open_dev(DEVICE *dev, char *VolName, int mode)
{
if (dev->is_open()) {
- /*
- * *****FIXME***** how to handle two threads wanting
- * different volumes mounted???? E.g. one is waiting
- * for the next volume to be mounted, and a new job
- * starts and snatches up the device.
- */
- if (VolName && strcmp(dev->VolCatInfo.VolCatName, VolName) != 0) {
- return -1;
+ if (dev->openmode == mode) {
+ return dev->fd;
+ } else {
+ close(dev->fd); /* close so correct mode will be used */
}
- dev->use_count++;
- Mmsg2(dev->errmsg, _("WARNING!!!! device %s opened %d times!!!\n"),
- dev->print_name(), dev->use_count);
- Emsg1(M_WARNING, 0, "%s", dev->errmsg);
- return dev->fd;
}
if (VolName) {
bstrncpy(dev->VolCatInfo.VolCatName, VolName, sizeof(dev->VolCatInfo.VolCatName));
int timeout;
int ioerrcnt = 10;
Dmsg0(29, "open_dev: device is tape\n");
+
if (mode == OPEN_READ_WRITE) {
dev->mode = O_RDWR | O_BINARY;
} else if (mode == OPEN_READ_ONLY) {
break;
}
if (dev->fd >= 0) {
- if (mode != 0) {
- /* If opened in non-block mode, close it an open it normally */
- mode = 0;
+ /* If opened in non-block mode, close it an open it normally */
+ if (nonblocking) {
+ nonblocking = 0;
close(dev->fd);
goto open_again;
}
+ dev->openmode = mode; /* save open mode */
dev->dev_errno = 0;
dev->state |= ST_OPENED;
dev->use_count = 1;
- update_pos_dev(dev); /* update position */
+ update_pos_dev(dev); /* update position */
set_os_device_parameters(dev); /* do system dependent stuff */
Dmsg0(500, "Open OK\n");
}
dev->tid = 0;
}
dev->use_count = 0;
+ dev->openmode = 0;
}
/*
/* New access control in process of being implemented */
brwlock_t lock; /* New mutual exclusion lock */
- int use_count; /* usage count on this device */
+ int use_count; /* usage count on this device 0 or 1 */
int fd; /* file descriptor */
int capabilities; /* capabilities mask */
int state; /* state mask */
return true;
}
- if (!dev->is_open()) {
- int mode;
- if (dev_cap(dev, CAP_STREAM)) {
- mode = OPEN_WRITE_ONLY;
- } else {
- mode = OPEN_READ_WRITE;
- }
- Dmsg0(129, "Opening device.\n");
- dev->open_nowait = true;
- if (open_dev(dev, NULL, mode) < 0) {
- Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
- dev->open_nowait = false;
- unlock_device(dev);
- return false;
- }
+ int mode;
+ if (dev_cap(dev, CAP_STREAM)) {
+ mode = OPEN_WRITE_ONLY;
+ } else {
+ mode = OPEN_READ_WRITE;
+ }
+ Dmsg0(129, "Opening device.\n");
+ dev->open_nowait = true;
+ if (open_dev(dev, NULL, mode) < 0) {
+ Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
+ dev->open_nowait = false;
+ unlock_device(dev);
+ return false;
}
Dmsg1(129, "open_dev %s OK\n", dev->print_name());
dev->open_nowait = false;
{
DEVICE *dev = dcr->dev;
/* Open device */
- if (!dev->is_open()) {
- int mode;
- if (dev_cap(dev, CAP_STREAM)) {
- mode = OPEN_WRITE_ONLY;
- } else {
- mode = OPEN_READ_WRITE;
- }
- if (open_dev(dev, dcr->VolCatInfo.VolCatName, mode) < 0) {
- /* If polling, ignore the error */
- if (!dev->poll) {
- Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
- Pmsg2(000, "Unable to open archive %s: ERR=%s\n",
- dev->print_name(), strerror_dev(dev));
- }
- return false;
+ int mode;
+ if (dev_cap(dev, CAP_STREAM)) {
+ mode = OPEN_WRITE_ONLY;
+ } else {
+ mode = OPEN_READ_WRITE;
+ }
+ if (open_dev(dev, dcr->VolCatInfo.VolCatName, mode) < 0) {
+ /* If polling, ignore the error */
+ if (!dev->poll) {
+ Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"),
+ dev->print_name(), strerror_dev(dev));
+ Pmsg2(000, "Unable to open archive %s: ERR=%s\n",
+ dev->print_name(), strerror_dev(dev));
}
+ return false;
}
return true;
}
}
} else {
if (!dev->is_tape()) {
- bnet_fsend(dir, _("3906 cannot mount non-tape.\n"));
+ /* Nothing to do */
break;
}
if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
} else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) {
Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
dev->dev_blocked);
- open_dev(dev, NULL, 0); /* fake open for close */
offline_or_rewind_dev(dev);
force_close_dev(dev);
dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
/* block_device(dev, BST_UNMOUNTED); replace with 2 lines below */
dev->dev_blocked = BST_UNMOUNTED;
dev->no_wait_id = 0;
- open_dev(dev, NULL, 0); /* fake open for close */
offline_or_rewind_dev(dev);
force_close_dev(dev);
bnet_fsend(dir, _("3002 Device %s unmounted.\n"),