void ADIO_Get_shared_fp(ADIO_File fd, int incr, ADIO_Offset *shared_fp, int *error_code) { ADIO_Status status; ADIO_Offset new_fp; MPI_Comm dupcommself; #ifdef ROMIO_NFS if (fd->file_system == ADIO_NFS) { ADIOI_NFS_Get_shared_fp(fd, incr, shared_fp, error_code); return; } #endif #ifdef ROMIO_BGL /* BGLOCKLESS won't support shared fp */ if (fd->file_system == ADIO_BGL) { ADIOI_BGL_Get_shared_fp(fd, incr, shared_fp, error_code); return; } #endif if (fd->shared_fp_fd == ADIO_FILE_NULL) { MPI_Comm_dup(MPI_COMM_SELF, &dupcommself); fd->shared_fp_fd = ADIO_Open(MPI_COMM_SELF, dupcommself, fd->shared_fp_fname, fd->file_system, fd->fns, ADIO_CREATE | ADIO_RDWR | ADIO_DELETE_ON_CLOSE, 0, MPI_BYTE, MPI_BYTE, MPI_INFO_NULL, ADIO_PERM_NULL, error_code); if (*error_code != MPI_SUCCESS) return; *shared_fp = 0; ADIOI_WRITE_LOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); ADIO_ReadContig(fd->shared_fp_fd, shared_fp, sizeof(ADIO_Offset), MPI_BYTE, ADIO_EXPLICIT_OFFSET, 0, &status, error_code); /* if the file is empty, the above function may return error (reading beyond end of file). In that case, shared_fp = 0, set above, is the correct value. */ } else { ADIOI_WRITE_LOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); ADIO_ReadContig(fd->shared_fp_fd, shared_fp, sizeof(ADIO_Offset), MPI_BYTE, ADIO_EXPLICIT_OFFSET, 0, &status, error_code); if (*error_code != MPI_SUCCESS) { ADIOI_UNLOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); return; } } if (incr == 0) {goto done;} new_fp = *shared_fp + incr; ADIO_WriteContig(fd->shared_fp_fd, &new_fp, sizeof(ADIO_Offset), MPI_BYTE, ADIO_EXPLICIT_OFFSET, 0, &status, error_code); done: ADIOI_UNLOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); }
void ADIO_Get_shared_fp(ADIO_File fd, ADIO_Offset incr, ADIO_Offset *shared_fp, int *error_code) { ADIO_Status status; ADIO_Offset new_fp; MPI_Comm dupcommself; /* Set the shared_fp in case this comes from an uninitialized stack variable The read routines will not read into the address of this variable if the file size of a shared pointer is 0, and if incr is always zero, this value will remain uninitialized. Initialize it here to prevent incorrect values */ *shared_fp = 0; #ifdef ROMIO_NFS if (fd->file_system == ADIO_NFS) { ADIOI_NFS_Get_shared_fp(fd, incr, shared_fp, error_code); return; } #endif if (fd->shared_fp_fd == ADIO_FILE_NULL) { MPI_Comm_dup(MPI_COMM_SELF, &dupcommself); fd->shared_fp_fd = ADIO_Open(MPI_COMM_SELF, dupcommself, fd->shared_fp_fname, fd->file_system, fd->fns, ADIO_CREATE | ADIO_RDWR | ADIO_DELETE_ON_CLOSE, 0, MPI_BYTE, MPI_BYTE, MPI_INFO_NULL, ADIO_PERM_NULL, error_code); if (*error_code != MPI_SUCCESS) return; ADIOI_WRITE_LOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); ADIO_ReadContig(fd->shared_fp_fd, shared_fp, sizeof(ADIO_Offset), MPI_BYTE, ADIO_EXPLICIT_OFFSET, 0, &status, error_code); /* if the file is empty, the above function may return error (reading beyond end of file). In that case, shared_fp = 0, set above, is the correct value. */ } else { ADIOI_WRITE_LOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); ADIO_ReadContig(fd->shared_fp_fd, shared_fp, sizeof(ADIO_Offset), MPI_BYTE, ADIO_EXPLICIT_OFFSET, 0, &status, error_code); if (*error_code != MPI_SUCCESS) { ADIOI_UNLOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); return; } } if (incr == 0) {goto done;} new_fp = *shared_fp + incr; ADIO_WriteContig(fd->shared_fp_fd, &new_fp, sizeof(ADIO_Offset), MPI_BYTE, ADIO_EXPLICIT_OFFSET, 0, &status, error_code); done: ADIOI_UNLOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); }
void ADIOI_NFS_ReadContig(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { int err=-1, datatype_size, len; #ifndef PRINT_ERR_MSG static char myname[] = "ADIOI_NFS_READCONTIG"; #endif MPI_Type_size(datatype, &datatype_size); len = datatype_size * count; if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { if (fd->fp_sys_posn != offset) lseek(fd->fd_sys, offset, SEEK_SET); if (fd->atomicity) ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); else ADIOI_READ_LOCK(fd, offset, SEEK_SET, len); err = read(fd->fd_sys, buf, len); ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_sys_posn = offset + err; /* individual file pointer not updated */ } else { /* read from curr. location of ind. file pointer */ offset = fd->fp_ind; if (fd->fp_sys_posn != fd->fp_ind) lseek(fd->fd_sys, fd->fp_ind, SEEK_SET); if (fd->atomicity) ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); else ADIOI_READ_LOCK(fd, offset, SEEK_SET, len); err = read(fd->fd_sys, buf, len); ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_ind += err; fd->fp_sys_posn = fd->fp_ind; } #ifdef HAVE_STATUS_SET_BYTES if (err != -1) MPIR_Status_set_bytes(status, datatype, err); #endif #ifdef PRINT_ERR_MSG *error_code = (err == -1) ? MPI_ERR_UNKNOWN : MPI_SUCCESS; #else if (err == -1) { *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, myname, "I/O Error", "%s", strerror(errno)); ADIOI_Error(fd, *error_code, myname); } else *error_code = MPI_SUCCESS; #endif }
void ADIOI_NFS_ReadContig(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { int err=-1, datatype_size, len; static char myname[] = "ADIOI_NFS_READCONTIG"; MPI_Type_size(datatype, &datatype_size); len = datatype_size * count; if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { if (fd->fp_sys_posn != offset) lseek(fd->fd_sys, offset, SEEK_SET); if (fd->atomicity) ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); else ADIOI_READ_LOCK(fd, offset, SEEK_SET, len); err = read(fd->fd_sys, buf, len); ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_sys_posn = offset + err; /* individual file pointer not updated */ } else { /* read from curr. location of ind. file pointer */ offset = fd->fp_ind; if (fd->fp_sys_posn != fd->fp_ind) lseek(fd->fd_sys, fd->fp_ind, SEEK_SET); if (fd->atomicity) ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); else ADIOI_READ_LOCK(fd, offset, SEEK_SET, len); err = read(fd->fd_sys, buf, len); ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_ind += err; fd->fp_sys_posn = fd->fp_ind; } /* --BEGIN ERROR HANDLING-- */ if (err == -1) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); return; } /* --END ERROR HANDLING-- */ #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, err); #endif *error_code = MPI_SUCCESS; }
void ADIO_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, int *error_code) { ADIO_Status status; MPI_Comm dupcommself; #ifdef ROMIO_NFS if (fd->file_system == ADIO_NFS) { ADIOI_NFS_Set_shared_fp(fd, offset, error_code); return; } #endif if (fd->shared_fp_fd == ADIO_FILE_NULL) { MPI_Comm_dup(MPI_COMM_SELF, &dupcommself); fd->shared_fp_fd = ADIO_Open(MPI_COMM_SELF, dupcommself, fd->shared_fp_fname, fd->file_system, fd->fns, ADIO_CREATE | ADIO_RDWR | ADIO_DELETE_ON_CLOSE, 0, MPI_BYTE, MPI_BYTE, MPI_INFO_NULL, ADIO_PERM_NULL, error_code); } if (*error_code != MPI_SUCCESS) return; ADIOI_WRITE_LOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); ADIO_WriteContig(fd->shared_fp_fd, &offset, sizeof(ADIO_Offset), MPI_BYTE, ADIO_EXPLICIT_OFFSET, 0, &status, error_code); ADIOI_UNLOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); }
void ADIOI_BGL_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, int *error_code) { int err; MPI_Comm dupcommself; static char myname[] = "ADIOI_BGL_SET_SHARED_FP"; if (fd->shared_fp_fd == ADIO_FILE_NULL) { MPI_Comm_dup(MPI_COMM_SELF, &dupcommself); fd->shared_fp_fd = ADIO_Open(MPI_COMM_SELF, dupcommself, fd->shared_fp_fname, fd->file_system, fd->fns, ADIO_CREATE | ADIO_RDWR | ADIO_DELETE_ON_CLOSE, 0, MPI_BYTE, MPI_BYTE, MPI_INFO_NULL, ADIO_PERM_NULL, error_code); } if (*error_code != MPI_SUCCESS) return; ADIOI_WRITE_LOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); lseek(fd->shared_fp_fd->fd_sys, 0, SEEK_SET); err = write(fd->shared_fp_fd->fd_sys, &offset, sizeof(ADIO_Offset)); ADIOI_UNLOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); if (err == -1) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); } else *error_code = MPI_SUCCESS; }
void ADIOI_NFS_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, int *error_code) { int err; MPI_Comm dupcommself; #ifndef PRINT_ERR_MSG static char myname[] = "ADIOI_NFS_SET_SHARED_FP"; #endif if (fd->shared_fp_fd == ADIO_FILE_NULL) { MPI_Comm_dup(MPI_COMM_SELF, &dupcommself); fd->shared_fp_fd = ADIO_Open(MPI_COMM_SELF, dupcommself, fd->shared_fp_fname, fd->file_system, ADIO_CREATE | ADIO_RDWR | ADIO_DELETE_ON_CLOSE, 0, MPI_BYTE, MPI_BYTE, M_ASYNC, MPI_INFO_NULL, ADIO_PERM_NULL, error_code); } if (*error_code != MPI_SUCCESS) return; ADIOI_WRITE_LOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); lseek(fd->shared_fp_fd->fd_sys, 0, SEEK_SET); err = write(fd->shared_fp_fd->fd_sys, &offset, sizeof(ADIO_Offset)); ADIOI_UNLOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); #ifdef PRINT_ERR_MSG *error_code = (err == -1) ? MPI_ERR_UNKNOWN : MPI_SUCCESS; #else if (err == -1) { *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, myname, "I/O Error", "%s", strerror(errno)); ADIOI_Error(fd, *error_code, myname); } else *error_code = MPI_SUCCESS; #endif }
void ADIOI_NFS_WriteContig(ADIO_File fd, const void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { ssize_t err=-1; MPI_Count datatype_size, len; ADIO_Offset bytes_xfered=0; size_t wr_count; static char myname[] = "ADIOI_NFS_WRITECONTIG"; char *p; MPI_Type_size_x(datatype, &datatype_size); len = datatype_size * (ADIO_Offset)count; if (file_ptr_type == ADIO_INDIVIDUAL) { offset = fd->fp_ind; } p = (char *)buf; while (bytes_xfered < len) { #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); #endif wr_count = len - bytes_xfered; /* work around FreeBSD and OS X defects*/ if (wr_count > INT_MAX) wr_count = INT_MAX; ADIOI_WRITE_LOCK(fd, offset+bytes_xfered, SEEK_SET, wr_count); err = pwrite(fd->fd_sys, p, wr_count, offset+bytes_xfered); /* --BEGIN ERROR HANDLING-- */ if (err == -1) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); fd->fp_sys_posn = -1; return; } /* --END ERROR HANDLING-- */ #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); #endif ADIOI_UNLOCK(fd, offset+bytes_xfered, SEEK_SET, wr_count); bytes_xfered += err; p += err; } fd->fp_sys_posn = offset + bytes_xfered; if (file_ptr_type == ADIO_INDIVIDUAL) { fd->fp_ind += bytes_xfered; } #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, bytes_xfered); #endif *error_code = MPI_SUCCESS; }
void ADIOI_NFS_ReadContig(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { ssize_t err=-1; MPI_Count datatype_size, len; ADIO_Offset bytes_xfered=0; size_t rd_count; static char myname[] = "ADIOI_NFS_READCONTIG"; char *p; MPI_Type_size_x(datatype, &datatype_size); len = datatype_size * count; if (file_ptr_type == ADIO_INDIVIDUAL) { offset = fd->fp_ind; } p = buf; while (bytes_xfered < len ) { rd_count = len - bytes_xfered; /* FreeBSD and Darwin workaround: bigger than INT_MAX is an error */ if (rd_count > INT_MAX) rd_count = INT_MAX; if (fd->atomicity) ADIOI_WRITE_LOCK(fd, offset+bytes_xfered, SEEK_SET, rd_count); else ADIOI_READ_LOCK(fd, offset+bytes_xfered, SEEK_SET, rd_count); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); #endif err = pread(fd->fd_sys, p, rd_count, offset+bytes_xfered); /* --BEGIN ERROR HANDLING-- */ if (err == -1) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); } /* --END ERROR HANDLING-- */ #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); #endif ADIOI_UNLOCK(fd, offset+bytes_xfered, SEEK_SET, rd_count); if (err == 0) { /* end of file */ break; } bytes_xfered += err; p += err; } fd->fp_sys_posn = offset + bytes_xfered; if (file_ptr_type == ADIO_INDIVIDUAL) { fd->fp_ind += bytes_xfered; } /* --END ERROR HANDLING-- */ #ifdef HAVE_STATUS_SET_BYTES if (err != -1) MPIR_Status_set_bytes(status, datatype, bytes_xfered); #endif *error_code = MPI_SUCCESS; }
int ADIOI_NFS_aio(ADIO_File fd, void *buf, int len, ADIO_Offset offset, int wr, MPI_Request *request) { int err=-1, fd_sys; int error_code, this_errno; struct aiocb *aiocbp; ADIOI_AIO_Request *aio_req; fd_sys = fd->fd_sys; aio_req = (ADIOI_AIO_Request*)ADIOI_Calloc(sizeof(ADIOI_AIO_Request), 1); aiocbp = (struct aiocb *) ADIOI_Calloc(sizeof(struct aiocb), 1); aiocbp->aio_offset = offset; aiocbp->aio_buf = buf; aiocbp->aio_nbytes = len; #ifdef ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_WHENCE aiocbp->aio_whence = SEEK_SET; #endif #ifdef ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_FILDES aiocbp->aio_fildes = fd_sys; #endif #ifdef ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_SIGEVENT # ifdef AIO_SIGNOTIFY_NONE aiocbp->aio_sigevent.sigev_notify = SIGEV_NONE; # endif aiocbp->aio_sigevent.sigev_signo = 0; #endif #ifdef ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_REQPRIO # ifdef AIO_PRIO_DFL aiocbp->aio_reqprio = AIO_PRIO_DFL; /* not needed in DEC Unix 4.0 */ # else aiocbp->aio_reqprio = 0; # endif #endif if (wr) ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); else ADIOI_READ_LOCK(fd, offset, SEEK_SET, len); #ifndef ROMIO_HAVE_AIO_CALLS_NEED_FILEDES if (wr) err = aio_write(aiocbp); else err = aio_read(aiocbp); #else /* Broken IBM interface */ if (wr) err = aio_write(fd_sys, aiocbp); else err = aio_read(fd_sys, aiocbp); #endif this_errno = errno; ADIOI_UNLOCK(fd, offset, SEEK_SET, len); if (err == -1) { if (this_errno == EAGAIN) { /* exceeded the max. no. of outstanding requests. complete all previous async. requests and try again. */ ADIO_WriteContig(fd, buf, len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, offset, NULL, &error_code); MPIO_Completed_request_create(&fd, len, &error_code, request); return 0; } else { return -this_errno; } } aio_req->aiocbp = aiocbp; if (ADIOI_GEN_greq_class == 0) { MPIX_Grequest_class_create(ADIOI_GEN_aio_query_fn, ADIOI_GEN_aio_free_fn, MPIU_Greq_cancel_fn, ADIOI_GEN_aio_poll_fn, ADIOI_GEN_aio_wait_fn, &ADIOI_GEN_greq_class); } MPIX_Grequest_class_allocate(ADIOI_GEN_greq_class, aio_req, request); memcpy(&(aio_req->req), request, sizeof(MPI_Request)); return 0; }
/*@ MPI_File_iread_shared - Nonblocking read using shared file pointer Input Parameters: . fh - file handle (handle) . count - number of elements in buffer (nonnegative integer) . datatype - datatype of each buffer element (handle) Output Parameters: . buf - initial address of buffer (choice) . request - request object (handle) .N fortran @*/ int MPI_File_iread_shared(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Request *request) { int error_code, buftype_is_contig, filetype_is_contig; ADIO_Offset bufsize; ADIO_File adio_fh; static char myname[] = "MPI_FILE_IREAD_SHARED"; MPI_Count datatype_size, incr; MPI_Status status; ADIO_Offset off, shared_fp; MPI_Offset nbytes=0; MPIU_THREAD_CS_ENTER(ALLFUNC,); adio_fh = MPIO_File_resolve(fh); /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); MPIO_CHECK_COUNT(adio_fh, count, myname, error_code); MPIO_CHECK_DATATYPE(adio_fh, datatype, myname, error_code); /* --END ERROR HANDLING-- */ MPI_Type_size_x(datatype, &datatype_size); /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_INTEGRAL_ETYPE(adio_fh, count, datatype_size, myname, error_code); MPIO_CHECK_FS_SUPPORTS_SHARED(adio_fh, myname, error_code); MPIO_CHECK_COUNT_SIZE(adio_fh, count, datatype_size, myname, error_code); /* --END ERROR HANDLING-- */ ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(adio_fh->filetype, &filetype_is_contig); ADIOI_TEST_DEFERRED(adio_fh, myname, &error_code); incr = (count*datatype_size)/adio_fh->etype_size; ADIO_Get_shared_fp(adio_fh, incr, &shared_fp, &error_code); /* --BEGIN ERROR HANDLING-- */ if (error_code != MPI_SUCCESS) { /* note: ADIO_Get_shared_fp should have set up error code already? */ MPIO_Err_return_file(adio_fh, error_code); } /* --END ERROR HANDLING-- */ if (buftype_is_contig && filetype_is_contig) { /* convert count and shared_fp to bytes */ bufsize = datatype_size * count; off = adio_fh->disp + adio_fh->etype_size * shared_fp; if (!(adio_fh->atomicity)) { ADIO_IreadContig(adio_fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, off, request, &error_code); } else { /* to maintain strict atomicity semantics with other concurrent operations, lock (exclusive) and call blocking routine */ if (adio_fh->file_system != ADIO_NFS) { ADIOI_WRITE_LOCK(adio_fh, off, SEEK_SET, bufsize); } ADIO_ReadContig(adio_fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, off, &status, &error_code); if (adio_fh->file_system != ADIO_NFS) { ADIOI_UNLOCK(adio_fh, off, SEEK_SET, bufsize); } if (error_code == MPI_SUCCESS){ nbytes = count * datatype_size; } MPIO_Completed_request_create(&adio_fh, nbytes, &error_code, request); } } else { ADIO_IreadStrided(adio_fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, shared_fp, request, &error_code); } /* --BEGIN ERROR HANDLING-- */ if (error_code != MPI_SUCCESS) error_code = MPIO_Err_return_file(adio_fh, error_code); /* --END ERROR HANDLING-- */ fn_exit: MPIU_THREAD_CS_EXIT(ALLFUNC,); return error_code; }
void ADIOI_NFS_WriteContig(ADIO_File fd, const void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { int err=-1; MPI_Count datatype_size, len; static char myname[] = "ADIOI_NFS_WRITECONTIG"; MPI_Type_size_x(datatype, &datatype_size); len = datatype_size * count; if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { if (fd->fp_sys_posn != offset) { #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); #endif lseek(fd->fd_sys, offset, SEEK_SET); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); #endif } ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); #endif err = write(fd->fd_sys, buf, len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); #endif ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_sys_posn = offset + err; /* individual file pointer not updated */ } else { /* write from curr. location of ind. file pointer */ offset = fd->fp_ind; if (fd->fp_sys_posn != fd->fp_ind) { #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); #endif lseek(fd->fd_sys, fd->fp_ind, SEEK_SET); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); #endif } ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); #endif err = write(fd->fd_sys, buf, len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); #endif ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_ind += err; fd->fp_sys_posn = fd->fp_ind; } /* --BEGIN ERROR HANDLING-- */ if (err == -1) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); return; } /* --END ERROR HANDLING-- */ #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, err); #endif *error_code = MPI_SUCCESS; }
/* * ADIOI_Sync_thread_start - start the synchronisation routine */ void *ADIOI_Sync_thread_start(void *ptr) { ADIOI_Sync_thread_t t = (ADIOI_Sync_thread_t)ptr; ADIOI_Atomic_queue_t q = (ADIOI_Atomic_queue_t)t->sub_; ADIOI_Sync_req_t r; size_t wr_count; MPI_Count datatype_size; char *buf; ADIO_Offset bytes_xfered, len, buf_size, offset, off; int type, count, fflags, error_code; ADIO_Request *req; MPI_Datatype datatype; /* get sync buffer size */ t->fd_; buf_size = t->fd_->hints->ind_wr_buffer_size; buf = (char *)ADIOI_Malloc(buf_size); for(;;) { /* get a new sync request */ #ifndef _USE_PTHREAD_MUTEX_ if ((r = ADIOI_Atomic_queue_front(q)) == NULL) continue; #else r = ADIOI_Atomic_queue_front(q); #endif /* pop sync request */ ADIOI_Atomic_queue_pop(q); /* get request type */ ADIOI_Sync_req_get_key(r, ADIOI_SYNC_TYPE, &type); /* check for shutdown type */ if (type == ADIOI_THREAD_SHUTDOWN) { break; } /* if sync type get all the fields */ ADIOI_Sync_req_get_key(r, ADIOI_SYNC_ALL, &offset, &datatype, &count, &req, &error_code, &fflags); /* init I/O req */ MPI_Type_size_x(datatype, &datatype_size); len = (ADIO_Offset)datatype_size * (ADIO_Offset)count; bytes_xfered = 0; off = offset; /* satisfy sync req */ while (bytes_xfered < len) { wr_count = (size_t)ADIOI_MIN(buf_size, len - bytes_xfered); #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_thread_read_a, 0, NULL); #endif /* read data from cache file */ pread(t->fd_->cache_fd->fd_sys, buf, wr_count, offset); #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_thread_read_b, 0, NULL); MPE_Log_event(ADIOI_MPE_thread_write_a, 0, NULL); #endif /* write data to global file */ pwrite(t->fd_->fd_sys, buf, wr_count, offset); #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_thread_write_b, 0, NULL); #endif /* update offset */ bytes_xfered += (ADIO_Offset)wr_count; offset += (ADIO_Offset)wr_count; } /* unlock extent locked in ADIO_WriteContig() */ if (t->fd_->hints->e10_cache_coherent == ADIOI_HINT_ENABLE) ADIOI_UNLOCK(t->fd_, off, SEEK_SET, len); /* ---Begin Error Handling--- */ /* --- End Error Handling --- */ /* complete Grequest */ MPI_Grequest_complete(*req); } ADIOI_Free(buf); pthread_exit(NULL); }
void ADIOI_GEN_ReadStrided_naive(ADIO_File fd, void *buf, int count, MPI_Datatype buftype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { /* offset is in units of etype relative to the filetype. */ ADIOI_Flatlist_node *flat_buf, *flat_file; int brd_size, frd_size=0, b_index; int bufsize, size, sum, n_etypes_in_filetype, size_in_filetype; int n_filetypes, etype_in_filetype; ADIO_Offset abs_off_in_filetype=0; int filetype_size, etype_size, buftype_size, req_len; MPI_Aint filetype_extent, buftype_extent; int buf_count, buftype_is_contig, filetype_is_contig; ADIO_Offset userbuf_off; ADIO_Offset off, req_off, disp, end_offset=0, start_off; ADIO_Status status1; *error_code = MPI_SUCCESS; /* changed below if error */ ADIOI_Datatype_iscontig(buftype, &buftype_is_contig); ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); MPI_Type_size(fd->filetype, &filetype_size); if ( ! filetype_size ) { *error_code = MPI_SUCCESS; return; } MPI_Type_extent(fd->filetype, &filetype_extent); MPI_Type_size(buftype, &buftype_size); MPI_Type_extent(buftype, &buftype_extent); etype_size = fd->etype_size; bufsize = buftype_size * count; /* contiguous in buftype and filetype is handled elsewhere */ if (!buftype_is_contig && filetype_is_contig) { int b_count; /* noncontiguous in memory, contiguous in file. */ ADIOI_Flatten_datatype(buftype); flat_buf = ADIOI_Flatlist; while (flat_buf->type != buftype) flat_buf = flat_buf->next; off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : fd->disp + etype_size * offset; start_off = off; end_offset = off + bufsize - 1; /* if atomicity is true, lock (exclusive) the region to be accessed */ if ((fd->atomicity) && (fd->file_system != ADIO_PIOFS) && (fd->file_system != ADIO_PVFS)) { ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); } /* for each region in the buffer, grab the data and put it in * place */ for (b_count=0; b_count < count; b_count++) { for (b_index=0; b_index < flat_buf->count; b_index++) { userbuf_off = b_count*buftype_extent + flat_buf->indices[b_index]; req_off = off; req_len = flat_buf->blocklens[b_index]; ADIO_ReadContig(fd, (char *) buf + userbuf_off, req_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, req_off, &status1, error_code); if (*error_code != MPI_SUCCESS) return; /* off is (potentially) used to save the final offset later */ off += flat_buf->blocklens[b_index]; } } if ((fd->atomicity) && (fd->file_system != ADIO_PIOFS) && (fd->file_system != ADIO_PVFS)) { ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); } if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; } else { /* noncontiguous in file */ int f_index, st_frd_size, st_index = 0, st_n_filetypes; int flag; /* First we're going to calculate a set of values for use in all * the noncontiguous in file cases: * start_off - starting byte position of data in file * end_offset - last byte offset to be acessed in the file * st_n_filetypes - how far into the file we start in terms of * whole filetypes * st_index - index of block in first filetype that we will be * starting in (?) * st_frd_size - size of the data in the first filetype block * that we will read (accounts for being part-way * into reading this block of the filetype * */ /* filetype already flattened in ADIO_Open */ flat_file = ADIOI_Flatlist; while (flat_file->type != fd->filetype) flat_file = flat_file->next; disp = fd->disp; if (file_ptr_type == ADIO_INDIVIDUAL) { start_off = fd->fp_ind; /* in bytes */ n_filetypes = -1; flag = 0; while (!flag) { n_filetypes++; for (f_index=0; f_index < flat_file->count; f_index++) { if (disp + flat_file->indices[f_index] + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[f_index] >= start_off) { /* this block contains our starting position */ st_index = f_index; frd_size = (int) (disp + flat_file->indices[f_index] + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[f_index] - start_off); flag = 1; break; } } } } else { n_etypes_in_filetype = filetype_size/etype_size; n_filetypes = (int) (offset / n_etypes_in_filetype); etype_in_filetype = (int) (offset % n_etypes_in_filetype); size_in_filetype = etype_in_filetype * etype_size; sum = 0; for (f_index=0; f_index < flat_file->count; f_index++) { sum += flat_file->blocklens[f_index]; if (sum > size_in_filetype) { st_index = f_index; frd_size = sum - size_in_filetype; abs_off_in_filetype = flat_file->indices[f_index] + size_in_filetype - (sum - flat_file->blocklens[f_index]); break; } } /* abs. offset in bytes in the file */ start_off = disp + (ADIO_Offset) n_filetypes*filetype_extent + abs_off_in_filetype; } st_frd_size = frd_size; st_n_filetypes = n_filetypes; /* start_off, st_n_filetypes, st_index, and st_frd_size are * all calculated at this point */ /* Calculate end_offset, the last byte-offset that will be accessed. * e.g., if start_off=0 and 100 bytes to be read, end_offset=99 */ userbuf_off = 0; f_index = st_index; off = start_off; frd_size = ADIOI_MIN(st_frd_size, bufsize); while (userbuf_off < bufsize) { userbuf_off += frd_size; end_offset = off + frd_size - 1; if (f_index < (flat_file->count - 1)) f_index++; else { f_index = 0; n_filetypes++; } off = disp + flat_file->indices[f_index] + (ADIO_Offset) n_filetypes*filetype_extent; frd_size = ADIOI_MIN(flat_file->blocklens[f_index], bufsize-(int)userbuf_off); } /* End of calculations. At this point the following values have * been calculated and are ready for use: * - start_off * - end_offset * - st_n_filetypes * - st_index * - st_frd_size */ /* if atomicity is true, lock (exclusive) the region to be accessed */ if ((fd->atomicity) && (fd->file_system != ADIO_PIOFS) && (fd->file_system != ADIO_PVFS)) { ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); } if (buftype_is_contig && !filetype_is_contig) { /* contiguous in memory, noncontiguous in file. should be the * most common case. */ userbuf_off = 0; f_index = st_index; off = start_off; n_filetypes = st_n_filetypes; frd_size = ADIOI_MIN(st_frd_size, bufsize); /* while there is still space in the buffer, read more data */ while (userbuf_off < bufsize) { if (frd_size) { /* TYPE_UB and TYPE_LB can result in frd_size = 0. save system call in such cases */ req_off = off; req_len = frd_size; ADIO_ReadContig(fd, (char *) buf + userbuf_off, req_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, req_off, &status1, error_code); if (*error_code != MPI_SUCCESS) return; } userbuf_off += frd_size; if (off + frd_size < disp + flat_file->indices[f_index] + flat_file->blocklens[f_index] + (ADIO_Offset) n_filetypes*filetype_extent) { /* important that this value be correct, as it is * used to set the offset in the fd near the end of * this function. */ off += frd_size; } /* did not reach end of contiguous block in filetype. * no more I/O needed. off is incremented by frd_size. */ else { if (f_index < (flat_file->count - 1)) f_index++; else { f_index = 0; n_filetypes++; } off = disp + flat_file->indices[f_index] + (ADIO_Offset) n_filetypes*filetype_extent; frd_size = ADIOI_MIN(flat_file->blocklens[f_index], bufsize-(int)userbuf_off); } } } else { int i, tmp_bufsize = 0; /* noncontiguous in memory as well as in file */ ADIOI_Flatten_datatype(buftype); flat_buf = ADIOI_Flatlist; while (flat_buf->type != buftype) flat_buf = flat_buf->next; b_index = buf_count = 0; i = (int) (flat_buf->indices[0]); f_index = st_index; off = start_off; n_filetypes = st_n_filetypes; frd_size = st_frd_size; brd_size = flat_buf->blocklens[0]; /* while we haven't read size * count bytes, keep going */ while (tmp_bufsize < bufsize) { int new_brd_size = brd_size, new_frd_size = frd_size; size = ADIOI_MIN(frd_size, brd_size); if (size) { req_off = off; req_len = size; userbuf_off = i; ADIO_ReadContig(fd, (char *) buf + userbuf_off, req_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, req_off, &status1, error_code); if (*error_code != MPI_SUCCESS) return; } if (size == frd_size) { /* reached end of contiguous block in file */ if (f_index < (flat_file->count - 1)) f_index++; else { f_index = 0; n_filetypes++; } off = disp + flat_file->indices[f_index] + (ADIO_Offset) n_filetypes*filetype_extent; new_frd_size = flat_file->blocklens[f_index]; if (size != brd_size) { i += size; new_brd_size -= size; } } if (size == brd_size) { /* reached end of contiguous block in memory */ b_index = (b_index + 1)%flat_buf->count; buf_count++; i = (int) (buftype_extent*(buf_count/flat_buf->count) + flat_buf->indices[b_index]); new_brd_size = flat_buf->blocklens[b_index]; if (size != frd_size) { off += size; new_frd_size -= size; } } tmp_bufsize += size; frd_size = new_frd_size; brd_size = new_brd_size; } } /* unlock the file region if we locked it */ if ((fd->atomicity) && (fd->file_system != ADIO_PIOFS) && (fd->file_system != ADIO_PVFS)) { ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); } if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; } /* end of (else noncontiguous in file) */ fd->fp_sys_posn = -1; /* mark it as invalid. */ #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, buftype, bufsize); /* This is a temporary way of filling in status. The right way is to * keep track of how much data was actually read and placed in buf */ #endif if (!buftype_is_contig) ADIOI_Delete_flattened(buftype); }
void ADIOI_NFS_Get_shared_fp(ADIO_File fd, int incr, ADIO_Offset *shared_fp, int *error_code) { ADIO_Offset new_fp; int err; MPI_Comm dupcommself; static char myname[] = "ADIOI_NFS_GET_SHARED_FP"; if (fd->shared_fp_fd == ADIO_FILE_NULL) { MPI_Comm_dup(MPI_COMM_SELF, &dupcommself); fd->shared_fp_fd = ADIO_Open(MPI_COMM_SELF, dupcommself, fd->shared_fp_fname, fd->file_system, fd->fns, ADIO_CREATE | ADIO_RDWR | ADIO_DELETE_ON_CLOSE, 0, MPI_BYTE, MPI_BYTE, MPI_INFO_NULL, ADIO_PERM_NULL, error_code); if (*error_code != MPI_SUCCESS) return; *shared_fp = 0; ADIOI_WRITE_LOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); #endif err = read(fd->shared_fp_fd->fd_sys, shared_fp, sizeof(ADIO_Offset)); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); #endif /* if the file is empty, the above read may return error (reading beyond end of file). In that case, shared_fp = 0, set above, is the correct value. */ } else { ADIOI_WRITE_LOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); #endif err = lseek(fd->shared_fp_fd->fd_sys, 0, SEEK_SET); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); #endif if (err == 0) { #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); #endif err = read(fd->shared_fp_fd->fd_sys, shared_fp, sizeof(ADIO_Offset)); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); #endif } if (err == -1) { ADIOI_UNLOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); return; } } if (incr == 0) {goto done;} new_fp = *shared_fp + incr; #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); #endif err = lseek(fd->shared_fp_fd->fd_sys, 0, SEEK_SET); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); #endif if (err == 0) { #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); #endif err = write(fd->shared_fp_fd->fd_sys, &new_fp, sizeof(ADIO_Offset)); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); #endif } done: ADIOI_UNLOCK(fd->shared_fp_fd, 0, SEEK_SET, sizeof(ADIO_Offset)); if (err == -1) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); } else *error_code = MPI_SUCCESS; }
/*@ MPI_File_write_shared - Write using shared file pointer Input Parameters: . fh - file handle (handle) . buf - initial address of buffer (choice) . count - number of elements in buffer (nonnegative integer) . datatype - datatype of each buffer element (handle) Output Parameters: . status - status object (Status) .N fortran @*/ int MPI_File_write_shared(MPI_File mpi_fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) { int error_code, bufsize, buftype_is_contig, filetype_is_contig; static char myname[] = "MPI_FILE_READ_SHARED"; int datatype_size, incr; ADIO_Offset off, shared_fp; ADIO_File fh; MPIU_THREAD_SINGLE_CS_ENTER("io"); MPIR_Nest_incr(); fh = MPIO_File_resolve(mpi_fh); /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_FILE_HANDLE(fh, myname, error_code); MPIO_CHECK_COUNT(fh, count, myname, error_code); MPIO_CHECK_DATATYPE(fh, datatype, myname, error_code); /* --END ERROR HANDLING-- */ MPI_Type_size(datatype, &datatype_size); if (count*datatype_size == 0) { #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, 0); #endif error_code = MPI_SUCCESS; goto fn_exit; } /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_INTEGRAL_ETYPE(fh, count, datatype_size, myname, error_code); MPIO_CHECK_FS_SUPPORTS_SHARED(fh, myname, error_code); /* --END ERROR HANDLING-- */ ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fh->filetype, &filetype_is_contig); ADIOI_TEST_DEFERRED(fh, myname, &error_code); incr = (count*datatype_size)/fh->etype_size; ADIO_Get_shared_fp(fh, incr, &shared_fp, &error_code); /* --BEGIN ERROR HANDLING-- */ if (error_code != MPI_SUCCESS) { error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, myname, __LINE__, MPI_ERR_INTERN, "**iosharedfailed", 0); error_code = MPIO_Err_return_file(fh, error_code); goto fn_exit; } /* --END ERROR HANDLING-- */ if (buftype_is_contig && filetype_is_contig) { /* convert bufocunt and shared_fp to bytes */ bufsize = datatype_size * count; off = fh->disp + fh->etype_size * shared_fp; /* if atomic mode requested, lock (exclusive) the region, because there could be a concurrent noncontiguous request. On NFS, locking is done in the ADIO_WriteContig.*/ if ((fh->atomicity) && (fh->file_system != ADIO_NFS)) ADIOI_WRITE_LOCK(fh, off, SEEK_SET, bufsize); ADIO_WriteContig(fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, off, status, &error_code); if ((fh->atomicity) && (fh->file_system != ADIO_NFS)) ADIOI_UNLOCK(fh, off, SEEK_SET, bufsize); } else { ADIO_WriteStrided(fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, shared_fp, status, &error_code); /* For strided and atomic mode, locking is done in ADIO_WriteStrided */ } /* --BEGIN ERROR HANDLING-- */ if (error_code != MPI_SUCCESS) error_code = MPIO_Err_return_file(fh, error_code); /* --END ERROR HANDLING-- */ fn_exit: MPIR_Nest_decr(); MPIU_THREAD_SINGLE_CS_EXIT("io"); return error_code; }
void ADIOI_GEN_ReadStrided(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { /* offset is in units of etype relative to the filetype. */ ADIOI_Flatlist_node *flat_buf, *flat_file; int i, j, k, brd_size, frd_size=0, st_index=0; int bufsize, num, size, sum, n_etypes_in_filetype, size_in_filetype; int n_filetypes, etype_in_filetype; ADIO_Offset abs_off_in_filetype=0; int filetype_size, etype_size, buftype_size, req_len, partial_read; MPI_Aint filetype_extent, buftype_extent; int buf_count, buftype_is_contig, filetype_is_contig; ADIO_Offset userbuf_off; ADIO_Offset off, req_off, disp, end_offset=0, readbuf_off, start_off; char *readbuf, *tmp_buf, *value; int flag, st_frd_size, st_n_filetypes, readbuf_len; int new_brd_size, new_frd_size, info_flag, max_bufsize; ADIO_Status status1; if (fd->hints->ds_read == ADIOI_HINT_DISABLE) { /* if user has disabled data sieving on reads, use naive * approach instead. */ ADIOI_GEN_ReadStrided_naive(fd, buf, count, datatype, file_ptr_type, offset, status, error_code); return; } *error_code = MPI_SUCCESS; /* changed below if error */ ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); MPI_Type_size(fd->filetype, &filetype_size); if ( ! filetype_size ) { *error_code = MPI_SUCCESS; return; } MPI_Type_extent(fd->filetype, &filetype_extent); MPI_Type_size(datatype, &buftype_size); MPI_Type_extent(datatype, &buftype_extent); etype_size = fd->etype_size; bufsize = buftype_size * count; /* get max_bufsize from the info object. */ value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); MPI_Info_get(fd->info, "ind_rd_buffer_size", MPI_MAX_INFO_VAL, value, &info_flag); max_bufsize = atoi(value); ADIOI_Free(value); if (!buftype_is_contig && filetype_is_contig) { /* noncontiguous in memory, contiguous in file. */ ADIOI_Flatten_datatype(datatype); flat_buf = ADIOI_Flatlist; while (flat_buf->type != datatype) flat_buf = flat_buf->next; off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : fd->disp + etype_size * offset; start_off = off; end_offset = off + bufsize - 1; readbuf_off = off; readbuf = (char *) ADIOI_Malloc(max_bufsize); readbuf_len = (int) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1)); /* if atomicity is true, lock (exclusive) the region to be accessed */ if ((fd->atomicity) && (fd->file_system != ADIO_PIOFS) && (fd->file_system != ADIO_PVFS)) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); ADIO_ReadContig(fd, readbuf, readbuf_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, readbuf_off, &status1, error_code); if (*error_code != MPI_SUCCESS) return; for (j=0; j<count; j++) for (i=0; i<flat_buf->count; i++) { userbuf_off = j*buftype_extent + flat_buf->indices[i]; req_off = off; req_len = flat_buf->blocklens[i]; ADIOI_BUFFERED_READ off += flat_buf->blocklens[i]; } if ((fd->atomicity) && (fd->file_system != ADIO_PIOFS) && (fd->file_system != ADIO_PVFS)) ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; ADIOI_Free(readbuf); } else { /* noncontiguous in file */ /* filetype already flattened in ADIO_Open */ flat_file = ADIOI_Flatlist; while (flat_file->type != fd->filetype) flat_file = flat_file->next; disp = fd->disp; if (file_ptr_type == ADIO_INDIVIDUAL) { offset = fd->fp_ind; /* in bytes */ n_filetypes = -1; flag = 0; while (!flag) { n_filetypes++; for (i=0; i<flat_file->count; i++) { if (disp + flat_file->indices[i] + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[i] >= offset) { st_index = i; frd_size = (int) (disp + flat_file->indices[i] + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[i] - offset); flag = 1; break; } } } } else { n_etypes_in_filetype = filetype_size/etype_size; n_filetypes = (int) (offset / n_etypes_in_filetype); etype_in_filetype = (int) (offset % n_etypes_in_filetype); size_in_filetype = etype_in_filetype * etype_size; sum = 0; for (i=0; i<flat_file->count; i++) { sum += flat_file->blocklens[i]; if (sum > size_in_filetype) { st_index = i; frd_size = sum - size_in_filetype; abs_off_in_filetype = flat_file->indices[i] + size_in_filetype - (sum - flat_file->blocklens[i]); break; } } /* abs. offset in bytes in the file */ offset = disp + (ADIO_Offset) n_filetypes*filetype_extent + abs_off_in_filetype; } start_off = offset; /* Calculate end_offset, the last byte-offset that will be accessed. e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/ st_frd_size = frd_size; st_n_filetypes = n_filetypes; i = 0; j = st_index; off = offset; frd_size = ADIOI_MIN(st_frd_size, bufsize); while (i < bufsize) { i += frd_size; end_offset = off + frd_size - 1; if (j < (flat_file->count - 1)) j++; else { j = 0; n_filetypes++; } off = disp + flat_file->indices[j] + (ADIO_Offset) n_filetypes*filetype_extent; frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i); } /* if atomicity is true, lock (exclusive) the region to be accessed */ if ((fd->atomicity) && (fd->file_system != ADIO_PIOFS) && (fd->file_system != ADIO_PVFS)) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); readbuf_off = 0; readbuf_len = 0; readbuf = (char *) ADIOI_Malloc(max_bufsize); if (buftype_is_contig && !filetype_is_contig) { /* contiguous in memory, noncontiguous in file. should be the most common case. */ i = 0; j = st_index; off = offset; n_filetypes = st_n_filetypes; frd_size = ADIOI_MIN(st_frd_size, bufsize); while (i < bufsize) { if (frd_size) { /* TYPE_UB and TYPE_LB can result in frd_size = 0. save system call in such cases */ /* lseek(fd->fd_sys, off, SEEK_SET); err = read(fd->fd_sys, ((char *) buf) + i, frd_size);*/ req_off = off; req_len = frd_size; userbuf_off = i; ADIOI_BUFFERED_READ } i += frd_size; if (off + frd_size < disp + flat_file->indices[j] + flat_file->blocklens[j] + (ADIO_Offset) n_filetypes*filetype_extent) off += frd_size; /* did not reach end of contiguous block in filetype. no more I/O needed. off is incremented by frd_size. */ else { if (j < (flat_file->count - 1)) j++; else { j = 0; n_filetypes++; } off = disp + flat_file->indices[j] + (ADIO_Offset) n_filetypes*filetype_extent; frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i); } } } else {
int MPIOI_File_iwrite(MPI_File mpi_fh, MPI_Offset offset, int file_ptr_type, void *buf, int count, MPI_Datatype datatype, char *myname, MPI_Request *request) { int error_code, bufsize, buftype_is_contig, filetype_is_contig; int datatype_size; ADIO_Status status; ADIO_Offset off; ADIO_File fh; MPI_Offset nbytes=0; fh = MPIO_File_resolve(mpi_fh); /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_FILE_HANDLE(fh, myname, error_code); MPIO_CHECK_COUNT(fh, count, myname, error_code); MPIO_CHECK_DATATYPE(fh, datatype, myname, error_code); if (file_ptr_type == ADIO_EXPLICIT_OFFSET && offset < 0) { error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_ARG, "**iobadoffset", 0); error_code = MPIO_Err_return_file(fh, error_code); goto fn_exit; } /* --END ERROR HANDLING-- */ MPI_Type_size(datatype, &datatype_size); /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_INTEGRAL_ETYPE(fh, count, datatype_size, myname, error_code); MPIO_CHECK_WRITABLE(fh, myname, error_code); MPIO_CHECK_NOT_SEQUENTIAL_MODE(fh, myname, error_code); MPIO_CHECK_COUNT_SIZE(fh, count, datatype_size, myname, error_code); /* --END ERROR HANDLING-- */ ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fh->filetype, &filetype_is_contig); ADIOI_TEST_DEFERRED(fh, myname, &error_code); if (buftype_is_contig && filetype_is_contig) { /* convert sizes to bytes */ bufsize = datatype_size * count; if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { off = fh->disp + fh->etype_size * offset; } else { off = fh->fp_ind; } if (!(fh->atomicity)) { ADIO_IwriteContig(fh, buf, count, datatype, file_ptr_type, off, request, &error_code); } else { /* to maintain strict atomicity semantics with other concurrent operations, lock (exclusive) and call blocking routine */ if (ADIO_Feature(fh, ADIO_LOCKS) ) { ADIOI_WRITE_LOCK(fh, off, SEEK_SET, bufsize); } ADIO_WriteContig(fh, buf, count, datatype, file_ptr_type, off, &status, &error_code); if (ADIO_Feature(fh, ADIO_LOCKS) ) { ADIOI_UNLOCK(fh, off, SEEK_SET, bufsize); } if (error_code == MPI_SUCCESS) { nbytes = count * datatype_size; } MPIO_Completed_request_create(&fh, nbytes, &error_code, request); } } else { ADIO_IwriteStrided(fh, buf, count, datatype, file_ptr_type, offset, request, &error_code); } fn_exit: return error_code; }
void ADIOI_NFS_WriteStrided(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { /* offset is in units of etype relative to the filetype. */ ADIOI_Flatlist_node *flat_buf, *flat_file; int i, j, k, err=-1, bwr_size, fwr_size=0, st_index=0; int bufsize, num, size, sum, n_etypes_in_filetype, size_in_filetype; int n_filetypes, etype_in_filetype; ADIO_Offset abs_off_in_filetype=0; int filetype_size, etype_size, buftype_size, req_len; MPI_Aint filetype_extent, buftype_extent; int buf_count, buftype_is_contig, filetype_is_contig; ADIO_Offset userbuf_off; ADIO_Offset off, req_off, disp, end_offset=0, writebuf_off, start_off; char *writebuf, *value; int flag, st_fwr_size, st_n_filetypes, writebuf_len, write_sz; int new_bwr_size, new_fwr_size, err_flag=0, info_flag, max_bufsize; static char myname[] = "ADIOI_NFS_WRITESTRIDED"; ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); MPI_Type_size(fd->filetype, &filetype_size); if ( ! filetype_size ) { *error_code = MPI_SUCCESS; return; } MPI_Type_extent(fd->filetype, &filetype_extent); MPI_Type_size(datatype, &buftype_size); MPI_Type_extent(datatype, &buftype_extent); etype_size = fd->etype_size; bufsize = buftype_size * count; /* get max_bufsize from the info object. */ value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); MPI_Info_get(fd->info, "ind_wr_buffer_size", MPI_MAX_INFO_VAL, value, &info_flag); max_bufsize = atoi(value); ADIOI_Free(value); if (!buftype_is_contig && filetype_is_contig) { /* noncontiguous in memory, contiguous in file. */ ADIOI_Flatten_datatype(datatype); flat_buf = ADIOI_Flatlist; while (flat_buf->type != datatype) flat_buf = flat_buf->next; off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : fd->disp + etype_size * offset; start_off = off; end_offset = off + bufsize - 1; writebuf_off = off; writebuf = (char *) ADIOI_Malloc(max_bufsize); writebuf_len = (int) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1)); /* if atomicity is true, lock the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); for (j=0; j<count; j++) for (i=0; i<flat_buf->count; i++) { userbuf_off = j*buftype_extent + flat_buf->indices[i]; req_off = off; req_len = flat_buf->blocklens[i]; ADIOI_BUFFERED_WRITE_WITHOUT_READ off += flat_buf->blocklens[i]; } /* write the buffer out finally */ lseek(fd->fd_sys, writebuf_off, SEEK_SET); if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); err = write(fd->fd_sys, writebuf, writebuf_len); if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); if (err == -1) err_flag = 1; if (fd->atomicity) ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); ADIOI_Free(writebuf); /* malloced in the buffered_write macro */ if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; if (err_flag) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); } else *error_code = MPI_SUCCESS; } else { /* noncontiguous in file */ /* filetype already flattened in ADIO_Open */ flat_file = ADIOI_Flatlist; while (flat_file->type != fd->filetype) flat_file = flat_file->next; disp = fd->disp; if (file_ptr_type == ADIO_INDIVIDUAL) { offset = fd->fp_ind; /* in bytes */ n_filetypes = -1; flag = 0; while (!flag) { n_filetypes++; for (i=0; i<flat_file->count; i++) { if (disp + flat_file->indices[i] + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[i] >= offset) { st_index = i; fwr_size = (int) (disp + flat_file->indices[i] + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[i] - offset); flag = 1; break; } } } } else { n_etypes_in_filetype = filetype_size/etype_size; n_filetypes = (int) (offset / n_etypes_in_filetype); etype_in_filetype = (int) (offset % n_etypes_in_filetype); size_in_filetype = etype_in_filetype * etype_size; sum = 0; for (i=0; i<flat_file->count; i++) { sum += flat_file->blocklens[i]; if (sum > size_in_filetype) { st_index = i; fwr_size = sum - size_in_filetype; abs_off_in_filetype = flat_file->indices[i] + size_in_filetype - (sum - flat_file->blocklens[i]); break; } } /* abs. offset in bytes in the file */ offset = disp + (ADIO_Offset) n_filetypes*filetype_extent + abs_off_in_filetype; } start_off = offset; /* Calculate end_offset, the last byte-offset that will be accessed. e.g., if start_offset=0 and 100 bytes to be write, end_offset=99*/ st_fwr_size = fwr_size; st_n_filetypes = n_filetypes; i = 0; j = st_index; off = offset; fwr_size = ADIOI_MIN(st_fwr_size, bufsize); while (i < bufsize) { i += fwr_size; end_offset = off + fwr_size - 1; if (j < (flat_file->count - 1)) j++; else { j = 0; n_filetypes++; } off = disp + flat_file->indices[j] + (ADIO_Offset) n_filetypes*filetype_extent; fwr_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i); } /* if atomicity is true, lock the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); /* initial read for the read-modify-write */ writebuf_off = offset; writebuf = (char *) ADIOI_Malloc(max_bufsize); writebuf_len = (int)(ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1)); if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); lseek(fd->fd_sys, writebuf_off, SEEK_SET); err = read(fd->fd_sys, writebuf, writebuf_len); if (err == -1) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "ADIOI_NFS_WriteStrided: ROMIO tries to optimize this access by doing a read-modify-write, but is unable to read the file. Please give the file read permission and open it with MPI_MODE_RDWR.", 0); return; } if (buftype_is_contig && !filetype_is_contig) { /* contiguous in memory, noncontiguous in file. should be the most common case. */ i = 0; j = st_index; off = offset; n_filetypes = st_n_filetypes; fwr_size = ADIOI_MIN(st_fwr_size, bufsize); while (i < bufsize) { if (fwr_size) { /* TYPE_UB and TYPE_LB can result in fwr_size = 0. save system call in such cases */ /* lseek(fd->fd_sys, off, SEEK_SET); err = write(fd->fd_sys, ((char *) buf) + i, fwr_size);*/ req_off = off; req_len = fwr_size; userbuf_off = i; ADIOI_BUFFERED_WRITE } i += fwr_size; if (off + fwr_size < disp + flat_file->indices[j] + flat_file->blocklens[j] + (ADIO_Offset) n_filetypes*filetype_extent) off += fwr_size; /* did not reach end of contiguous block in filetype. no more I/O needed. off is incremented by fwr_size. */ else { if (j < (flat_file->count - 1)) j++; else { j = 0; n_filetypes++; } off = disp + flat_file->indices[j] + (ADIO_Offset) n_filetypes*filetype_extent; fwr_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i); } } } else {
void ADIOI_NFS_ReadStrided(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { /* offset is in units of etype relative to the filetype. */ ADIOI_Flatlist_node *flat_buf, *flat_file; int i, j, k, err=-1, brd_size, st_index=0; int num, size, sum, n_etypes_in_filetype, size_in_filetype; MPI_Count bufsize; int n_filetypes, etype_in_filetype; ADIO_Offset abs_off_in_filetype=0; int req_len, partial_read; MPI_Count filetype_size, etype_size, buftype_size; MPI_Aint filetype_extent, buftype_extent; int buf_count, buftype_is_contig, filetype_is_contig; ADIO_Offset userbuf_off; ADIO_Offset off, req_off, disp, end_offset=0, readbuf_off, start_off; char *readbuf, *tmp_buf, *value; int st_n_filetypes, readbuf_len; ADIO_Offset frd_size=0, new_frd_size, st_frd_size; int new_brd_size, err_flag=0, info_flag, max_bufsize; static char myname[] = "ADIOI_NFS_READSTRIDED"; ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); MPI_Type_size_x(fd->filetype, &filetype_size); if ( ! filetype_size ) { #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, 0); #endif *error_code = MPI_SUCCESS; return; } MPI_Type_extent(fd->filetype, &filetype_extent); MPI_Type_size_x(datatype, &buftype_size); MPI_Type_extent(datatype, &buftype_extent); etype_size = fd->etype_size; bufsize = buftype_size * count; /* get max_bufsize from the info object. */ value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); ADIOI_Info_get(fd->info, "ind_rd_buffer_size", MPI_MAX_INFO_VAL, value, &info_flag); max_bufsize = atoi(value); ADIOI_Free(value); if (!buftype_is_contig && filetype_is_contig) { /* noncontiguous in memory, contiguous in file. */ ADIOI_Flatten_datatype(datatype); flat_buf = ADIOI_Flatlist; while (flat_buf->type != datatype) flat_buf = flat_buf->next; off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : fd->disp + etype_size * offset; start_off = off; end_offset = off + bufsize - 1; readbuf_off = off; readbuf = (char *) ADIOI_Malloc(max_bufsize); readbuf_len = (int) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1)); /* if atomicity is true, lock (exclusive) the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); #endif lseek(fd->fd_sys, readbuf_off, SEEK_SET); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); #endif if (!(fd->atomicity)) ADIOI_READ_LOCK(fd, readbuf_off, SEEK_SET, readbuf_len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); #endif err = read(fd->fd_sys, readbuf, readbuf_len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); #endif if (!(fd->atomicity)) ADIOI_UNLOCK(fd, readbuf_off, SEEK_SET, readbuf_len); if (err == -1) err_flag = 1; for (j=0; j<count; j++) for (i=0; i<flat_buf->count; i++) { userbuf_off = j*buftype_extent + flat_buf->indices[i]; req_off = off; req_len = flat_buf->blocklens[i]; ADIOI_BUFFERED_READ off += flat_buf->blocklens[i]; } if (fd->atomicity) ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; ADIOI_Free(readbuf); /* malloced in the buffered_read macro */ if (err_flag) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); } else *error_code = MPI_SUCCESS; } else { /* noncontiguous in file */ /* filetype already flattened in ADIO_Open */ flat_file = ADIOI_Flatlist; while (flat_file->type != fd->filetype) flat_file = flat_file->next; disp = fd->disp; if (file_ptr_type == ADIO_INDIVIDUAL) { /* Wei-keng reworked type processing to be a bit more efficient */ offset = fd->fp_ind - disp; n_filetypes = (offset - flat_file->indices[0]) / filetype_extent; offset -= (ADIO_Offset)n_filetypes * filetype_extent; /* now offset is local to this extent */ /* find the block where offset is located, skip blocklens[i]==0 */ for (i=0; i<flat_file->count; i++) { ADIO_Offset dist; if (flat_file->blocklens[i] == 0) continue; dist = flat_file->indices[i] + flat_file->blocklens[i] - offset; /* frd_size is from offset to the end of block i */ if (dist == 0) { i++; offset = flat_file->indices[i]; frd_size = flat_file->blocklens[i]; break; } if (dist > 0 ) { frd_size = dist; break; } } st_index = i; /* starting index in flat_file->indices[] */ offset += disp + (ADIO_Offset)n_filetypes*filetype_extent; } else { n_etypes_in_filetype = filetype_size/etype_size; n_filetypes = (int) (offset / n_etypes_in_filetype); etype_in_filetype = (int) (offset % n_etypes_in_filetype); size_in_filetype = etype_in_filetype * etype_size; sum = 0; for (i=0; i<flat_file->count; i++) { sum += flat_file->blocklens[i]; if (sum > size_in_filetype) { st_index = i; frd_size = sum - size_in_filetype; abs_off_in_filetype = flat_file->indices[i] + size_in_filetype - (sum - flat_file->blocklens[i]); break; } } /* abs. offset in bytes in the file */ offset = disp + (ADIO_Offset) n_filetypes*filetype_extent + abs_off_in_filetype; } start_off = offset; /* Wei-keng Liao: read request is within a single flat_file contig * block e.g. with subarray types that actually describe the whole * array */ if (buftype_is_contig && bufsize <= frd_size) { ADIO_ReadContig(fd, buf, bufsize, MPI_BYTE, ADIO_EXPLICIT_OFFSET, offset, status, error_code); if (file_ptr_type == ADIO_INDIVIDUAL) { /* update MPI-IO file pointer to point to the first byte that * can be accessed in the fileview. */ fd->fp_ind = offset + bufsize; if (bufsize == frd_size) { do { st_index++; if (st_index == flat_file->count) { st_index = 0; n_filetypes++; } } while (flat_file->blocklens[st_index] == 0); fd->fp_ind = disp + flat_file->indices[st_index] + n_filetypes*filetype_extent; } } fd->fp_sys_posn = -1; /* set it to null. */ #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, bufsize); #endif return; } /* Calculate end_offset, the last byte-offset that will be accessed. e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/ st_frd_size = frd_size; st_n_filetypes = n_filetypes; i = 0; j = st_index; off = offset; frd_size = ADIOI_MIN(st_frd_size, bufsize); while (i < bufsize) { i += frd_size; end_offset = off + frd_size - 1; j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; while (flat_file->blocklens[j]==0) { j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; } off = disp + flat_file->indices[j] + (ADIO_Offset) n_filetypes*filetype_extent; frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i); } /* if atomicity is true, lock (exclusive) the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); /* initial read into readbuf */ readbuf_off = offset; readbuf = (char *) ADIOI_Malloc(max_bufsize); readbuf_len = (int) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1)); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); #endif lseek(fd->fd_sys, offset, SEEK_SET); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); #endif if (!(fd->atomicity)) ADIOI_READ_LOCK(fd, offset, SEEK_SET, readbuf_len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); #endif err = read(fd->fd_sys, readbuf, readbuf_len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); #endif if (!(fd->atomicity)) ADIOI_UNLOCK(fd, offset, SEEK_SET, readbuf_len); if (err == -1) err_flag = 1; if (buftype_is_contig && !filetype_is_contig) { /* contiguous in memory, noncontiguous in file. should be the most common case. */ i = 0; j = st_index; off = offset; n_filetypes = st_n_filetypes; frd_size = ADIOI_MIN(st_frd_size, bufsize); while (i < bufsize) { if (frd_size) { /* TYPE_UB and TYPE_LB can result in frd_size = 0. save system call in such cases */ /* lseek(fd->fd_sys, off, SEEK_SET); err = read(fd->fd_sys, ((char *) buf) + i, frd_size);*/ req_off = off; req_len = frd_size; userbuf_off = i; ADIOI_BUFFERED_READ } i += frd_size; if (off + frd_size < disp + flat_file->indices[j] + flat_file->blocklens[j] + (ADIO_Offset) n_filetypes*filetype_extent) off += frd_size; /* did not reach end of contiguous block in filetype. no more I/O needed. off is incremented by frd_size. */ else { j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; while (flat_file->blocklens[j]==0) { j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; } off = disp + flat_file->indices[j] + (ADIO_Offset) n_filetypes*filetype_extent; frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i); } } } else {
void ADIOI_NFS_ReadStrided(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { /* offset is in units of etype relative to the filetype. */ ADIOI_Flatlist_node *flat_buf, *flat_file; int i, j, k, err=-1, brd_size, frd_size=0, st_index=0; int bufsize, num, size, sum, n_etypes_in_filetype, size_in_filetype; int n_filetypes, etype_in_filetype; ADIO_Offset abs_off_in_filetype=0; int filetype_size, etype_size, buftype_size, req_len, partial_read; MPI_Aint filetype_extent, buftype_extent; int buf_count, buftype_is_contig, filetype_is_contig; ADIO_Offset userbuf_off; ADIO_Offset off, req_off, disp, end_offset, readbuf_off, start_off; char *readbuf, *tmp_buf, *value; int flag, st_frd_size, st_n_filetypes, readbuf_len; int new_brd_size, new_frd_size, err_flag=0, info_flag, max_bufsize; #ifndef PRINT_ERR_MSG static char myname[] = "ADIOI_NFS_READSTRIDED"; #endif ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); MPI_Type_size(fd->filetype, &filetype_size); MPI_Type_extent(fd->filetype, &filetype_extent); MPI_Type_size(datatype, &buftype_size); MPI_Type_extent(datatype, &buftype_extent); etype_size = fd->etype_size; bufsize = buftype_size * count; /* get max_bufsize from the info object. */ value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); MPI_Info_get(fd->info, "ind_rd_buffer_size", MPI_MAX_INFO_VAL, value, &info_flag); max_bufsize = atoi(value); ADIOI_Free(value); if (!buftype_is_contig && filetype_is_contig) { /* noncontiguous in memory, contiguous in file. */ ADIOI_Flatten_datatype(datatype); flat_buf = ADIOI_Flatlist; while (flat_buf->type != datatype) flat_buf = flat_buf->next; off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : fd->disp + etype_size * offset; start_off = off; end_offset = off + bufsize - 1; readbuf_off = off; readbuf = (char *) ADIOI_Malloc(max_bufsize); readbuf_len = (int) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1)); /* if atomicity is true, lock (exclusive) the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); lseek(fd->fd_sys, readbuf_off, SEEK_SET); if (!(fd->atomicity)) ADIOI_READ_LOCK(fd, readbuf_off, SEEK_SET, readbuf_len); err = read(fd->fd_sys, readbuf, readbuf_len); if (!(fd->atomicity)) ADIOI_UNLOCK(fd, readbuf_off, SEEK_SET, readbuf_len); if (err == -1) err_flag = 1; for (j=0; j<count; j++) for (i=0; i<flat_buf->count; i++) { userbuf_off = j*buftype_extent + flat_buf->indices[i]; req_off = off; req_len = flat_buf->blocklens[i]; ADIOI_BUFFERED_READ off += flat_buf->blocklens[i]; } if (fd->atomicity) ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; ADIOI_Free(readbuf); /* malloced in the buffered_read macro */ #ifdef PRINT_ERR_MSG *error_code = (err_flag) ? MPI_ERR_UNKNOWN : MPI_SUCCESS; #else if (err_flag) { *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, myname, "I/O Error", "%s", strerror(errno)); ADIOI_Error(fd, *error_code, myname); } else *error_code = MPI_SUCCESS; #endif } else { /* noncontiguous in file */ /* filetype already flattened in ADIO_Open */ flat_file = ADIOI_Flatlist; while (flat_file->type != fd->filetype) flat_file = flat_file->next; disp = fd->disp; if (file_ptr_type == ADIO_INDIVIDUAL) { offset = fd->fp_ind; /* in bytes */ n_filetypes = -1; flag = 0; while (!flag) { n_filetypes++; for (i=0; i<flat_file->count; i++) { if (disp + flat_file->indices[i] + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[i] >= offset) { st_index = i; frd_size = (int) (disp + flat_file->indices[i] + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[i] - offset); flag = 1; break; } } } } else { n_etypes_in_filetype = filetype_size/etype_size; n_filetypes = (int) (offset / n_etypes_in_filetype); etype_in_filetype = (int) (offset % n_etypes_in_filetype); size_in_filetype = etype_in_filetype * etype_size; sum = 0; for (i=0; i<flat_file->count; i++) { sum += flat_file->blocklens[i]; if (sum > size_in_filetype) { st_index = i; frd_size = sum - size_in_filetype; abs_off_in_filetype = flat_file->indices[i] + size_in_filetype - (sum - flat_file->blocklens[i]); break; } } /* abs. offset in bytes in the file */ offset = disp + (ADIO_Offset) n_filetypes*filetype_extent + abs_off_in_filetype; } start_off = offset; /* Calculate end_offset, the last byte-offset that will be accessed. e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/ st_frd_size = frd_size; st_n_filetypes = n_filetypes; i = 0; j = st_index; off = offset; frd_size = ADIOI_MIN(st_frd_size, bufsize); while (i < bufsize) { i += frd_size; end_offset = off + frd_size - 1; if (j < (flat_file->count - 1)) j++; else { j = 0; n_filetypes++; } off = disp + flat_file->indices[j] + (ADIO_Offset) n_filetypes*filetype_extent; frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i); } /* if atomicity is true, lock (exclusive) the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); /* initial read into readbuf */ readbuf_off = offset; readbuf = (char *) ADIOI_Malloc(max_bufsize); readbuf_len = (int) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1)); lseek(fd->fd_sys, offset, SEEK_SET); if (!(fd->atomicity)) ADIOI_READ_LOCK(fd, offset, SEEK_SET, readbuf_len); err = read(fd->fd_sys, readbuf, readbuf_len); if (!(fd->atomicity)) ADIOI_UNLOCK(fd, offset, SEEK_SET, readbuf_len); if (err == -1) err_flag = 1; if (buftype_is_contig && !filetype_is_contig) { /* contiguous in memory, noncontiguous in file. should be the most common case. */ i = 0; j = st_index; off = offset; n_filetypes = st_n_filetypes; frd_size = ADIOI_MIN(st_frd_size, bufsize); while (i < bufsize) { if (frd_size) { /* TYPE_UB and TYPE_LB can result in frd_size = 0. save system call in such cases */ /* lseek(fd->fd_sys, off, SEEK_SET); err = read(fd->fd_sys, ((char *) buf) + i, frd_size);*/ req_off = off; req_len = frd_size; userbuf_off = i; ADIOI_BUFFERED_READ } i += frd_size; if (off + frd_size < disp + flat_file->indices[j] + flat_file->blocklens[j] + (ADIO_Offset) n_filetypes*filetype_extent) off += frd_size; /* did not reach end of contiguous block in filetype. no more I/O needed. off is incremented by frd_size. */ else { if (j < (flat_file->count - 1)) j++; else { j = 0; n_filetypes++; } off = disp + flat_file->indices[j] + (ADIO_Offset) n_filetypes*filetype_extent; frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i); } } } else {
int MPIOI_File_read(MPI_File fh, MPI_Offset offset, int file_ptr_type, void *buf, int count, MPI_Datatype datatype, char *myname, MPI_Status *status) { int error_code, buftype_is_contig, filetype_is_contig; MPI_Count datatype_size; ADIO_File adio_fh; ADIO_Offset off, bufsize; void *xbuf=NULL, *e32_buf=NULL; ROMIO_THREAD_CS_ENTER(); adio_fh = MPIO_File_resolve(fh); /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); MPIO_CHECK_COUNT(adio_fh, count, myname, error_code); MPIO_CHECK_DATATYPE(adio_fh, datatype, myname, error_code); if (file_ptr_type == ADIO_EXPLICIT_OFFSET && offset < 0) { error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_ARG, "**iobadoffset", 0); error_code = MPIO_Err_return_file(adio_fh, error_code); goto fn_exit; } /* --END ERROR HANDLING-- */ MPI_Type_size_x(datatype, &datatype_size); /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_COUNT_SIZE(adio_fh, count, datatype_size, myname, error_code); /* --END ERROR HANDLING-- */ if (count*datatype_size == 0) { #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, 0); #endif error_code = MPI_SUCCESS; goto fn_exit; } /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_INTEGRAL_ETYPE(adio_fh, count, datatype_size, myname, error_code); MPIO_CHECK_READABLE(adio_fh, myname, error_code); MPIO_CHECK_NOT_SEQUENTIAL_MODE(adio_fh, myname, error_code); /* --END ERROR HANDLING-- */ ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(adio_fh->filetype, &filetype_is_contig); ADIOI_TEST_DEFERRED(adio_fh, myname, &error_code); xbuf = buf; if (adio_fh->is_external32) { MPI_Aint e32_size = 0; error_code = MPIU_datatype_full_size(datatype, &e32_size); if (error_code != MPI_SUCCESS) goto fn_exit; e32_buf = ADIOI_Malloc(e32_size*count); xbuf = e32_buf; } if (buftype_is_contig && filetype_is_contig) { /* convert count and offset to bytes */ bufsize = datatype_size * count; if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { off = adio_fh->disp + adio_fh->etype_size * offset; } else /* ADIO_INDIVIDUAL */ { off = adio_fh->fp_ind; } /* if atomic mode requested, lock (exclusive) the region, because there could be a concurrent noncontiguous request. */ if ((adio_fh->atomicity) && ADIO_Feature(adio_fh, ADIO_LOCKS)) { ADIOI_WRITE_LOCK(adio_fh, off, SEEK_SET, bufsize); } ADIO_ReadContig(adio_fh, xbuf, count, datatype, file_ptr_type, off, status, &error_code); if ((adio_fh->atomicity) && ADIO_Feature(adio_fh, ADIO_LOCKS)) { ADIOI_UNLOCK(adio_fh, off, SEEK_SET, bufsize); } } else { ADIO_ReadStrided(adio_fh, xbuf, count, datatype, file_ptr_type, offset, status, &error_code); /* For strided and atomic mode, locking is done in ADIO_ReadStrided */ } /* --BEGIN ERROR HANDLING-- */ if (error_code != MPI_SUCCESS) error_code = MPIO_Err_return_file(adio_fh, error_code); /* --END ERROR HANDLING-- */ if (e32_buf != NULL) { error_code = MPIU_read_external32_conversion_fn(buf, datatype, count, e32_buf); ADIOI_Free(e32_buf); } fn_exit: ROMIO_THREAD_CS_EXIT(); return error_code; }
void ADIOI_BGL_WriteContig(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { int err=-1, datatype_size; ADIO_Offset len; static char myname[] = "ADIOI_BGL_WRITECONTIG"; #ifdef AGGREGATION_PROFILE MPE_Log_event (5036, 0, NULL); #endif #if BGL_PROFILE /* timing */ double io_time, io_time2; if (bglmpio_timing) { io_time = MPI_Wtime(); bglmpio_prof_cw[ BGLMPIO_CIO_DATA_SIZE ] += len; } #endif MPI_Type_size(datatype, &datatype_size); len = (ADIO_Offset)datatype_size * (ADIO_Offset)count; ADIOI_Assert(len == (unsigned int) len); /* write takes an unsigned int parm */ #if BGL_PROFILE if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { if (bglmpio_timing2) io_time2 = MPI_Wtime(); if (fd->fp_sys_posn != offset) lseek(fd->fd_sys, offset, SEEK_SET); if (bglmpio_timing2) bglmpio_prof_cw[ BGLMPIO_CIO_T_SEEK ] += (MPI_Wtime() - io_time2); ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); if (bglmpio_timing2) io_time2 = MPI_Wtime(); err = write(fd->fd_sys, buf, (unsigned int)len); if (bglmpio_timing2) bglmpio_prof_cw[ BGLMPIO_CIO_T_POSI_RW ] += (MPI_Wtime() - io_time2); ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_sys_posn = offset + err; /* individual file pointer not updated */ } else { /* write from curr. location of ind. file pointer */ offset = fd->fp_ind; if (bglmpio_timing2) io_time2 = MPI_Wtime(); if (fd->fp_sys_posn != fd->fp_ind) lseek(fd->fd_sys, fd->fp_ind, SEEK_SET); if (bglmpio_timing2) bglmpio_prof_cw[ BGLMPIO_CIO_T_SEEK ] += (MPI_Wtime() - io_time2); ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); if (bglmpio_timing2) io_time2 = MPI_Wtime(); err = write(fd->fd_sys, buf, (unsigned int)len); if (bglmpio_timing2) bglmpio_prof_cw[ BGLMPIO_CIO_T_POSI_RW ] += (MPI_Wtime() - io_time2); ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_ind += err; fd->fp_sys_posn = fd->fp_ind; } #else /* BGL_PROFILE */ if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { if (fd->fp_sys_posn != offset) lseek(fd->fd_sys, offset, SEEK_SET); ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); err = write(fd->fd_sys, buf, (unsigned int)len); ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_sys_posn = offset + err; /* individual file pointer not updated */ } else { /* write from curr. location of ind. file pointer */ offset = fd->fp_ind; if (fd->fp_sys_posn != fd->fp_ind) lseek(fd->fd_sys, fd->fp_ind, SEEK_SET); ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); err = write(fd->fd_sys, buf, (unsigned int)len); ADIOI_UNLOCK(fd, offset, SEEK_SET, len); fd->fp_ind += err; fd->fp_sys_posn = fd->fp_ind; } #endif /* BGL_PROFILE */ #if BGL_PROFILE if (bglmpio_timing) bglmpio_prof_cw[ BGLMPIO_CIO_T_MPIO_RW ] += (MPI_Wtime() - io_time); #endif /* --BEGIN ERROR HANDLING-- */ if (err == -1) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); return; } /* --END ERROR HANDLING-- */ #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, err); #endif *error_code = MPI_SUCCESS; #ifdef AGGREGATION_PROFILE MPE_Log_event (5037, 0, NULL); #endif }
int MPIOI_File_read(MPI_File mpi_fh, MPI_Offset offset, int file_ptr_type, void *buf, int count, MPI_Datatype datatype, char *myname, MPI_Status *status) { int error_code, bufsize, buftype_is_contig, filetype_is_contig; int datatype_size; ADIO_File fh; ADIO_Offset off; MPID_CS_ENTER(); MPIR_Nest_incr(); fh = MPIO_File_resolve(mpi_fh); /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_FILE_HANDLE(fh, myname, error_code); MPIO_CHECK_COUNT(fh, count, myname, error_code); MPIO_CHECK_DATATYPE(fh, datatype, myname, error_code); if (file_ptr_type == ADIO_EXPLICIT_OFFSET && offset < 0) { error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_ARG, "**iobadoffset", 0); error_code = MPIO_Err_return_file(fh, error_code); goto fn_exit; } /* --END ERROR HANDLING-- */ MPI_Type_size(datatype, &datatype_size); if (count*datatype_size == 0) { #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, 0); #endif error_code = MPI_SUCCESS; goto fn_exit; } /* --BEGIN ERROR HANDLING-- */ MPIO_CHECK_INTEGRAL_ETYPE(fh, count, datatype_size, myname, error_code); MPIO_CHECK_READABLE(fh, myname, error_code); MPIO_CHECK_NOT_SEQUENTIAL_MODE(fh, myname, error_code); /* --END ERROR HANDLING-- */ ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fh->filetype, &filetype_is_contig); ADIOI_TEST_DEFERRED(fh, myname, &error_code); if (buftype_is_contig && filetype_is_contig) { /* convert count and offset to bytes */ bufsize = datatype_size * count; if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { off = fh->disp + fh->etype_size * offset; } else /* ADIO_INDIVIDUAL */ { off = fh->fp_ind; } /* if atomic mode requested, lock (exclusive) the region, because there could be a concurrent noncontiguous request. Locking doesn't work on PIOFS and PVFS, and on NFS it is done in the ADIO_ReadContig. */ if ((fh->atomicity) && (fh->file_system != ADIO_PIOFS) && (fh->file_system != ADIO_NFS) && (fh->file_system != ADIO_PVFS) && (fh->file_system != ADIO_PVFS2)) ADIOI_WRITE_LOCK(fh, off, SEEK_SET, bufsize); ADIO_ReadContig(fh, buf, count, datatype, file_ptr_type, off, status, &error_code); if ((fh->atomicity) && (fh->file_system != ADIO_PIOFS) && (fh->file_system != ADIO_NFS) && (fh->file_system != ADIO_PVFS) && (fh->file_system != ADIO_PVFS2)) ADIOI_UNLOCK(fh, off, SEEK_SET, bufsize); } else { ADIO_ReadStrided(fh, buf, count, datatype, file_ptr_type, offset, status, &error_code); /* For strided and atomic mode, locking is done in ADIO_ReadStrided */ } fn_exit: MPIR_Nest_decr(); MPID_CS_EXIT(); return error_code; }
void ADIOI_NFS_WriteStrided(ADIO_File fd, const void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status * status, int *error_code) { /* offset is in units of etype relative to the filetype. */ ADIOI_Flatlist_node *flat_buf, *flat_file; int i, j, k, err = -1, bwr_size, st_index = 0; ADIO_Offset i_offset, sum, size_in_filetype; ADIO_Offset num, size, n_etypes_in_filetype; MPI_Count bufsize; ADIO_Offset n_filetypes, etype_in_filetype; ADIO_Offset abs_off_in_filetype = 0; int req_len; MPI_Count filetype_size, etype_size, buftype_size; MPI_Aint filetype_extent, buftype_extent; int buf_count, buftype_is_contig, filetype_is_contig; ADIO_Offset userbuf_off; ADIO_Offset off, req_off, disp, end_offset = 0, writebuf_off, start_off; char *writebuf = NULL, *value; int st_n_filetypes, writebuf_len, write_sz; ADIO_Offset fwr_size = 0, new_fwr_size, st_fwr_size; int new_bwr_size, err_flag = 0, info_flag, max_bufsize; static char myname[] = "ADIOI_NFS_WRITESTRIDED"; ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); MPI_Type_size_x(fd->filetype, &filetype_size); if (!filetype_size) { #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, 0); #endif *error_code = MPI_SUCCESS; return; } MPI_Type_extent(fd->filetype, &filetype_extent); MPI_Type_size_x(datatype, &buftype_size); MPI_Type_extent(datatype, &buftype_extent); etype_size = fd->etype_size; bufsize = buftype_size * count; /* get max_bufsize from the info object. */ value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL + 1) * sizeof(char)); ADIOI_Info_get(fd->info, "ind_wr_buffer_size", MPI_MAX_INFO_VAL, value, &info_flag); max_bufsize = atoi(value); ADIOI_Free(value); if (!buftype_is_contig && filetype_is_contig) { /* noncontiguous in memory, contiguous in file. */ flat_buf = ADIOI_Flatten_and_find(datatype); off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : fd->disp + etype_size * offset; start_off = off; end_offset = off + bufsize - 1; writebuf_off = off; writebuf = (char *) ADIOI_Malloc(max_bufsize); writebuf_len = (int) (MPL_MIN(max_bufsize, end_offset - writebuf_off + 1)); /* if atomicity is true, lock the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset - start_off + 1); for (j = 0; j < count; j++) for (i = 0; i < flat_buf->count; i++) { userbuf_off = j * buftype_extent + flat_buf->indices[i]; req_off = off; req_len = flat_buf->blocklens[i]; ADIOI_BUFFERED_WRITE_WITHOUT_READ off += flat_buf->blocklens[i]; } /* write the buffer out finally */ #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_lseek_a, 0, NULL); #endif lseek(fd->fd_sys, writebuf_off, SEEK_SET); #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_lseek_b, 0, NULL); #endif if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_write_a, 0, NULL); #endif err = write(fd->fd_sys, writebuf, writebuf_len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_write_b, 0, NULL); #endif if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); if (err == -1) err_flag = 1; if (fd->atomicity) ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset - start_off + 1); if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; if (err_flag) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", "**io %s", strerror(errno)); } else *error_code = MPI_SUCCESS; } else { /* noncontiguous in file */ flat_file = ADIOI_Flatten_and_find(fd->filetype); disp = fd->disp; if (file_ptr_type == ADIO_INDIVIDUAL) { /* Wei-keng reworked type processing to be a bit more efficient */ offset = fd->fp_ind - disp; n_filetypes = (offset - flat_file->indices[0]) / filetype_extent; offset -= (ADIO_Offset) n_filetypes *filetype_extent; /* now offset is local to this extent */ /* find the block where offset is located, skip blocklens[i]==0 */ for (i = 0; i < flat_file->count; i++) { ADIO_Offset dist; if (flat_file->blocklens[i] == 0) continue; dist = flat_file->indices[i] + flat_file->blocklens[i] - offset; /* fwr_size is from offset to the end of block i */ if (dist == 0) { i++; offset = flat_file->indices[i]; fwr_size = flat_file->blocklens[i]; break; } if (dist > 0) { fwr_size = dist; break; } } st_index = i; /* starting index in flat_file->indices[] */ offset += disp + (ADIO_Offset) n_filetypes *filetype_extent; } else { n_etypes_in_filetype = filetype_size / etype_size; n_filetypes = offset / n_etypes_in_filetype; etype_in_filetype = offset % n_etypes_in_filetype; size_in_filetype = etype_in_filetype * etype_size; sum = 0; for (i = 0; i < flat_file->count; i++) { sum += flat_file->blocklens[i]; if (sum > size_in_filetype) { st_index = i; fwr_size = sum - size_in_filetype; abs_off_in_filetype = flat_file->indices[i] + size_in_filetype - (sum - flat_file->blocklens[i]); break; } } /* abs. offset in bytes in the file */ offset = disp + (ADIO_Offset) n_filetypes *filetype_extent + abs_off_in_filetype; } start_off = offset; /* Wei-keng Liao:write request is within single flat_file contig block */ /* this could happen, for example, with subarray types that are * actually fairly contiguous */ if (buftype_is_contig && bufsize <= fwr_size) { /* though MPI api has an integer 'count' parameter, derived * datatypes might describe more bytes than can fit into an integer. * if we've made it this far, we can pass a count of original * datatypes, instead of a count of bytes (which might overflow) * Other WriteContig calls in this path are operating on data * sieving buffer */ ADIO_WriteContig(fd, buf, count, datatype, ADIO_EXPLICIT_OFFSET, offset, status, error_code); if (file_ptr_type == ADIO_INDIVIDUAL) { /* update MPI-IO file pointer to point to the first byte * that can be accessed in the fileview. */ fd->fp_ind = offset + bufsize; if (bufsize == fwr_size) { do { st_index++; if (st_index == flat_file->count) { st_index = 0; n_filetypes++; } } while (flat_file->blocklens[st_index] == 0); fd->fp_ind = disp + flat_file->indices[st_index] + (ADIO_Offset) n_filetypes *filetype_extent; } } fd->fp_sys_posn = -1; /* set it to null. */ #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, bufsize); #endif goto fn_exit; } /* Calculate end_offset, the last byte-offset that will be accessed. * e.g., if start_offset=0 and 100 bytes to be write, end_offset=99 */ st_fwr_size = fwr_size; st_n_filetypes = n_filetypes; i_offset = 0; j = st_index; off = offset; fwr_size = MPL_MIN(st_fwr_size, bufsize); while (i_offset < bufsize) { i_offset += fwr_size; end_offset = off + fwr_size - 1; j = (j + 1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; while (flat_file->blocklens[j] == 0) { j = (j + 1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; } off = disp + flat_file->indices[j] + n_filetypes * (ADIO_Offset) filetype_extent; fwr_size = MPL_MIN(flat_file->blocklens[j], bufsize - i_offset); } /* if atomicity is true, lock the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset - start_off + 1); /* initial read for the read-modify-write */ writebuf_off = offset; writebuf = (char *) ADIOI_Malloc(max_bufsize); memset(writebuf, -1, max_bufsize); writebuf_len = (int) (MPL_MIN(max_bufsize, end_offset - writebuf_off + 1)); if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_lseek_a, 0, NULL); #endif lseek(fd->fd_sys, writebuf_off, SEEK_SET); #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_lseek_b, 0, NULL); #endif #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_read_a, 0, NULL); #endif err = read(fd->fd_sys, writebuf, writebuf_len); #ifdef ADIOI_MPE_LOGGING MPE_Log_event(ADIOI_MPE_read_b, 0, NULL); #endif if (err == -1) { *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "ADIOI_NFS_WriteStrided: ROMIO tries to optimize this access by doing a read-modify-write, but is unable to read the file. Please give the file read permission and open it with MPI_MODE_RDWR.", 0); goto fn_exit; } if (buftype_is_contig && !filetype_is_contig) { /* contiguous in memory, noncontiguous in file. should be the most common case. */ i_offset = 0; j = st_index; off = offset; n_filetypes = st_n_filetypes; fwr_size = MPL_MIN(st_fwr_size, bufsize); while (i_offset < bufsize) { if (fwr_size) { /* TYPE_UB and TYPE_LB can result in * fwr_size = 0. save system call in such cases */ /* lseek(fd->fd_sys, off, SEEK_SET); * err = write(fd->fd_sys, ((char *) buf) + i, fwr_size); */ req_off = off; req_len = fwr_size; userbuf_off = i_offset; ADIOI_BUFFERED_WRITE} i_offset += fwr_size; if (off + fwr_size < disp + flat_file->indices[j] + flat_file->blocklens[j] + n_filetypes * (ADIO_Offset) filetype_extent) off += fwr_size; /* did not reach end of contiguous block in filetype. * no more I/O needed. off is incremented by fwr_size. */ else { j = (j + 1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; while (flat_file->blocklens[j] == 0) { j = (j + 1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; } off = disp + flat_file->indices[j] + n_filetypes * (ADIO_Offset) filetype_extent; fwr_size = MPL_MIN(flat_file->blocklens[j], bufsize - i_offset); } } } else {
/*@ MPI_File_iread_at - Nonblocking read using explict offset Input Parameters: . fh - file handle (handle) . offset - file offset (nonnegative integer) . count - number of elements in buffer (nonnegative integer) . datatype - datatype of each buffer element (handle) Output Parameters: . buf - initial address of buffer (choice) . request - request object (handle) .N fortran @*/ int MPI_File_iread_at(MPI_File fh, MPI_Offset offset, void *buf, int count, MPI_Datatype datatype, MPIO_Request *request) { int error_code, bufsize, buftype_is_contig, filetype_is_contig; #ifndef PRINT_ERR_MSG static char myname[] = "MPI_FILE_IREAD_AT"; #endif int datatype_size; ADIO_Status status; ADIO_Offset off; #ifdef MPI_hpux int fl_xmpi; HPMP_IO_START(fl_xmpi, BLKMPIFILEIREADAT, TRDTSYSTEM, fh, datatype, count); #endif /* MPI_hpux */ #ifdef PRINT_ERR_MSG if ((fh <= (MPI_File) 0) || (fh->cookie != ADIOI_FILE_COOKIE)) { FPRINTF(stderr, "MPI_File_iread_at: Invalid file handle\n"); MPI_Abort(MPI_COMM_WORLD, 1); } #else ADIOI_TEST_FILE_HANDLE(fh, myname); #endif if (offset < 0) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_iread_at: Invalid offset argument\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_ARG, MPIR_ERR_OFFSET_ARG, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } if (count < 0) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_iread_at: Invalid count argument\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_ARG, MPIR_ERR_COUNT_ARG, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } if (datatype == MPI_DATATYPE_NULL) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_iread_at: Invalid datatype\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_TYPE, MPIR_ERR_TYPE_NULL, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } MPI_Type_size(datatype, &datatype_size); if ((count*datatype_size) % fh->etype_size != 0) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_iread_at: Only an integral number of etypes can be accessed\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ERR_ETYPE_FRACTIONAL, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } if (fh->access_mode & MPI_MODE_WRONLY) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_iread_at: Can't read from a file opened with MPI_MODE_WRONLY\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_UNSUPPORTED_OPERATION, MPIR_ERR_MODE_WRONLY, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } if (fh->access_mode & MPI_MODE_SEQUENTIAL) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_iread_at: Can't use this function because file was opened with MPI_MODE_SEQUENTIAL\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_UNSUPPORTED_OPERATION, MPIR_ERR_AMODE_SEQ, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fh->filetype, &filetype_is_contig); /* contiguous or strided? */ if (buftype_is_contig && filetype_is_contig) { /* convert count and offset to bytes */ bufsize = datatype_size * count; off = fh->disp + fh->etype_size * offset; if (!(fh->atomicity)) ADIO_IreadContig(fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, off, request, &error_code); else { /* to maintain strict atomicity semantics with other concurrent operations, lock (exclusive) and call blocking routine */ *request = ADIOI_Malloc_request(); (*request)->optype = ADIOI_READ; (*request)->fd = fh; (*request)->datatype = datatype; (*request)->queued = 0; (*request)->handle = 0; if ((fh->file_system != ADIO_PIOFS) && (fh->file_system != ADIO_NFS) && (fh->file_system != ADIO_PVFS)) ADIOI_WRITE_LOCK(fh, off, SEEK_SET, bufsize); ADIO_ReadContig(fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, off, &status, &error_code); if ((fh->file_system != ADIO_PIOFS) && (fh->file_system != ADIO_NFS) && (fh->file_system != ADIO_PVFS)) ADIOI_UNLOCK(fh, off, SEEK_SET, bufsize); fh->async_count++; /* status info. must be linked to the request structure, so that it can be accessed later from a wait */ } } else ADIO_IreadStrided(fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, offset, request, &error_code); #ifdef MPI_hpux HPMP_IO_END(fl_xmpi, fh, datatype, count); #endif /* MPI_hpux */ return error_code; }
/*@ MPI_File_read_shared - Read using shared file pointer Input Parameters: . fh - file handle (handle) . count - number of elements in buffer (nonnegative integer) . datatype - datatype of each buffer element (handle) Output Parameters: . buf - initial address of buffer (choice) . status - status object (Status) .N fortran @*/ int MPI_File_read_shared(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) { int error_code, bufsize, buftype_is_contig, filetype_is_contig; #ifndef PRINT_ERR_MSG static char myname[] = "MPI_FILE_READ_SHARED"; #endif int datatype_size, incr; ADIO_Offset off, shared_fp; #ifdef PRINT_ERR_MSG if ((fh <= (MPI_File) 0) || (fh->cookie != ADIOI_FILE_COOKIE)) { FPRINTF(stderr, "MPI_File_read_shared: Invalid file handle\n"); MPI_Abort(MPI_COMM_WORLD, 1); } #else ADIOI_TEST_FILE_HANDLE(fh, myname); #endif if (count < 0) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_read_shared: Invalid count argument\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_ARG, MPIR_ERR_COUNT_ARG, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } if (datatype == MPI_DATATYPE_NULL) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_read_shared: Invalid datatype\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_TYPE, MPIR_ERR_TYPE_NULL, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } MPI_Type_size(datatype, &datatype_size); if (count*datatype_size == 0) return MPI_SUCCESS; if ((count*datatype_size) % fh->etype_size != 0) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_read_shared: Only an integral number of etypes can be accessed\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ERR_ETYPE_FRACTIONAL, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } if ((fh->file_system == ADIO_PIOFS) || (fh->file_system == ADIO_PVFS)) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_read_shared: Shared file pointer not supported on PIOFS and PVFS\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_UNSUPPORTED_OPERATION, MPIR_ERR_NO_SHARED_FP, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fh->filetype, &filetype_is_contig); incr = (count*datatype_size)/fh->etype_size; ADIO_Get_shared_fp(fh, incr, &shared_fp, &error_code); if (error_code != MPI_SUCCESS) { FPRINTF(stderr, "MPI_File_read_shared: Error! Could not access shared file pointer.\n"); MPI_Abort(MPI_COMM_WORLD, 1); } /* contiguous or strided? */ if (buftype_is_contig && filetype_is_contig) { /* convert count and shared_fp to bytes */ bufsize = datatype_size * count; off = fh->disp + fh->etype_size * shared_fp; /* if atomic mode requested, lock (exclusive) the region, because there could be a concurrent noncontiguous request. On NFS, locking is done in the ADIO_ReadContig.*/ if ((fh->atomicity) && (fh->file_system != ADIO_NFS)) ADIOI_WRITE_LOCK(fh, off, SEEK_SET, bufsize); ADIO_ReadContig(fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, off, status, &error_code); if ((fh->atomicity) && (fh->file_system != ADIO_NFS)) ADIOI_UNLOCK(fh, off, SEEK_SET, bufsize); } else ADIO_ReadStrided(fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, shared_fp, status, &error_code); /* For strided and atomic mode, locking is done in ADIO_ReadStrided */ return error_code; }
void ADIOI_LUSTRE_WriteStrided(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status * status, int *error_code) { /* offset is in units of etype relative to the filetype. */ ADIOI_Flatlist_node *flat_buf, *flat_file; ADIO_Offset i_offset, sum, size_in_filetype; int i, j, k, st_index=0; int n_etypes_in_filetype; ADIO_Offset num, size, n_filetypes, etype_in_filetype, st_n_filetypes; ADIO_Offset abs_off_in_filetype=0; int filetype_size, etype_size, buftype_size; MPI_Aint filetype_extent, buftype_extent; int buf_count, buftype_is_contig, filetype_is_contig; ADIO_Offset userbuf_off; ADIO_Offset off, req_off, disp, end_offset=0, writebuf_off, start_off; char *writebuf; unsigned bufsize, writebuf_len, write_sz; ADIO_Status status1; ADIO_Offset new_bwr_size, new_fwr_size, st_fwr_size, fwr_size=0, bwr_size, req_len; int stripe_size; static char myname[] = "ADIOI_LUSTRE_WriteStrided"; if (fd->hints->ds_write == ADIOI_HINT_DISABLE) { /* if user has disabled data sieving on writes, use naive * approach instead. */ ADIOI_GEN_WriteStrided_naive(fd, buf, count, datatype, file_ptr_type, offset, status, error_code); return; } *error_code = MPI_SUCCESS; /* changed below if error */ ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); MPI_Type_size(fd->filetype, &filetype_size); if (!filetype_size) { #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, 0); #endif *error_code = MPI_SUCCESS; return; } MPI_Type_extent(fd->filetype, &filetype_extent); MPI_Type_size(datatype, &buftype_size); MPI_Type_extent(datatype, &buftype_extent); etype_size = fd->etype_size; ADIOI_Assert((buftype_size * count) == ((ADIO_Offset)(unsigned)buftype_size * (ADIO_Offset)count)); bufsize = buftype_size * count; /* get striping info */ stripe_size = fd->hints->striping_unit; /* Different buftype to different filetype */ if (!buftype_is_contig && filetype_is_contig) { /* noncontiguous in memory, contiguous in file. */ ADIOI_Flatten_datatype(datatype); flat_buf = ADIOI_Flatlist; while (flat_buf->type != datatype) flat_buf = flat_buf->next; off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : fd->disp + (ADIO_Offset)etype_size * offset; start_off = off; end_offset = start_off + bufsize - 1; /* write stripe size buffer each time */ writebuf = (char *) ADIOI_Malloc(ADIOI_MIN(bufsize, stripe_size)); writebuf_off = 0; writebuf_len = 0; /* if atomicity is true, lock the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, bufsize); for (j = 0; j < count; j++) { for (i = 0; i < flat_buf->count; i++) { userbuf_off = (ADIO_Offset)j * (ADIO_Offset)buftype_extent + flat_buf->indices[i]; req_off = off; req_len = flat_buf->blocklens[i]; ADIOI_BUFFERED_WRITE_WITHOUT_READ off += flat_buf->blocklens[i]; } } /* write the buffer out finally */ ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); if (fd->atomicity) ADIOI_UNLOCK(fd, start_off, SEEK_SET, bufsize); if (*error_code != MPI_SUCCESS) { ADIOI_Free(writebuf); return; } ADIOI_Free(writebuf); if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; } else { /* noncontiguous in file */ /* filetype already flattened in ADIO_Open */ flat_file = ADIOI_Flatlist; while (flat_file->type != fd->filetype) flat_file = flat_file->next; disp = fd->disp; if (file_ptr_type == ADIO_INDIVIDUAL) { /* Wei-keng reworked type processing to be a bit more efficient */ offset = fd->fp_ind - disp; n_filetypes = (offset - flat_file->indices[0]) / filetype_extent; offset -= (ADIO_Offset)n_filetypes * filetype_extent; /* now offset is local to this extent */ /* find the block where offset is located, skip blocklens[i]==0 */ for (i=0; i<flat_file->count; i++) { ADIO_Offset dist; if (flat_file->blocklens[i] == 0) continue; dist = flat_file->indices[i] + flat_file->blocklens[i] - offset; /* fwr_size is from offset to the end of block i */ if (dist == 0) { i++; offset = flat_file->indices[i]; fwr_size = flat_file->blocklens[i]; break; } if (dist > 0) { fwr_size = dist; break; } } st_index = i; /* starting index in flat_file->indices[] */ offset += disp + (ADIO_Offset)n_filetypes*filetype_extent; } else { n_etypes_in_filetype = filetype_size/etype_size; n_filetypes = offset / n_etypes_in_filetype; etype_in_filetype = offset % n_etypes_in_filetype; size_in_filetype = etype_in_filetype * etype_size; sum = 0; for (i = 0; i < flat_file->count; i++) { sum += flat_file->blocklens[i]; if (sum > size_in_filetype) { st_index = i; fwr_size = sum - size_in_filetype; abs_off_in_filetype = flat_file->indices[i] + size_in_filetype - (sum - flat_file->blocklens[i]); break; } } /* abs. offset in bytes in the file */ offset = disp + (ADIO_Offset) n_filetypes *filetype_extent + abs_off_in_filetype; } start_off = offset; /* Wei-keng Liao:write request is within single flat_file * contig block*/ /* this could happen, for example, with subarray types that are * actually fairly contiguous */ if (buftype_is_contig && bufsize <= fwr_size) { req_off = start_off; req_len = bufsize; end_offset = start_off + bufsize - 1; writebuf = (char *) ADIOI_Malloc(ADIOI_MIN(bufsize, stripe_size)); memset(writebuf, -1, ADIOI_MIN(bufsize, stripe_size)); writebuf_off = 0; writebuf_len = 0; userbuf_off = 0; ADIOI_BUFFERED_WRITE_WITHOUT_READ /* write the buffer out finally */ ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); if (file_ptr_type == ADIO_INDIVIDUAL) { /* update MPI-IO file pointer to point to the first byte * that can be accessed in the fileview. */ fd->fp_ind = offset + bufsize; if (bufsize == fwr_size) { do { st_index++; if (st_index == flat_file->count) { st_index = 0; n_filetypes++; } } while (flat_file->blocklens[st_index] == 0); fd->fp_ind = disp + flat_file->indices[st_index] + (ADIO_Offset)n_filetypes*filetype_extent; } } fd->fp_sys_posn = -1; /* set it to null. */ #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, bufsize); #endif ADIOI_Free(writebuf); return; } /* Calculate end_offset, the last byte-offset that will be accessed. e.g., if start_offset=0 and 100 bytes to be write, end_offset=99*/ st_fwr_size = fwr_size; st_n_filetypes = n_filetypes; i_offset = 0; j = st_index; off = offset; fwr_size = ADIOI_MIN(st_fwr_size, bufsize); while (i_offset < bufsize) { i_offset += fwr_size; end_offset = off + fwr_size - 1; j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; while (flat_file->blocklens[j]==0) { j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; } off = disp + flat_file->indices[j] + n_filetypes*(ADIO_Offset)filetype_extent; fwr_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset); } /* if atomicity is true, lock the region to be accessed */ if (fd->atomicity) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); writebuf_off = 0; writebuf_len = 0; writebuf = (char *) ADIOI_Malloc(stripe_size); memset(writebuf, -1, stripe_size); if (buftype_is_contig && !filetype_is_contig) { /* contiguous in memory, noncontiguous in file. should be the most common case. */ i_offset = 0; j = st_index; off = offset; n_filetypes = st_n_filetypes; fwr_size = ADIOI_MIN(st_fwr_size, bufsize); while (i_offset < bufsize) { if (fwr_size) { /* TYPE_UB and TYPE_LB can result in fwr_size = 0. save system call in such cases */ /* lseek(fd->fd_sys, off, SEEK_SET); err = write(fd->fd_sys, ((char *) buf) + i_offset, fwr_size);*/ req_off = off; req_len = fwr_size; userbuf_off = i_offset; ADIOI_BUFFERED_WRITE } i_offset += fwr_size; if (off + fwr_size < disp + flat_file->indices[j] + flat_file->blocklens[j] + n_filetypes*(ADIO_Offset)filetype_extent) off += fwr_size; /* did not reach end of contiguous block in filetype. no more I/O needed. off is incremented by fwr_size. */ else { j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; while (flat_file->blocklens[j]==0) { j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; } off = disp + flat_file->indices[j] + n_filetypes*(ADIO_Offset)filetype_extent; fwr_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset); } } } else {
void ADIOI_GEN_ReadStrided(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, int file_ptr_type, ADIO_Offset offset, ADIO_Status *status, int *error_code) { /* offset is in units of etype relative to the filetype. */ ADIOI_Flatlist_node *flat_buf, *flat_file; ADIO_Offset i_offset, new_brd_size, brd_size, size; int i, j, k, st_index=0; MPI_Count num, bufsize; int n_etypes_in_filetype; ADIO_Offset n_filetypes, etype_in_filetype, st_n_filetypes, size_in_filetype; ADIO_Offset abs_off_in_filetype=0, new_frd_size, frd_size=0, st_frd_size; MPI_Count filetype_size, etype_size, buftype_size, partial_read; MPI_Aint filetype_extent, buftype_extent; int buf_count, buftype_is_contig, filetype_is_contig; ADIO_Offset userbuf_off, req_len, sum; ADIO_Offset off, req_off, disp, end_offset=0, readbuf_off, start_off; char *readbuf, *tmp_buf, *value; int info_flag; unsigned max_bufsize, readbuf_len; ADIO_Status status1; if (fd->hints->ds_read == ADIOI_HINT_DISABLE) { /* if user has disabled data sieving on reads, use naive * approach instead. */ ADIOI_GEN_ReadStrided_naive(fd, buf, count, datatype, file_ptr_type, offset, status, error_code); return; } *error_code = MPI_SUCCESS; /* changed below if error */ ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); MPI_Type_size_x(fd->filetype, &filetype_size); if ( ! filetype_size ) { #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, 0); #endif *error_code = MPI_SUCCESS; return; } MPI_Type_extent(fd->filetype, &filetype_extent); MPI_Type_size_x(datatype, &buftype_size); MPI_Type_extent(datatype, &buftype_extent); etype_size = fd->etype_size; ADIOI_Assert((buftype_size * count) == ((ADIO_Offset)(MPI_Count)buftype_size * (ADIO_Offset)count)); bufsize = buftype_size * count; /* get max_bufsize from the info object. */ value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); ADIOI_Info_get(fd->info, "ind_rd_buffer_size", MPI_MAX_INFO_VAL, value, &info_flag); max_bufsize = atoi(value); ADIOI_Free(value); if (!buftype_is_contig && filetype_is_contig) { /* noncontiguous in memory, contiguous in file. */ flat_buf = ADIOI_Flatten_and_find(datatype); off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : fd->disp + (ADIO_Offset)etype_size * offset; start_off = off; end_offset = off + bufsize - 1; readbuf_off = off; readbuf = (char *) ADIOI_Malloc(max_bufsize); readbuf_len = (unsigned) (MPL_MIN(max_bufsize, end_offset-readbuf_off+1)); /* if atomicity is true, lock (exclusive) the region to be accessed */ if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS)) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); ADIO_ReadContig(fd, readbuf, readbuf_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, readbuf_off, &status1, error_code); if (*error_code != MPI_SUCCESS) return; for (j=0; j<count; j++) { for (i=0; i<flat_buf->count; i++) { userbuf_off = (ADIO_Offset)j*(ADIO_Offset)buftype_extent + flat_buf->indices[i]; req_off = off; req_len = flat_buf->blocklens[i]; ADIOI_BUFFERED_READ off += flat_buf->blocklens[i]; } } if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS)) ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; ADIOI_Free(readbuf); } else { /* noncontiguous in file */ flat_file = ADIOI_Flatten_and_find(fd->filetype); disp = fd->disp; if (file_ptr_type == ADIO_INDIVIDUAL) { /* Wei-keng reworked type processing to be a bit more efficient */ offset = fd->fp_ind - disp; n_filetypes = (offset - flat_file->indices[0]) / filetype_extent; offset -= (ADIO_Offset)n_filetypes * filetype_extent; /* now offset is local to this extent */ /* find the block where offset is located, skip blocklens[i]==0 */ for (i=0; i<flat_file->count; i++) { ADIO_Offset dist; if (flat_file->blocklens[i] == 0) continue; dist = flat_file->indices[i] + flat_file->blocklens[i] - offset; /* frd_size is from offset to the end of block i */ if (dist == 0) { i++; offset = flat_file->indices[i]; frd_size = flat_file->blocklens[i]; break; } if (dist > 0) { frd_size = dist; break; } } st_index = i; /* starting index in flat_file->indices[] */ offset += disp + (ADIO_Offset)n_filetypes*filetype_extent; } else { n_etypes_in_filetype = filetype_size/etype_size; n_filetypes = offset / n_etypes_in_filetype; etype_in_filetype = offset % n_etypes_in_filetype; size_in_filetype = etype_in_filetype * etype_size; sum = 0; for (i=0; i<flat_file->count; i++) { sum += flat_file->blocklens[i]; if (sum > size_in_filetype) { st_index = i; frd_size = sum - size_in_filetype; abs_off_in_filetype = flat_file->indices[i] + size_in_filetype - (sum - flat_file->blocklens[i]); break; } } /* abs. offset in bytes in the file */ offset = disp + (ADIO_Offset) n_filetypes*filetype_extent + abs_off_in_filetype; } start_off = offset; /* Wei-keng Liao: read request is within a single flat_file contig * block e.g. with subarray types that actually describe the whole * array */ if (buftype_is_contig && bufsize <= frd_size) { /* a count of bytes can overflow. operate on original type instead */ ADIO_ReadContig(fd, buf, count, datatype, ADIO_EXPLICIT_OFFSET, offset, status, error_code); if (file_ptr_type == ADIO_INDIVIDUAL) { /* update MPI-IO file pointer to point to the first byte that * can be accessed in the fileview. */ fd->fp_ind = offset + bufsize; if (bufsize == frd_size) { do { st_index++; if (st_index == flat_file->count) { st_index = 0; n_filetypes++; } } while (flat_file->blocklens[st_index] == 0); fd->fp_ind = disp + flat_file->indices[st_index] + n_filetypes*filetype_extent; } } fd->fp_sys_posn = -1; /* set it to null. */ #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, datatype, bufsize); #endif return; } /* Calculate end_offset, the last byte-offset that will be accessed. e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/ st_frd_size = frd_size; st_n_filetypes = n_filetypes; i_offset = 0; j = st_index; off = offset; frd_size = MPL_MIN(st_frd_size, bufsize); while (i_offset < bufsize) { i_offset += frd_size; end_offset = off + frd_size - 1; j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; while (flat_file->blocklens[j]==0) { j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; } off = disp + flat_file->indices[j] + n_filetypes*(ADIO_Offset)filetype_extent; frd_size = MPL_MIN(flat_file->blocklens[j], bufsize-i_offset); } /* if atomicity is true, lock (exclusive) the region to be accessed */ if ((fd->atomicity) && ADIO_Feature(fd, ADIO_LOCKS)) ADIOI_WRITE_LOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); readbuf_off = 0; readbuf_len = 0; readbuf = (char *) ADIOI_Malloc(max_bufsize); if (buftype_is_contig && !filetype_is_contig) { /* contiguous in memory, noncontiguous in file. should be the most common case. */ i_offset = 0; j = st_index; off = offset; n_filetypes = st_n_filetypes; frd_size = MPL_MIN(st_frd_size, bufsize); while (i_offset < bufsize) { if (frd_size) { /* TYPE_UB and TYPE_LB can result in frd_size = 0. save system call in such cases */ /* lseek(fd->fd_sys, off, SEEK_SET); err = read(fd->fd_sys, ((char *) buf) + i, frd_size);*/ req_off = off; req_len = frd_size; userbuf_off = i_offset; ADIOI_BUFFERED_READ } i_offset += frd_size; if (off + frd_size < disp + flat_file->indices[j] + flat_file->blocklens[j] + n_filetypes*(ADIO_Offset)filetype_extent) off += frd_size; /* did not reach end of contiguous block in filetype. no more I/O needed. off is incremented by frd_size. */ else { j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; while (flat_file->blocklens[j]==0) { j = (j+1) % flat_file->count; n_filetypes += (j == 0) ? 1 : 0; } off = disp + flat_file->indices[j] + n_filetypes*(ADIO_Offset)filetype_extent; frd_size = MPL_MIN(flat_file->blocklens[j], bufsize-i_offset); } } } else {
/*@ MPI_File_write - Write using individual file pointer Input Parameters: . fh - file handle (handle) . buf - initial address of buffer (choice) . count - number of elements in buffer (nonnegative integer) . datatype - datatype of each buffer element (handle) Output Parameters: . status - status object (Status) .N fortran @*/ int MPI_File_write(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) { int error_code, bufsize, buftype_is_contig, filetype_is_contig; #ifndef PRINT_ERR_MSG static char myname[] = "MPI_FILE_WRITE"; #endif int datatype_size; ADIO_Offset off; #ifdef MPI_hpux int fl_xmpi; HPMP_IO_START(fl_xmpi, BLKMPIFILEWRITE, TRDTBLOCK, fh, datatype, count); #endif /* MPI_hpux */ #ifdef PRINT_ERR_MSG if ((fh <= (MPI_File) 0) || (fh->cookie != ADIOI_FILE_COOKIE)) { FPRINTF(stderr, "MPI_File_write: Invalid file handle\n"); MPI_Abort(MPI_COMM_WORLD, 1); } #else ADIOI_TEST_FILE_HANDLE(fh, myname); #endif if (count < 0) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_write: Invalid count argument\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_ARG, MPIR_ERR_COUNT_ARG, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } if (datatype == MPI_DATATYPE_NULL) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_write: Invalid datatype\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_TYPE, MPIR_ERR_TYPE_NULL, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } MPI_Type_size(datatype, &datatype_size); if (count*datatype_size == 0) { #ifdef MPI_hpux HPMP_IO_END(fl_xmpi, fh, datatype, count); #endif /* MPI_hpux */ return MPI_SUCCESS; } if ((count*datatype_size) % fh->etype_size != 0) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_write: Only an integral number of etypes can be accessed\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ERR_ETYPE_FRACTIONAL, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } if (fh->access_mode & MPI_MODE_SEQUENTIAL) { #ifdef PRINT_ERR_MSG FPRINTF(stderr, "MPI_File_write: Can't use this function because file was opened with MPI_MODE_SEQUENTIAL\n"); MPI_Abort(MPI_COMM_WORLD, 1); #else error_code = MPIR_Err_setmsg(MPI_ERR_UNSUPPORTED_OPERATION, MPIR_ERR_AMODE_SEQ, myname, (char *) 0, (char *) 0); return ADIOI_Error(fh, error_code, myname); #endif } ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); ADIOI_Datatype_iscontig(fh->filetype, &filetype_is_contig); /* contiguous or strided? */ if (buftype_is_contig && filetype_is_contig) { bufsize = datatype_size * count; /* if atomic mode requested, lock (exclusive) the region, because there could be a concurrent noncontiguous request. Locking doesn't work on PIOFS and PVFS, and on NFS it is done in the ADIO_WriteContig.*/ off = fh->fp_ind; if ((fh->atomicity) && (fh->file_system != ADIO_PIOFS) && (fh->file_system != ADIO_PVFS) && (fh->file_system != ADIO_NFS)) ADIOI_WRITE_LOCK(fh, off, SEEK_SET, bufsize); ADIO_WriteContig(fh, buf, count, datatype, ADIO_INDIVIDUAL, 0, status, &error_code); if ((fh->atomicity) && (fh->file_system != ADIO_PIOFS) && (fh->file_system != ADIO_PVFS) && (fh->file_system != ADIO_NFS)) ADIOI_UNLOCK(fh, off, SEEK_SET, bufsize); } else ADIO_WriteStrided(fh, buf, count, datatype, ADIO_INDIVIDUAL, 0, status, &error_code); /* For strided and atomic mode, locking is done in ADIO_WriteStrided */ #ifdef MPI_hpux HPMP_IO_END(fl_xmpi, fh, datatype, count); #endif /* MPI_hpux */ return error_code; }