int pvfs_check_vector(const struct iovec *iov, int count, PVFS_Request *req, void **buf) { int i; int vstart; int vlen; int bsz; PVFS_size stride; int32_t *bsz_array; PVFS_size *disp_array; PVFS_Request *req_array; int rblk; /* set up request arrays */ bsz_array = (int32_t *)malloc(count * sizeof(int32_t)); if (!bsz_array) { return -1; } disp_array = (PVFS_size *)malloc(count * sizeof(PVFS_size)); if (!disp_array) { free(bsz_array); return -1; } req_array = (PVFS_Request *)malloc(count * sizeof(PVFS_Request)); if (!disp_array) { free(disp_array); free(bsz_array); return -1; } /* for now we assume that addresses in the iovec are ascending */ /* not that otherwise won't work, but we're not sure */ /* the first address will be assumed to be the base address of */ /* the whole request. the displacement of each vector is relative */ /* to that address */ if (count > 0) { *buf = iov[0].iov_base; } rblk = 0; /* start at beginning of iovec */ i = 0; while(i < count) { /* starting a new vector at position i */ vstart = i; vlen = 1; bsz = iov[i].iov_len; stride = 0; /* vector blocks must be of equal size */ while(++i < count && iov[i].iov_len == bsz) { if(vlen == 1) { /* two blocks of equal size are a vector of two */ stride = (u_char *)iov[i].iov_base - (u_char *)iov[i - 1].iov_base; if (stride < bsz) { /* overlapping blocks and negative strides are problems */ break; } vlen++; } else if (((u_char *)iov[i].iov_base - (u_char *)iov[i - 1].iov_base) == stride) { /* to add more blocks, stride must match */ vlen++; } else { /* doesn't match - end of vector */ break; } } if (vlen == 1) { /* trivial conversion */ bsz_array[rblk] = iov[vstart].iov_len; disp_array[rblk] = (PVFS_size)((u_char *)iov[vstart].iov_base - (u_char *)*buf); req_array[rblk] = PVFS_BYTE; rblk++; } else { /* found a vector */ bsz_array[rblk] = 1; disp_array[rblk] = (PVFS_size)((u_char *)iov[vstart].iov_base - (u_char *)*buf); PVFS_Request_vector(vlen, bsz, stride, PVFS_BYTE, &req_array[rblk]); rblk++; } } /* now build full request */ PVFS_Request_struct(rblk, bsz_array, disp_array, req_array, req); PVFS_Request_commit(req); free(bsz_array); free(disp_array); while (rblk--) { if (req_array[rblk] != PVFS_BYTE) { PVFS_Request_free(&req_array[rblk]); } } free(req_array); /* req is not freed, the caller is expected to do that */ return 0; }
int convert_mpi_pvfs2_dtype(MPI_Datatype *mpi_dtype, PVFS_Request *pvfs_dtype) { int num_int = -1, num_addr = -1, num_dtype = -1, combiner = -1, i = -1, ret = -1, leaf = -1; int *arr_int = NULL; MPI_Aint *arr_addr = NULL; MPI_Datatype *arr_dtype = NULL; PVFS_Request *old_pvfs_dtype = NULL; PVFS_Request *old_pvfs_dtype_arr = NULL; int arr_count = -1; PVFS_size *pvfs_arr_disp = NULL; int *pvfs_arr_len = NULL; MPI_Type_get_envelope(*mpi_dtype, &num_int, &num_addr, &num_dtype, &combiner); /* Depending on type of datatype do the following * operations */ if (combiner == MPI_COMBINER_NAMED) { convert_named(mpi_dtype, pvfs_dtype, combiner); return 1; } /* Allocate space for the arrays necessary for * MPI_Type_get_contents */ if ((arr_int = ADIOI_Malloc(sizeof(int)*num_int)) == NULL) { fprintf(stderr, "Failed to allocate array_int\n"); return -1; } if ((arr_addr = ADIOI_Malloc(sizeof(int)*num_addr)) == NULL) { ADIOI_Free(arr_int); fprintf(stderr, "Failed to allocate array_addr\n"); return -1; } if ((arr_dtype = ADIOI_Malloc(sizeof(MPI_Datatype)*num_dtype)) == NULL) { ADIOI_Free(arr_int); ADIOI_Free(arr_addr); fprintf(stderr, "Failed to allocate array_dtypes\n"); return -1; } MPI_Type_get_contents(*mpi_dtype, num_int, num_addr, num_dtype, arr_int, arr_addr, arr_dtype); /* If it's not a predefined datatype, it is either a * derived datatype or a structured datatype */ if (combiner != MPI_COMBINER_STRUCT) { if ((old_pvfs_dtype = ADIOI_Malloc(sizeof(PVFS_Request))) == NULL) fprintf(stderr, "convert_mpi_pvfs2_dtype: " "Failed to allocate PVFS_Request\n"); switch (combiner) { case MPI_COMBINER_CONTIGUOUS: leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); ret = PVFS_Request_contiguous(arr_int[0], *old_pvfs_dtype, pvfs_dtype); break; case MPI_COMBINER_VECTOR: leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); ret = PVFS_Request_vector(arr_int[0], arr_int[1], arr_int[2], *old_pvfs_dtype, pvfs_dtype); break; case MPI_COMBINER_HVECTOR: leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); ret = PVFS_Request_hvector(arr_int[0], arr_int[1], arr_addr[0], *old_pvfs_dtype, pvfs_dtype); break; /* Both INDEXED and HINDEXED types require PVFS_size * address arrays. Therefore, we need to copy and * convert the data from MPI_get_contents() into * a PVFS_size buffer */ case MPI_COMBINER_INDEXED: leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); if ((pvfs_arr_disp = ADIOI_Malloc(arr_int[0]*sizeof(PVFS_size))) == 0) { fprintf(stderr, "convert_mpi_pvfs2_dtype: " "Failed to allocate pvfs_arr_disp\n"); } for (i = 0; i < arr_int[0]; i++) { pvfs_arr_disp[i] = (PVFS_size) arr_int[arr_int[0]+1+i]; } ret = PVFS_Request_indexed(arr_int[0], &arr_int[1], pvfs_arr_disp, *old_pvfs_dtype, pvfs_dtype); ADIOI_Free(pvfs_arr_disp); break; case MPI_COMBINER_HINDEXED: leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); if ((pvfs_arr_disp = ADIOI_Malloc(arr_int[0]*sizeof(PVFS_size))) == 0) { fprintf(stderr, "convert_mpi_pvfs2_dtype: " "Failed to allocate pvfs_arr_disp\n"); } for (i = 0; i < arr_int[0]; i++) { pvfs_arr_disp[i] = (PVFS_size) arr_addr[i]; } ret = PVFS_Request_hindexed(arr_int[0], &arr_int[1], (int64_t *)&arr_addr[0], *old_pvfs_dtype, pvfs_dtype); ADIOI_Free(pvfs_arr_disp); break; case MPI_COMBINER_DUP: leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); ret = PVFS_Request_contiguous(1, *old_pvfs_dtype, pvfs_dtype); break; case MPI_COMBINER_INDEXED_BLOCK: /* No native PVFS2 support for this operation currently */ ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "INDEXED_BLOCK is unsupported\n"); break; case MPI_COMBINER_HINDEXED_BLOCK: /* No native PVFS2 support for this operation currently */ ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "HINDEXED_BLOCK is unsupported\n"); break; case MPI_COMBINER_HINDEXED_INTEGER: ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "HINDEXED_INTEGER is unsupported\n"); break; case MPI_COMBINER_STRUCT_INTEGER: ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "STRUCT_INTEGER is unsupported\n"); break; case MPI_COMBINER_SUBARRAY: ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "SUBARRAY is unsupported\n"); break; case MPI_COMBINER_DARRAY: ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "DARRAY is unsupported\n"); break; case MPI_COMBINER_F90_REAL: ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "F90_REAL is unsupported\n"); break; case MPI_COMBINER_F90_COMPLEX: ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "F90_COMPLEX is unsupported\n"); break; case MPI_COMBINER_F90_INTEGER: ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "F90_INTEGER is unsupported\n"); break; case MPI_COMBINER_RESIZED: ADIOI_Free(old_pvfs_dtype); fprintf(stderr, "convert_mpi_pvfs2_dtype: " "RESIZED is unsupported\n"); break; default: break; } if (ret != 0) fprintf(stderr, "Error in PVFS_Request_* " "for a derived datatype\n"); #ifdef DEBUG_DTYPE print_dtype_info(combiner, num_int, num_addr, num_dtype, arr_int, arr_addr, arr_dtype); #endif if (leaf != 1 && combiner != MPI_COMBINER_DUP) MPI_Type_free(&arr_dtype[0]); ADIOI_Free(arr_int); ADIOI_Free(arr_addr); ADIOI_Free(arr_dtype); PVFS_Request_free(old_pvfs_dtype); ADIOI_Free(old_pvfs_dtype); return ret; } else /* MPI_COMBINER_STRUCT */ { MPI_Aint mpi_lb = -1, mpi_extent = -1; PVFS_offset pvfs_lb = -1; PVFS_size pvfs_extent = -1; int has_lb_ub = 0; /* When converting into a PVFS_Request_struct, we no longer * can use MPI_LB and MPI_UB. Therfore, we have to do the * following. * We simply ignore all the MPI_LB and MPI_UB types and * get the lb and extent and pass it on through a * PVFS resized_req */ arr_count = 0; for (i = 0; i < arr_int[0]; i++) { if (arr_dtype[i] != MPI_LB && arr_dtype[i] != MPI_UB) { arr_count++; } } if (arr_int[0] != arr_count) { MPI_Type_get_extent(*mpi_dtype, &mpi_lb, &mpi_extent); pvfs_lb = mpi_lb; pvfs_extent = mpi_extent; if ((pvfs_arr_len = ADIOI_Malloc(arr_count*sizeof(int))) == NULL) { fprintf(stderr, "convert_mpi_pvfs2_dtype: " "Failed to allocate pvfs_arr_len\n"); } has_lb_ub = 1; } if ((old_pvfs_dtype_arr = ADIOI_Malloc(arr_count*sizeof(PVFS_Request))) == NULL) fprintf(stderr, "convert_mpi_pvfs2_dtype: " "Failed to allocate PVFS_Requests\n"); if ((pvfs_arr_disp = ADIOI_Malloc(arr_count*sizeof(PVFS_size))) == NULL) { fprintf(stderr, "convert_mpi_pvfs2_dtype: " "Failed to allocate pvfs_arr_disp\n"); } arr_count = 0; for (i = 0; i < arr_int[0]; i++) { if (arr_dtype[i] != MPI_LB && arr_dtype[i] != MPI_UB) { leaf = convert_mpi_pvfs2_dtype( &arr_dtype[i], &old_pvfs_dtype_arr[arr_count]); if (leaf != 1) MPI_Type_free(&arr_dtype[i]); pvfs_arr_disp[arr_count] = (PVFS_size) arr_addr[i]; if (has_lb_ub) { pvfs_arr_len[arr_count] = arr_int[i+1]; } arr_count++; } } /* If a MPI_UB or MPI_LB did exist, we have to * resize the datatype */ if (has_lb_ub) { PVFS_Request *tmp_pvfs_dtype = NULL; if ((tmp_pvfs_dtype = ADIOI_Malloc(sizeof(PVFS_Request))) == NULL) fprintf(stderr, "convert_mpi_pvfs2_dtype: " "Failed to allocate PVFS_Request\n"); ret = PVFS_Request_struct(arr_count, pvfs_arr_len, pvfs_arr_disp, old_pvfs_dtype_arr, tmp_pvfs_dtype); if (ret != 0) fprintf(stderr, "Error in PVFS_Request_struct\n"); arr_count = 0; for (i = 0; i < arr_int[0]; i++) { if (arr_dtype[i] != MPI_LB && arr_dtype[i] != MPI_UB) { PVFS_Request_free(&old_pvfs_dtype_arr[arr_count]); arr_count++; } } #ifdef DEBUG_DTYPE fprintf(stderr, "STRUCT(WITHOUT %d LB or UB)(%d,[", arr_int[0] - arr_count, arr_count); for (i = 0; i < arr_count; i++) fprintf(stderr, "(%d,%Ld) ", pvfs_arr_len[i], pvfs_arr_disp[i]); fprintf(stderr, "]\n"); fprintf(stderr, "RESIZED(LB = %Ld, EXTENT = %Ld)\n", pvfs_lb, pvfs_extent); #endif ret = PVFS_Request_resized(*tmp_pvfs_dtype, pvfs_lb, pvfs_extent, pvfs_dtype); if (ret != 0) fprintf(stderr, "Error in PVFS_Request_resize\n"); PVFS_Request_free(tmp_pvfs_dtype); ADIOI_Free(tmp_pvfs_dtype); } else /* No MPI_LB or MPI_UB datatypes */ { ret = PVFS_Request_struct(arr_int[0], &arr_int[1], pvfs_arr_disp, old_pvfs_dtype_arr, pvfs_dtype); if (ret != 0) fprintf(stderr, "Error in PVFS_Request_struct\n"); for (i = 0; i < arr_int[0]; i++) { if (arr_dtype[i] != MPI_LB && arr_dtype[i] != MPI_UB) PVFS_Request_free(&old_pvfs_dtype_arr[i]); } #ifdef DEBUG_DTYPE print_dtype_info(combiner, num_int, num_addr, num_dtype, arr_int, arr_addr, arr_dtype); #endif } ADIOI_Free(arr_int); ADIOI_Free(arr_addr); ADIOI_Free(arr_dtype); ADIOI_Free(old_pvfs_dtype_arr); ADIOI_Free(pvfs_arr_disp); ADIOI_Free(pvfs_arr_len); return ret; } /* Shouldn't have gotten here */ fprintf(stderr, "convert_mpi_pvfs2_dtype: SERIOUS ERROR\n"); return -1; }