From: Kern Sibbald Date: Sat, 13 Mar 2004 11:50:12 +0000 (+0000) Subject: Phil's code + rework status command X-Git-Tag: Release-7.0.0~9625 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=1741604a8bfcf2788868f521b94d17a2fbbd4954;p=bacula%2Fbacula Phil's code + rework status command git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1133 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/ChangeLog b/bacula/ChangeLog index 269225cf7c..60157ec77b 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,4 +1,139 @@ +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 diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index fb648972ca..ce77c6920f 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -24,6 +24,11 @@ New directives: 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" @@ -33,6 +38,8 @@ New Commands: - "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. diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index f3328a5bb2..ddf614a4d2 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -1440,11 +1440,16 @@ gentoo) 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` diff --git a/bacula/configure b/bacula/configure index d1513edbf2..1c5c2d4696 100755 --- a/bacula/configure +++ b/bacula/configure @@ -17948,11 +17948,16 @@ gentoo) 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` diff --git a/bacula/platforms/Makefile.in b/bacula/platforms/Makefile.in index a31517717e..2084f84b1d 100644 --- a/bacula/platforms/Makefile.in +++ b/bacula/platforms/Makefile.in @@ -12,7 +12,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL = @INSTALL@ SUBDIRS = freebsd redhat solaris unknown openbsd irix gentoo \ - darwin aix bsdi mandrake + darwin aix bsdi mandrake slackware MAKE = make diff --git a/bacula/platforms/slackware/Makefile.in b/bacula/platforms/slackware/Makefile.in new file mode 100644 index 0000000000..f4b86dace8 --- /dev/null +++ b/bacula/platforms/slackware/Makefile.in @@ -0,0 +1,63 @@ +# +# 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 diff --git a/bacula/platforms/slackware/functions.bacula.in b/bacula/platforms/slackware/functions.bacula.in new file mode 100644 index 0000000000..b2054fbd16 --- /dev/null +++ b/bacula/platforms/slackware/functions.bacula.in @@ -0,0 +1,190 @@ +#! /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 +} + + diff --git a/bacula/platforms/slackware/rc.bacula-dir.in b/bacula/platforms/slackware/rc.bacula-dir.in new file mode 100644 index 0000000000..dcda59307d --- /dev/null +++ b/bacula/platforms/slackware/rc.bacula-dir.in @@ -0,0 +1,53 @@ +#! /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 diff --git a/bacula/platforms/slackware/rc.bacula-fd.in b/bacula/platforms/slackware/rc.bacula-fd.in new file mode 100644 index 0000000000..338b2cc4d1 --- /dev/null +++ b/bacula/platforms/slackware/rc.bacula-fd.in @@ -0,0 +1,54 @@ +#! /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 + diff --git a/bacula/platforms/slackware/rc.bacula-sd.in b/bacula/platforms/slackware/rc.bacula-sd.in new file mode 100644 index 0000000000..5dbc707eec --- /dev/null +++ b/bacula/platforms/slackware/rc.bacula-sd.in @@ -0,0 +1,55 @@ +#! /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 + + diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index 7e2a80346b..3b97f59341 100755 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -42,18 +42,18 @@ int num_jobs_run; 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)); } } @@ -64,7 +64,7 @@ void term_last_jobs_list() struct s_last_job *je; if (last_jobs) { foreach_dlist(je, last_jobs) { - free(je); + free(je); } delete last_jobs; last_jobs = NULL; @@ -77,32 +77,32 @@ void read_last_jobs_list(int fd, uint64_t addr) 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()); + } } } } @@ -112,7 +112,7 @@ uint64_t write_last_jobs_list(int fd, uint64_t addr) 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; } @@ -121,13 +121,13 @@ uint64_t write_last_jobs_list(int fd, uint64_t addr) 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 */ @@ -181,7 +181,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) 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); @@ -197,7 +197,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) 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; @@ -223,23 +223,23 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) /* * 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"); } /* @@ -270,15 +270,15 @@ static void free_common_jcr(JCR *jcr) 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: @@ -286,7 +286,7 @@ static void free_common_jcr(JCR *jcr) } 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 */ @@ -332,42 +332,42 @@ static void free_common_jcr(JCR *jcr) #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"); } @@ -377,35 +377,35 @@ void free_jcr(JCR *jcr) */ 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(); @@ -413,23 +413,23 @@ JCR *get_jcr_by_id(uint32_t JobId) } /* - * 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(); @@ -438,15 +438,15 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime) /* - * 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) { @@ -456,11 +456,11 @@ JCR *get_jcr_by_partial_name(char *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(); @@ -469,14 +469,14 @@ JCR *get_jcr_by_partial_name(char *Job) /* - * 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; @@ -484,11 +484,11 @@ JCR *get_jcr_by_full_name(char *Job) 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(); @@ -521,7 +521,7 @@ void lock_jcr_chain() int errstat; if ((errstat=rwl_writelock(&lock)) != 0) { Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n", - strerror(errstat)); + strerror(errstat)); } } @@ -533,7 +533,7 @@ void unlock_jcr_chain() int errstat; if ((errstat=rwl_writeunlock(&lock)) != 0) { Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n", - strerror(errstat)); + strerror(errstat)); } } @@ -551,7 +551,7 @@ JCR *get_next_jcr(JCR *prev_jcr) 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; } @@ -561,8 +561,8 @@ bool init_jcr_subsystem(void) 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); @@ -583,51 +583,51 @@ static void jcr_timeout_check(watchdog_t *self) */ 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"); } /* @@ -635,5 +635,5 @@ static void jcr_timeout_check(watchdog_t *self) */ static void timeout_handler(int sig) { - return; /* thus interrupting the function */ + return; /* thus interrupting the function */ } diff --git a/bacula/src/lib/watchdog.c b/bacula/src/lib/watchdog.c index 708554a908..05e59dfe01 100755 --- a/bacula/src/lib/watchdog.c +++ b/bacula/src/lib/watchdog.c @@ -64,7 +64,7 @@ int start_watchdog(void) 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) { @@ -159,7 +159,7 @@ bool register_watchdog(watchdog_t *wd) 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(); @@ -177,7 +177,7 @@ bool unregister_watchdog_unlocked(watchdog_t *wd) 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; } } @@ -185,12 +185,12 @@ bool unregister_watchdog_unlocked(watchdog_t *wd) 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; } @@ -211,7 +211,7 @@ bool unregister_watchdog(watchdog_t *wd) 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; @@ -248,7 +248,7 @@ static void *watchdog_thread(void *arg) bmicrosleep(SLEEP_TIME, 0); } - Dmsg0(200, "NicB-reworked watchdog thread exited\n"); + Dmsg0(400, "NicB-reworked watchdog thread exited\n"); return NULL; } diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index d8ae98f0cd..d05b2fe30d 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -155,7 +155,7 @@ int dir_find_next_appendable_volume(JCR *jcr) 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 @@ -168,6 +168,7 @@ int dir_find_next_appendable_volume(JCR *jcr) 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); @@ -182,11 +183,12 @@ int dir_find_next_appendable_volume(JCR *jcr) 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; } diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 26c38b9e4a..c04c3d3b13 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -167,8 +167,9 @@ int job_cmd(JCR *jcr) 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. */ diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c index 18b08018fd..68aa67d4d0 100644 --- a/bacula/src/stored/status.c +++ b/bacula/src/stored/status.c @@ -45,6 +45,7 @@ extern int num_jobs_run; /* 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); @@ -56,10 +57,10 @@ int status_cmd(JCR *jcr) { 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); @@ -67,6 +68,11 @@ int status_cmd(JCR *jcr) 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 */ @@ -75,6 +81,7 @@ int status_cmd(JCR *jcr) /* * List devices */ + bnet_fsend(user, _("Device status:\n")); LockRes(); foreach_res(device, R_DEVICE) { for (dev=device->dev; dev; dev=dev->next) { @@ -123,54 +130,12 @@ int status_cmd(JCR *jcr) } 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); @@ -243,6 +208,67 @@ static void send_blocked_status(JCR *jcr, DEVICE *dev) } +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]; @@ -316,7 +342,7 @@ static void list_terminated_jobs(void *arg) dt, JobName); sendit(buf, strlen(buf), arg); } - sendit("\n", 1, arg); + sendit("====\n", 1, arg); unlock_last_jobs_list(); }