]> git.sur5r.net Git - bacula/bacula/commitdiff
- Add disk-changer to scripts directory + configure/Makefile
authorKern Sibbald <kern@sibbald.com>
Tue, 14 Feb 2006 14:11:10 +0000 (14:11 +0000)
committerKern Sibbald <kern@sibbald.com>
Tue, 14 Feb 2006 14:11:10 +0000 (14:11 +0000)
- Eliminate PoolId from jcr -- it is in jcr->jr.PoolId
- Implement store_bit scanner to replace store_yesno.  Mostly done.
- Implement new store_bool that stores in a bool.
- Add true/false to yes/no conf directives.
- Make first cut at changing appropriate store_yesno to store_bool.
- Complete implementation of Pool storage devices.
- Move starting clones to job.c
- Move create_restore_bootstrap_file() to job.c
- Make copy_storage() more general to be able to handle
  Pool storage.
- Cleanup a lot of migration code for manual running, including
  using Pool storage.
- Move getting a scratch Volume into a subroutine.
- Make all places a Volume that is added to a pool to
  respect max vols.
- Fix bug in autochanger recycle code (improper edit 64 bit).
- Fix segfault in restore command when no value specified.
- Start adding code to handle multiple MediaTypes in restore.
- Eliminate race condition in getting Volume name for
  two drive autochanger.
- More debug code in autochanger.
- Add storage keyword to bootstrap file, add parsing.
- Move slot in bsr file into Volume record as there will be
  a different slot for each Volume.
- Create reserve.h

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2784 91ce42f0-d328-0410-95d8-f526ca767f89

56 files changed:
bacula/autoconf/configure.in
bacula/configure
bacula/kernstodo
bacula/kes-1.39
bacula/scripts/.cvsignore
bacula/scripts/Makefile.in
bacula/scripts/disk-changer.in [new file with mode: 0644]
bacula/scripts/mtx-changer.in
bacula/src/cats/sql_find.c
bacula/src/console/console_conf.c
bacula/src/dird/autoprune.c
bacula/src/dird/backup.c
bacula/src/dird/catreq.c
bacula/src/dird/dird.c
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/job.c
bacula/src/dird/jobq.c
bacula/src/dird/mac.c
bacula/src/dird/newvol.c
bacula/src/dird/next_vol.c
bacula/src/dird/protos.h
bacula/src/dird/recycle.c
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_label.c
bacula/src/dird/ua_output.c
bacula/src/dird/ua_purge.c
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_status.c
bacula/src/dird/ua_update.c
bacula/src/dird/verify.c
bacula/src/filed/filed_conf.c
bacula/src/gnome2-console/console_conf.c
bacula/src/jcr.h
bacula/src/lib/parse_conf.c
bacula/src/lib/parse_conf.h
bacula/src/stored/acquire.c
bacula/src/stored/askdir.c
bacula/src/stored/autochanger.c
bacula/src/stored/bsr.h
bacula/src/stored/dev.c
bacula/src/stored/dircmd.c
bacula/src/stored/job.c
bacula/src/stored/mount.c
bacula/src/stored/parse_bsr.c
bacula/src/stored/protos.h
bacula/src/stored/reserve.c
bacula/src/stored/reserve.h [new file with mode: 0644]
bacula/src/stored/status.c
bacula/src/stored/stored.c
bacula/src/stored/stored.h
bacula/src/stored/stored_conf.c
bacula/src/stored/wait.c
bacula/src/tray-monitor/tray_conf.c
bacula/src/version.h
bacula/src/wx-console/console_conf.c

index 44a88459e332833fde88f3ffa287fa302fc608d9..984b356e95af71b25d2dd7001469674a47eef438 100644 (file)
@@ -1932,6 +1932,7 @@ AC_OUTPUT([autoconf/Make.common \
           scripts/bacula.desktop.gnome2.xsu \
           scripts/gnome-console.console_apps \
           scripts/mtx-changer \
+          scripts/disk-changer \
           scripts/dvd-handler \
           scripts/bacula-tray-monitor.desktop \
           scripts/logwatch/Makefile \
index 9d85ea7ab17b6cd9b39aeeb3ebd7c2971010597b..6adc9896dea1f78d226bdacdd31d6af47afd838e 100755 (executable)
@@ -29834,7 +29834,7 @@ if test "x${subsysdir}" = "x${sbindir}" ; then
    exit 1
 fi
 
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ac_config_files="$ac_config_files autoconf/Make.common Makefile scripts/startmysql scripts/stopmysql scripts/btraceback scripts/startit scripts/stopit scripts/bconsole scripts/gconsole scripts/bacula scripts/devel_bacula scripts/Makefile scripts/logrotate scripts/bacula.desktop.gnome1 scripts/bacula.desktop.gnome2 scripts/bacula.desktop.gnome1.consolehelper scripts/bacula.desktop.gnome2.consolehelper scripts/bacula.desktop.gnome1.xsu scripts/bacula.desktop.gnome2.xsu scripts/gnome-console.console_apps scripts/mtx-changer scripts/dvd-handler scripts/bacula-tray-monitor.desktop scripts/logwatch/Makefile scripts/logwatch/logfile.bacula.conf src/Makefile src/host.h src/console/Makefile src/console/bconsole.conf src/gnome2-console/Makefile src/gnome2-console/gnome-console.conf src/wx-console/Makefile src/wx-console/wx-console.conf src/tray-monitor/Makefile src/tray-monitor/tray-monitor.conf src/dird/Makefile src/dird/bacula-dir.conf src/lib/Makefile src/stored/Makefile src/stored/bacula-sd.conf src/filed/Makefile src/filed/bacula-fd.conf src/filed/win32/Makefile src/cats/Makefile src/cats/make_catalog_backup src/cats/delete_catalog_backup src/cats/create_postgresql_database src/cats/update_postgresql_tables src/cats/make_postgresql_tables src/cats/grant_postgresql_privileges src/cats/drop_postgresql_tables src/cats/drop_postgresql_database src/cats/create_mysql_database src/cats/update_mysql_tables src/cats/make_mysql_tables src/cats/grant_mysql_privileges src/cats/drop_mysql_tables src/cats/drop_mysql_database src/cats/create_sqlite_database src/cats/update_sqlite_tables src/cats/make_sqlite_tables src/cats/grant_sqlite_privileges src/cats/drop_sqlite_tables src/cats/drop_sqlite_database src/cats/create_sqlite3_database src/cats/update_sqlite3_tables src/cats/make_sqlite3_tables src/cats/grant_sqlite3_privileges src/cats/drop_sqlite3_tables src/cats/drop_sqlite3_database src/cats/sqlite src/cats/mysql src/cats/create_bdb_database src/cats/update_bdb_tables src/cats/make_bdb_tables src/cats/grant_bdb_privileges src/cats/drop_bdb_tables src/cats/drop_bdb_database src/cats/create_bacula_database src/cats/update_bacula_tables src/cats/grant_bacula_privileges src/cats/make_bacula_tables src/cats/drop_bacula_tables src/cats/drop_bacula_database src/findlib/Makefile src/pygtk-console/Makefile src/tools/Makefile src/win32/winbacula.nsi src/win32/baculafd/bacula-fd.conf src/win32/Makefile src/win32/console/bconsole.conf src/win32/wx-console/wx-console.conf src/win32/pebuilder/Makefile po/Makefile.in $PFILES"
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ac_config_files="$ac_config_files autoconf/Make.common Makefile scripts/startmysql scripts/stopmysql scripts/btraceback scripts/startit scripts/stopit scripts/bconsole scripts/gconsole scripts/bacula scripts/devel_bacula scripts/Makefile scripts/logrotate scripts/bacula.desktop.gnome1 scripts/bacula.desktop.gnome2 scripts/bacula.desktop.gnome1.consolehelper scripts/bacula.desktop.gnome2.consolehelper scripts/bacula.desktop.gnome1.xsu scripts/bacula.desktop.gnome2.xsu scripts/gnome-console.console_apps scripts/mtx-changer scripts/disk-changer scripts/dvd-handler scripts/bacula-tray-monitor.desktop scripts/logwatch/Makefile scripts/logwatch/logfile.bacula.conf src/Makefile src/host.h src/console/Makefile src/console/bconsole.conf src/gnome2-console/Makefile src/gnome2-console/gnome-console.conf src/wx-console/Makefile src/wx-console/wx-console.conf src/tray-monitor/Makefile src/tray-monitor/tray-monitor.conf src/dird/Makefile src/dird/bacula-dir.conf src/lib/Makefile src/stored/Makefile src/stored/bacula-sd.conf src/filed/Makefile src/filed/bacula-fd.conf src/filed/win32/Makefile src/cats/Makefile src/cats/make_catalog_backup src/cats/delete_catalog_backup src/cats/create_postgresql_database src/cats/update_postgresql_tables src/cats/make_postgresql_tables src/cats/grant_postgresql_privileges src/cats/drop_postgresql_tables src/cats/drop_postgresql_database src/cats/create_mysql_database src/cats/update_mysql_tables src/cats/make_mysql_tables src/cats/grant_mysql_privileges src/cats/drop_mysql_tables src/cats/drop_mysql_database src/cats/create_sqlite_database src/cats/update_sqlite_tables src/cats/make_sqlite_tables src/cats/grant_sqlite_privileges src/cats/drop_sqlite_tables src/cats/drop_sqlite_database src/cats/create_sqlite3_database src/cats/update_sqlite3_tables src/cats/make_sqlite3_tables src/cats/grant_sqlite3_privileges src/cats/drop_sqlite3_tables src/cats/drop_sqlite3_database src/cats/sqlite src/cats/mysql src/cats/create_bdb_database src/cats/update_bdb_tables src/cats/make_bdb_tables src/cats/grant_bdb_privileges src/cats/drop_bdb_tables src/cats/drop_bdb_database src/cats/create_bacula_database src/cats/update_bacula_tables src/cats/grant_bacula_privileges src/cats/make_bacula_tables src/cats/drop_bacula_tables src/cats/drop_bacula_database src/findlib/Makefile src/pygtk-console/Makefile src/tools/Makefile src/win32/winbacula.nsi src/win32/baculafd/bacula-fd.conf src/win32/Makefile src/win32/console/bconsole.conf src/win32/wx-console/wx-console.conf src/win32/pebuilder/Makefile po/Makefile.in $PFILES"
           ac_config_commands="$ac_config_commands default"
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -30398,6 +30398,7 @@ do
   "scripts/bacula.desktop.gnome2.xsu" ) CONFIG_FILES="$CONFIG_FILES scripts/bacula.desktop.gnome2.xsu" ;;
   "scripts/gnome-console.console_apps" ) CONFIG_FILES="$CONFIG_FILES scripts/gnome-console.console_apps" ;;
   "scripts/mtx-changer" ) CONFIG_FILES="$CONFIG_FILES scripts/mtx-changer" ;;
+  "scripts/disk-changer" ) CONFIG_FILES="$CONFIG_FILES scripts/disk-changer" ;;
   "scripts/dvd-handler" ) CONFIG_FILES="$CONFIG_FILES scripts/dvd-handler" ;;
   "scripts/bacula-tray-monitor.desktop" ) CONFIG_FILES="$CONFIG_FILES scripts/bacula-tray-monitor.desktop" ;;
   "scripts/logwatch/Makefile" ) CONFIG_FILES="$CONFIG_FILES scripts/logwatch/Makefile" ;;
index a857ee2233856893db9307f1830194dde3796d78..df9fc31983fb1655aa6d1cc7549258f88d9d8153 100644 (file)
@@ -1,5 +1,5 @@
                     Kern's ToDo List
-                     11 January 2006
+                     08 February 2006
 
 Major development:      
 Project                     Developer
@@ -15,14 +15,13 @@ Document:
 - %d and %v only valid on Director, not for ClientRunBefore/After.
 
 Priority:
-- Implement a way to disable a drive (so you can use the second
-  drive of an autochanger, and the first one will not be used or
-  even defined).
 - Implement code that makes the Dir aware that a drive is an             
   autochanger (so the user doesn't need to use the Autochanger = yes 
   directive).
 
 For 1.39:
+- Detect resource deadlock in Migrate when same job wants to read
+  and write the same device.
 - Make hardlink code at line 240 of find_one.c use binary search.
 - Queue warning/error messages during restore so that they
   are reported at the end of the report rather than being
@@ -1276,3 +1275,9 @@ Block Position: 0
   integers.
 - Implement status that shows why a job is being held in reserve, or
   rather why none of the drives are suitable.
+- Implement a way to disable a drive (so you can use the second
+  drive of an autochanger, and the first one will not be used or
+  even defined).
+- Make sure Maximum Volumes is respected in Pools when adding
+  Volumes (e.g. when pulling a Scratch volume).
+
index 6cb67deadee5c45a375e89ace7df611f7934a2fb..9e3c3d8711d7544db4b36583fd885f21f6e70e45 100644 (file)
@@ -4,8 +4,61 @@
 General:
 
 Changes to 1.39.5
+14Feb06
+- Add disk-changer to scripts directory + configure/Makefile
+- Eliminate PoolId from jcr -- it is in jcr->jr.PoolId
+- Implement store_bit scanner to replace store_yesno.  Mostly done.
+- Implement new store_bool that stores in a bool. 
+- Add true/false to yes/no conf directives.
+- Make first cut at changing appropriate store_yesno to store_bool.
+- Complete implementation of Pool storage devices.
+- Move starting clones to job.c
+- Move create_restore_bootstrap_file() to job.c
+- Make copy_storage() more general to be able to handle
+  Pool storage.
+- Cleanup a lot of migration code for manual running, including
+  using Pool storage.
+- Move getting a scratch Volume into a subroutine.
+- Make all places a Volume that is added to a pool to 
+  respect max vols.
+- Fix bug in autochanger recycle code (improper edit 64 bit).
+- Fix segfault in restore command when no value specified.
+- Start adding code to handle multiple MediaTypes in restore.
+- Eliminate race condition in getting Volume name for
+  two drive autochanger.
+- More debug code in autochanger.
+- Add storage keyword to bootstrap file, add parsing.
+- Move slot in bsr file into Volume record as there will be
+  a different slot for each Volume.
+- Create reserve.h
+07Feb06
+- Implement Pool storage overrides.
 06Feb06
 - Implement first cut of Migration.
+- Implement mysql_use_result() from patch by Karl Hakimian.
+  This reduces significantly the memory consumption during
+  the restore tree building, and hence runs faster too.
+- Implement StorageId patch supplied by user (reggie) in bug
+  #536.  This should permit Bacula to work correctly with two
+  autochangers.
+- Implement Job listing variations suggested by a user.
+- Move updating bootstrap code in backup.c to subroutine
+  update_bootstrap_file().
+- Add new job status elapsed time and bytes written user
+  friendly job report output patch sent by a user.
+- Implement a storage list in Pools.
+- Separate out setup_job() code from run_job().
+- Get migration working -- lots of changes in mac.c in both
+  DIR and SD.
+- Apply patch from user (Eric Bollinger I think) that fixes a  
+  DIR crash when no arguments are supplied to a dot command.
+- Fix typo (strcpy->strcmp) in ua_prune.c as reported by Martin.
+- Fix command arg name->volume in label command of gnome-console.
+- Fix SD acquire.c to release correct DCR by explicitly testing
+  on the dcr address rather than trying to "devine" if it is a read
+  or write dcr.  This failed in error conditions when the device was
+  not fully setup.
 30Jan06
 - Apply user supplied patch for more readable rate output
   in job report.
index f1c514e9e1c08f1cb8652fc356cb2bbb28787291..e39d44a262e03fac28da57315b1dc542f262014d 100644 (file)
@@ -1,3 +1,4 @@
+disk-changer
 bacula-tray-monitor.desktop
 bacula-tray-monior.desktop
 .xvpics
index d440b3c48ae65e5c56aa8dd4c43f780f2c683276..1bf17739fca92e2b556a2a44a067e9db2ab0641a 100755 (executable)
@@ -43,6 +43,11 @@ install: installdirs
           $(MV) -f ${DESTDIR}${scriptdir}/mtx-changer ${DESTDIR}${scriptdir}/mtx-changer.old; \
        fi
        $(INSTALL_SCRIPT) mtx-changer $(DESTDIR)$(scriptdir)/mtx-changer
+       @if  test -f ${DESTDIR}${scriptdir}/disk-changer; then \
+          echo "  ==> Saving existing disk-changer to disk-changer.old"; \
+          $(MV) -f ${DESTDIR}${scriptdir}/disk-changer ${DESTDIR}${scriptdir}/disk-changer.old; \
+       fi
+       $(INSTALL_SCRIPT) disk-changer $(DESTDIR)$(scriptdir)/disk-changer
        @if  test -f ${DESTDIR}${scriptdir}/dvd-handler; then \
           echo "  ==> Saving existing dvd-handler to dvd-handler.old"; \
           $(MV) -f ${DESTDIR}${scriptdir}/dvd-handler ${DESTDIR}${scriptdir}/dvd-handler.old; \
@@ -66,6 +71,7 @@ uninstall:
        (cd $(DESTDIR)$(scriptdir); $(RMF) bacula)
        (cd $(DESTDIR)$(scriptdir); $(RMF) fd)
        (cd $(DESTDIR)$(scriptdir); $(RMF) mtx-changer)
+       (cd $(DESTDIR)$(scriptdir); $(RMF) disk-changer)
        (cd $(DESTDIR)$(scriptdir); $(RMF) dvd-handler)  
        (cd $(DESTDIR)$(scriptdir); $(RMF) btraceback.gdb)
        (cd $(DESTDIR)$(scriptdir); $(RMF) btraceback.dbx)
@@ -76,7 +82,7 @@ Makefile: Makefile.in
        cd $(topdir) \
            && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
        chmod 755 startmysql stopmysql bacula startit stopit btraceback
-       chmod 755 mtx-changer dvd-handler bconsole gconsole
+       chmod 755 disk-changer mtx-changer dvd-handler bconsole gconsole
 
 Makefiles:
        $(SHELL) config.status
