From ba0c96d6935af4485f55a98f6cb306f06e08d81d Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Fri, 26 Sep 2003 10:29:29 +0000 Subject: [PATCH] Misc -- see ChangeLog git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@713 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ChangeLog | 23 +++++ bacula/ReleaseNotes | 39 ++++++-- bacula/autoconf/config.h.in | 13 --- bacula/autoconf/configure.in | 19 ++-- bacula/configure | 158 ++---------------------------- bacula/kernstodo | 25 ++++- bacula/src/cats/sql_create.c | 2 +- bacula/src/dird/ua_label.c | 53 ++++++---- bacula/src/lib/bsys.c | 6 +- bacula/src/lib/protos.h | 2 +- bacula/src/stored/append.c | 23 ++--- bacula/src/stored/block.c | 28 ++++-- bacula/src/stored/block.h | 1 + bacula/src/stored/bscan.c | 10 +- bacula/src/stored/dircmd.c | 11 ++- bacula/src/stored/job.c | 30 +----- bacula/src/stored/protos.h | 167 ++++++++++++++++---------------- bacula/src/stored/read_record.c | 1 + bacula/src/version.h | 4 +- 19 files changed, 266 insertions(+), 349 deletions(-) diff --git a/bacula/ChangeLog b/bacula/ChangeLog index 31b70f765e..bf5d6580de 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,4 +1,27 @@ +2003-09-26 Version 1.32 26Sep03 Beta +- Add regression and GUI-interface chapters to the manual. +- Fix "label" of a volume that is already in the catalog, + but not yet labeled. +- Correct the test for spooling attributes which was backward. + This caused the creation of a spool file in the working + directory for every job run. +- Print to the job output stream when block checksum errors + occur, but continue processing. If more than one occurs, + print number at end of job. +- Remove a few unneeded tests from configure.in +- Modify configure to use -pthread on FreeBSD 4.8, + but nothing on FreeBSD 5.1 +- Clarify that bmicrosleep() takes sec and microsecs +- Apply Franc Carter's code to specify a DB host in + bscan. +- Fix sanity login length test in stored/dircmd.c +- remove old code fro stored/job.c +- Lots of work on regress so that it works on FreeBSD + and Solaris. +- Make the default gnome-console wider (console.c) +- Add \r to the items that terminate a token. + 2003-09-20 Version 1.32 20Sep03 Beta - Replace a number strcpy() calls with bstrncpy(). - Added code to ensure that the names for each resource diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index ede070c3e2..668426ebe3 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -1,27 +1,37 @@ Release Notes for Bacula 1.32 - Bacula code: Total files = 259 Total lines = 77,576 (*.h *.c *.in) + Bacula code: Total files = 259 Total lines = 77,702 (*.h *.c *.in) Major Changes this Release: -- Fixed gnome-console to compile with RH9 (Gnome 2.0) -- Implemented a single routine to read_records. It also returns - a different record packet for each session. This means - that multiple simultaneous jobs should work. - Implemented forward space file/block whenever possible - during restore. -- Added SDConnectTimeout to FD. + during restore. Restoring a small number of files is now + much faster. +- There is a new option to restore that allows you + to restore files based on their Filename. You can + also specify a file to read which contains the list. - Added ClientRunBeforeJob and ClientRunAfterJob. - Implemented Include | and < in File daemon. -- Implemented a new Include/Exclude syntax. -- Lots of fixes with variable expansion and counter variables -- Automatic labeling of tape Volumes is fixed. +- Automatic labeling of tape Volumes should work now. - Recycling has been completely restructured and should work. - Implemented full length time interval qualifiers (e.g "5n is now "5 min" or "5 minutes". A modifier is now required! +- Fixed gnome-console to compile with RH9 (Gnome 2.0) +- Implemented "list nextvol job=xxx", which displays the + next volume to be used by job xxx. The Volume name to + be used is also added to the "status dir" output. +- Lots of fixes with variable expansion and counter variables +- Implemented a new Include/Exclude syntax. Other Changes this Release: +- A warning message is sent when a job starts that will be + blocked because the user did an "unmount". +- Block checksum errors if any are printed in the job report. +- Implemented a single routine to read_records. It also returns + a different record packet for each session. This means + that multiple simultaneous jobs should work. +- Added SDConnectTimeout to FD. - Lots of doc enhancements - Fixed a PurgeOldestVolume bug (VolStatus not returned) - Don't crash if DB address record not specified. @@ -45,9 +55,18 @@ Other Changes this Release: be phased out over time. FDAddress, FDPassword, SDAddress SDPassword, SDDeviceName, and DBPassword. - A possible fix to the very intermittent SD crashes that Alex gets. + Items to note: !!!!! - Modifiers (sec, min, hour, day, ...) are now required on conf file time interval specifications. - Duplicate names within the same conf resource are prohibited. +- If you have used a prior BETA version of 1.32, please do + the following to cleanup any zero length spool files: + + cd + rm -f *.spool.* + + Please be sure there are no spaces between the asterisks + and the periods. diff --git a/bacula/autoconf/config.h.in b/bacula/autoconf/config.h.in index 988e364de4..13c47a8636 100644 --- a/bacula/autoconf/config.h.in +++ b/bacula/autoconf/config.h.in @@ -378,10 +378,6 @@ /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP -/* Define to 1 if you have the `strcoll' function and it is properly defined. - */ -#undef HAVE_STRCOLL - /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR @@ -447,12 +443,6 @@ */ #undef HAVE_SYS_NDIR_H -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_PTEM_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_PTE_H - /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H @@ -465,9 +455,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STREAM_H - /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index bdb404b965..f00fbe38a9 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -368,17 +368,7 @@ AC_HEADER_DIRENT AC_CHECK_FUNCS(strcasecmp select setenv putenv tcgetattr setlocale lstat lchown) AC_CHECK_FUNCS(nanosleep) -#AC_CHECK_FUNC(getopt_long, AC_DEFINE(HAVE_GETOPT_LONG), -# [LIBEXTRAOBJ="$LIBEXTRAOBJ getopt.o getopt1.o" -# EXTRAOBJ="$EXTRAOBJ lib/getopt.o lib/getopt1.o"]) - -AC_CHECK_FUNC(getopt_long, AC_DEFINE(HAVE_GETOPT_LONG)) - - -AC_FUNC_STRCOLL - -AC_CHECK_HEADERS(varargs.h \ - sys/ptem.h sys/pte.h sys/stream.h) +AC_CHECK_HEADERS(varargs.h) # End of readline stuff # ----------------------------------------------------------------------- @@ -1237,8 +1227,11 @@ debian) ;; freebsd) DISTVER=`uname -a |awk '{print $3}'` - PTHREAD_LIB="-pthread" - CFLAGS="${CFLAGS} -pthread" + VER=`echo $DISTVER | cut -c 1` + if test x$VER = x4 ; then + PTHREAD_LIB="-pthread" + CFLAGS="${CFLAGS} -pthread" + fi lld="qd" llu="qu" TAPEDRIVE="/dev/nrsa0" diff --git a/bacula/configure b/bacula/configure index 84baa3d3f5..ea8b2cac36 100755 --- a/bacula/configure +++ b/bacula/configure @@ -6046,157 +6046,8 @@ fi done -#AC_CHECK_FUNC(getopt_long, AC_DEFINE(HAVE_GETOPT_LONG), -# [LIBEXTRAOBJ="$LIBEXTRAOBJ getopt.o getopt1.o" -# EXTRAOBJ="$EXTRAOBJ lib/getopt.o lib/getopt1.o"]) -echo "$as_me:$LINENO: checking for getopt_long" >&5 -echo $ECHO_N "checking for getopt_long... $ECHO_C" >&6 -if test "${ac_cv_func_getopt_long+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char getopt_long (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ -#ifdef __STDC__ -# include -#else -# include -#endif -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char getopt_long (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_getopt_long) || defined (__stub___getopt_long) -choke me -#else -char (*f) () = getopt_long; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != getopt_long; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_getopt_long=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_getopt_long=no -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_getopt_long" >&5 -echo "${ECHO_T}$ac_cv_func_getopt_long" >&6 -if test $ac_cv_func_getopt_long = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_GETOPT_LONG 1 -_ACEOF - -fi - - - -echo "$as_me:$LINENO: checking for working strcoll" >&5 -echo $ECHO_N "checking for working strcoll... $ECHO_C" >&6 -if test "${ac_cv_func_strcoll_works+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then - ac_cv_func_strcoll_works=no -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -exit (strcoll ("abc", "def") >= 0 || - strcoll ("ABC", "DEF") >= 0 || - strcoll ("123", "456") >= 0) - ; - return 0; -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_strcoll_works=yes -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_func_strcoll_works=no -fi -rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_func_strcoll_works" >&5 -echo "${ECHO_T}$ac_cv_func_strcoll_works" >&6 -if test $ac_cv_func_strcoll_works = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_STRCOLL 1 -_ACEOF - -fi - - - - - - -for ac_header in varargs.h \ - sys/ptem.h sys/pte.h sys/stream.h +for ac_header in varargs.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then @@ -17400,8 +17251,11 @@ debian) ;; freebsd) DISTVER=`uname -a |awk '{print $3}'` - PTHREAD_LIB="-pthread" - CFLAGS="${CFLAGS} -pthread" + VER=`echo $DISTVER | cut -c 1` + if test x$VER = x4 ; then + PTHREAD_LIB="-pthread" + CFLAGS="${CFLAGS} -pthread" + fi lld="qd" llu="qu" TAPEDRIVE="/dev/nrsa0" diff --git a/bacula/kernstodo b/bacula/kernstodo index 00228063c9..217f116396 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 20 September 2003 + 26 September 2003 Documentation to do: (any release a little bit at a time) - Document running a test version. @@ -21,6 +21,7 @@ Testing to do: (painful) - Test cancel at EOM. - Test not zeroing Autochanger slot when it is wrong. - Figure out how to use ssh or stunnel to protect Bacula communications. +- Test connect timeouts. For 1.32 Testing/Documentation: - Document new records in Director. SDAddress SDDeviceName, SDPassword. @@ -29,15 +30,28 @@ For 1.32 Testing/Documentation: - Document new Include/Exclude ... - Document all the status codes JobLevel, JobType, JobStatus. - Add test of exclusion, test multiple Include {} statements. +- Add counter variable test. For 1.32: +- Look at Cleaning tape in ua_label.c for media create/update +- Fix get_storage_from_media_type (ua_restore) to use command line + storage= +- Document list nextvol and status output. +- Add GUI interface to manual +- Add regression testing to the manual + + +For 1.33 - Enhance "update slots" to include a "scan" feature scan 1; scan 1-5; scan 1,2,4 ... to update the catalog - Allow a slot or range of slots on the label barcodes command. - Don't print "Warning: Wrong Volume mounted ..." if mounting second volume. - - -For 1.33 +- Make Dmsg look at global before calling subroutine. +- Enable trace output at runtime for Win32 +- Make sure that Volumes are recycled based on "Least recently used" + rather than lowest MediaId. +- Available volumes for autochangers (see patrick@baanboard.com 3 Sep 03 + and 4 Sep) scan slots. - Upgrade to cygwin 1.5 - Get MySQL 3.23.58 - Get and test MySQL 4.0 @@ -930,3 +944,6 @@ Done: (see kernsdone for more) - Require some modifer. - Restrict characters permitted in a Resource name, and don't permit duplicate names. +- Figure out some way to ignore or get past checksum errors in + reading. +- The SD spooling file gets created even if it is not used. diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 00e63e8110..80ea509e25 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -247,7 +247,7 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) if (QUERY_DB(jcr, mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 0) { - Mmsg1(&mdb->errmsg, _("Volume \"%s\" already exists\n."), mr->VolumeName); + Mmsg1(&mdb->errmsg, _("Volume \"%s\" already exists.\n"), mr->VolumeName); sql_free_result(mdb); db_unlock(mdb); return 0; diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 4422215835..27af6a471c 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -42,7 +42,7 @@ typedef struct s_vol_list { static int do_label(UAContext *ua, char *cmd, int relabel); static void label_from_barcodes(UAContext *ua); static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, - POOL_DBR *pr, int relabel); + POOL_DBR *pr, int relabel, bool media_record_exits); static vol_list_t *get_slot_list_from_SD(UAContext *ua); static int is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr); @@ -151,6 +151,7 @@ static int do_label(UAContext *ua, char *cmd, int relabel) int ok = FALSE; int mounted = FALSE; int i; + bool media_record_exists = false; static char *barcode_keyword[] = { "barcode", "barcodes", @@ -207,6 +208,7 @@ checkVol: /* Get a new Volume name */ for ( ;; ) { + media_record_exists = false; if (!get_cmd(ua, _("Enter new Volume name: "))) { return 1; } @@ -217,10 +219,14 @@ checkName: memset(&mr, 0, sizeof(mr)); bstrncpy(mr.VolumeName, ua->cmd, sizeof(mr.VolumeName)); + /* If VolBytes are zero the Volume is not labeled */ if (db_get_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"), - mr.VolumeName); - continue; + if (mr.VolBytes != 0) { + bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"), + mr.VolumeName); + continue; + } + media_record_exists = true; } break; /* Got it */ } @@ -255,7 +261,7 @@ checkName: } sd = ua->jcr->store_bsock; - ok = send_label_request(ua, &mr, &omr, &pr, relabel); + ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists); if (ok) { if (relabel) { @@ -303,6 +309,7 @@ static void label_from_barcodes(UAContext *ua) POOL_DBR pr; MEDIA_DBR mr, omr; vol_list_t *vl, *vol_list = NULL; + bool media_record_exists; vol_list = get_slot_list_from_SD(ua); @@ -334,10 +341,14 @@ static void label_from_barcodes(UAContext *ua) memset(&mr, 0, sizeof(mr)); bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); + media_record_exists = false; if (db_get_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"), - vl->Slot, mr.VolumeName); - continue; + if (mr.VolBytes != 0) { + bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"), + vl->Slot, mr.VolumeName); + continue; + } + media_record_exists = true; } /* * Deal with creating cleaning tape here. Normal tapes created in @@ -367,7 +378,7 @@ static void label_from_barcodes(UAContext *ua) } mr.Slot = vl->Slot; - send_label_request(ua, &mr, &omr, &pr, 0); + send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists); } @@ -427,7 +438,7 @@ int is_volume_name_legal(UAContext *ua, char *name) } static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, - POOL_DBR *pr, int relabel) + POOL_DBR *pr, int relabel, bool media_record_exists) { BSOCK *sd; char dev_name[MAX_NAME_LENGTH]; @@ -465,14 +476,22 @@ static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, unbash_spaces(pr->Name); mr->LabelDate = time(NULL); if (ok) { - set_pool_dbr_defaults_in_media_dbr(mr, pr); - mr->VolBytes = 1; /* flag indicating Volume labeled */ - if (db_create_media_record(ua->jcr, ua->db, mr)) { - bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"), + if (media_record_exists) { /* we update it */ + mr->VolBytes = 1; + if (!db_update_media_record(ua->jcr, ua->db, mr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + ok = FALSE; + } + } else { /* create the media record */ + set_pool_dbr_defaults_in_media_dbr(mr, pr); + mr->VolBytes = 1; /* flag indicating Volume labeled */ + if (db_create_media_record(ua->jcr, ua->db, mr)) { + bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"), mr->VolumeName, mr->Slot); - } else { - bsendmsg(ua, "%s", db_strerror(ua->db)); - ok = FALSE; + } else { + bsendmsg(ua, "%s", db_strerror(ua->db)); + ok = FALSE; + } } } else { bsendmsg(ua, _("Label command failed.\n")); diff --git a/bacula/src/lib/bsys.c b/bacula/src/lib/bsys.c index da3fd7c176..8e66a9adf9 100644 --- a/bacula/src/lib/bsys.c +++ b/bacula/src/lib/bsys.c @@ -389,12 +389,12 @@ static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t timer = PTHREAD_COND_INITIALIZER; /* - * This routine will sleep (sec, msec). Note, however, that if a + * This routine will sleep (sec, microsec). Note, however, that if a * signal occurs, it will return early. It is up to the caller * to recall this routine if he/she REALLY wants to sleep the * requested time. */ -int bmicrosleep(time_t sec, long msec) +int bmicrosleep(time_t sec, long usec) { struct timespec timeout; struct timeval tv; @@ -402,7 +402,7 @@ int bmicrosleep(time_t sec, long msec) int stat; timeout.tv_sec = sec; - timeout.tv_nsec = msec * 1000; + timeout.tv_nsec = usec * 1000; #ifdef HAVE_NANOSLEEP stat = nanosleep(&timeout, NULL); diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index d4abd6a481..8f8bbf4218 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -53,7 +53,7 @@ int pool_sprintf (char *pool_buf, char *fmt, ...); void create_pid_file (char *dir, char *progname, int port); int delete_pid_file (char *dir, char *progname, int port); void drop (char *uid, char *gid); -int bmicrosleep (time_t sec, long msec); +int bmicrosleep (time_t sec, long usec); char *bfgets (char *s, int size, FILE *fd); void make_unique_filename (POOLMEM **name, int Id, char *what); #ifndef HAVE_STRTOLL diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index a73ce428c6..e67a8d770e 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -283,33 +283,30 @@ int do_append_data(JCR *jcr) static bool is_spooled(JCR *jcr) { - if (jcr->spool_attributes && jcr->dir_bsock->spool_fd) { - return true; - } - return false; + return jcr->spool_attributes && jcr->dir_bsock->spool_fd; } static int begin_attribute_spool(JCR *jcr) { if (!jcr->no_attributes && jcr->spool_attributes) { - return 0; + return open_spool_file(jcr, jcr->dir_bsock); } - return open_spool_file(jcr, jcr->dir_bsock); + return 1; } static int discard_attribute_spool(JCR *jcr) { - if (!is_spooled(jcr)) { - return 0; + if (is_spooled(jcr)) { + return close_spool_file(jcr, jcr->dir_bsock); } - return close_spool_file(jcr, jcr->dir_bsock); + return 1; } static int commit_attribute_spool(JCR *jcr) { - if (!is_spooled(jcr)) { - return 0; + if (is_spooled(jcr)) { + bnet_despool(jcr->dir_bsock); + return close_spool_file(jcr, jcr->dir_bsock); } - bnet_despool(jcr->dir_bsock); - return close_spool_file(jcr, jcr->dir_bsock); + return 1; } diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 1ea2a85d1c..bdb2fab383 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -127,6 +127,18 @@ DEV_BLOCK *new_block(DEVICE *dev) return block; } +/* + * Only the first block checksum error was reported. + * If there are more, report it now. + */ +void print_block_errors(JCR *jcr, DEV_BLOCK *block) +{ + if (block->checksum_errors > 1) { + Jmsg(jcr, M_ERROR, 0, _("%d block checksum errors ignored.\n"), + block->checksum_errors); + } +} + /* * Free block */ @@ -180,13 +192,13 @@ static void ser_block_header(DEV_BLOCK *block) } /* - * Unserialized the block header for reading block. + * Unserialize the block header for reading block. * This includes setting all the buffer pointers correctly. * * Returns: 0 on failure (not a block) * 1 on success */ -static int unser_block_header(DEVICE *dev, DEV_BLOCK *block) +static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) { ser_declare; char Id[BLKHDR_ID_LENGTH+1]; @@ -260,7 +272,10 @@ static int unser_block_header(DEVICE *dev, DEV_BLOCK *block) CheckSum); Mmsg3(&dev->errmsg, _("Block checksum mismatch in block %u: calc=%x blk=%x\n"), (unsigned)BlockNumber, BlockCheckSum, CheckSum); - return 0; + if (block->checksum_errors == 0) { + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + } + block->checksum_errors++; } } return 1; @@ -630,7 +645,8 @@ reread: } BlockNumber = block->BlockNumber + 1; - if (!unser_block_header(dev, block)) { + if (!unser_block_header(jcr, dev, block)) { + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); block->read_len = 0; return 0; } @@ -673,8 +689,8 @@ reread: } if (block->block_len > block->read_len) { - Mmsg2(&dev->errmsg, _("Short block of %d bytes on device %s discarded.\n"), - block->read_len, dev->dev_name); + Mmsg3(&dev->errmsg, _("Short block at %u of %d bytes on device %s discarded.\n"), + dev->block_num, block->read_len, dev->dev_name); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); dev->state |= ST_SHORT; /* set short block */ block->read_len = block->binbuf = 0; diff --git a/bacula/src/stored/block.h b/bacula/src/stored/block.h index e52e075079..6827457935 100644 --- a/bacula/src/stored/block.h +++ b/bacula/src/stored/block.h @@ -99,6 +99,7 @@ struct DEV_BLOCK { int BlockVer; /* block version 1 or 2 */ bool write_failed; /* set if write failed */ bool block_read; /* set when block read */ + int checksum_errors; /* count of block checksum errors */ int32_t FirstIndex; /* first index this block */ int32_t LastIndex; /* last index this block */ char *bufp; /* pointer into buffer */ diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index adad6a0c36..897ff9e664 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -83,6 +83,7 @@ static time_t lasttime = 0; static char *db_name = "bacula"; static char *db_user = "bacula"; static char *db_password = ""; +static char *db_host = NULL; static char *wd = NULL; static int update_db = 0; static int update_vol_info = 0; @@ -106,6 +107,7 @@ static void usage() " -n name specify the database name (default bacula)\n" " -u user specify database user name (default bacula)\n" " -p password specify database password (default none)\n" +" -h host specify database host (default NULL)\n" " -r list records\n" " -s synchronize or store in database\n" " -v verbose\n" @@ -125,7 +127,7 @@ int main (int argc, char *argv[]) init_msg(NULL, NULL); - while ((ch = getopt(argc, argv, "b:c:d:mn:p:rsu:vV:w:?")) != -1) { + while ((ch = getopt(argc, argv, "b:c:d:h:mn:p:rsu:vV:w:?")) != -1) { switch (ch) { case 'b': bsr = parse_bsr(NULL, optarg); @@ -144,6 +146,10 @@ int main (int argc, char *argv[]) debug_level = 1; break; + case 'h': + db_host = optarg; + break; + case 'm': update_vol_info = 1; break; @@ -233,7 +239,7 @@ int main (int argc, char *argv[]) exit(1); } - if ((db=db_init_database(NULL, db_name, db_user, db_password, NULL, 0, NULL)) == NULL) { + if ((db=db_init_database(NULL, db_name, db_user, db_password, db_host, 0, NULL)) == NULL) { Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n")); } if (!db_open_database(NULL, db)) { diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 91a6ac3c17..143ee339bb 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -100,7 +100,7 @@ static struct s_cmds cmds[] = { /* * Connection request. We accept connections either from the - * Director or a Client. + * Director or a Client (File daemon). * * Note, we are running as a seperate thread of the Storage daemon. * and it is because a Director has made a connection with @@ -108,6 +108,7 @@ static struct s_cmds cmds[] = { * * Basic tasks done here: * - Create a JCR record + * - If it was from the FD, call handle_filed_connection() * - Authenticate the Director * - We wait for a command * - We execute the command @@ -127,11 +128,15 @@ void *connection_request(void *arg) } /* - * See if this is a File daemon connection + * Do a sanity check on the message received */ - if (bs->msglen < 25 || bs->msglen > (int)sizeof(name)+25) { + if (bs->msglen < 25 || bs->msglen > (int)sizeof(name)-25) { Emsg1(M_ERROR, 0, _("Invalid Dir connection. Len=%d\n"), bs->msglen); } + /* + * See if this is a File daemon connection. If so + * call FD handler. + */ if (sscanf(bs->msg, "Hello Start Job %127s calling\n", name) == 1) { handle_filed_connection(bs, name); return NULL; diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 37f732732b..664e3f4909 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -182,36 +182,14 @@ int job_cmd(JCR *jcr) } /* - * This entry point is only called if we have a separate - * Storage Daemon Data port. Otherwise, the connection - * is made to the main port, and if it is a File daemon - * calling, handle_filed_connection() is called directly. - */ -void connection_from_filed(void *arg) -{ - BSOCK *fd = (BSOCK *)arg; - char job_name[MAX_NAME_LENGTH]; - - Dmsg0(110, "enter connection_from_filed\n"); - if (bnet_recv(fd) <= 0) { - Emsg0(M_FATAL, 0, _("Unable to authenticate Client.\n")); - return; - } - Dmsg1(100, "got: %s\n", fd->msg); - - if (fd->msglen < 17 || fd->msglen > 17+127 || - sscanf(fd->msg, "Hello Start Job %127s\n", job_name) != 1) { - Emsg1(M_FATAL, 0, _("Bad Hello from FD: %s\n"), fd->msg); - return; - } - handle_filed_connection(fd, job_name); - return; -} - + * After receiving a connection (in job.c) if it is + * from the File daemon, this routine is called. + */ void handle_filed_connection(BSOCK *fd, char *job_name) { JCR *jcr; + bmicrosleep(0, 50000); /* wait 50 millisecs */ if (!(jcr=get_jcr_by_full_name(job_name))) { Jmsg1(NULL, M_FATAL, 0, _("Job name not found: %s\n"), job_name); return; diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 8a58a97711..8ad2262660 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,92 +28,93 @@ uint32_t new_VolSessionId(); /* From acquire.c */ -DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int release_device(JCR *jcr, DEVICE *dev); +DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int release_device(JCR *jcr, DEVICE *dev); /* From askdir.c */ enum get_vol_info_rw { GET_VOL_INFO_FOR_WRITE, GET_VOL_INFO_FOR_READ }; -int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw); -int dir_find_next_appendable_volume(JCR *jcr); -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int label); -int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev); -int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); -int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); -int dir_send_job_status(JCR *jcr); -int dir_create_jobmedia_record(JCR *jcr); +int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw); +int dir_find_next_appendable_volume(JCR *jcr); +int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int label); +int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev); +int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); +int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); +int dir_send_job_status(JCR *jcr); +int dir_create_jobmedia_record(JCR *jcr); /* authenticate.c */ -int authenticate_director(JCR *jcr); -int authenticate_filed(JCR *jcr); +int authenticate_director(JCR *jcr); +int authenticate_filed(JCR *jcr); /* From block.c */ -void dump_block(DEV_BLOCK *b, char *msg); +void dump_block(DEV_BLOCK *b, char *msg); DEV_BLOCK *new_block(DEVICE *dev); -void init_block_write(DEV_BLOCK *block); -void empty_block(DEV_BLOCK *block); -void free_block(DEV_BLOCK *block); -int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void init_block_write(DEV_BLOCK *block); +void empty_block(DEV_BLOCK *block); +void free_block(DEV_BLOCK *block); +int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void print_block_errors(JCR *jcr, DEV_BLOCK *block); #define CHECK_BLOCK_NUMBERS true #define NO_BLOCK_NUMBER_CHECK false -int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); -int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); +int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); +int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers); /* From butil.c -- utilities for SD tool programs */ -void print_ls_output(char *fname, char *link, int type, struct stat *statp); +void print_ls_output(char *fname, char *link, int type, struct stat *statp); JCR *setup_jcr(char *name, char *device, BSR *bsr, char *VolumeName); DEVICE *setup_to_access_device(JCR *jcr, int read_access); -void display_tape_error_status(JCR *jcr, DEVICE *dev); +void display_tape_error_status(JCR *jcr, DEVICE *dev); DEVRES *find_device_res(char *device_name, int read_access); /* From dev.c */ -DEVICE *init_dev(DEVICE *dev, DEVRES *device); -int open_dev(DEVICE *dev, char *VolName, int mode); -void close_dev(DEVICE *dev); -void force_close_dev(DEVICE *dev); -int truncate_dev(DEVICE *dev); -void term_dev(DEVICE *dev); -char * strerror_dev(DEVICE *dev); -void clrerror_dev(DEVICE *dev, int func); -int update_pos_dev(DEVICE *dev); -int rewind_dev(DEVICE *dev); -int load_dev(DEVICE *dev); -int offline_dev(DEVICE *dev); -int flush_dev(DEVICE *dev); -int weof_dev(DEVICE *dev, int num); -int write_block(DEVICE *dev); -int write_dev(DEVICE *dev, char *buf, size_t len); -int read_dev(DEVICE *dev, char *buf, size_t len); -int status_dev(DEVICE *dev, uint32_t *status); -int eod_dev(DEVICE *dev); -int fsf_dev(DEVICE *dev, int num); -int fsr_dev(DEVICE *dev, int num); -int bsf_dev(DEVICE *dev, int num); -int bsr_dev(DEVICE *dev, int num); -void attach_jcr_to_device(DEVICE *dev, JCR *jcr); -void detach_jcr_from_device(DEVICE *dev, JCR *jcr); -JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); -int dev_can_write(DEVICE *dev); -int offline_or_rewind_dev(DEVICE *dev); -int reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); +DEVICE *init_dev(DEVICE *dev, DEVRES *device); +int open_dev(DEVICE *dev, char *VolName, int mode); +void close_dev(DEVICE *dev); +void force_close_dev(DEVICE *dev); +int truncate_dev(DEVICE *dev); +void term_dev(DEVICE *dev); +char * strerror_dev(DEVICE *dev); +void clrerror_dev(DEVICE *dev, int func); +int update_pos_dev(DEVICE *dev); +int rewind_dev(DEVICE *dev); +int load_dev(DEVICE *dev); +int offline_dev(DEVICE *dev); +int flush_dev(DEVICE *dev); +int weof_dev(DEVICE *dev, int num); +int write_block(DEVICE *dev); +int write_dev(DEVICE *dev, char *buf, size_t len); +int read_dev(DEVICE *dev, char *buf, size_t len); +int status_dev(DEVICE *dev, uint32_t *status); +int eod_dev(DEVICE *dev); +int fsf_dev(DEVICE *dev, int num); +int fsr_dev(DEVICE *dev, int num); +int bsf_dev(DEVICE *dev, int num); +int bsr_dev(DEVICE *dev, int num); +void attach_jcr_to_device(DEVICE *dev, JCR *jcr); +void detach_jcr_from_device(DEVICE *dev, JCR *jcr); +JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); +int dev_can_write(DEVICE *dev); +int offline_or_rewind_dev(DEVICE *dev); +int reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); /* Get info about device */ -char * dev_name(DEVICE *dev); -char * dev_vol_name(DEVICE *dev); +char * dev_name(DEVICE *dev); +char * dev_vol_name(DEVICE *dev); uint32_t dev_block(DEVICE *dev); uint32_t dev_file(DEVICE *dev); -int dev_is_tape(DEVICE *dev); +int dev_is_tape(DEVICE *dev); /* From device.c */ -int open_device(DEVICE *dev); -int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int open_device(DEVICE *dev); +int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); void _lock_device(char *file, int line, DEVICE *dev); void _unlock_device(char *file, int line, DEVICE *dev); void _block_device(char *file, int line, DEVICE *dev, int state); @@ -125,45 +126,45 @@ void set_new_file_parameters(JCR *jcr, DEVICE *dev); int device_is_unmounted(DEVICE *dev); /* From dircmd.c */ -void *connection_request(void *arg); +void *connection_request(void *arg); /* From fd_cmds.c */ -void run_job(JCR *jcr); +void run_job(JCR *jcr); /* From job.c */ -void stored_free_jcr(JCR *jcr); -void connection_from_filed(void *arg); -void handle_filed_connection(BSOCK *fd, char *job_name); +void stored_free_jcr(JCR *jcr); +void connection_from_filed(void *arg); +void handle_filed_connection(BSOCK *fd, char *job_name); /* From label.c */ -int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); -void create_volume_label(DEVICE *dev, char *VolName, char *PoolName); -int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); -int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); -int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void dump_volume_label(DEVICE *dev); -void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); -int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); -int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); +int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); +void create_volume_label(DEVICE *dev, char *VolName, char *PoolName); +int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); +int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); +int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void dump_volume_label(DEVICE *dev); +void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); +int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); +int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); /* From match_bsr.c */ int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, - SESSION_LABEL *sesrec); + SESSION_LABEL *sesrec); int match_bsr_block(BSR *bsr, DEV_BLOCK *block); void position_bsr_block(BSR *bsr, DEV_BLOCK *block); BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); /* From mount.c */ -int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release); -int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void release_volume(JCR *jcr, DEVICE *dev); +int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release); +int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void release_volume(JCR *jcr, DEVICE *dev); /* From autochanger.c */ -int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir); -int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir); -void invalidate_slot_in_catalog(JCR *jcr); +int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir); +int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir); +void invalidate_slot_in_catalog(JCR *jcr); /* From parse_bsr.c */ @@ -178,11 +179,11 @@ extern void create_vol_list(JCR *jcr); /* From record.c */ char *FI_to_ascii(int fi); char *stream_to_ascii(int stream, int fi); -int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); +int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); DEV_RECORD *new_record(); -void free_record(DEV_RECORD *rec); +void free_record(DEV_RECORD *rec); /* From read_record.c */ int read_records(JCR *jcr, DEVICE *dev, diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c index 2dc21358e0..8e34737869 100644 --- a/bacula/src/stored/read_record.c +++ b/bacula/src/stored/read_record.c @@ -266,6 +266,7 @@ int read_records(JCR *jcr, DEVICE *dev, rec = nrec; } delete recs; + print_block_errors(jcr, block); free_block(block); return ok; } diff --git a/bacula/src/version.h b/bacula/src/version.h index 377540ca05..47e2bf31fa 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -2,8 +2,8 @@ #undef VERSION #define VERSION "1.32" #define VSTRING "1" -#define BDATE "20 Sep 2003" -#define LSMDATE "20Sep03" +#define BDATE "26 Sep 2003" +#define LSMDATE "26Sep03" /* Debug flags */ #undef DEBUG -- 2.39.5