/*
 * File         : .c
 * Headerfile   : .h 
 * Author       : Xinying Li
 * Created      : Thu Apr  9 12:22:15 1998
 * Revision     : $Revision: 1.2 $
 * Updated      : $Date: 1999/03/03 19:55:27 $
 * Copyright: Northeast Parallel Architectures Center
 *            at Syracuse University 1998
 */

#include <mpi.h>
#include "mpi_Prequest.h"
#include "mpi_Datatype.h"

#include "handle.h"
#include "buffer.h"
#include "ID.h"

DECLARE_CLASS("mpi/Request", request_class)
DECLARE_FIELD_ID(request_class, "handle", "J", reqhandleID)
DECLARE_FIELD_ID(request_class, "CbufHandle", "J", reqbufhandleID)
DECLARE_FIELD_ID(request_class, "releaseCbufWhenDone", "I", reqrelbufID)
DECLARE_FIELD_ID(request_class, "commBuf", "Ljava/lang/Object;", reqbufID)
DECLARE_FIELD_ID(request_class, "commOffset", "I", reqoffsetID)
DECLARE_FIELD_ID(request_class, "commType", "Lmpi/Datatype;", reqtypeID)
DECLARE_FIELD_ID(request_class, "commCount", "I", reqcountID)

DECLARE_CLASS("mpi/Datatype", datatype_class)
DECLARE_FIELD_ID(datatype_class, "handle", "J", DatatypehandleID)
DECLARE_FIELD_ID(datatype_class, "baseType", "I", DatatypebaseTypeID)
DECLARE_FIELD_ID(datatype_class, "baseSize", "I", DatatypebaseSizeID)

void copyInToCBufMaybe(JNIEnv *env, jobject req)
{
  jint releaseLater = (*env)->GetIntField(env, req, reqrelbufID);
  void* bufptr;
  jobject buf;
  jint offset;
  jint count;
  jobject type;

  if (releaseLater & BUF_WRITEBACK) {
     /* Buffer is for receiving. */
    return;
  }
  bufptr = (void *)jlong_to_handle((*env)->GetLongField(env, req, reqbufhandleID));
  buf = (*env)->GetObjectField(env, req, reqbufID);
  offset = (*env)->GetIntField(env, req, reqoffsetID);
  count = (*env)->GetIntField(env, req, reqcountID);
  type = (*env)->GetObjectField(env, req, reqtypeID);

  count *= (Java_mpi_Datatype_size(env, type) /
	    (*env)->GetIntField(env, type, DatatypebaseSizeID));

  switch ((*env)->GetIntField(env,type,DatatypebaseTypeID)) {
    case 0:
      break;
    case 1:
      (*env)->GetByteArrayRegion(env,buf,offset,count,bufptr);
      break;
    case 2:
      (*env)->GetCharArrayRegion(env,buf,offset,count,bufptr);
      break;
    case 3:
      (*env)->GetShortArrayRegion(env,buf,offset,count,bufptr);
      break;
    case 4:
      (*env)->GetBooleanArrayRegion(env,buf,offset,count,bufptr);
      break;
    case 5:
      (*env)->GetIntArrayRegion(env,buf,offset,count,bufptr);
      break;
    case 6:
      (*env)->GetLongArrayRegion(env,buf,offset,count,bufptr);
      break;
    case 7:
      (*env)->GetFloatArrayRegion(env,buf,offset,count,bufptr);
      break;
    case 8:
      (*env)->GetDoubleArrayRegion(env,buf,offset,count,bufptr);
      break;
    case 9:
      (*env)->GetByteArrayRegion(env,buf,offset,count,bufptr);
      break;
    case 10:
      break;
    case 11:
      break;
    case 12:
      (*env)->GetByteArrayRegion(env,buf,offset,count,bufptr);
      break;
    default:
      break;
  }
}

/*
 * Class:     mpi_Prequest
 * Method:    start
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_mpi_Prequest_start
  (JNIEnv *env, jobject jthis)
{
   MPI_Request req;

   req=(MPI_Request)jlong_to_handle((*env)->GetLongField(env,jthis,reqhandleID));
   copyInToCBufMaybe(env, jthis);
   MPI_Start(&req);
}

/*
 * Class:     mpi_Prequest
 * Method:    startall
 * Signature: ([Lmpi/Request;)V
 */
JNIEXPORT void JNICALL Java_mpi_Prequest_startall
  (JNIEnv *env, jclass jthis, jobjectArray array_of_request)
{
   int i;
   int count=(*env)->GetArrayLength(env,array_of_request);
   MPI_Request *reqs=(MPI_Request*)calloc(count, sizeof(MPI_Request));

   for(i=0; i<count; i++) {
     jobject r_i = (*env)->GetObjectArrayElement(env,array_of_request,i);
     copyInToCBufMaybe(env, r_i);
     reqs[i]=
       (MPI_Request)jlong_to_handle((*env)->GetLongField(env, r_i, reqhandleID));
   }
   MPI_Startall(count,reqs);
   free(reqs);
}
                                         