diff --git a/bacula/scripts/disk-changer.in b/bacula/scripts/disk-changer.in
new file mode 100644 (file)
index 0000000..7181c60
--- /dev/null
@@ -0,0 +1,211 @@
+#!/bin/sh
+#
+# Bacula interface to virtual autoloader using disk storage
+#
+#  $Id$
+#
+#  If you set in your Device resource
+#
+#  Changer Command = "path-to-this-script/disk-changer" %c %o %S %a %d
+#    you will have the following input to this script:
+#
+#  So Bacula will always call with all the following arguments, even though
+#    in come cases, not all are used.
+#
+#  disk-changer "changer-device" "command" "slot" "archive-device" "drive-index"
+#                  $1              $2       $3        $4               $5
+#
+# By default the autochanger has 10 Volumes and 1 Drive.
+#
+# Note: For this script to work, you *must" specify
+#    Device Type = File 
+# in each of the Devices associated with your AutoChanger resource.
+#
+# changer-device is the name of a file that overrides the default
+#   volumes and drives.  It may have:
+#       maxslot=n   where n is one based (default 10)
+#       maxdrive=m  where m is zero based (default 1 -- i.e. 2 drives)
+#  
+#   This code can also simulate barcodes. You simply put
+#   a list of the slots and barcodes in the "base" directory/barcodes.
+#   See below for the base directory definition.  Example of a 
+#   barcodes file:
+#      /var/bacula/barcodes
+#      1:Vol001
+#      2:Vol002
+#      ...
+# 
+# archive-device is the name of the base directory where you want the
+#  Volumes stored appended with /drive0 for the first drive; /drive1
+#  for the second drive, ... For example, you might use
+#  /var/bacula/drive0  Note: you must not have a trailing slash, and
+#  the string (e.g. /drive0) must be unique, and it must not match
+#  any other part of the directory name. These restrictions could be
+#  easily removed by any clever script jockey.
+#
+#  Full example: disk-changer /var/bacula/conf load 1 /var/bacula/drive0 0
+#
+# The Volumes will be created with names slot1, slot2, slot3, ... maxslot in the
+#  base directory. In the above example the base directory is /var/bacula.
+#  However, as with tapes, their Bacula Volume names will be stored inside the
+#  Volume label. In addition to the Volumes (e.g. /var/bacula/slot1, 
+#  /var/bacula/slot3, ...) this script will create a /var/bacula/loadedn
+#  file to keep track of what Slot is loaded. You should not change this file.
+#
+#
+
+wd=@working_dir@
+
+#
+# log whats done
+#
+# to turn on logging, uncomment the following line
+#touch $wd/disk-changer.log
+#
+dbgfile="$wd/disk-changer.log"
+debug() {
+    if test -e $dbgfile; then
+       echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile
+    fi
+}
+
+
+#
+# Create a temporary file
+#
+make_temp_file() {
+  TMPFILE=`mktemp -t mtx.XXXXXXXXXX`
+  if test x${TMPFILE} = x; then
+     TMPFILE="$wd/disk-changer.$$"
+     if test -f ${TMPFILE}; then
+       echo "Temp file security problem on: ${TMPFILE}"
+       exit 1
+     fi
+  fi
+}
+
+# check parameter count on commandline
+#
+check_parm_count() {
+    pCount=$1
+    pCountNeed=$2
+    if test $pCount -lt $pCountNeed; then
+       echo "usage: disk-changer ctl-device command [slot archive-device drive-index]"
+       echo "  Insufficient number of arguments arguments given."
+       if test $pCount -lt 2; then
+           echo "  Mimimum usage is first two arguments ..."
+       else
+           echo "  Command expected $pCountNeed arguments"
+       fi
+       exit 1
+    fi
+}
+
+#
+# Strip off the final name in order to get the Directory ($dir)
+#  that we are dealing with.
+#
+get_dir() {
+   bn=`basename $device`
+   dir=`echo "$device" | sed -e s%/$bn%%g -`
+}
+
+
+# Setup arguments
+ctl=$1
+cmd="$2"
+slot=$3
+device=$4
+drive=$5
+
+# set defaults
+maxdrive=1
+maxslot=10
+
+# Pull in conf file
+if [ -f $ctl ]; then 
+   . $ctl
+fi
+
+
+# Check for special cases where only 2 arguments are needed, 
+#  all others are a minimum of 5
+#
+case $2 in
+    list)
+       check_parm_count $# 2
+       ;;
+    slots)
+       check_parm_count $# 2
+       ;;
+    *)
+       check_parm_count $# 5
+       if [ $drive -gt $maxdrive ]; then
+          echo "Drive ($drive) out of range (0-$maxdrive)"
+          exit 1
+       fi
+       if [ $slot -gt $maxslot ]; then
+          echo "Slot ($slot) out of range (1-$maxslot)"
+          exit 1
+       fi
+       ;;
+esac
+
+
+
+debug "Parms: $ctl $cmd $slot $device $drive"
+
+case $cmd in 
+   unload)
+      debug "Doing disk -f $ctl unload $slot $device $drive"
+      get_dir
+      echo "0" >$dir/loaded${drive}
+      unlink $device 2>/dev/null >/dev/null
+      rm -f $device
+      ;;
+
+   load)
+      debug "Doing disk $ctl load $slot $device $drive"
+      get_dir
+      echo "0" >$dir/loaded${drive}
+      unlink $device 2>/dev/null >/dev/null
+      rm -f $device
+      ln -s $dir/slot${slot} $device
+      rtn=$?
+      if [ $rtn -eq 0 ]; then
+        echo $slot >$dir/loaded${drive}
+      fi
+      exit $rtn
+      ;;
+
+   list) 
+      debug "Doing disk -f $ctl -- to list volumes"
+      get_dir 
+      if [ -f $dir/barcodes ]; then
+        cat $dir/barcodes
+      else
+        i=1
+        while [ $i -le $maxslot ]; do
+           echo "$i:"
+           i=`expr $i + 1`
+        done
+      fi
+      exit 0
+      ;;
+
+   loaded)
+      debug "Doing disk -f $ctl $drive -- to find what is loaded"
+      get_dir
+      if [ -f $dir/loaded${drive} ]; then
+        cat $dir/loaded${drive}
+      else
+        echo "0"
+      fi
+      exit
+      ;;
+
+   slots)
+      debug "Doing disk -f $ctl -- to get count of slots"
+      echo $maxslot
+      ;;
+esac
index 217981ba29173577fa6eca015cde24cd0484524c..41498ef89e9a3efbcf0d01a2686f9e5cda35fb39 100644 (file)
@@ -11,7 +11,7 @@
 #
 #  So Bacula will always call with all the following arguments, even though
 #    in come cases, not all are used.
-
+#
 #  mtx-changer "changer-device" "command" "slot" "archive-device" "drive-index"
 #                 $1              $2       $3        $4               $5
 #
 
 MTX=@MTX@
 
+#
+# log whats done
+#
+# to turn on logging, uncomment the following line
+#touch @working_dir@/mtx.log
+#
+dbgfile="@working_dir@/mtx.log"
+debug() {
+    if test -e $dbgfile; then
+       echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile
+    fi
+}
+
+
 #
 # Create a temporary file
 #
@@ -65,19 +79,44 @@ wait_for_drive() {
     if mt -f $1 status | grep ONLINE  >/dev/null 2>&1; then
       break
     fi
-#   echo "Device $1 - not ready, retrying..."
+    debug "Device $1 - not ready, retrying..."
     sleep 1
     i=`expr $i + 1`
   done
 }
 
+# check parameter count on commandline
+#
+check_parm_count() {
+    pCount=$1
+    pCountNeed=$2
+    if test $pCount -lt $pCountNeed; then
+       echo "usage: mtx-changer ctl-device command [slot archive-device drive-index]"
+       echo "  Insufficient number of arguments arguments given."
+       if test $pCount -lt 2; then
+           echo "  Mimimum usage is first two arguments ..."
+       else
+           echo "  Command expected $pCountNeed arguments"
+       fi
+       exit 1
+    fi
+}
+
+# Check for special cases where only 2 arguments are needed, 
+#  all others are a minimum of 5
+#
+case $2 in
+    list)
+       check_parm_count $# 2
+       ;;
+    slots)
+       check_parm_count $# 2
+       ;;
+    *)
+       check_parm_count $# 5
+       ;;
+esac
 
-if test $# -lt 2 ; then
-  echo "usage: mtx-changer ctl-device command slot archive-device drive"
-  echo "  Insufficient number of arguments arguments given."
-  echo "  Mimimum usage is first two arguments ..."
-  exit 1
-fi
 
 # Setup arguments
 ctl=$1
@@ -86,36 +125,20 @@ slot=$3
 device=$4
 drive=$5
 
-
-#
-# Check for special cases where only 2 arguments are needed, 
-#  all others are a minimum of 3
-case $cmd in
-   list)
-     ;;
-   slots)
-     ;;
-   *)
-     if test $# -lt 5; then
-       echo "usage: mtx-changer ctl-device command slot archive-device drive"
-       echo "  Insufficient number of arguments arguments given."
-       exit 1
-     fi
-     ;;
-esac
-
+debug "Parms: $ctl $cmd $slot $device $drive"
 
 case $cmd in 
    unload)
-#     echo "Doing mtx -f $ctl unload $slot $drive"
+      debug "Doing mtx -f $ctl unload $slot $drive"
 #
 # enable the following line if you need to eject the cartridge
 #     mt -f $device offline
+#     sleep 10
       ${MTX} -f $ctl unload $slot $drive
       ;;
 
    load)
-#     echo "Doing mtx -f $ctl load $slot $drive"
+      debug "Doing mtx -f $ctl load $slot $drive"
       ${MTX} -f $ctl load $slot $drive
       rtn=$?
 #
@@ -127,13 +150,15 @@ case $cmd in
       ;;
 
    list) 
-#     echo "Doing mtx -f $ctl -- to list volumes"
+      debug "Doing mtx -f $ctl -- to list volumes"
       make_temp_file
+# Enable the following if you are using barcodes and need an inventory
+#     $(MTX) -f $ctl inventory
       ${MTX} -f $ctl status >${TMPFILE}
       rtn=$?
       cat ${TMPFILE} | grep " *Storage Element [0-9]*:.*Full" | awk "{print \$3 \$4}" | sed "s/Full *\(:VolumeTag=\)*//"
       cat ${TMPFILE} | grep "^Data Transfer Element [0-9]*:Full (Storage Element [0-9]" | awk '{printf "%s:%s\n",$7,$10}'
-      rm -f ${TMPFILE} 2>&1 >/dev/null
+      rm -f ${TMPFILE} >/dev/null 2>&1
 #
 # If you have a VXA PacketLoader and the above does not work, try
 #  turning it off and enabling the following line.
@@ -142,18 +167,18 @@ case $cmd in
       ;;
 
    loaded)
-#     echo "Doing mtx -f $ctl $drive -- to find what is loaded"
+      debug "Doing mtx -f $ctl $drive -- to find what is loaded"
       make_temp_file
       ${MTX} -f $ctl status >${TMPFILE}
       rtn=$?
       cat ${TMPFILE} | grep "^Data Transfer Element $drive:Full" | awk "{print \$7}"
       cat ${TMPFILE} | grep "^Data Transfer Element $drive:Empty" | awk "{print 0}"
-      rm -f ${TMPFILE} 2>&1 >/dev/null
+      rm -f ${TMPFILE} >/dev/null 2>&1
       exit $rtn
       ;;
 
    slots)
-#     echo "Doing mtx -f $ctl -- to get count of slots"
+      debug "Doing mtx -f $ctl -- to get count of slots"
       ${MTX} -f $ctl status | grep " *Storage Changer" | awk "{print \$5}"
       ;;
 esac
