From 9088cfd03ff08b98e6850ec75e9e0d12c4efca48 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 31 Jul 2010 18:54:35 +0200 Subject: [PATCH] More backport from Branch-5.1 to Branch-5.0 --- bacula/scripts/Makefile.in | 5 +- bacula/scripts/mtx-changer.in | 7 +- bacula/src/lib/bpipe.c | 3 +- bacula/src/lib/bsock.c | 39 +- bacula/src/lib/mntent_cache.c | 449 +++++++++++++++++++ bacula/src/lib/mntent_cache.h | 52 +++ bacula/src/lib/util.c | 12 +- bacula/src/qt-console/mainwin.cpp | 4 +- bacula/src/qt-console/pages.cpp | 9 + bacula/src/qt-console/pages.h | 2 + bacula/src/qt-console/run/run.cpp | 2 + bacula/src/qt-console/util/fmtwidgetitem.cpp | 2 +- bacula/src/stored/autochanger.c | 10 +- bacula/src/stored/btape.c | 1 + bacula/src/stored/mac.c | 24 +- bacula/src/tools/bbatch.c | 43 +- 16 files changed, 624 insertions(+), 40 deletions(-) create mode 100644 bacula/src/lib/mntent_cache.c create mode 100644 bacula/src/lib/mntent_cache.h diff --git a/bacula/scripts/Makefile.in b/bacula/scripts/Makefile.in index 374043256f..3295014881 100755 --- a/bacula/scripts/Makefile.in +++ b/bacula/scripts/Makefile.in @@ -65,8 +65,10 @@ install: installdirs $(INSTALL_SCRIPT) dvd-handler $(DESTDIR)$(scriptdir)/dvd-handler $(INSTALL_DATA) btraceback.gdb $(DESTDIR)$(scriptdir)/btraceback.gdb $(INSTALL_DATA) btraceback.dbx $(DESTDIR)$(scriptdir)/btraceback.dbx + $(INSTALL_DATA) btraceback.mdb $(DESTDIR)$(scriptdir)/btraceback.mdb chmod 0644 $(DESTDIR)$(scriptdir)/btraceback.gdb \ - $(DESTDIR)$(scriptdir)/btraceback.dbx + $(DESTDIR)$(scriptdir)/btraceback.dbx \ + $(DESTDIR)$(scriptdir)/btraceback.mdb $(INSTALL_SCRIPT) btraceback $(DESTDIR)$(sbindir)/btraceback @@ -86,6 +88,7 @@ uninstall: (cd $(DESTDIR)$(scriptdir); $(RMF) dvd-handler) (cd $(DESTDIR)$(scriptdir); $(RMF) btraceback.gdb) (cd $(DESTDIR)$(scriptdir); $(RMF) btraceback.dbx) + (cd $(DESTDIR)$(scriptdir); $(RMF) btraceback.mdb) (cd $(DESTDIR)$(sbindir); $(RMF) btraceback) Makefile: Makefile.in diff --git a/bacula/scripts/mtx-changer.in b/bacula/scripts/mtx-changer.in index 5aa9926747..ca5c5481ff 100644 --- a/bacula/scripts/mtx-changer.in +++ b/bacula/scripts/mtx-changer.in @@ -215,7 +215,7 @@ case $cmd in fi ${MTX} -f $ctl status >${TMPFILE} rtn=$? - # can be converted to awk+sed+cut, contributions are welcome + # can be converted to awk+sed+cut, see below perl -ne ' /Data Transfer Element (\d+):Empty/ && print "D:$1:E\n"; /Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "D:$1:F:$2:$4\n"; @@ -223,6 +223,11 @@ case $cmd in /Storage Element (\d+):Full( :VolumeTag=(.+))?/ && print "S:$1:F:$3\n"; /Storage Element (\d+) IMPORT.EXPORT:Empty/ && print "I:$1:E\n"; /Storage Element (\d+) IMPORT.EXPORT:Full( :VolumeTag=(.+))?/ && print "I:$1:F:$3\n";' ${TMPFILE} + # If perl isn't installed, you can use by those commands +#cat ${TMPFILE} | grep "Data Transfer Element" | awk "{print \"D:\"\$4 \$7 \$9 \$10}" | sed "s/=/:/" | sed "s/Full/F:/" | sed "s/Empty/E/" +#cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep -v "IMPORT/EXPORT" | awk "{print \"S:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/" +#cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep "IMPORT/EXPORT" | awk "{print \"I:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/" + rm -f ${TMPFILE} >/dev/null 2>&1 exit $rtn ;; diff --git a/bacula/src/lib/bpipe.c b/bacula/src/lib/bpipe.c index cd0aaedf3b..79a6c0cbce 100644 --- a/bacula/src/lib/bpipe.c +++ b/bacula/src/lib/bpipe.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2002-2008 Free Software Foundation Europe e.V. + Copyright (C) 2002-2010 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -30,7 +30,6 @@ * * Kern Sibbald, November MMII * - * Version $Id$ */ diff --git a/bacula/src/lib/bsock.c b/bacula/src/lib/bsock.c index 80fabde618..94efd6bfe4 100644 --- a/bacula/src/lib/bsock.c +++ b/bacula/src/lib/bsock.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2007-2008 Free Software Foundation Europe e.V. + Copyright (C) 2007-2010 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -30,7 +30,6 @@ * * by Kern Sibbald * - * Version $Id: $ */ @@ -334,9 +333,29 @@ bool BSOCK::send() int32_t *hdr; bool ok = true; - if (errors || is_terminated() || msglen > 1000000) { + if (errors) { + if (!m_suppress_error_msgs) { + Qmsg4(m_jcr, M_ERROR, 0, _("Socket has errors=%d on call to %s:%s:%d\n"), + errors, m_who, m_host, m_port); + } + return false; + } + if (is_terminated()) { + if (!m_suppress_error_msgs) { + Qmsg4(m_jcr, M_ERROR, 0, _("Socket is terminated=%d on call to %s:%s:%d\n"), + is_terminated(), m_who, m_host, m_port); + } + return false; + } + if (msglen > 4000000) { + if (!m_suppress_error_msgs) { + Qmsg4(m_jcr, M_ERROR, 0, + _("Socket has insane msglen=%d on call to %s:%s:%d\n"), + msglen, m_who, m_host, m_port); + } return false; } + if (m_use_locking) P(m_mutex); /* Compute total packet length */ if (msglen <= 0) { @@ -649,6 +668,7 @@ int BSOCK::get_peer(char *buf, socklen_t buflen) bool BSOCK::set_buffer_size(uint32_t size, int rw) { uint32_t dbuf_size, start_size; + #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT) int opt; opt = IPTOS_THROUGHPUT; @@ -665,6 +685,17 @@ bool BSOCK::set_buffer_size(uint32_t size, int rw) Qmsg0(get_jcr(), M_FATAL, 0, _("Could not malloc BSOCK data buffer\n")); return false; } + + /* + * If user has not set the size, use the OS default -- i.e. do not + * try to set it. This allows sys admins to set the size they + * want in the OS, and Bacula will comply. See bug #1493 + */ + if (size == 0) { + msglen = dbuf_size; + return true; + } + if (rw & BNET_SETBUF_READ) { while ((dbuf_size > TAPE_BSIZE) && (setsockopt(m_fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) { @@ -1021,7 +1052,7 @@ bail_out: bsnprintf(msg, msglen, _("Authorization problem with Director at \"%s:%d\"\n" "Most likely the passwords do not agree.\n" "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n" - "Please see http://www.bacula.org/5.0.x-manuals/Auth-Error for help.\n"), + "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"), dir->host(), dir->port()); return false; } diff --git a/bacula/src/lib/mntent_cache.c b/bacula/src/lib/mntent_cache.c new file mode 100644 index 0000000000..def077c47e --- /dev/null +++ b/bacula/src/lib/mntent_cache.c @@ -0,0 +1,449 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2009-2010 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ + +/** + * This code implements a cache with the current mounted filesystems for which + * its uses the mostly in kernel mount information and export the different OS + * specific interfaces using a generic interface. We use a hashed cache which is + * accessed using a hash on the device id and we keep the previous cache hit as + * most of the time we get called quite a lot with most of the time the same + * device so keeping the previous cache hit we have a very optimized code path. + * + * This interface is implemented for the following OS-es: + * + * - Linux + * - HPUX + * - DARWIN (OSX) + * - IRIX + * - AIX + * - OSF1 (True64) + * - Solaris + * + * Currently we only use this code for Linux and OSF1 based fstype determination. + * For the other OS-es we can use the fstype present in stat structure on those OS-es. + * + * This code replaces the big switch we used before based on SUPER_MAGIC present in + * the statfs(2) structure but which need extra code for each new filesystem added to + * the OS and for Linux that tends to be often as it has quite some different filesystems. + * This new implementation should eliminate this as we use the Linux /proc/mounts in kernel + * data which automatically adds any new filesystem when added to the kernel. + */ + +/* + * Marco van Wieringen, August 2009 + */ + +#include "bacula.h" +#include "mntent_cache.h" + +#include +#include +#include +#include +#include + +#if defined(HAVE_GETMNTENT) +#if defined(HAVE_LINUX_OS) || defined(HAVE_HPUX_OS) +#include +#elif defined(HAVE_SUN_OS) +#include +#endif /* HAVE_GETMNTENT */ +#elif defined(HAVE_GETMNTINFO) +#if defined(HAVE_DARWIN_OS) +#include +#include +#include +#else +#include +#include +#endif +#elif defined(HAVE_AIX_OS) +#include +#include +#elif defined(HAVE_OSF1_OS) +#include +#endif + +static char cache_initialized = 0; + +/** + * Protected data by mutex lock. + */ +static pthread_mutex_t mntent_cache_lock = PTHREAD_MUTEX_INITIALIZER; +static mntent_cache_entry_t *mntent_cache_entry_hashtable[NR_MNTENT_CACHE_ENTRIES]; +static mntent_cache_entry_t *previous_cache_hit = NULL; + +/** + * Simple hash function. + */ +static uint32_t mntent_hash_function(uint32_t dev) +{ + return (dev % NR_MNTENT_CACHE_ENTRIES); +} + +/** + * Add a new entry to the cache. + * This function should be called with a write lock on the mntent_cache. + */ +static void add_mntent_mapping(uint32_t dev, const char *special, const char *mountpoint, + const char *fstype, const char *mntopts) +{ + uint32_t hash; + mntent_cache_entry_t *mce; + + /** + * Select the correct hash bucket. + */ + hash = mntent_hash_function(dev); + + /** + * See if this is the first being put into the hash bucket. + */ + if (mntent_cache_entry_hashtable[hash] == (mntent_cache_entry_t *)NULL) { + mce = (mntent_cache_entry_t *)malloc(sizeof(mntent_cache_entry_t)); + memset((caddr_t)mce, 0, sizeof(mntent_cache_entry_t)); + mntent_cache_entry_hashtable[hash] = mce; + } else { + /** + * Walk the linked list in the hash bucket. + */ + for (mce = mntent_cache_entry_hashtable[hash]; mce->next != NULL; mce = mce->next) ; + mce->next = (mntent_cache_entry_t *)malloc(sizeof(mntent_cache_entry_t)); + mce = mce->next; + memset((caddr_t)mce, 0, sizeof(mntent_cache_entry_t)); + } + + mce->dev = dev; + mce->special = bstrdup(special); + mce->mountpoint = bstrdup(mountpoint); + mce->fstype = bstrdup(fstype); + if (mntopts) { + mce->mntopts = bstrdup(mntopts); + } +} + +/** + * OS specific function to load the different mntents into the cache. + * This function should be called with a write lock on the mntent_cache. + */ +static void refresh_mount_cache(void) +{ +#if defined(HAVE_GETMNTENT) + FILE *fp; + struct stat st; +#if defined(HAVE_LINUX_OS) || defined(HAVE_HPUX_OS) || defined(HAVE_IRIX_OS) + struct mntent *mnt; + +#if defined(HAVE_LINUX_OS) + if ((fp = setmntent("/proc/mounts", "r")) == (FILE *)NULL) { + if ((fp = setmntent(_PATH_MOUNTED, "r")) == (FILE *)NULL) { + return; + } + } +#elif defined(HAVE_HPUX_OS) + if ((fp = fopen(MNT_MNTTAB, "r")) == (FILE *)NULL) { + return; + } +#elif defined(HAVE_IRIX_OS) + if ((fp = setmntent(MOUNTED, "r")) == (FILE *)NULL) { + return; + } +#endif + + while ((mnt = getmntent(fp)) != (struct mntent *)NULL) { + if (stat(mnt->mnt_dir, &st) < 0) { + continue; + } + + add_mntent_mapping(st.st_dev, mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts); + } + + endmntent(fp); +#elif defined(HAVE_SUN_OS) + struct mnttab mnt; + + if ((fp = fopen(MNTTAB, "r")) == (FILE *)NULL) + return; + + while (getmntent(fp, &mnt) == 0) { + if (stat(mnt.mnt_mountp, &st) < 0) { + continue; + } + + add_mntent_mapping(st.st_dev, mnt.mnt_special, mnt.mnt_mountp, mnt.mnt_fstype, mnt.mnt_mntopts); + } + + fclose(fp); +#endif /* HAVE_SUN_OS */ +#elif defined(HAVE_GETMNTINFO) + int cnt; + struct stat st; +#if defined(HAVE_DARWIN_OS) + struct statfs *mntinfo; +#else + struct statvfs *mntinfo; +#endif + + if ((cnt = getmntinfo(&mntinfo, MNT_NOWAIT)) > 0) { + while (cnt > 0) { + if (stat(mntinfo->f_mntonname, &st) == 0) { + add_mntent_mapping(st.st_dev, + mntinfo->f_mntfromname, + mntinfo->f_mntonname, + mntinfo->f_fstypename, + NULL); + } + mntinfo++; + cnt--; + } + } +#elif defined(HAVE_AIX_OS) + int bufsize; + char *entries, *current; + struct vmount *vmp; + struct stat st; + struct vfs_ent *ve; + int n_entries, cnt; + + if (mntctl(MCTL_QUERY, sizeof(bufsize), (struct vmount *)&bufsize) != 0) { + return; + } + + entries = malloc(bufsize); + if ((n_entries = mntctl(MCTL_QUERY, bufsize, (struct vmount *) entries)) < 0) { + free(entries); + return; + } + + cnt = 0; + current = entries; + while (cnt < n_entries) { + vmp = (struct vmount *)current; + + if (stat(current + vmp->vmt_data[VMT_STUB].vmt_off, &st) < 0) { + continue; + } + + ve = getvfsbytype(vmp->vmt_gfstype); + if (ve && ve->vfsent_name) { + add_mntent_mapping(st.st_dev, + current + vmp->vmt_data[VMT_OBJECT].vmt_off, + current + vmp->vmt_data[VMT_STUB].vmt_off, + ve->vfsent_name, + current + vmp->vmt_data[VMT_ARGS].vmt_off); + } + current = current + vmp->vmt_length; + cnt++; + } + free(entries); +#elif defined(HAVE_OSF1_OS) + struct statfs *entries, *current; + struct stat st; + int n_entries, cnt; + int size; + + if ((n_entries = getfsstat((struct statfs *)0, 0L, MNT_NOWAIT)) < 0) { + return; + } + + size = (n_entries + 1) * sizeof(struct statfs); + entries = malloc(size); + + if ((n_entries = getfsstat(entries, size, MNT_NOWAIT)) < 0) { + free(entries); + return; + } + + cnt = 0; + current = entries; + while (cnt < n_entries) { + if (stat(current->f_mntonname, &st) < 0) { + continue; + } + add_mntent_mapping(st.st_dev, + current->f_mntfromname, + current->f_mntonname, + current->f_fstypename, + NULL); + current++; + cnt++; + } + free(stats); +#endif +} + +/** + * Clear the cache (either by flushing it or by initializing it.) + * This function should be called with a write lock on the mntent_cache. + */ +static void clear_mount_cache() +{ + uint32_t hash; + mntent_cache_entry_t *mce, *mce_next; + + if (cache_initialized == 0) { + /** + * Initialize the hash table. + */ + memset((caddr_t)mntent_cache_entry_hashtable, 0, NR_MNTENT_CACHE_ENTRIES * sizeof(mntent_cache_entry_t *)); + cache_initialized = 1; + } else { + /** + * Clear the previous_cache_hit. + */ + previous_cache_hit = NULL; + + /** + * Walk all hash buckets. + */ + for (hash = 0; hash < NR_MNTENT_CACHE_ENTRIES; hash++) { + /** + * Walk the content of this hash bucket. + */ + mce = mntent_cache_entry_hashtable[hash]; + mntent_cache_entry_hashtable[hash] = NULL; + while (mce != NULL) { + /** + * Save the pointer to the next entry. + */ + mce_next = mce->next; + + /** + * Free the structure. + */ + if (mce->mntopts) + free(mce->mntopts); + free(mce->fstype); + free(mce->mountpoint); + free(mce->special); + free(mce); + + mce = mce_next; + } + } + } +} + +/** + * Initialize the cache for use. + */ +static void initialize_mntent_cache(void) +{ + /** + * Lock the cache while we update it. + */ + P(mntent_cache_lock); + + /** + * Make sure the cache is empty (either by flushing it or by initializing it.) + */ + clear_mount_cache(); + + /** + * Refresh the cache. + */ + refresh_mount_cache(); + + /** + * We are done updating the cache. + */ + V(mntent_cache_lock); +} + +void preload_mntent_cache(void) +{ + initialize_mntent_cache(); +} + +void flush_mntent_cache(void) +{ + /** + * Lock the cache while we update it. + */ + P(mntent_cache_lock); + + /** + * Make sure the cache is empty (either by flushing it or by initializing it.) + */ + clear_mount_cache(); + + /** + * We are done updating the cache. + */ + V(mntent_cache_lock); +} + +/** + * Find a mapping in the cache. + */ +mntent_cache_entry_t *find_mntent_mapping(uint32_t dev) +{ + uint32_t hash; + mntent_cache_entry_t *mce; + + /** + * Initialize the cache if that was not done before. + */ + if (cache_initialized == 0) { + initialize_mntent_cache(); + } + + /** + * Shortcut when we get a request for the same device again. + */ + if (previous_cache_hit && previous_cache_hit->dev == dev) { + return previous_cache_hit; + } + + /** + * Lock the cache while we walk it. + */ + P(mntent_cache_lock); + + /** + * Select the correct hash bucket. + */ + hash = mntent_hash_function(dev); + + /** + * Walk the hash bucket. + */ + for (mce = mntent_cache_entry_hashtable[hash]; mce != NULL; mce = mce->next) { + if (mce->dev == dev) { + previous_cache_hit = mce; + V(mntent_cache_lock); + return mce; + } + } + + /** + * We are done walking the cache. + */ + V(mntent_cache_lock); + return NULL; +} diff --git a/bacula/src/lib/mntent_cache.h b/bacula/src/lib/mntent_cache.h new file mode 100644 index 0000000000..39b7e2ff48 --- /dev/null +++ b/bacula/src/lib/mntent_cache.h @@ -0,0 +1,52 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2009-2010 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ + +/* + * Marco van Wieringen, August 2009 + */ + +#ifndef _MNTENT_CACHE_H +#define _MNTENT_CACHE_H 1 + +#define NR_MNTENT_CACHE_ENTRIES 32 + +struct mntent_cache_entry_t { + uint32_t dev; + char *special; + char *mountpoint; + char *fstype; + char *mntopts; + struct mntent_cache_entry_t *next; +}; + +mntent_cache_entry_t *find_mntent_mapping(uint32_t dev); + +void preload_mntent_cache(void); +void flush_mntent_cache(void); + +#endif /* _MNTENT_CACHE_H */ diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index 8f1fb4b21e..c3a5142b8f 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -399,7 +399,7 @@ const char *job_type_to_str(int type) */ char *aop_to_str(int aop, POOL_MEM &ret) { - if (aop & AOP_TRUNCATE) { + if (aop & ON_PURGE_TRUNCATE) { pm_strcpy(ret, _("Truncate")); } if (!aop) { @@ -718,6 +718,8 @@ void decode_session_key(char *decode, char *session, char *key, int maxlen) * %t = Job type (Backup, ...) * %r = Recipients * %v = Volume name + * %b = Job Bytes + * %f = Job Files * * omsg = edited output message * imsg = input string containing edit codes (%x) @@ -728,7 +730,7 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to, job_co { char *p, *q; const char *str; - char add[20]; + char add[50]; char name[MAX_NAME_LENGTH]; int i; @@ -803,6 +805,12 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to, job_co str = _("*none*"); } break; + case 'f': /* Job Files */ + str = edit_uint64(jcr->JobFiles, add); + break; + case 'b': /* Job Bytes */ + str = edit_uint64(jcr->JobBytes, add); + break; case 't': if (jcr) { str = job_type_to_str(jcr->getJobType()); diff --git a/bacula/src/qt-console/mainwin.cpp b/bacula/src/qt-console/mainwin.cpp index 676ee898cb..eca18bd28d 100644 --- a/bacula/src/qt-console/mainwin.cpp +++ b/bacula/src/qt-console/mainwin.cpp @@ -515,9 +515,7 @@ void MainWin::treeItemChanged(QTreeWidgetItem *currentitem, QTreeWidgetItem *pre } /* set the value for the currently active console */ int stackindex = tabWidget->indexOf(nextPage); - if (!nextPage->isOnceDocked()) { - nextPage->dockPage(); - } + nextPage->firstUseDock(); /* Is this page currently on the stack or is it undocked */ if (stackindex >= 0) { diff --git a/bacula/src/qt-console/pages.cpp b/bacula/src/qt-console/pages.cpp index a1700672b2..8537604b02 100644 --- a/bacula/src/qt-console/pages.cpp +++ b/bacula/src/qt-console/pages.cpp @@ -57,6 +57,15 @@ Pages::Pages() m_docked = false; m_onceDocked = false; m_closeable = true; + m_dockOnFirstUse = true; +} + +/* first Use Dock */ +void Pages::firstUseDock() +{ + if (!m_onceDocked && m_dockOnFirstUse) { + dockPage(); + } } /* diff --git a/bacula/src/qt-console/pages.h b/bacula/src/qt-console/pages.h index 6547122406..a31443d103 100644 --- a/bacula/src/qt-console/pages.h +++ b/bacula/src/qt-console/pages.h @@ -78,6 +78,7 @@ public: QString &name() { return m_name; }; void getVolumeList(QStringList &); void getStatusList(QStringList &); + void firstUseDock(); public slots: /* closeEvent is a virtual function inherited from QWidget */ @@ -94,6 +95,7 @@ protected: bool m_closeable; bool m_docked; bool m_onceDocked; + bool m_dockOnFirstUse; Console *m_console; QString m_name; }; diff --git a/bacula/src/qt-console/run/run.cpp b/bacula/src/qt-console/run/run.cpp index cf3c67cb98..60c59b3972 100644 --- a/bacula/src/qt-console/run/run.cpp +++ b/bacula/src/qt-console/run/run.cpp @@ -46,6 +46,7 @@ runPage::runPage() runPage::runPage(const QString &defJob) { + m_dockOnFirstUse = false; init(); if (defJob != "") jobCombo->setCurrentIndex(jobCombo->findText(defJob, Qt::MatchExactly)); @@ -57,6 +58,7 @@ runPage::runPage(const QString &defJob, const QString &level, const QString &pool, const QString &storage, const QString &client, const QString &fileset) { + m_dockOnFirstUse = false; init(); jobCombo->setCurrentIndex(jobCombo->findText(defJob, Qt::MatchExactly)); job_name_change(0); diff --git a/bacula/src/qt-console/util/fmtwidgetitem.cpp b/bacula/src/qt-console/util/fmtwidgetitem.cpp index 817800f6ee..348d2b2ef7 100644 --- a/bacula/src/qt-console/util/fmtwidgetitem.cpp +++ b/bacula/src/qt-console/util/fmtwidgetitem.cpp @@ -221,7 +221,7 @@ void ItemFormatterBase::setPercent(int index, float value) * the tooltip stuff */ void ItemFormatterBase::setPixmap(int index, const QPixmap &pix, - const QString &tip) + const QString & /* tip */) { setPixmap(index, pix); } diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index cb009f1581..40189d6ae1 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -653,7 +653,15 @@ char *edit_device_codes(DCR *dcr, char *omsg, const char *imsg, const char *cmd) str = dcr->jcr->Job; break; case 'v': - str = NPRT(dcr->VolumeName); + if (dcr->VolCatInfo.VolCatName[0]) { + str = dcr->VolCatInfo.VolCatName; + } else if (dcr->VolumeName[0]) { + str = dcr->VolumeName; + } else if (dcr->dev->vol && dcr->dev->vol->vol_name) { + str = dcr->dev->vol->vol_name; + } else { + str = dcr->dev->VolHdr.VolumeName; + } break; case 'f': str = NPRT(dcr->jcr->client_name); diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index d19fbcc7d4..b4fbf4f239 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -2552,6 +2552,7 @@ static bool do_unfill() if (compare_blocks(last_block, block)) { if (simple) { Pmsg0(-1, _("\nThe last block on the tape matches. Test succeeded.\n\n")); + rc = true; } else { Pmsg0(-1, _("\nThe last block of the first tape matches.\n\n")); } diff --git a/bacula/src/stored/mac.c b/bacula/src/stored/mac.c index 1354682784..5641e7e853 100644 --- a/bacula/src/stored/mac.c +++ b/bacula/src/stored/mac.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2006-2009 Free Software Foundation Europe e.V. + Copyright (C) 2006-2010 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -31,7 +31,6 @@ * * Kern Sibbald, January MMVI * - * Version $Id$ */ #include "bacula.h" @@ -187,7 +186,6 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) JCR *jcr = dcr->jcr; DEVICE *dev = jcr->dcr->dev; char buf1[100], buf2[100]; - int32_t stream; #ifdef xxx Dmsg5(000, "on entry JobId=%d FI=%s SessId=%d Strm=%s len=%d\n", @@ -263,25 +261,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len); - /* Send attributes and digest to Director for Catalog */ - stream = rec->Stream; - if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX || - crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) { - if (!jcr->no_attributes) { - BSOCK *dir = jcr->dir_bsock; - if (are_attributes_spooled(jcr)) { - dir->set_spooling(); - } - Dmsg0(850, "Send attributes to dir.\n"); - if (!dir_update_file_attributes(jcr->dcr, rec)) { - dir->clear_spooling(); - Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"), - dir->bstrerror()); - return false; - } - dir->clear_spooling(); - } - } + send_attrs_to_dir(jcr, rec); return true; } diff --git a/bacula/src/tools/bbatch.c b/bacula/src/tools/bbatch.c index 5d2d144b05..c7d5cab557 100644 --- a/bacula/src/tools/bbatch.c +++ b/bacula/src/tools/bbatch.c @@ -87,6 +87,7 @@ PROG_COPYRIGHT " -P specify database host (default NULL)\n" " -w specify working directory\n" +" -r call restore code with given jobids\n" " -v verbose\n" " -f specify data file\n" " -? print this message\n\n"), 2001, VERSION, BDATE); @@ -96,9 +97,17 @@ PROG_COPYRIGHT /* number of thread started */ int nb=0; +static int list_handler(void *ctx, int num_fields, char **row) +{ + uint64_t *a = (uint64_t*) ctx; + (*a)++; + return 0; +} + int main (int argc, char *argv[]) { int ch; + char *restore_list=NULL; setlocale(LC_ALL, ""); bindtextdomain("bacula", LOCALEDIR); textdomain("bacula"); @@ -112,8 +121,12 @@ int main (int argc, char *argv[]) OSDependentInit(); - while ((ch = getopt(argc, argv, "h:c:d:n:P:Su:vf:w:?")) != -1) { + while ((ch = getopt(argc, argv, "h:c:d:n:P:Su:vf:w:r:?")) != -1) { switch (ch) { + case 'r': + restore_list=bstrdup(optarg); + break; + case 'd': /* debug level */ if (*optarg == 't') { dbg_timestamp = true; @@ -169,6 +182,30 @@ int main (int argc, char *argv[]) usage(); } + if (restore_list) { + uint64_t nb_file=0; + btime_t start, end; + /* To use the -r option, the catalog should already contains records */ + + if ((db=db_init(NULL, NULL, db_name, db_user, db_password, + db_host, 0, NULL, 0)) == NULL) { + Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n")); + } + if (!db_open_database(NULL, db)) { + Emsg0(M_ERROR_TERM, 0, db_strerror(db)); + } + + start = get_current_btime(); + db_get_file_list(NULL, db, restore_list, list_handler, &nb_file); + end = get_current_btime(); + + Pmsg3(0, _("Computing file list for jobid=%s files=%lld secs=%d\n"), + restore_list, nb_file, (uint32_t)btime_to_unix(end-start)); + + free(restore_list); + return 0; + } + #ifdef HAVE_BATCH_FILE_INSERT printf("With new Batch mode\n"); #else @@ -198,8 +235,8 @@ int main (int argc, char *argv[]) bjcr->fileset_md5 = get_pool_memory(PM_FNAME); pm_strcpy(bjcr->fileset_md5, "Dummy.fileset.md5"); - if ((db=db_init_database(NULL, db_name, db_user, db_password, - db_host, 0, NULL, 0)) == NULL) { + if ((db=db_init(NULL, NULL, db_name, db_user, db_password, + db_host, 0, NULL, 0)) == NULL) { Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n")); } if (!db_open_database(NULL, db)) { -- 2.39.2