#!/bin/ksh
# 
# $Copyright
# Copyright 1993, 1994 , 1995 Intel Corporation
# INTEL CONFIDENTIAL
# The technical data and computer software contained herein are subject
# to the copyright notices; trademarks; and use and disclosure
# restrictions identified in the file located in /etc/copyright on
# this system.
# Copyright$
# 
 
#
# Copyright (c) 1992-1995, Locus Computing Corporation
# All rights reserved
#
#
# HISTORY
# $Log: pan,v $
# Revision 1.6  1995/02/02  00:19:35  bolsen
#  Reviewer(s): Jerry Toman
#  Risk: Medium (lots of files)
#  Module(s): Too many to list
#  Configurations built: STD, LITE, & RAMDISK
#
#  Added or Updated the Locus Copyright message.
#
# Revision 1.5  1994/11/18  20:57:18  mtm
# Copyright additions/changes
#
# Revision 1.4  1993/07/14  18:54:23  cfj
# OSF/1 AD 1.0.4 code drop from Locus.
#
# Revision 1.3  1992/12/11  03:09:41  cfj
# Merged 12-1-92 bug drop from Locus.
#
# Revision 1.2  1992/11/30  23:04:40  dleslie
# Copy of NX branch back into main trunk
#
# Revision 1.1.2.1  1992/11/06  00:15:07  dleslie
# Local changes for NX through noon, November 5, 1992.
#
# Revision 1.1.1.2  1993/07/01  21:22:04  cfj
# Adding new code from vendor
#
# Revision 3.1  92/11/23  11:51:25  chrisp
# Major overhaul: now use stresslib, accept node ranges, visit all nodes
#         before and after tests to compute numbers of processes run,
#         various other tweeks.
# 
# Revision 3.0  92/07/21  12:07:00  chrisp
# First appearance
# 
# 
#

. stresslib

required onnode

while getopts ":L:N:n:g:h:r:q" opt; do
	case "$opt" in
	    L)	LOGFILE="$OPTARG";;
	    N)	node_list="$OPTARG";;
	    n)	node_list="$OPTARG"; RANDOMIZING_NODES=true;;
	    g)	num_series=$OPTARG;;
	    h)	num_clones=$OPTARG;;
	    q)	QUIET=please;;
	    r)	RANDOM=$OPTARG;;
	    :)	echo "$NAME: $OPTARG requires a value"
		exit 2;;
	   \?)	echo "$NAME: unknown option $OPTARG"
		echo "usage: $NAME -n|N<node_list> -h<#head> -g<#gen> <cmd>"
		exit 2;;
	esac
done
shift OPTIND-1
command="$*"

#
# Prompt for all the important stuff if not given
# 
if [ ! "$command" ]; then
	read command?"What to spawn? "
	[ "$command" ]    || exit 1
	[ "$node_list" ]  || read node_list?"Node list? "
	[ "$num_clones" ] || read num_clones?"Number of head? "
	[ "$num_series" ] || read num_series?"Number of generations? "
fi
#
# Take default values:
#
[ "$node_list" ]   || node_list="$(node_self)"
[ "$num_clones" ]  || num_clones=1
[ "$num_series" ]  || num_series=1

declare_nodes $node_list

#
# Create an array with node numbers to be selected
#
CYCLING_NODES=true
let "n = 1"
while ((n <= num_clones * num_series)); do
	next_node
	node_array[n]=$NODE
	let "n += 1"
done

#
# Determine the first PID to be assigned on each node.
# This will be used later to calculate how many processes we've spawned
#
log "visiting selected nodes to gather PID info"
home=$(node_self)
unique_node_list=$(for n in ${NODES[*]} $home; do echo $n; done | sort -u)
for node in $unique_node_list; do
	migrate_to_node $node
	: &
	let "pid_node[node] = $!"
done
migrate_to_node $home

#
#
# Use onnode to fire up the command on a random set of other nodes
#
trap   "log '*** interrupted ***'; \
	while kill %+ 1>/dev/null 2>&1; do \
		: ; \
	done; \
	exit 1 \
	" HUP INT KILL TERM
(( num_clones > 1 )) && s_if_plural="s"
log "spawning $num_clones clone$s_if_plural of \"$command\"..."
let "i = 0"
let "j = 0"
while (( i < num_clones )); do
	let "i += 1"
	(
		let "k = i"
		while (( j < num_series )); do
			let "j += 1"
			let "node = node_array[k]"
			let "k += num_clones"
			cmd=$(eval echo $command)
			onnode $node $cmd &
			child=$!
			log "[$child] $i-$j/$num_series - onnode $node $cmd &"
			wait $child
		done
	) &
done
wait
s_if_plural=; (( num_series > 1 )) && s_if_plural="s"
log "...$num_series generation$s_if_plural completed"

let "num_procs = 0"
for node in $unique_node_list; do
	migrate_to_node $node
	: &
	let "delta = $! - pid_node[node]"
	let "num_procs += delta"
	log "$delta processes run on node $node"
done
log "$num_procs processes run in $SECONDS secs"
log "...vanishing from node $(node_self)"
exit 0