index a875d44528068a01845082e496e9ff3440d88f07..048de8fd428ccf5e894f086efee77f0a6d734bff 100644 (file)
@@ -105,7 +105,7 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime)
             jr->JobType, L_INCREMENTAL, L_DIFFERENTIAL, L_FULL, jr->Name,
             edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2));
       } else {
-         Mmsg1(&mdb->errmsg, _("Unknown level=%d\n"), jr->JobLevel);
+         Mmsg1(mdb->errmsg, _("Unknown level=%d\n"), jr->JobLevel);
          goto bail_out;
       }
    } else {
@@ -199,6 +199,7 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
 
    /* Find last full */
    db_lock(mdb);
+   Dmsg2(100, "JobLevel=%d JobType=%d\n", jr->JobLevel, jr->JobType);
    if (jr->JobLevel == L_VERIFY_CATALOG) {
       Mmsg(mdb->cmd,
 "SELECT JobId FROM Job WHERE Type='V' AND Level='%c' AND "
@@ -208,7 +209,7 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
            edit_int64(jr->ClientId, ed1));
    } else if (jr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG ||
               jr->JobLevel == L_VERIFY_DISK_TO_CATALOG ||
-              jr->JobType == JT_MIGRATE) {
+              jr->JobType == JT_BACKUP) {
       if (Name) {
          Mmsg(mdb->cmd,
 "SELECT JobId FROM Job WHERE Type='B' AND JobStatus='T' AND "
@@ -220,7 +221,7 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
            edit_int64(jr->ClientId, ed1));
       }
    } else {
-      Mmsg1(&mdb->errmsg, _("Unknown Job level=%c\n"), jr->JobLevel);
+      Mmsg1(&mdb->errmsg, _("Unknown Job level=%d\n"), jr->JobLevel);
       db_unlock(mdb);
       return false;
    }
index 0ef206407a25d0ecd39f47bb05c6adc623111c36..10dae2d3052b4da2729c950d847ddf5966617a88 100644 (file)
@@ -76,8 +76,8 @@ static RES_ITEM cons_items[] = {
    {"rcfile",         store_dir,      ITEM(res_cons.rc_file), 0, 0, 0},
    {"historyfile",    store_dir,      ITEM(res_cons.hist_file), 0, 0, 0},
    {"password",       store_password, ITEM(res_cons.password), 0, ITEM_REQUIRED, 0},
-   {"tlsenable",      store_yesno,     ITEM(res_cons.tls_enable), 1, 0, 0},
-   {"tlsrequire",     store_yesno,     ITEM(res_cons.tls_require), 1, 0, 0},
+   {"tlsenable",      store_bit,     ITEM(res_cons.tls_enable), 1, 0, 0},
+   {"tlsrequire",     store_bit,     ITEM(res_cons.tls_require), 1, 0, 0},
    {"tlscacertificatefile", store_dir, ITEM(res_cons.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir", store_dir,  ITEM(res_cons.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate", store_dir,       ITEM(res_cons.tls_certfile), 0, 0, 0},
@@ -93,8 +93,8 @@ static RES_ITEM dir_items[] = {
    {"dirport",        store_int,       ITEM(res_dir.DIRport),  0, ITEM_DEFAULT, 9101},
    {"address",        store_str,       ITEM(res_dir.address),  0, 0, 0},
    {"password",       store_password,  ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
-   {"tlsenable",      store_yesno,     ITEM(res_dir.tls_enable), 1, 0, 0},
-   {"tlsrequire",     store_yesno,     ITEM(res_dir.tls_require), 1, 0, 0},
+   {"tlsenable",      store_bit,     ITEM(res_dir.tls_enable), 1, 0, 0},
+   {"tlsrequire",     store_bit,     ITEM(res_dir.tls_require), 1, 0, 0},
    {"tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir", store_dir,  ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate", store_dir,       ITEM(res_dir.tls_certfile), 0, 0, 0},
index bf054db8eb3c4602a303e6dcc1c76dbb12b06bc5..e0214080d93d2f46c993b1d90c8b18bc7ed70666 100644 (file)
@@ -101,7 +101,7 @@ int prune_volumes(JCR *jcr)
    db_lock(jcr->db);
 
    /* Get the List of all media ids in the current Pool */
-   if (!db_get_media_ids(jcr, jcr->db, jcr->PoolId, &num_ids, &ids)) {
+   if (!db_get_media_ids(jcr, jcr->db, jcr->jr.PoolId, &num_ids, &ids)) {
       Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
       goto bail_out;
    }
@@ -114,7 +114,7 @@ int prune_volumes(JCR *jcr)
          continue;
       }
       /* Prune only Volumes from current Pool */
-      if (jcr->PoolId != mr.PoolId) {
+      if (jcr->jr.PoolId != mr.PoolId) {
          continue;
       }
       /* Prune only Volumes with status "Full", or "Used" */
index f8107485b763dd996908a200b4428a887aed11a4..496e14d6d808d9e3b12a4f02dfbcb99d2dacdf41 100644 (file)
@@ -97,35 +97,18 @@ bool do_backup_init(JCR *jcr)
          }
       }
    }
-   jcr->PoolId = pr.PoolId;
    jcr->jr.PoolId = pr.PoolId;
 
-   /*
-    * Fire off any clone jobs (run directives)
-    */
-   Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
-   if (!jcr->cloned && jcr->job->run_cmds) {
-      char *runcmd;
-      JOB *job = jcr->job;
-      POOLMEM *cmd = get_pool_memory(PM_FNAME);
-      UAContext *ua = new_ua_context(jcr);
-      ua->batch = true;
-      foreach_alist(runcmd, job->run_cmds) {
-         cmd = edit_job_codes(jcr, cmd, runcmd, "");              
-         Mmsg(ua->cmd, "run %s cloned=yes", cmd);
-         Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
-         parse_ua_args(ua);                 /* parse command */
-         int stat = run_cmd(ua, ua->cmd);
-         if (stat == 0) {
-            Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
-         } else {
-            Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
-         }
-      }
-      free_ua_context(ua);
-      free_pool_memory(cmd);
+   /* If pool storage specified, use it instead of job storage */
+   copy_storage(jcr, jcr->pool->storage);
+
+   if (!jcr->storage) {
+      Jmsg(jcr, M_FATAL, 0, _("No Storage specification found in Job or Pool.\n"));
+      return false;
    }
 
+   create_clones(jcr);                /* run any clone jobs */
+
    return true;
 }
 
index 62e4400077efb2f31f91f7e2f28b4864b0768f6f..e599bd95f2f1d5d79a06afa20f1057dac967cc22 100644 (file)
@@ -160,7 +160,7 @@ void catalog_request(JCR *jcr, BSOCK *bs)
              *   Pool matches, and it is either Append or Recycle
              *   and Media Type matches and Pool allows any volume.
              */
-            if (mr.PoolId != jcr->PoolId) {
+            if (mr.PoolId != jcr->jr.PoolId) {
                reason = _("not in Pool");
             } else if (strcmp(mr.MediaType, jcr->store->media_type) != 0) {
                reason = _("not correct MediaType");
index 63a3b1ea8ac873ed4a9df9274d4d8953174dfeab..617400c8a208b42f247feda2433861f2b62099fb 100644 (file)
@@ -559,6 +559,7 @@ static int check_resources()
          for (i=0; job_items[i].name; i++) {
             char **def_svalue, **svalue;  /* string value */
             int *def_ivalue, *ivalue;     /* integer value */
+            bool *def_bvalue, *bvalue;    /* bool value */
             int64_t *def_lvalue, *lvalue; /* 64 bit values */
             uint32_t offset;
 
@@ -608,9 +609,9 @@ static int check_resources()
                   }
                /*
                 * Handle integer fields
-                *    Note, our store_yesno does not handle bitmaped fields
+                *    Note, our store_bit does not handle bitmaped fields
                 */
-               } else if (job_items[i].handler == store_yesno   ||
+               } else if (job_items[i].handler == store_bit     ||
                           job_items[i].handler == store_pint    ||
                           job_items[i].handler == store_jobtype ||
                           job_items[i].handler == store_level   ||
@@ -634,6 +635,16 @@ static int check_resources()
                   lvalue = (int64_t *)((char *)job + offset);
                   *lvalue = *def_lvalue;
                   set_bit(i, job->hdr.item_present);
+               /*
+                * Handle bool fields
+                */
+               } else if (job_items[i].handler == store_bool) {
+                  def_bvalue = (bool *)((char *)(job->jobdefs) + offset);
+                  Dmsg5(400, "Job \"%s\", field \"%s\" def_bvalue=%d item %d offset=%u\n",
+                       job->hdr.name, job_items[i].name, *def_bvalue, i, offset);
+                  bvalue = (bool *)((char *)job + offset);
+                  *bvalue = *def_bvalue;
+                  set_bit(i, job->hdr.item_present);
                }
             }
          }
index 38de435a16ceef3804c493334f4d5b8a112d10a6..0ebace8e607ceb8ae944260de9ff13d74efad626 100644 (file)
@@ -97,9 +97,9 @@ static RES_ITEM dir_items[] = {
    {"password",    store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
    {"fdconnecttimeout", store_time,ITEM(res_dir.FDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
    {"sdconnecttimeout", store_time,ITEM(res_dir.SDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
-   {"tlsenable",            store_yesno,     ITEM(res_dir.tls_enable), 1, 0, 0},
-   {"tlsrequire",           store_yesno,     ITEM(res_dir.tls_require), 1, 0, 0},
-   {"tlsverifypeer",        store_yesno,     ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
+   {"tlsenable",            store_bool,      ITEM(res_dir.tls_enable), 0, 0, 0},
+   {"tlsrequire",           store_bool,      ITEM(res_dir.tls_require), 0, 0, 0},
+   {"tlsverifypeer",        store_bool,      ITEM(res_dir.tls_verify_peer), 0, ITEM_DEFAULT, true},
    {"tlscacertificatefile", store_dir,       ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir",  store_dir,       ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate",       store_dir,       ITEM(res_dir.tls_certfile), 0, 0, 0},
@@ -127,9 +127,9 @@ static RES_ITEM con_items[] = {
    {"commandacl",  store_acl,      ITEM(res_con.ACL_lists), Command_ACL, 0, 0},
    {"filesetacl",  store_acl,      ITEM(res_con.ACL_lists), FileSet_ACL, 0, 0},
    {"catalogacl",  store_acl,      ITEM(res_con.ACL_lists), Catalog_ACL, 0, 0},
-   {"tlsenable",            store_yesno,     ITEM(res_con.tls_enable), 1, 0, 0},
-   {"tlsrequire",           store_yesno,     ITEM(res_con.tls_require), 1, 0, 0},
-   {"tlsverifypeer",        store_yesno,     ITEM(res_con.tls_verify_peer), 1, ITEM_DEFAULT, 1},
+   {"tlsenable",            store_bool,      ITEM(res_con.tls_enable), 0, 0, 0},
+   {"tlsrequire",           store_bool,      ITEM(res_con.tls_require), 0, 0, 0},
+   {"tlsverifypeer",        store_bool,      ITEM(res_con.tls_verify_peer), 0, ITEM_DEFAULT, true},
    {"tlscacertificatefile", store_dir,       ITEM(res_con.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir",  store_dir,       ITEM(res_con.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate",       store_dir,       ITEM(res_con.tls_certfile), 0, 0, 0},
@@ -157,10 +157,10 @@ static RES_ITEM cli_items[] = {
    {"catalog",  store_res,        ITEM(res_client.catalog),  R_CATALOG, ITEM_REQUIRED, 0},
    {"fileretention", store_time,  ITEM(res_client.FileRetention), 0, ITEM_DEFAULT, 60*60*24*60},
    {"jobretention",  store_time,  ITEM(res_client.JobRetention),  0, ITEM_DEFAULT, 60*60*24*180},
-   {"autoprune", store_yesno,     ITEM(res_client.AutoPrune), 1, ITEM_DEFAULT, 1},
+   {"autoprune", store_bool,      ITEM(res_client.AutoPrune), 0, ITEM_DEFAULT, true},
    {"maximumconcurrentjobs", store_pint, ITEM(res_client.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1},
-   {"tlsenable",            store_yesno,     ITEM(res_client.tls_enable), 1, 0, 0},
-   {"tlsrequire",           store_yesno,     ITEM(res_client.tls_require), 1, 0, 0},
+   {"tlsenable",            store_bool,      ITEM(res_client.tls_enable), 0, 0, 0},
+   {"tlsrequire",           store_bool,      ITEM(res_client.tls_require), 0, 0, 0},
    {"tlscacertificatefile", store_dir,       ITEM(res_client.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir",  store_dir,       ITEM(res_client.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate",       store_dir,       ITEM(res_client.tls_certfile), 0, 0, 0},
@@ -182,12 +182,12 @@ static RES_ITEM store_items[] = {
    {"sdpassword",  store_password, ITEM(res_store.password),   0, 0, 0},
    {"device",      store_device,   ITEM(res_store.device),     R_DEVICE, ITEM_REQUIRED, 0},
    {"mediatype",   store_strname,  ITEM(res_store.media_type), 0, ITEM_REQUIRED, 0},
-   {"autochanger", store_yesno,    ITEM(res_store.autochanger), 1, ITEM_DEFAULT, 0},
-   {"enabled",     store_yesno,    ITEM(res_store.enabled),     1, ITEM_DEFAULT, 1},
+   {"autochanger", store_bool,     ITEM(res_store.autochanger), 0, ITEM_DEFAULT, 0},
+   {"enabled",     store_bool,     ITEM(res_store.enabled),     0, ITEM_DEFAULT, true},
    {"maximumconcurrentjobs", store_pint, ITEM(res_store.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1},
    {"sddport", store_pint, ITEM(res_store.SDDport), 0, 0, 0}, /* deprecated */
-   {"tlsenable",            store_yesno,     ITEM(res_store.tls_enable), 1, 0, 0},
-   {"tlsrequire",           store_yesno,     ITEM(res_store.tls_require), 1, 0, 0},
+   {"tlsenable",            store_bool,      ITEM(res_store.tls_enable), 0, 0, 0},
+   {"tlsrequire",           store_bool,      ITEM(res_store.tls_require), 0, 0, 0},
    {"tlscacertificatefile", store_dir,       ITEM(res_store.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir",  store_dir,       ITEM(res_store.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate",       store_dir,       ITEM(res_store.tls_certfile), 0, 0, 0},
@@ -213,7 +213,7 @@ static RES_ITEM cat_items[] = {
    {"dbname",   store_str,      ITEM(res_cat.db_name),     0, ITEM_REQUIRED, 0},
    {"dbsocket", store_str,      ITEM(res_cat.db_socket),   0, 0, 0},
    /* Turned off for the moment */
-   {"multipleconnections", store_yesno, ITEM(res_cat.mult_db_connections), 0, 0, 0},
+   {"multipleconnections", store_bit, ITEM(res_cat.mult_db_connections), 0, 0, 0},
    {NULL, NULL, NULL, 0, 0, 0}
 };
 
@@ -228,7 +228,7 @@ RES_ITEM job_items[] = {
    {"type",      store_jobtype, ITEM(res_job.JobType),  0, ITEM_REQUIRED, 0},
    {"level",     store_level,   ITEM(res_job.JobLevel),    0, 0, 0},
    {"messages",  store_res,     ITEM(res_job.messages), R_MSGS, ITEM_REQUIRED, 0},
-   {"storage",   store_alist_res, ITEM(res_job.storage),  R_STORAGE, ITEM_REQUIRED, 0},
+   {"storage",   store_alist_res, ITEM(res_job.storage),  R_STORAGE, 0, 0},
    {"pool",      store_res,     ITEM(res_job.pool),     R_POOL, ITEM_REQUIRED, 0},
    {"fullbackuppool",  store_res, ITEM(res_job.full_pool),   R_POOL, 0, 0},
    {"incrementalbackuppool",  store_res, ITEM(res_job.inc_pool), R_POOL, 0, 0},
@@ -255,26 +255,26 @@ RES_ITEM job_items[] = {
    {"maxwaittime",  store_time, ITEM(res_job.MaxWaitTime), 0, 0, 0},
    {"maxstartdelay",store_time, ITEM(res_job.MaxStartDelay), 0, 0, 0},
    {"jobretention", store_time, ITEM(res_job.JobRetention),  0, 0, 0},
-   {"prefixlinks", store_yesno, ITEM(res_job.PrefixLinks), 1, ITEM_DEFAULT, 0},
-   {"prunejobs",   store_yesno, ITEM(res_job.PruneJobs), 1, ITEM_DEFAULT, 0},
-   {"prunefiles",  store_yesno, ITEM(res_job.PruneFiles), 1, ITEM_DEFAULT, 0},
-   {"prunevolumes",store_yesno, ITEM(res_job.PruneVolumes), 1, ITEM_DEFAULT, 0},
-   {"enabled",     store_yesno, ITEM(res_job.enabled), 1, ITEM_DEFAULT, 1},
-   {"spoolattributes",store_yesno, ITEM(res_job.SpoolAttributes), 1, ITEM_DEFAULT, 0},
-   {"spooldata",   store_yesno, ITEM(res_job.spool_data), 1, ITEM_DEFAULT, 0},
-   {"rerunfailedlevels",   store_yesno, ITEM(res_job.rerun_failed_levels), 1, ITEM_DEFAULT, 0},
-   {"prefermountedvolumes", store_yesno, ITEM(res_job.PreferMountedVolumes), 1, ITEM_DEFAULT, 1},
+   {"prefixlinks", store_bool, ITEM(res_job.PrefixLinks), 0, ITEM_DEFAULT, false},
+   {"prunejobs",   store_bool, ITEM(res_job.PruneJobs), 0, ITEM_DEFAULT, false},
+   {"prunefiles",  store_bool, ITEM(res_job.PruneFiles), 0, ITEM_DEFAULT, false},
+   {"prunevolumes",store_bool, ITEM(res_job.PruneVolumes), 0, ITEM_DEFAULT, false},
+   {"enabled",     store_bool, ITEM(res_job.enabled), 0, ITEM_DEFAULT, true},
+   {"spoolattributes",store_bool, ITEM(res_job.SpoolAttributes), 0, ITEM_DEFAULT, false},
+   {"spooldata",   store_bit, ITEM(res_job.spool_data), 0, ITEM_DEFAULT, false},
+   {"rerunfailedlevels",   store_bool, ITEM(res_job.rerun_failed_levels), 0, ITEM_DEFAULT, false},
+   {"prefermountedvolumes", store_bool, ITEM(res_job.PreferMountedVolumes), 0, ITEM_DEFAULT, true},
    {"runbeforejob", store_str,  ITEM(res_job.RunBeforeJob), 0, 0, 0},
    {"runafterjob",  store_str,  ITEM(res_job.RunAfterJob),  0, 0, 0},
    {"runafterfailedjob",  store_str,  ITEM(res_job.RunAfterFailedJob),  0, 0, 0},
    {"clientrunbeforejob", store_str,  ITEM(res_job.ClientRunBeforeJob), 0, 0, 0},
    {"clientrunafterjob",  store_str,  ITEM(res_job.ClientRunAfterJob),  0, 0, 0},
    {"maximumconcurrentjobs", store_pint, ITEM(res_job.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1},
-   {"rescheduleonerror", store_yesno, ITEM(res_job.RescheduleOnError), 1, ITEM_DEFAULT, 0},
+   {"rescheduleonerror", store_bool, ITEM(res_job.RescheduleOnError), 0, ITEM_DEFAULT, false},
    {"rescheduleinterval", store_time, ITEM(res_job.RescheduleInterval), 0, ITEM_DEFAULT, 60 * 30},
    {"rescheduletimes", store_pint, ITEM(res_job.RescheduleTimes), 0, 0, 0},
    {"priority",   store_pint, ITEM(res_job.Priority), 0, ITEM_DEFAULT, 10},
-   {"writepartafterjob",   store_yesno, ITEM(res_job.write_part_after_job), 1, ITEM_DEFAULT, 0},
+   {"writepartafterjob",   store_bool, ITEM(res_job.write_part_after_job), 0, ITEM_DEFAULT, false},
    {NULL, NULL, NULL, 0, 0, 0}
 };
 
@@ -287,8 +287,8 @@ static RES_ITEM fs_items[] = {
    {"description", store_str,  ITEM(res_fs.hdr.desc), 0, 0, 0},
    {"include",     store_inc,  NULL,                  0, ITEM_NO_EQUALS, 0},
    {"exclude",     store_inc,  NULL,                  1, ITEM_NO_EQUALS, 0},
-   {"ignorefilesetchanges", store_yesno, ITEM(res_fs.ignore_fs_changes), 1, ITEM_DEFAULT, 0},
-   {"enablevss",   store_yesno, ITEM(res_fs.enable_vss), 1, ITEM_DEFAULT, 0},
+   {"ignorefilesetchanges", store_bool, ITEM(res_fs.ignore_fs_changes), 0, ITEM_DEFAULT, false},
+   {"enablevss",   store_bool, ITEM(res_fs.enable_vss), 0, ITEM_DEFAULT, false},
    {NULL,          NULL,       NULL,                  0, 0, 0}
 };
 
@@ -314,18 +314,18 @@ static RES_ITEM pool_items[] = {
    {"pooltype",        store_strname, ITEM(res_pool.pool_type),     0, ITEM_REQUIRED, 0},
    {"labelformat",     store_strname, ITEM(res_pool.label_format),  0, 0,     0},
    {"labeltype",       store_label,   ITEM(res_pool.LabelType),     0, 0,     0},     
-   {"cleaningprefix",  store_strname, ITEM(res_pool.cleaning_prefix), 0, 0,     0},
-   {"usecatalog",      store_yesno,   ITEM(res_pool.use_catalog),    1, ITEM_DEFAULT,  1},
-   {"usevolumeonce",   store_yesno,   ITEM(res_pool.use_volume_once),1, 0,        0},
-   {"purgeoldestvolume", store_yesno, ITEM(res_pool.purge_oldest_volume), 1, 0, 0},
-   {"recycleoldestvolume", store_yesno,  ITEM(res_pool.recycle_oldest_volume), 1, 0, 0},
-   {"recyclecurrentvolume", store_yesno, ITEM(res_pool.recycle_current_volume), 1, 0, 0},
+   {"cleaningprefix",  store_strname, ITEM(res_pool.cleaning_prefix), 0, 0,   0},
+   {"usecatalog",      store_bool,    ITEM(res_pool.use_catalog),    0, ITEM_DEFAULT, true},
+   {"usevolumeonce",   store_bool,    ITEM(res_pool.use_volume_once), 0, 0,   0},
+   {"purgeoldestvolume", store_bool,  ITEM(res_pool.purge_oldest_volume), 0, 0, 0},
+   {"recycleoldestvolume", store_bool,  ITEM(res_pool.recycle_oldest_volume), 0, 0, 0},
+   {"recyclecurrentvolume", store_bool, ITEM(res_pool.recycle_current_volume), 0, 0, 0},
    {"maximumvolumes",  store_pint,    ITEM(res_pool.max_volumes),   0, 0,        0},
    {"maximumvolumejobs", store_pint,  ITEM(res_pool.MaxVolJobs),    0, 0,       0},
    {"maximumvolumefiles", store_pint, ITEM(res_pool.MaxVolFiles),   0, 0,       0},
    {"maximumvolumebytes", store_size, ITEM(res_pool.MaxVolBytes),   0, 0,       0},
-   {"acceptanyvolume", store_yesno,   ITEM(res_pool.accept_any_volume), 1, ITEM_DEFAULT,     1},
-   {"catalogfiles",    store_yesno,   ITEM(res_pool.catalog_files),  1, ITEM_DEFAULT,  1},
+   {"acceptanyvolume", store_bool,    ITEM(res_pool.accept_any_volume), 0, ITEM_DEFAULT, true},
+   {"catalogfiles",    store_bool,    ITEM(res_pool.catalog_files),  0, ITEM_DEFAULT, true},
    {"volumeretention", store_time,    ITEM(res_pool.VolRetention),   0, ITEM_DEFAULT, 60*60*24*365},
    {"volumeuseduration", store_time,  ITEM(res_pool.VolUseDuration), 0, 0, 0},
    {"migrationtime",  store_time,     ITEM(res_pool.MigrationTime), 0, 0, 0},
@@ -333,8 +333,8 @@ static RES_ITEM pool_items[] = {
    {"migrationlowbytes", store_size,  ITEM(res_pool.MigrationLowBytes), 0, 0, 0},
    {"nextpool",      store_res,       ITEM(res_pool.NextPool), R_POOL, 0, 0},
    {"storage",       store_alist_res, ITEM(res_pool.storage),  R_STORAGE, 0, 0},
-   {"autoprune",       store_yesno,   ITEM(res_pool.AutoPrune), 1, ITEM_DEFAULT, 1},
-   {"recycle",         store_yesno,   ITEM(res_pool.Recycle),     1, ITEM_DEFAULT, 1},
+   {"autoprune",       store_bool,    ITEM(res_pool.AutoPrune), 0, ITEM_DEFAULT, true},
+   {"recycle",         store_bool,    ITEM(res_pool.Recycle),   0, ITEM_DEFAULT, true},
    {NULL, NULL, NULL, 0, 0, 0}
 };
 
index 45b48eb51c61ed2d5aa837537059a172fa049bd0..6886983ee4c03df96a76a6ebdf81e1c660d937b4 100644 (file)
@@ -102,9 +102,6 @@ public:
    uint32_t MaxConcurrentJobs;        /* Max concurrent jobs for whole director */
    utime_t FDConnectTimeout;          /* timeout for connect in seconds */
    utime_t SDConnectTimeout;          /* timeout in seconds */
-   int tls_enable;                    /* Enable TLS */
-   int tls_require;                   /* Require TLS */
-   int tls_verify_peer;              /* TLS Verify Client Certificate */
    char *tls_ca_certfile;             /* TLS CA Certificate File */
    char *tls_ca_certdir;              /* TLS CA Certificate Directory */
    char *tls_certfile;                /* TLS Server Certificate File */
@@ -112,6 +109,9 @@ public:
    char *tls_dhfile;                  /* TLS Diffie-Hellman Parameters */
    alist *tls_allowed_cns;            /* TLS Allowed Clients */
    TLS_CONTEXT *tls_ctx;              /* Shared TLS Context */
+   bool tls_enable;                   /* Enable TLS */
+   bool tls_require;                  /* Require TLS */
+   bool tls_verify_peer;              /* TLS Verify Client Certificate */
 };
 
 /*
@@ -168,9 +168,6 @@ public:
    RES   hdr;
    char *password;                    /* UA server password */
    alist *ACL_lists[Num_ACL];         /* pointers to ACLs */
-   int tls_enable;                    /* Enable TLS */
-   int tls_require;                   /* Require TLS */
-   int tls_verify_peer;              /* TLS Verify Client Certificate */
    char *tls_ca_certfile;             /* TLS CA Certificate File */
    char *tls_ca_certdir;              /* TLS CA Certificate Directory */
    char *tls_certfile;                /* TLS Server Certificate File */
@@ -178,6 +175,9 @@ public:
    char *tls_dhfile;                  /* TLS Diffie-Hellman Parameters */
    alist *tls_allowed_cns;            /* TLS Allowed Clients */
    TLS_CONTEXT *tls_ctx;              /* Shared TLS Context */
+   bool tls_enable;                   /* Enable TLS */
+   bool tls_require;                  /* Require TLS */
+   bool tls_verify_peer;              /* TLS Verify Client Certificate */
 };
 
 
@@ -189,7 +189,7 @@ class CAT {
 public:
    RES   hdr;
 
-   int   db_port;                     /* Port -- not yet implemented */
+   int   db_port;                     /* Port */
    char *db_address;                  /* host name for remote access */
    char *db_socket;                   /* Socket for local access */
    char *db_password;
@@ -208,7 +208,6 @@ public:
    RES   hdr;
 
    int   FDport;                      /* Where File daemon listens */
-   int   AutoPrune;                   /* Do automatic pruning? */
    utime_t FileRetention;             /* file retention period in seconds */
    utime_t JobRetention;              /* job retention period in seconds */
    char *address;
@@ -216,13 +215,14 @@ public:
    CAT *catalog;                      /* Catalog resource */
    uint32_t MaxConcurrentJobs;        /* Maximume concurrent jobs */
    uint32_t NumConcurrentJobs;        /* number of concurrent jobs running */
-   int tls_enable;                    /* Enable TLS */
-   int tls_require;                   /* Require TLS */
    char *tls_ca_certfile;             /* TLS CA Certificate File */
    char *tls_ca_certdir;              /* TLS CA Certificate Directory */
    char *tls_certfile;                /* TLS Client Certificate File */
    char *tls_keyfile;                 /* TLS Client Key File */
    TLS_CONTEXT *tls_ctx;              /* Shared TLS Context */
+   bool tls_enable;                   /* Enable TLS */
+   bool tls_require;                  /* Require TLS */
+   bool AutoPrune;                    /* Do automatic pruning? */
 };
 
 /*
@@ -239,19 +239,19 @@ public:
    char *password;
    char *media_type;
    alist *device;                     /* Alternate devices for this Storage */
-   int  autochanger;                  /* set if autochanger */
-   int  drives;                       /* number of drives in autochanger */
    uint32_t MaxConcurrentJobs;        /* Maximume concurrent jobs */
    uint32_t NumConcurrentJobs;        /* number of concurrent jobs running */
-   int tls_enable;                    /* Enable TLS */
-   int tls_require;                   /* Require TLS */
    char *tls_ca_certfile;             /* TLS CA Certificate File */
    char *tls_ca_certdir;              /* TLS CA Certificate Directory */
    char *tls_certfile;                /* TLS Client Certificate File */
    char *tls_keyfile;                 /* TLS Client Key File */
    TLS_CONTEXT *tls_ctx;              /* Shared TLS Context */
+   bool tls_enable;                   /* Enable TLS */
+   bool tls_require;                  /* Require TLS */
+   bool enabled;                      /* Set if device is enabled */
+   bool  autochanger;                 /* set if autochanger */
    int64_t StorageId;                 /* Set from Storage DB record */
-   int enabled;                       /* Set if device is enabled */
+   int  drives;                       /* number of drives in autochanger */
 
    /* Methods */
    char *dev_name() const;
@@ -296,21 +296,21 @@ public:
    utime_t DiffMaxWaitTime;           /* Max Differential job wait time */
    utime_t IncMaxWaitTime;            /* Max Incremental job wait time */
    utime_t MaxStartDelay;             /* max start delay in seconds */
-   int PrefixLinks;                   /* prefix soft links with Where path */
-   int PruneJobs;                     /* Force pruning of Jobs */
-   int PruneFiles;                    /* Force pruning of Files */
-   int PruneVolumes;                  /* Force pruning of Volumes */
-   int SpoolAttributes;               /* Set to spool attributes in SD */
-   int spool_data;                    /* Set to spool data in SD */
-   int rerun_failed_levels;           /* Upgrade to rerun failed levels */
-   int PreferMountedVolumes;          /* Prefer vols mounted rather than new one */
-   uint32_t MaxConcurrentJobs;        /* Maximume concurrent jobs */
-   int RescheduleOnError;             /* Set to reschedule on error */
-   int RescheduleTimes;               /* Number of times to reschedule job */
    utime_t RescheduleInterval;        /* Reschedule interval */
    utime_t JobRetention;              /* job retention period in seconds */
-   int write_part_after_job;          /* Set to write part after job in SD */
-   int enabled;                       /* Set if job enabled */
+   uint32_t MaxConcurrentJobs;        /* Maximume concurrent jobs */
+   int RescheduleTimes;               /* Number of times to reschedule job */
+   bool RescheduleOnError;            /* Set to reschedule on error */
+   bool PrefixLinks;                  /* prefix soft links with Where path */
+   bool PruneJobs;                    /* Force pruning of Jobs */
+   bool PruneFiles;                   /* Force pruning of Files */
+   bool PruneVolumes;                 /* Force pruning of Volumes */
+   bool SpoolAttributes;              /* Set to spool attributes in SD */
+   bool spool_data;                   /* Set to spool data in SD */
+   bool rerun_failed_levels;          /* Upgrade to rerun failed levels */
+   bool PreferMountedVolumes;         /* Prefer vols mounted rather than new one */
+   bool write_part_after_job;         /* Set to write part after job in SD */
+   bool enabled;                      /* Set if job enabled */
    
    MSGS      *messages;               /* How and where to send messages */
    SCHED     *schedule;               /* When -- Automatic schedule */
@@ -373,8 +373,8 @@ public:
    bool have_MD5;                     /* set if MD5 initialized */
    struct MD5Context md5c;            /* MD5 of include/exclude */
    char MD5[30];                      /* base 64 representation of MD5 */
-   int ignore_fs_changes;             /* Don't force Full if FS changed */
-   int enable_vss;                    /* Enable Volume Shadow Copy */
+   bool ignore_fs_changes;            /* Don't force Full if FS changed */
+   bool enable_vss;                   /* Enable Volume Shadow Copy */
 };
 
 
@@ -416,13 +416,6 @@ public:
    char *label_format;                /* Label format string */
    char *cleaning_prefix;             /* Cleaning label prefix */
    int   LabelType;                   /* Bacula/ANSI/IBM label type */
-   int   use_catalog;                 /* maintain catalog for media */
-   int   catalog_files;               /* maintain file entries in catalog */
-   int   use_volume_once;             /* write on volume only once */
-   int   accept_any_volume;           /* accept any volume */
-   int   purge_oldest_volume;         /* purge oldest volume */
-   int   recycle_oldest_volume;       /* attempt to recycle oldest volume */
-   int   recycle_current_volume;      /* attempt recycle of current volume */
    uint32_t max_volumes;              /* max number of volumes */
    utime_t VolRetention;              /* volume retention period in seconds */
    utime_t VolUseDuration;            /* duration volume can be used */
@@ -434,8 +427,15 @@ public:
    uint32_t MigrationLowBytes;        /* When migration stops */
    POOL  *NextPool;                   /* Next pool for migration */
    alist *storage;                    /* Where is device -- list of Storage to be used */
-   int   AutoPrune;                   /* default for pool auto prune */
-   int   Recycle;                     /* default for media recycle yes/no */
+   bool  use_catalog;                 /* maintain catalog for media */
+   bool  catalog_files;               /* maintain file entries in catalog */
+   bool  use_volume_once;             /* write on volume only once */
+   bool  accept_any_volume;           /* accept any volume */
+   bool  purge_oldest_volume;         /* purge oldest volume */
+   bool  recycle_oldest_volume;       /* attempt to recycle oldest volume */
+   bool  recycle_current_volume;      /* attempt recycle of current volume */
+   bool  AutoPrune;                   /* default for pool auto prune */
+   bool  Recycle;                     /* default for media recycle yes/no */
 };
 
 
index 2c9829e31f13a31a3840c9396992939e672bb574..f23976861c8e3b95803e459d1044d1182275db9c 100644 (file)
@@ -406,7 +406,7 @@ bool cancel_job(UAContext *ua, JCR *jcr)
       /* Cancel Storage daemon */
       if (jcr->store_bsock) {
          if (!ua->jcr->storage) {
-            copy_storage(ua->jcr, jcr);
+            copy_storage(ua->jcr, jcr->storage);
          } else {
             set_storage(ua->jcr, jcr->store);
          }
@@ -828,7 +828,6 @@ void dird_free_jcr(JCR *jcr)
  */
 void set_jcr_defaults(JCR *jcr, JOB *job)
 {
-   STORE *st;
    jcr->job = job;
    jcr->JobType = job->JobType;
    switch (jcr->JobType) {
@@ -842,18 +841,7 @@ void set_jcr_defaults(JCR *jcr, JOB *job)
    }
    jcr->JobPriority = job->Priority;
    /* Copy storage definitions -- deleted in dir_free_jcr above */
-   if (job->storage) {
-      if (jcr->storage) {
-         delete jcr->storage;
-      }
-      jcr->storage = New(alist(10, not_owned_by_alist));
-      foreach_alist(st, job->storage) {
-         jcr->storage->append(st);
-      }
-   }
-   if (jcr->storage) {
-      jcr->store = (STORE *)jcr->storage->first();
-   }
+   copy_storage(jcr, job->storage);
    jcr->client = job->client;
    if (!jcr->client_name) {
       jcr->client_name = get_pool_memory(PM_NAME);
@@ -897,28 +885,28 @@ void set_jcr_defaults(JCR *jcr, JOB *job)
    }
 }
 
-/*
- * copy the storage definitions from an old JCR to a new one
+
+/* 
+ * Copy the storage definitions from an alist to the JCR
  */
-void copy_storage(JCR *new_jcr, JCR *old_jcr)
+void copy_storage(JCR *jcr, alist *storage)
 {
-   if (old_jcr->storage) {
+   if (storage) {
       STORE *st;
-      if (old_jcr->storage) {
-         delete old_jcr->storage;
+      if (jcr->storage) {
+         delete jcr->storage;
       }
-      new_jcr->storage = New(alist(10, not_owned_by_alist));
-      foreach_alist(st, old_jcr->storage) {
-         new_jcr->storage->append(st);
+      jcr->storage = New(alist(10, not_owned_by_alist));
+      foreach_alist(st, storage) {
+         jcr->storage->append(st);
       }
-   }
-   if (old_jcr->store) {
-      new_jcr->store = old_jcr->store;
-   } else if (new_jcr->storage) {
-      new_jcr->store = (STORE *)new_jcr->storage->first();
+   }               
+   if (jcr->storage) {
+      jcr->store = (STORE *)jcr->storage->first();
    }
 }
 
+
 /* Set storage override */
 void set_storage(JCR *jcr, STORE *store)
 {
@@ -933,3 +921,64 @@ void set_storage(JCR *jcr, STORE *store)
    /* Store not in list, so add it */
    jcr->storage->prepend(store);
 }
+
+void create_clones(JCR *jcr)
+{
+   /*
+    * Fire off any clone jobs (run directives)
+    */
+   Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
+   if (!jcr->cloned && jcr->job->run_cmds) {
+      char *runcmd;
+      JOB *job = jcr->job;
+      POOLMEM *cmd = get_pool_memory(PM_FNAME);
+      UAContext *ua = new_ua_context(jcr);
+      ua->batch = true;
+      foreach_alist(runcmd, job->run_cmds) {
+         cmd = edit_job_codes(jcr, cmd, runcmd, "");              
+         Mmsg(ua->cmd, "run %s cloned=yes", cmd);
+         Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
+         parse_ua_args(ua);                 /* parse command */
+         int stat = run_cmd(ua, ua->cmd);
+         if (stat == 0) {
+            Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
+         } else {
+            Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
+         }
+      }
+      free_ua_context(ua);
+      free_pool_memory(cmd);
+   }
+}
+
+bool create_restore_bootstrap_file(JCR *jcr)
+{
+   RESTORE_CTX rx;
+   UAContext *ua;
+   memset(&rx, 0, sizeof(rx));
+   rx.bsr = new_bsr();
+   rx.JobIds = "";                       
+   rx.bsr->JobId = jcr->target_jr.JobId;
+   ua = new_ua_context(jcr);
+   complete_bsr(ua, rx.bsr);
+   rx.bsr->fi = new_findex();
+   rx.bsr->fi->findex = 1;
+   rx.bsr->fi->findex2 = jcr->target_jr.JobFiles;
+   jcr->ExpectedFiles = write_bsr_file(ua, rx);
+   if (jcr->ExpectedFiles == 0) {
+      free_ua_context(ua);
+      free_bsr(rx.bsr);
+      return false;
+   }
+   if (jcr->RestoreBootstrap) {
+      free(jcr->RestoreBootstrap);
+   }
+   POOLMEM *fname = get_pool_memory(PM_MESSAGE);
+   make_unique_restore_filename(ua, &fname);
+   jcr->RestoreBootstrap = bstrdup(fname);
+   free_ua_context(ua);
+   free_bsr(rx.bsr);
+   free_pool_memory(fname);
+   jcr->needs_sd = true;
+   return true;
+}
index 7c0d86485f675d0364946e9960db863af5387156..6ec9a5de51cd4bebe807282ee03ff8d9f0fee4af 100755 (executable)
@@ -509,7 +509,7 @@ void *jobq_server(void *arg)
             njcr->reschedule_count = jcr->reschedule_count;
             njcr->JobLevel = jcr->JobLevel;
             njcr->JobStatus = jcr->JobStatus;
-            copy_storage(njcr, jcr);
+            copy_storage(njcr, jcr->storage);
             njcr->messages = jcr->messages;
             Dmsg0(2300, "Call to run new job\n");
             V(jq->mutex);
index 81c4003a435e40a50a8188c01f96fb2a7d8581a4..aeaeca655a51c1ac0f38ea5a85dba64d103b2067 100644 (file)
@@ -42,11 +42,7 @@ static char OKbootstrap[] = "3000 OK bootstrap\n";
 bool do_mac_init(JCR *jcr)
 {
    POOL_DBR pr;
-   JOB_DBR jr;
-   JobId_t input_jobid;
    char *Name;
-   RESTORE_CTX rx;
-   UAContext *ua;
    const char *Type;
 
    switch(jcr->JobType) {
@@ -71,18 +67,17 @@ bool do_mac_init(JCR *jcr)
    /*
     * Find JobId of last job that ran.
     */
-   memcpy(&jr, &jcr->jr, sizeof(jr));
    Name = jcr->job->migration_job->hdr.name;
    Dmsg1(100, "find last jobid for: %s\n", NPRT(Name));
-   if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) {
-      Jmsg(jcr, M_FATAL, 0, _(
-           _("Unable to find JobId of previous Job for this client.\n")));
+   jcr->target_jr.JobType = JT_BACKUP;
+   if (!db_find_last_jobid(jcr, jcr->db, Name, &jcr->target_jr)) {
+      Jmsg(jcr, M_FATAL, 0, 
+           _("Previous job \"%s\" not found. ERR=%s\n"), Name,
+           db_strerror(jcr->db));
       return false;
    }
-   input_jobid = jr.JobId;
-   Dmsg1(100, "Last jobid=%d\n", input_jobid);
+   Dmsg1(100, "Last jobid=%d\n", jcr->target_jr.JobId);
 
-   jcr->target_jr.JobId = input_jobid;
    if (!db_get_job_record(jcr, jcr->db, &jcr->target_jr)) {
       Jmsg(jcr, M_FATAL, 0, _("Could not get job record for previous Job. ERR=%s"),
            db_strerror(jcr->db));
@@ -90,7 +85,7 @@ bool do_mac_init(JCR *jcr)
    }
    if (jcr->target_jr.JobStatus != 'T') {
       Jmsg(jcr, M_FATAL, 0, _("Last Job %d did not terminate normally. JobStatus=%c\n"),
-         input_jobid, jcr->target_jr.JobStatus);
+         jcr->target_jr.JobId, jcr->target_jr.JobStatus);
       return false;
    }
    Jmsg(jcr, M_INFO, 0, _("%s using JobId=%d Job=%s\n"),
@@ -130,35 +125,19 @@ bool do_mac_init(JCR *jcr)
          Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
       }
    }
-   jcr->PoolId = pr.PoolId;               /****FIXME**** this can go away */
    jcr->jr.PoolId = pr.PoolId;
 
-   memset(&rx, 0, sizeof(rx));
-   rx.bsr = new_bsr();
-   rx.JobIds = "";                       
-   rx.bsr->JobId = jcr->target_jr.JobId;
-   ua = new_ua_context(jcr);
-   complete_bsr(ua, rx.bsr);
-   rx.bsr->fi = new_findex();
-   rx.bsr->fi->findex = 1;
-   rx.bsr->fi->findex2 = jcr->target_jr.JobFiles;
-   jcr->ExpectedFiles = write_bsr_file(ua, rx);
-   if (jcr->ExpectedFiles == 0) {
-      free_ua_context(ua);
-      free_bsr(rx.bsr);
+   /* If pool storage specified, use it instead of job storage */
+   copy_storage(jcr, jcr->pool->storage);
+
+   if (!jcr->storage) {
+      Jmsg(jcr, M_FATAL, 0, _("No Storage specification found in Job or Pool.\n"));
       return false;
    }
-   if (jcr->RestoreBootstrap) {
-      free(jcr->RestoreBootstrap);
+
+   if (!create_restore_bootstrap_file(jcr)) {
+      return false;
    }
-   POOLMEM *fname = get_pool_memory(PM_MESSAGE);
-   make_unique_restore_filename(ua, &fname);
-   jcr->RestoreBootstrap = bstrdup(fname);
-   free_ua_context(ua);
-   free_bsr(rx.bsr);
-   free_pool_memory(fname);
-
-   jcr->needs_sd = true;
    return true;
 }
 
@@ -170,6 +149,8 @@ bool do_mac_init(JCR *jcr)
  */
 bool do_mac(JCR *jcr)
 {
+   POOL_DBR pr;
+   POOL *pool;
    const char *Type;
    char ed1[100];
    BSOCK *sd;
@@ -209,15 +190,66 @@ bool do_mac(JCR *jcr)
    }
 
    tjcr = jcr->target_jcr = new_jcr(sizeof(JCR), dird_free_jcr);
+   memcpy(&tjcr->target_jr, &jcr->target_jr, sizeof(tjcr->target_jr));
    set_jcr_defaults(tjcr, tjob);
 
    if (!setup_job(tjcr)) {
       return false;
    }
-   tjcr->PoolId = jcr->PoolId;
+   /* Set output PoolId and FileSetId. */
    tjcr->jr.PoolId = jcr->jr.PoolId;
    tjcr->jr.FileSetId = jcr->jr.FileSetId;
 
+   /*
+    * Get the PoolId used with the original job. Then
+    *  find the pool name from the database record.
+    */
+   memset(&pr, 0, sizeof(pr));
+   pr.PoolId = tjcr->target_jr.PoolId;
+   if (!db_get_pool_record(jcr, jcr->db, &pr)) {
+      char ed1[50];
+      Jmsg(jcr, M_FATAL, 0, _("Pool for JobId %s not in database. ERR=%s\n"),
+            edit_int64(pr.PoolId, ed1), db_strerror(jcr->db));
+         return false;
+   }
+   /* Get the pool resource corresponding to the original job */
+   pool = (POOL *)GetResWithName(R_POOL, pr.Name);
+   if (!pool) {
+      Jmsg(jcr, M_FATAL, 0, _("Pool resource \"%s\" not found.\n"), pr.Name);
+      return false;
+   }
+
+   /* If pool storage specified, use it for restore */
+   copy_storage(tjcr, pool->storage);
+
+   /* If the original backup pool has a NextPool, make sure a 
+    *  record exists in the database.
+    */
+   if (pool->NextPool) {
+      memset(&pr, 0, sizeof(pr));
+      bstrncpy(pr.Name, pool->NextPool->hdr.name, sizeof(pr.Name));
+
+      while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
+         /* Try to create the pool */
+         if (create_pool(jcr, jcr->db, pool->NextPool, POOL_OP_CREATE) < 0) {
+            Jmsg(jcr, M_FATAL, 0, _("Pool \"%s\" not in database. %s"), pr.Name,
+               db_strerror(jcr->db));
+            return false;
+         } else {
+            Jmsg(jcr, M_INFO, 0, _("Pool \"%s\" created in database.\n"), pr.Name);
+         }
+      }
+      /*
+       * put the "NextPool" resource pointer in our jcr so that we
+       * can pull the Storage reference from it.
+       */
+      tjcr->pool = jcr->pool = pool->NextPool;
+      tjcr->jr.PoolId = jcr->jr.PoolId = pr.PoolId;
+   }
+
+   /* If pool storage specified, use it instead of job storage for backup */
+   copy_storage(jcr, jcr->pool->storage);
+
    /* Print Job Start message */
    Jmsg(jcr, M_INFO, 0, _("Start %s JobId %s, Job=%s\n"),
         Type, edit_uint64(jcr->JobId, ed1), jcr->Job);
@@ -255,6 +287,9 @@ bool do_mac(JCR *jcr)
    /*
     * Now start a job with the Storage daemon
     */
+   Dmsg2(000, "Read store=%s, write store=%s\n", 
+      ((STORE *)tjcr->storage->first())->hdr.name,
+      ((STORE *)jcr->storage->first())->hdr.name);
    if (!start_storage_daemon_job(jcr, tjcr->storage, jcr->storage)) {
       return false;
    }
@@ -299,7 +334,7 @@ bool do_mac(JCR *jcr)
 void mac_cleanup(JCR *jcr, int TermCode)
 {
    char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
-   char ec1[30], ec2[30], ec3[30];
+   char ec1[30], ec2[30], ec3[30], ec4[30], elapsed[50];
    char term_code[100], sd_term_msg[100];
    const char *term_msg;
    int msg_type;
@@ -426,8 +461,9 @@ void mac_cleanup(JCR *jcr, int TermCode)
 // bmicrosleep(15, 0);                /* for debugging SIGHUP */
 
    Jmsg(jcr, msg_type, 0, _("Bacula %s (%s): %s\n"
-"  Migration JobId:        %u\n"
-"  Backup JobId:           %u\n"
+"  Old Backup JobId:       %u\n"
+"  New Backup JobId:       %u\n"
+"  JobId:                  %u\n"
 "  Job:                    %s\n"
 "  Backup Level:           %s%s\n"
 "  Client:                 %s\n"
@@ -435,8 +471,10 @@ void mac_cleanup(JCR *jcr, int TermCode)
 "  Pool:                   \"%s\"\n"
 "  Start time:             %s\n"
 "  End time:               %s\n"
+"  Elapsed time:           %s\n"
+"  Priority:               %d\n"
 "  SD Files Written:       %s\n"
-"  SD Bytes Written:       %s\n"
+"  SD Bytes Written:       %s (%sB)\n"
 "  Rate:                   %.1f KB/s\n"
 "  Volume name(s):         %s\n"
 "  Volume Session Id:      %d\n"
@@ -448,8 +486,9 @@ void mac_cleanup(JCR *jcr, int TermCode)
    VERSION,
    LSMDATE,
         edt, 
-        jcr->jr.JobId,
+        jcr->target_jr.JobId,
         tjcr->jr.JobId,
+        jcr->jr.JobId,
         jcr->jr.Job,
         level_to_str(jcr->JobLevel), jcr->since,
         jcr->client->hdr.name,
@@ -457,8 +496,11 @@ void mac_cleanup(JCR *jcr, int TermCode)
         jcr->pool->hdr.name,
         sdt,
         edt,
+        edit_utime(RunTime, elapsed, sizeof(elapsed)),
+        jcr->JobPriority,
         edit_uint64_with_commas(jcr->SDJobFiles, ec2),
         edit_uint64_with_commas(jcr->SDJobBytes, ec3),
+        edit_uint64_with_suffix(jcr->jr.JobBytes, ec4),
         (float)kbps,
         tjcr->VolumeName,
         jcr->VolSessionId,
@@ -469,5 +511,7 @@ void mac_cleanup(JCR *jcr, int TermCode)
         term_code);
 
    Dmsg1(100, "Leave mac_cleanup() target_jcr=0x%x\n", jcr->target_jcr);
-   free_jcr(jcr->target_jcr);
+   if (jcr->target_jcr) {
+      free_jcr(jcr->target_jcr);
+   }
 }
index b10447272d08d6da99689513a9f6c44d2cf5f023..354c5ddec2455f97c57a7eee4d6c6d933276b496 100644 (file)
@@ -13,7 +13,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
index d04e55e9b4c432162038eed171d3d061baa5eb0e..e2bcfe616df6b211d530d0d4261388831a3a1504 100644 (file)
@@ -9,7 +9,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2001-2005 Kern Sibbald
+   Copyright (C) 2001-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -26,6 +26,9 @@
 #include "bacula.h"
 #include "dird.h"
 
+static bool get_scratch_volume(JCR *jcr, MEDIA_DBR *mr, bool InChanger);
+
+
 /*
  *  Items needed:
  *   mr.PoolId must be set
@@ -43,7 +46,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, bool create)
    STORE *store = jcr->store;
 
    bstrncpy(mr->MediaType, store->media_type, sizeof(mr->MediaType));
-   Dmsg2(100, "CatReq FindMedia: Id=%d, MediaType=%s\n", (int)mr->PoolId, mr->MediaType);
+   Dmsg2(100, "CatReq FindMedia: PoolId=%d, MediaType=%s\n", (int)mr->PoolId, mr->MediaType);
    /*
     * If we are using an Autochanger, restrict Volume
     *   search to the Autochanger on the first pass
@@ -87,48 +90,10 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, bool create)
          }
 
          if (!ok) {
-            MEDIA_DBR smr;
-            POOL_DBR pr;
-            POOLMEM *query;
-            char ed1[50], ed2[50];
             /*
              * 5. Try pulling a volume from the Scratch pool
              */ 
-             memset(&pr, 0, sizeof(pr));
-             bstrncpy(pr.Name, "Scratch", sizeof(pr.Name));
-             if (db_get_pool_record(jcr, jcr->db, &pr)) {
-                memset(&smr, 0, sizeof(smr));
-                smr.PoolId = pr.PoolId;
-                bstrncpy(smr.VolStatus, "Append", sizeof(smr.VolStatus));  /* want only appendable volumes */
-                bstrncpy(smr.MediaType, mr->MediaType, sizeof(smr.MediaType));
-                if (db_find_next_volume(jcr, jcr->db, 1, InChanger, &smr)) {
-                   query = get_pool_memory(PM_MESSAGE);
-                   db_lock(jcr->db);
-                   Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
-                        edit_int64(mr->PoolId, ed1),
-                        edit_int64(smr.MediaId, ed2));
-                   ok = db_sql_query(jcr->db, query, NULL, NULL);  
-                   db_unlock(jcr->db);
-                   Jmsg(jcr, M_INFO, 0, _("Using Volume \"%s\" from 'Scratch' pool.\n"), 
-                        smr.VolumeName);
-                   /* Set new Pool Id in smr record, then copy it to mr */
-                   smr.PoolId = mr->PoolId;
-                   memcpy(mr, &smr, sizeof(MEDIA_DBR));
-                   memset(&pr, 0, sizeof(pr));
-                   bstrncpy(pr.Name, jcr->pool->hdr.name, sizeof(pr.Name));
-                   /* Set default parameters from current pool */
-                   if (db_get_pool_record(jcr, jcr->db, &pr)) {
-                      set_pool_dbr_defaults_in_media_dbr(mr, &pr);
-                      if (!db_update_media_record(jcr, jcr->db, mr)) {
-                         Jmsg(jcr, M_WARNING, 0, _("Unable to update Volume record: ERR=%s"), 
-                            db_strerror(jcr->db));
-                      }
-                   } else {
-                      Jmsg(jcr, M_WARNING, 0, _("Unable to get Pool record: ERR=%s"), 
-                         db_strerror(jcr->db));
-                   }
-                }
-             }
+            ok = get_scratch_volume(jcr, mr, InChanger);
          }
 
          if (!ok && create) {
@@ -333,3 +298,71 @@ void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, const char **r
       }
    }
 }
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static bool get_scratch_volume(JCR *jcr, MEDIA_DBR *mr, bool InChanger)
+{
+   MEDIA_DBR smr;
+   POOL_DBR spr, pr;
+   bool ok = false;
+   char ed1[50], ed2[50];
+
+   /* Only one thread at a time can pull from the scratch pool */
+   P(mutex);
+   /*   
+    * Get pool record where the Scratch Volume will go
+    */
+   memset(&pr, 0, sizeof(pr));
+   bstrncpy(pr.Name, jcr->pool->hdr.name, sizeof(pr.Name));
+   if (!db_get_pool_record(jcr, jcr->db, &pr)) {
+      Jmsg(jcr, M_WARNING, 0, _("Unable to get Pool record: ERR=%s"), 
+           db_strerror(jcr->db));
+      goto bail_out;
+   }
+   if (pr.MaxVols > 0 && pr.NumVols >= pr.MaxVols) {
+      Jmsg(jcr, M_WARNING, 0, _("Unable to use Scratch Volume, Pool full MaxVols=%d\n"),
+         pr.MaxVols);
+      goto bail_out;
+   }
+   /* 
+    * Get Pool record for Scratch Pool
+    */
+   memset(&spr, 0, sizeof(spr));
+   bstrncpy(spr.Name, "Scratch", sizeof(spr.Name));
+   if (db_get_pool_record(jcr, jcr->db, &spr)) {
+      memset(&smr, 0, sizeof(smr));
+      smr.PoolId = spr.PoolId;
+      bstrncpy(smr.VolStatus, "Append", sizeof(smr.VolStatus));  /* want only appendable volumes */
+      bstrncpy(smr.MediaType, mr->MediaType, sizeof(smr.MediaType));
+      if (db_find_next_volume(jcr, jcr->db, 1, InChanger, &smr)) {
+         POOL_MEM query(PM_MESSAGE);
+         db_lock(jcr->db);
+         Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
+              edit_int64(mr->PoolId, ed1),
+              edit_int64(smr.MediaId, ed2));
+         ok = db_sql_query(jcr->db, query.c_str(), NULL, NULL);  
+         db_unlock(jcr->db);
+         if (!ok) {
+            Jmsg(jcr, M_WARNING, 0, _("Failed to move Scratch Volume. ERR=%s\n"),
+               db_strerror(jcr->db));
+           goto bail_out;
+          }
+         Jmsg(jcr, M_INFO, 0, _("Using Volume \"%s\" from 'Scratch' pool.\n"), 
+              smr.VolumeName);
+         /* Set new Pool Id in smr record, then copy it to mr */
+         smr.PoolId = mr->PoolId;
+         memcpy(mr, &smr, sizeof(MEDIA_DBR));
+         /* Set default parameters from current pool */
+         set_pool_dbr_defaults_in_media_dbr(mr, &pr);
+         if (!db_update_media_record(jcr, jcr->db, mr)) {
+            Jmsg(jcr, M_WARNING, 0, _("Unable to update Volume record: ERR=%s"), 
+                 db_strerror(jcr->db));
+            ok = false;
+         }
+      }
+   }
+bail_out:
+   V(mutex);
+   return ok;
+}
index ef34968eb3bc1aa33fd04f626b65ab89beca8a9d..15ce08bbbd28e1294d9ac438bfdc9d8fef685ec7 100644 (file)
@@ -97,9 +97,11 @@ extern bool get_or_create_fileset_record(JCR *jcr);
 extern JobId_t run_job(JCR *jcr);
 extern bool cancel_job(UAContext *ua, JCR *jcr);
 extern void init_jcr_job_record(JCR *jcr);
-extern void copy_storage(JCR *new_jcr, JCR *old_jcr);
+extern void copy_storage(JCR *jcr, alist *storage);
 extern void set_storage(JCR *jcr, STORE *store);
 extern bool setup_job(JCR *jcr);
+extern void create_clones(JCR *jcr);
+extern bool create_restore_bootstrap_file(JCR *jcr);
 
 /* mac.c */
 extern bool do_mac(JCR *jcr);
@@ -152,6 +154,7 @@ enum e_pool_op {
 };
 int create_pool(JCR *jcr, B_DB *db, POOL *pool, e_pool_op op);
 void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr);
+void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op);
 
 /* ua_input.c */
 int get_cmd(UAContext *ua, const char *prompt);
index 20d5b5db3dab261207e2a38fcbba74ac9a20d56a..11241990ff5d3241188ac78606e90a0f1361478c 100644 (file)
@@ -78,7 +78,7 @@ int recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr)
    if (InChanger) {
       char changer[100];
       bsnprintf(changer, sizeof(changer), "AND InChanger=1 AND StorageId=%s",
-         mr->StorageId);
+         edit_uint64(mr->StorageId, ed1));
       Mmsg(query, select, edit_int64(mr->PoolId, ed1), mr->MediaType, changer);
    } else {
       Mmsg(query, select, edit_int64(mr->PoolId, ed1), mr->MediaType, "");
index df9593c377eb20aba5a3ef7f4ba7a5e888065591..6ab82d7ff22b81203aab62115cc374acb29f66de 100644 (file)
@@ -222,7 +222,7 @@ static int add_cmd(UAContext *ua, const char *cmd)
       pr.MaxVols, pr.PoolType);
 
    while (pr.MaxVols > 0 && pr.NumVols >= pr.MaxVols) {
-      bsendmsg(ua, _("Pool already has maximum volumes = %d\n"), pr.MaxVols);
+      bsendmsg(ua, _("Pool already has maximum volumes=%d\n"), pr.MaxVols);
       for (;;) {
          if (!get_pint(ua, _("Enter new maximum (zero for unlimited): "))) {
             return 1;
index dce647bbb81c4fd85807fa540c21b31b1ee97dd9..f94121061a4779673f327985ffe4ea9174bcee9c 100644 (file)
@@ -544,6 +544,10 @@ static void label_from_barcodes(UAContext *ua, int drive)
                 bsendmsg(ua, "%s", db_strerror(ua->db));
             }
          } else {                        /* create the media record */
+            if (pr.MaxVols > 0 && pr.NumVols >= pr.MaxVols) {
+               bsendmsg(ua, _("Maximum pool Volumes=%d reached.\n"), pr.MaxVols);
+               goto bail_out;
+            }
             set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
             bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
             mr.MediaType[0] = 0;
index 9a94681b0cbec21c41ddc0eeac147cc9d61d7898..c3f1ac1883a37bbb4bd0d8e2c711018d8d063ad7 100644 (file)
@@ -463,12 +463,12 @@ static bool list_nextvol(UAContext *ua, int ndays)
       if (!complete_jcr_for_job(jcr, job, pool)) {
          return false;
       }
-      mr.PoolId = jcr->PoolId;
+      mr.PoolId = jcr->jr.PoolId;
       if (run->storage) {
          jcr->store = run->storage;
       }
       memset(&pr, 0, sizeof(pr));
-      pr.PoolId = jcr->PoolId;
+      pr.PoolId = jcr->jr.PoolId;
       if (! db_get_pool_record(ua->jcr, ua->db, &pr)) {
          strcpy(pr.Name, "*UnknownPool*");
       }
@@ -626,7 +626,6 @@ int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool)
          Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
       }
    }
-   jcr->PoolId = pr.PoolId;
    jcr->jr.PoolId = pr.PoolId;
    return 1;
 }
index 49f6aa9f2923804a1a96173db491f4fe6ce938a5..5a2d1189ff6b41b65e63e946d99ef4bac316d214 100644 (file)
@@ -267,7 +267,7 @@ int purgecmd(UAContext *ua, const char *cmd)
 static int purge_files_from_client(UAContext *ua, CLIENT *client)
 {
    struct s_file_del_ctx del;
-   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
    int i;
    CLIENT_DBR cr;
    char ed1[50];
@@ -340,13 +340,12 @@ bail_out:
  * is older than the retention period, we unconditionally delete
  * it and all File records for that Job.  This is simple enough that no
  * temporary tables are needed. We simply make an in memory list of
- * the JobIds meeting the prune conditions, then delete the Job,
- * Files, and JobMedia records in that list.
+ * the JobIds then delete the Job, Files, and JobMedia records in that list.
  */
 static int purge_jobs_from_client(UAContext *ua, CLIENT *client)
 {
    struct s_job_del_ctx del;
-   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
    int i;
    CLIENT_DBR cr;
    char ed1[50];
@@ -426,10 +425,10 @@ bail_out:
 
 void purge_files_from_job(UAContext *ua, JOB_DBR *jr)
 {
-   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
    char ed1[50];
 
-   edit_int64(jr->JobId,ed1);
+   edit_int64(jr->JobId, ed1);
    Mmsg(query, "DELETE FROM File WHERE JobId=%s", ed1);
    db_sql_query(ua->db, query, NULL, (void *)NULL);
 
@@ -448,7 +447,7 @@ void purge_files_from_volume(UAContext *ua, MEDIA_DBR *mr )
  */
 int purge_jobs_from_volume(UAContext *ua, MEDIA_DBR *mr)
 {
-   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
    struct s_count_ctx cnt;
    struct s_file_del_ctx del;
    int i, stat = 0;
index 57c5d9a7348f0e48af708d7034eca9aceec956bd..5db990706f41e514c2e650136c4dd3d035bbbf4c 100644 (file)
@@ -249,6 +249,15 @@ static int get_client_name(UAContext *ua, RESTORE_CTX *rx)
    return 1;
 }
 
+static bool has_value(UAContext *ua, int i)
+{
+   if (!ua->argv[i]) {
+      bsendmsg(ua, _("Missing value for keyword: %s\n"), ua->argk[i]);
+      return false;
+   }
+   return true;
+}
+
 /*
  * The first step in the restore process is for the user to
  *  select a list of JobIds from which he will subsequently
@@ -321,6 +330,9 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
       /* Found keyword in kw[] list, process it */
       switch (j) {
       case 0:                            /* jobid */
+         if (!has_value(ua, i)) {
+            return 0;
+         }
          if (*rx->JobIds != 0) {
             pm_strcat(rx->JobIds, ",");
          }
@@ -332,6 +344,9 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
          have_date = true;
          break;
       case 2:                            /* before */
+         if (!has_value(ua, i)) {
+            return 0;
+         }
          if (str_to_utime(ua->argv[i]) == 0) {
             bsendmsg(ua, _("Improper date format: %s\n"), ua->argv[i]);
             return 0;
@@ -341,6 +356,9 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
          break;
       case 3:                            /* file */
       case 4:                            /* dir */
+         if (!has_value(ua, i)) {
+            return 0;
+         }
          if (!have_date) {
             bstrutime(date, sizeof(date), time(NULL));
          }
@@ -365,6 +383,9 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
          done = true;
          break;
       case 6:                            /* pool specified */
+         if (!has_value(ua, i)) {
+            return 0;
+         }
          rx->pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
          if (!rx->pool) {
             bsendmsg(ua, _("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]);
index 95e3abb740e4f5aef8eeea89f3e6f36a9dfd6142..84138f31b0df4961d6ec14e8e0f355905b9fd9b9 100644 (file)
@@ -379,7 +379,7 @@ static void prt_runtime(UAContext *ua, sched_pkt *sp)
          close_db = true;             /* new db opened, remember to close it */
       }
       if (ok) {
-         mr.PoolId = jcr->PoolId;
+         mr.PoolId = jcr->jr.PoolId;
          ok = find_next_volume_for_append(jcr, &mr, 1, false/*no create*/);
       }
       if (!ok) {
index 22e3e3a09864f6a71e01398275958e141c3633b2..c02ab2bca41cbfc8e22e499c3f3104aeea7ed749 100644 (file)
@@ -29,7 +29,6 @@
 extern char *list_pool;               /* in sql_cmds.c */
 
 /* Imported functions */
-void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op);
 void update_slots(UAContext *ua);
 
 
@@ -515,7 +514,7 @@ static int update_volume(UAContext *ua)
          }
          Slot = ua->pint32_val;
          if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) {
-            bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"),
+            bsendmsg(ua, _("Invalid slot, it must be between 0 and MaxVols=%d\n"),
                pr.MaxVols);
             break;
          }
index 97be8d80953e7cd28471a2510396d6bffd184d3f..45b0246a5856f54b2fc9a35f765bac26fdf9eba2 100644 (file)
@@ -126,34 +126,9 @@ bool do_verify_init(JCR *jcr)
     *   File daemon but not used).
     */
    if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
-      RESTORE_CTX rx;
-      UAContext *ua;
-      memset(&rx, 0, sizeof(rx));
-      rx.bsr = new_bsr();
-      rx.JobIds = "";                       
-      rx.bsr->JobId = jcr->target_jr.JobId;
-      ua = new_ua_context(jcr);
-      complete_bsr(ua, rx.bsr);
-      rx.bsr->fi = new_findex();
-      rx.bsr->fi->findex = 1;
-      rx.bsr->fi->findex2 = jcr->target_jr.JobFiles;
-      jcr->ExpectedFiles = write_bsr_file(ua, rx);
-      if (jcr->ExpectedFiles == 0) {
-         free_ua_context(ua);
-         free_bsr(rx.bsr);
+      if (!create_restore_bootstrap_file(jcr)) {
          return false;
       }
-      if (jcr->RestoreBootstrap) {
-         free(jcr->RestoreBootstrap);
-      }
-      POOLMEM *fname = get_pool_memory(PM_MESSAGE);
-      make_unique_restore_filename(ua, &fname);
-      jcr->RestoreBootstrap = bstrdup(fname);
-      free_ua_context(ua);
-      free_bsr(rx.bsr);
-      free_pool_memory(fname);
-      jcr->needs_sd = true;
-
    } else {
       jcr->sd_auth_key = bstrdup("dummy");    /* dummy Storage daemon key */
    }
index 515b7944d20f334932f760066dfa5963d246daba..f01b862d24110633a2290b3d59f7aa2df1b650d6 100644 (file)
@@ -89,13 +89,13 @@ static RES_ITEM cli_items[] = {
    {"heartbeatinterval", store_time, ITEM(res_client.heartbeat_interval), 0, ITEM_DEFAULT, 0},
    {"sdconnecttimeout", store_time,ITEM(res_client.SDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
    {"maximumnetworkbuffersize", store_pint, ITEM(res_client.max_network_buffer_size), 0, 0, 0},
-   {"pkisignatures",         store_yesno,     ITEM(res_client.pki_sign), 1, ITEM_DEFAULT, 0},
-   {"pkiencryption",         store_yesno,     ITEM(res_client.pki_encrypt), 1, ITEM_DEFAULT, 0},
+   {"pkisignatures",         store_bit,     ITEM(res_client.pki_sign), 1, ITEM_DEFAULT, 0},
+   {"pkiencryption",         store_bit,     ITEM(res_client.pki_encrypt), 1, ITEM_DEFAULT, 0},
    {"pkikeypair",            store_dir,       ITEM(res_client.pki_keypair_file), 0, 0, 0},
    {"pkisigner",             store_alist_str, ITEM(res_client.pki_signing_key_files), 0, 0, 0},
    {"pkimasterkey",          store_alist_str, ITEM(res_client.pki_master_key_files), 0, 0, 0},
-   {"tlsenable",             store_yesno,     ITEM(res_client.tls_enable),  1, 0, 0},
-   {"tlsrequire",            store_yesno,     ITEM(res_client.tls_require), 1, 0, 0},
+   {"tlsenable",             store_bit,     ITEM(res_client.tls_enable),  1, 0, 0},
+   {"tlsrequire",            store_bit,     ITEM(res_client.tls_require), 1, 0, 0},
    {"tlscacertificatefile",  store_dir,       ITEM(res_client.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir",   store_dir,       ITEM(res_client.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate",        store_dir,       ITEM(res_client.tls_certfile), 0, 0, 0},
@@ -109,10 +109,10 @@ static RES_ITEM dir_items[] = {
    {"description", store_str,      ITEM(res_dir.hdr.desc),  0, 0, 0},
    {"password",    store_password, ITEM(res_dir.password),  0, ITEM_REQUIRED, 0},
    {"address",     store_str,      ITEM(res_dir.address),   0, 0, 0},
-   {"monitor",     store_yesno,    ITEM(res_dir.monitor),   1, ITEM_DEFAULT, 0},
-   {"tlsenable",            store_yesno,     ITEM(res_dir.tls_enable), 1, 0, 0},
-   {"tlsrequire",           store_yesno,     ITEM(res_dir.tls_require), 1, 0, 0},
-   {"tlsverifypeer",        store_yesno,     ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
+   {"monitor",     store_bit,    ITEM(res_dir.monitor),   1, ITEM_DEFAULT, 0},
+   {"tlsenable",            store_bit,     ITEM(res_dir.tls_enable), 1, 0, 0},
+   {"tlsrequire",           store_bit,     ITEM(res_dir.tls_require), 1, 0, 0},
+   {"tlsverifypeer",        store_bit,     ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
    {"tlscacertificatefile", store_dir,       ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir",  store_dir,       ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate",       store_dir,       ITEM(res_dir.tls_certfile), 0, 0, 0},
index ac4ad05fcecf36e9909061e017f2e8fdcaba9d24..fa9561ff65d84d6df233e5e2cfa367046a06b713 100644 (file)
@@ -69,8 +69,8 @@ static RES_ITEM dir_items[] = {
    {"dirport",     store_int,      ITEM(dir_res.DIRport),  0, ITEM_DEFAULT, 9101},
    {"address",     store_str,      ITEM(dir_res.address),  0, ITEM_REQUIRED, 0},
    {"password",    store_password, ITEM(dir_res.password), 0, 0, 0},
-   {"tlsenable",      store_yesno,     ITEM(dir_res.tls_enable), 1, 0, 0},
-   {"tlsrequire",     store_yesno,     ITEM(dir_res.tls_require), 1, 0, 0},
+   {"tlsenable",      store_bit,     ITEM(dir_res.tls_enable), 1, 0, 0},
+   {"tlsrequire",     store_bit,     ITEM(dir_res.tls_require), 1, 0, 0},
    {"tlscacertificatefile", store_dir, ITEM(dir_res.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir", store_dir,  ITEM(dir_res.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate", store_dir,       ITEM(dir_res.tls_certfile), 0, 0, 0},
@@ -82,8 +82,8 @@ static RES_ITEM con_items[] = {
    {"name",        store_name,     ITEM(con_res.hdr.name), 0, ITEM_REQUIRED, 0},
    {"description", store_str,      ITEM(con_res.hdr.desc), 0, 0, 0},
    {"password",    store_password, ITEM(con_res.password), 0, ITEM_REQUIRED, 0},
-   {"tlsenable",      store_yesno,     ITEM(con_res.tls_enable), 1, 0, 0},
-   {"tlsrequire",     store_yesno,     ITEM(con_res.tls_require), 1, 0, 0},
+   {"tlsenable",      store_bit,     ITEM(con_res.tls_enable), 1, 0, 0},
+   {"tlsrequire",     store_bit,     ITEM(con_res.tls_require), 1, 0, 0},
    {"tlscacertificatefile", store_dir, ITEM(con_res.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir", store_dir,  ITEM(con_res.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate", store_dir,       ITEM(con_res.tls_certfile), 0, 0, 0},
@@ -95,7 +95,7 @@ static RES_ITEM con_font_items[] = {
    {"name",        store_name,     ITEM(con_font.hdr.name), 0, ITEM_REQUIRED, 0},
    {"description", store_str,      ITEM(con_font.hdr.desc), 0, 0, 0},
    {"font",        store_str,      ITEM(con_font.fontface), 0, 0, 0},
-   {"requiressl",  store_yesno,    ITEM(con_font.require_ssl), 1, ITEM_DEFAULT, 0},
+   {"requiressl",  store_bit,    ITEM(con_font.require_ssl), 1, ITEM_DEFAULT, 0},
    {NULL, NULL, NULL, 0, 0, 0}
 };
 
index 5d5c761a7cda80e076e482cd43ab577dbe20a320..a0e51aaaf23fccbad66f0bf3da1a57db70588296 100644 (file)
@@ -185,7 +185,6 @@ public:
    volatile int FDJobStatus;          /* File daemon Job Status */
    uint32_t ExpectedFiles;            /* Expected restore files */
    uint32_t MediaId;                  /* DB record IDs associated with this job */
-   uint32_t PoolId;                   /* Pool record id */
    FileId_t FileId;                   /* Last file id inserted */
    uint32_t FileIndex;                /* Last FileIndex processed */
    POOLMEM *fname;                    /* name to put into catalog */
index aaa75baf1f429899ae6fa26b2fff8e6877c27ed3..1e8b2be9edbbb60b64fa8928971c4756b1b5bacc 100755 (executable)
@@ -191,8 +191,10 @@ void init_resource(int type, RES_ITEM *items, int pass)
             (items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
             items[i].default_value);
       if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) {
-         if (items[i].handler == store_yesno) {
+         if (items[i].handler == store_bit) {
             *(int *)(items[i].value) |= items[i].code;
+         } else if (items[i].handler == store_bool) {
+            *(bool *)(items[i].value) = items[i].default_value;
          } else if (items[i].handler == store_pint ||
                     items[i].handler == store_int) {
             *(int *)(items[i].value) = items[i].default_value;
@@ -688,20 +690,36 @@ void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
 
 
 /* Store a yes/no in a bit field */
-void store_yesno(LEX *lc, RES_ITEM *item, int index, int pass)
+void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
 {
    lex_get_token(lc, T_NAME);
-   if (strcasecmp(lc->str, "yes") == 0) {
+   if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
       *(int *)(item->value) |= item->code;
-   } else if (strcasecmp(lc->str, "no") == 0) {
+   } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
       *(int *)(item->value) &= ~(item->code);
    } else {
-      scan_err3(lc, _("Expect a %s or %s, got: %s"), "YES", "NO", lc->str); /* YES and NO must not be translated */
+      scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
    }
    scan_to_eol(lc);
    set_bit(index, res_all.hdr.item_present);
 }
 
+/* Store a bool in a bit field */
+void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+   lex_get_token(lc, T_NAME);
+   if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
+      *(bool *)(item->value) = true;
+   } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
+      *(bool *)(item->value) = false;
+   } else {
+      scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
+   }
+   scan_to_eol(lc);
+   set_bit(index, res_all.hdr.item_present);
+}
+
+
 /*
  * Store Tape Label Type (Bacula, ANSI, IBM)
  *
index af81738e579bc1e04a567797c07736a1c435d36f..754a009cc75ba7a5b4927addf036dcc084de0aa5 100644 (file)
@@ -21,7 +21,7 @@
 
  */
 
-struct RES_ITEM;                   /* Declare forward referenced structure */
+struct RES_ITEM;                    /* Declare forward referenced structure */
 typedef void (MSG_RES_HANDLER)(LEX *lc, RES_ITEM *item, int index, int pass);
 
 /* This is the structure that defines
@@ -30,29 +30,29 @@ typedef void (MSG_RES_HANDLER)(LEX *lc, RES_ITEM *item, int index, int pass);
  * tables.
  */
 struct RES_ITEM {
-   const char *name;                 /* Resource name i.e. Director, ... */
-   MSG_RES_HANDLER *handler;         /* Routine storing the resource item */
-   void **value;                     /* Where to store the item */
-   int code;                         /* item code/additional info */
-   int flags;                        /* flags: default, required, ... */
-   int default_value;                /* default value */
+   const char *name;                  /* Resource name i.e. Director, ... */
+   MSG_RES_HANDLER *handler;          /* Routine storing the resource item */
+   void **value;                      /* Where to store the item */
+   int  code;                         /* item code/additional info */
+   int  flags;                        /* flags: default, required, ... */
+   int  default_value;                /* default value */
 };
 
 /* For storing name_addr items in res_items table */
 #define ITEM(x) ((void **)&res_all.x)
 
-#define MAX_RES_ITEMS 70             /* maximum resource items per RES */
+#define MAX_RES_ITEMS 70              /* maximum resource items per RES */
 
 /* This is the universal header that is
  * at the beginning of every resource
  * record.
  */
 struct RES {
-   RES *next;                        /* pointer to next resource of this type */
-   char *name;                       /* resource name */
-   char *desc;                       /* resource description */
-   int  rcode;                       /* resource id or type */
-   int  refcnt;                      /* reference count for releasing */
+   RES *next;                         /* pointer to next resource of this type */
+   char *name;                        /* resource name */
+   char *desc;                        /* resource description */
+   int   rcode;                       /* resource id or type */
+   int   refcnt;                      /* reference count for releasing */
    char  item_present[MAX_RES_ITEMS]; /* set if item is present in conf file */
 };
 
@@ -63,25 +63,25 @@ struct RES {
  * resources that are available to this daemon.
  */
 struct RES_TABLE {
-   const char *name;                 /* resource name */
-   RES_ITEM *items;                  /* list of resource keywords */
-   int rcode;                        /* code if needed */
+   const char *name;                  /* resource name */
+   RES_ITEM *items;                   /* list of resource keywords */
+   int rcode;                         /* code if needed */
 };
 
 /* Common Resource definitions */
 
-#define MAX_RES_NAME_LENGTH MAX_NAME_LENGTH-1      /* maximum resource name length */
+#define MAX_RES_NAME_LENGTH MAX_NAME_LENGTH-1       /* maximum resource name length */
 
-#define ITEM_REQUIRED   0x1          /* item required */
-#define ITEM_DEFAULT    0x2          /* default supplied */
+#define ITEM_REQUIRED    0x1          /* item required */
+#define ITEM_DEFAULT     0x2          /* default supplied */
 #define ITEM_NO_EQUALS   0x4          /* Don't scan = after name */
 
 /* Message Resource */
 struct MSGS {
-   RES  hdr;
-   char *mail_cmd;                   /* mail command */
-   char *operator_cmd;               /* Operator command */
-   DEST *dest_chain;                 /* chain of destinations */
+   RES   hdr;
+   char *mail_cmd;                    /* mail command */
+   char *operator_cmd;                /* Operator command */
+   DEST *dest_chain;                  /* chain of destinations */
    char send_msg[nbytes_for_bits(M_MAX+1)];  /* bit array of types */
 };
 
@@ -97,7 +97,7 @@ union CURES {
 
 /* Configuration routines */
 int   parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error = NULL);
-void   free_config_resources(void);
+void    free_config_resources(void);
 RES   **save_config_resources(void);
 RES   **new_res_head();
 
@@ -119,7 +119,7 @@ const char *res_to_str(int rcode);
 
 #ifdef the_old_way
 #define foreach_res(var, type) \
-       for((var)=NULL; (((void *)(var))=GetNextRes((type), (RES *)var));)
+        for((var)=NULL; (((void *)(var))=GetNextRes((type), (RES *)var));)
 #endif
 
 
@@ -135,7 +135,8 @@ void store_int(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_pint(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass);
-void store_yesno(LEX *lc, RES_ITEM *item, int index, int pass);
+void store_bit(LEX *lc, RES_ITEM *item, int index, int pass);
+void store_bool(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_time(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_size(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass);
index 7977f5468b7c3209d3a86fa8ca07052626226fbf..0d779b9855ef0e19da2c78b419a333965592ab9f 100644 (file)
 #include "bacula.h"                   /* pull in global headers */
 #include "stored.h"                   /* pull in Storage Deamon headers */
 
-/*
- * Create a new Device Control Record and attach
- *   it to the device (if this is a real job).
- */
-DCR *new_dcr(JCR *jcr, DEVICE *dev)
-{
-   DCR *dcr = (DCR *)malloc(sizeof(DCR));
-   memset(dcr, 0, sizeof(DCR));
-   dcr->jcr = jcr;
-   if (dev) {
-      dcr->dev = dev;
-      dcr->device = dev->device;
-      dcr->block = new_block(dev);
-      dcr->rec = new_record();
-      dcr->max_job_spool_size = dev->device->max_job_spool_size;
-      /* Attach this dcr only if dev is initialized */
-      if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
-         dev->attached_dcrs->append(dcr);  /* attach dcr to device */
-//       jcr->dcrs->append(dcr);         /* put dcr in list for Job */
-      }
-   }
-   dcr->spool_fd = -1;
-   return dcr;
-}
-
-/*
- * Search the dcrs list for the given dcr. If it is found,
- *  as it should be, then remove it. Also zap the jcr pointer
- *  to the dcr if it is the same one.
- */
-#ifdef needed
-static void remove_dcr_from_dcrs(DCR *dcr)
-{
-   JCR *jcr = dcr->jcr;
-   if (jcr->dcrs) {
-      int i = 0;
-      DCR *ldcr;
-      int num = jcr->dcrs->size();
-      for (i=0; i < num; i++) {
-         ldcr = (DCR *)jcr->dcrs->get(i);
-         if (ldcr == dcr) {
-            jcr->dcrs->remove(i);
-            if (jcr->dcr == dcr) {
-               jcr->dcr = NULL;
-            }
-         }
-      }
-   }
-}
-#endif
-
-/*
- * Free up all aspects of the given dcr -- i.e. dechain it,
- *  release allocated memory, zap pointers, ...
- */
-void free_dcr(DCR *dcr)
-{
-   JCR *jcr = dcr->jcr;
-   DEVICE *dev = dcr->dev;
-
-   if (dcr->reserved_device) {
-      lock_device(dev);
-      dev->reserved_device--;
-      /* If we set read mode in reserving, remove it */
-      if (dev->can_read()) {
-         dev->clear_read();
-      }
-      Dmsg1(100, "Dec reserve=%d\n", dev->reserved_device);
-      dcr->reserved_device = false;
-      if (dev->num_writers < 0) {
-         Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
-         dev->num_writers = 0;
-      }
-      unlock_device(dev);
-   }
-
-   /* Detach this dcr only if the dev is initialized */
-   if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
-      dev->attached_dcrs->remove(dcr);  /* detach dcr from device */
-//    remove_dcr_from_dcrs(dcr);      /* remove dcr from jcr list */
-   }
-   if (dcr->block) {
-      free_block(dcr->block);
-   }
-   if (dcr->rec) {
-      free_record(dcr->rec);
-   }
-   if (dcr->jcr) {
-      dcr->jcr->dcr = NULL;
-   }
-   free_unused_volume(dcr);           /* free unused vols attached to this dcr */
-   free(dcr);
-   pthread_cond_broadcast(&dev->wait_next_vol);
-   pthread_cond_broadcast(&wait_device_release);
-}
 
 /*********************************************************************
  * Acquire device for reading. 
@@ -162,6 +67,16 @@ DCR *acquire_device_for_read(DCR *dcr)
       goto get_out;                   /* should not happen */   
    }
    bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
+   bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
+   dcr->VolCatInfo.Slot = vol->Slot;
+   Dmsg4(100, "===== Vol=%s MT=%s Slt=%d Dev-MT=%s\n", dcr->VolumeName,        
+      dcr->media_type, vol->Slot, dev->device->media_type);
+
+   if (strcmp(dcr->media_type, dev->device->media_type) != 0) {
+      Dmsg2(000, "Wrong MT have=%s want=%s\n", dev->device->media_type,
+         dcr->media_type);
+      Dmsg1(000, "New storage=%s\n", vol->storage);
+   }
 
    init_device_wait_timers(dcr);
 
@@ -274,6 +189,13 @@ default_path:
       dcr->VolumeName, dev->print_name());
 
 get_out:
+   P(dev->mutex);
+   if (dcr->reserved_device) {
+      dev->reserved_device--;
+      Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
+      dcr->reserved_device = false;
+   }
+   V(dev->mutex);
    dev->unblock();
    if (!vol_ok) {
       dcr = NULL;
@@ -396,7 +318,7 @@ DCR *acquire_device_for_append(DCR *dcr)
    P(dev->mutex);
    if (dcr->reserved_device) {
       dev->reserved_device--;
-      Dmsg1(100, "Dec reserve=%d\n", dev->reserved_device);
+      Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
       dcr->reserved_device = false;
    }
    V(dev->mutex);
@@ -410,7 +332,7 @@ get_out:
    P(dev->mutex);
    if (dcr->reserved_device) {
       dev->reserved_device--;
-      Dmsg1(100, "Dec reserve=%d\n", dev->reserved_device);
+      Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
       dcr->reserved_device = false;
    }
    V(dev->mutex);
@@ -418,6 +340,7 @@ get_out:
    return NULL;
 }
 
+
 /*
  * This job is done, so release the device. From a Unix standpoint,
  *  the device remains open.
@@ -430,12 +353,12 @@ bool release_device(DCR *dcr)
    bool ok = true;
 
    lock_device(dev);
-   Dmsg1(100, "release_device device is %s\n", dev->is_tape()?"tape":"disk");
+   Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
 
    /* if device is reserved, job never started, so release the reserve here */
    if (dcr->reserved_device) {
       dev->reserved_device--;
-      Dmsg1(100, "Dec reserve=%d\n", dev->reserved_device);
+      Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
       dcr->reserved_device = false;
    }
 
@@ -522,3 +445,99 @@ bool release_device(DCR *dcr)
    free_dcr(dcr);
    return ok;
 }
+
+/*
+ * Create a new Device Control Record and attach
+ *   it to the device (if this is a real job).
+ */
+DCR *new_dcr(JCR *jcr, DEVICE *dev)
+{
+   DCR *dcr = (DCR *)malloc(sizeof(DCR));
+   memset(dcr, 0, sizeof(DCR));
+   dcr->jcr = jcr;
+   if (dev) {
+      dcr->dev = dev;
+      dcr->device = dev->device;
+      dcr->block = new_block(dev);
+      dcr->rec = new_record();
+      dcr->max_job_spool_size = dev->device->max_job_spool_size;
+      /* Attach this dcr only if dev is initialized */
+      if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
+         dev->attached_dcrs->append(dcr);  /* attach dcr to device */
+//       jcr->dcrs->append(dcr);         /* put dcr in list for Job */
+      }
+   }
+   dcr->spool_fd = -1;
+   return dcr;
+}
+
+/*
+ * Search the dcrs list for the given dcr. If it is found,
+ *  as it should be, then remove it. Also zap the jcr pointer
+ *  to the dcr if it is the same one.
+ */
+#ifdef needed
+static void remove_dcr_from_dcrs(DCR *dcr)
+{
+   JCR *jcr = dcr->jcr;
+   if (jcr->dcrs) {
+      int i = 0;
+      DCR *ldcr;
+      int num = jcr->dcrs->size();
+      for (i=0; i < num; i++) {
+         ldcr = (DCR *)jcr->dcrs->get(i);
+         if (ldcr == dcr) {
+            jcr->dcrs->remove(i);
+            if (jcr->dcr == dcr) {
+               jcr->dcr = NULL;
+            }
+         }
+      }
+   }
+}
+#endif
+
+/*
+ * Free up all aspects of the given dcr -- i.e. dechain it,
+ *  release allocated memory, zap pointers, ...
+ */
+void free_dcr(DCR *dcr)
+{
+   JCR *jcr = dcr->jcr;
+   DEVICE *dev = dcr->dev;
+
+   if (dcr->reserved_device) {
+      lock_device(dev);
+      dev->reserved_device--;
+      Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
+      dcr->reserved_device = false;
+      /* If we set read mode in reserving, remove it */
+      if (dev->can_read()) {
+         dev->clear_read();
+      }
+      if (dev->num_writers < 0) {
+         Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
+         dev->num_writers = 0;
+      }
+      unlock_device(dev);
+   }
+
+   /* Detach this dcr only if the dev is initialized */
+   if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
+      dev->attached_dcrs->remove(dcr);  /* detach dcr from device */
+//    remove_dcr_from_dcrs(dcr);      /* remove dcr from jcr list */
+   }
+   if (dcr->block) {
+      free_block(dcr->block);
+   }
+   if (dcr->rec) {
+      free_record(dcr->rec);
+   }
+   if (dcr->jcr) {
+      dcr->jcr->dcr = NULL;
+   }
+   free_unused_volume(dcr);           /* free unused vols attached to this dcr */
+   free(dcr);
+   pthread_cond_broadcast(&dev->wait_next_vol);
+   pthread_cond_broadcast(&wait_device_release);
+}
index 93984bcc9880566b805b136b89eb47931d014970..16557abd989d1b1e724cd438ae396dbde69f09ba 100644 (file)
@@ -213,6 +213,8 @@ bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing)
     return ok;
 }
 
+
+
 /*
  * Get info on the next appendable volume in the Director's database
  * Returns: true  on success
@@ -226,6 +228,10 @@ bool dir_find_next_appendable_volume(DCR *dcr)
     JCR *jcr = dcr->jcr;
     BSOCK *dir = jcr->dir_bsock;
     bool found = false;
+    /* This mutex should keep different devices from getting the
+     * same Volume.  
+     */
+    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
     Dmsg0(200, "dir_find_next_appendable_volume\n");
     /*
@@ -233,6 +239,7 @@ bool dir_find_next_appendable_volume(DCR *dcr)
      *   the most available could already be mounted on another
      *   drive, so we continue looking for a not in use Volume.
      */
+    P(mutex);
     for (int vol_index=1;  vol_index < 20; vol_index++) {
        bash_spaces(dcr->media_type);
        bash_spaces(dcr->pool_name);
@@ -251,15 +258,18 @@ bool dir_find_next_appendable_volume(DCR *dcr)
           }
        } else {
           Dmsg0(200, "No volume info, return false\n");
-          return false;
+          found = false;
+          break;
        }
     }
     if (found) {
        Dmsg0(400, "dir_find_next_appendable_volume return true\n");
        new_volume(dcr, dcr->VolumeName);   /* reserve volume */
+       V(mutex);
        return true;
     }
     dcr->VolumeName[0] = 0;
+    V(mutex);
     return false;
 }
 
index 821c856c2c2e06a79e8033c89bdfc3ec7fdd9bf2..e135852474046f086a8038758eef5cd0b12da48a 100644 (file)
@@ -105,6 +105,7 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir)
    POOLMEM *changer;
 
    if (!dev->is_autochanger()) {
+      Dmsg0(200, "======== NOT AUTOCHANGER ======\n");
       return 0;
    }
    slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
@@ -112,7 +113,7 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir)
     * Handle autoloaders here.  If we cannot autoload it, we
     *  will return 0 so that the sysop will be asked to load it.
     */
-   if (writing && dev->is_autochanger() && slot <= 0) {
+   if (writing && slot <= 0) {
       if (dir) {
          return 0;                    /* For user, bail out right now */
       }
@@ -155,6 +156,7 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir)
          changer = edit_device_codes(dcr, changer, 
                       dcr->device->changer_command, "load");
          dev->close();
+         Dmsg1(200, "Run program=%s\n", changer);
          status = run_program(changer, timeout, NULL);
          if (status == 0) {
             Jmsg(jcr, M_INFO, 0, _("3305 Autochanger \"load slot %d, drive %d\", status is OK.\n"),
@@ -218,8 +220,9 @@ int get_autochanger_loaded_slot(DCR *dcr)
         drive);
    changer = edit_device_codes(dcr, changer, dcr->device->changer_command, "loaded");
    *results = 0;
+   Dmsg1(200, "Run program=%s\n", changer);
    status = run_program(changer, timeout, results);
-   Dmsg3(50, "run_prog: %s stat=%d result=%s\n", changer, status, results);
+   Dmsg3(200, "run_prog: %s stat=%d result=%s\n", changer, status, results);
    if (status == 0) {
       loaded = str_to_int32(results);
       if (loaded > 0) {
@@ -300,6 +303,7 @@ bool unload_autochanger(DCR *dcr, int loaded)
       changer = edit_device_codes(dcr, changer, 
                    dcr->device->changer_command, "unload");
       dev->close();
+      Dmsg1(200, "Run program=%s\n", changer);
       int stat = run_program(changer, timeout, NULL);
       dcr->VolCatInfo.Slot = slot;
       if (stat != 0) {
@@ -331,6 +335,7 @@ static bool unload_other_drive(DCR *dcr, int slot)
    AUTOCHANGER *changer = dcr->dev->device->changer_res;
    DEVRES *device;
    bool found = false;
+   bool first = true;
 
    if (!changer) {
       return false;
@@ -349,12 +354,24 @@ static bool unload_other_drive(DCR *dcr, int slot)
    if (!found) {
       return true;
    }
+
+   /* The Volume we want is on another device. */
+       
+   for (int i=0; i < 3; i++) {
+      if (dev->is_busy()) {
+         wait_for_device(dcr->jcr, first);
+         first = false;
+         continue;
+      }
+      break;
+   }
+   P(dev->mutex);
    if (dev->is_busy()) {
-      Jmsg(jcr, M_WARNING, 0, _("Volume %s is in use by device %s\n"),
+      Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" is in use by device %s\n"),
            dcr->VolumeName, dev->print_name());
-      Dmsg2(200, "Volume %s is in use by device %s\n",
+      Dmsg2(200, "Volume \"%s\" is in use by device %s\n",
            dcr->VolumeName, dev->print_name());
-      
+      V(dev->mutex);
       return false;
    }
 
@@ -367,14 +384,16 @@ static bool unload_other_drive(DCR *dcr, int slot)
    Dmsg2(200, "Issuing autochanger \"unload slot %d, drive %d\" command.\n",
         slot, dev->drive_index);
 
-   save_slot = dcr->VolCatInfo.Slot;
    save_dev = dcr->dev;
    dcr->dev = dev;
+   save_slot = dcr->VolCatInfo.Slot;
    dcr->VolCatInfo.Slot = slot;
    changer_cmd = edit_device_codes(dcr, changer_cmd, 
                 dcr->device->changer_command, "unload");
-   Dmsg1(200, "Run program=%s\n", changer_cmd);
    dev->close();
+   Dmsg2(200, "close dev=%s reserve=%d\n", dev->print_name(), 
+      dev->reserved_device);
+   Dmsg1(200, "Run program=%s\n", changer_cmd);
    int stat = run_program(changer_cmd, timeout, NULL);
    dcr->VolCatInfo.Slot = save_slot;
    dcr->dev = save_dev;
@@ -392,6 +411,7 @@ static bool unload_other_drive(DCR *dcr, int slot)
       Dmsg0(200, "Slot unloaded\n");
    }
    unlock_changer(dcr);
+   V(dev->mutex);
    free_pool_memory(changer_cmd);
    return ok;
 }
index 9d18ea0b903c7f47f004baad8ebc4012ab85935a..9f43a847072abd85dc0b7035f233bb9cf26fb172 100644 (file)
@@ -7,22 +7,17 @@
  *
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2002-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+   modify it under the terms of the GNU General Public License
+   version 2 as amended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    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 General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
@@ -38,6 +33,7 @@ struct VOL_LIST {
    VOL_LIST *next;
    char VolumeName[MAX_NAME_LENGTH];
    char MediaType[MAX_NAME_LENGTH];
+   char storage[MAX_NAME_LENGTH];   /* ***FIXME*** use alist here */
    int Slot;
    uint32_t start_file;
 };
@@ -56,6 +52,8 @@ struct BSR_VOLUME {
    BSR_VOLUME *next;
    char VolumeName[MAX_NAME_LENGTH];
    char MediaType[MAX_NAME_LENGTH];
+   char storage[MAX_NAME_LENGTH];   /* ***FIXME*** use alist here */
+   int32_t       Slot;                /* Slot */
 };
 
 struct BSR_CLIENT {
@@ -133,7 +131,6 @@ struct BSR {
    bool          use_fast_rejection;  /* set if fast rejection can be used */
    bool          use_positioning;     /* set if we can position the archive */
    BSR_VOLUME   *volume;
-   int32_t       Slot;                /* Slot */
    uint32_t      count;               /* count of files to restore this bsr */
    uint32_t      found;               /* count of restored files this bsr */
    BSR_VOLFILE  *volfile;
index 6fadf6c981f24cbf7b9d7b48762bcad2eb632487..820bd43dd10d78759225c60414b3d6e3240046f3 100644 (file)
@@ -321,7 +321,7 @@ void DEVICE::open_tape_device(DCR *dcr, int omode)
    int nonblocking = O_NONBLOCK;
    Dmsg0(29, "open dev: device is tape\n");
 
-   if (is_tape() && is_autochanger()) {
+   if (is_autochanger()) {
       get_autochanger_loaded_slot(dcr);
    }
 
@@ -407,22 +407,33 @@ void DEVICE::open_file_device(DCR *dcr, int omode)
 {
    POOL_MEM archive_name(PM_FNAME);
 
+   if (is_autochanger()) {
+      get_autochanger_loaded_slot(dcr);
+   }
+
    /*
     * Handle opening of File Archive (not a tape)
     */     
 
-   if (VolCatInfo.VolCatName[0] == 0) {
-      Mmsg(errmsg, _("Could not open file device %s. No Volume name given.\n"),
-         print_name());
-      clear_opened();
-      return;
-   }
-
    pm_strcpy(archive_name, dev_name);
-   if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
-      pm_strcat(archive_name, "/");
+   /*  
+    * If this is a virtual autochanger (i.e. changer_res != NULL)
+    *  we simply use the deviced name, assuming it has been
+    *  appropriately setup by the "autochanger".
+    */
+   if (!device->changer_res) {
+      if (VolCatInfo.VolCatName[0] == 0) {
+         Mmsg(errmsg, _("Could not open file device %s. No Volume name given.\n"),
+            print_name());
+         clear_opened();
+         return;
+      }
+
+      if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
+         pm_strcat(archive_name, "/");
+      }
+      pm_strcat(archive_name, VolCatInfo.VolCatName);
    }
-   pm_strcat(archive_name, VolCatInfo.VolCatName);
 
    mount(1);                          /* do mount if required */
          
@@ -1801,7 +1812,7 @@ bool DEVICE::do_mount(int mount, int dotimeout)
    
    edit_mount_codes(ocmd, icmd);
    
-   Dmsg2(200, "do_mount_dvd: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
+   Dmsg2(000, "do_mount_dvd: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
 
    if (dotimeout) {
       /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
index e6d4b289ed3e766bce1bd380f8bd800ab451a12f..5c6817972a85e8c85ce5b7c9a10d0ebd09d5be9a 100644 (file)
@@ -192,7 +192,7 @@ void *handle_connection_request(void *arg)
       if ((bnet_stat = bnet_recv(bs)) <= 0) {
          break;               /* connection terminated */
       }
-      Dmsg1(199, "<dird: %s", bs->msg);
+      Dmsg1(199, "<dird: %s\n", bs->msg);
       /* Ensure that device initialization is complete */
       while (!init_done) {
          bmicrosleep(1, 0);
@@ -873,7 +873,7 @@ static bool changer_cmd(JCR *jcr)
       if (dcr) {
          dev = dcr->dev;
          P(dev->mutex);               /* Use P to avoid indefinite block */
-         if (!dev->is_tape()) {
+         if (!dev->device->changer_res) {     
             bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), 
                dev->print_name());
          /* Under certain "safe" conditions, we can steal the lock */
index c00c7d37ea01e28e05bd891261bd9f5cd8094c5c..4809fc72861c1bdacacb9a9d77d9cb1771afb8a7 100644 (file)
@@ -347,5 +347,14 @@ void stored_free_jcr(JCR *jcr)
       free_dcr(jcr->read_dcr);
       jcr->read_dcr = NULL;
    }
+   if (jcr->dirstore) {
+      DIRSTORE *store;
+      foreach_alist(store, jcr->dirstore) {
+         delete store->device;
+         delete store;
+      }
+      delete jcr->dirstore;
+      jcr->dirstore = NULL;
+   }
    return;
 }
index d88181a9c2b48c090e7a56ed62362dcfd2d61cc3..9387bc36129510339964336adebba880e5691dc8 100644 (file)
@@ -57,7 +57,8 @@ bool mount_next_write_volume(DCR *dcr, bool release)
    DEV_BLOCK *block = dcr->block;
    int mode;
 
-   Dmsg1(150, "Enter mount_next_volume(release=%d)\n", release);
+   Dmsg2(150, "Enter mount_next_volume(release=%d) dev=%s\n", release,
+      dev->print_name());
 
    init_device_wait_timers(dcr);
 
@@ -164,9 +165,9 @@ mount_next_vol:
       mode = OPEN_READ_WRITE;
    }
    while (dev->open(dcr, mode) < 0) {
-      Dmsg0(000, "open_device failed\n");
+      Dmsg0(150, "open_device failed\n");
       if (dev->is_file() && dev->is_removable()) {
-         Dmsg0(000, "call scan_dir_for_vol\n");
+         Dmsg0(150, "call scan_dir_for_vol\n");
          if (dev->scan_dir_for_volume(dcr)) {
             break;                    /* got a valid volume */
          }
@@ -394,7 +395,9 @@ read_volume:
       empty_block(block);             /* we used it for reading so set for write */
    }
    dev->set_append();
-   Dmsg0(150, "set APPEND, normal return from read_dev_for_append\n");
+   Dmsg1(150, "set APPEND, normal return from mount_next_write_volume. dev=%s\n",
+      dev->print_name());
+
    return true;
 }
 
index f5076ee584c9d769c6fbca360068802a54255648..c6eec08a18447a56cb80050d6c0290ad75dad6ec 100755 (executable)
@@ -7,7 +7,7 @@
  */
 
 /*
-   Copyright (C) 2002-2005 Kern Sibbald
+   Copyright (C) 2002-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -29,6 +29,7 @@ typedef BSR * (ITEM_HANDLER)(LEX *lc, BSR *bsr);
 
 static BSR *store_vol(LEX *lc, BSR *bsr);
 static BSR *store_mediatype(LEX *lc, BSR *bsr);
+static BSR *store_storage(LEX *lc, BSR *bsr);
 static BSR *store_client(LEX *lc, BSR *bsr);
 static BSR *store_job(LEX *lc, BSR *bsr);
 static BSR *store_jobid(LEX *lc, BSR *bsr);
@@ -73,6 +74,7 @@ struct kw_items items[] = {
    {"volblock", store_volblock},
    {"stream",  store_stream},
    {"slot",    store_slot},
+   {"storage",    store_storage},
    {NULL, NULL}
 
 };
@@ -268,6 +270,28 @@ static BSR *store_mediatype(LEX *lc, BSR *bsr)
    return bsr;
 }
 
+/* Shove the Storage name in each Volume in the current bsr */
+static BSR *store_storage(LEX *lc, BSR *bsr)
+{
+   int token;
+
+   token = lex_get_token(lc, T_STRING);
+   if (token == T_ERROR) {
+      return NULL;
+   }
+   if (!bsr->volume) {
+      Emsg1(M_ERROR,0, _("Storage %s in bsr at inappropriate place.\n"),
+         lc->str);
+      return bsr;
+   }
+   BSR_VOLUME *bv;
+   for (bv=bsr->volume; bv; bv=bv->next) {
+      bstrncpy(bv->storage, lc->str, sizeof(bv->storage));
+   }
+   return bsr;
+}
+
+
 
 static BSR *store_client(LEX *lc, BSR *bsr)
 {
@@ -603,7 +627,12 @@ static BSR *store_slot(LEX *lc, BSR *bsr)
    if (token == T_ERROR) {
       return NULL;
    }
-   bsr->Slot = lc->pint32_val;
+   if (!bsr->volume) {
+      Emsg1(M_ERROR,0, _("Slot %d in bsr at inappropriate place.\n"),
+         lc->pint32_val);
+      return bsr;
+   }
+   bsr->volume->Slot = lc->pint32_val;
    scan_to_eol(lc);
    return bsr;
 }
@@ -677,6 +706,9 @@ void dump_volume(BSR_VOLUME *volume)
 {
    if (volume) {
       Pmsg1(-1, _("VolumeName  : %s\n"), volume->VolumeName);
+      Pmsg1(-1, _("  MediaType : %s\n"), volume->MediaType);
+      Pmsg1(-1, _("  Storage   : %s\n"), volume->storage);
+      Pmsg1(-1, _("  Slot      : %d\n"), volume->Slot);
       dump_volume(volume->next);
    }
 }
@@ -730,9 +762,6 @@ void dump_bsr(BSR *bsr, bool recurse)
    dump_jobid(bsr->JobId);
    dump_job(bsr->job);
    dump_findex(bsr->FileIndex);
-   if (bsr->Slot) {
-      Pmsg1(-1, _("Slot        : %u\n"), bsr->Slot);
-   }
    if (bsr->count) {
       Pmsg1(-1, _("count       : %u\n"), bsr->count);
       Pmsg1(-1, _("found       : %u\n"), bsr->found);
@@ -875,6 +904,8 @@ void create_restore_volume_list(JCR *jcr)
             vol = new_restore_volume();
             bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName));
             bstrncpy(vol->MediaType,  bsrvol->MediaType,  sizeof(vol->MediaType));
+            bstrncpy(vol->storage, bsrvol->storage, sizeof(vol->storage));
+            vol->Slot = bsrvol->Slot;
             vol->start_file = sfile;
             if (add_restore_volume(jcr, vol)) {
                jcr->NumVolumes++;
index 384cfb7ef739c846fcde9fbfbf9f54c851132841..9c8d3b4791638cca5f790465005dc507a3a31d3c 100644 (file)
@@ -215,11 +215,12 @@ VOLRES *new_volume(DCR *dcr, const char *VolumeName);
 VOLRES *find_volume(const char *VolumeName);
 bool    free_volume(DEVICE *dev);
 void    free_unused_volume(DCR *dcr);
-void    create_volume_list();
+void    init_volume_list();
 void    free_volume_list();
 void    list_volumes(BSOCK *user);
 bool    is_volume_in_use(DCR *dcr);
 void    send_drive_reserve_messages(JCR *jcr, BSOCK *user);
+bool    find_suitable_device_for_job(JCR *jcr, RCTX &rctx);
 
 
 /* From spool.c */
index 25a030c9ebc26130f7069327a18f4b164d48195f..362eccac70fcde422a4a69fec4f8430f305a107a 100644 (file)
 #include "bacula.h"
 #include "stored.h"
 
-/*
- *   Use Device command from Director
- *   He tells is what Device Name to use, the Media Type,
- *      the Pool Name, and the Pool Type.
- *
- *    Ensure that the device exists and is opened, then store
- *      the media and pool info in the JCR.  This class is used
- *      only temporarily in this file.
- */
-class DIRSTORE {
-public:
-   alist *device;
-   bool append;
-   char name[MAX_NAME_LENGTH];
-   char media_type[MAX_NAME_LENGTH];
-   char pool_name[MAX_NAME_LENGTH];
-   char pool_type[MAX_NAME_LENGTH];
-};
-
-/* Reserve context */
-class RCTX {
-public:
-   JCR *jcr;
-   char *device_name;
-   DIRSTORE *store;
-   DEVRES   *device;
-   DEVICE *low_use_drive;             /* Low use drive candidate */
-   int num_writers;                   /* for selecting low use drive */
-   bool try_low_use_drive;            /* see if low use drive available */
-   bool any_drive;                    /* Accept any drive if set */
-   bool PreferMountedVols;            /* Prefer volumes already mounted */
-   bool exact_match;                  /* Want exact volume */
-   bool have_volume;                  /* Have DIR suggested vol name */
-   bool suitable_device;              /* at least one device is suitable */
-   bool autochanger_only;             /* look at autochangers only */
-   char VolumeName[MAX_NAME_LENGTH];  /* Vol name suggested by DIR */
-};
 
 static dlist *vol_list = NULL;
 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -75,8 +38,8 @@ static int reserve_device(RCTX &rctx);
 static bool reserve_device_for_read(DCR *dcr);
 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
 static bool use_storage_cmd(JCR *jcr);
-bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx);
 static void queue_reserve_message(JCR *jcr);
+static void release_msgs(JCR *jcr);
 
 /* Requests from the Director daemon */
 static char use_storage[]  = "use storage=%127s media_type=%127s "
@@ -246,7 +209,7 @@ void list_volumes(BSOCK *user)
 }
       
 /* Create the Volume list */
-void create_volume_list()
+void init_volume_list()
 {
    VOLRES *dummy = NULL;
    if (vol_list == NULL) {
@@ -483,11 +446,15 @@ static bool use_storage_cmd(JCR *jcr)
    }
 
 all_done:
-   foreach_alist(store, jcr->dirstore) {
-      delete store->device;
-      delete store;
-   }
-   delete jcr->dirstore;
+   release_msgs(jcr);
+   return ok;
+}
+
+static void release_msgs(JCR *jcr)
+{
+   alist *msgs = jcr->reserve_msgs;
+   char *msg;
+
    P(search_lock);
    while ((msg = (char *)msgs->pop())) {
       free(msg);
@@ -495,10 +462,8 @@ all_done:
    delete msgs;
    jcr->reserve_msgs = NULL;
    V(search_lock);
-   return ok;
 }
 
-
 /*
  * Search for a device suitable for this job.
  */
@@ -527,7 +492,7 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
             ok = true;
             break;
          } else if (stat == 0) {      /* device busy */
-            Dmsg1(100, "Suitable busy device found=%s\n", device_name);
+            Dmsg1(100, "Suitable device found=%s, not used: busy\n", device_name);
          } else {
             /* otherwise error */
             Dmsg0(100, "No suitable device found.\n");
@@ -567,10 +532,10 @@ static int search_res_for_device(RCTX &rctx)
             }
             POOL_MEM dev_name;
             if (rctx.store->append == SD_APPEND) {
-               Dmsg2(100, "Device %s reserved=%d.\n", rctx.device_name,
+               Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
                   rctx.jcr->dcr->dev->reserved_device);
             } else {
-               Dmsg2(100, "Device %s reserved=%d.\n", rctx.device_name,
+               Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
                   rctx.jcr->read_dcr->dev->reserved_device);
             }
             pm_strcpy(dev_name, rctx.device->hdr.name);
@@ -617,6 +582,8 @@ static int reserve_device(RCTX &rctx)
    const int name_len = MAX_NAME_LENGTH;
 
    /* Make sure MediaType is OK */
+   Dmsg2(100, "MediaType device=%s request=%s\n",
+         rctx.device->media_type, rctx.store->media_type);
    if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
       return -1;
    }
@@ -724,6 +691,10 @@ static bool reserve_device_for_read(DCR *dcr)
    dev->clear_append();
    dev->set_read();
    ok = true;
+   dev->reserved_device++;
+   Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
+      dev->print_name(), dev);
+   dcr->reserved_device = true;
 
 bail_out:
    V(dev->mutex);
diff --git a/bacula/src/stored/reserve.h b/bacula/src/stored/reserve.h
new file mode 100644 (file)
index 0000000..78e35c8
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Definitions for reservation system.
+ *
+ *  Kern Sibbald, February MMVI
+ *
+ *  Version $Id$
+ */ 
+
+/*
+   Copyright (C) 2006 Kern Sibbald
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   version 2 as amended with additional clauses defined in the
+   file LICENSE in the main source directory.
+
+   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 
+   the file LICENSE for additional details.
+
+ */
+
+/*
+ *   Use Device command from Director
+ *   The DIR tells us what Device Name to use, the Media Type,
+ *      the Pool Name, and the Pool Type.
+ *
+ *    Ensure that the device exists and is opened, then store
+ *      the media and pool info in the JCR.  This class is used
+ *      only temporarily in this file.
+ */
+class DIRSTORE {
+public:
+   alist *device;
+   bool append;
+   char name[MAX_NAME_LENGTH];
+   char media_type[MAX_NAME_LENGTH];
+   char pool_name[MAX_NAME_LENGTH];
+   char pool_type[MAX_NAME_LENGTH];
+};
+
+/* Reserve context */
+class RCTX {
+public:
+   JCR *jcr;
+   char *device_name;
+   DIRSTORE *store;
+   DEVRES   *device;
+   DEVICE *low_use_drive;             /* Low use drive candidate */
+   int num_writers;                   /* for selecting low use drive */
+   bool try_low_use_drive;            /* see if low use drive available */
+   bool any_drive;                    /* Accept any drive if set */
+   bool PreferMountedVols;            /* Prefer volumes already mounted */
+   bool exact_match;                  /* Want exact volume */
+   bool have_volume;                  /* Have DIR suggested vol name */
+   bool suitable_device;              /* at least one device is suitable */
+   bool autochanger_only;             /* look at autochangers only */
+   char VolumeName[MAX_NAME_LENGTH];  /* Vol name suggested by DIR */
+};
index 596bbafc1493e3142f47dcb34fc190ef9806951f..eff170455ee0d65fe1e22cdfdfa4d8b5437ac7be 100644 (file)
@@ -155,7 +155,7 @@ bool status_cmd(JCR *jcr)
 
       } else {
          if (dev) {
-            bnet_fsend(user, _("Device %s is not open or does not exist.\n"), dev->print_name());
+            bnet_fsend(user, _("Device %s is not open.\n"), dev->print_name());
          } else {
             bnet_fsend(user, _("Device \"%s\" is not open or does not exist.\n"), device->hdr.name);
          }
index cc561a12dfbcd622e0bbe526640c3e868dc78453..095a9ab2f437132d2521490227c4b4fed9f2541b 100644 (file)
@@ -10,7 +10,7 @@
  *
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -228,7 +228,7 @@ int main (int argc, char *argv[])
     /*
      * Start the device allocation thread
      */
-   create_volume_list();              /* do before device_init */
+   init_volume_list();                /* do before device_init */
    if (pthread_create(&thid, NULL, device_initialization, NULL) != 0) {
       Emsg1(M_ABORT, 0, _("Unable to create thread. ERR=%s\n"), strerror(errno));
    }
index c75a523adcc80d6de3e22cd90490185b2d719114..f55aa444040f45ea44f2dcb05a5d349c72d07dc7 100644 (file)
@@ -40,6 +40,7 @@
 #include "stored_conf.h"
 #include "bsr.h"
 #include "jcr.h"
+#include "reserve.h"
 #include "protos.h"
 #ifdef HAVE_LIBZ
 #include <zlib.h>                     /* compression headers */
index f6f2e8ed3d5430965c702dda4f457489fe5a900a..99e5652fe0b4766b439e4867c6b418dcb05a1efa 100644 (file)
@@ -61,9 +61,9 @@ static RES_ITEM store_items[] = {
    {"scriptsdirectory",      store_dir,  ITEM(res_store.scripts_directory), 0, 0, 0},
    {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 10},
    {"heartbeatinterval",     store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 0},
-   {"tlsenable",             store_yesno,     ITEM(res_store.tls_enable), 1, 0, 0},
-   {"tlsrequire",            store_yesno,     ITEM(res_store.tls_require), 1, 0, 0},
-   {"tlsverifypeer",         store_yesno,     ITEM(res_store.tls_verify_peer), 1, ITEM_DEFAULT, 1},
+   {"tlsenable",             store_bit,     ITEM(res_store.tls_enable), 1, 0, 0},
+   {"tlsrequire",            store_bit,     ITEM(res_store.tls_require), 1, 0, 0},
+   {"tlsverifypeer",         store_bit,     ITEM(res_store.tls_verify_peer), 1, ITEM_DEFAULT, 1},
    {"tlscacertificatefile",  store_dir,       ITEM(res_store.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir",   store_dir,       ITEM(res_store.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate",        store_dir,       ITEM(res_store.tls_certfile), 0, 0, 0},
@@ -79,10 +79,10 @@ static RES_ITEM dir_items[] = {
    {"name",        store_name,     ITEM(res_dir.hdr.name),   0, ITEM_REQUIRED, 0},
    {"description", store_str,      ITEM(res_dir.hdr.desc),   0, 0, 0},
    {"password",    store_password, ITEM(res_dir.password),   0, ITEM_REQUIRED, 0},
-   {"monitor",     store_yesno,    ITEM(res_dir.monitor),   1, ITEM_DEFAULT, 0},
-   {"tlsenable",            store_yesno,     ITEM(res_dir.tls_enable), 1, 0, 0},
-   {"tlsrequire",           store_yesno,     ITEM(res_dir.tls_require), 1, 0, 0},
-   {"tlsverifypeer",        store_yesno,     ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
+   {"monitor",     store_bit,    ITEM(res_dir.monitor),   1, ITEM_DEFAULT, 0},
+   {"tlsenable",            store_bit,     ITEM(res_dir.tls_enable), 1, 0, 0},
+   {"tlsrequire",           store_bit,     ITEM(res_dir.tls_require), 1, 0, 0},
+   {"tlsverifypeer",        store_bit,     ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
    {"tlscacertificatefile", store_dir,       ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir",  store_dir,       ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate",       store_dir,       ITEM(res_dir.tls_certfile), 0, 0, 0},
@@ -99,28 +99,28 @@ static RES_ITEM dev_items[] = {
    {"mediatype",             store_strname,ITEM(res_dev.media_type),      0, ITEM_REQUIRED, 0},
    {"devicetype",            store_devtype,ITEM(res_dev.dev_type), 0, 0, 0},
    {"archivedevice",         store_strname,ITEM(res_dev.device_name),     0, ITEM_REQUIRED, 0},
-   {"hardwareendoffile",     store_yesno,  ITEM(res_dev.cap_bits), CAP_EOF,  ITEM_DEFAULT, 1},
-   {"hardwareendofmedium",   store_yesno,  ITEM(res_dev.cap_bits), CAP_EOM,  ITEM_DEFAULT, 1},
-   {"backwardspacerecord",   store_yesno,  ITEM(res_dev.cap_bits), CAP_BSR,  ITEM_DEFAULT, 1},
-   {"backwardspacefile",     store_yesno,  ITEM(res_dev.cap_bits), CAP_BSF,  ITEM_DEFAULT, 1},
-   {"bsfateom",              store_yesno,  ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0},
-   {"twoeof",                store_yesno,  ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0},
-   {"forwardspacerecord",    store_yesno,  ITEM(res_dev.cap_bits), CAP_FSR,  ITEM_DEFAULT, 1},
-   {"forwardspacefile",      store_yesno,  ITEM(res_dev.cap_bits), CAP_FSF,  ITEM_DEFAULT, 1},
-   {"fastforwardspacefile",  store_yesno,  ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1},
-   {"removablemedia",        store_yesno,  ITEM(res_dev.cap_bits), CAP_REM,  ITEM_DEFAULT, 1},
-   {"randomaccess",          store_yesno,  ITEM(res_dev.cap_bits), CAP_RACCESS, 0, 0},
-   {"automaticmount",        store_yesno,  ITEM(res_dev.cap_bits), CAP_AUTOMOUNT,  ITEM_DEFAULT, 0},
-   {"labelmedia",            store_yesno,  ITEM(res_dev.cap_bits), CAP_LABEL,      ITEM_DEFAULT, 0},
-   {"alwaysopen",            store_yesno,  ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
-   {"autochanger",           store_yesno,  ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
-   {"closeonpoll",           store_yesno,  ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
-   {"blockpositioning",      store_yesno,  ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
-   {"usemtiocget",           store_yesno,  ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
-   {"checklabels",           store_yesno,  ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
-   {"requiresmount",         store_yesno,  ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
-   {"offlineonunmount",      store_yesno,  ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
-   {"autoselect",            store_yesno,  ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1},
+   {"hardwareendoffile",     store_bit,  ITEM(res_dev.cap_bits), CAP_EOF,  ITEM_DEFAULT, 1},
+   {"hardwareendofmedium",   store_bit,  ITEM(res_dev.cap_bits), CAP_EOM,  ITEM_DEFAULT, 1},
+   {"backwardspacerecord",   store_bit,  ITEM(res_dev.cap_bits), CAP_BSR,  ITEM_DEFAULT, 1},
+   {"backwardspacefile",     store_bit,  ITEM(res_dev.cap_bits), CAP_BSF,  ITEM_DEFAULT, 1},
+   {"bsfateom",              store_bit,  ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0},
+   {"twoeof",                store_bit,  ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0},
+   {"forwardspacerecord",    store_bit,  ITEM(res_dev.cap_bits), CAP_FSR,  ITEM_DEFAULT, 1},
+   {"forwardspacefile",      store_bit,  ITEM(res_dev.cap_bits), CAP_FSF,  ITEM_DEFAULT, 1},
+   {"fastforwardspacefile",  store_bit,  ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1},
+   {"removablemedia",        store_bit,  ITEM(res_dev.cap_bits), CAP_REM,  ITEM_DEFAULT, 1},
+   {"randomaccess",          store_bit,  ITEM(res_dev.cap_bits), CAP_RACCESS, 0, 0},
+   {"automaticmount",        store_bit,  ITEM(res_dev.cap_bits), CAP_AUTOMOUNT,  ITEM_DEFAULT, 0},
+   {"labelmedia",            store_bit,  ITEM(res_dev.cap_bits), CAP_LABEL,      ITEM_DEFAULT, 0},
+   {"alwaysopen",            store_bit,  ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
+   {"autochanger",           store_bit,  ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
+   {"closeonpoll",           store_bit,  ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
+   {"blockpositioning",      store_bit,  ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
+   {"usemtiocget",           store_bit,  ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
+   {"checklabels",           store_bit,  ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
+   {"requiresmount",         store_bit,  ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
+   {"offlineonunmount",      store_bit,  ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
+   {"autoselect",            store_bit,  ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1},
    {"changerdevice",         store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
    {"changercommand",        store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
    {"alertcommand",          store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
@@ -160,7 +160,7 @@ static RES_ITEM changer_items[] = {
 };
 
 
-// {"mountanonymousvolumes", store_yesno,  ITEM(res_dev.cap_bits), CAP_ANONVOLS,   ITEM_DEFAULT, 0},
+// {"mountanonymousvolumes", store_bit,  ITEM(res_dev.cap_bits), CAP_ANONVOLS,   ITEM_DEFAULT, 0},
 
 
 /* Message resource */
index 0e39ba5c6025620b99793b2b5a596dad46bfa2c7..85555618182e13fad3af5e392d77e8f44a1132ef 100644 (file)
@@ -9,7 +9,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -190,7 +190,7 @@ bool wait_for_device(JCR *jcr, bool first)
    struct timespec timeout;
    int stat = 0;
    bool ok = true;
-   const int wait_time = 10 * 60;       /* wait 10 minutes */
+   const int wait_time = 5 * 60;       /* wait 5 minutes */
 
    Dmsg0(100, "Enter wait_for_device\n");
    P(device_release_mutex);
index 7614c2052a4eba451cc828f8de8372742dc87809..18cfdf04f47a544384d3b6321ca8c7ba37ce89c6 100644 (file)
@@ -8,14 +8,14 @@
 *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
 *
 *   2. The generic config  scanner in lib/parse_config.c and
-*      lib/parse_config.h.
-*      These files contain the parser code, some utility
-*      routines, and the common store routines (name, int,
-*      string).
+*       lib/parse_config.h.
+*       These files contain the parser code, some utility
+*       routines, and the common store routines (name, int,
+*       string).
 *
 *   3. The daemon specific file, which contains the Resource
-*      definitions as well as any specific store routines
-*      for the resource records.
+*       definitions as well as any specific store routines
+*       for the resource records.
 *
 *     Nicolas Boichat, August MMIV
 *
@@ -69,12 +69,12 @@ int  res_all_size = sizeof(res_all);
 /*
 *    Monitor Resource
 *
-*   name          handler     value                 code flags    default_value
+*   name           handler     value                 code flags    default_value
 */
 static RES_ITEM mon_items[] = {
    {"name",        store_name,     ITEM(res_monitor.hdr.name), 0, ITEM_REQUIRED, 0},
    {"description", store_str,      ITEM(res_monitor.hdr.desc), 0, 0, 0},
-   {"requiressl",  store_yesno,    ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0},
+   {"requiressl",  store_bit,    ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0},
    {"password",    store_password, ITEM(res_monitor.password), 0, ITEM_REQUIRED, 0},
    {"refreshinterval",  store_time,ITEM(res_monitor.RefreshInterval),  0, ITEM_DEFAULT, 5},
    {"fdconnecttimeout", store_time,ITEM(res_monitor.FDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
@@ -88,14 +88,14 @@ static RES_ITEM dir_items[] = {
    {"description", store_str,      ITEM(res_dir.hdr.desc), 0, 0, 0},
    {"dirport",     store_int,      ITEM(res_dir.DIRport),  0, ITEM_DEFAULT, 9101},
    {"address",     store_str,      ITEM(res_dir.address),  0, 0, 0},
-   {"enablessl",   store_yesno,    ITEM(res_dir.enable_ssl), 1, ITEM_DEFAULT, 0},
+   {"enablessl",   store_bit,    ITEM(res_dir.enable_ssl), 1, ITEM_DEFAULT, 0},
    {NULL, NULL, NULL, 0, 0, 0}
 };
 
 /*
 *    Client or File daemon resource
 *
-*   name          handler     value                 code flags    default_value
+*   name           handler     value                 code flags    default_value
 */
 
 static RES_ITEM cli_items[] = {
@@ -104,13 +104,13 @@ static RES_ITEM cli_items[] = {
    {"address",  store_str,        ITEM(res_client.address),  0, ITEM_REQUIRED, 0},
    {"fdport",   store_pint,       ITEM(res_client.FDport),   0, ITEM_DEFAULT, 9102},
    {"password", store_password,   ITEM(res_client.password), 0, ITEM_REQUIRED, 0},
-   {"enablessl", store_yesno,     ITEM(res_client.enable_ssl), 1, ITEM_DEFAULT, 0},
+   {"enablessl", store_bit,     ITEM(res_client.enable_ssl), 1, ITEM_DEFAULT, 0},
    {NULL, NULL, NULL, 0, 0, 0}
 };
 
 /* Storage daemon resource
 *
-*   name          handler     value                 code flags    default_value
+*   name           handler     value                 code flags    default_value
 */
 static RES_ITEM store_items[] = {
    {"name",        store_name,     ITEM(res_store.hdr.name),   0, ITEM_REQUIRED, 0},
@@ -120,7 +120,7 @@ static RES_ITEM store_items[] = {
    {"sdaddress",   store_str,      ITEM(res_store.address),    0, 0, 0},
    {"password",    store_password, ITEM(res_store.password),   0, ITEM_REQUIRED, 0},
    {"sdpassword",  store_password, ITEM(res_store.password),   0, 0, 0},
-   {"enablessl",   store_yesno,    ITEM(res_store.enable_ssl),  1, ITEM_DEFAULT, 0},
+   {"enablessl",   store_bit,    ITEM(res_store.enable_ssl),  1, ITEM_DEFAULT, 0},
    {NULL, NULL, NULL, 0, 0, 0}
 };
 
@@ -131,7 +131,7 @@ static RES_ITEM store_items[] = {
 *  NOTE!!! keep it in the same order as the R_codes
 *    or eliminate all resources[rindex].name
 *
-*  name             items        rcode        res_head
+*  name      items        rcode        res_head
 */
 RES_TABLE resources[] = {
    {"monitor",      mon_items,    R_MONITOR},
@@ -152,7 +152,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       sendit(sock, _("No %s resource defined\n"), res_to_str(type));
       return;
    }
-   if (type < 0) {                   /* no recursion */
+   if (type < 0) {                    /* no recursion */
       type = - type;
       recurse = false;
    }
@@ -194,7 +194,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
 */
 void free_resource(RES *sres, int type)
 {
-   RES *nres;                        /* next resource if linked */
+   RES *nres;                         /* next resource if linked */
    URES *res = (URES *)sres;
 
    if (res == NULL)
@@ -258,14 +258,14 @@ void save_resource(int type, RES_ITEM *items, int pass)
    */
    for (i=0; items[i].name; i++) {
       if (items[i].flags & ITEM_REQUIRED) {
-        if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
-              Emsg2(M_ERROR_TERM, 0, _("%s item is required in %s resource, but not found.\n"),
-                 items[i].name, resources[rindex]);
-        }
+         if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
+               Emsg2(M_ERROR_TERM, 0, _("%s item is required in %s resource, but not found.\n"),
+                  items[i].name, resources[rindex]);
+         }
       }
       /* If this triggers, take a look at lib/parse_conf.h */
       if (i >= MAX_RES_ITEMS) {
-        Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
+         Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
       }
    }
 
@@ -282,22 +282,22 @@ void save_resource(int type, RES_ITEM *items, int pass)
       case R_CLIENT:
       case R_STORAGE:
       case R_DIRECTOR:
-        break;
+         break;
       default:
-        Emsg1(M_ERROR, 0, _("Unknown resource type %d in save_resource.\n"), type);
-        error = 1;
-        break;
+         Emsg1(M_ERROR, 0, _("Unknown resource type %d in save_resource.\n"), type);
+         error = 1;
+         break;
       }
       /* Note, the resource name was already saved during pass 1,
       * so here, we can just release it.
       */
       if (res_all.res_monitor.hdr.name) {
-        free(res_all.res_monitor.hdr.name);
-        res_all.res_monitor.hdr.name = NULL;
+         free(res_all.res_monitor.hdr.name);
+         res_all.res_monitor.hdr.name = NULL;
       }
       if (res_all.res_monitor.hdr.desc) {
-        free(res_all.res_monitor.hdr.desc);
-        res_all.res_monitor.hdr.desc = NULL;
+         free(res_all.res_monitor.hdr.desc);
+         res_all.res_monitor.hdr.desc = NULL;
       }
       return;
    }
@@ -330,21 +330,21 @@ void save_resource(int type, RES_ITEM *items, int pass)
       memcpy(res, &res_all, size);
       if (!res_head[rindex]) {
    res_head[rindex] = (RES *)res; /* store first entry */
-        Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
-        res->res_monitor.hdr.name, rindex);
+         Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
+         res->res_monitor.hdr.name, rindex);
       } else {
    RES *next;
    /* Add new res to end of chain */
    for (next=res_head[rindex]; next->next; next=next->next) {
       if (strcmp(next->name, res->res_monitor.hdr.name) == 0) {
-        Emsg2(M_ERROR_TERM, 0,
-                 _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
-        resources[rindex].name, res->res_monitor.hdr.name);
+         Emsg2(M_ERROR_TERM, 0,
+                  _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
+         resources[rindex].name, res->res_monitor.hdr.name);
       }
    }
    next->next = (RES *)res;
-        Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
-        res->res_monitor.hdr.name, rindex, pass);
+         Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
+         res->res_monitor.hdr.name, rindex, pass);
       }
    }
 }
index 0bc3be13e78baf5ecd3b1b58335ae551f964411a..1b91bd96f789d35d4043a2dba892eacdbdfef927 100644 (file)
@@ -4,8 +4,8 @@
 
 #undef  VERSION
 #define VERSION "1.39.5"
-#define BDATE   "06 February 2006"
-#define LSMDATE "06Feb06"
+#define BDATE   "14 February 2006"
+#define LSMDATE "14Feb06"
 
 /* Debug flags */
 #undef  DEBUG
index c13abcac29e18502686ddf3a481689dd393a1a64..b6c05f7151c080624a8eb50cb8942f4de59df569 100644 (file)
@@ -81,8 +81,8 @@ static RES_ITEM cons_items[] = {
    {"rcfile",      store_dir,      ITEM(res_cons.rc_file), 0, 0, 0},
    {"historyfile", store_dir,      ITEM(res_cons.hist_file), 0, 0, 0},
    {"password",    store_password, ITEM(res_cons.password), 0, ITEM_REQUIRED, 0},
-   {"tlsenable",      store_yesno,     ITEM(res_cons.tls_enable), 1, 0, 0},
-   {"tlsrequire",     store_yesno,     ITEM(res_cons.tls_require), 1, 0, 0},
+   {"tlsenable",      store_bit,     ITEM(res_cons.tls_enable), 1, 0, 0},
+   {"tlsrequire",     store_bit,     ITEM(res_cons.tls_require), 1, 0, 0},
    {"tlscacertificatefile", store_dir, ITEM(res_cons.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir", store_dir,  ITEM(res_cons.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate", store_dir,       ITEM(res_cons.tls_certfile), 0, 0, 0},
@@ -98,8 +98,8 @@ static RES_ITEM dir_items[] = {
    {"dirport",     store_int,      ITEM(res_dir.DIRport),  0, ITEM_DEFAULT, 9101},
    {"address",     store_str,      ITEM(res_dir.address),  0, 0, 0},
    {"password",    store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
-   {"tlsenable",      store_yesno,     ITEM(res_dir.tls_enable), 1, 0, 0},
-   {"tlsrequire",     store_yesno,     ITEM(res_dir.tls_require), 1, 0, 0},
+   {"tlsenable",      store_bit,     ITEM(res_dir.tls_enable), 1, 0, 0},
+   {"tlsrequire",     store_bit,     ITEM(res_dir.tls_require), 1, 0, 0},
    {"tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
    {"tlscacertificatedir", store_dir,  ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
    {"tlscertificate", store_dir,       ITEM(res_dir.tls_certfile), 0, 0, 0},