
/*
 *         PVM version 3.3:  Parallel Virtual Machine System
 *               University of Tennessee, Knoxville TN.
 *           Oak Ridge National Laboratory, Oak Ridge TN.
 *                   Emory University, Atlanta GA.
 *      Authors:  A. L. Beguelin, J. J. Dongarra, G. A. Geist,
 *    W. C. Jiang, R. J. Manchek, B. K. Moore, and V. S. Sunderam
 *                   (C) 1992 All Rights Reserved
 *
 *                              NOTICE
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted
 * provided that the above copyright notice appear in all copies and
 * that both the copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * Neither the Institutions (Emory University, Oak Ridge National
 * Laboratory, and University of Tennessee) nor the Authors make any
 * representations about the suitability of this software for any
 * purpose.  This software is provided ``as is'' without express or
 * implied warranty.
 *
 * PVM version 3 was funded in part by the U.S. Department of Energy,
 * the National Science Foundation and the State of Tennessee.
 */

/*
 *	sdpro.c
 *
 *	Pvmd entry points for messages from scheduler.
 *
$Log: sdpro.c,v $
 * Revision 1.3  1994/10/15  19:29:02  manchek
 * cast message tags for comparison as integers
 *
 * Revision 1.2  1994/07/18  19:22:56  manchek
 * ALPHA segfaulted on array subscript
 *
 * Revision 1.1  1994/06/03  20:38:27  manchek
 * Initial revision
 *
 *
 */


#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include "global.h"
#include "tdpro.h"
#include "ddpro.h"
#include <pvmsdpro.h>
#include "protoglarp.h"
#include "pvmalloc.h"
#include "host.h"
#include "mesg.h"
#include "waitc.h"
#include "task.h"
#include "bfunc.h"


extern int debugmask;				/* from pvmd.c */
extern int hostertid;				/* from pvmd.c */
extern int hosterwid;				/* from ddpro.c */
extern int pvmschedtid;				/* from pvmd.c */
extern int taskertid;				/* from pvmd.c */


/***************
 **  Private  **
 **           **
 ***************/

static char rcsid[] = "$Id: sdpro.c,v 1.3 1994/10/15 19:29:02 manchek Exp $";
static char pvmtxt[512];			/* scratch for error log */

int sm_bogus();
int sm_exec();
int sm_add();
int sm_handoff();
int sm_sthostack();
int sm_taskx();

int (*smswitch[])() = {
	sm_bogus,
	sm_exec,
	sm_bogus,
	sm_bogus,
	sm_bogus,
	sm_bogus,
	sm_bogus,
	sm_add,
	sm_bogus,
	sm_bogus,
	sm_taskx,
	sm_bogus,
	sm_handoff,
	sm_bogus,
	sm_bogus,
	sm_sthostack,
	sm_bogus,
};

char *sm_names[] = {
	"sm_spawn",
	"sm_exec",
	"sm_execack",
	"sm_task",
	"sm_config",
	"sm_addhost",
	"sm_delhost",
	"sm_add",
	"sm_addack",
	"sm_notify",
	"sm_taskx",
	"sm_hostx",
	"sm_handoff",
	"sm_sched",
	"sm_sthost",
	"sm_sthostack",
	"sm_sttask",
};


char *
smname(code)
	int code;
{
	if (code < (int)SM_FIRST || code > (int)SM_LAST)
		return "unknown";
	code -= SM_FIRST;
	return sm_names[code];
}


int
schentry(mp)
	struct mesg *mp;
{
	int c = mp->m_cod;

	if (debugmask & PDMMESSAGE) {
		sprintf(pvmtxt, "schentry() from t%x cod %s\n", mp->m_src, smname(c));
		pvmlogerror(pvmtxt);
	}

	if (c < (int)SM_FIRST || c > (int)SM_LAST) {
		sprintf(pvmtxt, "schentry() message from t%x with bogus code %d\n",
				mp->m_src, c);
		pvmlogerror(pvmtxt);
		goto bail;
	}

	c -= SM_FIRST;
	(smswitch[c])(mp);

bail:
	mesg_unref(mp);
	return 0;
}


