From d63d9c8839f6520ce4abb18cca73cb6ea5fd17a5 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 13 Jun 2005 10:14:01 +0000 Subject: [PATCH] - Make default mandir /usr/share/man - Install Bacula man page. - Implement passing of FileSet Enable VSS to FD. - Move main body of reserve drive code into subroutine so that it can be called multiple times. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2122 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/autoconf/Make.common.in | 4 +- bacula/autoconf/configure.in | 16 +- bacula/configure | 57 ++- bacula/kernstodo | 15 +- bacula/kes-1.37 | 9 + bacula/scripts/Makefile.in | 6 + bacula/src/cats/make_catalog_backup.in | 2 +- bacula/src/console/console.c | 7 +- bacula/src/dird/dird_conf.c | 1 + bacula/src/dird/dird_conf.h | 6 +- bacula/src/dird/fd_cmds.c | 19 +- bacula/src/dird/inc_conf.c | 228 ++++++----- bacula/src/dird/job.c | 6 - bacula/src/filed/job.c | 520 +++++++++++++------------ bacula/src/jcr.h | 1 + bacula/src/lib/htable.c | 55 ++- bacula/src/lib/htable.h | 16 +- bacula/src/stored/reserve.c | 121 +++--- bacula/src/version.h | 4 +- 19 files changed, 583 insertions(+), 510 deletions(-) diff --git a/bacula/autoconf/Make.common.in b/bacula/autoconf/Make.common.in index d8444df146..cb078251b6 100644 --- a/bacula/autoconf/Make.common.in +++ b/bacula/autoconf/Make.common.in @@ -23,8 +23,8 @@ manprefix = sbindir = @sbindir@ sysconfdir = @sysconfdir@ scriptdir = @scriptdir@ -mandir = @mandir@/man1 -manext = 1 +mandir = @mandir@/man8 +manext = 8 # Tools & program stuff CC = @CC@ diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index e41aa4e904..2a7b01e454 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -40,10 +40,13 @@ AC_PROG_CXX AC_PROG_CC_C_O dnl Determine if C compiler support -c -o. AC_PROG_GCC_TRADITIONAL dnl Determine if ioctl() need -traditional. -if test "x$CC" = xgcc -then +if test "x$CC" = xgcc; then AC_DEFINE(HAVE_GCC) fi +AC_PATH_PROG(CXX, $CXX, $CXX) +if test ! -e $CXX; then + AC_MSG_ERROR(Unable to find C++ compiler) +fi dnl ------------------------------------------------------- dnl# Check for programs. @@ -145,6 +148,14 @@ if test x$sbindir = x'${exec_prefix}/sbin' ; then sbindir=${exec_prefix}/sbin fi sbindir=`eval echo ${sbindir}` + +# ------------------------------------------------------------------------- +# If the user has not set --mandir, we default to /usr/share/man +# ------------------------------------------------------------------------- +if test x$mandir = x'${prefix}/man' ; then + mandir=/usr/share/man +fi + # ------------------------------------------------------------------ # All list of languages for which a translation exist. Each @@ -2051,6 +2062,7 @@ Configuration on `date`: Working directory: ${working_dir} PID directory: ${piddir} Subsys directory: ${subsysdir} + Man directory: ${mandir} C Compiler: ${CC} ${CCVERSION} C++ Compiler: ${CXX} ${CXXVERSION} Compiler flags: ${WCFLAGS} ${CFLAGS} diff --git a/bacula/configure b/bacula/configure index e2ece8e935..a351ee5f29 100755 --- a/bacula/configure +++ b/bacula/configure @@ -3204,13 +3204,57 @@ echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6 fi fi -if test "x$CC" = xgcc -then +if test "x$CC" = xgcc; then cat >>confdefs.h <<\_ACEOF #define HAVE_GCC 1 _ACEOF fi +# Extract the first word of "$CXX", so it can be a program name with args. +set dummy $CXX; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_CXX="$CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_CXX" && ac_cv_path_CXX="$CXX" + ;; +esac +fi +CXX=$ac_cv_path_CXX + +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test ! -e $CXX; then + { { echo "$as_me:$LINENO: error: Unable to find C++ compiler" >&5 +echo "$as_me: error: Unable to find C++ compiler" >&2;} + { (exit 1); exit 1; }; } +fi # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -4717,6 +4761,14 @@ if test x$sbindir = x'${exec_prefix}/sbin' ; then fi sbindir=`eval echo ${sbindir}` +# ------------------------------------------------------------------------- +# If the user has not set --mandir, we default to /usr/share/man +# ------------------------------------------------------------------------- +if test x$mandir = x'${prefix}/man' ; then + mandir=/usr/share/man +fi + + # ------------------------------------------------------------------ # All list of languages for which a translation exist. Each # language is separated by a space. @@ -23143,6 +23195,7 @@ Configuration on `date`: Working directory: ${working_dir} PID directory: ${piddir} Subsys directory: ${subsysdir} + Man directory: ${mandir} C Compiler: ${CC} ${CCVERSION} C++ Compiler: ${CXX} ${CXXVERSION} Compiler flags: ${WCFLAGS} ${CFLAGS} diff --git a/bacula/kernstodo b/bacula/kernstodo index 432033c103..ab8881e22b 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,12 +1,12 @@ Kern's ToDo List - 27 May 2005 + 12 June 2005 Major development: Project Developer ======= ========= TLS Landon Fuller Unicode in Win32 Thorsten Engel (done) -VSS Thorsten Engel (being implemented) +VSS Thorsten Engel (in beta testing) Version 1.37 Kern (see below) ======================================================== @@ -21,9 +21,6 @@ Version 1.37 Kern (see below) ## Create a new GUI chapter explaining all the GUI programs. Autochangers: -- 3. Prevent two drives requesting the same Volume in any given - autochanger, by checking if a Volume is mounted on another drive - in an Autochanger. - 7. Implement new Console commands to allow offlining/reserving drives, and possibly manipulating the autochanger (much asked for). - Make "update slots" when pointing to Autochanger, remove @@ -53,6 +50,7 @@ Document: - Document that ChangerDevice is used for Alert command. - Document new CDROM directory. - Document Heartbeat Interval in the dealing with firewalls section. +- Document the multiple-drive-changer.txt script. For 1.37: - Implement "PreferMountedVolumes = yes|no" in Job resource. @@ -66,8 +64,6 @@ For 1.37: - Implement Files/Bytes,... stats for restore job. - Implement Total Bytes Written, ... for restore job. - Add setting Volume State via Python. -- Upgrade to MySQL 4.1.1 See: - http://dev.mysql.com/doc/mysql/en/Server_SQL_mode.html - Max Vols limit in Pool off by one? - Make bootstrap file handle multiple MediaTypes (SD) - Test restoring into a user restricted directory on Win32 -- see @@ -1286,3 +1282,8 @@ Block Position: 0 - Implement Maximum Job Spool Size - Fix 3993 error in SD. It forgets to look at autochanger resource for device command, ... +- 3. Prevent two drives requesting the same Volume in any given + autochanger, by checking if a Volume is mounted on another drive + in an Autochanger. +- Upgrade to MySQL 4.1.12 See: + http://dev.mysql.com/doc/mysql/en/Server_SQL_mode.html diff --git a/bacula/kes-1.37 b/bacula/kes-1.37 index 47c327953c..72df675cb8 100644 --- a/bacula/kes-1.37 +++ b/bacula/kes-1.37 @@ -4,6 +4,15 @@ General: Changes to 1.37.22: +13Jun05 +- Make default mandir /usr/share/man +- Install Bacula man page. +- Implement passing of FileSet Enable VSS to FD. +- Move main body of reserve drive code into subroutine + so that it can be called multiple times. +12Jun05 +- Eliminate getpass() for Win32 builds in console as the + function does not exist. 10Jun05 - Correct some reservation problems in SD when no devices are available. diff --git a/bacula/scripts/Makefile.in b/bacula/scripts/Makefile.in index c08fc344b3..0f6fcafa2a 100755 --- a/bacula/scripts/Makefile.in +++ b/bacula/scripts/Makefile.in @@ -30,6 +30,7 @@ installdirs: $(MKDIR) $(DESTDIR)$(sysconfdir) $(MKDIR) $(DESTDIR)$(sbindir) $(MKDIR) $(DESTDIR)$(scriptdir) + $(MKDIR) $(DESTDIR)$(mandir) install: installdirs $(INSTALL_SCRIPT) startmysql $(DESTDIR)$(scriptdir)/startmysql @@ -55,6 +56,10 @@ install: installdirs $(INSTALL_DATA) btraceback.gdb $(DESTDIR)$(scriptdir)/btraceback.gdb $(INSTALL_DATA) btraceback.dbx $(DESTDIR)$(scriptdir)/btraceback.dbx $(INSTALL_SCRIPT) btraceback $(DESTDIR)$(sbindir)/btraceback + gzip bacula.8.gz + $(INSTALL_DATA) bacula.8.gz $(DESTDIR)$(mandir)/bacula.8.gz + @rm -f bacula.8.gz + uninstall: (cd $(DESTDIR)$(scriptdir); $(RMF) startmysql) @@ -69,6 +74,7 @@ uninstall: (cd $(DESTDIR)$(scriptdir); $(RMF) btraceback.gdb) (cd $(DESTDIR)$(scriptdir); $(RMF) btraceback.dbx) (cd $(DESTDIR)$(sbindir); $(RMF) btraceback) + (cd $(DESTDIR)$(mandir); $(RMF) bacula.8.gz) Makefile: Makefile.in cd $(topdir) \ diff --git a/bacula/src/cats/make_catalog_backup.in b/bacula/src/cats/make_catalog_backup.in index 05295ed0ca..b4d2fbdd28 100755 --- a/bacula/src/cats/make_catalog_backup.in +++ b/bacula/src/cats/make_catalog_backup.in @@ -24,7 +24,7 @@ fi # To read back a MySQL database use: # cd @working_dir@ # rm -f @SQL_BINDIR@/../var/bacula/* -# mysql file_bsock; if (jcr->fileset->new_include) { - bnet_fsend(fd, fileset); + bnet_fsend(fd, filesetcmd, jcr->fileset->enable_vss ? " vss=1" : ""); return send_fileset(jcr); } return true; diff --git a/bacula/src/dird/inc_conf.c b/bacula/src/dird/inc_conf.c index 9fa2428917..f6ef20d115 100644 --- a/bacula/src/dird/inc_conf.c +++ b/bacula/src/dird/inc_conf.c @@ -1,6 +1,6 @@ /* * Configuration file parser for new and old Include and - * Exclude records + * Exclude records * * Kern Sibbald, March MMIII * @@ -10,19 +10,14 @@ Copyright (C) 2003-2005 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 ammended 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. */ @@ -62,7 +57,7 @@ static INCEXE res_incexe; /* * new Include/Exclude items - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM newinc_items[] = { {"file", store_fname, NULL, 0, 0, 0}, @@ -105,7 +100,6 @@ static RES_ITEM options_items[] = { /* Define FileSet KeyWord values */ - enum { INC_KW_NONE, INC_KW_COMPRESSION, @@ -116,8 +110,8 @@ enum { INC_KW_RECURSE, INC_KW_SPARSE, INC_KW_HARDLINK, - INC_KW_REPLACE, /* restore options */ - INC_KW_READFIFO, /* Causes fifo data to be read */ + INC_KW_REPLACE, /* restore options */ + INC_KW_READFIFO, /* Causes fifo data to be read */ INC_KW_PORTABLE, INC_KW_MTIMEONLY, INC_KW_KEEPATIME, @@ -151,7 +145,7 @@ static struct s_kw FS_option_kw[] = { {"aclsupport", INC_KW_ACL}, {"ignorecase", INC_KW_IGNORECASE}, {"hfsplussupport", INC_KW_HFSPLUS}, - {NULL, 0} + {NULL, 0} }; /* Options for FileSet keywords */ @@ -210,7 +204,7 @@ static struct s_fs_opt FS_options[] = { {"no", INC_KW_IGNORECASE, "0"}, {"yes", INC_KW_HFSPLUS, "R"}, /* "R" for resource fork */ {"no", INC_KW_HFSPLUS, "0"}, - {NULL, 0, 0} + {NULL, 0, 0} }; @@ -227,10 +221,10 @@ static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen) char option[3]; int lcopts = lc->options; - option[0] = 0; /* default option = none */ - option[2] = 0; /* terminate options */ - lc->options |= LOPT_STRING; /* force string */ - token = lex_get_token(lc, T_STRING); /* expect at least one option */ + option[0] = 0; /* default option = none */ + option[2] = 0; /* terminate options */ + lc->options |= LOPT_STRING; /* force string */ + token = lex_get_token(lc, T_STRING); /* expect at least one option */ if (keyword == INC_KW_VERIFY) { /* special case */ /* ***FIXME**** ensure these are in permitted set */ bstrncat(opts, "V", optlen); /* indicate Verify */ @@ -243,18 +237,18 @@ static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen) */ } else { for (i=0; FS_options[i].name; i++) { - if (strcasecmp(lc->str, FS_options[i].name) == 0 && FS_options[i].keyword == keyword) { - /* NOTE! maximum 2 letters here or increase option[3] */ - option[0] = FS_options[i].option[0]; - option[1] = FS_options[i].option[1]; - i = 0; - break; - } + if (strcasecmp(lc->str, FS_options[i].name) == 0 && FS_options[i].keyword == keyword) { + /* NOTE! maximum 2 letters here or increase option[3] */ + option[0] = FS_options[i].option[0]; + option[1] = FS_options[i].option[1]; + i = 0; + break; + } } if (i != 0) { scan_err1(lc, "Expected a FileSet option keyword, got:%s:", lc->str); } else { /* add option */ - bstrncat(opts, option, optlen); + bstrncat(opts, option, optlen); Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen); } } @@ -310,25 +304,25 @@ static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass) res_all.res_fs.new_include = true; while ((token = lex_get_token(lc, T_SKIP_EOL)) != T_EOF) { if (token == T_EOB) { - break; + break; } if (token != T_IDENTIFIER) { scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str); } for (i=0; newinc_items[i].name; i++) { options = strcasecmp(lc->str, "options") == 0; - if (strcasecmp(newinc_items[i].name, lc->str) == 0) { - if (!options) { - token = lex_get_token(lc, T_SKIP_EOL); - if (token != T_EQUALS) { + if (strcasecmp(newinc_items[i].name, lc->str) == 0) { + if (!options) { + token = lex_get_token(lc, T_SKIP_EOL); + if (token != T_EQUALS) { scan_err1(lc, "expected an equals, got: %s", lc->str); - } - } - /* Call item handler */ - newinc_items[i].handler(lc, &newinc_items[i], i, pass); - i = -1; - break; - } + } + } + /* Call item handler */ + newinc_items[i].handler(lc, &newinc_items[i], i, pass); + i = -1; + break; + } } if (i >=0) { scan_err1(lc, "Keyword %s not permitted in this resource", lc->str); @@ -339,22 +333,22 @@ static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass) memcpy(incexe, &res_incexe, sizeof(INCEXE)); memset(&res_incexe, 0, sizeof(INCEXE)); if (item->code == 0) { /* include */ - if (res_all.res_fs.num_includes == 0) { - res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *)); - } else { - res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items, - sizeof(INCEXE *) * (res_all.res_fs.num_includes + 1)); - } - res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe; + if (res_all.res_fs.num_includes == 0) { + res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *)); + } else { + res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items, + sizeof(INCEXE *) * (res_all.res_fs.num_includes + 1)); + } + res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe; Dmsg1(900, "num_includes=%d\n", res_all.res_fs.num_includes); - } else { /* exclude */ - if (res_all.res_fs.num_excludes == 0) { - res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *)); - } else { - res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items, - sizeof(INCEXE *) * (res_all.res_fs.num_excludes + 1)); - } - res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe; + } else { /* exclude */ + if (res_all.res_fs.num_excludes == 0) { + res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *)); + } else { + res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items, + sizeof(INCEXE *) * (res_all.res_fs.num_excludes + 1)); + } + res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe; Dmsg1(900, "num_excludes=%d\n", res_all.res_fs.num_excludes); } } @@ -380,30 +374,30 @@ static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass) case T_IDENTIFIER: case T_UNQUOTED_STRING: case T_QUOTED_STRING: - rc = regcomp(&preg, lc->str, REG_EXTENDED); - if (rc != 0) { - regerror(rc, &preg, prbuf, sizeof(prbuf)); - regfree(&preg); + rc = regcomp(&preg, lc->str, REG_EXTENDED); + if (rc != 0) { + regerror(rc, &preg, prbuf, sizeof(prbuf)); + regfree(&preg); scan_err1(lc, _("Regex compile error. ERR=%s\n"), prbuf); - break; - } - regfree(&preg); - if (item->code == 1) { + break; + } + regfree(&preg); + if (item->code == 1) { type = "regexdir"; - res_incexe.current_opts->regexdir.append(bstrdup(lc->str)); - newsize = res_incexe.current_opts->regexdir.size(); - } else if (item->code == 2) { + res_incexe.current_opts->regexdir.append(bstrdup(lc->str)); + newsize = res_incexe.current_opts->regexdir.size(); + } else if (item->code == 2) { type = "regexfile"; - res_incexe.current_opts->regexfile.append(bstrdup(lc->str)); - newsize = res_incexe.current_opts->regexfile.size(); - } else { + res_incexe.current_opts->regexfile.append(bstrdup(lc->str)); + newsize = res_incexe.current_opts->regexfile.size(); + } else { type = "regex"; - res_incexe.current_opts->regex.append(bstrdup(lc->str)); - newsize = res_incexe.current_opts->regex.size(); - } + res_incexe.current_opts->regex.append(bstrdup(lc->str)); + newsize = res_incexe.current_opts->regex.size(); + } Dmsg4(900, "set %s %p size=%d %s\n", - type, res_incexe.current_opts, newsize, lc->str); - break; + type, res_incexe.current_opts, newsize, lc->str); + break; default: scan_err1(lc, _("Expected a regex string, got: %s\n"), lc->str); } @@ -474,22 +468,22 @@ static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass) case T_IDENTIFIER: case T_UNQUOTED_STRING: case T_QUOTED_STRING: - if (item->code == 1) { + if (item->code == 1) { type = "wilddir"; - res_incexe.current_opts->wilddir.append(bstrdup(lc->str)); - newsize = res_incexe.current_opts->wilddir.size(); - } else if (item->code == 2) { + res_incexe.current_opts->wilddir.append(bstrdup(lc->str)); + newsize = res_incexe.current_opts->wilddir.size(); + } else if (item->code == 2) { type = "wildfile"; - res_incexe.current_opts->wildfile.append(bstrdup(lc->str)); - newsize = res_incexe.current_opts->wildfile.size(); - } else { + res_incexe.current_opts->wildfile.append(bstrdup(lc->str)); + newsize = res_incexe.current_opts->wildfile.size(); + } else { type = "wild"; - res_incexe.current_opts->wild.append(bstrdup(lc->str)); - newsize = res_incexe.current_opts->wild.size(); - } + res_incexe.current_opts->wild.append(bstrdup(lc->str)); + newsize = res_incexe.current_opts->wild.size(); + } Dmsg4(9, "set %s %p size=%d %s\n", - type, res_incexe.current_opts, newsize, lc->str); - break; + type, res_incexe.current_opts, newsize, lc->str); + break; default: scan_err1(lc, _("Expected a wild-card string, got: %s\n"), lc->str); } @@ -509,10 +503,10 @@ static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass) case T_IDENTIFIER: case T_UNQUOTED_STRING: case T_QUOTED_STRING: - res_incexe.current_opts->fstype.append(bstrdup(lc->str)); + res_incexe.current_opts->fstype.append(bstrdup(lc->str)); Dmsg3(900, "set fstype %p size=%d %s\n", - res_incexe.current_opts, res_incexe.current_opts->fstype.size(), lc->str); - break; + res_incexe.current_opts, res_incexe.current_opts->fstype.size(), lc->str); + break; default: scan_err1(lc, _("Expected an fstype string, got: %s\n"), lc->str); } @@ -535,20 +529,20 @@ static void store_fname(LEX *lc, RES_ITEM *item, int index, int pass) /* Pickup Filename string */ switch (token) { - case T_IDENTIFIER: - case T_UNQUOTED_STRING: - case T_QUOTED_STRING: - if (res_all.res_fs.have_MD5) { - MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len); - } - incexe = &res_incexe; - if (incexe->name_list.size() == 0) { - incexe->name_list.init(10, true); - } - incexe->name_list.append(bstrdup(lc->str)); + case T_IDENTIFIER: + case T_UNQUOTED_STRING: + case T_QUOTED_STRING: + if (res_all.res_fs.have_MD5) { + MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len); + } + incexe = &res_incexe; + if (incexe->name_list.size() == 0) { + incexe->name_list.init(10, true); + } + incexe->name_list.append(bstrdup(lc->str)); Dmsg1(900, "Add to name_list %s\n", lc->str); - break; - default: + break; + default: scan_err1(lc, _("Expected a filename, got: %s"), lc->str); } } @@ -574,25 +568,25 @@ static void options_res(LEX *lc, RES_ITEM *item, int index, int pass) while ((token = lex_get_token(lc, T_ALL)) != T_EOF) { if (token == T_EOL) { - continue; + continue; } if (token == T_EOB) { - break; + break; } if (token != T_IDENTIFIER) { scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str); } for (i=0; options_items[i].name; i++) { - if (strcasecmp(options_items[i].name, lc->str) == 0) { - token = lex_get_token(lc, T_SKIP_EOL); - if (token != T_EQUALS) { + if (strcasecmp(options_items[i].name, lc->str) == 0) { + token = lex_get_token(lc, T_SKIP_EOL); + if (token != T_EQUALS) { scan_err1(lc, "expected an equals, got: %s", lc->str); - } - /* Call item handler */ - options_items[i].handler(lc, &options_items[i], i, pass); - i = -1; - break; - } + } + /* Call item handler */ + options_items[i].handler(lc, &options_items[i], i, pass); + i = -1; + break; + } } if (i >=0) { scan_err1(lc, "Keyword %s not permitted in this resource", lc->str); @@ -615,8 +609,8 @@ static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass) /* Look up the keyword */ for (i=0; FS_option_kw[i].name; i++) { if (strcasecmp(item->name, FS_option_kw[i].name) == 0) { - keyword = FS_option_kw[i].token; - break; + keyword = FS_option_kw[i].token; + break; } } if (keyword == INC_KW_NONE) { @@ -651,7 +645,7 @@ static void setup_current_opts(void) res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *)); } else { res_incexe.opts_list = (FOPTS **)realloc(res_incexe.opts_list, - sizeof(FOPTS *) * (res_incexe.num_opts + 1)); + sizeof(FOPTS *) * (res_incexe.num_opts + 1)); } res_incexe.opts_list[res_incexe.num_opts++] = fo; } diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 7fa9fb58e0..aca03f5d77 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -660,12 +660,6 @@ bool get_or_create_fileset_record(JCR *jcr, FILESET_DBR *fsr) } } jcr->jr.FileSetId = fsr->FileSetId; -#ifdef needed - if (fsr->created && jcr != NULL) { - Jmsg(jcr, M_INFO, 0, _("Created new FileSet record \"%s\" %s\n"), - fsr->FileSet, fsr->cCreateTime); - } -#endif Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name, jcr->jr.FileSetId); return true; diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 2698ee7193..4665fceebc 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -29,7 +29,9 @@ #endif extern char my_name[]; -extern CLIENT *me; /* our client resource */ +extern CLIENT *me; /* our client resource */ + +int enable_vss = 0; /* set to use vss */ /* Imported functions */ extern int status_cmd(JCR *jcr); @@ -88,7 +90,7 @@ static struct s_cmds cmds[] = { {"bootstrap", bootstrap_cmd, 0}, {"RunBeforeJob", runbefore_cmd, 0}, {"RunAfterJob", runafter_cmd, 0}, - {NULL, NULL} /* list terminator */ + {NULL, NULL} /* list terminator */ }; /* Commands received from director that need scanning */ @@ -181,37 +183,37 @@ void *handle_client_request(void *dirp) /* Read command */ if (bnet_recv(dir) < 0) { - break; /* connection terminated */ + break; /* connection terminated */ } dir->msg[dir->msglen] = 0; Dmsg1(100, "msg); found = false; for (i=0; cmds[i].cmd; i++) { - if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) { - found = true; /* indicate command found */ - if (!jcr->authenticated && cmds[i].func != hello_cmd) { - bnet_fsend(dir, no_auth); - bnet_sig(dir, BNET_EOD); - break; - } - if ((jcr->authenticated) && (!cmds[i].monitoraccess) && (jcr->director->monitor)) { + if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) { + found = true; /* indicate command found */ + if (!jcr->authenticated && cmds[i].func != hello_cmd) { + bnet_fsend(dir, no_auth); + bnet_sig(dir, BNET_EOD); + break; + } + if ((jcr->authenticated) && (!cmds[i].monitoraccess) && (jcr->director->monitor)) { Dmsg1(100, "Command %s illegal.\n", cmds[i].cmd); - bnet_fsend(dir, illegal_cmd); - bnet_sig(dir, BNET_EOD); - break; - } + bnet_fsend(dir, illegal_cmd); + bnet_sig(dir, BNET_EOD); + break; + } Dmsg1(100, "Executing %s command.\n", cmds[i].cmd); - if (!cmds[i].func(jcr)) { /* do command */ - quit = true; /* error or fully terminated, get out */ + if (!cmds[i].func(jcr)) { /* do command */ + quit = true; /* error or fully terminated, get out */ Dmsg1(20, "Quit command loop. Canceled=%d\n", job_canceled(jcr)); - } - break; - } + } + break; + } } - if (!found) { /* command not found */ - bnet_fsend(dir, errmsg); - quit = true; - break; + if (!found) { /* command not found */ + bnet_fsend(dir, errmsg); + quit = true; + break; } } @@ -225,7 +227,7 @@ void *handle_client_request(void *dirp) } generate_daemon_event(jcr, "JobEnd"); - dequeue_messages(jcr); /* send any queued messages */ + dequeue_messages(jcr); /* send any queued messages */ /* Inform Director that we are done */ bnet_sig(dir, BNET_TERMINATE); @@ -237,48 +239,48 @@ void *handle_client_request(void *dirp) int i, j, k; /* Delete FileSet Include lists */ for (i=0; iinclude_list.size(); i++) { - findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i); - for (j=0; jopts_list.size(); j++) { - findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); - for (k=0; kregex.size(); k++) { - regfree((regex_t *)fo->regex.get(k)); - } - fo->regex.destroy(); - fo->regexdir.destroy(); - fo->regexfile.destroy(); - fo->wild.destroy(); - fo->wilddir.destroy(); - fo->wildfile.destroy(); - fo->base.destroy(); - fo->fstype.destroy(); - if (fo->reader) { - free(fo->reader); - } - if (fo->writer) { - free(fo->writer); - } - } - incexe->opts_list.destroy(); - incexe->name_list.destroy(); + findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i); + for (j=0; jopts_list.size(); j++) { + findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); + for (k=0; kregex.size(); k++) { + regfree((regex_t *)fo->regex.get(k)); + } + fo->regex.destroy(); + fo->regexdir.destroy(); + fo->regexfile.destroy(); + fo->wild.destroy(); + fo->wilddir.destroy(); + fo->wildfile.destroy(); + fo->base.destroy(); + fo->fstype.destroy(); + if (fo->reader) { + free(fo->reader); + } + if (fo->writer) { + free(fo->writer); + } + } + incexe->opts_list.destroy(); + incexe->name_list.destroy(); } fileset->include_list.destroy(); /* Delete FileSet Exclude lists */ for (i=0; iexclude_list.size(); i++) { - findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i); - for (j=0; jopts_list.size(); j++) { - findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); - fo->regex.destroy(); - fo->regexdir.destroy(); - fo->regexfile.destroy(); - fo->wild.destroy(); - fo->wilddir.destroy(); - fo->wildfile.destroy(); - fo->base.destroy(); - fo->fstype.destroy(); - } - incexe->opts_list.destroy(); - incexe->name_list.destroy(); + findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i); + for (j=0; jopts_list.size(); j++) { + findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); + fo->regex.destroy(); + fo->regexdir.destroy(); + fo->regexfile.destroy(); + fo->wild.destroy(); + fo->wilddir.destroy(); + fo->wildfile.destroy(); + fo->base.destroy(); + fo->fstype.destroy(); + } + incexe->opts_list.destroy(); + incexe->name_list.destroy(); } fileset->exclude_list.destroy(); free(fileset); @@ -288,7 +290,7 @@ void *handle_client_request(void *dirp) term_find_files((FF_PKT *)jcr->ff); jcr->ff = NULL; Dmsg0(100, "Done with term_find_files\n"); - free_jcr(jcr); /* destroy JCR record */ + free_jcr(jcr); /* destroy JCR record */ Dmsg0(100, "Done with free_jcr\n"); return NULL; } @@ -321,20 +323,20 @@ static int cancel_cmd(JCR *jcr) if (!(cjcr=get_jcr_by_full_name(Job))) { bnet_fsend(dir, "2901 Job %s not found.\n", Job); } else { - if (cjcr->store_bsock) { - P(cjcr->mutex); - cjcr->store_bsock->timed_out = 1; - cjcr->store_bsock->terminated = 1; + if (cjcr->store_bsock) { + P(cjcr->mutex); + cjcr->store_bsock->timed_out = 1; + cjcr->store_bsock->terminated = 1; /* * #if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32) */ #if !defined(HAVE_CYGWIN) - pthread_kill(cjcr->my_thread_id, TIMEOUT_SIGNAL); + pthread_kill(cjcr->my_thread_id, TIMEOUT_SIGNAL); #endif - V(cjcr->mutex); - } - set_jcr_job_status(cjcr, JS_Canceled); - free_jcr(cjcr); + V(cjcr->mutex); + } + set_jcr_job_status(cjcr, JS_Canceled); + free_jcr(cjcr); bnet_fsend(dir, _("2001 Job %s marked to be canceled.\n"), Job); } } else { @@ -394,8 +396,8 @@ static int job_cmd(JCR *jcr) sd_auth_key = get_memory(dir->msglen); if (sscanf(dir->msg, jobcmd, &jcr->JobId, jcr->Job, - &jcr->VolSessionId, &jcr->VolSessionTime, - sd_auth_key) != 5) { + &jcr->VolSessionId, &jcr->VolSessionTime, + sd_auth_key) != 5) { pm_strcpy(jcr->errmsg, dir->msg); Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg); bnet_fsend(dir, BADjob); @@ -472,13 +474,13 @@ static bool run_cmd(JCR *jcr, char *cmd, const char *name) if (bpipe == NULL) { berrno be; Jmsg(jcr, M_FATAL, 0, _("%s could not execute. ERR=%s\n"), name, - be.strerror()); + be.strerror()); return false; } while (fgets(line, sizeof(line), bpipe->rfd)) { int len = strlen(line); if (len > 0 && line[len-1] == '\n') { - line[len-1] = 0; + line[len-1] = 0; } Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line); } @@ -486,7 +488,7 @@ static bool run_cmd(JCR *jcr, char *cmd, const char *name) if (status != 0) { berrno be; Jmsg(jcr, M_FATAL, 0, _("%s returned non-zero status=%d. ERR=%s\n"), name, - status, be.strerror(status)); + status, be.strerror(status)); return false; } return true; @@ -555,39 +557,39 @@ static void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *filese ch = (uint8_t)*p; switch (ch) { case '|': - p++; /* skip over | */ + p++; /* skip over | */ fn = get_pool_memory(PM_FNAME); fn = edit_job_codes(jcr, fn, p, ""); bpipe = open_bpipe(fn, 0, "r"); free_pool_memory(fn); if (!bpipe) { Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"), - p, strerror(errno)); - return; + p, strerror(errno)); + return; } while (fgets(buf, sizeof(buf), bpipe->rfd)) { - strip_trailing_junk(buf); - fileset->incexe->name_list.append(bstrdup(buf)); + strip_trailing_junk(buf); + fileset->incexe->name_list.append(bstrdup(buf)); } if ((stat=close_bpipe(bpipe)) != 0) { Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. RtnStat=%d ERR=%s\n"), - p, stat, strerror(errno)); - return; + p, stat, strerror(errno)); + return; } break; case '<': Dmsg0(100, "Doing < include on client.\n"); - p++; /* skip over < */ + p++; /* skip over < */ if ((ffd = fopen(p, "r")) == NULL) { - berrno be; + berrno be; Jmsg(jcr, M_FATAL, 0, _("Cannot open FileSet input file: %s. ERR=%s\n"), - p, be.strerror()); - return; + p, be.strerror()); + return; } while (fgets(buf, sizeof(buf), ffd)) { - strip_trailing_junk(buf); + strip_trailing_junk(buf); Dmsg1(100, "%s\n", buf); - fileset->incexe->name_list.append(bstrdup(buf)); + fileset->incexe->name_list.append(bstrdup(buf)); } fclose(ffd); break; @@ -666,27 +668,27 @@ static void add_fileset(JCR *jcr, const char *item) char prbuf[500]; preg = (regex_t *)malloc(sizeof(regex_t)); if (current_opts->flags & FO_IGNORECASE) { - rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE); + rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE); } else { - rc = regcomp(preg, item, REG_EXTENDED); + rc = regcomp(preg, item, REG_EXTENDED); } if (rc != 0) { - regerror(rc, preg, prbuf, sizeof(prbuf)); - regfree(preg); - free(preg); + regerror(rc, preg, prbuf, sizeof(prbuf)); + regfree(preg); + free(preg); Jmsg(jcr, M_FATAL, 0, "REGEX %s compile error. ERR=%s\n", item, prbuf); - state = state_error; - break; + state = state_error; + break; } state = state_options; if (subcode == ' ') { - current_opts->regex.append(preg); + current_opts->regex.append(preg); } else if (subcode == 'D') { - current_opts->regexdir.append(preg); + current_opts->regexdir.append(preg); } else if (subcode == 'F') { - current_opts->regexfile.append(preg); + current_opts->regexfile.append(preg); } else { - state = state_error; + state = state_error; } break; case 'B': @@ -703,13 +705,13 @@ static void add_fileset(JCR *jcr, const char *item) current_opts = start_options(ff); state = state_options; if (subcode == ' ') { - current_opts->wild.append(bstrdup(item)); + current_opts->wild.append(bstrdup(item)); } else if (subcode == 'D') { - current_opts->wilddir.append(bstrdup(item)); + current_opts->wilddir.append(bstrdup(item)); } else if (subcode == 'F') { - current_opts->wildfile.append(bstrdup(item)); + current_opts->wildfile.append(bstrdup(item)); } else { - state = state_error; + state = state_error; } break; case 'O': @@ -745,37 +747,37 @@ static bool term_fileset(JCR *jcr) findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i); Dmsg0(400, "I\n"); for (j=0; jopts_list.size(); j++) { - findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); - for (k=0; kregex.size(); k++) { + findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); + for (k=0; kregex.size(); k++) { Dmsg1(400, "R %s\n", (char *)fo->regex.get(k)); - } - for (k=0; kregexdir.size(); k++) { + } + for (k=0; kregexdir.size(); k++) { Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k)); - } - for (k=0; kregexfile.size(); k++) { + } + for (k=0; kregexfile.size(); k++) { Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k)); - } - for (k=0; kwild.size(); k++) { + } + for (k=0; kwild.size(); k++) { Dmsg1(400, "W %s\n", (char *)fo->wild.get(k)); - } - for (k=0; kwilddir.size(); k++) { + } + for (k=0; kwilddir.size(); k++) { Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k)); - } - for (k=0; kwildfile.size(); k++) { + } + for (k=0; kwildfile.size(); k++) { Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k)); - } - for (k=0; kbase.size(); k++) { + } + for (k=0; kbase.size(); k++) { Dmsg1(400, "B %s\n", (char *)fo->base.get(k)); - } - for (k=0; kfstype.size(); k++) { + } + for (k=0; kfstype.size(); k++) { Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k)); - } - if (fo->reader) { + } + if (fo->reader) { Dmsg1(400, "D %s\n", fo->reader); - } - if (fo->writer) { + } + if (fo->writer) { Dmsg1(400, "T %s\n", fo->writer); - } + } } for (j=0; jname_list.size(); j++) { Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j)); @@ -785,31 +787,31 @@ static bool term_fileset(JCR *jcr) findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i); Dmsg0(400, "E\n"); for (j=0; jopts_list.size(); j++) { - findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); - for (k=0; kregex.size(); k++) { + findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); + for (k=0; kregex.size(); k++) { Dmsg1(400, "R %s\n", (char *)fo->regex.get(k)); - } - for (k=0; kregexdir.size(); k++) { + } + for (k=0; kregexdir.size(); k++) { Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k)); - } - for (k=0; kregexfile.size(); k++) { + } + for (k=0; kregexfile.size(); k++) { Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k)); - } - for (k=0; kwild.size(); k++) { + } + for (k=0; kwild.size(); k++) { Dmsg1(400, "W %s\n", (char *)fo->wild.get(k)); - } - for (k=0; kwilddir.size(); k++) { + } + for (k=0; kwilddir.size(); k++) { Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k)); - } - for (k=0; kwildfile.size(); k++) { + } + for (k=0; kwildfile.size(); k++) { Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k)); - } - for (k=0; kbase.size(); k++) { + } + for (k=0; kbase.size(); k++) { Dmsg1(400, "B %s\n", (char *)fo->base.get(k)); - } - for (k=0; kfstype.size(); k++) { + } + for (k=0; kfstype.size(); k++) { Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k)); - } + } } for (j=0; jname_list.size(); j++) { Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j)); @@ -833,72 +835,72 @@ static void set_options(findFOPTS *fo, const char *opts) switch (*p) { case 'a': /* alway replace */ case '0': /* no option */ - break; + break; case 'e': - fo->flags |= FO_EXCLUDE; - break; + fo->flags |= FO_EXCLUDE; + break; case 'f': - fo->flags |= FO_MULTIFS; - break; + fo->flags |= FO_MULTIFS; + break; case 'h': /* no recursion */ - fo->flags |= FO_NO_RECURSION; - break; + fo->flags |= FO_NO_RECURSION; + break; case 'H': /* no hard link handling */ - fo->flags |= FO_NO_HARDLINK; - break; + fo->flags |= FO_NO_HARDLINK; + break; case 'i': - fo->flags |= FO_IGNORECASE; - break; + fo->flags |= FO_IGNORECASE; + break; case 'M': /* MD5 */ - fo->flags |= FO_MD5; - break; + fo->flags |= FO_MD5; + break; case 'n': - fo->flags |= FO_NOREPLACE; - break; + fo->flags |= FO_NOREPLACE; + break; case 'p': /* use portable data format */ - fo->flags |= FO_PORTABLE; - break; + fo->flags |= FO_PORTABLE; + break; case 'R': /* Resource forks and Finder Info */ - fo->flags |= FO_HFSPLUS; + fo->flags |= FO_HFSPLUS; case 'r': /* read fifo */ - fo->flags |= FO_READFIFO; - break; + fo->flags |= FO_READFIFO; + break; case 'S': - fo->flags |= FO_SHA1; - break; + fo->flags |= FO_SHA1; + break; case 's': - fo->flags |= FO_SPARSE; - break; + fo->flags |= FO_SPARSE; + break; case 'm': - fo->flags |= FO_MTIMEONLY; - break; + fo->flags |= FO_MTIMEONLY; + break; case 'k': - fo->flags |= FO_KEEPATIME; - break; + fo->flags |= FO_KEEPATIME; + break; case 'A': - fo->flags |= FO_ACL; - break; + fo->flags |= FO_ACL; + break; case 'V': /* verify options */ - /* Copy Verify Options */ + /* Copy Verify Options */ for (j=0; *p && *p != ':'; p++) { - fo->VerifyOpts[j] = *p; - if (j < (int)sizeof(fo->VerifyOpts) - 1) { - j++; - } - } - fo->VerifyOpts[j] = 0; - break; + fo->VerifyOpts[j] = *p; + if (j < (int)sizeof(fo->VerifyOpts) - 1) { + j++; + } + } + fo->VerifyOpts[j] = 0; + break; case 'w': - fo->flags |= FO_IF_NEWER; - break; + fo->flags |= FO_IF_NEWER; + break; case 'Z': /* gzip compression */ - fo->flags |= FO_GZIP; + fo->flags |= FO_GZIP; fo->GZIP_level = *++p - '0'; Dmsg1(200, "Compression level=%d\n", fo->GZIP_level); - break; + break; default: Emsg1(M_ERROR, 0, "Unknown include/exclude option: %c\n", *p); - break; + break; } } } @@ -910,6 +912,10 @@ static void set_options(findFOPTS *fo, const char *opts) static int fileset_cmd(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; + int vss = 0; + + sscanf(dir->msg, "fileset vss=%d", &vss); + enable_vss = vss; if (!init_fileset(jcr)) { return 0; @@ -952,10 +958,10 @@ static int bootstrap_cmd(JCR *jcr) * read our error message. */ while (bnet_recv(dir) >= 0) - { } + { } Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"), - jcr->RestoreBootstrap, be.strerror()); + jcr->RestoreBootstrap, be.strerror()); free_pool_memory(jcr->RestoreBootstrap); jcr->RestoreBootstrap = NULL; set_jcr_job_status(jcr, JS_ErrorTerminated); @@ -1003,54 +1009,54 @@ static int level_cmd(JCR *jcr) return 1; /* * We get his UTC since time, then sync the clocks and correct it - * to agree with our clock. + * to agree with our clock. */ } else if (strcmp(level, "since_utime") == 0) { buf = get_memory(dir->msglen+1); utime_t since_time, adj; btime_t his_time, bt_start, rt=0, bt_adj=0; if (jcr->JobLevel == L_NONE) { - jcr->JobLevel = L_SINCE; /* if no other job level set, do it now */ + jcr->JobLevel = L_SINCE; /* if no other job level set, do it now */ } if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d", - buf, &mtime_only) != 2) { - goto bail_out; + buf, &mtime_only) != 2) { + goto bail_out; } - since_time = str_to_uint64(buf); /* this is the since time */ + since_time = str_to_uint64(buf); /* this is the since time */ char ed1[50], ed2[50]; /* * Sync clocks by polling him for the time. We take * 10 samples of his time throwing out the first two. */ for (int i=0; i<10; i++) { - bt_start = get_current_btime(); - bnet_sig(dir, BNET_BTIME); /* poll for time */ - if (bnet_recv(dir) <= 0) { /* get response */ - goto bail_out; - } + bt_start = get_current_btime(); + bnet_sig(dir, BNET_BTIME); /* poll for time */ + if (bnet_recv(dir) <= 0) { /* get response */ + goto bail_out; + } if (sscanf(dir->msg, "btime %s", buf) != 1) { - goto bail_out; - } - if (i < 2) { /* toss first two results */ - continue; - } - his_time = str_to_uint64(buf); - rt = get_current_btime() - bt_start; /* compute round trip time */ - bt_adj -= his_time - bt_start - rt/2; + goto bail_out; + } + if (i < 2) { /* toss first two results */ + continue; + } + his_time = str_to_uint64(buf); + rt = get_current_btime() - bt_start; /* compute round trip time */ + bt_adj -= his_time - bt_start - rt/2; Dmsg2(200, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2)); } - bt_adj = bt_adj / 8; /* compute average time */ + bt_adj = bt_adj / 8; /* compute average time */ Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2)); adj = btime_to_utime(bt_adj); - since_time += adj; /* adjust for clock difference */ + since_time += adj; /* adjust for clock difference */ if (adj != 0) { Jmsg(jcr, M_INFO, 0, _("DIR and FD clocks differ by %d seconds, FD automatically adjusting.\n"), adj); } bnet_sig(dir, BNET_EOD); Dmsg2(100, "adj = %d since_time=%d\n", (int)adj, (int)since_time); - jcr->incremental = 1; /* set incremental or decremental backup */ + jcr->incremental = 1; /* set incremental or decremental backup */ jcr->mtime = (time_t)since_time; /* set since time */ } else { Jmsg1(jcr, M_FATAL, 0, "Unknown backup level: %s\n", level); @@ -1082,9 +1088,9 @@ static int session_cmd(JCR *jcr) Dmsg1(100, "SessionCmd: %s", dir->msg); if (sscanf(dir->msg, sessioncmd, jcr->VolumeName, - &jcr->VolSessionId, &jcr->VolSessionTime, - &jcr->StartFile, &jcr->EndFile, - &jcr->StartBlock, &jcr->EndBlock) != 7) { + &jcr->VolSessionId, &jcr->VolSessionTime, + &jcr->StartFile, &jcr->EndFile, + &jcr->StartBlock, &jcr->EndBlock) != 7) { pm_strcpy(jcr->errmsg, dir->msg); Jmsg(jcr, M_FATAL, 0, "Bad session command: %s", jcr->errmsg); return 0; @@ -1099,10 +1105,10 @@ static int session_cmd(JCR *jcr) */ static int storage_cmd(JCR *jcr) { - int stored_port; /* storage daemon port */ - int enable_ssl; /* enable ssl to sd */ + int stored_port; /* storage daemon port */ + int enable_ssl; /* enable ssl to sd */ BSOCK *dir = jcr->dir_bsock; - BSOCK *sd; /* storage daemon bsock */ + BSOCK *sd; /* storage daemon bsock */ Dmsg1(100, "StorageCmd: %s", dir->msg); if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, &enable_ssl) != 3) { @@ -1114,12 +1120,12 @@ static int storage_cmd(JCR *jcr) /* Open command communications with Storage daemon */ /* Try to connect for 1 hour at 10 second intervals */ sd = bnet_connect(jcr, 10, (int)me->SDConnectTimeout, _("Storage daemon"), - jcr->stored_addr, NULL, stored_port, 1); + jcr->stored_addr, NULL, stored_port, 1); if (sd == NULL) { Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"), - jcr->stored_addr, stored_port); + jcr->stored_addr, stored_port); Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n", - jcr->stored_addr, stored_port); + jcr->stored_addr, stored_port); return 0; } Dmsg0(110, "Connection OK to SD.\n"); @@ -1173,7 +1179,7 @@ static int backup_cmd(JCR *jcr) Dmsg1(110, "msg); if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) { Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg); - goto cleanup; + goto cleanup; } Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket); } else { @@ -1201,20 +1207,20 @@ static int backup_cmd(JCR *jcr) /* START VSS ON WIN 32 */ if (g_pVSSClient) { if (g_pVSSClient->InitializeForBackup()) { - /* tell vss which drives to snapshot */ - char szWinDriveLetters[27]; - if (get_win32_driveletters((FF_PKT *)jcr->ff, szWinDriveLetters)) { + /* tell vss which drives to snapshot */ + char szWinDriveLetters[27]; + if (get_win32_driveletters((FF_PKT *)jcr->ff, szWinDriveLetters)) { Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters); - if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) { + if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) { Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshots failed\n")); - } - else { + } + else { /* tell user if snapshot creation of a specific drive failed */ - for (size_t i=0; iGetWriterCount(); i++) { int msg_type = M_INFO; @@ -1223,8 +1229,8 @@ static int backup_cmd(JCR *jcr) Jmsg(jcr, msg_type, 0, _("VSS Writer: %s\n"), g_pVSSClient->GetWriterInfo(i)); } - } - } + } + } } else { Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled.")); } @@ -1238,20 +1244,20 @@ static int backup_cmd(JCR *jcr) if (!blast_data_to_storage_daemon(jcr, NULL)) { set_jcr_job_status(jcr, JS_ErrorTerminated); bnet_suppress_error_messages(sd, 1); - bget_msg(sd); /* Read final response from append_data */ + bget_msg(sd); /* Read final response from append_data */ Dmsg0(110, "Error in blast_data.\n"); } else { set_jcr_job_status(jcr, JS_Terminated); if (jcr->JobStatus != JS_Terminated) { - bnet_suppress_error_messages(sd, 1); - goto cleanup; /* bail out now */ + bnet_suppress_error_messages(sd, 1); + goto cleanup; /* bail out now */ } /* * Expect to get response to append_data from Storage daemon */ if (!response(jcr, sd, OK_append, "Append Data")) { - set_jcr_job_status(jcr, JS_ErrorTerminated); - goto cleanup; + set_jcr_job_status(jcr, JS_ErrorTerminated); + goto cleanup; } /* @@ -1260,8 +1266,8 @@ static int backup_cmd(JCR *jcr) bnet_fsend(sd, append_end, jcr->Ticket); /* Get end OK */ if (!response(jcr, sd, OK_end, "Append End")) { - set_jcr_job_status(jcr, JS_ErrorTerminated); - goto cleanup; + set_jcr_job_status(jcr, JS_ErrorTerminated); + goto cleanup; } /* @@ -1269,18 +1275,18 @@ static int backup_cmd(JCR *jcr) */ bnet_fsend(sd, append_close, jcr->Ticket); while (bget_msg(sd) >= 0) { /* stop on signal or error */ - if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) { - ok = 1; + if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) { + ok = 1; Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus); - } + } } if (!ok) { Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n")); - goto cleanup; + goto cleanup; } if (SDJobStatus != JS_Terminated) { Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"), - SDJobStatus); + SDJobStatus); } } @@ -1297,7 +1303,7 @@ cleanup: edit_uint64(jcr->JobBytes, ed2), jcr->Errors); Dmsg1(110, "End FD msg: %s\n", dir->msg); - return 0; /* return and stop command loop */ + return 0; /* return and stop command loop */ } /* @@ -1344,7 +1350,7 @@ static int verify_cmd(JCR *jcr) break; case L_VERIFY_VOLUME_TO_CATALOG: if (!open_sd_read_session(jcr)) { - return 0; + return 0; } start_dir_heartbeat(jcr); do_verify_volume(jcr); @@ -1356,7 +1362,7 @@ static int verify_cmd(JCR *jcr) Dmsg1(130, "bfiled>stored: %s", sd->msg); /* ****FIXME**** check response */ - bget_msg(sd); /* get OK */ + bget_msg(sd); /* get OK */ /* Inform Storage daemon that we are done */ bnet_sig(sd, BNET_TERMINATE); @@ -1379,7 +1385,7 @@ static int verify_cmd(JCR *jcr) /* Inform Director that we are done */ bnet_sig(dir, BNET_TERMINATE); - return 0; /* return and terminate command loop */ + return 0; /* return and terminate command loop */ } /* @@ -1405,9 +1411,9 @@ static int restore_cmd(JCR *jcr) if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, where) != 3) { if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) { - pm_strcpy(jcr->errmsg, dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg); - return 0; + return 0; } *where = 0; } @@ -1456,7 +1462,7 @@ static int restore_cmd(JCR *jcr) bnet_fsend(sd, read_close, jcr->Ticket); Dmsg1(130, "bfiled>stored: %s", sd->msg); - bget_msg(sd); /* get OK */ + bget_msg(sd); /* get OK */ /* Inform Storage daemon that we are done */ bnet_sig(sd, BNET_TERMINATE); @@ -1475,7 +1481,7 @@ bail_out: bnet_sig(dir, BNET_TERMINATE); Dmsg0(130, "Done in job.c\n"); - return 0; /* return and terminate command loop */ + return 0; /* return and terminate command loop */ } static int open_sd_read_session(JCR *jcr) @@ -1504,7 +1510,7 @@ static int open_sd_read_session(JCR *jcr) Dmsg1(110, "bfiledmsg); if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) { Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg); - return 0; + return 0; } Dmsg1(110, "bfiled: got Ticket=%d\n", jcr->Ticket); } else { @@ -1561,7 +1567,7 @@ static void filed_free_jcr(JCR *jcr) * sent. Check that the response is OK. * * Returns: 0 on failure - * 1 on success + * 1 on success */ int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd) { @@ -1571,18 +1577,18 @@ int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd) if (bget_msg(sd) > 0) { Dmsg0(110, sd->msg); if (strcmp(sd->msg, resp) == 0) { - return 1; + return 1; } } if (job_canceled(jcr)) { - return 0; /* if canceled avoid useless error messages */ + return 0; /* if canceled avoid useless error messages */ } if (is_bnet_error(sd)) { Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"), - cmd, bnet_strerror(sd)); + cmd, bnet_strerror(sd)); } else { Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"), - cmd, resp, sd->msg); + cmd, resp, sd->msg); } return 0; } @@ -1603,7 +1609,7 @@ static int send_bootstrap_file(JCR *jcr) if (!bs) { berrno be; Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"), - jcr->RestoreBootstrap, be.strerror()); + jcr->RestoreBootstrap, be.strerror()); set_jcr_job_status(jcr, JS_ErrorTerminated); goto bail_out; } diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 2182be7606..a7761fbbc6 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -256,6 +256,7 @@ public: bool spool_data; /* set to spool data */ int CurVol; /* Current Volume count */ DIRRES* director; /* Director resource */ + alist *dirstore; bool write_part_after_job; /* Set to write part after job */ bool PreferMountedVols; /* Prefer mounted vols rather than new */ diff --git a/bacula/src/lib/htable.c b/bacula/src/lib/htable.c index 0af1101356..3c5a52f633 100644 --- a/bacula/src/lib/htable.c +++ b/bacula/src/lib/htable.c @@ -26,19 +26,14 @@ Copyright (C) 2003-2005 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 ammended 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. */ @@ -79,11 +74,11 @@ void htable::init(void *item, void *link, int tsize) tsize >>= 1; } loffset = (char *)link - (char *)item; - mask = ~((~0)< table size = 8 */ - rshift = 30 - pwr; /* start using bits 28, 29, 30 */ - num_items = 0; /* number of entries in table */ - buckets = 1< table size = 8 */ + rshift = 30 - pwr; /* start using bits 28, 29, 30 */ + num_items = 0; /* number of entries in table */ + buckets = 1<next); - j++; + p = (hlink *)(p->next); + j++; } if (j > max) { - max = j; + max = j; } if (j < MAX_COUNT) { - hits[j]++; + hits[j]++; } } for (i=0; i < MAX_COUNT; i++) { @@ -164,10 +159,10 @@ void htable::grow_table() Dmsg1(100, "Grow insert: %s\n", ((hlink *)((char *)item+loffset))->key); big->insert(((hlink *)((char *)item+loffset))->key, item); if (ni) { - item = (void *)((char *)ni-loffset); + item = (void *)((char *)ni-loffset); } else { - walkptr = NULL; - item = next(); + walkptr = NULL; + item = next(); } } Dmsg1(100, "After copy new num_items=%d\n", big->num_items); @@ -184,7 +179,7 @@ bool htable::insert(char *key, void *item) { hlink *hp; if (lookup(key)) { - return false; /* already exists */ + return false; /* already exists */ } sm_check(__FILE__, __LINE__, false); ASSERT(index < buckets); @@ -215,7 +210,7 @@ void *htable::lookup(char *key) // Dmsg2(100, "hp=0x%x key=%s\n", (long)hp, hp->key); if (hash == hp->hash && strcmp(key, hp->key) == 0) { Dmsg1(100, "lookup return %x\n", ((char *)hp)-loffset); - return ((char *)hp)-loffset; + return ((char *)hp)-loffset; } } return NULL; @@ -231,12 +226,12 @@ void *htable::next() walkptr = table[walk_index++]; if (walkptr) { Dmsg3(100, "new walkptr=0x%x next=0x%x inx=%d\n", (unsigned)walkptr, - (unsigned)(walkptr->next), walk_index-1); + (unsigned)(walkptr->next), walk_index-1); } } if (walkptr) { Dmsg2(100, "next: rtn 0x%x walk_index=%d\n", - (unsigned)(((char *)walkptr)-loffset), walk_index); + (unsigned)(((char *)walkptr)-loffset), walk_index); return ((char *)walkptr)-loffset; } Dmsg0(100, "next: return NULL\n"); @@ -246,13 +241,13 @@ void *htable::next() void *htable::first() { Dmsg0(100, "Enter first\n"); - walkptr = table[0]; /* get first bucket */ - walk_index = 1; /* Point to next index */ + walkptr = table[0]; /* get first bucket */ + walk_index = 1; /* Point to next index */ while (!walkptr && walk_index < buckets) { walkptr = table[walk_index++]; /* go to next bucket */ if (walkptr) { Dmsg3(100, "first new walkptr=0x%x next=0x%x inx=%d\n", (unsigned)walkptr, - (unsigned)(walkptr->next), walk_index-1); + (unsigned)(walkptr->next), walk_index-1); } } if (walkptr) { @@ -310,7 +305,7 @@ int main() jcrtbl->insert(jcr->key, jcr); if (i == 10) { - save_jcr = jcr; + save_jcr = jcr; } } if (!(item = (MYJCR *)jcrtbl->lookup(save_jcr->key))) { diff --git a/bacula/src/lib/htable.h b/bacula/src/lib/htable.h index cb18c8fd30..ddf7605859 100644 --- a/bacula/src/lib/htable.h +++ b/bacula/src/lib/htable.h @@ -1,24 +1,18 @@ /* * Version $Id$ */ - /* Copyright (C) 2003-2005 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 ammended 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. */ diff --git a/bacula/src/stored/reserve.c b/bacula/src/stored/reserve.c index 36f093d414..8ce61cdcd7 100644 --- a/bacula/src/stored/reserve.c +++ b/bacula/src/stored/reserve.c @@ -65,6 +65,7 @@ static int reserve_device(RCTX &rctx); static bool reserve_device_for_read(DCR *dcr); static bool reserve_device_for_append(DCR *dcr); static bool use_storage_cmd(JCR *jcr); +bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx); /* Requests from the Director daemon */ static char use_storage[] = "use storage=%127s media_type=%127s " @@ -222,10 +223,8 @@ static bool use_storage_cmd(JCR *jcr) int append; bool ok; int Copy, Stripe; - alist *dirstore; DIRSTORE *store; char *device_name; - DCR *dcr = NULL; RCTX rctx; rctx.jcr = jcr; #ifdef implemented @@ -237,7 +236,7 @@ static bool use_storage_cmd(JCR *jcr) * use_device for each device that it wants to use. */ Dmsg1(100, "msg); - dirstore = New(alist(10, not_owned_by_alist)); + jcr->dirstore = New(alist(10, not_owned_by_alist)); do { ok = sscanf(dir->msg, use_storage, store_name.c_str(), media_type.c_str(), pool_name.c_str(), @@ -250,7 +249,7 @@ static bool use_storage_cmd(JCR *jcr) unbash_spaces(pool_name); unbash_spaces(pool_type); store = new DIRSTORE; - dirstore->append(store); + jcr->dirstore->append(store); memset(store, 0, sizeof(DIRSTORE)); store->device = New(alist(10)); bstrncpy(store->name, store_name, sizeof(store->name)); @@ -273,7 +272,7 @@ static bool use_storage_cmd(JCR *jcr) #ifdef DEVELOPER /* This loop is debug code and can be removed */ /* ***FIXME**** remove after 1.38 release */ - foreach_alist(store, dirstore) { + foreach_alist(store, jcr->dirstore) { Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n", store->name, store->media_type, store->pool_name, store->pool_type); @@ -293,42 +292,9 @@ static bool use_storage_cmd(JCR *jcr) * Wiffle through them and find one that can do the backup. */ if (ok) { - bool first = true; - init_jcr_device_wait_timers(jcr); - for ( ;; ) { - int need_wait = false; - foreach_alist(store, dirstore) { - rctx.store = store; - foreach_alist(device_name, store->device) { - int stat; - rctx.device_name = device_name; - stat = search_res_for_device(rctx); - if (stat == 1) { /* found available device */ - dcr = jcr->dcr; - dcr->Copy = Copy; - dcr->Stripe = Stripe; - ok = true; - goto done; - } else if (stat == 0) { /* device busy */ - need_wait = true; - } -// rctx->errors.push(bstrdup(jcr->errmsg)); - } - } - /* - * If there is some device for which we can wait, then - * wait and try again until the wait time expires - */ - if (!need_wait || !wait_for_device(jcr, first)) { - break; - } -#ifdef implemented - first = false; - for (error=(char*)rctx->errors.first(); error; - error=(char*)rctx->errors.next()) { - free(error); - } -#endif + ok = find_suitable_device_for_job(jcr, rctx); + if (ok) { + goto done; } if (verbose) { unbash_spaces(dir->msg); @@ -339,35 +305,29 @@ static bool use_storage_cmd(JCR *jcr) " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"), dev_name.c_str(), media_type.c_str()); bnet_fsend(dir, NO_device, dev_name.c_str()); +#ifdef implemented + for (error=(char*)rctx->errors.first(); error; + error=(char*)rctx->errors.next()) { + Jmsg(jcr, M_INFO, 0, "%s", error); + } +#endif Dmsg1(100, ">dird: %s\n", dir->msg); - ok = false; } else { unbash_spaces(dir->msg); pm_strcpy(jcr->errmsg, dir->msg); if (verbose) { Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg); } - Jmsg(jcr, M_FATAL, 0, _("Could not find an available device.\n")); -#ifdef implemented - for (error=(char*)rctx->errors.first(); error; - error=(char*)rctx->errors.next()) { - Jmsg(jcr, M_INFO, 0, "%s", error); - } -#endif bnet_fsend(dir, BAD_use, jcr->errmsg); Dmsg1(100, ">dird: %s\n", dir->msg); - ok = false; } done: - foreach_alist(store, dirstore) { + foreach_alist(store, jcr->dirstore) { delete store->device; delete store; } - delete dirstore; - if (!ok && dcr) { - free_dcr(dcr); - } + delete jcr->dirstore; #ifdef implemented for (error=(char*)rctx->errors.first(); error; error=(char*)rctx->errors.next()) { @@ -378,7 +338,58 @@ done: } +/* + * Search for a device suitable for this job. + */ +bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx) +{ + bool first = true; + bool ok = false; + DCR *dcr = NULL; + DIRSTORE *store; + char *device_name; + + init_jcr_device_wait_timers(jcr); + for ( ;; ) { + int need_wait = false; + foreach_alist(store, jcr->dirstore) { + rctx.store = store; + foreach_alist(device_name, store->device) { + int stat; + rctx.device_name = device_name; + stat = search_res_for_device(rctx); + if (stat == 1) { /* found available device */ + dcr = jcr->dcr; + ok = true; + break; + } else if (stat == 0) { /* device busy */ + need_wait = true; + } + /* otherwise error */ +// rctx->errors.push(bstrdup(jcr->errmsg)); + } + } + /* + * If there is some device for which we can wait, then + * wait and try again until the wait time expires + */ + if (!need_wait || !wait_for_device(jcr, first)) { + break; + } + first = false; +#ifdef implemented + for (error=(char*)rctx->errors.first(); error; + error=(char*)rctx->errors.next()) { + free(error); + } +#endif + } + if (!ok && dcr) { + free_dcr(dcr); + } + return ok; +} /* * Search for a particular storage device with particular storage diff --git a/bacula/src/version.h b/bacula/src/version.h index a9182f5c2a..83ca8cb709 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION #define VERSION "1.37.22" -#define BDATE "10 June 2005" -#define LSMDATE "10Jun05" +#define BDATE "12 June 2005" +#define LSMDATE "12Jun05" /* Debug flags */ #undef DEBUG -- 2.39.2