+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
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.
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 <working-directory-as-in-Bacula-conf>
+ rm -f *.spool.*
+
+ Please be sure there are no spaces between the asterisks
+ and the periods.
/* 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
*/
#undef HAVE_SYS_NDIR_H
-/* Define to 1 if you have the <sys/ptem.h> header file. */
-#undef HAVE_SYS_PTEM_H
-
-/* Define to 1 if you have the <sys/pte.h> header file. */
-#undef HAVE_SYS_PTE_H
-
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
-/* Define to 1 if you have the <sys/stream.h> header file. */
-#undef HAVE_SYS_STREAM_H
-
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
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
# -----------------------------------------------------------------------
;;
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"
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 <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#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
;;
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"
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.
- 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.
- 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
- 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.
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;
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);
int ok = FALSE;
int mounted = FALSE;
int i;
+ bool media_record_exists = false;
static char *barcode_keyword[] = {
"barcode",
"barcodes",
/* Get a new Volume name */
for ( ;; ) {
+ media_record_exists = false;
if (!get_cmd(ua, _("Enter new Volume name: "))) {
return 1;
}
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 */
}
}
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) {
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);
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
}
mr.Slot = vl->Slot;
- send_label_request(ua, &mr, &omr, &pr, 0);
+ send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists);
}
}
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];
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"));
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;
int stat;
timeout.tv_sec = sec;
- timeout.tv_nsec = msec * 1000;
+ timeout.tv_nsec = usec * 1000;
#ifdef HAVE_NANOSLEEP
stat = nanosleep(&timeout, NULL);
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
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;
}
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
*/
}
/*
- * 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];
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;
}
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;
}
}
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;
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 */
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;
" -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"
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);
debug_level = 1;
break;
+ case 'h':
+ db_host = optarg;
+ break;
+
case 'm':
update_vol_info = 1;
break;
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)) {
/*
* 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
*
* 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
}
/*
- * 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;
}
/*
- * 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;
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);
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 */
/* 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,
rec = nrec;
}
delete recs;
+ print_block_errors(jcr, block);
free_block(block);
return ok;
}
#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