#! /bin/sh
# Master batching control.

# =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
. ${NEWSCONFIG-/usr/lib/news/bin/config}

PATH=$NEWSCTL/bin:$NEWSBIN/batch:$NEWSBIN:$NEWSPATH ; export PATH
umask $NEWSUMASK

origpath="$PATH"

parms=$NEWSCTL/batchparms
log=$NEWSCTL/batchlog

case "$-" in
*x*)    n='***NOTE***'
        echo "$n expect spurious batching failures due to \`sh -x' $n" >&2
        # no, there isn't any portable fix
        ;;
esac

# set up unlocker
glock=
llock=
trap "rm -f \$glock \$llock ; exit 0" 0 1 2 15

# lock against multiple simultaneous execution, unless suppressed by -p
case $1 in
-p)     shift   ;;
*)      lock="$NEWSCTL/LOCKbatch"
        ltemp="$NEWSCTL/L.$$"
        echo $$ >$ltemp
        glock="$ltemp"
        if newslock $ltemp $lock
        then
                glock="$ltemp $lock"
        else
                exit 0
        fi
        ;;
esac

cd $NEWSARTS/out.going

# Determine what systems are being requested, in what order.
case "$1" in
-d)     debug=yes
        shift
        ;;
esac
case $# in
0)      if detab < $parms | egrep '^/default/[ ]'  >/dev/null   # default line found
        then
                syses=`ls -tr | egrep -v '^[@.]'`       # oldest first
        else
                syses="`egrep '^[^/#]' $parms | awk '{ print $1 }'`"
        fi
        ;;
*)      syses="$*"      ;;
esac
case $debug in
yes)    for sys in $syses
        do
                echo $sys
        done
        exit 0
        ;;
esac

# Start up logging.
echo "`date`, sendbatches $$" >>$log

# Run through them.
for sys in $syses
do
        # Move into his directory, include it in search path.
        here=$NEWSARTS/out.going/$sys
        if test ! -d $here
        then
                echo "$0: cannot find batch directory for \`$sys'" |
                                                        mail $NEWSMASTER
                continue
        fi
        cd $here
        PATH=$here:$origpath ; export PATH
        NEWSSITE=$sys ; export NEWSSITE         # For site-specific programs.
        NEWSSITEDIR=$here ; export NEWSSITEDIR  # ditto

        # Is there anything to do?
        files=`echo togo*`
        if test "$files" = 'togo*' || test "$files" = "togo" -a ! -s togo
        then
                continue                        # no
        fi

        # Pick up the batchparms line.
        ctlline="` detab < $parms | egrep "^$sys[ ]"  | sed 1q`"
        if test " $ctlline" = " "
        then
                ctlline="`detab < $parms | egrep '^/default/[ ]'  | sed 1q`"
        fi
        set $ctlline
        if test " $#" -ne 6
        then
                echo "$0: bad or missing batchparms line for \`$sys'" |
                                                        mail $NEWSMASTER
                continue
        fi
        batchsize=$2
        limit=$3
        batcher=$4
        muncher=$5
        sender=$6

        # lock against multiple simultaneous execution of batcher for this site
        lock="LOCKbatch"
        ltemp="L.$$"
        llock="$ltemp"
        echo $$ >$ltemp
        if newslock $ltemp $lock
        then
                llock="$ltemp $lock"
        else
                rm -f $ltemp    # didn't get the lock; this site is busy
                continue        # try the next site
        fi

        # How many to send?
        outstand="`queuelen $sys`"
        nbatch=`expr $limit - $outstand`
        roomfor=`spacefor $batchsize outbound $sys`
        if test " $nbatch" -gt " $roomfor"
        then
                nbatch=$roomfor
        fi

        # If not allowed to send, remember reason.
        status='batches flowing'
        if test " $nbatch" -le 0
        then
                if test " $roomfor" -le 0
                then
                        status='disk too full for batching'
                else
                        status='queue full, no recent movement'
                fi
        fi

        # Try sending some.
        while test " $nbatch" -gt 0
        do
                # Does he have batches prepared already?
                if test "`echo togo.[0-9]`" = 'togo.[0-9]'
                then
                        # No -- need some more batches.
                        if test ! -s togo && test ! -s togo.more &&
                                                        test ! -s togo.next
                        then
                                break           # Nothing left to do.
                        fi
                        batchsplit $batchsize $nbatch
                fi

                # Send some batches.
                them=`ls | egrep '^togo\.[0-9]' | sed "${nbatch}q"`
                for f in $them
                do
                        # Sigh... sh -x on this won't work, because the -x
                        # output ends up in /tmp/nb$$, and there is no way
                        # to either (a) separate it out (bearing in mind that
                        # some shells randomly interleave -x lines from the
                        # processes in a pipeline) or (b) turn off -x for
                        # a moment in a portable way.
                        ( ( cd $NEWSARTS ; $batcher $here/$f ) | $muncher |
                                                $sender $sys ) >/tmp/nb$$ 2>&1
                        if test $? -eq 0 -a ! -s /tmp/nb$$
                        then
                                # okay
                                rm -f $f /tmp/nb$$
                        else
                                (
                                        echo "$0: batching $f for \`$sys' failed"
                                        cat /tmp/nb$$
                                        echo "$0: aborting"
                                ) | mail $NEWSMASTER
                                rm -f /tmp/nb$$
                                # unlock this site
                                rm -f $ltemp $lock
                                exit 1
                        fi
                done
                ndone=`echo $them | wc -w`
                nbatch=`expr $nbatch - $ndone`

                # Recheck the space -- it can fall for other reasons.
                roomfor=`spacefor $batchsize outbound $sys`
                if test " $nbatch" -gt " $roomfor"
                then
                        nbatch=$roomfor
                fi
        done

        # Report status, if appropriate.
        nart=`cat togo* | wc -l | awk '{print $1}'`
        if test " $nart" -gt 0
        then
                echo "$sys      backlog $nart ($status)" >>$log
        fi

        # unlock this site
        rm -f $ltemp $lock
done

echo "`date`, sendbatches $$" >>$log
echo >>$log
