/*
 *
 * 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 1997 The Ohio State University
 *	NJN
 *
 *	$Id: get.c,v 1.1 1999/07/28 00:31:59 jsquyres Exp $
 *
 *	Function:	- get data from a window
 *	Accepts:	- origin address
 *			- origin count
 *			- origin datatype
 *			- target rank
 *			- target displacement
 *			- target count
 *			- target datatype
 *			- window
 *	Returns:	- MPI_SUCCESS or error code
 */

#include <errno.h>
#include <stdlib.h>

#include <blktype.h>
#include <mpi.h>
#include <mpisys.h>
#include <rpisys.h>
#include <typical.h>


int
MPI_Get(orgaddr, orgcnt, orgtype, rank, targdisp, targcnt, targtype, win)

void			*orgaddr;
int			orgcnt;
MPI_Datatype		orgtype;
int			rank;
MPI_Aint		targdisp;
int			targcnt;
MPI_Datatype		targtype;
MPI_Win			win;

{
	MPI_Comm	comm;			/* underlying communicator */
	struct _osdhdr	*header;		/* 1-sided protocol header */
	int		err;			/* error code */

	lam_initerr_m();
	lam_setfunc_m(BLKMPIGET);
/*
 * Check arguments.
 */
	if (win == MPI_WIN_NULL) {
		return(lam_err_comm(MPI_COMM_WORLD, MPI_ERR_WIN, 0,
			"null handle"));
	}

	comm = win->w_comm;

	if (orgtype == MPI_DATATYPE_NULL || targtype == MPI_DATATYPE_NULL) {
		return(lam_err_win(win, MPI_ERR_TYPE, 0, "null handle"));
	}
/*
 * Trivial case.
 */
	if (rank == MPI_PROC_NULL) return(MPI_SUCCESS);

	if (rank < 0 || rank >= comm->c_group->g_nprocs) {
		return(lam_err_win(win, MPI_ERR_RANK, 0, "out of range"));
	}
/*
 * Check epoch.
 */
	if (!((win->w_flags & LAM_WFACCEPOCH)
			|| win->w_pstate[rank] & LAM_WFSTARTED)) {
		
		if (win->w_flags & LAM_WFNOOUT) {
			return(lam_err_win(win, MPI_ERR_EPOCH, 0, ""));
		} else {
			win->w_flags |= LAM_WFACCEPOCH | LAM_WFEXPEPOCH;
		}
	}
/*
 * Send get protocol header to target.
 */
	header = (struct _osdhdr *) malloc(sizeof(struct _osdhdr));
	if (header == 0) {
		return(lam_err_win(win, MPI_ERR_OTHER, errno, ""));
	}

	LAM_ZERO_ME(*header);
	err = lam_osd_fillheader(LAM_OSD_GET, 0,
			targdisp, targcnt, targtype, header);
	if (err != MPI_SUCCESS) {
		return(lam_err_win(win, err, 0, ""));
	}

	err = lam_osd_send(header, 1, lam_osdhdr_type, rank,
			LAM_OSD_HEADER, comm, TRUE, TRUE);
	if (err != MPI_SUCCESS) {
		return(lam_errfunc(comm, BLKMPIGET, err));
	}
/*
 * Receive data from target.
 */
	err = lam_osd_recv(orgaddr, orgcnt, orgtype, rank,
			LAM_OSD_GET, comm, TRUE);
	if (err != MPI_SUCCESS) {
		return(lam_errfunc(comm, BLKMPIGET, err));
	}
/*
 * Make progress.
 */
	err = lam_osd_push();
	if (err != MPI_SUCCESS) {
		return(lam_errfunc(comm, BLKMPIGET, err));
	}

        lam_resetfunc_m(BLKMPIGET);
	return(MPI_SUCCESS);
}