int
sm_bogus(mp)
	struct mesg *mp;
{
	sprintf(pvmtxt, "sm_bogus() message code %s from t%x ?\n",
			smname(mp->m_cod), mp->m_src);
	pvmlogerror(pvmtxt);
	return 0;
}


/*	sm_exec(wid)
*
*	Request the pvmd to start task processes.
*	Just like DM_EXEC but different.
*/

int
sm_exec(mp)
	struct mesg *mp;
{
	struct mesg *rmp;

	rmp = mesg_new(0);
	rmp->m_dst = mp->m_src;
	rmp->m_cod = SM_EXECACK;
	rmp->m_wid = mp->m_wid;
	exectasks(mp, rmp, mp->m_src);
	return 0;
}


/*	sm_add()
*
*	Scheduler requests the master pvmd to add hosts.
*	Just like DM_ADD but different.
*
*	SM_ADD(wid) {
*		int count
*		string name[count]
*	}
*/

int
sm_add(mp)
	struct mesg *mp;
{
	struct mesg *rmp;

	rmp = mesg_new(0);
	rmp->m_dst = mp->m_src;
	rmp->m_cod = SM_ADDACK;
	rmp->m_wid = mp->m_wid;
	addhosts(mp, rmp);
	return 0;
}


/*	sm_taskx()
*
*	Tasker notifies us that process exited.
*
*	SM_TASKX() {
*		int tid		// of toasted process
*		int status	// exit status
*		int u_sec	// user time used
*		int u_usec
*		int s_sec	// system time used
*		int s_usec
*	}
*/

int
sm_taskx(mp)
	struct mesg *mp;
{
	int tid;
	struct task *tp;
	int i;

	if (mp->m_src != taskertid) {
		sprintf(pvmtxt, "sm_taskx() from t%x (not the tasker)\n", mp->m_src);
		pvmlogerror(pvmtxt);
		return 0;
	}
	upkuint(mp, &tid);
	if (tp = task_find(tid)) {
		if (debugmask & PDMTASK) {
			sprintf(pvmtxt, "sm_taskx() t%x\n", tid);
			pvmlogerror(pvmtxt);
		}
		upkuint(mp, &tp->t_status);
		upkuint(mp, &i);
		tp->t_utime.tv_sec = i;
		upkuint(mp, &i);
		tp->t_utime.tv_usec = i;
		upkuint(mp, &i);
		tp->t_stime.tv_sec = i;
		upkuint(mp, &i);
		tp->t_stime.tv_usec = i;
		task_cleanup(tp);
		task_free(tp);

	} else {
		if (debugmask & PDMTASK) {
			sprintf(pvmtxt, "sm_taskx() t%x (no such)\n", tid);
			pvmlogerror(pvmtxt);
		}
	}
	return 0;
}


/*	sm_handoff()
*
*	Current scheduler for this pvmd gets reassigned.
*
*	SM_HANDOFF() {
*		uint newsched		// tid
*	}
*/

int
sm_handoff(mp)
	struct mesg *mp;
{
	int tid;

	upkuint(mp, &tid);
	if (debugmask & PDMSCHED) {
		sprintf(pvmtxt, "sm_handoff() old t%x new t%x\n", pvmschedtid, tid);
		pvmlogerror(pvmtxt);
	}
	pvmschedtid = tid;
	return 0;
}


/*	sm_sthostack()
*
*	Hoster finishes starting slave pvmds.
*
*	SM_STHOSTACK(wid_rtn) {
*		{
*			int tid
*			string result
*		} []				// implied
*	}
*/

int
sm_sthostack(mp)
	struct mesg *mp;
{
	struct waitc *wp;		/* wait context on pvmd' */

	if (mp->m_src != hostertid) {
		sprintf(pvmtxt, "sm_sthostack() from t%x (not the hoster)\n",
				mp->m_src);
		pvmlogerror(pvmtxt);
		return 0;
	}

	if (mp->m_wid != hosterwid) {
		sprintf(pvmtxt, "sm_sthostack() from t%x bad wid %d wanted %d\n",
				mp->m_src, mp->m_wid, hosterwid);
		pvmlogerror(pvmtxt);
		return 0;
	}

	if (!(wp = wait_find(hosterwid)))
		return 0;

	hosterwid = 0;

	startack(wp, mp);

	return 0;
}


