+13Mar04
+- Added two tar files that Phil sent for adding slackware support.
+ Thanks Phil and Matt Howard.
+- Fix relabel command -- || should have been &&.
+- Correct once more the scheduling algorithm -- this time it should
+ be much better.
+12Mar04
+- Implement simple spool statistics printed by "status sd".
+- Cleanup/add spool error messages.
+- On multiple ctl-c, exit from console quickly.
+- Implement code to select a different Volume in the SD if the
+ current Volume is busy -- requested by Patrick Cole.
+- Change postgreSQL make tables to use bigint instead of integer
+ for StartBlock and EndBlock because
+ there is no unsigned integer in postgreSQL and these fields use 32 bits.
+- Implement multiple drive autochanger support -- prompted by email of
+ Patrick Cole.
+11Mar04
+- Update version and date in Win32 build.
+- Fix bug in run_conf with month range zapping wday and wom.
+- Correct editing of port for PQsetdbLogin in postgresql.c as reported
+ by J. Conroy, and do a second try.
+10Mar04
+- Integrate Phil's Makefile patch.
+- Add SpoolDirectory to SD Device resource.
+- Add MaximumJobSpoolSize to SD Device resource.
+- Add MaximumSpoolSize to SD Device resource.
+- Implement the above.
+- Make despooling lock the device so only it writes
+ to the device during despooling.
+09Mar04
+- Data spooling now passes the regression tests.
+- Added "Files Expected" to the restore job report.
+- Implemented SpoolData = yes/no in the Job resource
+- Implemented SpoolData = yes/no in the Run overrides.
+- Note, you must have a 1.33.4-09Mar05 SD or later with the Director since
+ the DIR->SD protocol has changed to support data spooling.
+- Remove the confusing "Which DBMS do you want to use (please select only one):"
+ messages from ./configure.
+- Fix broken Jmsg with missing argument in find_one.c
+08Mar04
+- Second cut data spooling code.
+- Fix missing piece of yesterday's patch.
+07Mar04
+- Integrate patches supplied by Jason Conroy that fix Slot numbers
+ getting lost.
+06Mar04
+- This version contains a *major* addition to the SD structures.
+ Many variables have been moved out of the JCR into a new DCR
+ (Device Context Record). This required quite a few changes, and
+ introduced a bit of instability. In the end, after a few more
+ rounds of changes, the DCR will replace virtually all arguments
+ to the low level SD read/write routines. This change permits
+ (with a bit more code) the SD to write to multiple devices at
+ the same time for a single Job. It also facilitates adding the
+ data spooling code.
+- Added a patch that fixed the port specification for postgresql.
+- Fixed findlib/find_one.c so that it will complain about backing
+ up a hard linked file twice, which makes a restore impossible.
+- Tighten up permissions on pid file.
+- Attempt to avoid warnings when casting 64 bit pointers to an
+ integer.
+- Added skeleton code for data spooling.
+- Make sure spooled attributes are discarded on error.
+03Mar04
+- Updated getdiskinfo in rescue/linux to handle the fact that the
+ sfdisk -s option now includes info on partitions. Also, before
+ creating the diskinfo files, clean out the old ones.
+02Mar04
+- Add debug and error output to jobq.c
+- Fix some minor errors in debug output of scheduler.c
+- Add "trace on/off" command and modify trace code in message.c
+ to work off trace flag rather than #defines.
+01Mar04
+- If console is found during install warn user (new name is bconsole).
+- On install copy console.conf to bconsole.conf if it exists.
+- Make RunAfterJob error non-fatal.
+- Rework minor details in status output.
+- Attempt to define all values for "consoles" in JCR to avoid
+ confusion.
+28Feb04
+- Use net start bacula to start Bacula on WinXP/NT/2K
+ systems after installation.
+- Change a few strcpy()s to bstrncpy()s in signal.
+- Add "gui on/off" command to console to turn on gui mode,
+ which will adapt Bacula better to batch or gui programs.
+ Currently, it prevents commas from being inserted into
+ numbers in the list command.
+- Tweak some of the Makefiles so that the install is done with
+ the right program (nothing really changed).
+- Install logrotate in the "make autostart" of Bacula on RedHat.
+- Implement SIGHUP while jobs are running. It *seems* to work but is
+ a bit fragile and still crashes if you push it. More work needed.
+- Applied Phil's GNOME 1.4 patch. Very clean. Thanks Phil.
+- Major updates to the native Win32 installer.
+27Feb04
+- Restructure free of conf resources to handle job_end_push()
+ and SIGHUP. Lots of changes little substance.
+26Feb04
+- Add mtimeonly=yes/no and keepatime=yes/no to Include list
+ 1.33 style.
+- Allow no modifier in time and size specifications.
+- Attempt to implement disk seeking. More work needed.
+- Implement more in win32 installer and test it.
+25Feb04
+- Implement kb, mb, and gb modifiers for size, which mean
+ 1,000 bytes, 1,000,000, ... bytes.
+- Add Makefile to src/win32 to allow building the full
+ release -- it calls nmake where appropriate.
+- Remove the rsi directory from win32 as suggested by Christopher
+- Add Michel Meyers' nsi file to win32 and integrate it with
+ the build.
+24Feb04
+- Add the frigging _O_BINARY to the right variable. Win32 works!
+- Add debug code to state file. There is a problem with Win32 read
+ returning one byte less than it should.
+- Implement a number of new functions for alist so that it has
+ equivalent functionality to dlist. It will be used for
+ job_end_push().
+- More work on state file.
+- Added a popup message box on Windows if Bacula Aborts.
+- Attempt to shutdown the FD server, but doesn't work on Windows. This
+ would have given a cleaner shutdown, no problem.
+23Feb04
+- Update projects
+- Attempt to fix state file on Win32 -- no luck.
+- Add HPUX tweaks to configure.in
+- Update quickstart and install.wml of doc.
+- Eliminate extern int h_errno from bnet.c by including netdb.h
+- Eliminate NumJobs from last_job structure so that FD and SD
+ correctly report what is in the state file.
+22Feb04
+- Implement daemon state file, and save/restore last_jobs list.
+- Fix time routines in win32 compat.cpp
+- Fix a bug of not checking the bpipe_open() status in do_shell_expansion().
21Feb04
- Add Volker's bacula script to the SuSE directory and convert it
to bacula.in
FullPool=xxx
IncrementalPool=xxx
DifferentialPool=xxx
+- SpoolData=yes/no in DIR Job resource
+- SpoolData=yes/no in Run override directive.
+- MaximumSpoolSize in SD Device resource
+- MaximumSpoolJobSize in SD Device resource
+- SpoolDirectory in SD Device resource.
New Commands:
- "SetIP"
- "markdir" command in restore tree.
- "unmarkdir" command in restore tree.
- "quit" command in restore tree.
+- Trace option on "setdebug trace=1/0 ..."
+
Most Significant Changes since 1.32f-4
- Add a missing unlock in the jobq handler.
platforms/gentoo/bacula-sd \
platforms/gentoo/bacula-dir"
;;
-
slackware)
DISTVER=`cat /etc/slackware-version`
TAPEDRIVE="/dev/nst0"
PSCMD="ps -e -o pid,command"
+ PFILES="${PFILES} \
+ platforms/slackware/Makefile \
+ platforms/slackware/rc.bacula-fd \
+ platforms/slackware/rc.bacula-sd \
+ platforms/slackware/rc.bacula-dir\
+ platforms/slackware/functions.bacula"
;;
solaris)
DISTVER=`uname -r`
platforms/gentoo/bacula-sd \
platforms/gentoo/bacula-dir"
;;
-
slackware)
DISTVER=`cat /etc/slackware-version`
TAPEDRIVE="/dev/nst0"
PSCMD="ps -e -o pid,command"
+ PFILES="${PFILES} \
+ platforms/slackware/Makefile \
+ platforms/slackware/rc.bacula-fd \
+ platforms/slackware/rc.bacula-sd \
+ platforms/slackware/rc.bacula-dir\
+ platforms/slackware/functions.bacula"
;;
solaris)
DISTVER=`uname -r`
INSTALL = @INSTALL@
SUBDIRS = freebsd redhat solaris unknown openbsd irix gentoo \
- darwin aix bsdi mandrake
+ darwin aix bsdi mandrake slackware
MAKE = make
--- /dev/null
+#
+# This file is used as the template to create the
+# Makefile for the Slackware specific installation.
+#
+# 22 January 2003 -- Kern Sibbald
+# and corrected for Gentoo by
+# Patrick Naubert 25 Jan 2003
+# and reworked for Slackware by
+# Matt Howard 09 Mar 2004
+#
+# for Bacula release @VERSION@ (@DATE@) -- @DISTNAME@
+#
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+
+nothing:
+
+install: install-autostart
+
+install-autostart: install-autostart-fd install-autostart-sd install-autostart-dir
+
+install-autostart-fd: install-autostart-rc
+ @$(INSTALL) -m 744 rc.bacula-fd $(DESTDIR)/etc/rc.d/rc.bacula-fd
+
+install-autostart-sd: install-autostart-rc
+ @$(INSTALL) -m 744 rc.bacula-sd $(DESTDIR)/etc/rc.d/rc.bacula-sd
+
+install-autostart-dir: install-autostart-rc
+ @$(INSTALL) -m 744 rc.bacula-dir $(DESTDIR)/etc/rc.d/rc.bacula-dir
+
+install-autostart-rc:
+ @$(INSTALL) -m 744 functions.bacula $(DESTDIR)/etc/rc.d
+ ./add-remove-rc.local.pl -a $(DESTDIR)
+
+
+uninstall: uninstall-autostart
+
+uninstall-autostart: uninstall-autostart-fd uninstall-autostart-sd uninstall-autostart-dir
+
+uninstall-autostart-fd: uninstall-autostart-rc
+ @rm -f $(DESTDIR)/etc/rc.d/rc.bacula-fd
+
+uninstall-autostart-sd: uninstall-autostart-rc
+ @rm -f $(DESTDIR)/etc/rc.d/rc.bacula-sd
+
+uninstall-autostart-dir: uninstall-autostart-rc
+ @rm -f $(DESTDIR)/etc/rc.d/rc.bacula-dir
+
+uninstall-autostart-rc:
+ @rm -f $(DESTDIR)/etc/rc.d/functions.bacula
+ ./add-remove-rc.local.pl -r $(DESTDIR)
+
+
+clean:
+ @rm -f rc.bacula-sd rc.bacula-fd rc.bacula-dir
+
+distclean: clean
+ @rm -f Makefile
+ @rm -rf CVS
+
+devclean: clean
+ @rm -f Makefile
--- /dev/null
+#! /bin/sh
+#
+# bacula This shell script takes care of starting and stopping
+# the bacula daemons.
+#
+# This is pretty much watered down version of the RedHat script
+# that works on Solaris as well as Linux, but it won't work everywhere.
+#
+# description: It comes by night and sucks the vital essence from your computers.
+#
+
+PSCMD="@PSCMD@"
+
+# All these are not *really* needed but it makes it
+# easier to "steal" this code for the development
+# environment where they are different.
+#
+BACFDBIN=@sbindir@
+BACFDCFG=@sysconfdir@
+BACSDBIN=@sbindir@
+BACSDCFG=@sysconfdir@
+BACDIRBIN=@sbindir@
+BACDIRCFG=@sysconfdir@
+PIDDIR=@piddir@
+SUBSYSDIR=@subsysdir@
+
+DIR_PORT=@dir_port@
+FD_PORT=@fd_port@
+SD_PORT=@sd_port@
+
+DIR_USER=@dir_user@
+DIR_GROUP=@dir_group@
+FD_USER=@fd_user@
+FD_GROUP=@fd_group@
+SD_USER=@sd_user@
+SD_GROUP=@sd_group@
+
+# A function to stop a program.
+killproc() {
+ RC=0
+ # Test syntax.
+ if [ $# = 0 ]; then
+ echo "Usage: killproc {program} [signal]"
+ return 1
+ fi
+
+ notset=0
+ # check for third arg to be kill level
+ if [ "$3" != "" ] ; then
+ killlevel=$3
+ else
+ notset=1
+ killlevel="-9"
+ fi
+
+ # Get base program name
+ base=`basename $1`
+
+ # Find pid.
+ pid=`pidofproc $base $2`
+
+ # Kill it.
+ if [ "$pid" != "" ] ; then
+ if [ "$notset" = "1" ] ; then
+ if ps -p $pid>/dev/null 2>&1; then
+ # TERM first, then KILL if not dead
+ kill -TERM $pid 2>/dev/null
+ sleep 1
+ if ps -p $pid >/dev/null 2>&1 ; then
+ sleep 1
+ if ps -p $pid >/dev/null 2>&1 ; then
+ sleep 3
+ if ps -p $pid >/dev/null 2>&1 ; then
+ kill -KILL $pid 2>/dev/null
+ fi
+ fi
+ fi
+ fi
+ ps -p $pid >/dev/null 2>&1
+ RC=$?
+ [ $RC -eq 0 ] && failure "$base shutdown" || success "$base shutdown"
+ # RC=$((! $RC))
+ # use specified level only
+ else
+ if ps -p $pid >/dev/null 2>&1; then
+ kill $killlevel $pid 2>/dev/null
+ RC=$?
+ [ $RC -eq 0 ] && success "$base $killlevel" || failure "$base $killlevel"
+ fi
+ fi
+ else
+ failure "$base shutdown"
+ fi
+ # Remove pid file if any.
+ if [ "$notset" = "1" ]; then
+ rm -f ${PIDDIR}/$base.$2.pid
+ fi
+ return $RC
+}
+
+# A function to find the pid of a program.
+pidofproc() {
+ pid=""
+ # Test syntax.
+ if [ $# = 0 ] ; then
+ echo "Usage: pidofproc {program}"
+ return 1
+ fi
+
+ # Get base program name
+ base=`basename $1`
+
+ # First try PID file
+ if [ -f ${PIDDIR}/$base.$2.pid ] ; then
+ pid=`head -1 ${PIDDIR}/$base.$2.pid`
+ if [ "$pid" != "" ] ; then
+ echo $pid
+ return 0
+ fi
+ fi
+
+ # Next try "pidof"
+ if [ -x /sbin/pidof ] ; then
+ pid=`/sbin/pidof $1`
+ fi
+ if [ "$pid" != "" ] ; then
+ echo $pid
+ return 0
+ fi
+
+ # Finally try to extract it from ps
+ ${PSCMD} | grep $1 | awk '{ print $1 }' | tr '\n' ' '
+ return 0
+}
+
+status() {
+ # Test syntax.
+ if [ $# = 0 ] ; then
+ echo "Usage: status {program}"
+ return 1
+ fi
+
+ # Get base program name
+ base=`basename $1`
+
+ # First try "pidof"
+ if [ -x /sbin/pidof ] ; then
+ pid=`/sbin/pidof $1`
+ fi
+ if [ "$pid" != "" ] ; then
+ echo "$base (pid $pid) is running..."
+ return 0
+ else
+ pid=`${PSCMD} | awk 'BEGIN { prog=ARGV[1]; ARGC=1 }
+ { if ((prog == $2) || (("(" prog ")") == $2) ||
+ (("[" prog "]") == $2) ||
+ ((prog ":") == $2)) { print $1 ; exit 0 } }' $1`
+ if [ "$pid" != "" ] ; then
+ echo "$base (pid $pid) is running..."
+ return 0
+ fi
+ fi
+
+ # Next try the PID files
+ if [ -f ${PIDDIR}/$base.$2.pid ] ; then
+ pid=`head -1 ${PIDDIR}/$base.$2.pid`
+ if [ "$pid" != "" ] ; then
+ echo "$base dead but pid file exists"
+ return 1
+ fi
+ fi
+ # See if the subsys lock exists
+ if [ -f ${SUBSYSDIR}/$base ] ; then
+ echo "$base dead but subsys locked"
+ return 2
+ fi
+ echo "$base is stopped"
+ return 3
+}
+
+success() {
+ return 0
+}
+
+failure() {
+ rc=$?
+ return $rc
+}
+
+
--- /dev/null
+#! /bin/sh
+#
+# bacula This shell script takes care of starting and stopping
+# the bacula Director daemon
+#
+# chkconfig: 2345 92 99
+# description: It comes by night and sucks the vital essence from your computers.
+#
+# For Bacula release @VERSION@ (@DATE@) -- @DISTNAME@
+#
+
+# Source function library
+. /etc/rc.d/functions.bacula
+
+case "$1" in
+ start)
+ [ -x ${BACDIRBIN}/bacula-dir ] && {
+ sleep 2
+ echo -n "Starting the Director daemon: "
+ OPTIONS=''
+ if [ "${DIR_USER}" != '' ]; then
+ OPTIONS="${OPTIONS} -u ${DIR_USER}"
+ fi
+
+ if [ "${DIR_GROUP}" != '' ]; then
+ OPTIONS="${OPTIONS} -g ${DIR_GROUP}"
+ fi
+
+ ${BACDIRBIN}/bacula-dir $2 ${OPTIONS} -v -c ${BACDIRCFG}/bacula-dir.conf
+ echo Done.
+ }
+ ;;
+ stop)
+ [ -x ${BACDIRBIN}/bacula-dir ] && {
+ echo -n "Stopping the Director daemon: "
+ killproc ${BACDIRBIN}/bacula-dir ${DIR_PORT}
+ echo Done.
+ }
+ ;;
+ restart)
+ $0 stop
+ sleep 5
+ $0 start
+ ;;
+ status)
+ [ -x ${BACDIRBIN}/bacula-dir ] && status ${BACDIRBIN}/bacula-dir ${DIR_PORT}
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|status}"
+ exit 1
+ ;;
+esac
+exit 0
--- /dev/null
+#! /bin/sh
+#
+# bacula This shell script takes care of starting and stopping
+# the bacula File daemon.
+#
+# chkconfig: 2345 91 99
+# description: It comes by night and sucks the vital essence from your computers.
+#
+# For Bacula release @VERSION@ (@DATE@) -- @DISTNAME@
+#
+
+# Source function library
+. /etc/rc.d/functions.bacula
+
+case "$1" in
+ start)
+ [ -x ${BACFDBIN}/bacula-fd ] && {
+ sleep 2
+ echo -n "Starting the File daemon: "
+ OPTIONS=''
+ if [ "${FD_USER}" != '' ]; then
+ OPTIONS="${OPTIONS} -u ${FD_USER}"
+ fi
+
+ if [ "${FD_GROUP}" != '' ]; then
+ OPTIONS="${OPTIONS} -g ${FD_GROUP}"
+ fi
+
+ ${BACFDBIN}/bacula-fd $2 ${OPTIONS} -v -c ${BACFDCFG}/bacula-fd.conf
+ echo Done.
+ }
+ ;;
+ stop)
+ [ -x ${BACFDBIN}/bacula-fd ] && {
+ echo -n "Stopping the File daemon: "
+ killproc ${BACFDBIN}/bacula-fd ${FD_PORT}
+ echo Done.
+ }
+ ;;
+ restart)
+ $0 stop
+ sleep 5
+ $0 start
+ ;;
+ status)
+ [ -x ${BACFDBIN}/bacula-fd ] && status ${BACFDBIN}/bacula-fd ${FD_PORT}
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|status}"
+ exit 1
+ ;;
+esac
+exit 0
+
--- /dev/null
+#! /bin/sh
+#
+# bacula This shell script takes care of starting and stopping
+# the bacula Storage daemon.
+#
+# chkconfig: 2345 90 99
+# description: It comes by night and sucks the vital essence from your computers.
+#
+# For Bacula release @VERSION@ (@DATE@) -- @DISTNAME@
+#
+
+# Source function library
+. /etc/rc.d/functions.bacula
+
+case "$1" in
+ start)
+ [ -x ${BACSDBIN}/bacula-sd ] && {
+ sleep 2
+ echo -n "Starting the Storage daemon: "
+ OPTIONS=''
+ if [ "${SD_USER}" != '' ]; then
+ OPTIONS="${OPTIONS} -u ${SD_USER}"
+ fi
+
+ if [ "${SD_GROUP}" != '' ]; then
+ OPTIONS="${OPTIONS} -g ${SD_GROUP}"
+ fi
+
+ ${BACSDBIN}/bacula-sd $2 ${OPTIONS} -v -c ${BACSDCFG}/bacula-sd.conf
+ echo Done.
+ }
+ ;;
+ stop)
+ [ -x ${BACSDBIN}/bacula-sd ] && {
+ echo -n "Stopping the Storage daemon: "
+ killproc ${BACSDBIN}/bacula-sd ${SD_PORT}
+ echo Done.
+ }
+ ;;
+ restart)
+ $0 stop
+ sleep 5
+ $0 start
+ ;;
+ status)
+ [ -x ${BACSDBIN}/bacula-sd ] && status ${BACSDBIN}/bacula-sd ${SD_PORT}
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|status}"
+ exit 1
+ ;;
+esac
+exit 0
+
+
dlist *last_jobs = NULL;
static const int max_last_jobs = 10;
-static JCR *jobs = NULL; /* pointer to JCR chain */
-static brwlock_t lock; /* lock for last jobs and JCR chain */
+static JCR *jobs = NULL; /* pointer to JCR chain */
+static brwlock_t lock; /* lock for last jobs and JCR chain */
void init_last_jobs_list()
{
int errstat;
struct s_last_job *job_entry = NULL;
if (!last_jobs) {
- last_jobs = new dlist(job_entry, &job_entry->link);
+ last_jobs = new dlist(job_entry, &job_entry->link);
if ((errstat=rwl_init(&lock)) != 0) {
Emsg1(M_ABORT, 0, _("Unable to initialize jcr_chain lock. ERR=%s\n"),
- strerror(errstat));
+ strerror(errstat));
}
}
struct s_last_job *je;
if (last_jobs) {
foreach_dlist(je, last_jobs) {
- free(je);
+ free(je);
}
delete last_jobs;
last_jobs = NULL;
struct s_last_job *je, job;
uint32_t num;
- Dmsg1(010, "read_last_jobs seek to %d\n", (int)addr);
+ Dmsg1(100, "read_last_jobs seek to %d\n", (int)addr);
if (addr == 0 || lseek(fd, addr, SEEK_SET) < 0) {
return;
}
if (read(fd, &num, sizeof(num)) != sizeof(num)) {
return;
}
- Dmsg1(010, "Read num_items=%d\n", num);
+ Dmsg1(100, "Read num_items=%d\n", num);
if (num > 4 * max_last_jobs) { /* sanity check */
return;
}
for ( ; num; num--) {
if (read(fd, &job, sizeof(job)) != sizeof(job)) {
Dmsg1(000, "Read job entry. ERR=%s\n", strerror(errno));
- return;
+ return;
}
if (job.JobId > 0) {
- je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
- memcpy((char *)je, (char *)&job, sizeof(job));
- if (!last_jobs) {
- init_last_jobs_list();
- }
- last_jobs->append(je);
- if (last_jobs->size() > max_last_jobs) {
- last_jobs->remove(last_jobs->first());
- }
+ je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
+ memcpy((char *)je, (char *)&job, sizeof(job));
+ if (!last_jobs) {
+ init_last_jobs_list();
+ }
+ last_jobs->append(je);
+ if (last_jobs->size() > max_last_jobs) {
+ last_jobs->remove(last_jobs->first());
+ }
}
}
}
struct s_last_job *je;
uint32_t num;
- Dmsg1(010, "write_last_jobs seek to %d\n", (int)addr);
+ Dmsg1(100, "write_last_jobs seek to %d\n", (int)addr);
if (lseek(fd, addr, SEEK_SET) < 0) {
return 0;
}
num = last_jobs->size();
if (write(fd, &num, sizeof(num)) != sizeof(num)) {
Dmsg1(000, "Error writing num_items: ERR=%s\n", strerror(errno));
- return 0;
+ return 0;
}
foreach_dlist(je, last_jobs) {
- if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) {
+ if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) {
Dmsg1(000, "Error writing job: ERR=%s\n", strerror(errno));
- return 0;
- }
+ return 0;
+ }
}
}
/* Return current address */
MQUEUE_ITEM *item = NULL;
struct sigaction sigtimer;
- Dmsg0(200, "Enter new_jcr\n");
+ Dmsg0(400, "Enter new_jcr\n");
jcr = (JCR *)malloc(size);
memset(jcr, 0, size);
jcr->msg_queue = new dlist(item, &item->link);
jcr->errmsg = get_pool_memory(PM_MESSAGE);
jcr->errmsg[0] = 0;
/* Setup some dummy values */
- jcr->Job[0] = 0; /* no job name by default */
+ jcr->Job[0] = 0; /* no job name by default */
jcr->JobId = 0;
jcr->JobType = JT_ADMIN;
jcr->JobLevel = L_NONE;
/*
* Remove a JCR from the chain
* NOTE! The chain must be locked prior to calling
- * this routine.
+ * this routine.
*/
static void remove_jcr(JCR *jcr)
{
- Dmsg0(150, "Enter remove_jcr\n");
+ Dmsg0(400, "Enter remove_jcr\n");
if (!jcr) {
Emsg0(M_ABORT, 0, "NULL jcr.\n");
}
- if (!jcr->prev) { /* if no prev */
- jobs = jcr->next; /* set new head */
+ if (!jcr->prev) { /* if no prev */
+ jobs = jcr->next; /* set new head */
} else {
jcr->prev->next = jcr->next; /* update prev */
}
if (jcr->next) {
jcr->next->prev = jcr->prev;
}
- Dmsg0(150, "Leave remove_jcr\n");
+ Dmsg0(400, "Leave remove_jcr\n");
}
/*
last_job.end_time = time(NULL);
/* Keep list of last jobs, but not Console where JobId==0 */
if (last_job.JobId > 0) {
- je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
- memcpy((char *)je, (char *)&last_job, sizeof(last_job));
- if (!last_jobs) {
- init_last_jobs_list();
- }
- last_jobs->append(je);
- if (last_jobs->size() > max_last_jobs) {
- last_jobs->remove(last_jobs->first());
- }
+ je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
+ memcpy((char *)je, (char *)&last_job, sizeof(last_job));
+ if (!last_jobs) {
+ init_last_jobs_list();
+ }
+ last_jobs->append(je);
+ if (last_jobs->size() > max_last_jobs) {
+ last_jobs->remove(last_jobs->first());
+ }
}
break;
default:
}
pthread_mutex_destroy(&jcr->mutex);
- close_msg(jcr); /* close messages for this job */
+ close_msg(jcr); /* close messages for this job */
delete jcr->msg_queue;
/* do this after closing messages */
#ifdef DEBUG
void b_free_jcr(const char *file, int line, JCR *jcr)
{
- Dmsg3(200, "Enter free_jcr 0x%x from %s:%d\n", jcr, file, line);
+ Dmsg3(400, "Enter free_jcr 0x%x from %s:%d\n", jcr, file, line);
#else
void free_jcr(JCR *jcr)
{
- Dmsg1(200, "Enter free_jcr 0x%x\n", jcr);
+ Dmsg1(400, "Enter free_jcr 0x%x\n", jcr);
#endif
lock_jcr_chain();
- jcr->use_count--; /* decrement use count */
+ jcr->use_count--; /* decrement use count */
if (jcr->use_count < 0) {
Emsg2(M_ERROR, 0, _("JCR use_count=%d JobId=%d\n"),
- jcr->use_count, jcr->JobId);
+ jcr->use_count, jcr->JobId);
}
- Dmsg3(200, "Dec free_jcr 0x%x use_count=%d jobid=%d\n", jcr, jcr->use_count, jcr->JobId);
- if (jcr->use_count > 0) { /* if in use */
+ Dmsg3(400, "Dec free_jcr 0x%x use_count=%d jobid=%d\n", jcr, jcr->use_count, jcr->JobId);
+ if (jcr->use_count > 0) { /* if in use */
unlock_jcr_chain();
- Dmsg2(200, "free_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
+ Dmsg2(400, "free_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
return;
}
remove_jcr(jcr);
- job_end_pop(jcr); /* pop and call hooked routines */
+ job_end_pop(jcr); /* pop and call hooked routines */
- Dmsg1(200, "End job=%d\n", jcr->JobId);
+ Dmsg1(400, "End job=%d\n", jcr->JobId);
if (jcr->daemon_free_jcr) {
jcr->daemon_free_jcr(jcr); /* call daemon free routine */
}
free_common_jcr(jcr);
- close_msg(NULL); /* flush any daemon messages */
+ close_msg(NULL); /* flush any daemon messages */
unlock_jcr_chain();
- Dmsg0(200, "Exit free_jcr\n");
+ Dmsg0(400, "Exit free_jcr\n");
}
*/
void free_locked_jcr(JCR *jcr)
{
- jcr->use_count--; /* decrement use count */
- Dmsg2(200, "Dec free_locked_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
- if (jcr->use_count > 0) { /* if in use */
+ jcr->use_count--; /* decrement use count */
+ Dmsg2(400, "Dec free_locked_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
+ if (jcr->use_count > 0) { /* if in use */
return;
}
remove_jcr(jcr);
- jcr->daemon_free_jcr(jcr); /* call daemon free routine */
+ jcr->daemon_free_jcr(jcr); /* call daemon free routine */
free_common_jcr(jcr);
}
/*
- * Given a JobId, find the JCR
+ * Given a JobId, find the JCR
* Returns: jcr on success
- * NULL on failure
+ * NULL on failure
*/
JCR *get_jcr_by_id(uint32_t JobId)
{
- JCR *jcr;
+ JCR *jcr;
- lock_jcr_chain(); /* lock chain */
+ lock_jcr_chain(); /* lock chain */
for (jcr = jobs; jcr; jcr=jcr->next) {
if (jcr->JobId == JobId) {
- P(jcr->mutex);
- jcr->use_count++;
- V(jcr->mutex);
- Dmsg2(200, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
- break;
+ P(jcr->mutex);
+ jcr->use_count++;
+ V(jcr->mutex);
+ Dmsg2(400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
+ break;
}
}
unlock_jcr_chain();
}
/*
- * Given a SessionId and SessionTime, find the JCR
+ * Given a SessionId and SessionTime, find the JCR
* Returns: jcr on success
- * NULL on failure
+ * NULL on failure
*/
JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
{
- JCR *jcr;
+ JCR *jcr;
lock_jcr_chain();
for (jcr = jobs; jcr; jcr=jcr->next) {
if (jcr->VolSessionId == SessionId &&
- jcr->VolSessionTime == SessionTime) {
- P(jcr->mutex);
- jcr->use_count++;
- V(jcr->mutex);
- Dmsg2(200, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
- break;
+ jcr->VolSessionTime == SessionTime) {
+ P(jcr->mutex);
+ jcr->use_count++;
+ V(jcr->mutex);
+ Dmsg2(400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
+ break;
}
}
unlock_jcr_chain();
/*
- * Given a Job, find the JCR
+ * Given a Job, find the JCR
* compares on the number of characters in Job
* thus allowing partial matches.
* Returns: jcr on success
- * NULL on failure
+ * NULL on failure
*/
JCR *get_jcr_by_partial_name(char *Job)
{
- JCR *jcr;
+ JCR *jcr;
int len;
if (!Job) {
len = strlen(Job);
for (jcr = jobs; jcr; jcr=jcr->next) {
if (strncmp(Job, jcr->Job, len) == 0) {
- P(jcr->mutex);
- jcr->use_count++;
- V(jcr->mutex);
- Dmsg2(200, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
- break;
+ P(jcr->mutex);
+ jcr->use_count++;
+ V(jcr->mutex);
+ Dmsg2(400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
+ break;
}
}
unlock_jcr_chain();
/*
- * Given a Job, find the JCR
+ * Given a Job, find the JCR
* requires an exact match of names.
* Returns: jcr on success
- * NULL on failure
+ * NULL on failure
*/
JCR *get_jcr_by_full_name(char *Job)
{
- JCR *jcr;
+ JCR *jcr;
if (!Job) {
return NULL;
lock_jcr_chain();
for (jcr = jobs; jcr; jcr=jcr->next) {
if (strcmp(jcr->Job, Job) == 0) {
- P(jcr->mutex);
- jcr->use_count++;
- V(jcr->mutex);
- Dmsg2(200, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
- break;
+ P(jcr->mutex);
+ jcr->use_count++;
+ V(jcr->mutex);
+ Dmsg2(400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
+ break;
}
}
unlock_jcr_chain();
int errstat;
if ((errstat=rwl_writelock(&lock)) != 0) {
Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
- strerror(errstat));
+ strerror(errstat));
}
}
int errstat;
if ((errstat=rwl_writeunlock(&lock)) != 0) {
Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
- strerror(errstat));
+ strerror(errstat));
}
}
P(jcr->mutex);
jcr->use_count++;
V(jcr->mutex);
- Dmsg2(200, "Inc get_next_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
+ Dmsg2(400, "Inc get_next_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
}
return jcr;
}
watchdog_t *wd = new_watchdog();
wd->one_shot = false;
- wd->interval = 30; /* FIXME: should be configurable somewhere, even
- if only with a #define */
+ wd->interval = 30; /* FIXME: should be configurable somewhere, even
+ if only with a #define */
wd->callback = jcr_timeout_check;
register_watchdog(wd);
*/
lock_jcr_chain();
foreach_jcr(jcr) {
- free_locked_jcr(jcr); /* OK to free now cuz chain is locked */
+ free_locked_jcr(jcr); /* OK to free now cuz chain is locked */
if (jcr->JobId == 0) {
- continue;
+ continue;
}
fd = jcr->store_bsock;
if (fd) {
- timer_start = fd->timer_start;
- if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
- fd->timer_start = 0; /* turn off timer */
- fd->timed_out = TRUE;
- Jmsg(jcr, M_ERROR, 0, _(
+ timer_start = fd->timer_start;
+ if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
+ fd->timer_start = 0; /* turn off timer */
+ fd->timed_out = TRUE;
+ Jmsg(jcr, M_ERROR, 0, _(
"Watchdog sending kill after %d secs to thread stalled reading Storage daemon.\n"),
- watchdog_time - timer_start);
- pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
- }
+ watchdog_time - timer_start);
+ pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
+ }
}
fd = jcr->file_bsock;
if (fd) {
- timer_start = fd->timer_start;
- if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
- fd->timer_start = 0; /* turn off timer */
- fd->timed_out = TRUE;
- Jmsg(jcr, M_ERROR, 0, _(
+ timer_start = fd->timer_start;
+ if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
+ fd->timer_start = 0; /* turn off timer */
+ fd->timed_out = TRUE;
+ Jmsg(jcr, M_ERROR, 0, _(
"Watchdog sending kill after %d secs to thread stalled reading File daemon.\n"),
- watchdog_time - timer_start);
- pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
- }
+ watchdog_time - timer_start);
+ pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
+ }
}
fd = jcr->dir_bsock;
if (fd) {
- timer_start = fd->timer_start;
- if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
- fd->timer_start = 0; /* turn off timer */
- fd->timed_out = TRUE;
- Jmsg(jcr, M_ERROR, 0, _(
+ timer_start = fd->timer_start;
+ if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
+ fd->timer_start = 0; /* turn off timer */
+ fd->timed_out = TRUE;
+ Jmsg(jcr, M_ERROR, 0, _(
"Watchdog sending kill after %d secs to thread stalled reading Director.\n"),
- watchdog_time - timer_start);
- pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
- }
+ watchdog_time - timer_start);
+ pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
+ }
}
}
unlock_jcr_chain();
- Dmsg0(200, "Finished JCR timeout checks\n");
+ Dmsg0(400, "Finished JCR timeout checks\n");
}
/*
*/
static void timeout_handler(int sig)
{
- return; /* thus interrupting the function */
+ return; /* thus interrupting the function */
}
if (wd_is_init) {
return 0;
}
- Dmsg0(200, "Initialising NicB-hacked watchdog thread\n");
+ Dmsg0(400, "Initialising NicB-hacked watchdog thread\n");
watchdog_time = time(NULL);
if ((errstat=rwl_init(&lock)) != 0) {
wd_lock();
wd->next_fire = watchdog_time + wd->interval;
wd_queue->append(wd);
- Dmsg3(200, "Registered watchdog %p, interval %d%s\n",
+ Dmsg3(400, "Registered watchdog %p, interval %d%s\n",
wd, wd->interval, wd->one_shot ? " one shot" : "");
wd_unlock();
foreach_dlist(p, wd_queue) {
if (wd == p) {
wd_queue->remove(wd);
- Dmsg1(200, "Unregistered watchdog %p\n", wd);
+ Dmsg1(400, "Unregistered watchdog %p\n", wd);
return true;
}
}
foreach_dlist(p, wd_inactive) {
if (wd == p) {
wd_inactive->remove(wd);
- Dmsg1(200, "Unregistered inactive watchdog %p\n", wd);
+ Dmsg1(400, "Unregistered inactive watchdog %p\n", wd);
return true;
}
}
- Dmsg1(200, "Failed to unregister watchdog %p\n", wd);
+ Dmsg1(400, "Failed to unregister watchdog %p\n", wd);
return false;
}
static void *watchdog_thread(void *arg)
{
- Dmsg0(200, "NicB-reworked watchdog thread entered\n");
+ Dmsg0(400, "NicB-reworked watchdog thread entered\n");
while (!quit) {
watchdog_t *p;
bmicrosleep(SLEEP_TIME, 0);
}
- Dmsg0(200, "NicB-reworked watchdog thread exited\n");
+ Dmsg0(400, "NicB-reworked watchdog thread exited\n");
return NULL;
}
for (int vol_index=1; vol_index < 3; vol_index++) {
bnet_fsend(dir, Find_media, jcr->Job, vol_index);
if (do_get_volume_info(jcr)) {
- Dmsg1(200, "Got possible Vol=%s\n", jcr->VolumeName);
+ Dmsg2(200, "JobId=%d got possible Vol=%s\n", jcr->JobId, jcr->VolumeName);
bool found = false;
/*
* Walk through all jobs and see if the volume is
if (jcr == njcr) {
continue; /* us */
}
+ Dmsg2(200, "Compare to JobId=%d using Vol=%s\n", njcr->JobId, njcr->VolumeName);
if (strcmp(jcr->VolumeName, njcr->VolumeName) == 0) {
found = true;
Dmsg1(200, "Vol in use by JobId=%u\n", njcr->JobId);
return true; /* Got good Volume */
}
} else {
- break;
+ Dmsg0(200, "No volume info, return false\n");
+ return false;
}
}
- Dmsg0(200, "dir_find_next_appendable_volume return false\n");
- return false;
+ Dmsg0(200, "dir_find_next_appendable_volume return true\n");
+ return true;
}
timeout.tv_sec = tv.tv_sec + 30 * 60; /* wait 30 minutes */
- Dmsg1(100, "%s waiting on job_start_wait\n", jcr->Job);
- /* Wait for the File daemon to contact us to start the Job,
+ Dmsg1(100, "%s waiting on FD to contact SD\n", jcr->Job);
+ /*
+ * Wait for the File daemon to contact us to start the Job,
* when he does, we will be released, unless the 30 minutes
* expires.
*/
/* Forward referenced functions */
static void send_blocked_status(JCR *jcr, DEVICE *dev);
static void list_terminated_jobs(void *arg);
+static void list_running_jobs(BSOCK *user);
static void sendit(char *msg, int len, void *arg);
static char *level_to_str(int level);
{
DEVRES *device;
DEVICE *dev;
- int found, bps, sec, bpb;
BSOCK *user = jcr->dir_bsock;
char dt[MAX_TIME_LENGTH];
char b1[30], b2[30], b3[30];
+ int bpb;
bnet_fsend(user, "\n%s Version: " VERSION " (" BDATE ") %s %s %s\n", my_name,
HOST_OS, DISTNAME, DISTVER);
bnet_fsend(user, _("Daemon started %s, %d Job%s run since started.\n"), dt, num_jobs_run,
num_jobs_run == 1 ? "" : "s");
+ /*
+ * List running jobs
+ */
+ list_running_jobs(user);
+
/*
* List terminated jobs
*/
/*
* List devices
*/
+ bnet_fsend(user, _("Device status:\n"));
LockRes();
foreach_res(device, R_DEVICE) {
for (dev=device->dev; dev; dev=dev->next) {
}
UnlockRes();
- found = 0;
- lock_jcr_chain();
- /* NOTE, we reuse a calling argument jcr. Be warned! */
- foreach_jcr(jcr) {
- if (jcr->JobStatus == JS_WaitFD) {
- bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"),
- job_type_to_str(jcr->JobType), jcr->Job);
- }
- if (jcr->device) {
- bnet_fsend(user, _("%s %s job %s using Volume \"%s\" on device \"%s\"\n"),
- job_level_to_str(jcr->JobLevel),
- job_type_to_str(jcr->JobType),
- jcr->Job,
- jcr->VolumeName,
- jcr->device->device_name);
- sec = time(NULL) - jcr->run_time;
- if (sec <= 0) {
- sec = 1;
- }
- bps = jcr->JobBytes / sec;
- bnet_fsend(user, _(" Files=%s Bytes=%s Bytes/sec=%s\n"),
- edit_uint64_with_commas(jcr->JobFiles, b1),
- edit_uint64_with_commas(jcr->JobBytes, b2),
- edit_uint64_with_commas(bps, b3));
- found = 1;
-#ifdef DEBUG
- if (jcr->file_bsock) {
- bnet_fsend(user, " FDReadSeqNo=%s in_msg=%u out_msg=%d fd=%d\n",
- edit_uint64_with_commas(jcr->file_bsock->read_seqno, b1),
- jcr->file_bsock->in_msg_no, jcr->file_bsock->out_msg_no,
- jcr->file_bsock->fd);
- } else {
- bnet_fsend(user, " FDSocket closed\n");
- }
-#endif
- }
- free_locked_jcr(jcr);
- }
- unlock_jcr_chain();
- if (!found) {
- bnet_fsend(user, _("No jobs running.\n"));
- }
#ifdef xfull_status
bnet_fsend(user, "\n\n");
dump_resource(R_DEVICE, resources[R_DEVICE-r_first].res_head, sendit, user);
#endif
- bnet_fsend(user, "====\n");
+ bnet_fsend(user, "====\n\n");
list_spool_stats(user);
}
+static void list_running_jobs(BSOCK *user)
+{
+ bool found = false;
+ int bps, sec;
+ JCR *jcr;
+ char JobName[MAX_NAME_LENGTH];
+ char b1[30], b2[30], b3[30];
+
+ bnet_fsend(user, _("\nRunning Jobs:\n"));
+ lock_jcr_chain();
+ foreach_jcr(jcr) {
+ if (jcr->JobStatus == JS_WaitFD) {
+ bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"),
+ job_type_to_str(jcr->JobType), jcr->Job);
+ }
+ if (jcr->device) {
+ bstrncpy(JobName, jcr->Job, sizeof(JobName));
+ /* There are three periods after the Job name */
+ char *p;
+ for (int i=0; i<3; i++) {
+ if ((p=strrchr(JobName, '.')) != NULL) {
+ *p = 0;
+ }
+ }
+ bnet_fsend(user, _("%s %s job %s JobId=%d Volume=\"%s\" device=\"%s\"\n"),
+ job_level_to_str(jcr->JobLevel),
+ job_type_to_str(jcr->JobType),
+ JobName,
+ jcr->JobId,
+ jcr->VolumeName,
+ jcr->device->device_name);
+ sec = time(NULL) - jcr->run_time;
+ if (sec <= 0) {
+ sec = 1;
+ }
+ bps = jcr->JobBytes / sec;
+ bnet_fsend(user, _(" Files=%s Bytes=%s Bytes/sec=%s\n"),
+ edit_uint64_with_commas(jcr->JobFiles, b1),
+ edit_uint64_with_commas(jcr->JobBytes, b2),
+ edit_uint64_with_commas(bps, b3));
+ found = true;
+#ifdef DEBUG
+ if (jcr->file_bsock) {
+ bnet_fsend(user, " FDReadSeqNo=%s in_msg=%u out_msg=%d fd=%d\n",
+ edit_uint64_with_commas(jcr->file_bsock->read_seqno, b1),
+ jcr->file_bsock->in_msg_no, jcr->file_bsock->out_msg_no,
+ jcr->file_bsock->fd);
+ } else {
+ bnet_fsend(user, " FDSocket closed\n");
+ }
+#endif
+ }
+ free_locked_jcr(jcr);
+ }
+ unlock_jcr_chain();
+ if (!found) {
+ bnet_fsend(user, _("No jobs running.\n"));
+ }
+ bnet_fsend(user, "====\n");
+}
+
static void list_terminated_jobs(void *arg)
{
char dt[MAX_TIME_LENGTH], b1[30], b2[30];
dt, JobName);
sendit(buf, strlen(buf), arg);
}
- sendit("\n", 1, arg);
+ sendit("====\n", 1, arg);
unlock_last_jobs_list();
}