#!/bin/sh
# Copyright 1996 James H. Lowe, Jr.
# Copying Policy: FSF's GPL
# $Id: shak0_waitlock_v 1.9 1996/05/19 21:11:23 jhl Exp $

# Program -  shak0_waitlock
# Wait to get valid lock and monitor queue.

# Program arguments
#    $1: wait time in seconds.

# Return values:
# 0: have lock
# 1: re-queued : don't have lock: position improved.
# 2: re-queued : don't have lock: position not improved or unknown.
# 3: not re-queued : dont't have lock
# 4: wait expired
# 5: serious protocol exception.
# 6: jukebox exception


returnvalue () {
	return $1
}

wait_loop () {

# $1=lastknown
# $2=entry
# $3=waitcycles
# $4=elapsed wait cycles

# exit values

# 0: have lock
# 1: re-queued : don't have lock: position improved.
# 2: re-queued : don't have lock: position not improved or unknown.
# 3: not re-queued : dont't have lock
# 4: wait expired
# 5: serious protocol exception.
# 6: jukebox exception

lastknown="$1"
entry="$2"
waitcycles="$3"
elapsed="$4"

loop=1
i=$elapsed


while [ $loop ]
do
  
  queue="`${SHAK_LIBPATH}/shak_checklock  -q $SHAK_INDEXHOST $entry`"
  if [ "$shak_debugQ" -gt  "1" ]; then
	${SHAK_LIBPATH}/shak_qlog "shak_waitlock: wait_loop $i, Q position $queue."	
  fi
  if [ ! "$queue" ]; then
#	somebody finished a backup and erased the lockfile, good.
#	re-queue and exit.
#       Re-queing is a controlled race condition based on a delay
#       using the last known queue position.
	if [ "$lastknown" -eq 0 ]; then
		j=0
	else
		j=1
	fi
	reqdelay="` expr $shak_chkfreq '*' 2  '*' $j + $shak_chkfreq '*' $lastknown `"
	if [ "$shak_debugQ" -ge "1" ]; then
		${SHAK_LIBPATH}/shak_qlog " re-queuing: Sleeping $reqdelay seconds."
	fi
	sleep $reqdelay
	if [ "$shak_debugQ" -gt  "1" ]; then
		${SHAK_LIBPATH}/shak_qlog "Finished sleeping, will lock."	
	fi
	${SHAK_LIBPATH}/shak_lock
	locked=$?
	if [ $locked -eq 0 ]; then
		if [ "$shak_debugQ" -gt 1 ]; then
			${SHAK_LIBPATH}/shak_qlog "Locked successfully."	
		fi
		${SHAK_LIBPATH}/shak_jukebox $SHAK_TAPENUMBER
		if [ $? -ne 0 ]; then
			echo 6:1
			exit 6
		fi
		echo $i
		exit 0
	else
		if [ "$shak_debugQ" -ge 1 ]; then
			${SHAK_LIBPATH}/shak_qlog "Lock failed."	
		fi
  		queue="`${SHAK_LIBPATH}/shak_checklock  -q $SHAK_INDEXHOST $entry`"
		if [ ! "$queue" ]; then
			if [ "$shak_debugQ" -gt 1 ]; then
				${SHAK_LIBPATH}/shak_qlog "Not in queue."	
			fi
			echo ${i}:0
			exit 3
		else
			if [  $queue  -lt $lastknown ]; then
				if [ "$shak_debugQ" -gt 1 ]; then
					${SHAK_LIBPATH}/shak_qlog "Queue Position improved."	
				fi
				echo ${i}:$queue
				exit 1
			else	
				if [ "$shak_debugQ" -gt 1 ]; then
					${SHAK_LIBPATH}/shak_qlog "Queue Position not improved."	
				fi
				echo ${i}:$queue
				exit 2
			fi
		fi
        fi
  else
	if [ "$lastknown" = "$queue" ]; then
#		normal wait condition
		:
		if [ "$shak_debugQ" -gt "1" ]; then
			${SHAK_LIBPATH}/shak_qlog "Queue Position unchanged."	
		fi
	else
		if [ "$shak_debugQ" -gt "1" ]; then
			${SHAK_LIBPATH}/shak_qlog "Queue Position changed, handled exception."	
		fi
  		nentries="`${SHAK_LIBPATH}/shak_checklock  -t $SHAK_INDEXHOST $entry`"
		if [ "$nentries" -gt 1 ]; then
			echo ${i}:$queue
			exit 5
		fi
	fi
  fi

  i="` expr $i + 1 `"
  
  if [ $i -gt $waitcycles ]; then
	echo ${i}:$queue
  	exit 4
  fi
  sleep $shak_chkfreq
done
}


waitloop () {
	lastknown="$1"
	entry="$2"
	waitcycles="$3"
	elapsed="$4"

	retval=1
	until [ $retval -eq 0 -o $retval -eq 5 -o $retval -eq 4 -o $retval -eq 6 ]
	do
		retstr="`  wait_loop "$lastknown" "$entry" "$waitcycles" "$elapsed"  `"
		retval=$?
		if [ "$shak_debugQ" -gt "1" ]; then
			${SHAK_LIBPATH}/shak_qlog "shak_waitlock: wait_loop returned $retval, restarting."	
		fi	
		lastknown="`echo $retstr | sed -e 's/[^:]*://'`"	
		elapsed="`echo $retstr | sed -e 's/:.*//'`"
		returnvalue $retval	
	done
	return $?
}


if [ $# -eq 0 ]; then
	waittime=$shak_waittime
else
	waittime=$1
fi

entry="`$SHAK_LIBPATH/shak_lockentry`"

if [ $waittime -eq 0 ]; then
   waittime=2000000000
fi

lastknown="`${SHAK_LIBPATH}/shak_checklock  -q $SHAK_INDEXHOST $entry`"

if [ ! "$lastknown" ]; then
	lastknown=0
fi

if [ $lastknown -eq 1 ]; then
	exit 0
fi

waitcycles="` expr $waittime / $shak_chkfreq + 1 `"

if [ "$shak_debugQ" -gt "1" ]; then
	${SHAK_LIBPATH}/shak_qlog "shak_waitlock: entering waitloop."	
fi

waitloop "$lastknown" "$entry"  "$waitcycles" 0
retval=$?

if [ "$shak_debugQ" -gt "1" ]; then
	${SHAK_LIBPATH}/shak_qlog "shak_waitlock: waitloop returned $retval, exiting $retval."	
fi

exit $retval


