/*
 *                 Exemple "Failure.c" PVM versio 3.3
 *   	   	Susana Maria Bajo Sanchez (ei05646@salleURL.edu)
 *  	   	Josep Maria Garrell i Guiu (josepmg@salleURL.edu)
 *				Software Paral.lel
 *		   	Departament d'Informatica (DI)
 *	         Enginyeria i Arquitectura La Salle
 *	 	      Universitat Ramon Llull (URL)
 * 		           Curs 1999/2000
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pvm3.h"

#define MAXNCHILD 20 	// Maximum number of children this program will spawn
#define TASKDIED 11 	// Tag to use for the task done message

//---------------------------------------------------------------
int main(int argc, char* argv[]) 
{
int ntask = 3; 		// number of tasks to spawn, use 3 as the default
int info; 			// return code from pvm calls
int mytid; 			// my task id
int myparent; 		// my parents task id
int child[MAXNCHILD]; 	// children task id array
int i, deadtid; 

	mytid = pvm_mytid(); 		// find out my task id number
	if (mytid<0) 			// check for error
		{
		pvm_perror(argv[0]); 	// print out the error 
		return -1; 			// exit the program
		}
 
	myparent = pvm_parent(); 	// find my parent's task id number

	// exit if there is some error other than PvmNoParent
	if ((myparent<0)&&(myparent!=PvmNoParent))
		{
		pvm_perror(argv[0]); 
		pvm_exit(); 
		return -1; 
 		}

	// if i don't have a parent then i am the parent 
	if (myparent == PvmNoParent)
		{
		// find out how many tasks to spawn
		if (argc == 2) ntask = atoi(argv[1]); 
		// make sure ntask is legal
		if ((ntask<1)||(ntask>MAXNCHILD)) { pvm_exit(); return 0; }

		// spawn the child tasks
		info = pvm_spawn(argv[0], (char**)0, PvmTaskDebug, (char*)0, ntask, child); 
		// make sure spawn succeeded
		if (info != ntask) { pvm_exit(); return -1; }

		// print the tids
		for (i=0; i<ntask;i++) printf("t%x\t",child[i]); putchar('\n'); 

		// ask for notification when child exits
		info = pvm_notify(PvmTaskExit, TASKDIED, ntask, child); 
		if (info< 0) {pvm_perror("notify"); pvm_exit(); return -1;}
		
		// reap the middle child 
		info = pvm_kill(child[ntask/2]); 
		if (info<0) {pvm_perror("kill"); pvm_exit(); return -1;} 

		// wait for the notification
		info = pvm_recv(-1, TASKDIED); 
		if (info<0) {pvm_perror("recv"); pvm_exit(); return -1;}
		info = pvm_upkint(&deadtid,1,1); 
		if (info<0) pvm_perror("calling pvm_upkint"); 
		
		// should be the middle child
		printf("Task t%x has exited.\n", deadtid); 
		printf("Task t%x is middle child.\n", child[ntask/2]); 

		pvm_exit(); 
		return 0; 
		} 

	// i'm a child 
	sleep(63); 
	pvm_exit(); 
	return 0; 
	} 
