/*
 *
 * Copyright 1998-1999, University of Notre Dame.
 * Authors: Jeffrey M. Squyres, Kinis L. Meyer with M. D. McNally 
 *          and Andrew Lumsdaine
 *
 * This file is part of the Notre Dame LAM implementation of MPI.
 *
 * You should have received a copy of the License Agreement for the
 * Notre Dame LAM implementation of MPI along with the software; see
 * the file LICENSE.  If not, contact Office of Research, University
 * of Notre Dame, Notre Dame, IN 46556.
 *
 * Permission to modify the code and to distribute modified code is
 * granted, provided the text of this NOTICE is retained, a notice that
 * the code was modified is included with the above COPYRIGHT NOTICE and
 * with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
 * file is distributed with the modified code.
 *
 * LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
 * By way of example, but not limitation, Licensor MAKES NO
 * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
 * PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
 * OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
 * OR OTHER RIGHTS.  
 *
 * Additional copyrights may follow.
 *
 *	Ohio Trollius
 *	Copyright 1996 The Ohio State University
 *	GDB
 *
 *	$Id: asc_schedule.c,v 6.4 1999/06/16 05:54:50 jsquyres Exp $
 *
 *	Function:	- schedules an application schema
 *			- LAM specific
 *			- generates a new application list with one
 *			  process, one node entries
 *			- four scheduling cases:
 *			  1) "foo -c # <nodes>"  # procs on this list of nodes
 *			  2) "foo -c #"          # procs using all nodes
 *			  3) "foo <nodes>"       1 proc on each of these nodes
 *			  4) "foo"               1 proc on every node
 *
 *	Accepts:	- parsed application schema
 *	Returns:	- expanded, precise application schema or NULL
 */

#include <all_list.h>
#include <app_schema.h>
#include <ndi.h>

LIST *
asc_schedule(applist)

LIST *			applist;

{
	LIST *		newapplist;		/* scheduled app schema */
	LIST *		newnodelist;		/* explicit node ids */
	LIST *		parsenodelist;		/* parsed nodes or default */
	struct aschema	newproc;		/* precise app process */
	struct aschema *p;			/* current app process */
	struct ndi *	node;			/* current node ID */
	char *		nodev[3];		/* default node spec */
	int		n;
/*
 * Expand each entry in the parsed schema.
 */
	p = (struct aschema *) al_top(applist);
	newapplist = al_init(sizeof(struct aschema), 0);

	while (p) {
/*
 * Absent node information is replaced by all nodes.
 */
		if (al_count(p->asc_nodelist) == 0) {
			nodev[0] = "cmd";
			nodev[1] = "N";
			nodev[2] = 0;

			parsenodelist = ndi_parse(2, nodev, 0);

			if (parsenodelist == 0) {
				al_free(newapplist);
				return(0);
			}
		} else {
			parsenodelist = p->asc_nodelist;
		}
/*
 * Expand the node list into plain node identifiers.
 */
		newnodelist = ndi_resolve(parsenodelist);

		if (al_count(p->asc_nodelist) == 0) {
			al_free(parsenodelist);
		}

		if (newnodelist == 0) {
			al_free(newapplist);
			return(0);
		}
/*
 * An absent process count means one process on each node.
 */
		n = (p->asc_proc_cnt < 1) ? al_count(newnodelist) :
				p->asc_proc_cnt;
/*
 * Generate a one process, one node application schema.
 */
		node = (struct ndi *) al_top(newnodelist);
		newproc.asc_errno = 0;
		newproc.asc_proc_cnt = 1;
		newproc.asc_args = p->asc_args;
		newproc.asc_env = p->asc_env;
		newproc.asc_nodelist = 0;

		while (n > 0) {
			newproc.asc_node = node->ndi_node;
			newproc.asc_srcnode = (p->asc_srcnode == -1) ?
					node->ndi_node : p->asc_srcnode;
			newproc.asc_args->apa_refcount += 1;
			newproc.asc_env->ape_refcount += 1;

			if (al_append(newapplist, &newproc) == 0) {
				al_free(newapplist);
				al_free(newnodelist);
				return(0);
			}

			node = (struct ndi *) al_next(newnodelist, node);

			if (node == 0) {
				node = (struct ndi *) al_top(newnodelist);
			}

			n--;
		}

		al_free(newnodelist);
		p = al_next(applist, p);
	}

	return(newapplist);
}
