diff --git a/ompi/mca/io/romio314/romio/.codingcheck b/ompi/mca/io/romio314/romio/.codingcheck new file mode 100644 index 0000000000..9b52b35ce4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/.codingcheck @@ -0,0 +1,55 @@ +# Here are names that at least at one point were used within ROMIO. +# We should look at these and decide which we wish to allow and which +# should be replaced with something more ROMIO-specific. +%romioDefines = ( 'ROMIO_[A-Za-z0-9_]+' => romio, + 'PROFILE' => romio, + 'PRINT_ERR_MSG' => romio, + 'HPUX' => romio, + 'SPPUX'=> romio, + 'SX4'=> romio, + 'AIO_SUN'=> romio, + 'AIO_HANDLE_IN_AIOCB'=> romio, + 'NO_FD_IN_AIOCB'=> romio, + 'NO_AIO'=> romio, + 'AIO_PRIORITY_DEFAULT'=> romio, + 'AIO_SIGNOTIFY_NONE'=> romio, + 'MPISGI'=> romio, + 'CRAY'=> romio, + 'PARAGON'=> romio, + 'FREEBSD'=> romio, + 'LINUX'=> romio, + 'tflops'=> romio, + 'NFS'=> romio, + 'XFS'=> romio, + 'CB_CONFIG_LIST_DEBUG'=> romio, + 'SFS'=> romio, + 'HFS'=> romio, + 'UFS'=> romio, + 'PVFS_.+' => romio, + 'MPI_hpux'=> romio, + 'FORTRANCAPS'=> romio, + 'MPILAM'=> romio, + 'NEEDS_ADIOCB_T'=> romio, + 'AGG_DEBUG'=> romio, + 'SOLARIS'=> romio, + 'IRIX'=> romio, + 'AIX'=> romio, + 'DEC'=> romio, + 'NEEDS_MPI_TEST'=> romio, + 'PFS'=> romio, + 'PIOFS'=> romio, + 'MPICH'=> romio, + 'MPICH' => romio, + 'MPI_OFFSET_IS_INT'=> romio, + 'MPI_COMBINER_NAMED'=> romio, + '_UNICOS'=> romio, + 'MPIHP'=> romio, + ); + +# Only invoke this function if the function is defined (in case the +# user removed the cpp defines check with -rmchecks=cppdefines) +if (defined(&PushDefinesNames)) { + &PushDefinesNames( "romioDefines", "tree", "add" ); +} + +1; diff --git a/ompi/mca/io/romio314/romio/.config_params b/ompi/mca/io/romio314/romio/.config_params new file mode 100644 index 0000000000..96f735f21b --- /dev/null +++ b/ompi/mca/io/romio314/romio/.config_params @@ -0,0 +1,38 @@ +__sun4_ +__rs6000_ +__paragon_ +__solaris_ +__solaris86_ +__tflop_ +__tflops_ +__hpux_ +__sppux_ +__SX4_ +__sgi_ +__sgi5_ +__IRIX_ +__IRIX32_ +__IRIXN32_ +__IRIX64_ +__alpha_ +__ALPHA_ +__freebsd_ +__netbsd_ +__LINUX_ +__LINUX_ALPHA_ +__CRAY_ +__Darwin_ +__nfs_ +__ufs_ +__pfs_ +__piofs_ +__pvfs_ +__testfs_ +__xfs_ +__hfs_ +__sfs_ +__mpich_mpi +__sgi_mpi +__hp_mpi +__cray_mpi +__lam_mpi diff --git a/ompi/mca/io/romio314/romio/COPYRIGHT b/ompi/mca/io/romio314/romio/COPYRIGHT new file mode 100644 index 0000000000..609bcfa4e8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/COPYRIGHT @@ -0,0 +1,41 @@ + COPYRIGHT + +The following is a notice of limited availability of the code and +disclaimer, which must be included in the prologue of the code and in +all source listings of the code. + +Copyright (C) 1997 University of Chicago + +Permission is hereby granted to use, reproduce, prepare derivative +works, and to redistribute to others. + +The University of Chicago makes no representations as to the suitability, +operability, accuracy, or correctness of this software for any purpose. +It is provided "as is" without express or implied warranty. + +This software was authored by: +Rajeev Thakur: (630) 252-1682; thakur@mcs.anl.gov +Mathematics and Computer Science Division +Argonne National Laboratory, Argonne IL 60439, USA + + + GOVERNMENT LICENSE + +Portions of this material resulted from work developed under a U.S. +Government Contract and are subject to the following license: the +Government is granted for itself and others acting on its behalf a +paid-up, nonexclusive, irrevocable worldwide license in this computer +software to reproduce, prepare derivative works, and perform publicly +and display publicly. + + DISCLAIMER + +This computer code material was prepared, in part, as an account of +work sponsored by an agency of the United States Government. Neither +the United States Government, nor the University of Chicago, nor any +of their employees, makes any warranty express or implied, or assumes +any legal liability or responsibility for the accuracy, completeness, +or usefulness of any information, apparatus, product, or process +disclosed, or represents that its use would not infringe privately +owned rights. + diff --git a/ompi/mca/io/romio314/romio/Makefile.am b/ompi/mca/io/romio314/romio/Makefile.am new file mode 100644 index 0000000000..b9d4e258f1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/Makefile.am @@ -0,0 +1,172 @@ +# -*- Mode: Makefile; -*- +# +# (C) 2011 by Argonne National Laboratory. +# See COPYRIGHT in top-level directory. +# + +## TODO: need to write an automakefile that handles two primary cases: +## 1) that ROMIO is being embedded within the MPI library, as in MPICH or Open +## MPI +## 2) that ROMIO is being built standalone, old-school style. This case is +## basically unused in modern practice. + +# help autoreconf and friends realize where the macros live +ACLOCAL_AMFLAGS = -I confdb + +# empty variable initializations so that later code can append (+=) +include_HEADERS = +nodist_include_HEADERS = +noinst_HEADERS = +AM_CPPFLAGS = +EXTRA_DIST = +SUFFIXES = +doc1_src_txt = + +# ------------------------------------------------------------------------ +# variables to be populated by the included Makefile.mk fragments: + +# These are files that contain MPI routines (e.g., MPI_File_open). +# In MPICH these will have an MPI_ and a PMPI_ version. Other implementations +# (like OMPI) only want these to be MPI_ routines, possibly with some +# name-shifting prefix. +romio_mpi_sources = + +# regular old source files that implement ROMIO, such as ADIO code +romio_other_sources = + +# code that may need to be "up" called from the MPI library and/or is +# MPI-implementation-specific in some way +glue_sources = + +# ------------------------------------------------------------------------ +# when building under MPICH we must be able to find mpi.h +AM_CPPFLAGS += $(MPI_H_INCLUDE) + +# ------------------------------------------------------------------------ +# handle the "include" directory here +AM_CPPFLAGS += -I$(top_builddir)/include -I$(top_srcdir)/include +# nodist_ b/c these are created by config.status and should not be distributed +nodist_include_HEADERS += include/mpio.h include/mpiof.h + +# ------------------------------------------------------------------------ + +SUBDIRS = +DIST_SUBDIRS = test test-internal + +# for the sake of parallel make and avoiding an excessive number of convenience +# libs, we use a subdir automake fragment strategy +include mpi-io/Makefile.mk +include adio/Makefile.mk + +EXTRA_DIST += autogen.sh + +if BUILD_ROMIO_EMBEDDED +# Build a libtool convenience library that the enclosing MPI implementation can +# use by adding it to the right _LIBADD variable. +noinst_LTLIBRARIES = libromio.la +libromio_la_SOURCES = $(romio_mpi_sources) $(romio_other_sources) $(glue_sources) + +## NOTE: ROMIO's old build system builds a bunch of _foo.o objects that contain +## PMPI_ implementations as well as calls to only other PMPI routines. In +## MPICH, these are the objects that need to go into libmpi, while the foo.o +## objects should go into libpmpi. Furthermore, the -D option for ROMIO's +## source files is different and inverted (in the boolean sense) compared with +## MPICH's defintion. And ROMIO was dumping all of the symbols into the main +## libmpi library, regardless of the separate profiling library's existence. +## +## Annoying, right? +if BUILD_PROFILING_LIB +# The current best strategy for now is to build the PMPI symbols as a separate +# convenience lib to permit adding the special "-D..." argument for all objects. +# MPICH will then link in both convenience library into libmpi, since it +# won't work very well the other way around. +noinst_LTLIBRARIES += libpromio.la +libpromio_la_SOURCES = $(romio_mpi_sources) +libpromio_la_CPPFLAGS = $(AM_CPPFLAGS) -DMPIO_BUILD_PROFILING +endif BUILD_PROFILING_LIB + +else !BUILD_ROMIO_EMBEDDED +lib_LTLIBRARIES = libromio.la +libromio_la_SOURCES = $(romio_mpi_sources) $(romio_other_sources) $(glue_sources) +if BUILD_PROFILING_LIB +libpromio_la_SOURCES = $(romio_mpi_sources) +libpromio_la_CPPFLAGS = $(AM_CPPFLAGS) -DMPIO_BUILD_PROFILING +endif BUILD_PROFILING_LIB + +endif + +# -------------------------------------------------------------------------- +.PHONY: coverage +gcov_sources = $(libmpl_la_SOURCES) +# assumes that these sources were compiled appropriately ("-fprofile-arcs" +# and "-ftest-coverage") +coverage: + @for file in $(gcov_sources) ; do \ + dir=`dirname $$file` ; \ + bname=`basename $$file` ; \ + aux=`echo $$bname | sed -e 's,\.*$$,,'` ; \ + echo "( $(GCOV) -b -f -o $$file $$file && mv $${bname}.gcov $$dir )" ; \ + ( $(GCOV) -b -f -o $$file $$file && mv $${bname}.gcov $$dir ) ; \ + rm -f *.gcov ; \ + done + for subdir in $(SUBDIRS) - ; do \ + if test $$subdir = "-" ; then break ; fi ; \ + ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) coverage ) ; \ + done +# -------------------------------------------------------------------------- +.PHONY: mandoc mandoc-local htmldoc htmldoc-local +SUFFIXES += .man-phony .html-phony .man1-phony .html1-phony .txt + +# "make V=1" support for our documentation recipes +doctextman_verbose = $(doctextman_verbose_$(V)) +doctextman_verbose_ = $(doctextman_verbose_$(AM_DEFAULT_VERBOSITY)) +doctextman_verbose_0 = @echo " DOCTEXTMAN " $@; +doctexthtml_verbose = $(doctexthtml_verbose_$(V)) +doctexthtml_verbose_ = $(doctexthtml_verbose_$(AM_DEFAULT_VERBOSITY)) +doctexthtml_verbose_0 = @echo " DOCTEXTHTML " $@; + +# Build dir paths where the man pages will be created. Will usually be +# overridden by MPICH make. +mandoc_path1=$(abs_top_builddir)/man/man1 +mandoc_path3=$(abs_top_builddir)/man/man3 +htmldoc_path1=$(abs_top_builddir)/www/www1 +htmldoc_path3=$(abs_top_builddir)/www/www3 +doctext_docnotes= +# Provide an easily replaced url root for the generated index file. +# You can override this with URL desired in the index file generated by doctext. +# You can ignore this if you don't use mapnames or tohtml to add links +# to the MPI manual pages to documents. +htmldoc_root3="--your-url-here--" + +.c.man-phony: + $(doctextman_verbose)$(DOCTEXT) -man -mpath $(mandoc_path3) -ext 3 \ + -heading MPI -quotefmt -nolocation $(doctext_docnotes) $< +.c.html-phony: + $(doctexthtml_verbose)$(DOCTEXT) -html -mpath $(htmldoc_path3) \ + -heading MPI -quotefmt -nolocation \ + -index $(htmldoc_path3)/mpi.cit -indexdir $(htmldoc_root3) \ + $(doctext_docnotes) $< + +.txt.man1-phony: + $(doctextman_verbose)$(DOCTEXT) -man -mpath $(mandoc_path1) -ext 1 \ + -heading MPI -quotefmt -nolocation $(doctext_docnotes) $< +.txt.html1-phony: + $(doctexthtml_verbose)$(DOCTEXT) -html -mpath $(htmldoc_path1) \ + -heading MPI -quotefmt -nolocation $(doctext_docnotes) $< + +# use mandoc-local target to force directory creation before running DOCTEXT +mandoc: + test -d $(mandoc_path1) || $(MKDIR_P) $(mandoc_path1) + test -d $(mandoc_path3) || $(MKDIR_P) $(mandoc_path3) + $(MAKE) $(AM_MAKEFLAGS) mandoc-local +mandoc-local: $(romio_mpi_sources:.c=.man-phony) $(doc1_src_txt:.txt=.man1-phony) + +# use htmldoc-local target to force directory creation before running DOCTEXT +htmldoc: + test -d $(top_builddir)/www/www1 || $(MKDIR_P) $(top_builddir)/www/www1 + test -d $(top_builddir)/www/www3 || $(MKDIR_P) $(top_builddir)/www/www3 + $(MAKE) $(AM_MAKEFLAGS) htmldoc-local +htmldoc-local: $(romio_mpi_sources:.c=.html-phony) $(doc1_src_txt:.txt=.html1-phony) + +# -------------------------------------------------------------------------- + diff --git a/ompi/mca/io/romio314/romio/README b/ompi/mca/io/romio314/romio/README new file mode 100644 index 0000000000..a6fb25a09a --- /dev/null +++ b/ompi/mca/io/romio314/romio/README @@ -0,0 +1,660 @@ + ROMIO: A High-Performance, Portable MPI-IO Implementation + + Version 2008-03-09 + +Major Changes in this version: +------------------------------ +* Fixed performance problems with the darray and subarray datatypes + when using MPICH. + +* Better support for building against existing MPICH and MPICH versions. + + When building against an existing MPICH installation, use the + "--with-mpi=mpich" option to ROMIO configure. For MPICH, use the + "--with-mpi=mpich" option. These will allow ROMIO to take advantage + of internal features of these implementations. + +* Deprecation of SFS, HFS, and PIOFS implementations. + + These are no longer actively supported, although the code will continue + to be distributed for now. + +* Initial support for the Panasas PanFS filesystem. + + PanFS allows users to specify the layout of a file at file-creation time. + Layout information includes the number of StorageBlades (SB) + across which the data is stored, the number of SBs across which a + parity stripe is written, and the number of consecutive stripes that + are placed on the same set of SBs. The panfs_layout_* hints are only + used if supplied at file-creation time. + + panfs_layout_type - Specifies the layout of a file: + 2 = RAID0 + 3 = RAID5 Parity Stripes + panfs_layout_stripe_unit - The size of the stripe unit in bytes + panfs_layout_total_num_comps - The total number of StorageBlades a file + is striped across. + panfs_layout_parity_stripe_width - If the layout type is RAID5 Parity + Stripes, this hint specifies the + number of StorageBlades in a parity + stripe. + panfs_layout_parity_stripe_depth - If the layout type is RAID5 Parity + Stripes, this hint specifies the + number of contiguous parity stripes written + across the same set of SBs. + panfs_layout_visit_policy - If the layout type is RAID5 Parity Stripes, + the policy used to determine the parity + stripe a given file offset is written to: + 1 = Round Robin + + PanFS supports the "concurrent write" (CW) mode, where groups of cooperating + clients can disable the PanFS consistency mechanisms and use their own + consistency protocol. Clients participating in concurrent write mode use + application specific information to improve performance while maintaining + file consistency. All clients accessing the file(s) must enable concurrent + write mode. If any client does not enable concurrent write mode, then the + PanFS consistency protocol will be invoked. Once a file is opened in CW mode + on a machine, attempts to open a file in non-CW mode will fail with + EACCES. If a file is already opened in non-CW mode, attempts to open + the file in CW mode will fail with EACCES. The following hint is + used to enable concurrent write mode. + + panfs_concurrent_write - If set to 1 at file open time, the file + is opened using the PanFS concurrent write + mode flag. Concurrent write mode is not a + persistent attribute of the file. + + Below is an example PanFS layout using the following parameters: + + - panfs_layout_type = 3 + - panfs_layout_total_num_comps = 100 + - panfs_layout_parity_stripe_width = 10 + - panfs_layout_parity_stripe_depth = 8 + - panfs_layout_visit_policy = 1 + + Parity Stripe Group 1 Parity Stripe Group 2 . . . Parity Stripe Group 10 + ---------------------- ---------------------- -------------------- + SB1 SB2 ... SB10 SB11 SB12 ... SB20 ... SB91 SB92 ... SB100 + ----------------------- ----------------------- --------------------- + D1 D2 ... D10 D91 D92 ... D100 D181 D182 ... D190 + D11 D12 D20 D101 D102 D110 D191 D192 D193 + D21 D22 D30 . . . . . . + D31 D32 D40 + D41 D42 D50 + D51 D52 D60 + D61 D62 D70 + D71 D72 D80 + D81 D82 D90 D171 D172 D180 D261 D262 D270 + D271 D272 D273 . . . . . . + ... + +* Initial support for the Globus GridFTP filesystem. Work contributed by Troy + Baer (troy@osc.edu). + +Major Changes in Version 1.2.5: +------------------------------ + +* Initial support for MPICH-2 + +* fix for a bug in which ROMIO would get confused for some permutations + of the aggregator list + +* direct io on IRIX's XFS should work now + +* fixed an issue with the Fortran bindings that would cause them to fail + when some compilers tried to build them. + +* Initial support for deferred opens + +Major Changes in Version 1.2.4: +------------------------------ +* Added section describing ROMIO MPI_FILE_SYNC and MPI_FILE_CLOSE behavior to + User's Guide + +* Bug removed from PVFS ADIO implementation regarding resize operations + +* Added support for PVFS listio operations, including hints to control use + + +Major Changes in Version 1.2.3: +------------------------------- +* Enhanced aggregation control via cb_config_list, romio_cb_read, + and romio_cb_write hints + +* Asynchronous IO can be enabled under Linux with the --enable-aio argument + to configure + +* Additional PVFS support + +* Additional control over data sieving with romio_ds_read hint + +* NTFS ADIO implementation integrated into source tree + +* testfs ADIO implementation added for debugging purposes + + +Major Changes in Version 1.0.3: +------------------------------- + +* When used with MPICH 1.2.1, the MPI-IO functions return proper error codes + and classes, and the status object is filled in. + +* On SGI's XFS file system, ROMIO can use direct I/O even if the + user's request does not meet the various restrictions needed to use + direct I/O. ROMIO does this by doing part of the request with + buffered I/O (until all the restrictions are met) and doing the rest + with direct I/O. (This feature hasn't been tested rigorously. Please + check for errors.) + + By default, ROMIO will use only buffered I/O. Direct I/O can be + enabled either by setting the environment variables MPIO_DIRECT_READ + and/or MPIO_DIRECT_WRITE to TRUE, or on a per-file basis by using + the info keys "direct_read" and "direct_write". + + Direct I/O will result in higher performance only if you are + accessing a high-bandwidth disk system. Otherwise, buffered I/O is + better and is therefore used as the default. + +* Miscellaneous bug fixes. + + +Major Changes Version 1.0.2: +--------------------------- + +* Implemented the shared file pointer functions and + split collective I/O functions. Therefore, the main + components of the MPI I/O chapter not yet implemented are + file interoperability and error handling. + +* Added support for using "direct I/O" on SGI's XFS file system. + Direct I/O is an optional feature of XFS in which data is moved + directly between the user's buffer and the storage devices, bypassing + the file-system cache. This can improve performance significantly on + systems with high disk bandwidth. Without high disk bandwidth, + regular I/O (that uses the file-system cache) perfoms better. + ROMIO, therefore, does not use direct I/O by default. The user can + turn on direct I/O (separately for reading and writing) either by + using environment variables or by using MPI's hints mechanism (info). + To use the environment-variables method, do + setenv MPIO_DIRECT_READ TRUE + setenv MPIO_DIRECT_WRITE TRUE + To use the hints method, the two keys are "direct_read" and "direct_write". + By default their values are "false". To turn on direct I/O, set the values + to "true". The environment variables have priority over the info keys. + In other words, if the environment variables are set to TRUE, direct I/O + will be used even if the info keys say "false", and vice versa. + Note that direct I/O must be turned on separately for reading + and writing. + The environment-variables method assumes that the environment + variables can be read by each process in the MPI job. This is + not guaranteed by the MPI Standard, but it works with SGI's MPI + and the ch_shmem device of MPICH. + +* Added support (new ADIO device, ad_pvfs) for the PVFS parallel + file system for Linux clusters, developed at Clemson University + (see http://www.parl.clemson.edu/pvfs ). To use it, you must first install + PVFS and then when configuring ROMIO, specify "-file_system=pvfs" in + addition to any other options to "configure". (As usual, you can configure + for multiple file systems by using "+"; for example, + "-file_system=pvfs+ufs+nfs".) You will need to specify the path + to the PVFS include files via the "-cflags" option to configure, + for example, "configure -cflags=-I/usr/pvfs/include". You + will also need to specify the full path name of the PVFS library. + The best way to do this is via the "-lib" option to MPICH's + configure script (assuming you are using ROMIO from within MPICH). + +* Uses weak symbols (where available) for building the profiling version, + i.e., the PMPI routines. As a result, the size of the library is reduced + considerably. + +* The Makefiles use "virtual paths" if supported by the make utility. GNU make + supports it, for example. This feature allows you to untar the + distribution in some directory, say a slow NFS directory, + and compile the library (the .o files) in another + directory, say on a faster local disk. For example, if the tar file + has been untarred in an NFS directory called /home/thakur/romio, + one can compile it in a different directory, say /tmp/thakur, as follows: + cd /tmp/thakur + /home/thakur/romio/configure + make + The .o files will be created in /tmp/thakur; the library will be created in + /home/thakur/romio/lib/$ARCH/libmpio.a . + This method works only if the make utility supports virtual paths. + If the default make does not, you can install GNU make which does, + and specify it to configure as + /home/thakur/romio/configure -make=/usr/gnu/bin/gmake (or whatever) + +* Lots of miscellaneous bug fixes and other enhancements. + +* This version is included in MPICH 1.2.0. If you are using MPICH, you + need not download ROMIO separately; it gets built as part of MPICH. + The previous version of ROMIO is included in LAM, HP MPI, SGI MPI, and + NEC MPI. NEC has also implemented the MPI-IO functions missing + in ROMIO, and therefore NEC MPI has a complete implementation + of MPI-IO. + + +Major Changes in Version 1.0.1: +------------------------------ + +* This version is included in MPICH 1.1.1 and HP MPI 1.4. + +* Added support for NEC SX-4 and created a new device ad_sfs for + NEC SFS file system. + +* New devices ad_hfs for HP/Convex HFS file system and ad_xfs for + SGI XFS file system. + +* Users no longer need to prefix the filename with the type of + file system; ROMIO determines the file-system type on its own. + +* Added support for 64-bit file sizes on IBM PIOFS, SGI XFS, + HP/Convex HFS, and NEC SFS file systems. + +* MPI_Offset is an 8-byte integer on machines that support 8-byte integers. + It is of type "long long" in C and "integer*8" in Fortran. + With a Fortran 90 compiler, you can use either integer*8 or + integer(kind=MPI_OFFSET_KIND). + If you printf an MPI_Offset in C, remember to use %lld + or %ld as required by your compiler. (See what is used in the test + program romio/test/misc.c.) + +* On some machines, ROMIO detects at configure time that "long long" is + either not supported by the C compiler or it doesn't work properly. + In such cases, configure sets MPI_Offset to long in C and integer in + Fortran. This happens on Intel Paragon, Sun4, and FreeBSD. + +* Added support for passing hints to the implementation via the MPI_Info + parameter. ROMIO understands the following hints (keys in MPI_Info object): + + /* on all file systems */ + cb_buffer_size - buffer size for collective I/O + cb_nodes - no. of processes that actually perform I/O in collective I/O + ind_rd_buffer_size - buffer size for data sieving in independent reads + + /* on all file systems except IBM PIOFS */ + ind_wr_buffer_size - buffer size for data sieving in independent writes + /* ind_wr_buffer_size is ignored on PIOFS because data sieving + cannot be done for writes since PIOFS doesn't support file locking */ + + /* on Intel PFS and IBM PIOFS only. These hints are understood only if + supplied at file-creation time. */ + striping_factor - no. of I/O devices to stripe the file across + striping_unit - the striping unit in bytes + start_iodevice - the number of the I/O device from which to start + striping (between 0 and (striping_factor-1)) + + /* on Intel PFS only. */ + pfs_svr_buf - turn on or off PFS server buffering by setting the value + to "true" or "false", case-sensitive. + + If ROMIO doesn't understand a hint, or if the value is invalid, the hint + will be ignored. The values of hints being used by ROMIO at any time + can be obtained via MPI_File_get_info. + + + +General Information +------------------- + +ROMIO is a high-performance, portable implementation of MPI-IO (the +I/O chapter in MPI). ROMIO's home page is at +http://www.mcs.anl.gov/romio . The MPI standard is available at +http://www.mpi-forum.org/docs/docs.html . + +This version of ROMIO includes everything defined in the MPI I/O +chapter except support for file interoperability and +user-defined error handlers for files. The subarray and +distributed array datatype constructor functions from Chapter 4 +(Sec. 4.14.4 & 4.14.5) have been implemented. They are useful for +accessing arrays stored in files. The functions MPI_File_f2c and +MPI_File_c2f (Sec. 4.12.4) are also implemented. + +C, Fortran, and profiling interfaces are provided for all functions +that have been implemented. + +Please read the limitations of this version of ROMIO that are listed +below (e.g., MPIO_Request object, restriction to homogeneous +environments). + +This version of ROMIO runs on at least the following machines: IBM SP; +Intel Paragon; HP Exemplar; SGI Origin2000; Cray T3E; NEC SX-4; other +symmetric multiprocessors from HP, SGI, DEC, Sun, and IBM; and networks of +workstations (Sun, SGI, HP, IBM, DEC, Linux, and FreeBSD). Supported +file systems are IBM PIOFS, Intel PFS, HP/Convex HFS, SGI XFS, NEC +SFS, PVFS, NFS, and any Unix file system (UFS). + +This version of ROMIO is included in MPICH 1.2.3; an earlier version +is included in at least the following MPI implementations: LAM, HP +MPI, SGI MPI, and NEC MPI. + +Note that proper I/O error codes and classes are returned and the +status variable is filled only when used with MPICH 1.2.1 or later. + +You can open files on multiple file systems in the same program. The +only restriction is that the directory where the file is to be opened +must be accessible from the process opening the file. For example, a +process running on one workstation may not be able to access a +directory on the local disk of another workstation, and therefore +ROMIO will not be able to open a file in such a directory. NFS-mounted +files can be accessed. + +An MPI-IO file created by ROMIO is no different than any other file +created by the underlying file system. Therefore, you may use any of +the commands provided by the file system to access the file, e.g., ls, +mv, cp, rm, ftp. + + +Using ROMIO on NFS +------------------ + +To use ROMIO on NFS, file locking with fcntl must work correctly on +the NFS installation. On some installations, fcntl locks don't work. +To get them to work, you need to use Version 3 of NFS, ensure that the +lockd daemon is running on all the machines, and have the system +administrator mount the NFS file system with the "noac" option (no +attribute caching). Turning off attribute caching may reduce +performance, but it is necessary for correct behavior. + +The following are some instructions we received from Ian Wells of HP +for setting the noac option on NFS. We have not tried them +ourselves. We are including them here because you may find +them useful. Note that some of the steps may be specific to HP +systems, and you may need root permission to execute some of the +commands. + + >1. first confirm you are running nfs version 3 + > + >rpcnfo -p `hostname` | grep nfs + > + >ie + > goedel >rpcinfo -p goedel | grep nfs + > 100003 2 udp 2049 nfs + > 100003 3 udp 2049 nfs + > + > + >2. then edit /etc/fstab for each nfs directory read/written by MPIO + > on each machine used for multihost MPIO. + > + > Here is an example of a correct fstab entry for /epm1: + > + > ie grep epm1 /etc/fstab + > + > ROOOOT 11>grep epm1 /etc/fstab + > gershwin:/epm1 /rmt/gershwin/epm1 nfs bg,intr,noac 0 0 + > + > if the noac option is not present, add it + > and then remount this directory + > on each of the machines that will be used to share MPIO files + > + >ie + > + >ROOOOT >umount /rmt/gershwin/epm1 + >ROOOOT >mount /rmt/gershwin/epm1 + > + >3. Confirm that the directory is mounted noac: + > + >ROOOOT >grep gershwin /etc/mnttab + >gershwin:/epm1 /rmt/gershwin/epm1 nfs + >noac,acregmin=0,acregmax=0,acdirmin=0,acdirmax=0 0 0 899911504 + + + + +ROMIO Installation Instructions +------------------------------- + +Since ROMIO is included in MPICH, LAM, HP MPI, SGI MPI, and NEC MPI, +you don't need to install it separately if you are using any of these +MPI implementations. If you are using some other MPI, you can +configure and build ROMIO as follows: + +Untar the tar file as + + gunzip -c romio.tar.gz | tar xvf - + +OR + + zcat romio.tar.Z | tar xvf - + +THEN + + cd romio + ./configure + make + +Some example programs and a Makefile are provided in the romio/test directory. +Run the examples the way you would run any MPI program. Each program takes +the filename as a command-line argument "-fname filename". + +The configure script by default configures ROMIO for the file systems +most likely to be used on the given machine. If you wish, you can +explicitly specify the file systems by using the "-file_system" option +to configure. Multiple file systems can be specified by using "+" as a +separator. For example, + + ./configure -file_system=xfs+nfs + +For the entire list of options to configure do + + ./configure -h | more + +After building a specific version as above, you can install it in a +particular directory with + + make install PREFIX=/usr/local/romio (or whatever directory you like) + +or just + + make install (if you used -prefix at configure time) + +If you intend to leave ROMIO where you built it, you should NOT install it +(install is used only to move the necessary parts of a built ROMIO to +another location). The installed copy will have the include files, +libraries, man pages, and a few other odds and ends, but not the whole +source tree. It will have a test directory for testing the +installation and a location-independent Makefile built during +installation, which users can copy and modify to compile and link +against the installed copy. + +To rebuild ROMIO with a different set of configure options, do + + make distclean + +to clean everything including the Makefiles created by configure. +Then run configure again with the new options, followed by make. + + + +Testing ROMIO +------------- + +To test if the installation works, do + + make testing + +in the romio/test directory. This calls a script that runs the test +programs and compares the results with what they should be. By +default, "make testing" causes the test programs to create files in +the current directory and use whatever file system that corresponds +to. To test with other file systems, you need to specify a filename in +a directory corresponding to that file system as follows: + + make testing TESTARGS="-fname=/foo/piofs/test" + + + +Compiling and Running MPI-IO Programs +------------------------------------- + +If ROMIO is not already included in the MPI implementation, you need +to include the file mpio.h for C or mpiof.h for Fortran in your MPI-IO +program. + +Note that on HP machines running HPUX and on NEC SX-4, you need to +compile Fortran programs with mpifort, because the f77 compilers on +these machines don't support 8-byte integers. + +With MPICH, HP MPI, or NEC MPI, you can compile MPI-IO programs as + mpicc foo.c +or + mpif77 foo.f +or + mpifort foo.f + +As mentioned above, mpifort is preferred over mpif77 on HPUX and NEC +because the f77 compilers on those machines do not support 8-byte integers. + +With SGI MPI, you can compile MPI-IO programs as + cc foo.c -lmpi +or + f77 foo.f -lmpi +or + f90 foo.f -lmpi + +With LAM, you can compile MPI-IO programs as + hcc foo.c -lmpi +or + hf77 foo.f -lmpi + +If you have built ROMIO with some other MPI implementation, you can +compile MPI-IO programs by explicitly giving the path to the include +file mpio.h or mpiof.h and explicitly specifying the path to the +library libmpio.a, which is located in $(ROMIO_HOME)/lib/$(ARCH)/libmpio.a . + + +Run the program as you would run any MPI program on the machine. If +you use mpirun, make sure you use the correct mpirun for the MPI +implementation you are using. For example, if you are using MPICH on +an SGI machine, make sure that you use MPICH's mpirun and not SGI's +mpirun. + +The Makefile in the romio/test directory illustrates how to compile +and link MPI-IO programs. + + + +Limitations of this version of ROMIO +------------------------------------ + +* When used with any MPI implementation other than MPICH 1.2.1 (or later), +the "status" argument is not filled in any MPI-IO function. Consequently, +MPI_Get_count and MPI_Get_elements will not work when passed the status +object from an MPI-IO operation. + +* All nonblocking I/O functions use a ROMIO-defined "MPIO_Request" +object instead of the usual "MPI_Request" object. Accordingly, two +functions, MPIO_Test and MPIO_Wait, are provided to wait and test on +these MPIO_Request objects. They have the same semantics as MPI_Test +and MPI_Wait. + +int MPIO_Test(MPIO_Request *request, int *flag, MPI_Status *status); +int MPIO_Wait(MPIO_Request *request, MPI_Status *status); + +The usual functions MPI_Test, MPI_Wait, MPI_Testany, etc., will not +work for nonblocking I/O. + +* This version works only on a homogeneous cluster of machines, +and only the "native" file data representation is supported. + +* When used with any MPI implementation other than MPICH 1.2.1 (or later), +all MPI-IO functions return only two possible error codes---MPI_SUCCESS +on success and MPI_ERR_UNKNOWN on failure. + +* Shared file pointers are not supported on PVFS and IBM PIOFS file +systems because they don't support fcntl file locks, and ROMIO uses +that feature to implement shared file pointers. + +* On HP machines running HPUX and on NEC SX-4, you need to compile +Fortran programs with mpifort instead of mpif77, because the f77 +compilers on these machines don't support 8-byte integers. + +* The file-open mode MPI_MODE_EXCL does not work on Intel PFS file system, +due to a bug in PFS. + + + +Usage Tips +---------- + +* When using ROMIO with SGI MPI, you may sometimes get an error +message from SGI MPI: ``MPI has run out of internal datatype +entries. Please set the environment variable MPI_TYPE_MAX for +additional space.'' If you get this error message, add this line to +your .cshrc file: + setenv MPI_TYPE_MAX 65536 +Use a larger number if you still get the error message. + +* If a Fortran program uses a file handle created using ROMIO's C +interface, or vice-versa, you must use the functions MPI_File_c2f +or MPI_File_f2c. Such a situation occurs, +for example, if a Fortran program uses an I/O library written in C +with MPI-IO calls. Similar functions MPIO_Request_f2c and +MPIO_Request_c2f are also provided. + +* For Fortran programs on the Intel Paragon, you may need +to provide the complete path to mpif.h in the include statement, e.g., + include '/usr/local/mpich/include/mpif.h' +instead of + include 'mpif.h' +This is because the -I option to the Paragon Fortran compiler if77 +doesn't work correctly. It always looks in the default directories first +and, therefore, picks up Intel's mpif.h, which is actually the +mpif.h of an older version of MPICH. + + + +ROMIO Users Mailing List +------------------------ + +Please register your copy of ROMIO with us by sending email +to majordomo@mcs.anl.gov with the message + +subscribe romio-users + +This will enable us to notify you of new releases of ROMIO as well as +bug fixes. + + + +Reporting Bugs +-------------- + +If you have trouble, first check the users guide (in +romio/doc/users-guide.ps.gz). Then check the on-line list of known +bugs and patches at http://www.mcs.anl.gov/romio . +Finally, if you still have problems, send a detailed message containing: + + The type of system (often, uname -a) + The output of configure + The output of make + Any programs or tests + +to romio-maint@mcs.anl.gov . + + + +ROMIO Internals +--------------- + +A key component of ROMIO that enables such a portable MPI-IO +implementation is an internal abstract I/O device layer called +ADIO. Most users of ROMIO will not need to deal with the ADIO layer at +all. However, ADIO is useful to those who want to port ROMIO to some +other file system. The ROMIO source code and the ADIO paper +(see doc/README) will help you get started. + +MPI-IO implementation issues are discussed in our IOPADS '99 paper, +"On Implementing MPI-IO Portably and with High Performance." +All ROMIO-related papers are available online from +http://www.mcs.anl.gov/romio. + + +Learning MPI-IO +--------------- + +The book "Using MPI-2: Advanced Features of the Message-Passing +Interface," published by MIT Press, provides a tutorial introduction to +all aspects of MPI-2, including parallel I/O. It has lots of example +programs. See http://www.mcs.anl.gov/mpi/usingmpi2 for further +information about the book. diff --git a/ompi/mca/io/romio314/romio/adio/Makefile.mk b/ompi/mca/io/romio314/romio/adio/Makefile.mk new file mode 100644 index 0000000000..505d51846d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/Makefile.mk @@ -0,0 +1,46 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +AM_CPPFLAGS += -I$(top_builddir)/adio/include -I$(top_srcdir)/adio/include + +noinst_HEADERS += \ + adio/include/adio.h \ + adio/include/adio_cb_config_list.h \ + adio/include/adio_extern.h \ + adio/include/adioi.h \ + adio/include/adioi_errmsg.h \ + adio/include/adioi_error.h \ + adio/include/adioi_fs_proto.h \ + adio/include/heap-sort.h \ + adio/include/mpio_error.h \ + adio/include/mpipr.h \ + adio/include/mpiu_greq.h \ + adio/include/nopackage.h \ + adio/include/mpiu_external32.h \ + adio/include/hint_fns.h + +include $(top_srcdir)/adio/ad_gpfs/Makefile.mk +include $(top_srcdir)/adio/ad_gpfs/bg/Makefile.mk +include $(top_srcdir)/adio/ad_gpfs/pe/Makefile.mk +include $(top_srcdir)/adio/ad_gridftp/Makefile.mk +include $(top_srcdir)/adio/ad_hfs/Makefile.mk +include $(top_srcdir)/adio/ad_lustre/Makefile.mk +include $(top_srcdir)/adio/ad_nfs/Makefile.mk +## NTFS builds are handled entirely by the separate Windows build system +##include $(top_srcdir)/adio/ad_ntfs/Makefile.mk +include $(top_srcdir)/adio/ad_panfs/Makefile.mk +include $(top_srcdir)/adio/ad_pfs/Makefile.mk +include $(top_srcdir)/adio/ad_piofs/Makefile.mk +include $(top_srcdir)/adio/ad_pvfs/Makefile.mk +include $(top_srcdir)/adio/ad_pvfs2/Makefile.mk +include $(top_srcdir)/adio/ad_sfs/Makefile.mk +include $(top_srcdir)/adio/ad_testfs/Makefile.mk +include $(top_srcdir)/adio/ad_ufs/Makefile.mk +include $(top_srcdir)/adio/ad_xfs/Makefile.mk +include $(top_srcdir)/adio/ad_zoidfs/Makefile.mk +include $(top_srcdir)/adio/common/Makefile.mk + diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/.gitignore b/ompi/mca/io/romio314/romio/adio/ad_gpfs/.gitignore new file mode 100644 index 0000000000..509a693e92 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/.gitignore @@ -0,0 +1,11 @@ +/Makefile +/.deps +/*.bb +/*.bbg +/*.gcda +/*.gcno +/.libs +/.libstamp* +/*.lo +/.*-cache +/.state-cache diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_gpfs/Makefile.mk new file mode 100644 index 0000000000..db8737be5c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/Makefile.mk @@ -0,0 +1,26 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2012 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_GPFS + +noinst_HEADERS += \ + adio/ad_gpfs/ad_gpfs_aggrs.h \ + adio/ad_gpfs/ad_gpfs.h \ + adio/ad_gpfs/ad_gpfs_tuning.h + +romio_other_sources += \ + adio/ad_gpfs/ad_gpfs_aggrs.c \ + adio/ad_gpfs/ad_gpfs_close.c \ + adio/ad_gpfs/ad_gpfs_flush.c \ + adio/ad_gpfs/ad_gpfs_tuning.c \ + adio/ad_gpfs/ad_gpfs.c \ + adio/ad_gpfs/ad_gpfs_open.c \ + adio/ad_gpfs/ad_gpfs_hints.c \ + adio/ad_gpfs/ad_gpfs_rdcoll.c \ + adio/ad_gpfs/ad_gpfs_wrcoll.c + +endif BUILD_AD_GPFS diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs.c new file mode 100644 index 0000000000..4be147f49a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs.c @@ -0,0 +1,61 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs.c + * \brief ??? + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ +#include "ad_gpfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_GPFS_operations = { + ADIOI_GPFS_Open, /* Open */ + ADIOI_GEN_OpenColl, /* Collective open */ + ADIOI_GEN_ReadContig, /* ReadContig */ + ADIOI_GEN_WriteContig, /* WriteContig */ + ADIOI_GPFS_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GPFS_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_GEN_Fcntl, /* Fcntl */ +#if defined(BGQPLATFORM) || defined(PEPLATFORM) + ADIOI_GPFS_SetInfo, /* SetInfo for BlueGene or PE */ +#else + ADIOI_GEN_SetInfo, /* SetInfo for any platform besides BlueGene or PE */ +#endif + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_GEN_WriteStrided, /* WriteStrided */ + ADIOI_GPFS_Close, /* Close */ +#ifdef ROMIO_HAVE_WORKING_AIO +#warning Consider BG support for NFS before enabling this. + ADIOI_GEN_IreadContig, /* IreadContig */ + ADIOI_GEN_IwriteContig, /* IwriteContig */ +#else + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ +#endif + ADIOI_GEN_IODone, /* ReadDone */ + ADIOI_GEN_IODone, /* WriteDone */ + ADIOI_GEN_IOComplete, /* ReadComplete */ + ADIOI_GEN_IOComplete, /* WriteComplete */ + ADIOI_GEN_IreadStrided, /* IreadStrided */ + ADIOI_GEN_IwriteStrided, /* IwriteStrided */ + ADIOI_GPFS_Flush, /* Flush */ + ADIOI_GEN_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ + ADIOI_GEN_Feature, /* Features */ +#ifdef BGQPLATFORM + "GPFS+BGQ: IBM GPFS for Blue Gene", +#elif PEPLATFORM + "GPFS+PE: IBM GPFS for PE", +#else + "GPFS: IBM GPFS" +#endif +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs.h b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs.h new file mode 100644 index 0000000000..81fb076c33 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs.h @@ -0,0 +1,71 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs.h + * \brief ??? + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_GPFS_INCLUDE +#define AD_GPFS_INCLUDE + +#include +#include +#include +#include +#include "adio.h" + +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif + + +void ADIOI_GPFS_Open(ADIO_File fd, int *error_code); + +void ADIOI_GPFS_Close(ADIO_File fd, int *error_code); + +void ADIOI_GPFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_GPFS_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); + +void ADIOI_GPFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); + +void ADIOI_GPFS_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); +void ADIOI_GPFS_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); + +void ADIOI_GPFS_ReadStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); + +void ADIOI_GPFS_WriteStridedColl(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); + +void ADIOI_GPFS_Flush(ADIO_File fd, int *error_code); + +#include "ad_gpfs_tuning.h" + + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_aggrs.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_aggrs.c new file mode 100644 index 0000000000..e403d9b1e5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_aggrs.c @@ -0,0 +1,846 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs_aggrs.c + * \brief The externally used function from this file is is declared in ad_gpfs_aggrs.h + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 1997-2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + + +#include "adio.h" +#include "adio_cb_config_list.h" +#include "ad_gpfs.h" +#include "ad_gpfs_aggrs.h" + +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + + +#ifdef USE_DBG_LOGGING + #define AGG_DEBUG 1 +#endif + +#ifndef TRACE_ERR +# define TRACE_ERR(format...) +#endif + +/* Comments copied from common: + * This file contains four functions: + * + * ADIOI_Calc_aggregator() + * ADIOI_Calc_file_domains() + * ADIOI_Calc_my_req() + * ADIOI_Calc_others_req() + * + * The last three of these were originally in ad_read_coll.c, but they are + * also shared with ad_write_coll.c. I felt that they were better kept with + * the rest of the shared aggregation code. + */ + +/* Discussion of values available from above: + * + * ADIO_Offset st_offsets[0..nprocs-1] + * ADIO_Offset end_offsets[0..nprocs-1] + * These contain a list of start and end offsets for each process in + * the communicator. For example, an access at loc 10, size 10 would + * have a start offset of 10 and end offset of 19. + * int nprocs + * number of processors in the collective I/O communicator + * ADIO_Offset min_st_offset + * ADIO_Offset fd_start[0..nprocs_for_coll-1] + * starting location of "file domain"; region that a given process will + * perform aggregation for (i.e. actually do I/O) + * ADIO_Offset fd_end[0..nprocs_for_coll-1] + * start + size - 1 roughly, but it can be less, or 0, in the case of + * uneven distributions + */ + +/* Description from common/ad_aggregate.c. (Does it completely apply to bg?) + * ADIOI_Calc_aggregator() + * + * The intention here is to implement a function which provides basically + * the same functionality as in Rajeev's original version of + * ADIOI_Calc_my_req(). He used a ceiling division approach to assign the + * file domains, and we use the same approach here when calculating the + * location of an offset/len in a specific file domain. Further we assume + * this same distribution when calculating the rank_index, which is later + * used to map to a specific process rank in charge of the file domain. + * + * A better (i.e. more general) approach would be to use the list of file + * domains only. This would be slower in the case where the + * original ceiling division was used, but it would allow for arbitrary + * distributions of regions to aggregators. We'd need to know the + * nprocs_for_coll in that case though, which we don't have now. + * + * Note a significant difference between this function and Rajeev's old code: + * this code doesn't necessarily return a rank in the range + * 0..nprocs_for_coll; instead you get something in 0..nprocs. This is a + * result of the rank mapping; any set of ranks in the communicator could be + * used now. + * + * Returns an integer representing a rank in the collective I/O communicator. + * + * The "len" parameter is also modified to indicate the amount of data + * actually available in this file domain. + */ +/* + * This is more general aggregator search function which does not base on the assumption + * that each aggregator hosts the file domain with the same size + */ +int ADIOI_GPFS_Calc_aggregator(ADIO_File fd, + ADIO_Offset off, + ADIO_Offset min_off, + ADIO_Offset *len, + ADIO_Offset fd_size, + ADIO_Offset *fd_start, + ADIO_Offset *fd_end) +{ + int rank_index, rank; + ADIO_Offset avail_bytes; + TRACE_ERR("Entering ADIOI_GPFS_Calc_aggregator\n"); + + ADIOI_Assert ( (off <= fd_end[fd->hints->cb_nodes-1] && off >= min_off && fd_start[0] >= min_off ) ); + + /* binary search --> rank_index is returned */ + int ub = fd->hints->cb_nodes; + int lb = 0; + /* get an index into our array of aggregators */ + /* Common code for striping - bg doesn't use it but it's + here to make diff'ing easier. + rank_index = (int) ((off - min_off + fd_size)/ fd_size - 1); + + if (fd->hints->striping_unit > 0) { + * wkliao: implementation for file domain alignment + fd_start[] and fd_end[] have been aligned with file lock + boundaries when returned from ADIOI_Calc_file_domains() so cannot + just use simple arithmatic as above * + rank_index = 0; + while (off > fd_end[rank_index]) rank_index++; + } + bg does it's own striping below + */ + rank_index = fd->hints->cb_nodes / 2; + while ( off < fd_start[rank_index] || off > fd_end[rank_index] ) { + if ( off > fd_end [rank_index] ) { + lb = rank_index; + rank_index = (rank_index + ub) / 2; + } + else + if ( off < fd_start[rank_index] ) { + ub = rank_index; + rank_index = (rank_index + lb) / 2; + } + } + /* we index into fd_end with rank_index, and fd_end was allocated to be no + * bigger than fd->hins->cb_nodes. If we ever violate that, we're + * overrunning arrays. Obviously, we should never ever hit this abort */ + if (rank_index >= fd->hints->cb_nodes || rank_index < 0) { + FPRINTF(stderr, "Error in ADIOI_Calc_aggregator(): rank_index(%d) >= fd->hints->cb_nodes (%d) fd_size=%lld off=%lld\n", + rank_index,fd->hints->cb_nodes,fd_size,off); + MPI_Abort(MPI_COMM_WORLD, 1); + } + /* DBG_FPRINTF ("ADIOI_GPFS_Calc_aggregator: rank_index = %d\n", + rank_index ); */ + + /* + * remember here that even in Rajeev's original code it was the case that + * different aggregators could end up with different amounts of data to + * aggregate. here we use fd_end[] to make sure that we know how much + * data this aggregator is working with. + * + * the +1 is to take into account the end vs. length issue. + */ + avail_bytes = fd_end[rank_index] + 1 - off; + if (avail_bytes < *len && avail_bytes > 0) { + /* this file domain only has part of the requested contig. region */ + + *len = avail_bytes; + } + + /* map our index to a rank */ + /* NOTE: FOR NOW WE DON'T HAVE A MAPPING...JUST DO 0..NPROCS_FOR_COLL */ + rank = fd->hints->ranklist[rank_index]; + TRACE_ERR("Leaving ADIOI_GPFS_Calc_aggregator\n"); + + return rank; +} + +/* + * Compute a dynamic access range based file domain partition among I/O aggregators, + * which align to the GPFS block size + * Divide the I/O workload among "nprocs_for_coll" processes. This is + * done by (logically) dividing the file into file domains (FDs); each + * process may directly access only its own file domain. + * Additional effort is to make sure that each I/O aggregator get + * a file domain that aligns to the GPFS block size. So, there will + * not be any false sharing of GPFS file blocks among multiple I/O nodes. + * + * The common version of this now accepts a min_fd_size and striping_unit. + * It doesn't seem necessary here (using GPFS block sizes) but keep it in mind + * (e.g. we could pass striping unit instead of using fs_ptr->blksize). + */ +void ADIOI_GPFS_Calc_file_domains(ADIO_File fd, + ADIO_Offset *st_offsets, + ADIO_Offset *end_offsets, + int nprocs, + int nprocs_for_coll, + ADIO_Offset *min_st_offset_ptr, + ADIO_Offset **fd_start_ptr, + ADIO_Offset **fd_end_ptr, + ADIO_Offset *fd_size_ptr, + void *fs_ptr) +{ + ADIO_Offset min_st_offset, max_end_offset, *fd_start, *fd_end, *fd_size; + int i, aggr; + TRACE_ERR("Entering ADIOI_GPFS_Calc_file_domains\n"); + blksize_t blksize; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5004, 0, NULL); +#endif + +# if AGG_DEBUG + static char myname[] = "ADIOI_GPFS_Calc_file_domains"; + DBG_FPRINTF(stderr, "%s(%d): %d aggregator(s)\n", + myname,__LINE__,nprocs_for_coll); +# endif + if (fd->blksize <= 0) + /* default to 1M if blksize unset */ + fd->blksize = 1048576; + blksize = fd->blksize; + +# if AGG_DEBUG + DBG_FPRINTF(stderr,"%s(%d): Blocksize=%ld\n",myname,__LINE__,blksize); +# endif +/* find min of start offsets and max of end offsets of all processes */ + min_st_offset = st_offsets [0]; + max_end_offset = end_offsets[0]; + for (i=1; ihints->fs_hints.bg.numbridges*sizeof(int)); + /* tmpbridgelistnum: copy of the bridgelistnum whose entries can be + * decremented to keep track of bridge assignments during the actual + * large block assignments to the agg rank list*/ + int *tmpbridgelistnum = + (int *) ADIOI_Malloc(fd->hints->fs_hints.bg.numbridges*sizeof(int)); + + int j; + for (j=0;jhints->fs_hints.bg.numbridges;j++) { + int k, bridgerankoffset = 0; + for (k=0;khints->fs_hints.bg.bridgelistnum[k]; + } + bridgelistoffset[j] = bridgerankoffset; + } + + for (j=0;jhints->fs_hints.bg.numbridges;j++) + tmpbridgelistnum[j] = fd->hints->fs_hints.bg.bridgelistnum[j]; + int bridgeiter = 0; + + /* distribute the large blocks across the aggs going breadth-first + * across the bridgelist - this distributes the fd sizes across the + * ions, so later in the file domain assignment when it iterates thru + * the ranklist the offsets will be contiguous within the bridge and + * ion as well */ + for (j=0;j 0) { + foundbridge = 1; + /* + printf("bridgeiter is %d tmpbridgelistnum[bridgeiter] is %d bridgelistoffset[bridgeiter] is %d\n",bridgeiter,tmpbridgelistnum[bridgeiter],bridgelistoffset[bridgeiter]); + printf("naggs is %d bridgeiter is %d bridgelistoffset[bridgeiter] is %d tmpbridgelistnum[bridgeiter] is %d\n",naggs, bridgeiter,bridgelistoffset[bridgeiter],tmpbridgelistnum[bridgeiter]); + printf("naggs is %d bridgeiter is %d setting fd_size[%d]\n",naggs, bridgeiter,bridgelistoffset[bridgeiter]+(fd->hints->bridgelistnum[bridgeiter]-tmpbridgelistnum[bridgeiter])); + */ + int currentbridgelistnum = + (fd->hints->fs_hints.bg.bridgelistnum[bridgeiter]- + tmpbridgelistnum[bridgeiter]); + int currentfdsizeindex = bridgelistoffset[bridgeiter] + + currentbridgelistnum; + fd_size[currentfdsizeindex] = (nb_cn_small+1) * blksize; + tmpbridgelistnum[bridgeiter]--; + } + if (bridgeiter == (fd->hints->fs_hints.bg.numbridges-1)) { + /* guard against infinite loop - should only ever make 1 pass + * thru bridgelist */ + ADIOI_Assert(numbridgelistpasses == 0); + numbridgelistpasses++; + bridgeiter = 0; + } + else + bridgeiter++; + } + } + ADIOI_Free(tmpbridgelistnum); + ADIOI_Free(bridgelistoffset); + + } else { + /* BG/L- and BG/P-style distribution of file domains: simple allocation of + * file domins to each aggregator */ + for (i=0; icomm,&myrank); + if (myrank == 0) { + fprintf(stderr,"naggs_small is %d nb_cn_small is %d\n",naggs_small,nb_cn_small); + for (i=0; ihints->ranklist[i]); + } + } +#endif + +#else // not BGQ platform + for (i=0; i 0) { + off += fd_len; /* point to first remaining byte */ + fd_len = rem_len; /* save remaining size, pass to calc */ + proc = ADIOI_GPFS_Calc_aggregator(fd, off, min_st_offset, &fd_len, + fd_size, fd_start, fd_end); + + count_my_req_per_proc[proc]++; + rem_len -= fd_len; /* reduce remaining length by amount from fd */ + } + } + +/* now allocate space for my_req, offset, and len */ + + *my_req_ptr = (ADIOI_Access *) + ADIOI_Malloc(nprocs*sizeof(ADIOI_Access)); + my_req = *my_req_ptr; + + count_my_req_procs = 0; + for (i=0; i < nprocs; i++) { + if (count_my_req_per_proc[i]) { + my_req[i].offsets = (ADIO_Offset *) + ADIOI_Malloc(count_my_req_per_proc[i] * sizeof(ADIO_Offset)); + my_req[i].lens = + ADIOI_Malloc(count_my_req_per_proc[i] * sizeof(ADIO_Offset)); + count_my_req_procs++; + } + my_req[i].count = 0; /* will be incremented where needed + later */ + } + +/* now fill in my_req */ + curr_idx = 0; + for (i=0; i 0) { + off += fd_len; + fd_len = rem_len; + proc = ADIOI_GPFS_Calc_aggregator(fd, off, min_st_offset, &fd_len, + fd_size, fd_start, fd_end); + + if (buf_idx[proc] == -1) + { + ADIOI_Assert(curr_idx == (int) curr_idx); + buf_idx[proc] = (int) curr_idx; + } + + l = my_req[proc].count; + curr_idx += fd_len; + rem_len -= fd_len; + + my_req[proc].offsets[l] = off; + my_req[proc].lens[l] = fd_len; + my_req[proc].count++; + } + } + + + +#ifdef AGG_DEBUG + for (i=0; i 0) { + DBG_FPRINTF(stderr, "data needed from %d (count = %d):\n", i, + my_req[i].count); + for (l=0; l < my_req[i].count; l++) { + DBG_FPRINTF(stderr, " off[%d] = %lld, len[%d] = %lld\n", l, + my_req[i].offsets[l], l, my_req[i].lens[l]); + } + } + DBG_FPRINTF(stderr, "buf_idx[%d] = 0x%x\n", i, buf_idx[i]); + } +#endif + + *count_my_req_procs_ptr = count_my_req_procs; + *buf_idx_ptr = buf_idx; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5025, 0, NULL); +#endif + TRACE_ERR("Leaving ADIOI_GPFS_Calc_my_req\n"); +} + +/* + * ADIOI_Calc_others_req (copied to bg and switched to all to all for performance) + * + * param[in] count_my_req_procs Number of processes whose file domain my + * request touches. + * param[in] count_my_req_per_proc count_my_req_per_proc[i] gives the no. of + * contig. requests of this process in + * process i's file domain. + * param[in] my_req A structure defining my request + * param[in] nprocs Number of nodes in the block + * param[in] myrank Rank of this node + * param[out] count_others_req_proc_ptr Number of processes whose requests lie in + * my process's file domain (including my + * process itself) + * param[out] others_req_ptr Array of other process' requests that lie + * in my process's file domain + */ +void ADIOI_GPFS_Calc_others_req(ADIO_File fd, int count_my_req_procs, + int *count_my_req_per_proc, + ADIOI_Access *my_req, + int nprocs, int myrank, + int *count_others_req_procs_ptr, + ADIOI_Access **others_req_ptr) +{ + TRACE_ERR("Entering ADIOI_GPFS_Calc_others_req\n"); +/* determine what requests of other processes lie in this process's + file domain */ + +/* count_others_req_procs = number of processes whose requests lie in + this process's file domain (including this process itself) + count_others_req_per_proc[i] indicates how many separate contiguous + requests of proc. i lie in this process's file domain. */ + + int *count_others_req_per_proc, count_others_req_procs; + int i; + ADIOI_Access *others_req; + + /* Parameters for MPI_Alltoallv */ + int *scounts, *sdispls, *rcounts, *rdispls; + + /* Parameters for MPI_Alltoallv. These are the buffers, which + * are later computed to be the lowest address of all buffers + * to be sent/received for offsets and lengths. Initialize to + * the highest possible address which is the current minimum. + */ + void *sendBufForOffsets=(void*)0xFFFFFFFFFFFFFFFF, + *sendBufForLens =(void*)0xFFFFFFFFFFFFFFFF, + *recvBufForOffsets=(void*)0xFFFFFFFFFFFFFFFF, + *recvBufForLens =(void*)0xFFFFFFFFFFFFFFFF; + +/* first find out how much to send/recv and from/to whom */ +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5026, 0, NULL); +#endif + /* Send 1 int to each process. count_my_req_per_proc[i] is the number of + * requests that my process will do to the file domain owned by process[i]. + * Receive 1 int from each process. count_others_req_per_proc[i] is the number of + * requests that process[i] will do to the file domain owned by my process. + */ + count_others_req_per_proc = (int *) ADIOI_Malloc(nprocs*sizeof(int)); +/* cora2a1=timebase(); */ +/*for(i=0;icomm); + +/* total_cora2a+=timebase()-cora2a1; */ + + /* Allocate storage for an array of other nodes' accesses of our + * node's file domain. Also allocate storage for the alltoallv + * parameters. + */ + *others_req_ptr = (ADIOI_Access *) + ADIOI_Malloc(nprocs*sizeof(ADIOI_Access)); + others_req = *others_req_ptr; + + scounts = ADIOI_Malloc(nprocs*sizeof(int)); + sdispls = ADIOI_Malloc(nprocs*sizeof(int)); + rcounts = ADIOI_Malloc(nprocs*sizeof(int)); + rdispls = ADIOI_Malloc(nprocs*sizeof(int)); + + /* If process[i] has any requests in my file domain, + * initialize an ADIOI_Access structure that will describe each request + * from process[i]. The offsets, lengths, and buffer pointers still need + * to be obtained to complete the setting of this structure. + */ + count_others_req_procs = 0; + for (i=0; icomm); + + /************************/ + /* Exchange the lengths */ + /************************/ + + for (i=0; icomm); + + /* Clean up */ + ADIOI_Free(count_others_req_per_proc); + ADIOI_Free (scounts); + ADIOI_Free (sdispls); + ADIOI_Free (rcounts); + ADIOI_Free (rdispls); + + *count_others_req_procs_ptr = count_others_req_procs; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5027, 0, NULL); +#endif + TRACE_ERR("Leaving ADIOI_GPFS_Calc_others_req\n"); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_aggrs.h b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_aggrs.h new file mode 100644 index 0000000000..1b6215e576 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_aggrs.h @@ -0,0 +1,86 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs_aggrs.h + * \brief ??? + */ + +/* + * File: ad_gpfs_aggrs.h + * + * Declares functions optimized specifically for GPFS parallel I/O solution. + * + */ + +#ifndef AD_GPFS_AGGRS_H_ +#define AD_GPFS_AGGRS_H_ + +#include "adio.h" +#include + +#ifdef HAVE_GPFS_H +#include +#endif + + + /* overriding ADIOI_Calc_file_domains() to apply 'aligned file domain partitioning'. */ + void ADIOI_GPFS_Calc_file_domains(ADIO_File fd, + ADIO_Offset *st_offsets, + ADIO_Offset *end_offsets, + int nprocs, + int nprocs_for_coll, + ADIO_Offset *min_st_offset_ptr, + ADIO_Offset **fd_start_ptr, + ADIO_Offset **fd_end_ptr, + ADIO_Offset *fd_size_ptr, + void *fs_ptr); + + /* overriding ADIOI_Calc_aggregator() for the default implementation is specific for + static file domain partitioning */ + int ADIOI_GPFS_Calc_aggregator(ADIO_File fd, + ADIO_Offset off, + ADIO_Offset min_off, + ADIO_Offset *len, + ADIO_Offset fd_size, + ADIO_Offset *fd_start, + ADIO_Offset *fd_end); + + /* overriding ADIOI_Calc_my_req for the default implementation is specific for + static file domain partitioning */ + void ADIOI_GPFS_Calc_my_req ( ADIO_File fd, ADIO_Offset *offset_list, ADIO_Offset *len_list, + int contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset *fd_start, + ADIO_Offset *fd_end, ADIO_Offset fd_size, + int nprocs, + int *count_my_req_procs_ptr, + int **count_my_req_per_proc_ptr, + ADIOI_Access **my_req_ptr, + int **buf_idx_ptr); + + /* + * ADIOI_Calc_others_req + * + * param[in] count_my_req_procs Number of processes whose file domain my + * request touches. + * param[in] count_my_req_per_proc count_my_req_per_proc[i] gives the no. of + * contig. requests of this process in + * process i's file domain. + * param[in] my_req A structure defining my request + * param[in] nprocs Number of nodes in the block + * param[in] myrank Rank of this node + * param[out] count_others_req_proc_ptr Number of processes whose requests lie in + * my process's file domain (including my + * process itself) + * param[out] others_req_ptr Array of other process' requests that lie + * in my process's file domain + */ + void ADIOI_GPFS_Calc_others_req(ADIO_File fd, int count_my_req_procs, + int *count_my_req_per_proc, + ADIOI_Access *my_req, + int nprocs, int myrank, + int *count_others_req_procs_ptr, + ADIOI_Access **others_req_ptr); + + +#endif /* AD_GPFS_AGGRS_H_ */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_close.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_close.c new file mode 100644 index 0000000000..f8a41671a2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_close.c @@ -0,0 +1,57 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs_close.c + * \brief ??? + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gpfs.h" +#include "ad_gpfs_tuning.h" +#include + +void ADIOI_GPFS_Close(ADIO_File fd, int *error_code) +{ + int err, derr=0; + static char myname[] = "ADIOI_GPFS_CLOSE"; + +#ifdef PROFILE + MPE_Log_event(9, 0, "start close"); +#endif + + if (fd->null_fd >= 0) + close(fd->null_fd); + + err = close(fd->fd_sys); + if (fd->fd_direct >= 0) + { + derr = close(fd->fd_direct); + } + +#ifdef PROFILE + MPE_Log_event(10, 0, "end close"); +#endif + +/* FPRINTF(stderr,"%s(%d):'%s'. Free %#X\n",myname,__LINE__,fd->filename,(int)fd->fs_ptr);*/ + if (fd->fs_ptr != NULL) { + ADIOI_Free(fd->fs_ptr); + fd->fs_ptr = NULL; + } + fd->fd_sys = -1; + fd->fd_direct = -1; + + if (err == -1 || derr == -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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_flush.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_flush.c new file mode 100644 index 0000000000..555002f639 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_flush.c @@ -0,0 +1,68 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs_flush.c + * \brief Scalable flush for GPFS + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gpfs.h" + +void ADIOI_GPFS_Flush(ADIO_File fd, int *error_code) +{ + int err=0; + static char myname[] = "ADIOI_GPFS_FLUSH"; + + int rank; + + MPI_Comm_rank(fd->comm, &rank); + + /* the old logic about who is an fsync aggregator and who is not fell down + * when deferred open was enabled. Instead, make this look more like + * ad_pvfs2_flush. If one day the I/O aggregators have something they need + * to flush, we can consult the 'fd->hints->ranklist[]' array. For now, a + * flush from one process should suffice */ + + /* ensure all other proceses are done writing. On many platforms MPI_Reduce + * is fastest because it has the lightest constraints. On Blue Gene, BARRIER + * is optimized */ + MPI_Barrier(fd->comm); + + if (rank == fd->hints->ranklist[0]) { + err = fsync(fd->fd_sys); + DBG_FPRINTF(stderr,"aggregation:fsync %s, err=%#X, errno=%#X\n",fd->filename, err, errno); + /* We want errno, not the return code if it failed */ + if (err == -1) err = errno; + else err = 0; + } + MPI_Bcast(&err, 1, MPI_UNSIGNED, fd->hints->ranklist[0], fd->comm); + DBGV_FPRINTF(stderr,"aggregation result:fsync %s, errno %#X,\n",fd->filename, err); + + if (err) /* if it's non-zero, it must be an errno */ + { + errno = err; + err = -1; + } + + /* --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)); + DBGT_FPRINTF(stderr,"fsync %s, err=%#X, errno=%#X\n",fd->filename, err, errno); + return; + } + /* --END ERROR HANDLING-- */ + + *error_code = MPI_SUCCESS; +} + diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_hints.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_hints.c new file mode 100644 index 0000000000..7af0a0c67a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_hints.c @@ -0,0 +1,288 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs_hints.c + * \brief GPFS hint processing - for now, only used for BlueGene and PE platforms + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "hint_fns.h" + +#include "ad_gpfs.h" + +#define ADIOI_GPFS_CB_BUFFER_SIZE_DFLT "16777216" +#define ADIOI_GPFS_IND_RD_BUFFER_SIZE_DFLT "4194304" +#define ADIOI_GPFS_IND_WR_BUFFER_SIZE_DFLT "4194304" + +#ifdef BGQPLATFORM +#define ADIOI_BG_NAGG_IN_PSET_HINT_NAME "bg_nodes_pset" +#endif + +/** \page mpiio_vars MPIIO Configuration + * + * GPFS MPIIO configuration and performance tuning. Used by ad_gpfs ADIO. + * + * Used for BlueGene and PE platforms, which each have their own aggregator selection + * algorithms that ignore user provided cb_config_list. + * + * \section hint_sec Hints + * - bg_nodes_pset - BlueGene only - specify how many aggregators to use per pset. + * This hint will override the cb_nodes hint based on BlueGene psets. + * - N - Use N nodes per pset as aggregators. + * - Default is based on partition configuration and cb_nodes. + * + * The following default key/value pairs may differ from other platform defaults. + * + * - key = cb_buffer_size value = 16777216 + * - key = romio_cb_read value = enable + * - key = romio_cb_write value = enable + * - key = ind_rd_buffer_size value = 4194304 + * - key = ind_wr_buffer_size value = 4194304 + */ + +#ifdef BGQPLATFORM +/* Compute the aggregator-related parameters that are required in 2-phase collective IO of ADIO. */ +extern int +ADIOI_BG_gen_agg_ranklist(ADIO_File fd, int n_proxy_per_pset); +#elif PEPLATFORM +extern int +ADIOI_PE_gen_agg_ranklist(ADIO_File fd); +#endif + +void ADIOI_GPFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ +/* if fd->info is null, create a new info object. + Initialize fd->info to default values. + Initialize fd->hints to default values. + Examine the info object passed by the user. If it contains values that + ROMIO understands, override the default. */ + + MPI_Info info; + char *value; + int flag, intval, nprocs=0, nprocs_is_valid = 0; + static char myname[] = "ADIOI_GPFS_SETINFO"; + + int did_anything = 0; + + if (fd->info == MPI_INFO_NULL) MPI_Info_create(&(fd->info)); + info = fd->info; + + /* Note that fd->hints is allocated at file open time; thus it is + * not necessary to allocate it, or check for allocation, here. + */ + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + ADIOI_Assert ((value != NULL)); + + /* initialize info and hints to default values if they haven't been + * previously initialized + */ + if (!fd->hints->initialized) { + + ad_gpfs_get_env_vars(); + did_anything = 1; + + /* buffer size for collective I/O */ + ADIOI_Info_set(info, "cb_buffer_size", ADIOI_GPFS_CB_BUFFER_SIZE_DFLT); + fd->hints->cb_buffer_size = atoi(ADIOI_GPFS_CB_BUFFER_SIZE_DFLT); + + /* default is to let romio automatically decide when to use + * collective buffering + */ + ADIOI_Info_set(info, "romio_cb_read", "enable"); + fd->hints->cb_read = ADIOI_HINT_ENABLE; + ADIOI_Info_set(info, "romio_cb_write", "enable"); + fd->hints->cb_write = ADIOI_HINT_ENABLE; + + if ( fd->hints->cb_config_list != NULL ) ADIOI_Free (fd->hints->cb_config_list); + fd->hints->cb_config_list = NULL; + + /* number of processes that perform I/O in collective I/O */ + MPI_Comm_size(fd->comm, &nprocs); + nprocs_is_valid = 1; + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", nprocs); + ADIOI_Info_set(info, "cb_nodes", value); + fd->hints->cb_nodes = -1; + + /* hint indicating that no indep. I/O will be performed on this file */ + ADIOI_Info_set(info, "romio_no_indep_rw", "false"); + fd->hints->no_indep_rw = 0; + + /* gpfs is not implementing file realms (ADIOI_IOStridedColl), + initialize to disabled it. */ + /* hint instructing the use of persistent file realms */ + ADIOI_Info_set(info, "romio_cb_pfr", "disable"); + fd->hints->cb_pfr = ADIOI_HINT_DISABLE; + + /* hint guiding the assignment of persistent file realms */ + ADIOI_Info_set(info, "romio_cb_fr_types", "aar"); + fd->hints->cb_fr_type = ADIOI_FR_AAR; + + /* hint to align file realms with a certain byte value */ + ADIOI_Info_set(info, "romio_cb_fr_alignment", "1"); + fd->hints->cb_fr_alignment = 1; + + /* hint to set a threshold percentage for a datatype's size/extent at + * which data sieving should be done in collective I/O */ + ADIOI_Info_set(info, "romio_cb_ds_threshold", "0"); + fd->hints->cb_ds_threshold = 0; + + /* hint to switch between point-to-point or all-to-all for two-phase */ + ADIOI_Info_set(info, "romio_cb_alltoall", "automatic"); + fd->hints->cb_alltoall = ADIOI_HINT_AUTO; + + /* deferred_open derived from no_indep_rw and cb_{read,write} */ + fd->hints->deferred_open = 0; + + /* buffer size for data sieving in independent reads */ + ADIOI_Info_set(info, "ind_rd_buffer_size", ADIOI_GPFS_IND_RD_BUFFER_SIZE_DFLT); + fd->hints->ind_rd_buffer_size = atoi(ADIOI_GPFS_IND_RD_BUFFER_SIZE_DFLT); + + /* buffer size for data sieving in independent writes */ + ADIOI_Info_set(info, "ind_wr_buffer_size", ADIOI_GPFS_IND_WR_BUFFER_SIZE_DFLT); + fd->hints->ind_wr_buffer_size = atoi(ADIOI_GPFS_IND_WR_BUFFER_SIZE_DFLT); + + + ADIOI_Info_set(info, "romio_ds_read", "automatic"); + fd->hints->ds_read = ADIOI_HINT_AUTO; + ADIOI_Info_set(info, "romio_ds_write", "automatic"); + fd->hints->ds_write = ADIOI_HINT_AUTO; + + /* still to do: tune this a bit for a variety of file systems. there's + * no good default value so just leave it unset */ + fd->hints->min_fdomain_size = 0; + fd->hints->striping_unit = 0; + + fd->hints->initialized = 1; + } + + /* add in user's info if supplied */ + if (users_info != MPI_INFO_NULL) { + ADIOI_Info_check_and_install_int(fd, users_info, "cb_buffer_size", + &(fd->hints->cb_buffer_size), myname, error_code); + /* new hints for enabling/disabling coll. buffering on + * reads/writes + */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_read", + &(fd->hints->cb_read), myname, error_code); + if (fd->hints->cb_read == ADIOI_HINT_DISABLE) { + /* romio_cb_read overrides no_indep_rw */ + ADIOI_Info_set(info, "romio_no_indep_rw", "false"); + fd->hints->no_indep_rw = ADIOI_HINT_DISABLE; + } + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_write", + &(fd->hints->cb_write), myname, error_code); + if (fd->hints->cb_write == ADIOI_HINT_DISABLE) { + /* romio_cb_write overrides no_indep_rw */ + ADIOI_Info_set(info, "romio_no_indep_rw", "false"); + fd->hints->no_indep_rw = ADIOI_HINT_DISABLE; + } + /* Has the user indicated all I/O will be done collectively? */ + ADIOI_Info_check_and_install_true(fd, users_info, "romio_no_indep_rw", + &(fd->hints->no_indep_rw), myname, error_code); + if (fd->hints->no_indep_rw == 1) { + /* if 'no_indep_rw' set, also hint that we will do + * collective buffering: if we aren't doing independent io, + * then we have to do collective */ + ADIOI_Info_set(info, "romio_cb_write", "enable"); + ADIOI_Info_set(info, "romio_cb_read", "enable"); + fd->hints->cb_read = 1; + fd->hints->cb_write = 1; + } + + /* new hints for enabling/disabling data sieving on + * reads/writes + */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_ds_read", + &(fd->hints->ds_read), myname, error_code); + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_ds_write", + &(fd->hints->ds_write), myname, error_code); + + ADIOI_Info_check_and_install_int(fd, users_info, "ind_wr_buffer_size", + &(fd->hints->ind_wr_buffer_size), myname, error_code); + ADIOI_Info_check_and_install_int(fd, users_info, "ind_rd_buffer_size", + &(fd->hints->ind_rd_buffer_size), myname, error_code); + + memset( value, 0, MPI_MAX_INFO_VAL+1 ); + ADIOI_Info_get(users_info, "romio_min_fdomain_size", MPI_MAX_INFO_VAL, + value, &flag); + if ( flag && ((intval = atoi(value)) > 0) ) { + ADIOI_Info_set(info, "romio_min_fdomain_size", value); + fd->hints->min_fdomain_size = intval; + } + /* Now we use striping unit in common code so we should + process hints for it. */ + ADIOI_Info_check_and_install_int(fd, users_info, "striping_unit", + &(fd->hints->striping_unit), myname, error_code); + +#ifdef BGQPLATFORM + memset( value, 0, MPI_MAX_INFO_VAL+1 ); + ADIOI_Info_get(users_info, ADIOI_BG_NAGG_IN_PSET_HINT_NAME, MPI_MAX_INFO_VAL, + value, &flag); + if (flag && ((intval = atoi(value)) > 0)) { + + did_anything = 1; + ADIOI_Info_set(info, ADIOI_BG_NAGG_IN_PSET_HINT_NAME, value); + fd->hints->cb_nodes = intval; + } +#endif + } + + /* special CB aggregator assignment */ + if (did_anything) { +#ifdef BGQPLATFORM + ADIOI_BG_gen_agg_ranklist(fd, fd->hints->cb_nodes); +#elif PEPLATFORM + ADIOI_PE_gen_agg_ranklist(fd); +#endif + } + + /* deferred_open won't be set by callers, but if the user doesn't + * explicitly disable collecitve buffering (two-phase) and does hint that + * io w/o independent io is going on, we'll set this internal hint as a + * convenience */ + if ( ( (fd->hints->cb_read != ADIOI_HINT_DISABLE) \ + && (fd->hints->cb_write != ADIOI_HINT_DISABLE)\ + && fd->hints->no_indep_rw ) ) { + fd->hints->deferred_open = 1; + } else { + /* setting romio_no_indep_rw enable and romio_cb_{read,write} + * disable at the same time doesn't make sense. honor + * romio_cb_{read,write} and force the no_indep_rw hint to + * 'disable' */ + ADIOI_Info_set(info, "romio_no_indep_rw", "false"); + fd->hints->no_indep_rw = 0; + fd->hints->deferred_open = 0; + } + + /* BobC commented this out, but since hint processing runs on both bg and + * bglockless, we need to keep DS writes enabled on gpfs and disabled on + * PVFS */ + if (ADIO_Feature(fd, ADIO_DATA_SIEVING_WRITES) == 0) { + /* disable data sieving for fs that do not + support file locking */ + ADIOI_Info_get(info, "ind_wr_buffer_size", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + /* get rid of this value if it is set */ + ADIOI_Info_delete(info, "ind_wr_buffer_size"); + } + /* note: leave ind_wr_buffer_size alone; used for other cases + * as well. -- Rob Ross, 04/22/2003 + */ + ADIOI_Info_set(info, "romio_ds_write", "disable"); + fd->hints->ds_write = ADIOI_HINT_DISABLE; + } + + ADIOI_Free(value); + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_open.c new file mode 100644 index 0000000000..f4fef37c85 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_open.c @@ -0,0 +1,156 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs_open.c + * \brief ??? + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gpfs.h" +#include "ad_gpfs_tuning.h" + +#include +#include +#include +#include + + +#ifdef HAVE_GPFS_H +#include +#endif +#ifdef HAVE_GPFS_FCNTL_H +#include +#endif + +#ifdef HAVE_GPFS_FCNTL_H +static void gpfs_free_all_locks(int fd) +{ + int rc; + struct { + gpfsFcntlHeader_t header; + gpfsFreeRange_t release; + } release_all; + + release_all.header.totalLength = sizeof(release_all); + release_all.header.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION; + release_all.header.fcntlReserved = 0; + + release_all.release.structLen = sizeof(release_all.release); + release_all.release.structType = GPFS_FREE_RANGE; + release_all.release.start = 0; + release_all.release.length = 0; + + rc = gpfs_fcntl(fd, &release_all); + if (rc != 0) { + DBGV_FPRINTF(stderr,"GPFS fcntl release failed with rc=%d, errno=%d\n", + rc,errno); + } +} +#endif + + +void ADIOI_GPFS_Open(ADIO_File fd, int *error_code) +{ + int perm, old_mask, amode, rank, rc; + static char myname[] = "ADIOI_GPFS_OPEN"; + + /* set internal variables for tuning environment variables */ + ad_gpfs_get_env_vars(); + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_open_a, 0, NULL); +#endif + fd->fd_sys = open(fd->filename, amode, perm); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_open_b, 0, NULL); +#endif + DBG_FPRINTF(stderr,"open('%s',%#X,%#X) rc=%d, errno=%d\n",fd->filename,amode,perm,fd->fd_sys,errno); + fd->fd_direct = -1; + + if (gpfsmpio_devnullio == 1) { + fd->null_fd = open("/dev/null", O_RDWR); + } else { + fd->null_fd = -1; + } + + if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND)) + fd->fp_ind = fd->fp_sys_posn = lseek(fd->fd_sys, 0, SEEK_END); + + if(fd->fd_sys != -1) + { + + fd->blksize = 1048576; /* default to 1M */ + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_stat_a, 0, NULL); +#endif + /* in this fs-specific routine, we might not be called over entire + * communicator (deferred open). Collect statistics on one process. + * ADIOI_GEN_Opencoll (common-code caller) will take care of the + * broadcast */ + + MPI_Comm_rank(fd->comm, &rank); + if ((rank == fd->hints->ranklist[0]) || (fd->comm == MPI_COMM_SELF)) { + struct stat64 gpfs_statbuf; + /* Get the (real) underlying file system block size */ + rc = stat64(fd->filename, &gpfs_statbuf); + if (rc >= 0) + { + fd->blksize = gpfs_statbuf.st_blksize; + DBGV_FPRINTF(stderr,"Successful stat '%s'. Blocksize=%ld\n", + fd->filename,gpfs_statbuf.st_blksize); + } + else + { + DBGV_FPRINTF(stderr,"Stat '%s' failed with rc=%d, errno=%d\n", + fd->filename,rc,errno); + } + } + /* all other ranks have incorrect fd->blocksize, but ADIOI_GEN_Opencoll + * will take care of that in both standard and deferred-open case */ + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_stat_b, 0, NULL); +#endif + +#ifdef HAVE_GPFS_FCNTL_H + /* in parallel workload, might be helpful to immediately release block + * tokens. Or, system call overhead will outweigh any benefits... */ + if (getenv("ROMIO_GPFS_FREE_LOCKS")!=NULL) + gpfs_free_all_locks(fd->fd_sys); + +#endif + } + + if (fd->fd_sys == -1) { + *error_code = ADIOI_Err_create_code(myname, fd->filename, errno); + } + else *error_code = MPI_SUCCESS; +} +/* + *vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_rdcoll.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_rdcoll.c new file mode 100644 index 0000000000..c2cad8bf8b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_rdcoll.c @@ -0,0 +1,1171 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs_rdcoll.c + * \brief ??? + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "ad_gpfs.h" +#include "ad_gpfs_aggrs.h" + +#ifdef PROFILE +#include "mpe.h" +#endif + +#ifdef USE_DBG_LOGGING + #define RDCOLL_DEBUG 1 +#endif +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + +/* prototypes of functions used for collective reads only. */ +static void ADIOI_Read_and_exch(ADIO_File fd, void *buf, MPI_Datatype + datatype, int nprocs, + int myrank, ADIOI_Access + *others_req, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, + ADIO_Offset + min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *buf_idx, int *error_code); +static void ADIOI_R_Exchange_data(ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, ADIO_Offset *offset_list, ADIO_Offset + *len_list, int *send_size, int *recv_size, + int *count, int *start_pos, + int *partial_send, + int *recd_from_proc, int nprocs, + int myrank, int + buftype_is_contig, int contig_access_count, + ADIO_Offset min_st_offset, + ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + ADIOI_Access *others_req, + int iter, + MPI_Aint buftype_extent, int *buf_idx); +static void ADIOI_R_Exchange_data_alltoallv(ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, ADIO_Offset *offset_list, ADIO_Offset + *len_list, int *send_size, int *recv_size, + int *count, int *start_pos, + int *partial_send, + int *recd_from_proc, int nprocs, + int myrank, int + buftype_is_contig, int contig_access_count, + ADIO_Offset min_st_offset, + ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + ADIOI_Access *others_req, + int iter, + MPI_Aint buftype_extent, int *buf_idx); +static void ADIOI_Fill_user_buffer(ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, char **recv_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, + unsigned *recv_size, + MPI_Request *requests, MPI_Status *statuses, + int *recd_from_proc, int nprocs, + int contig_access_count, + ADIO_Offset min_st_offset, + ADIO_Offset fd_size, ADIO_Offset *fd_start, + ADIO_Offset *fd_end, + MPI_Aint buftype_extent); + +extern void ADIOI_Calc_my_off_len(ADIO_File fd, int bufcount, MPI_Datatype + datatype, int file_ptr_type, ADIO_Offset + offset, ADIO_Offset **offset_list_ptr, ADIO_Offset + **len_list_ptr, ADIO_Offset *start_offset_ptr, + ADIO_Offset *end_offset_ptr, int + *contig_access_count_ptr); + + + +void ADIOI_GPFS_ReadStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ +/* Uses a generalized version of the extended two-phase method described + in "An Extended Two-Phase Method for Accessing Sections of + Out-of-Core Arrays", Rajeev Thakur and Alok Choudhary, + Scientific Programming, (5)4:301--317, Winter 1996. + http://www.mcs.anl.gov/home/thakur/ext2ph.ps */ + + ADIOI_Access *my_req; + /* array of nprocs structures, one for each other process in + whose file domain this process's request lies */ + + ADIOI_Access *others_req; + /* array of nprocs structures, one for each other process + whose request lies in this process's file domain. */ + + int i, filetype_is_contig, nprocs, nprocs_for_coll, myrank; + int contig_access_count=0, interleave_count = 0, buftype_is_contig; + int *count_my_req_per_proc, count_my_req_procs, count_others_req_procs; + ADIO_Offset start_offset, end_offset, orig_fp, fd_size, min_st_offset, off; + ADIO_Offset *offset_list = NULL, *st_offsets = NULL, *fd_start = NULL, + *fd_end = NULL, *end_offsets = NULL; + ADIO_Offset *gpfs_offsets0 = NULL, *gpfs_offsets = NULL; + int ii; + ADIO_Offset *len_list = NULL; + int *buf_idx = NULL; + + GPFSMPIO_T_CIO_RESET( r); + +#ifdef HAVE_STATUS_SET_BYTES + MPI_Count bufsize, size; +#endif + +#if 0 +/* From common code - not implemented for bg. */ + if (fd->hints->cb_pfr != ADIOI_HINT_DISABLE) { + ADIOI_IOStridedColl (fd, buf, count, ADIOI_READ, datatype, + file_ptr_type, offset, status, error_code); + return; + } */ +#endif +#ifdef PROFILE + MPE_Log_event(13, 0, "start computation"); +#endif + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + /* number of aggregators, cb_nodes, is stored in the hints */ + nprocs_for_coll = fd->hints->cb_nodes; + orig_fp = fd->fp_ind; + + GPFSMPIO_T_CIO_SET_GET( r, 1, 0, GPFSMPIO_CIO_T_MPIO_CRW, GPFSMPIO_CIO_LAST) + GPFSMPIO_T_CIO_SET_GET( r, 1, 0, GPFSMPIO_CIO_T_LCOMP, GPFSMPIO_CIO_LAST ) + + /* only check for interleaving if cb_read isn't disabled */ + if (fd->hints->cb_read != ADIOI_HINT_DISABLE) { + /* For this process's request, calculate the list of offsets and + lengths in the file and determine the start and end offsets. */ + + /* Note: end_offset points to the last byte-offset that will be accessed. + e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/ + + ADIOI_Calc_my_off_len(fd, count, datatype, file_ptr_type, offset, + &offset_list, &len_list, &start_offset, + &end_offset, &contig_access_count); + + GPFSMPIO_T_CIO_SET_GET( r, 1, 1, GPFSMPIO_CIO_T_GATHER, GPFSMPIO_CIO_T_LCOMP ) + +#ifdef RDCOLL_DEBUG + for (i=0; icomm ); + + for (ii=0; iicomm); + MPI_Allgather(&end_offset, 1, ADIO_OFFSET, end_offsets, 1, + ADIO_OFFSET, fd->comm); + } + + GPFSMPIO_T_CIO_SET_GET( r, 1, 1, GPFSMPIO_CIO_T_PATANA, GPFSMPIO_CIO_T_GATHER ) + + /* are the accesses of different processes interleaved? */ + for (i=1; ihints->cb_read == ADIOI_HINT_DISABLE + || (!interleave_count && (fd->hints->cb_read == ADIOI_HINT_AUTO))) + { + /* don't do aggregation */ + if (fd->hints->cb_read != ADIOI_HINT_DISABLE) { + ADIOI_Free(offset_list); + ADIOI_Free(len_list); + ADIOI_Free(st_offsets); + ADIOI_Free(end_offsets); + } + + fd->fp_ind = orig_fp; + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + if (buftype_is_contig && filetype_is_contig) { + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + (ADIO_Offset)(fd->etype_size) * offset; + ADIO_ReadContig(fd, buf, count, datatype, ADIO_EXPLICIT_OFFSET, + off, status, error_code); + } + else ADIO_ReadContig(fd, buf, count, datatype, ADIO_INDIVIDUAL, + 0, status, error_code); + } + else ADIO_ReadStrided(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); + + return; + } + + GPFSMPIO_T_CIO_SET_GET( r, 1, 1, GPFSMPIO_CIO_T_FD_PART, GPFSMPIO_CIO_T_PATANA ) + + /* We're going to perform aggregation of I/O. Here we call + * ADIOI_Calc_file_domains() to determine what processes will handle I/O + * to what regions. We pass nprocs_for_coll into this function; it is + * used to determine how many processes will perform I/O, which is also + * the number of regions into which the range of bytes must be divided. + * These regions are called "file domains", or FDs. + * + * When this function returns, fd_start, fd_end, fd_size, and + * min_st_offset will be filled in. fd_start holds the starting byte + * location for each file domain. fd_end holds the ending byte location. + * min_st_offset holds the minimum byte location that will be accessed. + * + * Both fd_start[] and fd_end[] are indexed by an aggregator number; this + * needs to be mapped to an actual rank in the communicator later. + * + */ + if (gpfsmpio_tuneblocking) + ADIOI_GPFS_Calc_file_domains(fd, st_offsets, end_offsets, nprocs, + nprocs_for_coll, &min_st_offset, + &fd_start, &fd_end, &fd_size, fd->fs_ptr); + else + ADIOI_Calc_file_domains(st_offsets, end_offsets, nprocs, + nprocs_for_coll, &min_st_offset, + &fd_start, &fd_end, + fd->hints->min_fdomain_size, &fd_size, + fd->hints->striping_unit); + + GPFSMPIO_T_CIO_SET_GET( r, 1, 1, GPFSMPIO_CIO_T_MYREQ, GPFSMPIO_CIO_T_FD_PART ); + if (gpfsmpio_p2pcontig==1) { + /* For some simple yet common(?) workloads, full-on two-phase I/O is + * overkill. We can establish sub-groups of processes and their + * aggregator, and then these sub-groups will carry out a simplified + * two-phase over that sub-group. + * + * First verify that the filetype is contig and the offsets are + * increasing in rank order*/ + int x, inOrderAndNoGaps = 1; + for (x=0;x<(nprocs-1);x++) { + if (end_offsets[x] != (st_offsets[x+1]-1)) + inOrderAndNoGaps = 0; + } + if (inOrderAndNoGaps && buftype_is_contig) { + /* if these conditions exist then execute the P2PContig code else + * execute the original code */ + ADIOI_P2PContigReadAggregation(fd, buf, + error_code, st_offsets, end_offsets, fd_start, fd_end); + + /* NOTE: we are skipping the rest of two-phase in this path */ + GPFSMPIO_T_CIO_REPORT( 0, fd, myrank, nprocs) + + ADIOI_Free(offset_list); + ADIOI_Free(len_list); + ADIOI_Free(st_offsets); + ADIOI_Free(end_offsets); + ADIOI_Free(fd_start); + ADIOI_Free(fd_end); + goto fn_exit; + + } + } + + /* calculate where the portions of the access requests of this process + * are located in terms of the file domains. this could be on the same + * process or on other processes. this function fills in: + * count_my_req_procs - number of processes (including this one) for which + * this process has requests in their file domain + * count_my_req_per_proc - count of requests for each process, indexed + * by rank of the process + * my_req[] - array of data structures describing the requests to be + * performed by each process (including self). indexed by rank. + * buf_idx[] - array of locations into which data can be directly moved; + * this is only valid for contiguous buffer case + */ + if (gpfsmpio_tuneblocking) + ADIOI_GPFS_Calc_my_req(fd, offset_list, len_list, contig_access_count, + min_st_offset, fd_start, fd_end, fd_size, + nprocs, &count_my_req_procs, + &count_my_req_per_proc, &my_req, + &buf_idx); + else + ADIOI_Calc_my_req(fd, offset_list, len_list, contig_access_count, + min_st_offset, fd_start, fd_end, fd_size, + nprocs, &count_my_req_procs, + &count_my_req_per_proc, &my_req, + &buf_idx); + + GPFSMPIO_T_CIO_SET_GET( r, 1, 1, GPFSMPIO_CIO_T_OTHREQ, GPFSMPIO_CIO_T_MYREQ ) + + /* perform a collective communication in order to distribute the + * data calculated above. fills in the following: + * count_others_req_procs - number of processes (including this + * one) which have requests in this process's file domain. + * count_others_req_per_proc[] - number of separate contiguous + * requests from proc i lie in this process's file domain. + */ + if (gpfsmpio_tuneblocking) + ADIOI_GPFS_Calc_others_req(fd, count_my_req_procs, + count_my_req_per_proc, my_req, + nprocs, myrank, &count_others_req_procs, + &others_req); + + else + ADIOI_Calc_others_req(fd, count_my_req_procs, + count_my_req_per_proc, my_req, + nprocs, myrank, &count_others_req_procs, + &others_req); + + GPFSMPIO_T_CIO_SET_GET( r, 1, 1, GPFSMPIO_CIO_T_DEXCH, GPFSMPIO_CIO_T_OTHREQ ) + + /* my_req[] and count_my_req_per_proc aren't needed at this point, so + * let's free the memory + */ + ADIOI_Free(count_my_req_per_proc); + for (i=0; ifp_sys_posn = -1; /* set it to null. */ +} + +static void ADIOI_Read_and_exch(ADIO_File fd, void *buf, MPI_Datatype + datatype, int nprocs, + int myrank, ADIOI_Access + *others_req, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *buf_idx, int *error_code) +{ +/* Read in sizes of no more than coll_bufsize, an info parameter. + Send data to appropriate processes. + Place recd. data in user buf. + The idea is to reduce the amount of extra memory required for + collective I/O. If all data were read all at once, which is much + easier, it would require temp space more than the size of user_buf, + which is often unacceptable. For example, to read a distributed + array from a file, where each local array is 8Mbytes, requiring + at least another 8Mbytes of temp space is unacceptable. */ + + int i, j, m, ntimes, max_ntimes, buftype_is_contig; + ADIO_Offset st_loc=-1, end_loc=-1, off, done, real_off, req_off; + char *read_buf = NULL, *tmp_buf; + int *curr_offlen_ptr, *count, *send_size, *recv_size; + int *partial_send, *recd_from_proc, *start_pos; + /* Not convinced end_loc-st_loc couldn't be > int, so make these offsets*/ + ADIO_Offset real_size, size, for_curr_iter, for_next_iter; + int req_len, flag, rank; + MPI_Status status; + ADIOI_Flatlist_node *flat_buf=NULL; + MPI_Aint buftype_extent; + int coll_bufsize; +#ifdef RDCOLL_DEBUG + int iii; +#endif + *error_code = MPI_SUCCESS; /* changed below if error */ + /* only I/O errors are currently reported */ + +/* calculate the number of reads of size coll_bufsize + to be done by each process and the max among all processes. + That gives the no. of communication phases as well. + coll_bufsize is obtained from the hints object. */ + + coll_bufsize = fd->hints->cb_buffer_size; + + /* grab some initial values for st_loc and end_loc */ + for (i=0; i < nprocs; i++) { + if (others_req[i].count) { + st_loc = others_req[i].offsets[0]; + end_loc = others_req[i].offsets[0]; + break; + } + } + + /* now find the real values */ + for (i=0; i < nprocs; i++) + for (j=0; jcomm); + + read_buf = fd->io_buf; + + curr_offlen_ptr = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* its use is explained below. calloc initializes to 0. */ + + count = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* to store count of how many off-len pairs per proc are satisfied + in an iteration. */ + + partial_send = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* if only a portion of the last off-len pair is sent to a process + in a particular iteration, the length sent is stored here. + calloc initializes to 0. */ + + send_size = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* total size of data to be sent to each proc. in an iteration */ + + recv_size = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* total size of data to be recd. from each proc. in an iteration. + Of size nprocs so that I can use MPI_Alltoall later. */ + + recd_from_proc = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* amount of data recd. so far from each proc. Used in + ADIOI_Fill_user_buffer. initialized to 0 here. */ + + start_pos = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* used to store the starting value of curr_offlen_ptr[i] in + this iteration */ + + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + if (!buftype_is_contig) { + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + } + MPI_Type_extent(datatype, &buftype_extent); + + done = 0; + off = st_loc; + for_curr_iter = for_next_iter = 0; + + MPI_Comm_rank(fd->comm, &rank); + +#ifdef PROFILE + MPE_Log_event(14, 0, "end computation"); +#endif + + for (m=0; mio_buf); + fd->io_buf = (char *) ADIOI_Malloc(for_next_iter+coll_bufsize); + memcpy(fd->io_buf, tmp_buf, for_next_iter); + read_buf = fd->io_buf; + ADIOI_Free(tmp_buf); + } + + off += size; + done += size; + } + + for (i=0; icomm); + + nprocs_recv = 0; + for (i=0; i < nprocs; i++) if (recv_size[i]) nprocs_recv++; + + nprocs_send = 0; + for (i=0; icomm, requests+j); + j++; + buf_idx[i] += recv_size[i]; + } + } + else { +/* allocate memory for recv_buf and post receives */ + recv_buf = (char **) ADIOI_Malloc(nprocs * sizeof(char*)); + for (i=0; i < nprocs; i++) + if (recv_size[i]) recv_buf[i] = + (char *) ADIOI_Malloc(recv_size[i]); + + j = 0; + for (i=0; i < nprocs; i++) + if (recv_size[i]) { + MPI_Irecv(recv_buf[i], recv_size[i], MPI_BYTE, i, + myrank+i+100*iter, fd->comm, requests+j); + j++; +#ifdef RDCOLL_DEBUG + DBG_FPRINTF(stderr, "node %d, recv_size %d, tag %d \n", + myrank, recv_size[i], myrank+i+100*iter); +#endif + } + } + +/* create derived datatypes and send data */ + + j = 0; + for (i=0; icomm, requests+nprocs_recv+j); + MPI_Type_free(&send_type); + if (partial_send[i]) others_req[i].lens[k] = tmp; + j++; + } + } + + statuses = (MPI_Status *) ADIOI_Malloc((nprocs_send+nprocs_recv+1) * \ + sizeof(MPI_Status)); + /* +1 to avoid a 0-size malloc */ + + /* wait on the receives */ + if (nprocs_recv) { +#ifdef NEEDS_MPI_TEST + j = 0; + while (!j) MPI_Testall(nprocs_recv, requests, &j, statuses); +#else + MPI_Waitall(nprocs_recv, requests, statuses); +#endif + + /* if noncontiguous, to the copies from the recv buffers */ + if (!buftype_is_contig) + ADIOI_Fill_user_buffer(fd, buf, flat_buf, recv_buf, + offset_list, len_list, (unsigned*)recv_size, + requests, statuses, recd_from_proc, + nprocs, contig_access_count, + min_st_offset, fd_size, fd_start, fd_end, + buftype_extent); + } + + /* wait on the sends*/ + MPI_Waitall(nprocs_send, requests+nprocs_recv, statuses+nprocs_recv); + + ADIOI_Free(statuses); + ADIOI_Free(requests); + + if (!buftype_is_contig) { + for (i=0; i < nprocs; i++) + if (recv_size[i]) ADIOI_Free(recv_buf[i]); + ADIOI_Free(recv_buf); + } +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5033, 0, NULL); +#endif +} + +#define ADIOI_BUF_INCR \ +{ \ + while (buf_incr) { \ + size_in_buf = ADIOI_MIN(buf_incr, flat_buf_sz); \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + buf_incr -= size_in_buf; \ + } \ +} + + +#define ADIOI_BUF_COPY \ +{ \ + while (size) { \ + size_in_buf = ADIOI_MIN(size, flat_buf_sz); \ + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + user_buf_idx) == (ADIO_Offset)(MPIR_Upint)(buf + user_buf_idx)); \ + ADIOI_Assert(size_in_buf == (size_t)size_in_buf); \ + memcpy(((char *) buf) + user_buf_idx, \ + &(recv_buf[p][recv_buf_idx[p]]), size_in_buf); \ + recv_buf_idx[p] += size_in_buf; /* already tested (size_t)size_in_buf*/ \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + size -= size_in_buf; \ + buf_incr -= size_in_buf; \ + } \ + ADIOI_BUF_INCR \ +} + +static void ADIOI_Fill_user_buffer(ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, char **recv_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, + unsigned *recv_size, + MPI_Request *requests, MPI_Status *statuses, + int *recd_from_proc, int nprocs, + int contig_access_count, + ADIO_Offset min_st_offset, + ADIO_Offset fd_size, ADIO_Offset *fd_start, + ADIO_Offset *fd_end, + MPI_Aint buftype_extent) +{ + +/* this function is only called if buftype is not contig */ + + int i, p, flat_buf_idx; + ADIO_Offset flat_buf_sz, size_in_buf, buf_incr, size; + int n_buftypes; + ADIO_Offset off, len, rem_len, user_buf_idx; + /* Not sure unsigned is necessary, but it makes the math safer */ + unsigned *curr_from_proc, *done_from_proc, *recv_buf_idx; + + ADIOI_UNREFERENCED_ARG(requests); + ADIOI_UNREFERENCED_ARG(statuses); + +/* curr_from_proc[p] = amount of data recd from proc. p that has already + been accounted for so far + done_from_proc[p] = amount of data already recd from proc. p and + filled into user buffer in previous iterations + user_buf_idx = current location in user buffer + recv_buf_idx[p] = current location in recv_buf of proc. p */ + curr_from_proc = (unsigned *) ADIOI_Malloc(nprocs * sizeof(unsigned)); + done_from_proc = (unsigned *) ADIOI_Malloc(nprocs * sizeof(unsigned)); + recv_buf_idx = (unsigned *) ADIOI_Malloc(nprocs * sizeof(unsigned)); + + for (i=0; i < nprocs; i++) { + recv_buf_idx[i] = curr_from_proc[i] = 0; + done_from_proc[i] = recd_from_proc[i]; + } + + user_buf_idx = flat_buf->indices[0]; + flat_buf_idx = 0; + n_buftypes = 0; + flat_buf_sz = flat_buf->blocklens[0]; + + /* flat_buf_idx = current index into flattened buftype + flat_buf_sz = size of current contiguous component in + flattened buf */ + + for (i=0; i 0) { + len = rem_len; + /* NOTE: len value is modified by ADIOI_Calc_aggregator() to be no + * longer than the single region that processor "p" is responsible + * for. + */ + p = ADIOI_GPFS_Calc_aggregator(fd, + off, + min_st_offset, + &len, + fd_size, + fd_start, + fd_end); + + if (recv_buf_idx[p] < recv_size[p]) { + if (curr_from_proc[p]+len > done_from_proc[p]) { + if (done_from_proc[p] > curr_from_proc[p]) { + size = ADIOI_MIN(curr_from_proc[p] + len - + done_from_proc[p], recv_size[p]-recv_buf_idx[p]); + buf_incr = done_from_proc[p] - curr_from_proc[p]; + ADIOI_BUF_INCR + buf_incr = curr_from_proc[p]+len-done_from_proc[p]; + ADIOI_Assert((done_from_proc[p] + size) == (unsigned)((ADIO_Offset)done_from_proc[p] + size)); + curr_from_proc[p] = done_from_proc[p] + size; + ADIOI_BUF_COPY + } + else { + size = ADIOI_MIN(len,recv_size[p]-recv_buf_idx[p]); + buf_incr = len; + ADIOI_Assert((curr_from_proc[p] + size) == (unsigned)((ADIO_Offset)curr_from_proc[p] + size)); + curr_from_proc[p] += (unsigned) size; + ADIOI_BUF_COPY + } + } + else { + ADIOI_Assert((curr_from_proc[p] + len) == (unsigned)((ADIO_Offset)curr_from_proc[p] + len)); + curr_from_proc[p] += (unsigned) len; + buf_incr = len; + ADIOI_BUF_INCR + } + } + else { + buf_incr = len; + ADIOI_BUF_INCR + } + off += len; + rem_len -= len; + } + } + for (i=0; i < nprocs; i++) + if (recv_size[i]) recd_from_proc[i] = curr_from_proc[i]; + + ADIOI_Free(curr_from_proc); + ADIOI_Free(done_from_proc); + ADIOI_Free(recv_buf_idx); +} + +static void ADIOI_R_Exchange_data_alltoallv( + ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, ADIO_Offset *offset_list, ADIO_Offset + *len_list, int *send_size, int *recv_size, + int *count, int *start_pos, int *partial_send, + int *recd_from_proc, int nprocs, + int myrank, int + buftype_is_contig, int contig_access_count, + ADIO_Offset min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + ADIOI_Access *others_req, + int iter, MPI_Aint buftype_extent, int *buf_idx) +{ + int i, j, k=0, tmp=0, nprocs_recv, nprocs_send; + char **recv_buf = NULL; + MPI_Request *requests=NULL; + MPI_Status *statuses=NULL; + int rtail, stail; + char *sbuf_ptr, *from_ptr; + int len; + int *sdispls, *rdispls; + char *all_recv_buf, *all_send_buf; + + /* exchange send_size info so that each process knows how much to + receive from whom and how much memory to allocate. */ + MPI_Alltoall(send_size, 1, MPI_INT, recv_size, 1, MPI_INT, fd->comm); + + nprocs_recv = 0; + for (i=0; icomm ); + +#if 0 + DBG_FPRINTF(stderr, "\tall_recv_buf = " ); + for (i=131072; i<131073; i++) { DBG_FPRINTF(stderr, "%2d,", all_recv_buf [i] ); } + DBG_FPRINTF(stderr, "\n" ); +#endif + + /* unpack at the receiver side */ + if (nprocs_recv) { + if (!buftype_is_contig) + ADIOI_Fill_user_buffer(fd, buf, flat_buf, recv_buf, + offset_list, len_list, (unsigned*)recv_size, + requests, statuses, /* never used inside */ + recd_from_proc, + nprocs, contig_access_count, + min_st_offset, fd_size, fd_start, fd_end, + buftype_extent); + else { + rtail = 0; + for (i=0; i < nprocs; i++) + if (recv_size[i]) { + memcpy( (char *)buf + buf_idx[i], all_recv_buf + rtail, recv_size[i] ); + buf_idx[i] += recv_size[i]; + rtail += recv_size[i]; + } + } + } + + ADIOI_Free( all_send_buf ); + ADIOI_Free( all_recv_buf ); + ADIOI_Free( recv_buf ); + ADIOI_Free( sdispls ); + ADIOI_Free( rdispls ); + return; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_tuning.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_tuning.c new file mode 100644 index 0000000000..c99302143d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/ad_gpfs_tuning.c @@ -0,0 +1,277 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_gpfs_tuning.c + * \brief Defines ad_gpfs performance tuning + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/*--------------------------------------------------------------------- + * ad_gpfs_tuning.c + * + * defines global variables and functions for performance tuning and + * functional debugging. + *---------------------------------------------------------------------*/ + +#include "ad_gpfs_tuning.h" +#include "mpi.h" + +#if !defined(PVFS2_SUPER_MAGIC) + #define PVFS2_SUPER_MAGIC (0x20030528) +#endif + + +int gpfsmpio_timing; +int gpfsmpio_timing2; +int gpfsmpio_timing_cw_level; +int gpfsmpio_comm; +int gpfsmpio_tunegather; +int gpfsmpio_tuneblocking; +long bglocklessmpio_f_type; +int gpfsmpio_bg_nagg_pset; +int gpfsmpio_pthreadio; +int gpfsmpio_p2pcontig; +int gpfsmpio_balancecontig; +int gpfsmpio_devnullio; +int gpfsmpio_bridgeringagg; + +double gpfsmpio_prof_cw [GPFSMPIO_CIO_LAST+1]; +double gpfsmpio_prof_cr [GPFSMPIO_CIO_LAST+1]; + +/* set internal variables for tuning environment variables */ +/** \page mpiio_vars MPIIO Configuration + \section env_sec Environment Variables + * - GPFSMPIO_COMM - Define how data is exchanged on collective + * reads and writes. Possible values: + * - 0 - Use MPI_Alltoallv. + * - 1 - Use MPI_Isend/MPI_Irecv. + * - Default is 0. + * + * - GPFSMPIO_TIMING - collect timing breakdown for MPI I/O collective calls. + * Possible values: + * - 0 - Do not collect/report timing. + * - 1 - Collect/report timing. + * - Default is 0. + * + * - GPFSMPIO_TUNEGATHER - Tune how starting and ending offsets are communicated + * for aggregator collective i/o. Possible values: + * - 0 - Use two MPI_Allgather's to collect starting and ending offsets. + * - 1 - Use MPI_Allreduce(MPI_MAX) to collect starting and ending offsets. + * - Default is 1. + * + * - GPFSMPIO_TUNEBLOCKING - Tune how aggregate file domains are + * calculated (block size). Possible values: + * - 0 - Evenly calculate file domains across aggregators. Also use + * MPI_Isend/MPI_Irecv to exchange domain information. + * - 1 - Align file domains with the underlying file system's block size. Also use + * MPI_Alltoallv to exchange domain information. + * - Default is 1. + * + * - BGLOCKLESSMPIO_F_TYPE - Specify a filesystem type that should run + * the ad_bglockless driver. NOTE: Using romio prefixes (such as + * "bg:" or "bglockless:") on a file name will override this environment + * variable. Possible values: + * - 0xnnnnnnnn - Any valid file system type (or "magic number") from + * statfs() field f_type. + * - The default is 0x20030528 (PVFS2_SUPER_MAGIC) + * + * - GPFSMPIO_NAGG_PSET - Specify a ratio of "I/O aggregators" to use for each + * compute group (compute nodes + i/o nodes). Possible values: + * - any integer + * - Default is 8 + * + * - GPFSMPIO_PTHREADIO - Enables a very simple form of asyncronous io where a + * pthread is spawned to do the posix writes while the main thread does the + * data aggregation - useful for large files where multiple rounds are + * required (more that the cb_buffer_size of data per aggregator). User + * must ensure there is hw resource available for the thread to run. I + * am sure there is a better way to do this involving comm threads - this is + * just a start. NOTE: For some reason the stats collected when this is + * enabled misses some of the data so the data sizes are off a bit - this is + * a statistical issue only, the data is still accurately written out + * + * - GPFSMPIO_P2PCONTIG - Does simple point-to-point communication between the + * aggregator and the procs that feed it. Performance could be enhanced by a + * one-sided put algorithm. Current implementation allows only 1 round of + * data. Useful/allowed only when: + * 1.) The datatype is contiguous. + * 2.) The offsets are increasing in rank-order. + * 3.) There are no gaps between the offsets. + * 4.) No single rank has a data size which spans multiple file domains. + * + * - GPFSMPIO_BALANCECONTIG - Relevant only to BGQ. File domain blocks are assigned + * to aggregators in a breadth-first fashion relative to the ions - additionally, + * file domains on the aggregators sharing the same bridgeset and ion have contiguous + * offsets. The breadth-first assignment improves performance in the case of + * a relatively small file of size less than the gpfs block size multiplied + * by the number of ions. Files: ad_gpfs_aggrs.c ad_bg_aggrs.c. Possible Values + * - 0 - assign file domain blocks in the traditional manner + * - 1 - if there are variable sized file domain blocks, spread them out + * (balance) across bridge nodes + * + * - GPFSMPIO_DEVNULLIO - do everything *except* write to / read from the file + * system. When experimenting with different two-phase I/O strategies, it's + * helpful to remove the highly variable file system from the experiment. + * - 0 (disabled) or 1 (enabled) + * - Default is 0 + * + * - GPFSMPIO_BRIDGERINGAGG - Relevant only to BGQ. Aggregator placement + * optimization whch forms a 5-d ring around the bridge node starting at + * GPFSMPIO_BRIDGERINGAGG hops away. Experimental performance results + * suggest best value is 1 and only in conjunction with GPFSMPIO_P2PCONTIG + * and GPFSMPIO_BALANCECONTIG. The number of aggregators selected is still + * GPFSMPIO_NAGG_PSET however the bridge node itself is NOT selected. + * + */ + +void ad_gpfs_get_env_vars() { + char *x, *dummy; + + gpfsmpio_comm = 0; + x = getenv( "GPFSMPIO_COMM" ); + if (x) gpfsmpio_comm = atoi(x); + gpfsmpio_timing = 0; + x = getenv( "GPFSMPIO_TIMING" ); + if (x) gpfsmpio_timing = atoi(x); + gpfsmpio_tunegather = 1; + x = getenv( "GPFSMPIO_TUNEGATHER" ); + if (x) gpfsmpio_tunegather = atoi(x); + gpfsmpio_tuneblocking = 1; + x = getenv( "GPFSMPIO_TUNEBLOCKING" ); + if (x) gpfsmpio_tuneblocking = atoi(x); + bglocklessmpio_f_type = PVFS2_SUPER_MAGIC; + x = getenv( "BGLOCKLESSMPIO_F_TYPE" ); + if (x) bglocklessmpio_f_type = strtol(x,&dummy,0); + DBG_FPRINTF(stderr,"BGLOCKLESSMPIO_F_TYPE=%ld/%#lX\n", + bglocklessmpio_f_type,bglocklessmpio_f_type); + /* note: this value will be 'sanity checked' in ADIOI_BG_persInfo_init(), + * when we know a bit more about what "largest possible value" and + * "smallest possible value" should be */ + gpfsmpio_bg_nagg_pset = ADIOI_BG_NAGG_PSET_DFLT; + x = getenv("GPFSMPIO_NAGG_PSET"); + if (x) gpfsmpio_bg_nagg_pset = atoi(x); + + gpfsmpio_pthreadio = 0; + x = getenv( "GPFSMPIO_PTHREADIO" ); + if (x) gpfsmpio_pthreadio = atoi(x); + + gpfsmpio_p2pcontig = 0; + x = getenv( "GPFSMPIO_P2PCONTIG" ); + if (x) gpfsmpio_p2pcontig = atoi(x); + + gpfsmpio_balancecontig = 0; + x = getenv( "GPFSMPIO_BALANCECONTIG" ); + if (x) gpfsmpio_balancecontig = atoi(x); + + gpfsmpio_devnullio = 0; + x = getenv( "GPFSMPIO_DEVNULLIO" ); + if (x) gpfsmpio_devnullio = atoi(x); + + gpfsmpio_bridgeringagg = 0; + x = getenv( "GPFSMPIO_BRIDGERINGAGG" ); + if (x) gpfsmpio_bridgeringagg = atoi(x); +} + +/* report timing breakdown for MPI I/O collective call */ +void ad_gpfs_timing_crw_report( int rw, ADIO_File fd, int myrank, int nprocs ) +{ + int i; + + if (gpfsmpio_timing) { + /* Timing across the whole communicator is a little bit interesting, + * but what is *more* interesting is if we single out the aggregators + * themselves. non-aggregators spend a lot of time in "exchange" not + * exchanging data, but blocked because they are waiting for + * aggregators to finish writing. If we focus on just the aggregator + * processes we will get a more clear picture about the data exchange + * vs. i/o time breakdown */ + + /* if deferred open enabled, we could use the aggregator communicator */ + MPI_Comm agg_comm; + int nr_aggs, agg_rank; + MPI_Comm_split(fd->comm, (fd->is_agg ? 1 : MPI_UNDEFINED), 0, &agg_comm); + if(agg_comm != MPI_COMM_NULL) { + MPI_Comm_size(agg_comm, &nr_aggs); + MPI_Comm_rank(agg_comm, &agg_rank); + } + + double *gpfsmpio_prof_org = gpfsmpio_prof_cr; + if (rw) gpfsmpio_prof_org = gpfsmpio_prof_cw; + + double gpfsmpio_prof_avg[ GPFSMPIO_CIO_LAST ]; + double gpfsmpio_prof_max[ GPFSMPIO_CIO_LAST ]; + + if( agg_comm != MPI_COMM_NULL) { + MPI_Reduce( gpfsmpio_prof_org, gpfsmpio_prof_avg, GPFSMPIO_CIO_LAST, MPI_DOUBLE, MPI_SUM, 0, agg_comm); + MPI_Reduce( gpfsmpio_prof_org, gpfsmpio_prof_max, GPFSMPIO_CIO_LAST, MPI_DOUBLE, MPI_MAX, 0, agg_comm); + } + if (agg_comm != MPI_COMM_NULL && agg_rank == 0) { + + for (i=0; i +#endif + +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif +#ifdef PROFILE +#include "mpe.h" +#endif + +#include + +#ifdef HAVE_GPFS_H +#include +#endif +#ifdef HAVE_GPFS_FCNTL_H +#include +#endif + +#include +/* prototypes of functions used for collective writes only. */ +static void ADIOI_Exch_and_write(ADIO_File fd, const void *buf, MPI_Datatype + datatype, int nprocs, int myrank, ADIOI_Access + *others_req, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *buf_idx, int *error_code); +static void ADIOI_W_Exchange_data(ADIO_File fd, const void *buf, char *write_buf, + ADIOI_Flatlist_node *flat_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, int *send_size, + int *recv_size, ADIO_Offset off, int size, + int *count, int *start_pos, int *partial_recv, + int *sent_to_proc, int nprocs, + int myrank, int + buftype_is_contig, int contig_access_count, + ADIO_Offset min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + ADIOI_Access *others_req, + int *send_buf_idx, int *curr_to_proc, + int *done_to_proc, int *hole, int iter, + MPI_Aint buftype_extent, int *buf_idx, int *error_code); +static void ADIOI_W_Exchange_data_alltoallv( + ADIO_File fd, const void *buf, + char *write_buf, /* 1 */ + ADIOI_Flatlist_node *flat_buf, + ADIO_Offset *offset_list, + ADIO_Offset *len_list, int *send_size, int *recv_size, + ADIO_Offset off, int size, /* 2 */ + int *count, int *start_pos, int *partial_recv, + int *sent_to_proc, int nprocs, int myrank, + int buftype_is_contig, int contig_access_count, + ADIO_Offset min_st_offset, + ADIO_Offset fd_size, + ADIO_Offset *fd_start, + ADIO_Offset *fd_end, + ADIOI_Access *others_req, + int *send_buf_idx, int *curr_to_proc, /* 3 */ + int *done_to_proc, int *hole, /* 4 */ + int iter, MPI_Aint buftype_extent, int *buf_idx, + int *error_code); +static void ADIOI_Fill_send_buffer(ADIO_File fd, const void *buf, ADIOI_Flatlist_node + *flat_buf, char **send_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, int *send_size, + MPI_Request *requests, int *sent_to_proc, + int nprocs, int myrank, + int contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *send_buf_idx, int *curr_to_proc, + int *done_to_proc, int iter, + MPI_Aint buftype_extent); +static void ADIOI_Fill_send_buffer_nosend(ADIO_File fd, const void *buf, ADIOI_Flatlist_node + *flat_buf, char **send_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, int *send_size, + MPI_Request *requests, int *sent_to_proc, + int nprocs, int myrank, + int contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *send_buf_idx, int *curr_to_proc, + int *done_to_proc, int iter, + MPI_Aint buftype_extent); +static void ADIOI_Heap_merge(ADIOI_Access *others_req, int *count, + ADIO_Offset *srt_off, int *srt_len, int *start_pos, + int nprocs, int nprocs_recv, int total_elements); + + +void ADIOI_GPFS_WriteStridedColl(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ +/* Uses a generalized version of the extended two-phase method described + in "An Extended Two-Phase Method for Accessing Sections of + Out-of-Core Arrays", Rajeev Thakur and Alok Choudhary, + Scientific Programming, (5)4:301--317, Winter 1996. + http://www.mcs.anl.gov/home/thakur/ext2ph.ps */ + + ADIOI_Access *my_req; + /* array of nprocs access structures, one for each other process in + whose file domain this process's request lies */ + + ADIOI_Access *others_req; + /* array of nprocs access structures, one for each other process + whose request lies in this process's file domain. */ + + int i, filetype_is_contig, nprocs, nprocs_for_coll, myrank; + int contig_access_count=0, interleave_count = 0, buftype_is_contig; + int *count_my_req_per_proc, count_my_req_procs, count_others_req_procs; + ADIO_Offset orig_fp, start_offset, end_offset, fd_size, min_st_offset, off; + ADIO_Offset *offset_list = NULL, *st_offsets = NULL, *fd_start = NULL, + *fd_end = NULL, *end_offsets = NULL; + ADIO_Offset *gpfs_offsets0 = NULL, *gpfs_offsets = NULL; + int ii; + + int *buf_idx = NULL; + ADIO_Offset *len_list = NULL; + GPFSMPIO_T_CIO_RESET( w ) +#ifdef PROFILE + MPE_Log_event(13, 0, "start computation"); +#endif + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + +/* the number of processes that actually perform I/O, nprocs_for_coll, + * is stored in the hints off the ADIO_File structure + */ + nprocs_for_coll = fd->hints->cb_nodes; + orig_fp = fd->fp_ind; + + GPFSMPIO_T_CIO_SET_GET( w, 1, 0, GPFSMPIO_CIO_T_MPIO_CRW, GPFSMPIO_CIO_LAST) + GPFSMPIO_T_CIO_SET_GET( w, 1, 0, GPFSMPIO_CIO_T_LCOMP, GPFSMPIO_CIO_LAST ) + + + /* only check for interleaving if cb_write isn't disabled */ + if (fd->hints->cb_write != ADIOI_HINT_DISABLE) { + /* For this process's request, calculate the list of offsets and + lengths in the file and determine the start and end offsets. */ + + /* Note: end_offset points to the last byte-offset that will be accessed. + e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/ + + ADIOI_Calc_my_off_len(fd, count, datatype, file_ptr_type, offset, + &offset_list, &len_list, &start_offset, + &end_offset, &contig_access_count); + + GPFSMPIO_T_CIO_SET_GET( w, 1, 1, GPFSMPIO_CIO_T_GATHER, GPFSMPIO_CIO_T_LCOMP ) + + /* each process communicates its start and end offsets to other + processes. The result is an array each of start and end offsets stored + in order of process rank. */ + + st_offsets = (ADIO_Offset *) ADIOI_Malloc(nprocs*sizeof(ADIO_Offset)); + end_offsets = (ADIO_Offset *) ADIOI_Malloc(nprocs*sizeof(ADIO_Offset)); + + if (gpfsmpio_tunegather) { + gpfs_offsets0 = (ADIO_Offset *) ADIOI_Malloc(2*nprocs*sizeof(ADIO_Offset)); + gpfs_offsets = (ADIO_Offset *) ADIOI_Malloc(2*nprocs*sizeof(ADIO_Offset)); + for (ii=0; iicomm ); + + for (ii=0; iicomm); + MPI_Allgather(&end_offset, 1, ADIO_OFFSET, end_offsets, 1, + ADIO_OFFSET, fd->comm); + } + + GPFSMPIO_T_CIO_SET_GET(w, 1, 1, GPFSMPIO_CIO_T_PATANA, GPFSMPIO_CIO_T_GATHER ) + + /* are the accesses of different processes interleaved? */ + for (i=1; ihints->cb_write == ADIOI_HINT_DISABLE || + (!interleave_count && (fd->hints->cb_write == ADIOI_HINT_AUTO))) + { + /* use independent accesses */ + if (fd->hints->cb_write != ADIOI_HINT_DISABLE) { + ADIOI_Free(offset_list); + ADIOI_Free(len_list); + ADIOI_Free(st_offsets); + ADIOI_Free(end_offsets); + } + + fd->fp_ind = orig_fp; + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + if (buftype_is_contig && filetype_is_contig) { + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + (ADIO_Offset)(fd->etype_size) * offset; + ADIO_WriteContig(fd, buf, count, datatype, + ADIO_EXPLICIT_OFFSET, + off, status, error_code); + } + else ADIO_WriteContig(fd, buf, count, datatype, ADIO_INDIVIDUAL, + 0, status, error_code); + } + else ADIO_WriteStrided(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); + + return; + } + + GPFSMPIO_T_CIO_SET_GET( w, 1, 1, GPFSMPIO_CIO_T_FD_PART, GPFSMPIO_CIO_T_PATANA ) + +/* Divide the I/O workload among "nprocs_for_coll" processes. This is + done by (logically) dividing the file into file domains (FDs); each + process may directly access only its own file domain. */ + + if (gpfsmpio_tuneblocking) + ADIOI_GPFS_Calc_file_domains(fd, st_offsets, end_offsets, nprocs, + nprocs_for_coll, &min_st_offset, + &fd_start, &fd_end, &fd_size, fd->fs_ptr); + else + ADIOI_Calc_file_domains(st_offsets, end_offsets, nprocs, + nprocs_for_coll, &min_st_offset, + &fd_start, &fd_end, + fd->hints->min_fdomain_size, &fd_size, + fd->hints->striping_unit); + + GPFSMPIO_T_CIO_SET_GET( w, 1, 1, GPFSMPIO_CIO_T_MYREQ, GPFSMPIO_CIO_T_FD_PART ); + + if (gpfsmpio_p2pcontig==1) { + /* For some simple yet common(?) workloads, full-on two-phase I/O is overkill. We can establish sub-groups of processes and their aggregator, and then these sub-groups will carry out a simplified two-phase over that sub-group. + * + * First verify that the filetype is contig and the offsets are + * increasing in rank order*/ + int i, inOrderAndNoGaps = 1; + for (i=0;i<(nprocs-1);i++) { + if (end_offsets[i] != (st_offsets[i+1]-1)) + inOrderAndNoGaps = 0; + } + if (inOrderAndNoGaps && buftype_is_contig) { + /* if these conditions exist then execute the P2PContig code else + * execute the original code */ + ADIOI_P2PContigWriteAggregation(fd, buf, + error_code, st_offsets, end_offsets, fd_start, fd_end); + /* NOTE: we are skipping the rest of two-phase in this path */ + GPFSMPIO_T_CIO_REPORT( 1, fd, myrank, nprocs) + + ADIOI_Free(offset_list); + ADIOI_Free(len_list); + ADIOI_Free(st_offsets); + ADIOI_Free(end_offsets); + ADIOI_Free(fd_start); + ADIOI_Free(fd_end); + + goto fn_exit; + } + } + +/* calculate what portions of the access requests of this process are + located in what file domains */ + + if (gpfsmpio_tuneblocking) + ADIOI_GPFS_Calc_my_req(fd, offset_list, len_list, contig_access_count, + min_st_offset, fd_start, fd_end, fd_size, + nprocs, &count_my_req_procs, + &count_my_req_per_proc, &my_req, + &buf_idx); + else + ADIOI_Calc_my_req(fd, offset_list, len_list, contig_access_count, + min_st_offset, fd_start, fd_end, fd_size, + nprocs, &count_my_req_procs, + &count_my_req_per_proc, &my_req, + &buf_idx); + + GPFSMPIO_T_CIO_SET_GET( w, 1, 1, GPFSMPIO_CIO_T_OTHREQ, GPFSMPIO_CIO_T_MYREQ ) + +/* based on everyone's my_req, calculate what requests of other + processes lie in this process's file domain. + count_others_req_procs = number of processes whose requests lie in + this process's file domain (including this process itself) + count_others_req_per_proc[i] indicates how many separate contiguous + requests of proc. i lie in this process's file domain. */ + + if (gpfsmpio_tuneblocking) + ADIOI_GPFS_Calc_others_req(fd, count_my_req_procs, + count_my_req_per_proc, my_req, + nprocs, myrank, + &count_others_req_procs, &others_req); + else + ADIOI_Calc_others_req(fd, count_my_req_procs, + count_my_req_per_proc, my_req, + nprocs, myrank, + &count_others_req_procs, &others_req); + + GPFSMPIO_T_CIO_SET_GET( w, 1, 1, GPFSMPIO_CIO_T_DEXCH, GPFSMPIO_CIO_T_OTHREQ ) + + ADIOI_Free(count_my_req_per_proc); + for (i=0; i < nprocs; i++) { + if (my_req[i].count) { + ADIOI_Free(my_req[i].offsets); + ADIOI_Free(my_req[i].lens); + } + } + ADIOI_Free(my_req); + +/* exchange data and write in sizes of no more than coll_bufsize. */ + ADIOI_Exch_and_write(fd, buf, datatype, nprocs, myrank, + others_req, offset_list, + len_list, contig_access_count, min_st_offset, + fd_size, fd_start, fd_end, buf_idx, error_code); + + GPFSMPIO_T_CIO_SET_GET( w, 0, 1, GPFSMPIO_CIO_LAST, GPFSMPIO_CIO_T_DEXCH ) + GPFSMPIO_T_CIO_SET_GET( w, 0, 1, GPFSMPIO_CIO_LAST, GPFSMPIO_CIO_T_MPIO_CRW ) + + GPFSMPIO_T_CIO_REPORT( 1, fd, myrank, nprocs) + +/* free all memory allocated for collective I/O */ + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); + + for (i=0; ifp_sys_posn = -1; /* set it to null. */ +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5013, 0, NULL); +#endif +} + +static void gpfs_wr_access_start(int fd, ADIO_Offset offset, ADIO_Offset length) +{ + int rc=0; +#ifdef HAVE_GPFS_FCNTL_H + struct { + gpfsFcntlHeader_t header; + gpfsAccessRange_t access; + } take_locks; + + take_locks.header.totalLength = sizeof(take_locks); + take_locks.header.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION; + take_locks.header.fcntlReserved = 0; + + take_locks.access.structLen = sizeof(take_locks.access); + take_locks.access.structType = GPFS_ACCESS_RANGE; + take_locks.access.start = offset; + take_locks.access.length = length; + take_locks.access.isWrite = 1; + + rc = gpfs_fcntl(fd, &take_locks); +#endif + ADIOI_Assert(rc == 0); +} + +static void gpfs_wr_access_end(int fd, ADIO_Offset offset, ADIO_Offset length) +{ + int rc=0; +#ifdef HAVE_GPFS_FCNTL_H + struct { + gpfsFcntlHeader_t header; + gpfsFreeRange_t free; + } free_locks; + + + free_locks.header.totalLength = sizeof(free_locks); + free_locks.header.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION; + free_locks.header.fcntlReserved = 0; + + free_locks.free.structLen = sizeof(free_locks.free); + free_locks.free.structType = GPFS_FREE_RANGE; + free_locks.free.start = offset; + free_locks.free.length = length; + + rc = gpfs_fcntl(fd, &free_locks); +#endif + ADIOI_Assert(rc == 0); +} + +#ifdef BGQPLATFORM +/* my_start, my_end: this processes file domain. coudd be -1,-1 for "no i/o" + * fd_start, fd_end: arrays of length fd->hints->cb_nodes specifying all file domains */ +static int gpfs_find_access_for_ion(ADIO_File fd, + ADIO_Offset my_start, ADIO_Offset my_end, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + ADIO_Offset *start, ADIO_Offset *end) +{ + int my_ionode = MPIX_IO_node_id(); + int *rank_to_ionode; + int i, nprocs, rank; + ADIO_Offset group_start=LLONG_MAX, group_end=0; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &rank); + + rank_to_ionode = ADIOI_Calloc(nprocs, sizeof(int)); + MPI_Allgather(&my_ionode, 1, MPI_INT, rank_to_ionode, 1, MPI_INT, fd->comm); + + /* rank_to_ionode now contains a mapping from MPI rank to IO node */ + /* fd->hints->ranklist[] contains a list of MPI ranks that are aggregators */ + /* fd_start[] and fd_end[] contain a list of file domains. */ + + /* what we really want to do is take all the file domains associated + * with a given i/o node and find the begin/end of that range. + * + * Because gpfs_fcntl hints are expected to be released, we'll pass this + * start/end back to the caller, who will both declare and free this range + */ + if (my_start == -1 || my_end == -1) { + ADIOI_Free(rank_to_ionode); + return 0; /* no work to do */ + } + + for (i=0; ihints->cb_nodes; i++ ){ + if (my_ionode == rank_to_ionode[fd->hints->ranklist[i]] ) { + group_start = ADIOI_MIN(fd_start[i], group_start); + group_end = ADIOI_MAX(fd_end[i], group_end); + } + } + *start = group_start; + *end = group_end; + ADIOI_Free(rank_to_ionode); + return 1; +} +#endif // BGQPLATFORM + + +/* If successful, error_code is set to MPI_SUCCESS. Otherwise an error + * code is created and returned in error_code. + */ +static void ADIOI_Exch_and_write(ADIO_File fd, const void *buf, MPI_Datatype + datatype, int nprocs, + int myrank, + ADIOI_Access + *others_req, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, + ADIO_Offset min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *buf_idx, int *error_code) +{ +/* Send data to appropriate processes and write in sizes of no more + than coll_bufsize. + The idea is to reduce the amount of extra memory required for + collective I/O. If all data were written all at once, which is much + easier, it would require temp space more than the size of user_buf, + which is often unacceptable. For example, to write a distributed + array to a file, where each local array is 8Mbytes, requiring + at least another 8Mbytes of temp space is unacceptable. */ + + /* Not convinced end_loc-st_loc couldn't be > int, so make these offsets*/ + ADIO_Offset size=0; + int hole, i, j, m, ntimes, max_ntimes, buftype_is_contig; + ADIO_Offset st_loc=-1, end_loc=-1, off, done, req_off; + char *write_buf=NULL, *write_buf2=NULL; + int *curr_offlen_ptr, *count, *send_size, req_len, *recv_size; + int *partial_recv, *sent_to_proc, *start_pos, flag; + int *send_buf_idx, *curr_to_proc, *done_to_proc; + MPI_Status status; + ADIOI_Flatlist_node *flat_buf=NULL; + MPI_Aint buftype_extent; + int info_flag, coll_bufsize; + char *value; + static char myname[] = "ADIOI_EXCH_AND_WRITE"; + pthread_t io_thread; + void *thread_ret; + ADIOI_IO_ThreadFuncData io_thread_args; + + *error_code = MPI_SUCCESS; /* changed below if error */ + /* only I/O errors are currently reported */ + +/* calculate the number of writes of size coll_bufsize + to be done by each process and the max among all processes. + That gives the no. of communication phases as well. */ + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + ADIOI_Info_get(fd->info, "cb_buffer_size", MPI_MAX_INFO_VAL, value, + &info_flag); + coll_bufsize = atoi(value); + ADIOI_Free(value); + + if (gpfsmpio_pthreadio == 1){ + /* ROMIO will spawn an additional thread. both threads use separate + * halves of the collective buffer*/ + coll_bufsize = coll_bufsize/2; + } + + for (i=0; i < nprocs; i++) { + if (others_req[i].count) { + st_loc = others_req[i].offsets[0]; + end_loc = others_req[i].offsets[0]; + break; + } + } + + for (i=0; i < nprocs; i++) + for (j=0; j < others_req[i].count; j++) { + st_loc = ADIOI_MIN(st_loc, others_req[i].offsets[j]); + end_loc = ADIOI_MAX(end_loc, (others_req[i].offsets[j] + + others_req[i].lens[j] - 1)); + } + +/* ntimes=ceiling_div(end_loc - st_loc + 1, coll_bufsize)*/ + + ntimes = (int) ((end_loc - st_loc + coll_bufsize)/coll_bufsize); + + if ((st_loc==-1) && (end_loc==-1)) { + ntimes = 0; /* this process does no writing. */ + } + if (ntimes > 0) { /* only set the gpfs hint if we have io - ie this rank is + an aggregator -- otherwise will fail for deferred open */ + if (getenv("ROMIO_GPFS_DECLARE_ACCESS")!=NULL) { + gpfs_wr_access_start(fd->fd_sys, st_loc, end_loc - st_loc); + } + } + + ADIO_Offset st_loc_ion=0, end_loc_ion=0, needs_gpfs_access_cleanup=0; +#ifdef BGQPLATFORM + if (ntimes > 0) { /* only set the gpfs hint if we have io - ie this rank is + an aggregator -- otherwise will fail for deferred open */ + + if (getenv("ROMIO_GPFS_DECLARE_ION_ACCESS")!=NULL) { + if (gpfs_find_access_for_ion(fd, st_loc, end_loc, fd_start, fd_end, + &st_loc_ion, &end_loc_ion)) { + gpfs_wr_access_start(fd->fd_sys, st_loc_ion, end_loc_ion-st_loc_ion); + needs_gpfs_access_cleanup=1; + } + } + } +#endif + + MPI_Allreduce(&ntimes, &max_ntimes, 1, MPI_INT, MPI_MAX, + fd->comm); + + write_buf = fd->io_buf; + if (gpfsmpio_pthreadio == 1) { + write_buf2 = fd->io_buf + coll_bufsize; + } + + curr_offlen_ptr = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* its use is explained below. calloc initializes to 0. */ + + count = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* to store count of how many off-len pairs per proc are satisfied + in an iteration. */ + + partial_recv = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* if only a portion of the last off-len pair is recd. from a process + in a particular iteration, the length recd. is stored here. + calloc initializes to 0. */ + + send_size = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* total size of data to be sent to each proc. in an iteration. + Of size nprocs so that I can use MPI_Alltoall later. */ + + recv_size = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* total size of data to be recd. from each proc. in an iteration.*/ + + sent_to_proc = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* amount of data sent to each proc so far. Used in + ADIOI_Fill_send_buffer. initialized to 0 here. */ + + send_buf_idx = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + curr_to_proc = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + done_to_proc = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* Above three are used in ADIOI_Fill_send_buffer*/ + + start_pos = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* used to store the starting value of curr_offlen_ptr[i] in + this iteration */ + + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + if (!buftype_is_contig) { + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + } + MPI_Type_extent(datatype, &buftype_extent); + + +/* I need to check if there are any outstanding nonblocking writes to + the file, which could potentially interfere with the writes taking + place in this collective write call. Since this is not likely to be + common, let me do the simplest thing possible here: Each process + completes all pending nonblocking operations before completing. */ + + /*ADIOI_Complete_async(error_code); + if (*error_code != MPI_SUCCESS) return; + MPI_Barrier(fd->comm); + */ + + done = 0; + off = st_loc; + + if(gpfsmpio_pthreadio == 1) + io_thread = pthread_self(); + +#ifdef PROFILE + MPE_Log_event(14, 0, "end computation"); +#endif + + for (m=0; m < ntimes; m++) { + /* go through all others_req and check which will be satisfied + by the current write */ + + /* Note that MPI guarantees that displacements in filetypes are in + monotonically nondecreasing order and that, for writes, the + filetypes cannot specify overlapping regions in the file. This + simplifies implementation a bit compared to reads. */ + + /* off = start offset in the file for the data to be written in + this iteration + size = size of data written (bytes) corresponding to off + req_off = off in file for a particular contiguous request + minus what was satisfied in previous iteration + req_size = size corresponding to req_off */ + + /* first calculate what should be communicated */ + +#ifdef PROFILE + MPE_Log_event(13, 0, "start computation"); +#endif + for (i=0; i < nprocs; i++) count[i] = recv_size[i] = 0; + + size = ADIOI_MIN((unsigned)coll_bufsize, end_loc-st_loc+1-done); + + for (i=0; i < nprocs; i++) { + if (others_req[i].count) { + start_pos[i] = curr_offlen_ptr[i]; + for (j=curr_offlen_ptr[i]; jfd_sys, st_loc, end_loc-st_loc); + } + + if (needs_gpfs_access_cleanup) { + gpfs_wr_access_end(fd->fd_sys, st_loc_ion, end_loc_ion-st_loc_ion); + needs_gpfs_access_cleanup=0; + } + + unsetenv("LIBIOLOG_EXTRA_INFO"); +} + + +/* Sets error_code to MPI_SUCCESS if successful, or creates an error code + * in the case of error. + */ +static void ADIOI_W_Exchange_data(ADIO_File fd, const void *buf, char *write_buf, + ADIOI_Flatlist_node *flat_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, int *send_size, + int *recv_size, ADIO_Offset off, int size, + int *count, int *start_pos, + int *partial_recv, + int *sent_to_proc, int nprocs, + int myrank, int + buftype_is_contig, int contig_access_count, + ADIO_Offset min_st_offset, + ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + ADIOI_Access *others_req, + int *send_buf_idx, int *curr_to_proc, + int *done_to_proc, int *hole, int iter, + MPI_Aint buftype_extent, int *buf_idx, + int *error_code) +{ + int i, j, k, *tmp_len, nprocs_recv, nprocs_send, err; + char **send_buf = NULL; + MPI_Request *requests, *send_req; + MPI_Datatype *recv_types; + MPI_Status *statuses, status; + int *srt_len, sum; + ADIO_Offset *srt_off; + static char myname[] = "ADIOI_W_EXCHANGE_DATA"; + +/* exchange recv_size info so that each process knows how much to + send to whom. */ + + MPI_Alltoall(recv_size, 1, MPI_INT, send_size, 1, MPI_INT, fd->comm); + + /* create derived datatypes for recv */ + + nprocs_recv = 0; + for (i=0; i srt_len[0]) srt_len[0] = new_len; + } + else + break; + } + if (i < sum || size != srt_len[0]) /* hole in middle or end */ + *hole = 1; + } + + ADIOI_Free(srt_off); + ADIOI_Free(srt_len); + + if (nprocs_recv) { + if (*hole) { + const char * stuff = "data-sieve-in-two-phase"; + setenv("LIBIOLOG_EXTRA_INFO", stuff, 1); + ADIO_ReadContig(fd, write_buf, size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, off, &status, &err); + /* --BEGIN ERROR HANDLING-- */ + if (err != MPI_SUCCESS) { + *error_code = MPIO_Err_create_code(err, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, + "**ioRMWrdwr", 0); + return; + } + /* --END ERROR HANDLING-- */ + unsetenv("LIBIOLOG_EXTRA_INFO"); + } + } + + nprocs_send = 0; + for (i=0; i < nprocs; i++) if (send_size[i]) nprocs_send++; + + if (fd->atomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + requests = (MPI_Request *) + ADIOI_Malloc((nprocs_send+1)*sizeof(MPI_Request)); + send_req = requests; + } + else { + requests = (MPI_Request *) + ADIOI_Malloc((nprocs_send+nprocs_recv+1)*sizeof(MPI_Request)); + /* +1 to avoid a 0-size malloc */ + + /* post receives */ + j = 0; + for (i=0; icomm, requests+j); + j++; + } + } + send_req = requests + nprocs_recv; + } + +/* post sends. if buftype_is_contig, data can be directly sent from + user buf at location given by buf_idx. else use send_buf. */ + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5032, 0, NULL); +#endif + if (buftype_is_contig) { + j = 0; + for (i=0; i < nprocs; i++) + if (send_size[i]) { + MPI_Isend(((char *) buf) + buf_idx[i], send_size[i], + MPI_BYTE, i, myrank+i+100*iter, fd->comm, + send_req+j); + j++; + buf_idx[i] += send_size[i]; + } + } + else if (nprocs_send) { + /* buftype is not contig */ + send_buf = (char **) ADIOI_Malloc(nprocs*sizeof(char*)); + for (i=0; i < nprocs; i++) + if (send_size[i]) + send_buf[i] = (char *) ADIOI_Malloc(send_size[i]); + + ADIOI_Fill_send_buffer(fd, buf, flat_buf, send_buf, + offset_list, len_list, send_size, + send_req, + sent_to_proc, nprocs, myrank, + contig_access_count, + min_st_offset, fd_size, fd_start, fd_end, + send_buf_idx, curr_to_proc, done_to_proc, iter, + buftype_extent); + /* the send is done in ADIOI_Fill_send_buffer */ + } + + if (fd->atomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + j = 0; + for (i=0; icomm, &wkl_status); + j++; + } + } + } + + for (i=0; iatomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + statuses = (MPI_Status *) ADIOI_Malloc((nprocs_send+1) * \ + sizeof(MPI_Status)); + /* +1 to avoid a 0-size malloc */ + } + else { + statuses = (MPI_Status *) ADIOI_Malloc((nprocs_send+nprocs_recv+1) * \ + sizeof(MPI_Status)); + /* +1 to avoid a 0-size malloc */ + } + +#ifdef NEEDS_MPI_TEST + i = 0; + if (fd->atomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + while (!i) MPI_Testall(nprocs_send, send_req, &i, statuses); + } + else { + while (!i) MPI_Testall(nprocs_send+nprocs_recv, requests, &i, statuses); + } +#else + if (fd->atomicity) + /* bug fix from Wei-keng Liao and Kenin Coloma */ + MPI_Waitall(nprocs_send, send_req, statuses); + else + MPI_Waitall(nprocs_send+nprocs_recv, requests, statuses); +#endif + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5033, 0, NULL); +#endif + ADIOI_Free(statuses); + ADIOI_Free(requests); + if (!buftype_is_contig && nprocs_send) { + for (i=0; i < nprocs; i++) + if (send_size[i]) ADIOI_Free(send_buf[i]); + ADIOI_Free(send_buf); + } +} + + +#define ADIOI_BUF_INCR \ +{ \ + while (buf_incr) { \ + size_in_buf = ADIOI_MIN(buf_incr, flat_buf_sz); \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + buf_incr -= size_in_buf; \ + } \ +} + + +#define ADIOI_BUF_COPY \ +{ \ + while (size) { \ + size_in_buf = ADIOI_MIN(size, flat_buf_sz); \ + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + user_buf_idx) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + user_buf_idx)); \ + ADIOI_Assert(size_in_buf == (size_t)size_in_buf); \ + memcpy(&(send_buf[p][send_buf_idx[p]]), \ + ((char *) buf) + user_buf_idx, size_in_buf); \ + send_buf_idx[p] += size_in_buf; \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + size -= size_in_buf; \ + buf_incr -= size_in_buf; \ + } \ + ADIOI_BUF_INCR \ +} + +static void ADIOI_Fill_send_buffer(ADIO_File fd, const void *buf, ADIOI_Flatlist_node + *flat_buf, char **send_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, int *send_size, + MPI_Request *requests, int *sent_to_proc, + int nprocs, int myrank, + int contig_access_count, + ADIO_Offset min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *send_buf_idx, int *curr_to_proc, + int *done_to_proc, int iter, + MPI_Aint buftype_extent) +{ +/* this function is only called if buftype is not contig */ + + int i, p, flat_buf_idx; + ADIO_Offset flat_buf_sz, size_in_buf, buf_incr, size; + int jj, n_buftypes; + ADIO_Offset off, len, rem_len, user_buf_idx; + +/* curr_to_proc[p] = amount of data sent to proc. p that has already + been accounted for so far + done_to_proc[p] = amount of data already sent to proc. p in + previous iterations + user_buf_idx = current location in user buffer + send_buf_idx[p] = current location in send_buf of proc. p */ + + for (i=0; i < nprocs; i++) { + send_buf_idx[i] = curr_to_proc[i] = 0; + done_to_proc[i] = sent_to_proc[i]; + } + jj = 0; + + user_buf_idx = flat_buf->indices[0]; + flat_buf_idx = 0; + n_buftypes = 0; + flat_buf_sz = flat_buf->blocklens[0]; + + /* flat_buf_idx = current index into flattened buftype + flat_buf_sz = size of current contiguous component in + flattened buf */ + + for (i=0; i done_to_proc[p]) { + if (done_to_proc[p] > curr_to_proc[p]) { + size = ADIOI_MIN(curr_to_proc[p] + len - + done_to_proc[p], send_size[p]-send_buf_idx[p]); + buf_incr = done_to_proc[p] - curr_to_proc[p]; + ADIOI_BUF_INCR + ADIOI_Assert((curr_to_proc[p] + len - done_to_proc[p]) == (unsigned)(curr_to_proc[p] + len - done_to_proc[p])); + buf_incr = curr_to_proc[p] + len - done_to_proc[p]; + ADIOI_Assert((done_to_proc[p] + size) == (unsigned)(done_to_proc[p] + size)); + curr_to_proc[p] = done_to_proc[p] + size; + ADIOI_BUF_COPY + } + else { + size = ADIOI_MIN(len,send_size[p]-send_buf_idx[p]); + buf_incr = len; + ADIOI_Assert((curr_to_proc[p] + size) == (unsigned)((ADIO_Offset)curr_to_proc[p] + size)); + curr_to_proc[p] += size; + ADIOI_BUF_COPY + } + if (send_buf_idx[p] == send_size[p]) { + MPI_Isend(send_buf[p], send_size[p], MPI_BYTE, p, + myrank+p+100*iter, fd->comm, requests+jj); + jj++; + } + } + else { + ADIOI_Assert((curr_to_proc[p] + len) == (unsigned)((ADIO_Offset)curr_to_proc[p] + len)); + curr_to_proc[p] += len; + buf_incr = len; + ADIOI_BUF_INCR + } + } + else { + buf_incr = len; + ADIOI_BUF_INCR + } + off += len; + rem_len -= len; + } + } + for (i=0; i < nprocs; i++) + if (send_size[i]) sent_to_proc[i] = curr_to_proc[i]; +} + + + +static void ADIOI_Heap_merge(ADIOI_Access *others_req, int *count, + ADIO_Offset *srt_off, int *srt_len, int *start_pos, + int nprocs, int nprocs_recv, int total_elements) +{ + typedef struct { + ADIO_Offset *off_list; + ADIO_Offset *len_list; + int nelem; + } heap_struct; + + heap_struct *a, tmp; + int i, j, heapsize, l, r, k, smallest; + + a = (heap_struct *) ADIOI_Malloc((nprocs_recv+1)*sizeof(heap_struct)); + + j = 0; + for (i=0; i=0; i--) { + /* Heapify(a, i, heapsize); Algorithm from Cormen et al. pg. 143 + modified for a heap with smallest element at root. I have + removed the recursion so that there are no function calls. + Function calls are too expensive. */ + k = i; + while (1) { + l = 2*(k+1) - 1; + r = 2*(k+1); + + if ((l < heapsize) && + (*(a[l].off_list) < *(a[k].off_list))) + smallest = l; + else smallest = k; + + if ((r < heapsize) && + (*(a[r].off_list) < *(a[smallest].off_list))) + smallest = r; + + if (smallest != k) { + tmp.off_list = a[k].off_list; + tmp.len_list = a[k].len_list; + tmp.nelem = a[k].nelem; + + a[k].off_list = a[smallest].off_list; + a[k].len_list = a[smallest].len_list; + a[k].nelem = a[smallest].nelem; + + a[smallest].off_list = tmp.off_list; + a[smallest].len_list = tmp.len_list; + a[smallest].nelem = tmp.nelem; + + k = smallest; + } + else break; + } + } + + for (i=0; icomm); + + gpfsmpio_prof_cw[GPFSMPIO_CIO_T_DEXCH_RECV_EXCH] += MPI_Wtime() - io_time; + io_time = MPI_Wtime(); + + nprocs_recv = 0; + for (i=0; icomm ); + + ADIOI_Free( all_send_buf ); + ADIOI_Free(sdispls); + + gpfsmpio_prof_cw[GPFSMPIO_CIO_T_DEXCH_NET] += MPI_Wtime() - io_time; + io_time = MPI_Wtime(); + /* data sieving pre-read */ + /* To avoid a read-modify-write, check if there are holes in the + data to be written. For this, merge the (sorted) offset lists + others_req using a heap-merge. */ + + sum = 0; + for (i=0; i off) || + ((srt_off[sum-1] + srt_len[sum-1]) < (off + size))) + { + *hole = 1; + } + else /* See if there are holes between the requests, if there are more than one */ + for (i=0; iindices[0]; + flat_buf_idx = 0; + n_buftypes = 0; + flat_buf_sz = flat_buf->blocklens[0]; + + /* flat_buf_idx = current index into flattened buftype + flat_buf_sz = size of current contiguous component in + flattened buf */ + + for (i=0; i done_to_proc[p]) { + if (done_to_proc[p] > curr_to_proc[p]) { + size = ADIOI_MIN(curr_to_proc[p] + len - + done_to_proc[p], send_size[p]-send_buf_idx[p]); + buf_incr = done_to_proc[p] - curr_to_proc[p]; + ADIOI_BUF_INCR + ADIOI_Assert((curr_to_proc[p] + len - done_to_proc[p]) == (unsigned)(curr_to_proc[p] + len - done_to_proc[p])); + buf_incr = curr_to_proc[p] + len - done_to_proc[p]; + ADIOI_Assert((done_to_proc[p] + size) == (unsigned)(done_to_proc[p] + size)); + curr_to_proc[p] = done_to_proc[p] + size; + ADIOI_BUF_COPY + } + else { + size = ADIOI_MIN(len,send_size[p]-send_buf_idx[p]); + buf_incr = len; + ADIOI_Assert((curr_to_proc[p] + size) == (unsigned)((ADIO_Offset)curr_to_proc[p] + size)); + curr_to_proc[p] += size; + ADIOI_BUF_COPY + } + /* moved to alltoallv */ + /* + if (send_buf_idx[p] == send_size[p]) { + MPI_Isend(send_buf[p], send_size[p], MPI_BYTE, p, + myrank+p+100*iter, fd->comm, requests+jj); + jj++; + } + */ + } + else { + ADIOI_Assert((curr_to_proc[p] + len) == (unsigned)((ADIO_Offset)curr_to_proc[p] + len)); + curr_to_proc[p] += (int)len; + buf_incr = len; + ADIOI_BUF_INCR + } + } + else { + buf_incr = len; + ADIOI_BUF_INCR + } + off += len; + rem_len -= len; + } + } + for (i=0; i < nprocs; i++) + if (send_size[i]) sent_to_proc[i] = curr_to_proc[i]; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/Makefile.mk new file mode 100644 index 0000000000..1d957ef8f6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/Makefile.mk @@ -0,0 +1,18 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2012 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_BG + +noinst_HEADERS += \ + adio/ad_gpfs/bg/ad_bg_aggrs.h \ + adio/ad_gpfs/bg/ad_bg_pset.h + +romio_other_sources += \ + adio/ad_gpfs/bg/ad_bg_aggrs.c \ + adio/ad_gpfs/bg/ad_bg_pset.c + +endif BUILD_AD_BG diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_aggrs.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_aggrs.c new file mode 100644 index 0000000000..240c0138df --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_aggrs.c @@ -0,0 +1,675 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_bg_aggrs.c + * \brief The externally used function from this file is is declared in ad_bg_aggrs.h + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 1997-2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/*#define TRACE_ON */ + +// Uncomment this line to turn tracing on for the gpfsmpio_balancecontig aggr selection optimization +// #define balancecontigtrace 1 +// #define bridgeringaggtrace 1 + +#include "adio.h" +#include "adio_cb_config_list.h" +#include "../ad_gpfs.h" +#include "ad_bg_pset.h" +#include "ad_bg_aggrs.h" +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + + +#ifdef USE_DBG_LOGGING + #define AGG_DEBUG 1 +#endif + +#ifndef TRACE_ERR +# define TRACE_ERR(format...) +#endif + +/* Comments copied from common: + * This file contains four functions: + * + * ADIOI_Calc_aggregator() + * ADIOI_Calc_file_domains() + * ADIOI_Calc_my_req() + * ADIOI_Calc_others_req() + * + * The last three of these were originally in ad_read_coll.c, but they are + * also shared with ad_write_coll.c. I felt that they were better kept with + * the rest of the shared aggregation code. + */ + +/* Discussion of values available from above: + * + * ADIO_Offset st_offsets[0..nprocs-1] + * ADIO_Offset end_offsets[0..nprocs-1] + * These contain a list of start and end offsets for each process in + * the communicator. For example, an access at loc 10, size 10 would + * have a start offset of 10 and end offset of 19. + * int nprocs + * number of processors in the collective I/O communicator + * ADIO_Offset min_st_offset + * ADIO_Offset fd_start[0..nprocs_for_coll-1] + * starting location of "file domain"; region that a given process will + * perform aggregation for (i.e. actually do I/O) + * ADIO_Offset fd_end[0..nprocs_for_coll-1] + * start + size - 1 roughly, but it can be less, or 0, in the case of + * uneven distributions + */ + +/* forward declaration */ +static void +ADIOI_BG_compute_agg_ranklist_serial ( ADIO_File fd, + const ADIOI_BG_ConfInfo_t *confInfo, + ADIOI_BG_ProcInfo_t *all_procInfo); + +/* + * Compute the aggregator-related parameters that are required in 2-phase collective IO of ADIO. + * The parameters are + * . the number of aggregators (proxies) : fd->hints->cb_nodes + * . the ranks of the aggregators : fd->hints->ranklist + * By compute these two parameters in a BG-PSET-aware way, the default 2-phase collective IO of + * ADIO can work more efficiently. + */ +int +ADIOI_BG_gen_agg_ranklist(ADIO_File fd, int n_aggrs_per_pset) +{ + int r, s; + ADIOI_BG_ProcInfo_t *procInfo, *all_procInfo; + ADIOI_BG_ConfInfo_t *confInfo; + TRACE_ERR("Entering ADIOI_BG_gen_agg_ranklist\n"); + + MPI_Comm_size( fd->comm, &s ); + MPI_Comm_rank( fd->comm, &r ); + + /* Collect individual BG personality information */ + confInfo = ADIOI_BG_ConfInfo_new (); + procInfo = ADIOI_BG_ProcInfo_new (); + ADIOI_BG_persInfo_init( confInfo, procInfo, s, r, n_aggrs_per_pset, fd->comm); + + /* Gather BG personality infomation onto process 0 */ + /* if (r == 0) */ + all_procInfo = ADIOI_BG_ProcInfo_new_n (s); + + MPI_Gather( (void *)procInfo, sizeof(ADIOI_BG_ProcInfo_t), MPI_BYTE, + (void *)all_procInfo, sizeof(ADIOI_BG_ProcInfo_t), MPI_BYTE, + 0, + fd->comm ); + + /* Compute a list of the ranks of chosen IO proxy CN on process 0 */ + if (r == 0) { + ADIOI_BG_compute_agg_ranklist_serial (fd, confInfo, all_procInfo); + /* ADIOI_BG_ProcInfo_free (all_procInfo);*/ + } + ADIOI_BG_ProcInfo_free (all_procInfo); + + /* Send the info of IO proxy CN to all processes and keep the info in fd->hints struct. + Declared in adio_cb_config_list.h */ + ADIOI_cb_bcast_rank_map(fd); + if (gpfsmpio_balancecontig == 1) { /* additionally need to send bridgelist, + bridgelistnum and numbridges to all + ranks */ + if (r != 0) { + fd->hints->fs_hints.bg.bridgelist = + ADIOI_Malloc(fd->hints->cb_nodes*sizeof(int)); + if (fd->hints->fs_hints.bg.bridgelist == NULL) { + /* NEED TO HANDLE ENOMEM */ + } + } + MPI_Bcast(fd->hints->fs_hints.bg.bridgelist, fd->hints->cb_nodes, MPI_INT, 0, + fd->comm); + + if (r != 0) { + fd->hints->fs_hints.bg.bridgelistnum = + ADIOI_Malloc(fd->hints->cb_nodes*sizeof(int)); + if (fd->hints->fs_hints.bg.bridgelistnum == NULL) { + /* NEED TO HANDLE ENOMEM */ + } + } + MPI_Bcast(fd->hints->fs_hints.bg.bridgelistnum, fd->hints->cb_nodes, + MPI_INT, 0, fd->comm); + + MPI_Bcast(&fd->hints->fs_hints.bg.numbridges, 1, MPI_INT, 0, + fd->comm); + + } + + + ADIOI_BG_persInfo_free( confInfo, procInfo ); + TRACE_ERR("Leaving ADIOI_BG_gen_agg_ranklist\n"); + return 0; +} + + +/* There are some number of bridge nodes (randomly) distributed through the job + * We need to split the nodes among the bridge nodes */ +/* Maybe find which bridge node is closer (manhattan distance) and try to + * distribute evenly. + */ +/* + * Pick IO aggregators based on the under PSET organization and stores the ranks of the proxy CNs in tmp_ranklist. + * The first order of tmp_ranklist is : PSET number + * The secondary order of the list is determined in ADIOI_BG_select_agg_in_pset() and thus adjustable. + */ +typedef struct +{ + int rank; + int bridge; +} sortstruct; + +typedef struct +{ + int bridgeRank; + int numAggsAssigned; +} bridgeAggAssignment; + +static int intsort(const void *p1, const void *p2) +{ + sortstruct *i1, *i2; + i1 = (sortstruct *)p1; + i2 = (sortstruct *)p2; + return(i1->bridge - i2->bridge); +} + +static int +ADIOI_BG_compute_agg_ranklist_serial_do (const ADIOI_BG_ConfInfo_t *confInfo, + ADIOI_BG_ProcInfo_t *all_procInfo, + int *tmp_ranklist) +{ + TRACE_ERR("Entering ADIOI_BG_compute_agg_ranklist_serial_do\n"); + /* BES: This should be done in the init routines probably. */ + int i, j; + int aggTotal; + int *aggList; + + if (gpfsmpio_bridgeringagg > 0) { + + int numAggs = confInfo->aggRatio * confInfo->ioMinSize /*virtualPsetSize*/; + /* the number of aggregators is (numAggs per bridgenode) */ + if(numAggs == 1) + aggTotal = 1; + else + aggTotal = confInfo->numBridgeRanks * numAggs; + + aggList = (int *)ADIOI_Malloc(aggTotal * sizeof(int)); + if(aggTotal == 1) { /* special case when we only have one bridge node */ + + sortstruct *bridgelist = (sortstruct *)ADIOI_Malloc(confInfo->nProcs * sizeof(sortstruct)); + for(i=0; i < confInfo->nProcs; i++) + { + bridgelist[i].bridge = all_procInfo[i].bridgeRank; + bridgelist[i].rank = i; + TRACE_ERR("bridgelist[%d].bridge: %d .rank: %d\n", i, bridgelist[i].bridge, i); + } + + /* This list contains rank->bridge info. Now, we need to sort this list. */ + qsort(bridgelist, confInfo->nProcs, sizeof(sortstruct), intsort); + + aggList[0] = bridgelist[0].bridge; + ADIOI_Free(bridgelist); + + } + else { // aggTotal > 1 + + int currentAggListSize = 0; + int numBridgesWithAggAssignments = 0; + bridgeAggAssignment *aggAssignments = (bridgeAggAssignment *)ADIOI_Malloc(confInfo->numBridgeRanks * sizeof(bridgeAggAssignment)); + + int partitionSize = all_procInfo[0].numNodesInPartition; + int *nodesAssigned = (int *)ADIOI_Malloc(partitionSize * sizeof(int)); + for (i=0;inProcs;i++) { + if (all_procInfo[i].manhattanDistanceToBridge == currentNumHops) { + if (nodesAssigned[all_procInfo[i].nodeRank] == 0) { // node is not assigned as an agg yet + int foundBridge = 0; + for (j=0;(jnumBridgeRanks) { + allAggsAssigned = 1; + for (i=0;(i 1 + + memcpy(tmp_ranklist, aggList, aggTotal*sizeof(int)); + } // gpfsmpio_bridgeringagg > 0 + + else { // gpfsmpio_bridgeringagg unset - default code + + int distance, numAggs; + + /* Aggregators will be midpoints between sorted MPI rank lists of who shares a given + * bridge node */ + + sortstruct *bridgelist = (sortstruct *)ADIOI_Malloc(confInfo->nProcs * sizeof(sortstruct)); + for(i=0; i < confInfo->nProcs; i++) + { + bridgelist[i].bridge = all_procInfo[i].bridgeRank; + bridgelist[i].rank = i; + TRACE_ERR("bridgelist[%d].bridge: %d .rank: %d\n", i, bridgelist[i].bridge, i); + } + + /* This list contains rank->bridge info. Now, we need to sort this list. */ + qsort(bridgelist, confInfo->nProcs, sizeof(sortstruct), intsort); + + /* In this array, we can pick an appropriate number of midpoints based on + * our bridgenode index and the number of aggregators */ + + numAggs = confInfo->aggRatio * confInfo->ioMinSize /*virtualPsetSize*/; + if(numAggs == 1) + aggTotal = 1; + else + /* the number of aggregators is (numAggs per bridgenode) plus each + * bridge node is an aggregator */ + aggTotal = confInfo->numBridgeRanks * (numAggs+1); + + if(aggTotal>confInfo->nProcs) aggTotal=confInfo->nProcs; + + TRACE_ERR("numBridgeRanks: %d, aggRatio: %f numBridge: %d pset size: %d/%d numAggs: %d, aggTotal: %d\n", confInfo->numBridgeRanks, confInfo->aggRatio, confInfo->numBridgeRanks, confInfo->ioMinSize, confInfo->ioMaxSize /*virtualPsetSize*/, numAggs, aggTotal); + aggList = (int *)ADIOI_Malloc(aggTotal * sizeof(int)); + + + /* For each bridge node, determine who the aggregators will be */ + /* basically, the n*distance and bridge node */ + if(aggTotal == 1) /* special case when we only have one bridge node */ + aggList[0] = bridgelist[0].bridge; + else + { + int lastBridge = bridgelist[confInfo->nProcs-1].bridge; + int nextBridge = 0, nextAggr = confInfo->numBridgeRanks; + int psetSize = 0; + int procIndex; + for(procIndex=confInfo->nProcs-1; procIndex>=0; procIndex--) + { + TRACE_ERR("bridgelist[%d].bridge %u/rank %u\n",procIndex, bridgelist[procIndex].bridge, bridgelist[procIndex].rank); + if(lastBridge == bridgelist[procIndex].bridge) + { + psetSize++; + if(procIndex) continue; + else procIndex--;/* procIndex == 0 */ + } + /* Sets up a list of nodes which will act as aggregators. numAggs + * per bridge node total. The list of aggregators is + * bridgeNode 0 + * bridgeNode 1 + * bridgeNode ... + * bridgeNode N + * bridgeNode[0]aggr[0] + * bridgeNode[0]aggr[1]... + * bridgeNode[0]aggr[N]... + * ... + * bridgeNode[N]aggr[0].. + * bridgeNode[N]aggr[N] + */ + aggList[nextBridge]=lastBridge; + distance = psetSize/numAggs; + TRACE_ERR("nextBridge %u is bridge %u, distance %u, size %u\n",nextBridge, aggList[nextBridge],distance,psetSize); + if(numAggs>1) + { + for(j = 0; j < numAggs; j++) + { + ADIOI_Assert(nextAggr bridgelist[%d] = %d\n", nextAggr, procIndex+j*distance+1,aggList[nextAggr]); + if(aggList[nextAggr]==lastBridge) /* can't have bridge in the list twice */ + { + aggList[nextAggr] = bridgelist[procIndex+psetSize].rank; /* take the last one in the pset */ + TRACE_ERR("replacement agglist[%d] -> bridgelist[%d] = %d\n", nextAggr, procIndex+psetSize,aggList[nextAggr]); + } + nextAggr++; + } + } + if(procIndex<0) break; + lastBridge = bridgelist[procIndex].bridge; + psetSize = 1; + nextBridge++; + } + } + + TRACE_ERR("memcpy(tmp_ranklist, aggList, (numAggs(%u)*confInfo->numBridgeRanks(%u)+numAggs(%u)) (%u) %u*sizeof(int))\n",numAggs,confInfo->numBridgeRanks,numAggs,(numAggs*confInfo->numBridgeRanks+numAggs),aggTotal); + memcpy(tmp_ranklist, aggList, aggTotal*sizeof(int)); + for(i=0;ihints struct + */ +static void +ADIOI_BG_compute_agg_ranklist_serial ( ADIO_File fd, + const ADIOI_BG_ConfInfo_t *confInfo, + ADIOI_BG_ProcInfo_t *all_procInfo) +{ + TRACE_ERR("Entering ADIOI_BG_compute_agg_ranklist_serial\n"); + int i; + int naggs; + int size; + int *tmp_ranklist; + + /* compute the ranklist of IO aggregators and put into tmp_ranklist */ + tmp_ranklist = (int *) ADIOI_Malloc (confInfo->nProcs * sizeof(int)); + +# if AGG_DEBUG + for (i=0; inProcs; i++) { + DBG_FPRINTF(stderr, "\tcpuid %1d, rank = %6d\n", all_procInfo[i].coreID, all_procInfo[i].rank ); + } +# endif + + naggs= + ADIOI_BG_compute_agg_ranklist_serial_do (confInfo, all_procInfo, tmp_ranklist); + +# define VERIFY 1 +# if VERIFY + DBG_FPRINTF(stderr, "\tconfInfo = min: %3d, max: %3d, naggrs: %3d, bridge: %3d, nprocs: %3d, vpset: %3d, tsize: %3d, ratio: %.4f; naggs = %d\n", + confInfo->ioMinSize , + confInfo->ioMaxSize , + confInfo->nAggrs , + confInfo->numBridgeRanks , + confInfo->nProcs , + confInfo->ioMaxSize /*virtualPsetSize*/ , + confInfo->cpuIDsize, + confInfo->aggRatio , + naggs ); +# endif + MPI_Comm_size( fd->comm, &size ); + /* This fix is for when the bridgenode rnk is not part of the particular + * subcomm associated with this MPI File operation. I don't know if + * this is the best/right answer but it passes the test cases at least. + * I don't know how common file IO in subcomms is anyway... */ + for(i=0;i size) + { + TRACE_ERR("Using 0 as tmp_ranklist[%d] instead of %d for comm %x\n", + i, tmp_ranklist[i], fd->comm); + tmp_ranklist[i] = 0; + } + } + +# if AGG_DEBUG + for (i=0; i aggbridgerank) + summarybridgeminionaggrank[summaryranklistbridgeindex] = aggbridgerank; + numbridges++; + } + + bridgelistnum[summaryranklistbridgeindex]++; + } + + /* at this point summarybridgeminionaggrank has the agg rank of the bridge for entries, + * need to make each entry the minimum bridge rank for the entire ion. */ + for (i=0;i summarybridgeminionaggrank[i+1]) { + int tmpminionaggrank = summarybridgeminionaggrank[i]; + summarybridgeminionaggrank[i] = summarybridgeminionaggrank[i+1]; + summarybridgeminionaggrank[i+1] = tmpminionaggrank; + int tmpionid = ionlist[i]; + ionlist[i] = ionlist[i+1]; + ionlist[i+1] = tmpionid; + int tmpbridgerank = bridgelist[i]; + bridgelist[i] = bridgelist[i+1]; + bridgelist[i+1] = tmpbridgerank; + int tmpbridgeranknum = bridgelistnum[i]; + bridgelistnum[i] = bridgelistnum[i+1]; + bridgelistnum[i+1] = tmpbridgeranknum; + } + } + } + + // for each io node make sure bridgelist is in rank order + int startSortIndex = -1; + int endSortIndex = -1; + int currentBridgeIndex = 0; + + while (currentBridgeIndex < numbridges) { + int currentIonId = ionlist[currentBridgeIndex]; + startSortIndex = currentBridgeIndex; + while (ionlist[currentBridgeIndex] == currentIonId) + currentBridgeIndex++; + endSortIndex = currentBridgeIndex-1; + for (x=startSortIndex;x<=endSortIndex;x++) { + for (i=startSortIndex;i bridgelist[i+1]) { + int tmpbridgerank = bridgelist[i]; + bridgelist[i] = bridgelist[i+1]; + bridgelist[i+1] = tmpbridgerank; + int tmpbridgeranknum = bridgelistnum[i]; + bridgelistnum[i] = bridgelistnum[i+1]; + bridgelistnum[i+1] = tmpbridgeranknum; + } + } + } + } + + + /* populate interleavedbridgeranklist - essentially the agg rank list + * is now sorted by the ion minimum bridge rank and bridge node */ + int currentrankoffset = 0; + for (i=0;i thisBridgeAggList[n+1]) { + int tmpthisBridgeAggList = thisBridgeAggList[n]; + thisBridgeAggList[n] = thisBridgeAggList[n+1]; + thisBridgeAggList[n+1] = tmpthisBridgeAggList; + } + } + } + int n; + for (n=0;nhints */ + if(fd->hints->ranklist != NULL) + ADIOI_Free (fd->hints->ranklist); + if(fd->hints->fs_hints.bg.bridgelist != NULL) + ADIOI_Free (fd->hints->fs_hints.bg.bridgelist); + if(fd->hints->fs_hints.bg.bridgelistnum != NULL) + ADIOI_Free (fd->hints->fs_hints.bg.bridgelistnum); + + fd->hints->cb_nodes = naggs; + fd->hints->fs_hints.bg.numbridges = numbridges; + fd->hints->ranklist = (int *) ADIOI_Malloc (naggs * sizeof(int)); + memcpy( fd->hints->ranklist, interleavedbridgeranklist, naggs*sizeof(int) ); + + fd->hints->fs_hints.bg.bridgelist = (int *) ADIOI_Malloc (naggs * sizeof(int)); + memcpy( fd->hints->fs_hints.bg.bridgelist, bridgelist, naggs*sizeof(int) ); + + fd->hints->fs_hints.bg.bridgelistnum = (int *) ADIOI_Malloc (naggs * sizeof(int)); + memcpy( fd->hints->fs_hints.bg.bridgelistnum, bridgelistnum, naggs*sizeof(int) ); + + ADIOI_Free(summarybridgeminionaggrank); + ADIOI_Free( tmp_ranklist ); + ADIOI_Free( bridgelistnum ); + ADIOI_Free( bridgelist ); + ADIOI_Free( interleavedbridgeranklist ); + ADIOI_Free(ionlist); + + } else { + /* classic topology-agnostic copy of the ranklist of IO aggregators to + * fd->hints */ + if(fd->hints->ranklist != NULL) ADIOI_Free (fd->hints->ranklist); + + fd->hints->cb_nodes = naggs; + fd->hints->ranklist = (int *) ADIOI_Malloc (naggs * sizeof(int)); + memcpy( fd->hints->ranklist, tmp_ranklist, naggs*sizeof(int) ); + + ADIOI_Free( tmp_ranklist ); + } + TRACE_ERR("Leaving ADIOI_BG_compute_agg_ranklist_serial\n"); + return; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_aggrs.h b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_aggrs.h new file mode 100644 index 0000000000..b154722850 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_aggrs.h @@ -0,0 +1,33 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_bg_aggrs.h + * \brief ??? + */ + +/* + * + * Declares functions specific for the BlueGene platform within the GPFS + * parallel I/O solution. Implements aligned file-domain partitioning + * (7/28/2005); persistent file doamin work not implemented + * + */ + +#ifndef AD_BG_AGGRS_H_ +#define AD_BG_AGGRS_H_ + +#include "adio.h" +#include + +#ifdef HAVE_GPFS_H +#include +#endif +#if !defined(GPFS_SUPER_MAGIC) + #define GPFS_SUPER_MAGIC (0x47504653) +#endif + + /* generate a list of I/O aggregators that utilizes BG-PSET orginization. */ + int ADIOI_BG_gen_agg_ranklist(ADIO_File fd, int n_aggrs_per_pset); + +#endif /* AD_BG_AGGRS_H_ */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_pset.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_pset.c new file mode 100644 index 0000000000..a94c996de8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_pset.c @@ -0,0 +1,377 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_bg_pset.c + * \brief Definition of functions associated to structs ADIOI_BG_ProcInfo_t and ADIOI_BG_ConfInfo_t + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* #define TRACE_ON */ +// #define bridgeringaggtrace 1 + +#include +#include "../ad_gpfs.h" +#include "ad_bg_pset.h" +#include +#include + +#ifdef HAVE_MPIX_H +#include +#endif + +#ifndef TRACE_ERR +# define TRACE_ERR(fmt...) +#endif + +ADIOI_BG_ProcInfo_t * +ADIOI_BG_ProcInfo_new() +{ + ADIOI_BG_ProcInfo_t *p = (ADIOI_BG_ProcInfo_t *) ADIOI_Malloc (sizeof(ADIOI_BG_ProcInfo_t)); + ADIOI_Assert ((p != NULL)); + return p; +} + +ADIOI_BG_ProcInfo_t * +ADIOI_BG_ProcInfo_new_n( int n ) +{ + ADIOI_BG_ProcInfo_t *p = (ADIOI_BG_ProcInfo_t *) ADIOI_Malloc (n * sizeof(ADIOI_BG_ProcInfo_t)); + ADIOI_Assert ((p != NULL)); + return p; +} + +void +ADIOI_BG_ProcInfo_free( ADIOI_BG_ProcInfo_t *info ) +{ + if (info != NULL) ADIOI_Free (info); +} + +ADIOI_BG_ConfInfo_t * +ADIOI_BG_ConfInfo_new () +{ + ADIOI_BG_ConfInfo_t *p = (ADIOI_BG_ConfInfo_t *) ADIOI_Malloc (sizeof(ADIOI_BG_ConfInfo_t)); + ADIOI_Assert ((p != NULL)); + return p; +} + + +void +ADIOI_BG_ConfInfo_free( ADIOI_BG_ConfInfo_t *info ) +{ + if (info != NULL) ADIOI_Free (info); +} + + +typedef struct +{ + int rank; + int bridgeCoord; +} sortstruct; + +static int intsort(const void *p1, const void *p2) +{ + sortstruct *i1, *i2; + i1 = (sortstruct *)p1; + i2 = (sortstruct *)p2; + return(i1->bridgeCoord - i2->bridgeCoord); +} + +unsigned torusSize[MPIX_TORUS_MAX_DIMS]; +unsigned dimTorus[MPIX_TORUS_MAX_DIMS]; + +/* This function computes the number of hops between the torus coordinates of the + * aggCoords and bridgeCoords parameters. +*/ +static unsigned procManhattanDistance(unsigned *aggCoords, unsigned *bridgeCoords) { + + unsigned totalDistance = 0; + int i; + for (i=0;i 0) { // could torus make it closer? + if (dimTorus[i]) { + if (aggCoords[i] == torusSize[i]) { // is wrap-around closer + if ((bridgeCoords[i]+1) < dimDistance) // assume will use torus link + dimDistance = bridgeCoords[i]+1; + } + else if (bridgeCoords[i] == torusSize[i]) { // is wrap-around closer + if ((aggCoords[i]+1) < dimDistance) // assume will use torus link + dimDistance = aggCoords[i]+1; + } + } + } /* else: dimDistance == 0, meaning aggCoords[i] and bridgeCoords[i] are + the same and there's no closer point to pick */ + totalDistance += dimDistance; + } + return totalDistance; +} + + +void +ADIOI_BG_persInfo_init(ADIOI_BG_ConfInfo_t *conf, + ADIOI_BG_ProcInfo_t *proc, + int size, int rank, int n_aggrs, MPI_Comm comm) +{ + int i, iambridge=0, bridgerank = -1, bridgeIndex; + int countPset; + sortstruct *bridges; + int commsize; + + TRACE_ERR("Entering BG_persInfo_init, size: %d, rank: %d, n_aggrs: %d, comm: %d\n", size, rank, n_aggrs, (int)comm); + + Personality_t pers; + MPIX_Hardware_t hw; + MPIX_Hardware(&hw); + TRACE_ERR("BG_persInfo_init, my coords{%u,%u,%u,%u,%u} rankInPset %u,sizeOfPset %u,idOfPset %u\n",hw.Coords[0],hw.Coords[1],hw.Coords[2],hw.Coords[3],hw.Coords[4],hw.rankInPset,hw.sizeOfPset,hw.idOfPset); + + + Kernel_GetPersonality(&pers, sizeof(pers)); + + proc->rank = rank; + proc->coreID = hw.coreID; + + if (gpfsmpio_bridgeringagg > 0) { +#ifdef bridgeringaggtrace + if (rank == 0) + fprintf(stderr,"Block dimensions:\n"); +#endif + + /* Set the numNodesInPartition and nodeRank for this proc + */ + proc->numNodesInPartition = 1; + proc->nodeRank = 0; + for (i=0;inumNodesInPartition *= hw.Size[i]; + int baseNum = 1, j; + for (j=0;jnodeRank += (hw.Coords[i] * baseNum); +#ifdef bridgeringaggtrace + if (rank == 0) + fprintf(stderr,"Dimension %d has %d elements wrap-around value is %d\n",i,torusSize[i],dimTorus[i]); +#endif + } + } + + MPI_Comm_size(comm, &commsize); + + proc->ionID = MPIX_IO_node_id (); + + if(size == 1) + { + proc->iamBridge = 1; + proc->bridgeRank = rank; + if (gpfsmpio_bridgeringagg > 0) { + proc->manhattanDistanceToBridge = 0; + } + + /* Set up the other parameters */ + proc->myIOSize = size; + proc->ioNodeIndex = 0; + conf->ioMinSize = size; + conf->ioMaxSize = size; + conf->numBridgeRanks = 1; + conf->nProcs = size; + conf->cpuIDsize = hw.ppn; + /*conf->virtualPsetSize = conf->ioMaxSize * conf->cpuIDsize;*/ + conf->nAggrs = 1; + conf->aggRatio = 1. * conf->nAggrs / conf->ioMinSize /*virtualPsetSize*/; + if(conf->aggRatio > 1) conf->aggRatio = 1.; + TRACE_ERR("I am (single) Bridge rank\n"); + return; + } + + /* Find the nearest bridge node coords. We don't know the + rank in our comm so we will collective find/pick a bridge + rank later. + */ + int32_t bridgeCoords; + bridgeCoords = pers.Network_Config.cnBridge_A << 24 | + pers.Network_Config.cnBridge_B << 18 | + pers.Network_Config.cnBridge_C << 12 | + pers.Network_Config.cnBridge_D << 6 | + pers.Network_Config.cnBridge_E << 2; + ADIOI_Assert((bridgeCoords >= 0)); /* A dim is < 6 bits or sorting won't work */ + + if((hw.Coords[0] == pers.Network_Config.cnBridge_A) && + (hw.Coords[1] == pers.Network_Config.cnBridge_B) && + (hw.Coords[2] == pers.Network_Config.cnBridge_C) && + (hw.Coords[3] == pers.Network_Config.cnBridge_D) && + (hw.Coords[4] == pers.Network_Config.cnBridge_E)) { + iambridge = 1; /* I am bridge */ + if (gpfsmpio_bridgeringagg > 0) { + proc->manhattanDistanceToBridge = 0; + } + } + else { // calculate manhattan distance to bridge if gpfsmpio_bridgeringagg is set + if (gpfsmpio_bridgeringagg > 0) { + unsigned aggCoords[MPIX_TORUS_MAX_DIMS],manhattanBridgeCoords[MPIX_TORUS_MAX_DIMS]; + aggCoords[0] = hw.Coords[0]; + manhattanBridgeCoords[0] = pers.Network_Config.cnBridge_A; + aggCoords[1] = hw.Coords[1]; + manhattanBridgeCoords[1] = pers.Network_Config.cnBridge_B; + aggCoords[2] = hw.Coords[2]; + manhattanBridgeCoords[2] = pers.Network_Config.cnBridge_C; + aggCoords[3] = hw.Coords[3]; + manhattanBridgeCoords[3] = pers.Network_Config.cnBridge_D; + aggCoords[4] = hw.Coords[4]; + manhattanBridgeCoords[4] = pers.Network_Config.cnBridge_E; + + proc->manhattanDistanceToBridge= procManhattanDistance(aggCoords, manhattanBridgeCoords); +#ifdef bridgeringaggtrace + fprintf(stderr,"agg coords are %u %u %u %u %u bridge coords are %u %u %u %u %u distance is %u\n",aggCoords[0],aggCoords[1],aggCoords[2],aggCoords[3],aggCoords[4],manhattanBridgeCoords[0],manhattanBridgeCoords[1],manhattanBridgeCoords[2],manhattanBridgeCoords[3],manhattanBridgeCoords[4], proc->manhattanDistanceToBridge); +#endif + } + } + + TRACE_ERR("Bridge coords(%8.8X): %d %d %d %d %d, %d. iambridge %d\n",bridgeCoords, pers.Network_Config.cnBridge_A,pers.Network_Config.cnBridge_B,pers.Network_Config.cnBridge_C,pers.Network_Config.cnBridge_D,pers.Network_Config.cnBridge_E,0, iambridge); + + /* Allgather the ranks and bridgeCoords to determine the bridge + rank and how many ranks belong to each bridge rank*/ + bridges = (sortstruct *) ADIOI_Malloc(sizeof(sortstruct) * size); + + /* We're going to sort this structure by bridgeCoord: + + typedef struct + { + int rank; + int bridgeCoord; + } sortstruct; + + and I want the rank that IS the bridge to sort first, so + OR in '1' on non-bridge ranks that use a bridge coord. + */ + + /* My input to the collective */ + bridges[rank].rank = rank; + bridges[rank].bridgeCoord = bridgeCoords; + if(!iambridge) + bridges[rank].bridgeCoord |= 1; /* I am not bridge, turn on bit */ + + + MPI_Allgather(MPI_IN_PLACE, 2, MPI_INT, bridges, 2, MPI_INT, comm); + + qsort(bridges, size, sizeof(sortstruct), intsort); + + /* Once the list is sorted walk through it to setup bridge + info and find bridge ranks, etc. */ + + int tempCoords, tempRank, mincompute, maxcompute; + tempCoords = bridges[0].bridgeCoord & ~1; + tempRank = bridges[0].rank; + + countPset=1; + bridgeIndex = 0; + mincompute = size+1; + maxcompute = 1; + + for(i=1; i maxcompute) + maxcompute = countPset; + if(countPset < mincompute) + mincompute = countPset; + + /* Was this my bridge we finished? */ + if(tempCoords == bridgeCoords) + { + /* Am I the bridge rank? */ + if(tempRank == rank) + iambridge = 1; + else + iambridge = 0; /* Another rank on my node may have taken over */ + TRACE_ERR("Rank %u, bridge set %u, bridge rank %d (%#8.8X) has %d ranks, iambridge %u\n", + rank, bridgeIndex, tempRank, tempCoords, countPset,iambridge); + bridgerank = tempRank; + proc->myIOSize = countPset; + proc->ioNodeIndex = bridgeIndex; + } + /* Setup next bridge */ + tempCoords = bridges[i].bridgeCoord & ~1; + tempRank = bridges[i].rank; + bridgeIndex++; + countPset = 1; + } + } + /* Process last bridge */ + +#ifdef TRACE_ON + if(rank == 0) + TRACE_ERR("Bridge set %u, bridge rank %d (%#8.8X) has %d ranks\n", + bridgeIndex, tempRank, tempCoords, countPset); +#endif + if(countPset > maxcompute) + maxcompute = countPset; + if(countPset < mincompute) + mincompute = countPset; + + /* Was this my bridge? */ + if(tempCoords == bridgeCoords) + { + /* Am I the bridge rank? */ + if(tempRank == rank) + iambridge = 1; + else + iambridge = 0; /* Another rank on my node may have taken over */ + bridgerank = tempRank; + proc->myIOSize = countPset; + proc->ioNodeIndex = bridgeIndex; + } + + + if(rank == 0) + { + /* Only rank 0 has a conf structure, fill in stuff as appropriate */ + conf->ioMinSize = mincompute; + conf->ioMaxSize = maxcompute; /* equivalent to pset size */ + conf->numBridgeRanks = bridgeIndex+1; + conf->nProcs = size; + conf->cpuIDsize = hw.ppn; + /*conf->virtualPsetSize = maxcompute * conf->cpuIDsize;*/ + + conf->nAggrs = n_aggrs; + /* First pass gets nAggrs = -1 */ + if(conf->nAggrs <=0) + conf->nAggrs = gpfsmpio_bg_nagg_pset; + if(conf->ioMinSize <= conf->nAggrs) + conf->nAggrs = ADIOI_MAX(1,conf->ioMinSize-1); /* not including bridge itself */ +/* if(conf->nAggrs > conf->numBridgeRanks) + conf->nAggrs = conf->numBridgeRanks; +*/ + conf->aggRatio = 1. * conf->nAggrs / conf->ioMinSize /*virtualPsetSize*/; +/* if(conf->aggRatio > 1) conf->aggRatio = 1.; */ + TRACE_ERR("n_aggrs %zd, conf->nProcs %zu, conf->ioMaxSize %zu, ADIOI_BG_NAGG_PSET_DFLT %zu,conf->numBridgeRanks %zu,conf->nAggrs %zu\n",(size_t)n_aggrs, (size_t)conf->nProcs, (size_t)conf->ioMaxSize, (size_t)ADIOI_BG_NAGG_PSET_DFLT,(size_t)conf->numBridgeRanks,(size_t)conf->nAggrs); + TRACE_ERR("Maximum ranks under a bridge rank: %d, minimum: %d, nAggrs: %d, numBridgeRanks: %d pset dflt: %d naggrs: %d ratio: %f\n", maxcompute, mincompute, conf->nAggrs, conf->numBridgeRanks, ADIOI_BG_NAGG_PSET_DFLT, conf->nAggrs, conf->aggRatio); + } + + ADIOI_Assert((bridgerank != -1)); + proc->bridgeRank = bridgerank; + proc->iamBridge = iambridge; + TRACE_ERR("Rank %d has bridge set index %d (bridge rank: %d) with %d other ranks, ioNodeIndex: %d\n", rank, proc->ioNodeIndex, bridgerank, proc->myIOSize, proc->ioNodeIndex); + + ADIOI_Free(bridges); + +} + +void +ADIOI_BG_persInfo_free( ADIOI_BG_ConfInfo_t *conf, ADIOI_BG_ProcInfo_t *proc ) +{ + ADIOI_BG_ConfInfo_free( conf ); + ADIOI_BG_ProcInfo_free( proc ); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_pset.h b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_pset.h new file mode 100644 index 0000000000..bcdc61f5e3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/bg/ad_bg_pset.h @@ -0,0 +1,83 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_bg_pset.h + * \brief ??? + */ + +/* File: ad_bg_pset.h + * + * Defines two structures that keep BlueGene PSET specific information and their public interfaces: + * . ADIOI_BG_ProcInfo_t object keeps specific information to each process + * . ADIOI_BG_ConfInfo_t object keeps general information for the whole communicator, only kept + * on process 0. + */ + +#ifndef AD_BG_PSET_H_ +#define AD_BG_PSET_H_ + +#ifdef HAVE_MPIX_H +#include +#endif + +/* Keeps specific information to each process, will be exchanged among processes */ +typedef struct { + int ioNodeIndex; /* similar to psetNum on BGL/BGP */ + int rank; /* my rank */ + int ionID; /* ion id this cn is using */ +/* int myCoords[5]; */ + int bridgeRank; /* my bridge node (or proxy) rank */ + unsigned char coreID; + unsigned char threadID; /* unlikely to be useful but better than just padding */ + unsigned char __cpad[2]; + int myIOSize; /* number of ranks sharing my bridge/IO + node, i.e. psetsize*/ + int iamBridge; /* am *I* the bridge rank? */ + int __ipad[2]; + unsigned nodeRank; /* torus coords converted to an integer for use with gpfsmpio_bridgeringagg */ + unsigned numNodesInPartition; /* number of physical nodes in the job partition */ + unsigned manhattanDistanceToBridge; /* number of hops between this rank and the bridge node */ +} ADIOI_BG_ProcInfo_t __attribute__((aligned(16))); + +/* Keeps general information for the whole communicator, only on process 0 */ +typedef struct { + int ioMinSize; /* Smallest number of ranks shareing 1 bridge node */ + int ioMaxSize; /* Largest number of ranks sharing 1 bridge node */ + /* ioMaxSize will be the "psetsize" */ + int nAggrs; + int numBridgeRanks; + /*int virtualPsetSize; ppn * pset size */ + int nProcs; + int cpuIDsize; /* num ppn */ + float aggRatio; + +} ADIOI_BG_ConfInfo_t __attribute__((aligned(16))); + + +#undef MIN +#define MIN(a,b) (((a)<(b) ? (a) : (b))) + + + + +/* public funcs for ADIOI_BG_ProcInfo_t objects */ + ADIOI_BG_ProcInfo_t * ADIOI_BG_ProcInfo_new(); + ADIOI_BG_ProcInfo_t * ADIOI_BG_ProcInfo_new_n( int n ); + void ADIOI_BG_ProcInfo_free( ADIOI_BG_ProcInfo_t *info ); + + +/* public funcs for ADIOI_BG_ConfInfo_t objects */ + ADIOI_BG_ConfInfo_t * ADIOI_BG_ConfInfo_new (); + void ADIOI_BG_ConfInfo_free( ADIOI_BG_ConfInfo_t *info ); + + +/* public funcs for a pair of ADIOI_BG_ConfInfo_t and ADIOI_BG_ProcInfo_t objects */ + void ADIOI_BG_persInfo_init( ADIOI_BG_ConfInfo_t *conf, + ADIOI_BG_ProcInfo_t *proc, + int s, int r, int n_aggrs, MPI_Comm comm); + void ADIOI_BG_persInfo_free( ADIOI_BG_ConfInfo_t *conf, + ADIOI_BG_ProcInfo_t *proc ); + + +#endif /* AD_BG_PSET_H_ */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/pe/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_gpfs/pe/Makefile.mk new file mode 100644 index 0000000000..6173bd7fe0 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/pe/Makefile.mk @@ -0,0 +1,16 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2012 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_PE + +noinst_HEADERS += \ + adio/ad_gpfs/pe/ad_pe_aggrs.h + +romio_other_sources += \ + adio/ad_gpfs/pe/ad_pe_aggrs.c + +endif BUILD_AD_PE diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/pe/ad_pe_aggrs.c b/ompi/mca/io/romio314/romio/adio/ad_gpfs/pe/ad_pe_aggrs.c new file mode 100644 index 0000000000..8453238a83 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/pe/ad_pe_aggrs.c @@ -0,0 +1,276 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_pe_aggrs.c + * \brief The externally used function from this file is is declared in ad_pe_aggrs.h + */ + +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 1997-2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/*#define TRACE_ON */ + +#include "adio.h" +#include "adio_cb_config_list.h" +#include "../ad_gpfs.h" +#include "ad_pe_aggrs.h" +#include "mpiimpl.h" + +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + +#ifdef USE_DBG_LOGGING + #define AGG_DEBUG 1 +#endif + +#ifndef TRACE_ERR +# define TRACE_ERR(format...) +#endif + +/* + * Compute the aggregator-related parameters that are required in 2-phase + * collective IO of ADIO. + * The parameters are + * . the number of aggregators (proxies) : fd->hints->cb_nodes + * . the ranks of the aggregators : fd->hints->ranklist + * If MP_IONODEFILE is defined, POE determines all tasks on every node listed + * in the node file and defines MP_IOTASKLIST with them, making them all + * aggregators. Alternatively, the user can explictly set MP_IOTASKLIST + * themselves. The format of the MP_IOTASKLIST is a colon-delimited list of + * task ids, the first entry being the total number of aggregators, for example + * to specify 4 aggregators on task ids 0,8,16,24 the value would be: + * 4:0:8:16:24. If there is no MP_IONODEFILE, or MP_IOTASKLIST, then the + * default aggregator selection is 1 task per node for every node of the job - + * additionally, an environment variable MP_IOAGGR_CNT can be specified, which + * defines the total number of aggregators, spread evenly across all the nodes. + * The romio_cb_nodes and romio_cb_config_list hint user settings are ignored. + */ +int +ADIOI_PE_gen_agg_ranklist(ADIO_File fd) +{ + + int numAggs = 0; + char *ioTaskList = getenv( "MP_IOTASKLIST" ); + char *ioAggrCount = getenv("MP_IOAGGR_CNT"); + int i,j; + int inTERcommFlag = 0; + + int myRank,commSize; + MPI_Comm_rank(fd->comm, &myRank); + MPI_Comm_size(fd->comm, &commSize); + + MPI_Comm_test_inter(fd->comm, &inTERcommFlag); + if (inTERcommFlag) { + FPRINTF(stderr,"ERROR: ATTENTION: inTERcomms are not supported in MPI-IO - aborting....\n"); + perror("ADIOI_PE_gen_agg_ranklist:"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (ioTaskList) { + int ioTaskListLen = strlen(ioTaskList); + int ioTaskListPos = 0; + char tmpBuf[8]; /* Big enough for 1M tasks (7 digits task ID). */ + tmpBuf[7] = '\0'; + for (i=0; i<7; i++) { + tmpBuf[i] = *ioTaskList++; /* Maximum is 7 digits for 1 million. */ + ioTaskListPos++; + if (*ioTaskList == ':') { /* If the next char is a ':' ends it. */ + tmpBuf[i+1] = '\0'; + break; + } + } + numAggs = atoi(tmpBuf); + if (numAggs == 0) + FPRINTF(stderr,"ERROR: ATTENTION: Number of aggregators specified in MP_IOTASKLIST set at 0 - default aggregator selection will be used.\n"); + else if (!((numAggs > 0 ) && (numAggs <= commSize))) { + FPRINTF(stderr,"ERROR: ATTENTION: The number of aggregators (%s) specified in MP_IOTASKLIST is outside the communicator task range of %d.\n",tmpBuf,commSize); + numAggs = commSize; + } + fd->hints->ranklist = (int *) ADIOI_Malloc (numAggs * sizeof(int)); + + int aggIndex = 0; + while (aggIndex < numAggs) { + ioTaskList++; /* Advance past the ':' */ + ioTaskListPos++; + int allDigits=1; + for (i=0; i<7; i++) { + if (*ioTaskList < '0' || *ioTaskList > '9') + allDigits=0; + tmpBuf[i] = *ioTaskList++; + ioTaskListPos++; + if ( (*ioTaskList == ':') || (*ioTaskList == '\0') ) { + tmpBuf[i+1] = '\0'; + break; + } + } + if (allDigits) { + int newAggRank = atoi(tmpBuf); + if (!((newAggRank >= 0 ) && (newAggRank < commSize))) { + FPRINTF(stderr,"ERROR: ATTENTION: The aggregator '%s' specified in MP_IOTASKLIST is not within the communicator task range of 0 to %d - it will be ignored.\n",tmpBuf,commSize-1); + } + else { + int aggAlreadyAdded = 0; + for (i=0;ihints->ranklist[i] == newAggRank) { + aggAlreadyAdded = 1; + break; + } + if (!aggAlreadyAdded) + fd->hints->ranklist[aggIndex++] = newAggRank; + else + FPRINTF(stderr,"ERROR: ATTENTION: The aggregator '%d' is specified multiple times in MP_IOTASKLIST - duplicates are ignored.\n",newAggRank); + } + } + else { + FPRINTF(stderr,"ERROR: ATTENTION: The aggregator '%s' specified in MP_IOTASKLIST is not a valid integer task id - it will be ignored.\n",tmpBuf); + } + + /* At the end check whether the list is shorter than specified. */ + if (ioTaskListPos == ioTaskListLen) { + if (aggIndex == 0) { + FPRINTF(stderr,"ERROR: ATTENTION: No aggregators were correctly specified in MP_IOTASKLIST - default aggregator selection will be used.\n"); + ADIOI_Free(fd->hints->ranklist); + } + else if (aggIndex < numAggs) + FPRINTF(stderr,"ERROR: ATTENTION: %d aggregators were specified in MP_IOTASKLIST but only %d were correctly specified - setting the number of aggregators to %d.\n",numAggs, aggIndex,aggIndex); + numAggs = aggIndex; + } + } + } + if (numAggs == 0) { + MPID_Comm *mpidCommData; + + MPID_Comm_get_ptr(fd->comm,mpidCommData); + int localSize = mpidCommData->local_size; + + // get my node rank + int myNodeRank = mpidCommData->intranode_table[mpidCommData->rank]; + + int *allNodeRanks = (int *) ADIOI_Malloc (localSize * sizeof(int)); + + allNodeRanks[myRank] = myNodeRank; + MPI_Allgather(MPI_IN_PLACE, 1, MPI_INT, allNodeRanks, 1, MPI_INT, fd->comm); + +#ifdef AGG_DEBUG + printf("MPID_Comm data: local_size is %d\nintranode_table entries:\n",mpidCommData->local_size); + for (i=0;iintranode_table[i]); + } + printf("\ninternode_table entries:\n"); + for (i=0;iinternode_table[i]); + } + printf("\n"); + + printf("\nallNodeRanks entries:\n"); + for (i=0;ihints->ranklist = (int *) ADIOI_Malloc (localSize * sizeof(int)); + for (i=0;ihints->ranklist[rankListIndex++] = i; + numAggs++; + } + } + } + break; + case -2: + /* ALL tasks case */ + fd->hints->ranklist = (int *) ADIOI_Malloc (localSize * sizeof(int)); + for (i=0;ihints->ranklist[i] = i; + numAggs++; + } + break; + default: + /* Specific aggr count case -- MUST be less than localSize, otherwise set to localSize */ + if (cntType > localSize) + cntType = localSize; + + numAggs = cntType; + // Round-robin thru allNodeRanks - pick the 0's, then the 1's, etc + int currentNodeRank = 0; // node rank currently being selected as aggregator + int rankListIndex = 0; + int currentAllNodeIndex = 0; + + fd->hints->ranklist = (int *) ADIOI_Malloc (numAggs * sizeof(int)); + + while (rankListIndex < numAggs) { + int foundEntry = 0; + while (!foundEntry && (currentAllNodeIndex < localSize)) { + if (allNodeRanks[currentAllNodeIndex] == currentNodeRank) { + fd->hints->ranklist[rankListIndex++] = currentAllNodeIndex; + foundEntry = 1; + } + currentAllNodeIndex++; + } + if (!foundEntry) { + currentNodeRank++; + currentAllNodeIndex = 0; + } + } // while + break; + } // switch(cntType) + } // if (ioAggrCount) + + else { // default is 1 aggregator per node + // take the 0 entries from allNodeRanks + int rankListIndex = 0; + fd->hints->ranklist = (int *) ADIOI_Malloc (localSize * sizeof(int)); + for (i=0;ihints->ranklist[rankListIndex++] = i; + numAggs++; + } + } + } + + ADIOI_Free(allNodeRanks); + + } + + if ( getenv("MP_I_SHOW_AGGRS") ) { + if (myRank == 0) { + printf("Agg rank list of %d generated:\n", numAggs); + for (i=0;ihints->ranklist[i]); + } + printf("\n"); + } + } + + fd->hints->cb_nodes = numAggs; + + return 0; +} + diff --git a/ompi/mca/io/romio314/romio/adio/ad_gpfs/pe/ad_pe_aggrs.h b/ompi/mca/io/romio314/romio/adio/ad_gpfs/pe/ad_pe_aggrs.h new file mode 100644 index 0000000000..f779d182a5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gpfs/pe/ad_pe_aggrs.h @@ -0,0 +1,30 @@ +/* ---------------------------------------------------------------- */ +/* (C)Copyright IBM Corp. 2007, 2008 */ +/* ---------------------------------------------------------------- */ +/** + * \file ad_pe_aggrs.h + * \brief ??? + */ + +/* + * + * Declares functions specific for the PE platform within the GPFS + * parallel I/O solution. For now simply processes the MP_IOTASKLIST + * env var. + * + */ + +#ifndef AD_PE_AGGRS_H_ +#define AD_PE_AGGRS_H_ + +#include "adio.h" +#include + +#if !defined(GPFS_SUPER_MAGIC) + #define GPFS_SUPER_MAGIC (0x47504653) +#endif + + /* generate a list of I/O aggregators following a methodology specific for PE */ + int ADIOI_PE_gen_agg_ranklist(ADIO_File fd); + +#endif /* AD_PE_AGGRS_H_ */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_gridftp/Makefile.mk new file mode 100644 index 0000000000..2cd83a2ad2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/Makefile.mk @@ -0,0 +1,27 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_GRIDFTP + +noinst_HEADERS += adio/ad_gridftp/ad_gridftp.h + +romio_other_sources += \ + adio/ad_gridftp/ad_gridftp_close.c \ + adio/ad_gridftp/ad_gridftp_open.c \ + adio/ad_gridftp/ad_gridftp_read.c \ + adio/ad_gridftp/ad_gridftp_write.c \ + adio/ad_gridftp/ad_gridftp_fcntl.c \ + adio/ad_gridftp/ad_gridftp_flush.c \ + adio/ad_gridftp/ad_gridftp_resize.c \ + adio/ad_gridftp/ad_gridftp_hints.c \ + adio/ad_gridftp/ad_gridftp_delete.c \ + adio/ad_gridftp/ad_gridftp.c \ + adio/ad_gridftp/globus_routines.c \ + adio/ad_gridftp/ad_gridftp_features.c + +endif BUILD_AD_GRIDFTP + diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp.c new file mode 100644 index 0000000000..f08f112a3c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp.c @@ -0,0 +1,37 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gridftp.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_GRIDFTP_operations = { + ADIOI_GRIDFTP_Open, /* Open */ + ADIOI_GRIDFTP_ReadContig, /* ReadContig */ + ADIOI_GRIDFTP_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_GRIDFTP_Fcntl, /* Fcntl */ + ADIOI_GRIDFTP_SetInfo, /* SetInfo */ + ADIOI_GRIDFTP_ReadStrided, /* ReadStrided */ + ADIOI_GRIDFTP_WriteStrided, /* WriteStrided */ + ADIOI_GRIDFTP_Close, /* Close */ + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ + ADIOI_FAKE_IODone, /* ReadDone */ + ADIOI_FAKE_IODone, /* WriteDone */ + ADIOI_FAKE_IOComplete, /* ReadComplete */ + ADIOI_FAKE_IOComplete, /* WriteComplete */ + ADIOI_FAKE_IreadStrided, /* IreadStrided */ + ADIOI_FAKE_IwriteStrided, /* IwriteStrided */ + ADIOI_GRIDFTP_Flush, /* Flush */ + ADIOI_GRIDFTP_Resize, /* Resize */ + ADIOI_GRIDFTP_Delete, /* Delete */ + ADIOI_GRIDFTP_Feature, /* Features */ +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp.h b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp.h new file mode 100644 index 0000000000..0b94c780ea --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp.h @@ -0,0 +1,96 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_GRIDFTP_INCLUDE +#define AD_GRIDFTP_INCLUDE + +#include +#include +#include +#include +#include "adio.h" +#include + +/* These live in globus_routines.c */ +extern int num_gridftp_handles; +#ifndef ADIO_GRIDFTP_HANDLES_MAX +#define ADIO_GRIDFTP_HANDLES_MAX 200 +#endif /* ! ADIO_GRIDFTP_HANDLES_MAX */ +extern globus_ftp_client_handle_t gridftp_fh[ADIO_GRIDFTP_HANDLES_MAX]; +extern globus_ftp_client_operationattr_t oattr[ADIO_GRIDFTP_HANDLES_MAX]; + + +/* TODO: weed out the now-unused prototypes */ +void ADIOI_GRIDFTP_Open(ADIO_File fd, int *error_code); +void ADIOI_GRIDFTP_Close(ADIO_File fd, int *error_code); +void ADIOI_GRIDFTP_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_GRIDFTP_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_GRIDFTP_IwriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_GRIDFTP_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +int ADIOI_GRIDFTP_ReadDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +int ADIOI_GRIDFTP_WriteDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_GRIDFTP_ReadComplete(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_GRIDFTP_WriteComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIOI_GRIDFTP_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code); +void ADIOI_GRIDFTP_WriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code); +void ADIOI_GRIDFTP_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_GRIDFTP_WriteStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_GRIDFTP_ReadStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_GRIDFTP_IreadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_GRIDFTP_IwriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_GRIDFTP_Flush(ADIO_File fd, int *error_code); +void ADIOI_GRIDFTP_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +void ADIOI_GRIDFTP_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); +void ADIOI_GRIDFTP_Get_shared_fp(ADIO_File fd, int size, + ADIO_Offset *shared_fp, + int *error_code); +void ADIOI_GRIDFTP_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, + int *error_code); +void ADIOI_GRIDFTP_Delete(char *filename, int *error_code); + +void globus_err_handler(const char *routine, const char *caller, + globus_result_t result); + +#endif + + + + diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_close.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_close.c new file mode 100644 index 0000000000..c1693d65ce --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_close.c @@ -0,0 +1,50 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gridftp.h" +#include "adioi.h" + +void ADIOI_GRIDFTP_Close(ADIO_File fd, int *error_code) +{ + int err; + static char myname[]="ADIOI_GRIDFTP_Close"; + + globus_result_t result; + + MPI_Barrier(fd->comm); + + /* Destroy the ftp handle and opattr */ + result = globus_ftp_client_operationattr_destroy(&(oattr[fd->fd_sys])); + if (result != GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_operationattr_destroy", + myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s",globus_object_printable_to_string(globus_error_get(result))); + return; + } + result=globus_ftp_client_handle_destroy(&(gridftp_fh[fd->fd_sys])); + if (result != GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_handle_destroy", + myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + + fd->fd_sys = -1; + fd->fp_ind=0; + fd->fp_sys_posn=0; + num_gridftp_handles--; + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_delete.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_delete.c new file mode 100644 index 0000000000..54eb714429 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_delete.c @@ -0,0 +1,95 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gridftp.h" +#include "adioi.h" + +static globus_mutex_t lock; +static globus_cond_t cond; +static globus_bool_t delete_done, delete_success; +static void delete_cb(void *myarg, globus_ftp_client_handle_t *handle, globus_object_t *error) +{ + + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + else + { + delete_success=GLOBUS_TRUE; + } + delete_done=GLOBUS_TRUE; +} + +void ADIOI_GRIDFTP_Delete(char *filename, int *error_code) +{ + char myname[]="ADIOI_GRIDFTP_Delete"; + int myrank, nprocs; + globus_ftp_client_handle_t handle; + globus_result_t result; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + globus_module_activate(GLOBUS_FTP_CLIENT_MODULE); + result=globus_ftp_client_handle_init(&handle,GLOBUS_NULL); + + if (result != GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_handle_init",myname,result); + *error_code= MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_IO, + "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + + delete_done=GLOBUS_FALSE; + delete_success=GLOBUS_FALSE; + result=globus_ftp_client_delete(&handle,filename,GLOBUS_NULL,delete_cb,GLOBUS_NULL); + if (result != GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_delete",myname,result); + *error_code= MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_IO, + "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + globus_mutex_lock(&lock); + while ( delete_done!=GLOBUS_TRUE ) + globus_cond_wait(&cond,&lock); + globus_mutex_unlock(&lock); + result=globus_ftp_client_handle_destroy(&handle); + if (result != GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_handle_destroy",myname,result); + *error_code= MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_IO, + "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + + if ( delete_success!=GLOBUS_TRUE ) + { + *error_code= MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_IO, + "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_fcntl.c new file mode 100644 index 0000000000..dd9cb5ee09 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_fcntl.c @@ -0,0 +1,91 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gridftp.h" +#include "adioi.h" +#include "adio_extern.h" + +globus_mutex_t fcntl_size_lock; +globus_cond_t fcntl_size_cond; +globus_bool_t fcntl_size_done; + +void fcntl_size_cb(void *myargs, globus_ftp_client_handle_t *handle, + globus_object_t *error) +{ + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + globus_mutex_lock(&fcntl_size_lock); + fcntl_size_done=GLOBUS_TRUE; + globus_cond_signal(&fcntl_size_cond); + globus_mutex_unlock(&fcntl_size_lock); +} + +void ADIOI_GRIDFTP_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code) +{ + MPI_Datatype copy_etype, copy_filetype; + int combiner, i, j, k, filetype_is_contig, err; + ADIOI_Flatlist_node *flat_file; + char myname[]="ADIOI_GRIDFTP_Fcntl"; + + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + { + globus_result_t result; + globus_off_t fsize=0; + + globus_mutex_init(&fcntl_size_lock,GLOBUS_NULL); + globus_cond_init(&fcntl_size_cond,GLOBUS_NULL); + fcntl_size_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_size(&(gridftp_fh[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + &(fsize), + fcntl_size_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_size",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + globus_mutex_lock(&fcntl_size_lock); + while ( fcntl_size_done!=GLOBUS_TRUE ) + globus_cond_wait(&fcntl_size_lock,&fcntl_size_cond); + globus_mutex_unlock(&fcntl_size_lock); + globus_mutex_destroy(&fcntl_size_lock); + globus_cond_destroy(&fcntl_size_cond); + fcntl_struct->fsize=fsize; + } + *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + ADIOI_GEN_Prealloc(fd, fcntl_struct->diskspace, error_code); + break; + + case ADIO_FCNTL_SET_ATOMICITY: + default: + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**flag", "**flag %d", flag); + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_features.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_features.c new file mode 100644 index 0000000000..cbdc39586f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_features.c @@ -0,0 +1,18 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +int ADIOI_GRIDFTP_Feature (ADIO_File fd, int flag) +{ + switch(flag) { + case ADIO_SCALABLE_OPEN: + case ADIO_SHARED_FP: + case ADIO_LOCKS: + case ADIO_SEQUENTIAL: + case ADIO_DATA_SIEVING_WRITES: + default: + return 0; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_flush.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_flush.c new file mode 100644 index 0000000000..795341e888 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_flush.c @@ -0,0 +1,19 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gridftp.h" +#include "adioi.h" + +/* GridFTP doesn't give you a way to cache writes on the client side, so + is essentially a no-op */ +/* if there is a mechanism where we can ask the server to flush data to disk we + * should do it here. I'll leave that up to Troy */ + +void ADIOI_GRIDFTP_Flush(ADIO_File fd, int *error_code) +{ + return; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_hints.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_hints.c new file mode 100644 index 0000000000..c0b0a40ebb --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_hints.c @@ -0,0 +1,68 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +/* + +Valid hints for ftp:// and gsiftp:// URLs (aside from the std. ones): + + ftp_control_mode extended|block|stream|compressed + (default extended for gsiftp:// URLs and stream for ftp:// URLs) + + parallelism integer number of simultaneous threads connecting to + ftp server (default 1) + + striped_ftp true|false or enable|disable; enables gsiftp striped data transfer + + tcp_buffer integer size of tcp stream buffers in bytes + + transfer_type ascii or binary (default binary) + +These *must* be specified at open time currently. +*/ + +#include "ad_gridftp.h" +#include "adioi.h" + +void ADIOI_GRIDFTP_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ + + if (!(fd->info)) + { + if ( users_info==MPI_INFO_NULL ) + { + /* This must be part of the open call. */ + MPI_Info_create(&(fd->info)); + } + else + { + MPI_Info_dup(users_info,&(fd->info)); + } + } + else + { + int i,nkeys,valuelen,flag; + char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL]; + + if ( users_info!=MPI_INFO_NULL ) + { + MPI_Info_get_nkeys(users_info,&nkeys); + for (i=0;iinfo,key,value); + } + } + } + } + + /* let the generic ROMIO and MPI-I/O stuff happen... */ + ADIOI_GEN_SetInfo(fd, users_info, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_open.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_open.c new file mode 100644 index 0000000000..45aab92105 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_open.c @@ -0,0 +1,343 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gridftp.h" +#include "adioi.h" + +static globus_mutex_t lock; +static globus_cond_t cond; + +static globus_bool_t file_exists,exists_done; +static void exists_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error) +{ + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + else + { + file_exists=GLOBUS_TRUE; + } + exists_done=GLOBUS_TRUE; +} + +static globus_bool_t touch_ctl_done; +static void touch_ctl_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error) +{ + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + globus_mutex_lock(&lock); + touch_ctl_done=GLOBUS_TRUE; + globus_cond_signal(&cond); + globus_mutex_unlock(&lock); +} + +static void touch_data_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error, + globus_byte_t *buffer, globus_size_t length, globus_off_t offset, + globus_bool_t eof) +{ + if (error) + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + globus_ftp_client_register_read(handle,buffer,length,touch_data_cb,myargs); + return; +} + +void ADIOI_GRIDFTP_Open(ADIO_File fd, int *error_code) +{ + static char myname[]="ADIOI_GRIDFTP_Open"; + int myrank, nprocs, keyfound; + char hintval[MPI_MAX_INFO_VAL+1]; + globus_ftp_client_handleattr_t hattr; + globus_result_t result; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + /* activate Globus ftp client module -- can be called multiple times, so + it's safest to call once per file/connection */ + globus_module_activate(GLOBUS_FTP_CLIENT_MODULE); + fd->fd_sys = num_gridftp_handles; + /* No shared file pointers for now */ + fd->shared_fp_fname = NULL; + *error_code = MPI_SUCCESS; + + /* Access modes here mean something very different here than they + would on a "real" filesystem... As a result, the amode and hint + processing here is intermingled and a little weird because many + of them have to do with the connection rather than the file itself. + The thing that sucks about this is that read and write ops will + have to check themselves if the file is being accessed rdonly, rdwr, + or wronly. + */ + result=globus_ftp_client_handleattr_init(&hattr); + if ( result != GLOBUS_SUCCESS ) + { + + + globus_err_handler("globus_ftp_client_handleattr_init", + myname,result); + fd->fd_sys = -1; + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + result = globus_ftp_client_operationattr_init(&(oattr[fd->fd_sys])); + if ( result != GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_operationattr_init", + myname,result); + fd->fd_sys = -1; + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + + + /* Always use connection caching unless told otherwise */ + result=globus_ftp_client_handleattr_set_cache_all(&hattr,GLOBUS_TRUE); + if ( result !=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_handleattr_set_cache_all",myname,result); + + /* Assume that it's safe to cache a file if it's read-only */ + if ( (fd->access_mode&ADIO_RDONLY) && + (result=globus_ftp_client_handleattr_add_cached_url(&hattr,fd->filename))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_handleattr_add_cached_url",myname,result); + + /* Since we're (almost by definition) doing things that FTP S (stream) + control mode can't handle, default to E (extended block) control mode + for gsiftp:// URLs. ftp:// URLs use standard stream control mode + by default. This behavior can be overridden by the ftp_control_mode + hint. */ + + /* + if ( !strncmp(fd->filename,"gsiftp:",7) && + (result=globus_ftp_client_operationattr_set_mode(&(oattr[fd->fd_sys]),GLOBUS_FTP_CONTROL_MODE_EXTENDED_BLOCK))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_mode",myname,result); + else if ( !strncmp(fd->filename,"ftp:",4) && + (result=globus_ftp_client_operationattr_set_mode(&(oattr[fd->fd_sys]),GLOBUS_FTP_CONTROL_MODE_STREAM))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_mode",myname,result); + */ + + /* Set append mode if necessary */ + if ( (fd->access_mode&ADIO_APPEND) && + ((result=globus_ftp_client_operationattr_set_append(&(oattr[fd->fd_sys]),GLOBUS_TRUE))!=GLOBUS_SUCCESS) ) + globus_err_handler("globus_ftp_client_operationattr_set_append",myname,result); + + /* Other hint and amode processing that would affect hattr and/or + oattr[] (eg. parallelism, striping, etc.) goes here */ + if ( fd->info!=MPI_INFO_NULL ) + { + ADIOI_Info_get(fd->info,"ftp_control_mode",MPI_MAX_INFO_VAL,hintval,&keyfound); + if ( keyfound ) + { + if ( ( !strcmp(hintval,"extended") || !strcmp(hintval,"extended_block") ) && + (result=globus_ftp_client_operationattr_set_mode(&(oattr[fd->fd_sys]),GLOBUS_FTP_CONTROL_MODE_EXTENDED_BLOCK))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_mode",myname,result); + else if ( !strcmp(hintval,"block") && + (result=globus_ftp_client_operationattr_set_mode(&(oattr[fd->fd_sys]),GLOBUS_FTP_CONTROL_MODE_BLOCK))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_mode",myname,result); + else if ( !strcmp(hintval,"compressed") && + (result=globus_ftp_client_operationattr_set_mode(&(oattr[fd->fd_sys]),GLOBUS_FTP_CONTROL_MODE_COMPRESSED))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_mode",myname,result); + else if ( !strcmp(hintval,"stream") && + (result=globus_ftp_client_operationattr_set_mode(&(oattr[fd->fd_sys]),GLOBUS_FTP_CONTROL_MODE_STREAM))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_mode",myname,result); + } + + ADIOI_Info_get(fd->info,"parallelism",MPI_MAX_INFO_VAL,hintval,&keyfound); + if ( keyfound ) + { + int nftpthreads; + + if ( sscanf(hintval,"%d",&nftpthreads)==1 ) + { + globus_ftp_control_parallelism_t parallelism; + + parallelism.mode = GLOBUS_FTP_CONTROL_PARALLELISM_FIXED; + parallelism.fixed.size = nftpthreads; + if ( (result=globus_ftp_client_operationattr_set_parallelism(&(oattr[fd->fd_sys]), + ¶llelism))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_parallelism",myname,result); + } + } + + ADIOI_Info_get(fd->info,"striped_ftp",MPI_MAX_INFO_VAL,hintval,&keyfound); + if ( keyfound ) + { + /* if set to "true" or "enable", set up round-robin block layout */ + if ( !strncmp("true",hintval,4) || !strncmp("TRUE",hintval,4) || + !strncmp("enable",hintval,4) || !strncmp("ENABLE",hintval,4) ) + { + ADIOI_Info_get(fd->info,"striping_factor",MPI_MAX_INFO_VAL,hintval,&keyfound); + if ( keyfound ) + { + int striping_factor; + + if ( sscanf(hintval,"%d",&striping_factor)==1 ) + { + globus_ftp_control_layout_t layout; + + layout.mode = GLOBUS_FTP_CONTROL_STRIPING_BLOCKED_ROUND_ROBIN; + layout.round_robin.block_size = striping_factor; + if ( (result=globus_ftp_client_operationattr_set_layout(&(oattr[fd->fd_sys]), + &layout))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_layout", + myname,result); + } + } + } + } + + ADIOI_Info_get(fd->info,"tcp_buffer",MPI_MAX_INFO_VAL,hintval,&keyfound); + if ( keyfound ) + { + /* set tcp buffer size */ + int buffer_size; + if ( sscanf(hintval,"%d",&buffer_size)==1 ) + { + globus_ftp_control_tcpbuffer_t tcpbuf; + + tcpbuf.mode = GLOBUS_FTP_CONTROL_TCPBUFFER_FIXED; + tcpbuf.fixed.size = buffer_size; + if ( (result=globus_ftp_client_operationattr_set_tcp_buffer(&(oattr[fd->fd_sys]), + &tcpbuf))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_tcp_buffer",myname,result); + } + } + + ADIOI_Info_get(fd->info,"transfer_type",MPI_MAX_INFO_VAL,hintval,&keyfound); + if ( keyfound ) + { + globus_ftp_control_type_t filetype; + /* set transfer type (i.e. ASCII or binary) */ + if ( !strcmp("ascii",hintval) || !strcmp("ASCII",hintval) ) + { + filetype=GLOBUS_FTP_CONTROL_TYPE_ASCII; + } + else + { + filetype=GLOBUS_FTP_CONTROL_TYPE_IMAGE; + } + if ( (result=globus_ftp_client_operationattr_set_type(&(oattr[fd->fd_sys]),filetype))!=GLOBUS_SUCCESS ) + globus_err_handler("globus_ftp_client_operationattr_set_type",myname,result); + } + } + else + FPRINTF(stderr,"no MPI_Info object associated with %s\n",fd->filename); + + /* Create the ftp handle */ + result=globus_ftp_client_handle_init(&(gridftp_fh[fd->fd_sys]),&hattr); + if ( result != GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_handle_init",myname,result); + fd->fd_sys = -1; + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + + /* Check for existence of the file */ + globus_mutex_init(&lock, GLOBUS_NULL); + globus_cond_init(&cond, GLOBUS_NULL); + file_exists=GLOBUS_FALSE; + exists_done=GLOBUS_FALSE; + if ( myrank==0 ) + { + if ( (result=globus_ftp_client_exists(&(gridftp_fh[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + exists_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_exists",myname,result); + fd->fd_sys = -1; + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + /* wait till the callback completes */ + globus_mutex_lock(&lock); + while ( exists_done!=GLOBUS_TRUE ) + globus_cond_wait(&cond,&lock); + globus_mutex_unlock(&lock); + } + MPI_Barrier(fd->comm); + MPI_Bcast(&file_exists,1,MPI_INT,0,fd->comm); + + /* It turns out that this is handled by MPI_File_open() directly */ + if ( (file_exists!=GLOBUS_TRUE) && (fd->access_mode&ADIO_CREATE) && + !(fd->access_mode&ADIO_EXCL) && !(fd->access_mode&ADIO_RDONLY) ) + { + if ( myrank==0 ) + { + /* if the file doesn't exist, write a single NULL to it */ + globus_byte_t touchbuf=(globus_byte_t)'\0'; + touch_ctl_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_put(&(gridftp_fh[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + GLOBUS_NULL, + touch_ctl_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_put",myname,result); + fd->fd_sys = -1; + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + result=globus_ftp_client_register_write(&(gridftp_fh[fd->fd_sys]), + (globus_byte_t *)&touchbuf, 0, + (globus_off_t)0, GLOBUS_TRUE, + touch_data_cb, GLOBUS_NULL); + + if ( result != GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_register_write",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + globus_mutex_lock(&lock); + while ( touch_ctl_done!=GLOBUS_TRUE ) + globus_cond_wait(&cond,&lock); + globus_mutex_unlock(&lock); + } + MPI_Barrier(fd->comm); + } + else if ( (fd->access_mode&ADIO_EXCL) && (file_exists==GLOBUS_TRUE) ) + { + fd->fd_sys = -1; + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", 0); + return; + } + else if ( (fd->access_mode&ADIO_RDONLY) && (file_exists!=GLOBUS_TRUE) ) + { + if ( myrank==0 ) + { + FPRINTF(stderr,"WARNING: read-only file %s does not exist!\n",fd->filename); + } + } + num_gridftp_handles++; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_read.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_read.c new file mode 100644 index 0000000000..6a0fc9c7c4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_read.c @@ -0,0 +1,468 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gridftp.h" +#include "adioi.h" +#include "adio_extern.h" + +static globus_mutex_t readcontig_ctl_lock; +static globus_cond_t readcontig_ctl_cond; +static globus_bool_t readcontig_ctl_done; +static void readcontig_ctl_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error) +{ + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + globus_mutex_lock(&readcontig_ctl_lock); + if ( readcontig_ctl_done!=GLOBUS_TRUE ) + readcontig_ctl_done=GLOBUS_TRUE; + globus_cond_signal(&readcontig_ctl_cond); + globus_mutex_unlock(&readcontig_ctl_lock); + return; +} + +static void readcontig_data_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error, + globus_byte_t *buffer, globus_size_t length, globus_off_t offset, + globus_bool_t eof) +{ + globus_size_t *bytes_read; + + bytes_read=(globus_size_t *)myargs; + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + *bytes_read+=length; + /* I don't understand why the data callback has to keep recalling register_read, + but everything I've done and all the examples I've seen seem to require + that behavior to work... */ + /* + * Using buffer+length seems to work, but is probably not the correct + * solution. A big read of 256kB chunks will have lines like this: + readcontig_data_cb: buffer 0x404e0008 length 0 offset 31719424 eof 1 + readcontig_data_cb: buffer 0x404a0008 length 65536 offset 31981568 eof 0 + readcontig_data_cb: buffer 0x404b0008 length 65536 offset 32047104 eof 0 + readcontig_data_cb: buffer 0x404c0008 length 65536 offset 32112640 eof 0 + readcontig_data_cb: buffer 0x404d0008 length 65536 offset 32178176 eof 0 + */ + if ( !eof ) + globus_ftp_client_register_read(handle, + buffer+length, + length, + readcontig_data_cb, + (void *)(bytes_read)); + return; +} + +static globus_mutex_t readdiscontig_ctl_lock; +static globus_cond_t readdiscontig_ctl_cond; +static globus_bool_t readdiscontig_ctl_done; +static void readdiscontig_ctl_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error) +{ + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + globus_mutex_lock(&readdiscontig_ctl_lock); + if ( readdiscontig_ctl_done!=GLOBUS_TRUE ) + readdiscontig_ctl_done=GLOBUS_TRUE; + globus_cond_signal(&readdiscontig_ctl_cond); + globus_mutex_unlock(&readdiscontig_ctl_lock); + return; +} + +static void readdiscontig_data_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error, + globus_byte_t *buffer, globus_size_t length, globus_off_t offset, + globus_bool_t eof) +{ + globus_size_t *bytes_read; + + bytes_read=(globus_size_t *)myargs; + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + *bytes_read+=length; + /* I don't understand why the data callback has to keep recalling register_read, + but everything I've done and all the examples I've seen seem to require + that behavior to work... */ + if ( !eof ) + globus_ftp_client_register_read(handle, + buffer, + length, + readdiscontig_data_cb, + (void *)(bytes_read)); + return; +} + +void ADIOI_GRIDFTP_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ + static char myname[]="ADIOI_GRIDFTP_ReadContig"; + int myrank, nprocs; + MPI_Count datatype_size; + globus_size_t len,bytes_read=0; + globus_off_t goff; + globus_result_t result; + + if ( fd->access_mode&ADIO_WRONLY ) + { + *error_code=MPIR_ERR_MODE_WRONLY; + return; + } + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + MPI_Type_size_x(datatype, &datatype_size); + + if (file_ptr_type != ADIO_EXPLICIT_OFFSET) + { + offset = fd->fp_ind; + } + + /* Do the gridftp I/O transfer */ + goff = (globus_off_t)offset; + len = ((globus_size_t)datatype_size)*((globus_size_t)count); + + globus_mutex_init(&readcontig_ctl_lock, GLOBUS_NULL); + globus_cond_init(&readcontig_ctl_cond, GLOBUS_NULL); + readcontig_ctl_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_partial_get(&(gridftp_fh[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + GLOBUS_NULL, + goff, + goff+(globus_off_t)len, + readcontig_ctl_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_partial_get",myname,result); + *error_code=MPI_ERR_IO; + ADIOI_Error(fd,*error_code,myname); + return; + } + result=globus_ftp_client_register_read(&(gridftp_fh[fd->fd_sys]), + (globus_byte_t *)buf, len, readcontig_data_cb, + (void *)(&bytes_read)); + if ( result != GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_register_read",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + + + /* The ctl callback won't start till the data callbacks complete, so it's + safe to wait on just the ctl callback */ + globus_mutex_lock(&readcontig_ctl_lock); + while ( readcontig_ctl_done!=GLOBUS_TRUE ) + globus_cond_wait(&readcontig_ctl_cond,&readcontig_ctl_lock); + globus_mutex_unlock(&readcontig_ctl_lock); + + globus_mutex_destroy(&readcontig_ctl_lock); + globus_cond_destroy(&readcontig_ctl_cond); + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bytes_read); +#endif + if (file_ptr_type != ADIO_EXPLICIT_OFFSET) + { + fd->fp_ind += bytes_read; + fd->fp_sys_posn = fd->fp_ind; + } + else { + fd->fp_sys_posn = offset + bytes_read; + } +} + +void ADIOI_GRIDFTP_ReadDiscontig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ + char myname[]="ADIOI_GRIDFTP_ReadDiscontig"; + int myrank,nprocs; + /* size and extent of buffer in memory */ + MPI_Aint btype_size,btype_extent; + /* size and extent of file record layout */ + MPI_Aint ftype_size,ftype_extent; + /* size of file elemental type; seeks are done in units of this */ + MPI_Aint etype_size; + MPI_Aint extent; + ADIOI_Flatlist_node *flat_file; + int i,buf_contig,boff,nblks; + globus_off_t start,end,goff; + globus_size_t bytes_read; + globus_result_t result; + globus_byte_t *tmp; + + if ( fd->access_mode&ADIO_WRONLY ) + { + *error_code=MPIR_ERR_MODE_WRONLY; + return; + } + + *error_code=MPI_SUCCESS; + + MPI_Comm_rank(fd->comm,&myrank); + MPI_Comm_size(fd->comm,&nprocs); + + etype_size=fd->etype_size; + MPI_Type_size_x(fd->filetype,&ftype_size); + MPI_Type_extent(fd->filetype,&ftype_extent); + /* This is arguably unnecessary, as this routine assumes that the + buffer in memory is contiguous */ + MPI_Type_size_x(datatype,&btype_size); + MPI_Type_extent(datatype,&btype_extent); + ADIOI_Datatype_iscontig(datatype,&buf_contig); + + if ( ( btype_extent!=btype_size ) || ( ! buf_contig ) ) + { + FPRINTF(stderr,"[%d/%d] %s called with discontigous memory buffer\n", + myrank,nprocs,myname); + fflush(stderr); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", 0 ); + return; + } + /* from here we can assume btype_extent==btype_size */ + + /* Flatten out fd->filetype so we know which blocks to skip */ + ADIOI_Flatten_datatype(fd->filetype); + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype && flat_file->next!=NULL) + flat_file = flat_file->next; + + /* Figure out how big the area to read is */ + start=(globus_off_t)(offset*etype_size); + goff=start; + boff=0; + extent=0; + nblks=0; + while ( boff < (count*btype_size) ) + { + int blklen=0; + + for (i=0;icount;i++) + { + /* find the length of the next block */ + if ( (boff+flat_file->blocklens[i]) < (count*btype_size) ) + blklen=flat_file->blocklens[i]; + else + blklen=(count*btype_size)-boff; + /* increment buffer size to be used */ + boff+=blklen; + /* compute extent -- the nblks*ftype_extent bit is + there so we remember how many ftypes we've already + been through */ + extent=MAX(extent,nblks*ftype_extent+flat_file->indices[i]+blklen); + if ( boff>=(count*btype_size) ) + break; + } + nblks++; + } + if ( extent < count*btype_size ) + { + FPRINTF(stderr,"[%d/%d] %s error in computing extent -- extent %d is smaller than total bytes requested %d!\n", + myrank,nprocs,myname,extent,count*btype_size); + fflush(stderr); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", 0); + return; + } + end=start+(globus_off_t)extent; + tmp=(globus_byte_t *)ADIOI_Malloc((size_t)extent*sizeof(globus_byte_t)); + + /* start up the globus partial read */ + globus_mutex_init(&readdiscontig_ctl_lock, GLOBUS_NULL); + globus_cond_init(&readdiscontig_ctl_cond, GLOBUS_NULL); + readdiscontig_ctl_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_partial_get(&(gridftp_fh[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + GLOBUS_NULL, + start, + end, + readdiscontig_ctl_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_partial_get",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + + /* Do all the actual I/Os */ + /* Since globus_ftp_client_register_read() is brain-dead and doesn't + let you specify an offset, we have to slurp the entire extent into + memory and then parse out the pieces we want... Sucks, doesn't it? + + This should probably be done in chunks (preferably of a size + set using a file hint), but that'll have to come later. + --TB */ + if ( (result=globus_ftp_client_register_read(&(gridftp_fh[fd->fd_sys]), + tmp, + (globus_size_t)extent, + readdiscontig_data_cb, + (void *)(&bytes_read)))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_register_read",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + /* The ctl callback won't start till the data callbacks complete, so it's + safe to wait on just the ctl callback */ + globus_mutex_lock(&readdiscontig_ctl_lock); + while ( readdiscontig_ctl_done!=GLOBUS_TRUE ) + globus_cond_wait(&readdiscontig_ctl_cond,&readdiscontig_ctl_lock); + globus_mutex_unlock(&readdiscontig_ctl_lock); + + globus_mutex_destroy(&readdiscontig_ctl_lock); + globus_cond_destroy(&readdiscontig_ctl_cond); + + boff=0; + nblks=0; + goff=0; + while ( boff < (count*btype_size) ) + { + int i,blklen; + + for (i=0;icount;i++) + { + if ( (boff+flat_file->blocklens[i]) < (count*btype_size) ) + blklen=flat_file->blocklens[i]; + else + blklen=(count*btype_size)-boff; + if ( blklen > 0 ) + { + goff=nblks*ftype_extent+flat_file->indices[i]; + memcpy((globus_byte_t *)buf+boff,tmp+goff,(size_t)blklen); + boff+=blklen; + if ( boff>=(count*btype_size) ) + break; + } + } + nblks++; + } + ADIOI_Free(tmp); + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bytes_read); +#endif + if (file_ptr_type != ADIO_EXPLICIT_OFFSET) + { + fd->fp_ind += extent; + fd->fp_sys_posn = fd->fp_ind; + } + else { + fd->fp_sys_posn = offset + extent; + } +} + +void ADIOI_GRIDFTP_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ + /* + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); +#ifdef PRINT_ERR_MSG + FPRINTF(stdout, "[%d/%d] ADIOI_GRIDFTP_ReadStrided called on %s\n", myrank, + nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_GEN_ReadStrided\n", myrank, + nprocs); +#endif + + ADIOI_GEN_ReadStrided(fd, buf, count, datatype, file_ptr_type, offset, + status, error_code); + + */ + + char myname[]="ADIOI_GRIDFTP_ReadStrided"; + int myrank, nprocs; + int i,j; + int buf_contig,file_contig; + MPI_Aint btype_size,bufsize; + globus_off_t start,disp; + globus_size_t bytes_read; + globus_byte_t *intermediate; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + MPI_Type_size_x(datatype,&btype_size); + bufsize=count*btype_size; + ADIOI_Datatype_iscontig(fd->filetype,&file_contig); + ADIOI_Datatype_iscontig(datatype,&buf_contig); + if ( buf_contig && !file_contig ) + { + /* Contiguous in memory, discontig in file */ + ADIOI_GRIDFTP_ReadDiscontig(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + } + else if ( !buf_contig && file_contig ) + { + /* Discontiguous in mem, contig in file -- comparatively easy */ + int posn=0; + + /* read contiguous data into intermediate buffer */ + intermediate=(globus_byte_t *)ADIOI_Malloc((size_t)bufsize); + ADIOI_GRIDFTP_ReadContig(fd, intermediate, bufsize, MPI_BYTE, + file_ptr_type, offset, status, error_code); + + /* explode contents of intermediate buffer into main buffer */ + MPI_Unpack(intermediate,bufsize,&posn,buf,count,datatype,fd->comm); + + ADIOI_Free(intermediate); + } + else if ( !buf_contig && !file_contig ) + { + /* Discontig in both mem and file -- the hardest case */ + int posn=0; + + /* Read discontiguous data into intermediate buffer */ + intermediate=(globus_byte_t *)ADIOI_Malloc((size_t)bufsize); + ADIOI_GRIDFTP_ReadDiscontig(fd, intermediate, bufsize, MPI_BYTE, + file_ptr_type, offset, status, error_code); + + /* explode contents of intermediate buffer into main buffer */ + posn=0; + MPI_Unpack(intermediate,bufsize,&posn,buf,count,datatype,fd->comm); + + ADIOI_Free(intermediate); + } + else + { + /* Why did you bother calling ReadStrided?!?!?! */ + ADIOI_GRIDFTP_ReadContig(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + } + +} + diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_resize.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_resize.c new file mode 100644 index 0000000000..96c0460c42 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_resize.c @@ -0,0 +1,241 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gridftp.h" +#include "adioi.h" + +static globus_mutex_t resize_lock; +static globus_cond_t resize_cond; +static globus_bool_t resize_done; +static globus_bool_t resize_success; + +void resize_cb(void *myargs, globus_ftp_client_handle_t *handle, + globus_object_t *error) +{ + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + globus_mutex_lock(&resize_lock); + resize_success=GLOBUS_FALSE; + globus_mutex_unlock(&resize_lock); + } + else + { + globus_mutex_lock(&resize_lock); + resize_success=GLOBUS_TRUE; + globus_mutex_unlock(&resize_lock); + } + globus_mutex_lock(&resize_lock); + resize_done=GLOBUS_TRUE; + globus_cond_signal(&resize_cond); + globus_mutex_unlock(&resize_lock); +} + + +static void resize_wrdata_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error, + globus_byte_t *buffer, globus_size_t length, globus_off_t offset, + globus_bool_t eof) +{ + if (error) + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + if (!eof) + globus_ftp_client_register_read(handle, + buffer, + length, + resize_wrdata_cb, + myargs); + return; +} + + +void ADIOI_GRIDFTP_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int myrank, nprocs; + char myname[]="ADIOI_GRIDFTP_Resize"; + globus_off_t fsize; + globus_result_t result; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + /* Sanity check */ + if ( fd->access_mode&ADIO_RDONLY ) + { + FPRINTF(stderr,"%s: attempt to resize read-only file %s!\n", + myname,fd->filename); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", 0); + return; + } + + /* This routine is supposed to do the moral equivalent of truncate(), + but there's not an equivalent operation in the globus_ftp_client API. */ + globus_mutex_init(&resize_lock,GLOBUS_NULL); + globus_cond_init(&resize_cond,GLOBUS_NULL); + resize_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_size(&(gridftp_fh[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + &(fsize), + resize_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_size",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + globus_mutex_lock(&resize_lock); + while ( resize_done!=GLOBUS_TRUE ) + globus_cond_wait(&resize_lock,&resize_cond); + if ( fsize < (globus_off_t)size ) + { + /* The file is smaller than the requested size, so + do a zero-byte write to where the new EOF should be. */ + globus_byte_t touchbuf=(globus_byte_t)'\0'; + resize_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_partial_put(&(gridftp_fh[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + GLOBUS_NULL, + (globus_off_t)size, + (globus_off_t)size, + resize_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_partial_put",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + + if ( (result=globus_ftp_client_register_write(&(gridftp_fh[fd->fd_sys]), + (globus_byte_t *)&touchbuf, + 0, + (globus_off_t)0, + GLOBUS_TRUE, + resize_wrdata_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_register_write",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + globus_mutex_lock(&resize_lock); + while ( resize_done!=GLOBUS_TRUE ) + globus_cond_wait(&resize_cond,&resize_lock); + globus_mutex_unlock(&resize_lock); + } + else if ( fsize > (globus_off_t)size ) + { + /* The file is bigger than the requested size, so + we'll abuse globus_ftp_client_third_party_partial_put() + into truncating it for us. */ + char *urlold; + size_t urllen; + + urllen=strlen(fd->filename); + urlold=(char *)ADIOI_Malloc(urllen+5); + ADIOI_Snprintf(urlold,urllen+5,"%s.old",fd->filename); + resize_done=GLOBUS_FALSE; + resize_success=GLOBUS_FALSE; + if ( (result=globus_ftp_client_move(&(gridftp_fh[fd->fd_sys]), + fd->filename, + urlold, + &(oattr[fd->fd_sys]), + resize_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_move",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + globus_mutex_lock(&resize_lock); + while ( resize_done!=GLOBUS_TRUE ) + globus_cond_wait(&resize_cond,&resize_lock); + globus_mutex_unlock(&resize_lock); + if ( resize_success!=GLOBUS_TRUE ) + { + *error_code = MPI_ERR_IO; + return; + } + resize_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_partial_third_party_transfer(&(gridftp_fh[fd->fd_sys]), + urlold, + &(oattr[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + GLOBUS_NULL, + 0, + (globus_off_t)size, + resize_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_partial_third_party_transfer",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + globus_mutex_lock(&resize_lock); + while ( resize_done!=GLOBUS_TRUE ) + globus_cond_wait(&resize_cond,&resize_lock); + globus_mutex_unlock(&resize_lock); + if ( resize_success!=GLOBUS_TRUE ) + { + *error_code = MPI_ERR_IO; + ADIOI_Error(fd,*error_code,myname); + return; + } + resize_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_delete(&(gridftp_fh[fd->fd_sys]), + urlold, + &(oattr[fd->fd_sys]), + resize_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_delete",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", "**io %s", + globus_object_printable_to_string(globus_error_get(result))); + return; + } + globus_mutex_lock(&resize_lock); + while ( resize_done!=GLOBUS_TRUE ) + globus_cond_wait(&resize_cond,&resize_lock); + globus_mutex_unlock(&resize_lock); + if ( resize_success!=GLOBUS_TRUE ) + { + *error_code = MPI_ERR_IO; + ADIOI_Error(fd,*error_code,myname); + return; + } + ADIOI_Free(urlold); + } + globus_mutex_destroy(&resize_lock); + globus_cond_destroy(&resize_cond); +} + + + + + diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_write.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_write.c new file mode 100644 index 0000000000..0400dae30b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/ad_gridftp_write.c @@ -0,0 +1,473 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_gridftp.h" +#include "adioi.h" +#include "adio_extern.h" + +static globus_mutex_t writecontig_ctl_lock; +static globus_cond_t writecontig_ctl_cond; +static globus_bool_t writecontig_ctl_done; +static void writecontig_ctl_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error) +{ + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + globus_mutex_lock(&writecontig_ctl_lock); + if ( writecontig_ctl_done!=GLOBUS_TRUE ) + writecontig_ctl_done=GLOBUS_TRUE; + globus_cond_signal(&writecontig_ctl_cond); + globus_mutex_unlock(&writecontig_ctl_lock); +#ifdef PRINT_ERR_MSG + FPRINTF(stderr,"finished with contig write transaction\n"); +#endif /* PRINT_ERR_MSG */ + return; +} + +static void writecontig_data_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error, + globus_byte_t *buffer, globus_size_t length, globus_off_t offset, + globus_bool_t eof) +{ + globus_size_t *bytes_written; + + bytes_written=(globus_size_t *)myargs; + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + *bytes_written+=length; + /* I don't understand why the data callback has to keep recalling register_write, + but everything I've done and all the examples I've seen seem to require + that behavior to work... */ + if ( !eof ) + { + globus_ftp_client_register_write(handle, + buffer, + length, + offset, + GLOBUS_TRUE, + writecontig_data_cb, + (void *)(bytes_written)); + } +#ifdef PRINT_ERR_MSG + FPRINTF(stderr,"wrote %Ld bytes...",(long long)length); +#endif /* PRINT_ERR_MSG */ + return; +} + + +static globus_mutex_t writediscontig_ctl_lock; +static globus_cond_t writediscontig_ctl_cond; +static globus_bool_t writediscontig_ctl_done; +static void writediscontig_ctl_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error) +{ + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + globus_mutex_lock(&writediscontig_ctl_lock); + if ( writediscontig_ctl_done!=GLOBUS_TRUE ) + writediscontig_ctl_done=GLOBUS_TRUE; + globus_cond_signal(&writediscontig_ctl_cond); + globus_mutex_unlock(&writediscontig_ctl_lock); + return; +} + +static void writediscontig_data_cb(void *myargs, globus_ftp_client_handle_t *handle, globus_object_t *error, + globus_byte_t *buffer, globus_size_t length, globus_off_t offset, + globus_bool_t eof) +{ + globus_size_t *bytes_written; + + bytes_written=(globus_size_t *)myargs; + if (error) + { + FPRINTF(stderr, "%s\n", globus_object_printable_to_string(error)); + } + *bytes_written+=length; + /* I don't understand why the data callback has to keep recalling register_read, + but everything I've done and all the examples I've seen seem to require + that behavior to work... */ + if ( !eof ) + globus_ftp_client_register_write(handle, + buffer, + length, + offset, + eof, + writediscontig_data_cb, + (void *)(bytes_written)); + FPRINTF(stderr,"wrote %Ld bytes...",(long long)length); + return; +} + + +void ADIOI_GRIDFTP_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ + char myname[]="ADIOI_GRIDFTP_WriteContig"; + int myrank, nprocs; + MPI_Count datatype_size; + globus_size_t len,bytes_written=0; + globus_off_t goff; + globus_result_t result; + + if ( fd->access_mode&ADIO_RDONLY ) + { + *error_code=MPI_ERR_AMODE; + return; + } + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + MPI_Type_size_x(datatype, &datatype_size); + + if (file_ptr_type != ADIO_EXPLICIT_OFFSET) + { + offset = fd->fp_ind; + } + + /* Do the gridftp I/O transfer */ + goff = (globus_off_t)offset; + len = ((globus_size_t)datatype_size)*((globus_size_t)count); + + globus_mutex_init(&writecontig_ctl_lock, GLOBUS_NULL); + globus_cond_init(&writecontig_ctl_cond, GLOBUS_NULL); + writecontig_ctl_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_partial_put(&(gridftp_fh[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + GLOBUS_NULL, + goff, + goff+(globus_off_t)len, + writecontig_ctl_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_partial_put",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + if ( (result=globus_ftp_client_register_write(&(gridftp_fh[fd->fd_sys]), + (globus_byte_t *)buf, + len, + goff, + GLOBUS_TRUE, + writecontig_data_cb, + (void *)(&bytes_written)))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_register_write",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + + + /* The ctl callback won't start till the data callbacks complete, so it's + safe to wait on just the ctl callback */ + globus_mutex_lock(&writecontig_ctl_lock); + while ( writecontig_ctl_done!=GLOBUS_TRUE ) + globus_cond_wait(&writecontig_ctl_cond,&writecontig_ctl_lock); + globus_mutex_unlock(&writecontig_ctl_lock); + + globus_mutex_destroy(&writecontig_ctl_lock); + globus_cond_destroy(&writecontig_ctl_cond); + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bytes_written); +#endif + if (file_ptr_type != ADIO_EXPLICIT_OFFSET) + { + offset = fd->fp_ind; + fd->fp_ind += bytes_written; + fd->fp_sys_posn = fd->fp_ind; + } + else { + fd->fp_sys_posn = offset + bytes_written; + } +} + + +void ADIOI_GRIDFTP_WriteDiscontig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ + char myname[]="ADIOI_GRIDFTP_WriteDiscontig"; + int myrank,nprocs; + MPI_Aint btype_size,btype_extent; + MPI_Aint ftype_size,ftype_extent; + MPI_Aint etype_size; + MPI_Aint extent; + ADIOI_Flatlist_node *flat_file; + int buf_contig,boff,i,nblks; + globus_off_t start,end,goff; + globus_size_t bytes_written; + globus_result_t result; + + MPI_Comm_rank(fd->comm,&myrank); + MPI_Comm_size(fd->comm,&nprocs); + etype_size=fd->etype_size; + MPI_Type_size_x(fd->filetype,&ftype_size); + MPI_Type_extent(fd->filetype,&ftype_extent); + /* This is arguably unnecessary, as this routine assumes that the + buffer in memory is contiguous */ + MPI_Type_size_x(datatype,&btype_size); + MPI_Type_extent(datatype,&btype_extent); + ADIOI_Datatype_iscontig(datatype,&buf_contig); + + if ( ( btype_extent!=btype_size ) || ( ! buf_contig ) ) + { + FPRINTF(stderr,"[%d/%d] %s called with discontigous memory buffer\n", + myrank,nprocs,myname); + fflush(stderr); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + /* from here we can assume btype_extent==btype_size */ + + /* Flatten out fd->filetype so we know which blocks to skip */ + ADIOI_Flatten_datatype(fd->filetype); + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype && flat_file->next!=NULL) + flat_file = flat_file->next; + + /* Figure out how big the area to write is */ + /* ASSUMPTION: ftype_size is an integer multiple of btype_size or vice versa. */ + start=(globus_off_t)(offset*etype_size); + goff=start; + boff=0; + extent=0; + nblks=0; + while ( boff < (count*btype_size) ) + { + int blklen; + + for (i=0;icount;i++) + { + if ( (boff+flat_file->blocklens[i]) < (count*btype_size) ) + blklen=flat_file->blocklens[i]; + else + blklen=(count*btype_size)-boff; + boff+=blklen; + extent=MAX(extent,nblks*ftype_extent+flat_file->indices[i]+blklen); + if ( boff>=(count*btype_size) ) + break; + } + nblks++; + } + if ( extent < count*btype_size ) + { + FPRINTF(stderr,"[%d/%d] %s error in computing extent -- extent %d is smaller than total bytes requested %d!\n", + myrank,nprocs,myname,extent,count*btype_size); + fflush(stderr); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + end=start+(globus_off_t)extent; + FPRINTF(stderr,"[%d/%d] %s writing %d bytes into extent of %d bytes starting at offset %Ld\n", + myrank,nprocs,myname,count*btype_size,extent,(long long)start); + fflush(stderr); + + /* start up the globus partial write */ + globus_mutex_init(&writediscontig_ctl_lock, GLOBUS_NULL); + globus_cond_init(&writediscontig_ctl_cond, GLOBUS_NULL); + writediscontig_ctl_done=GLOBUS_FALSE; + if ( (result=globus_ftp_client_partial_put(&(gridftp_fh[fd->fd_sys]), + fd->filename, + &(oattr[fd->fd_sys]), + GLOBUS_NULL, + start, + end, + writediscontig_ctl_cb, + GLOBUS_NULL))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_partial_get",myname,result); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", globus_object_printable_to_string(globus_error_get(result))); + return; + } + + /* Do all the actual I/Os */ + boff=0; + nblks=0; + while ( boff < (count*btype_size) ) + { + int i,blklen; + + for (i=0;icount;i++) + { + if ( (boff+flat_file->blocklens[i]) < (count*btype_size) ) + blklen=flat_file->blocklens[i]; + else + blklen=(count*btype_size)-boff; + if ( blklen > 0 ) + { + goff=start+nblks*ftype_extent+((globus_off_t)flat_file->indices[i]); + /* + FPRINTF(stderr,"[%d/%d] %s writing %d bytes from boff=%d at goff=%Ld\n",myrank,nprocs,myname,blklen,boff,goff); + */ + if ( (result=globus_ftp_client_register_write(&(gridftp_fh[fd->fd_sys]), + ((globus_byte_t *)buf)+boff, + (globus_size_t)blklen, + goff, + GLOBUS_TRUE, + writediscontig_data_cb, + (void *)(&bytes_written)))!=GLOBUS_SUCCESS ) + { + globus_err_handler("globus_ftp_client_register_write",myname,result); + *error_code=MPI_ERR_IO; + ADIOI_Error(fd,*error_code,myname); + return; + } + boff+=blklen; + if ( boff>=(count*btype_size) ) + break; + } + } + nblks++; + } + + + /* The ctl callback won't start till the data callbacks complete, so it's + safe to wait on just the ctl callback */ + globus_mutex_lock(&writediscontig_ctl_lock); + while ( writediscontig_ctl_done!=GLOBUS_TRUE ) + globus_cond_wait(&writediscontig_ctl_cond,&writediscontig_ctl_lock); + globus_mutex_unlock(&writediscontig_ctl_lock); + globus_mutex_destroy(&writediscontig_ctl_lock); + globus_cond_destroy(&writediscontig_ctl_cond); + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bytes_written); +#endif + if (file_ptr_type != ADIO_EXPLICIT_OFFSET) + { + fd->fp_ind += extent; + fd->fp_sys_posn = fd->fp_ind; + } + else { + fd->fp_sys_posn = offset + extent; + } +} + + +#define GRIDFTP_USE_GENERIC_STRIDED +void ADIOI_GRIDFTP_WriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ +#ifdef GRIDFTP_USE_GENERIC_STRIDED + int myrank, nprocs; + + if ( fd->access_mode&ADIO_RDONLY ) + { + *error_code=MPI_ERR_AMODE; + return; + } + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + ADIOI_GEN_WriteStrided(fd, buf, count, datatype, file_ptr_type, offset, + status, error_code); + return; +#else + char myname[]="ADIOI_GRIDFTP_WriteStrided"; + int myrank, nprocs; + int buf_contig,file_contig; + MPI_Aint btype_size,bufsize; + globus_byte_t *intermediate; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + MPI_Type_size_x(datatype,&btype_size); + bufsize=count*btype_size; + ADIOI_Datatype_iscontig(fd->filetype,&file_contig); + ADIOI_Datatype_iscontig(datatype,&buf_contig); + if ( buf_contig && !file_contig ) + { + /* Contiguous in memory, discontig in file */ + FPRINTF(stderr,"[%d/%d] %s called w/ contig mem, discontig file\n", + myrank,nprocs,myname); + fflush(stderr); + + ADIOI_GRIDFTP_WriteDiscontig(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + } + else if ( !buf_contig && file_contig ) + { + /* Discontiguous in mem, contig in file -- comparatively easy */ + int posn=0; + + FPRINTF(stderr,"[%d/%d] %s called w/ discontig mem, contig file\n", + myrank,nprocs,myname); + fflush(stderr); + + + /* squeeze contents of main buffer into intermediate buffer*/ + intermediate=(globus_byte_t *)ADIOI_Malloc((size_t)bufsize); + MPI_Pack(buf,count,datatype,intermediate,bufsize,&posn,fd->comm); + + /* write contiguous data from intermediate buffer */ + ADIOI_GRIDFTP_WriteContig(fd, intermediate, bufsize, MPI_BYTE, + file_ptr_type, offset, status, error_code); + + ADIOI_Free(intermediate); + } + else if ( !buf_contig && !file_contig ) + { + /* Discontig in both mem and file -- the hardest case */ + int posn=0; + + FPRINTF(stderr,"[%d/%d] %s called w/ discontig mem, discontig file\n", + myrank,nprocs,myname); + fflush(stderr); + + /* squeeze contents of main buffer into intermediate buffer*/ + intermediate=(globus_byte_t *)ADIOI_Malloc((size_t)bufsize); + MPI_Pack(buf,count,datatype,intermediate,bufsize,&posn,fd->comm); + + /* write contiguous data from intermediate buffer */ + ADIOI_GRIDFTP_WriteDiscontig(fd, intermediate, bufsize, MPI_BYTE, + file_ptr_type, offset, status, error_code); + + ADIOI_Free(intermediate); + } + else + { + /* Why did you bother calling WriteStrided?!?!?! */ + FPRINTF(stderr,"[%d/%d] Why the heck did you call %s with contiguous buffer *and* file types?\n", + myrank,nprocs,myname); + ADIOI_GRIDFTP_WriteContig(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + } +#endif /* ! GRIDFTP_USE_GENERIC_STRIDED */ +} + diff --git a/ompi/mca/io/romio314/romio/adio/ad_gridftp/globus_routines.c b/ompi/mca/io/romio314/romio/adio/ad_gridftp/globus_routines.c new file mode 100644 index 0000000000..1cca367a3f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_gridftp/globus_routines.c @@ -0,0 +1,36 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago, Ohio Supercomputer Center. + * See COPYRIGHT notice in top-level directory. + */ + +#include +#include +#include +#include +#include "adio.h" +#include + +/* Here are the canonical definitions of the extern's referenced by + ad_gridftp.h */ +int num_gridftp_handles=0; +#ifndef ADIO_GRIDFTP_HANDLES_MAX +#define ADIO_GRIDFTP_HANDLES_MAX 200 +#endif /* ! ADIO_GRIDFTP_HANDLES_MAX */ +/* having to keep not one but two big global tables sucks... */ +globus_ftp_client_handle_t gridftp_fh[ADIO_GRIDFTP_HANDLES_MAX]; +globus_ftp_client_operationattr_t oattr[ADIO_GRIDFTP_HANDLES_MAX]; + +void globus_err_handler(const char *routine, const char *caller, + globus_result_t result) +{ + int myrank,nprocs; + globus_object_t *err; + + MPI_Comm_rank(MPI_COMM_WORLD,&myrank); + MPI_Comm_size(MPI_COMM_WORLD,&nprocs); + err = globus_error_get(result); + FPRINTF(stderr, "[%d/%d] %s error \"%s\", called from %s\n", + myrank,nprocs,routine,globus_object_printable_to_string(err),caller); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_hfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_hfs/Makefile.mk new file mode 100644 index 0000000000..318b507639 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_hfs/Makefile.mk @@ -0,0 +1,21 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_HFS + +noinst_HEADERS += adio/ad_hfs/ad_hfs.h + +romio_other_sources += \ + adio/ad_hfs/ad_hfs_read.c \ + adio/ad_hfs/ad_hfs_open.c \ + adio/ad_hfs/ad_hfs_write.c \ + adio/ad_hfs/ad_hfs_fcntl.c \ + adio/ad_hfs/ad_hfs_resize.c \ + adio/ad_hfs/ad_hfs.c + +endif BUILD_AD_HFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_hfs/README b/ompi/mca/io/romio314/romio/adio/ad_hfs/README new file mode 100644 index 0000000000..933677b177 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_hfs/README @@ -0,0 +1 @@ +This code is no longer supported. diff --git a/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs.c b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs.c new file mode 100644 index 0000000000..ad99ff7b81 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs.c @@ -0,0 +1,36 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_hfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_HFS_operations = { + ADIOI_HFS_Open, /* Open */ + ADIOI_HFS_ReadContig, /* ReadContig */ + ADIOI_HFS_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_HFS_Fcntl, /* Fcntl */ + ADIOI_GEN_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_GEN_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ + ADIOI_FAKE_IODone, /* ReadDone */ + ADIOI_FAKE_IODone, /* WriteDone */ + ADIOI_FAKE_IOComplete, /* ReadComplete */ + ADIOI_FAKE_IOComplete, /* WriteComplete */ + ADIOI_FAKE_IreadStrided, /* IreadStrided */ + ADIOI_FAKE_IwriteStrided, /* IwriteStrided */ + ADIOI_GEN_Flush, /* Flush */ + ADIOI_HFS_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs.h b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs.h new file mode 100644 index 0000000000..2950aa50fc --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_HFS_INCLUDE +#define AD_HFS_INCLUDE + +#include +#include +#include +#include "adio.h" +#ifdef SPPUX +# include +# include +# include +#endif + +void ADIOI_HFS_Open(ADIO_File fd, int *error_code); +void ADIOI_HFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_HFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_HFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIOI_HFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_fcntl.c new file mode 100644 index 0000000000..460c73666f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_fcntl.c @@ -0,0 +1,113 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_hfs.h" +#include "adio_extern.h" + +#ifndef HAVE_LSEEK64 +#define lseek64 lseek +#endif +void ADIOI_HFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code) +{ + int i, ntimes, err; + ADIO_Offset curr_fsize, alloc_size, size, len, done; + ADIO_Status status; + char *buf; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_HFS_FCNTL"; +#endif + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + fcntl_struct->fsize = lseek64(fd->fd_sys, 0, SEEK_END); +#ifdef HPUX + if (fd->fp_sys_posn != -1) + lseek64(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); +/* not required in SPPUX since there we use pread/pwrite */ +#endif + if (fcntl_struct->fsize == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-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); +#endif + } + else *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + /* will be called by one process only */ + +#ifdef HPUX + err = prealloc64(fd->fd_sys, fcntl_struct->diskspace); + /* prealloc64 works only if file is of zero length */ + if (err && (errno != ENOTEMPTY)) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else + *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, + myname, "I/O Error", "%s", strerror(errno)); + ADIOI_Error(fd, *error_code, myname); +#endif + return; + } + if (err && (errno == ENOTEMPTY)) { +#endif + +#ifdef SPPUX + /* SPPUX has no prealloc64. therefore, use prealloc + if size < (2GB - 1), otherwise use long method. */ + if (fcntl_struct->diskspace <= 2147483647) { + err = prealloc(fd->fd_sys, (off_t) fcntl_struct->diskspace); + if (err && (errno != ENOTEMPTY)) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else + *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, + myname, "I/O Error", "%s", strerror(errno)); + ADIOI_Error(fd, *error_code, myname); +#endif + return; + } + } + + if ((fcntl_struct->diskspace > 2147483647) || + (err && (errno == ENOTEMPTY))) { +#endif + ADIOI_GEN_Prealloc(fd,fcntl_struct->diskspace, error_code); + } + ADIOI_Free(buf); +#ifdef HPUX + if (fd->fp_sys_posn != -1) + lseek64(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); + /* not required in SPPUX since there we use pread/pwrite */ +#endif + } + *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_ATOMICITY: + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + *error_code = MPI_SUCCESS; + break; + + default: + FPRINTF(stderr, "Unknown flag passed to ADIOI_HFS_Fcntl\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_open.c new file mode 100644 index 0000000000..46ee2848e5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_open.c @@ -0,0 +1,67 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_hfs.h" + +#ifndef HAVE_LSEEK64 +#define lseek64 lseek +#endif + +void ADIOI_HFS_Open(ADIO_File fd, int *error_code) +{ + int perm, old_mask, amode; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_HFS_OPEN"; +#endif + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + fd->fd_sys = open64(fd->filename, amode, perm); + fd->fd_direct = -1; + + if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND)) { + fd->fp_ind = lseek64(fd->fd_sys, 0, SEEK_END); +#ifdef HPUX + fd->fp_sys_posn = fd->fp_ind; +#endif + } + +#ifdef SPPUX + fd->fp_sys_posn = -1; /* set it to null bec. we use pread, pwrite*/ +#endif + + if (fd->fd_sys == -1 ) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-1 */ + *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, + myname, "I/O Error", "%s", strerror(errno)); + ADIOI_Error(ADIO_FILE_NULL, *error_code, myname); +#endif + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_read.c b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_read.c new file mode 100644 index 0000000000..eac03ab6f8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_read.c @@ -0,0 +1,71 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_hfs.h" + +#ifndef HAVE_LSEEK64 +#define lseek64 lseek +#endif + +void ADIOI_HFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code) +{ + MPI_Count err=-1, datatype_size, len; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_HFS_READCONTIG"; +#endif + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + +#ifdef SPPUX + fd->fp_sys_posn = -1; /* set it to null, since we are using pread */ + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) + err = pread64(fd->fd_sys, buf, len, offset); + else { /* read from curr. location of ind. file pointer */ + err = pread64(fd->fd_sys, buf, len, fd->fp_ind); + fd->fp_ind += err; + } +#endif + +#ifdef HPUX + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + if (fd->fp_sys_posn != offset) + lseek64(fd->fd_sys, offset, SEEK_SET); + err = read(fd->fd_sys, buf, len); + fd->fp_sys_posn = offset + err; + /* individual file pointer not updated */ + } + else { /* read from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) + lseek64(fd->fd_sys, fd->fp_ind, SEEK_SET); + err = read(fd->fd_sys, buf, len); + fd->fp_ind += err; + fd->fp_sys_posn = fd->fp_ind; + } +#endif + +#ifdef HAVE_STATUS_SET_BYTES + if (err != -1) MPIR_Status_set_bytes(status, datatype, err); +#endif + + if (err == -1 ) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = (err == -1) ? MPI_ERR_UNKNOWN : MPI_SUCCESS; +#else /* MPICH-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); +#endif + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_resize.c b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_resize.c new file mode 100644 index 0000000000..de24ad672a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_resize.c @@ -0,0 +1,31 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_hfs.h" + +void ADIOI_HFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int err; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_HFS_RESIZE"; +#endif + + err = ftruncate64(fd->fd_sys, size); + if (err == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-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); +#endif + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_write.c b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_write.c new file mode 100644 index 0000000000..4bffa82a2f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_hfs/ad_hfs_write.c @@ -0,0 +1,70 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_hfs.h" + +#ifndef HAVE_LSEEK64 +#define lseek64 lseek +#endif + +void ADIOI_HFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code) +{ + MPI_Count err=-1, datatype_size, len; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_HFS_WRITECONTIG"; +#endif + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + +#ifdef SPPUX + fd->fp_sys_posn = -1; /* set it to null, since we are using pwrite */ + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) + err = pwrite64(fd->fd_sys, buf, len, offset); + else { /* write from curr. location of ind. file pointer */ + err = pwrite64(fd->fd_sys, buf, len, fd->fp_ind); + fd->fp_ind += err; + } +#endif + +#ifdef HPUX + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + if (fd->fp_sys_posn != offset) + lseek64(fd->fd_sys, offset, SEEK_SET); + err = write(fd->fd_sys, buf, len); + fd->fp_sys_posn = offset + err; + /* individual file pointer not updated */ + } + else { /* write from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) + lseek64(fd->fd_sys, fd->fp_ind, SEEK_SET); + err = write(fd->fd_sys, buf, len); + fd->fp_ind += err; + fd->fp_sys_posn = fd->fp_ind; + } +#endif + +#ifdef HAVE_STATUS_SET_BYTES + if (err != -1) MPIR_Status_set_bytes(status, datatype, err); +#endif + + if (err == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_SUCCESS; +#else /* MPICH-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); +#endif + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_lustre/Makefile.mk new file mode 100644 index 0000000000..43eaa025b9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/Makefile.mk @@ -0,0 +1,22 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_LUSTRE + +noinst_HEADERS += adio/ad_lustre/ad_lustre.h + +romio_other_sources += \ + adio/ad_lustre/ad_lustre.c \ + adio/ad_lustre/ad_lustre_open.c \ + adio/ad_lustre/ad_lustre_rwcontig.c \ + adio/ad_lustre/ad_lustre_wrcoll.c \ + adio/ad_lustre/ad_lustre_wrstr.c \ + adio/ad_lustre/ad_lustre_hints.c \ + adio/ad_lustre/ad_lustre_aggregate.c + +endif BUILD_AD_LUSTRE + diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/README b/ompi/mca/io/romio314/romio/adio/ad_lustre/README new file mode 100644 index 0000000000..a217c0f8fe --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/README @@ -0,0 +1,55 @@ +Upcoming soon: + o Hierarchical striping as described in the paper from CCGrid2007 + http://ft.ornl.gov/projects/io/pubs/CCGrid-2007-file-joining.pdf +Further out: + o To post the code for ParColl (Partitioned collective IO) + +----------------------------------------------------- +V05: +----------------------------------------------------- +Improved data redistribution + o Improve I/O pattern identification. Besides checking interleaving, + if request I/O size is small, collective I/O will be performed. + The hint bigsize can be used to define the req size value. + o Provide hint CO for load balancing to control the number of + IO clients for each OST + o Produce stripe-contiguous I/O pattern that Lustre prefers + o Control read-modify-write in data sieving in collective IO + by hint ds_in_coll. + o Reduce extent lock conflicts by make each OST accessed by one or + more constant clients. + +----------------------------------------------------- +V04: +----------------------------------------------------- + o Direct IO and Lockless IO support + +----------------------------------------------------- +V03: +----------------------------------------------------- + o Correct detection of fs_type when lustre: prefix is not given + o Further fix on stripe alignment + o Tested/Enabled striping hints over Cray XT (Catamount and CNL) + +----------------------------------------------------- +V02: +----------------------------------------------------- +The Lustre ADIO driver has been cleaned up quite a lot. Compared +to the intital posting, here are the changes: + o Removal of dead/redundant code + o Removal of asynchronous IO piece as it appears outdated + o Bug fixes for setting Lustre Hints + o Bug fixes for data sieving + o Improved Setsize operation with one process calling ftruncate + o Improved collective IO with domain partitioning on + Lustre stripe boundary + +Contributing: + o You may contribute via many different ways, such as + testing results, bug reports, and new feature patches. + o We appreciate any courtesy reference of this work. + o Disclaimer: you are welcome to try the code, but at your own risk. + +Contact info: + For more info, visit http://ft.ornl.gov/projects/io/ + diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre.c b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre.c new file mode 100644 index 0000000000..d524dd829d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre.c @@ -0,0 +1,44 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + * Copyright (C) 2007 Oak Ridge National Laboratory + * + * Copyright (C) 2008 Sun Microsystems, Lustre group + */ + +#include "ad_lustre.h" + +struct ADIOI_Fns_struct ADIO_LUSTRE_operations = { + ADIOI_LUSTRE_Open, /* Open */ + ADIOI_GEN_OpenColl, /* OpenColl */ + ADIOI_LUSTRE_ReadContig, /* ReadContig */ + ADIOI_LUSTRE_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_LUSTRE_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_GEN_Fcntl, /* Fcntl */ + ADIOI_LUSTRE_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_LUSTRE_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ +#if defined(ROMIO_HAVE_WORKING_AIO) && !defined(CRAY_XT_LUSTRE) + ADIOI_GEN_IreadContig, /* IreadContig */ + ADIOI_GEN_IwriteContig, /* IwriteContig */ +#else + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ +#endif + ADIOI_GEN_IODone, /* ReadDone */ + ADIOI_GEN_IODone, /* WriteDone */ + ADIOI_GEN_IOComplete, /* ReadComplete */ + ADIOI_GEN_IOComplete, /* WriteComplete */ + ADIOI_GEN_IreadStrided, /* IreadStrided */ + ADIOI_GEN_IwriteStrided, /* IwriteStrided */ + ADIOI_GEN_Flush, /* Flush */ + ADIOI_GEN_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ + ADIOI_GEN_Feature, /* Features */ + "LUSTRE:", +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre.h b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre.h new file mode 100644 index 0000000000..93034cd667 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre.h @@ -0,0 +1,91 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + * Copyright (C) 2007 Oak Ridge National Laboratory + * + * Copyright (C) 2008 Sun Microsystems, Lustre group + */ + +#ifndef AD_UNIX_INCLUDE +#define AD_UNIX_INCLUDE + +/* temp*/ +#define HAVE_ASM_TYPES_H 1 + +#include +#include + +#ifdef __linux__ +# include /* necessary for: */ +# include +# define __USE_GNU /* O_DIRECT and */ +# include /* IO operations */ +# undef __USE_GNU +#endif /* __linux__ */ + +/*#include */ +#include +#include +#include "adio.h" +/*#include "adioi.h"*/ + +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_AIO_H +#include +#ifdef HAVE_SYS_AIO_H +#include +#endif +#endif /* End of HAVE_SYS_AIO_H */ + +void ADIOI_LUSTRE_Open(ADIO_File fd, int *error_code); +void ADIOI_LUSTRE_Close(ADIO_File fd, int *error_code); +void ADIOI_LUSTRE_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code); +void ADIOI_LUSTRE_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); +void ADIOI_LUSTRE_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); +void ADIOI_LUSTRE_WriteStridedColl(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code); +void ADIOI_LUSTRE_ReadStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code); +void ADIOI_LUSTRE_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code); +void ADIOI_LUSTRE_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code); +void ADIOI_LUSTRE_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); + +/* the lustre utilities: */ +int ADIOI_LUSTRE_Docollect(ADIO_File fd, int contig_access_count, + ADIO_Offset *len_list, int nprocs); + +void ADIOI_LUSTRE_Get_striping_info(ADIO_File fd, int **striping_info_ptr, + int mode); +void ADIOI_LUSTRE_Calc_my_req(ADIO_File fd, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, + int *striping_info, int nprocs, + int *count_my_req_procs_ptr, + int **count_my_req_per_proc_ptr, + ADIOI_Access **my_req_ptr, + int ***buf_idx_ptr); + +int ADIOI_LUSTRE_Calc_aggregator(ADIO_File fd, ADIO_Offset off, + ADIO_Offset *len, int *striping_info); +#endif /* End of AD_UNIX_INCLUDE */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_aggregate.c b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_aggregate.c new file mode 100644 index 0000000000..cd552829ed --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_aggregate.c @@ -0,0 +1,322 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + * Copyright (C) 2007 Oak Ridge National Laboratory + * + * Copyright (C) 2008 Sun Microsystems, Lustre group + */ + +#include "ad_lustre.h" +#include "adio_extern.h" + +#undef AGG_DEBUG + +void ADIOI_LUSTRE_Get_striping_info(ADIO_File fd, int **striping_info_ptr, + int mode) +{ + int *striping_info = NULL; + /* get striping information: + * striping_info[0]: stripe_size + * striping_info[1]: stripe_count + * striping_info[2]: avail_cb_nodes + */ + int stripe_size, stripe_count, CO = 1; + int avail_cb_nodes, divisor, nprocs_for_coll = fd->hints->cb_nodes; + + /* Get hints value */ + /* stripe size */ + stripe_size = fd->hints->striping_unit; + /* stripe count */ + /* stripe_size and stripe_count have been validated in ADIOI_LUSTRE_Open() */ + stripe_count = fd->hints->striping_factor; + + /* Calculate the available number of I/O clients */ + if (!mode) { + /* for collective read, + * if "CO" clients access the same OST simultaneously, + * the OST disk seek time would be much. So, to avoid this, + * it might be better if 1 client only accesses 1 OST. + * So, we set CO = 1 to meet the above requirement. + */ + CO = 1; + /*XXX: maybe there are other better way for collective read */ + } else { + /* CO also has been validated in ADIOI_LUSTRE_Open(), >0 */ + CO = fd->hints->fs_hints.lustre.co_ratio; + } + /* Calculate how many IO clients we need */ + /* Algorithm courtesy Pascal Deveze (pascal.deveze@bull.net) */ + /* To avoid extent lock conflicts, + * avail_cb_nodes should either + * - be a multiple of stripe_count, + * - or divide stripe_count exactly + * so that each OST is accessed by a maximum of CO constant clients. */ + if (nprocs_for_coll >= stripe_count) + /* avail_cb_nodes should be a multiple of stripe_count and the number + * of procs per OST should be limited to the minimum between + * nprocs_for_coll/stripe_count and CO + * + * e.g. if stripe_count=20, nprocs_for_coll=42 and CO=3 then + * avail_cb_nodes should be equal to 40 */ + avail_cb_nodes = + stripe_count * ADIOI_MIN(nprocs_for_coll/stripe_count, CO); + else { + /* nprocs_for_coll is less than stripe_count */ + /* avail_cb_nodes should divide stripe_count */ + /* e.g. if stripe_count=60 and nprocs_for_coll=8 then + * avail_cb_nodes should be egal to 6 */ + /* This could be done with : + while (stripe_count % avail_cb_nodes != 0) avail_cb_nodes--; + but this can be optimized for large values of nprocs_for_coll and + stripe_count */ + divisor = 2; + avail_cb_nodes = 1; + /* try to divise */ + while (stripe_count >= divisor*divisor) { + if ((stripe_count % divisor) == 0) { + if (stripe_count/divisor <= nprocs_for_coll) { + /* The value is found ! */ + avail_cb_nodes = stripe_count/divisor; + break; + } + /* if divisor is less than nprocs_for_coll, divisor is a + * solution, but it is not sure that it is the best one */ + else if (divisor <= nprocs_for_coll) + avail_cb_nodes = divisor; + } + divisor++; + } + } + + *striping_info_ptr = (int *) ADIOI_Malloc(3 * sizeof(int)); + striping_info = *striping_info_ptr; + striping_info[0] = stripe_size; + striping_info[1] = stripe_count; + striping_info[2] = avail_cb_nodes; +} + +int ADIOI_LUSTRE_Calc_aggregator(ADIO_File fd, ADIO_Offset off, + ADIO_Offset *len, int *striping_info) +{ + int rank_index, rank; + ADIO_Offset avail_bytes; + int stripe_size = striping_info[0]; + int avail_cb_nodes = striping_info[2]; + + /* Produce the stripe-contiguous pattern for Lustre */ + rank_index = (int)((off / stripe_size) % avail_cb_nodes); + + /* we index into fd_end with rank_index, and fd_end was allocated to be no + * bigger than fd->hins->cb_nodes. If we ever violate that, we're + * overrunning arrays. Obviously, we should never ever hit this abort + */ + if (rank_index >= fd->hints->cb_nodes) + MPI_Abort(MPI_COMM_WORLD, 1); + + avail_bytes = (off / (ADIO_Offset)stripe_size + 1) * + (ADIO_Offset)stripe_size - off; + if (avail_bytes < *len) { + /* this proc only has part of the requested contig. region */ + *len = avail_bytes; + } + /* map our index to a rank */ + /* NOTE: FOR NOW WE DON'T HAVE A MAPPING...JUST DO 0..NPROCS_FOR_COLL */ + rank = fd->hints->ranklist[rank_index]; + + return rank; +} + +/* ADIOI_LUSTRE_Calc_my_req() - calculate what portions of the access requests + * of this process are located in the file domains of various processes + * (including this one) + */ + + +void ADIOI_LUSTRE_Calc_my_req(ADIO_File fd, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, + int *striping_info, int nprocs, + int *count_my_req_procs_ptr, + int **count_my_req_per_proc_ptr, + ADIOI_Access **my_req_ptr, + int ***buf_idx_ptr) +{ + /* Nothing different from ADIOI_Calc_my_req(), except calling + * ADIOI_Lustre_Calc_aggregator() instead of the old one */ + int *count_my_req_per_proc, count_my_req_procs, **buf_idx; + int i, l, proc; + ADIO_Offset avail_len, rem_len, curr_idx, off; + ADIOI_Access *my_req; + + *count_my_req_per_proc_ptr = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + count_my_req_per_proc = *count_my_req_per_proc_ptr; + /* count_my_req_per_proc[i] gives the no. of contig. requests of this + * process in process i's file domain. calloc initializes to zero. + * I'm allocating memory of size nprocs, so that I can do an + * MPI_Alltoall later on. + */ + + buf_idx = (int **) ADIOI_Malloc(nprocs * sizeof(int*)); + + /* one pass just to calculate how much space to allocate for my_req; + * contig_access_count was calculated way back in ADIOI_Calc_my_off_len() + */ + for (i = 0; i < contig_access_count; i++) { + /* short circuit offset/len processing if len == 0 + * (zero-byte read/write + */ + if (len_list[i] == 0) + continue; + off = offset_list[i]; + avail_len = len_list[i]; + /* note: we set avail_len to be the total size of the access. + * then ADIOI_LUSTRE_Calc_aggregator() will modify the value to return + * the amount that was available. + */ + proc = ADIOI_LUSTRE_Calc_aggregator(fd, off, &avail_len, striping_info); + count_my_req_per_proc[proc]++; + + /* figure out how many data is remaining in the access + * we'll take care of this data (if there is any) + * in the while loop below. + */ + rem_len = len_list[i] - avail_len; + + while (rem_len != 0) { + off += avail_len; /* point to first remaining byte */ + avail_len = rem_len; /* save remaining size, pass to calc */ + proc = ADIOI_LUSTRE_Calc_aggregator(fd, off, &avail_len, striping_info); + count_my_req_per_proc[proc]++; + rem_len -= avail_len; /* reduce remaining length by amount from fd */ + } + } + + /* buf_idx is relevant only if buftype_is_contig. + * buf_idx[i] gives the index into user_buf where data received + * from proc 'i' should be placed. This allows receives to be done + * without extra buffer. This can't be done if buftype is not contig. + */ + + /* initialize buf_idx vectors */ + for (i = 0; i < nprocs; i++) { + /* add one to count_my_req_per_proc[i] to avoid zero size malloc */ + buf_idx[i] = (int *) ADIOI_Malloc((count_my_req_per_proc[i] + 1) + * sizeof(int)); + } + + /* now allocate space for my_req, offset, and len */ + *my_req_ptr = (ADIOI_Access *) ADIOI_Malloc(nprocs * sizeof(ADIOI_Access)); + my_req = *my_req_ptr; + + count_my_req_procs = 0; + for (i = 0; i < nprocs; i++) { + if (count_my_req_per_proc[i]) { + my_req[i].offsets = (ADIO_Offset *) + ADIOI_Malloc(count_my_req_per_proc[i] * + sizeof(ADIO_Offset)); + my_req[i].lens = ADIOI_Malloc(count_my_req_per_proc[i] * + sizeof(ADIO_Offset)); + count_my_req_procs++; + } + my_req[i].count = 0; /* will be incremented where needed later */ + } + + /* now fill in my_req */ + curr_idx = 0; + for (i = 0; i < contig_access_count; i++) { + /* short circuit offset/len processing if len == 0 + * (zero-byte read/write */ + if (len_list[i] == 0) + continue; + off = offset_list[i]; + avail_len = len_list[i]; + proc = ADIOI_LUSTRE_Calc_aggregator(fd, off, &avail_len, striping_info); + + l = my_req[proc].count; + + ADIOI_Assert(curr_idx == (int) curr_idx); + ADIOI_Assert(l < count_my_req_per_proc[proc]); + buf_idx[proc][l] = (int) curr_idx; + curr_idx += avail_len; + + rem_len = len_list[i] - avail_len; + + /* store the proc, offset, and len information in an array + * of structures, my_req. Each structure contains the + * offsets and lengths located in that process's FD, + * and the associated count. + */ + my_req[proc].offsets[l] = off; + ADIOI_Assert(avail_len == (int) avail_len); + my_req[proc].lens[l] = (int) avail_len; + my_req[proc].count++; + + while (rem_len != 0) { + off += avail_len; + avail_len = rem_len; + proc = ADIOI_LUSTRE_Calc_aggregator(fd, off, &avail_len, + striping_info); + + l = my_req[proc].count; + ADIOI_Assert(curr_idx == (int) curr_idx); + ADIOI_Assert(l < count_my_req_per_proc[proc]); + buf_idx[proc][l] = (int) curr_idx; + + curr_idx += avail_len; + rem_len -= avail_len; + + my_req[proc].offsets[l] = off; + ADIOI_Assert(avail_len == (int) avail_len); + my_req[proc].lens[l] = (int) avail_len; + my_req[proc].count++; + } + } + +#ifdef AGG_DEBUG + for (i = 0; i < nprocs; i++) { + if (count_my_req_per_proc[i] > 0) { + FPRINTF(stdout, "data needed from %d (count = %d):\n", + i, my_req[i].count); + for (l = 0; l < my_req[i].count; l++) { + FPRINTF(stdout, " off[%d] = %lld, len[%d] = %d\n", + l, my_req[i].offsets[l], l, my_req[i].lens[l]); + } + } + } +#endif + + *count_my_req_procs_ptr = count_my_req_procs; + *buf_idx_ptr = buf_idx; +} + +int ADIOI_LUSTRE_Docollect(ADIO_File fd, int contig_access_count, + ADIO_Offset *len_list, int nprocs) +{ + /* If the processes are non-interleaved, we will check the req_size. + * if (avg_req_size > big_req_size) { + * docollect = 0; + * } + */ + + int i, docollect = 1, big_req_size = 0; + ADIO_Offset req_size = 0, total_req_size; + int avg_req_size, total_access_count; + + /* calculate total_req_size and total_access_count */ + for (i = 0; i < contig_access_count; i++) + req_size += len_list[i]; + MPI_Allreduce(&req_size, &total_req_size, 1, MPI_LONG_LONG_INT, MPI_SUM, + fd->comm); + MPI_Allreduce(&contig_access_count, &total_access_count, 1, MPI_INT, MPI_SUM, + fd->comm); + /* estimate average req_size */ + avg_req_size = (int)(total_req_size / total_access_count); + /* get hint of big_req_size */ + big_req_size = fd->hints->fs_hints.lustre.coll_threshold; + /* Don't perform collective I/O if there are big requests */ + if ((big_req_size > 0) && (avg_req_size > big_req_size)) + docollect = 0; + + return docollect; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_fcntl.c new file mode 100644 index 0000000000..a4bd6fc6d1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_fcntl.c @@ -0,0 +1,97 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + * Copyright (C) 2007 Oak Ridge National Laboratory + */ + +#include "ad_lustre.h" +#include "adio_extern.h" + +void ADIOI_LUSTRE_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code) +{ + int i, ntimes; + ADIO_Offset curr_fsize, alloc_size, size, len, done; + ADIO_Status status; + char *buf; +#if defined(MPICH) || !defined(PRINT_ERR_MSG) + static char myname[] = "ADIOI_LUSTRE_FCNTL"; +#endif + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + fcntl_struct->fsize = lseek(fd->fd_sys, 0, SEEK_END); + if (fd->fp_sys_posn != -1) + lseek(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); + if (fcntl_struct->fsize == -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; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + /* will be called by one process only */ + /* On file systems with no preallocation function, I have to + explicitly write + to allocate space. Since there could be holes in the file, + I need to read up to the current file size, write it back, + and then write beyond that depending on how much + preallocation is needed. + read/write in sizes of no more than ADIOI_PREALLOC_BUFSZ */ + + curr_fsize = lseek(fd->fd_sys, 0, SEEK_END); + alloc_size = fcntl_struct->diskspace; + + size = ADIOI_MIN(curr_fsize, alloc_size); + + ntimes = (size + ADIOI_PREALLOC_BUFSZ - 1)/ADIOI_PREALLOC_BUFSZ; + buf = (char *) ADIOI_Malloc(ADIOI_PREALLOC_BUFSZ); + done = 0; + + for (i=0; i curr_fsize) { + memset(buf, 0, ADIOI_PREALLOC_BUFSZ); + size = alloc_size - curr_fsize; + ntimes = (size + ADIOI_PREALLOC_BUFSZ - 1)/ADIOI_PREALLOC_BUFSZ; + for (i=0; ifp_sys_posn != -1) + lseek(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); + *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_ATOMICITY: + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + *error_code = MPI_SUCCESS; + break; + + default: + FPRINTF(stderr, "Unknown flag passed to ADIOI_LUSTRE_Fcntl\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_hints.c b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_hints.c new file mode 100644 index 0000000000..051cfb0c4c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_hints.c @@ -0,0 +1,180 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + * Copyright (C) 2007 Oak Ridge National Laboratory + * + * Copyright (C) 2008 Sun Microsystems, Lustre group + */ + +#include "ad_lustre.h" +#include "adio_extern.h" +#include "hint_fns.h" +#ifdef HAVE_LIMITS_H +#include +#endif + +void ADIOI_LUSTRE_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ + char *value; + int flag; + ADIO_Offset stripe_val[3], str_factor = -1, str_unit=0, start_iodev=-1; + struct lov_user_md lum = { 0 }; + int err, myrank, fd_sys, perm, amode, old_mask; + static char myname[] = "ADIOI_LUSTRE_SETINFO"; + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + if ( (fd->info) == MPI_INFO_NULL) { + /* This must be part of the open call. can set striping parameters + if necessary. */ + MPI_Info_create(&(fd->info)); + + ADIOI_Info_set(fd->info, "direct_read", "false"); + ADIOI_Info_set(fd->info, "direct_write", "false"); + fd->direct_read = fd->direct_write = 0; + /* initialize lustre hints */ + ADIOI_Info_set(fd->info, "romio_lustre_co_ratio", "1"); + fd->hints->fs_hints.lustre.co_ratio = 1; + ADIOI_Info_set(fd->info, "romio_lustre_coll_threshold", "0"); + fd->hints->fs_hints.lustre.coll_threshold = 0; + ADIOI_Info_set(fd->info, "romio_lustre_ds_in_coll", "enable"); + fd->hints->fs_hints.lustre.ds_in_coll = ADIOI_HINT_ENABLE; + + /* has user specified striping or server buffering parameters + and do they have the same value on all processes? */ + if (users_info != MPI_INFO_NULL) { + /* striping information */ + ADIOI_Info_get(users_info, "striping_unit", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) + str_unit=atoll(value); + + ADIOI_Info_get(users_info, "striping_factor", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) + str_factor=atoll(value); + + ADIOI_Info_get(users_info, "romio_lustre_start_iodevice", + MPI_MAX_INFO_VAL, value, &flag); + if (flag) + start_iodev=atoll(value); + + /* direct read and write */ + ADIOI_Info_get(users_info, "direct_read", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && (!strcmp(value, "true") || !strcmp(value, "TRUE"))) { + ADIOI_Info_set(fd->info, "direct_read", "true"); + fd->direct_read = 1; + } + ADIOI_Info_get(users_info, "direct_write", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && (!strcmp(value, "true") || !strcmp(value, "TRUE"))) { + ADIOI_Info_set(fd->info, "direct_write", "true"); + fd->direct_write = 1; + } + } + + /* set striping information with ioctl */ + MPI_Comm_rank(fd->comm, &myrank); + if (myrank == 0) { + stripe_val[0] = str_factor; + stripe_val[1] = str_unit; + stripe_val[2] = start_iodev; + } + MPI_Bcast(stripe_val, 3, MPI_OFFSET, 0, fd->comm); + + if (stripe_val[0] != str_factor + || stripe_val[1] != str_unit + || stripe_val[2] != start_iodev) { + FPRINTF(stderr, "ADIOI_LUSTRE_SetInfo: All keys" + "-striping_factor:striping_unit:start_iodevice " + "need to be identical across all processes\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } else if ((str_factor > 0) || (str_unit > 0) || (start_iodev >= 0)) { + /* if user has specified striping info, process 0 tries to set it */ + if (!myrank) { + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + /* we need to create file so ensure this is set */ + amode = amode | O_LOV_DELAY_CREATE | O_CREAT; + + fd_sys = open(fd->filename, amode, perm); + if (fd_sys == -1) { + if (errno != EEXIST) + fprintf(stderr, + "Failure to open file %s %d %d\n",strerror(errno), amode, perm); + } else { + lum.lmm_magic = LOV_USER_MAGIC; + lum.lmm_pattern = 0; + lum.lmm_stripe_size = str_unit; + /* crude check for overflow of lustre internal datatypes. + * Silently cap to large value if user provides a value + * larger than lustre supports */ + if (lum.lmm_stripe_size != str_unit) { + lum.lmm_stripe_size = UINT_MAX; + } + lum.lmm_stripe_count = str_factor; + if ( lum.lmm_stripe_count != str_factor) { + lum.lmm_stripe_count = USHRT_MAX; + } + lum.lmm_stripe_offset = start_iodev; + if (lum.lmm_stripe_offset != start_iodev) { + lum.lmm_stripe_offset = USHRT_MAX; + } + + err = ioctl(fd_sys, LL_IOC_LOV_SETSTRIPE, &lum); + if (err == -1 && errno != EEXIST) { + fprintf(stderr, "Failure to set stripe info %s \n", strerror(errno)); + } + close(fd_sys); + } + } /* End of striping parameters validation */ + } + MPI_Barrier(fd->comm); + } + /* get other hint */ + if (users_info != MPI_INFO_NULL) { + /* CO: IO Clients/OST, + * to keep the load balancing between clients and OSTs */ + ADIOI_Info_check_and_install_int(fd, users_info, "romio_lustre_co_ratio", + &(fd->hints->fs_hints.lustre.co_ratio), myname, error_code ); + + /* coll_threshold: + * if the req size is bigger than this, collective IO may not be performed. + */ + ADIOI_Info_check_and_install_int(fd, users_info, "romio_lustre_coll_threshold", + &(fd->hints->fs_hints.lustre.coll_threshold), myname, error_code ); + + /* ds_in_coll: disable data sieving in collective IO */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_lustre_ds_in_coll", + &(fd->hints->fs_hints.lustre.ds_in_coll), myname, error_code ); + + } + /* set the values for collective I/O and data sieving parameters */ + ADIOI_GEN_SetInfo(fd, users_info, error_code); + + if (ADIOI_Direct_read) fd->direct_read = 1; + if (ADIOI_Direct_write) fd->direct_write = 1; + + ADIOI_Free(value); + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_open.c b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_open.c new file mode 100644 index 0000000000..e06cb24d7a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_open.c @@ -0,0 +1,113 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + * Copyright (C) 2007 Oak Ridge National Laboratory + * + * Copyright (C) 2008 Sun Microsystems, Lustre group + */ + +#include "ad_lustre.h" + +/* what is the basis for this define? + * what happens if there are more than 1k UUIDs? */ + +#define MAX_LOV_UUID_COUNT 1000 + +void ADIOI_LUSTRE_Open(ADIO_File fd, int *error_code) +{ + int perm, old_mask, amode, amode_direct; + int lumlen; + struct lov_user_md *lum = NULL; + char *value; + +#if defined(MPICH) || !defined(PRINT_ERR_MSG) + static char myname[] = "ADIOI_LUSTRE_OPEN"; +#endif + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + amode_direct = amode | O_DIRECT; + + fd->fd_sys = open(fd->filename, amode|O_CREAT, perm); + + if (fd->fd_sys != -1) { + int err; + + /* get file striping information and set it in info */ + /* odd malloc here because lov_user_md contains some fixed data and + * then a list of 'lmm_objects' representing stripe */ + lumlen = sizeof(struct lov_user_md) + + MAX_LOV_UUID_COUNT * sizeof(struct lov_user_ost_data); + /* furthermore, Pascal Deveze reports that, even though we pass a + * "GETSTRIPE" (read) flag to the ioctl, if some of the values of this + * struct are uninitialzed, the call can give an error. calloc in case + * there are other members that must be initialized and in case + * lov_user_md struct changes in future */ + lum = (struct lov_user_md *)ADIOI_Calloc(1,lumlen); + lum->lmm_magic = LOV_USER_MAGIC; + err = ioctl(fd->fd_sys, LL_IOC_LOV_GETSTRIPE, (void *)lum); + if (!err) { + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + + fd->hints->striping_unit = lum->lmm_stripe_size; + sprintf(value, "%d", lum->lmm_stripe_size); + ADIOI_Info_set(fd->info, "striping_unit", value); + + fd->hints->striping_factor = lum->lmm_stripe_count; + sprintf(value, "%d", lum->lmm_stripe_count); + ADIOI_Info_set(fd->info, "striping_factor", value); + + fd->hints->fs_hints.lustre.start_iodevice = lum->lmm_stripe_offset; + sprintf(value, "%d", lum->lmm_stripe_offset); + ADIOI_Info_set(fd->info, "romio_lustre_start_iodevice", value); + + ADIOI_Free(value); + } + ADIOI_Free(lum); + + if (fd->access_mode & ADIO_APPEND) + fd->fp_ind = fd->fp_sys_posn = lseek(fd->fd_sys, 0, SEEK_END); + } + + if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND)) + fd->fp_ind = fd->fp_sys_posn = lseek(fd->fd_sys, 0, SEEK_END); + + fd->fd_direct = -1; + if (fd->direct_write || fd->direct_read) { + fd->fd_direct = open(fd->filename, amode_direct, perm); + if (fd->fd_direct != -1) { + fd->d_mem = fd->d_miniosz = (1<<12); + } else { + perror("cannot open file with O_Direct"); + fd->direct_write = fd->direct_read = 0; + } + } + + /* --BEGIN ERROR HANDLING-- */ + if (fd->fd_sys == -1 || ((fd->fd_direct == -1) && + (fd->direct_write || fd->direct_read))) { + *error_code = ADIOI_Err_create_code(myname, fd->filename, errno); + } + /* --END ERROR HANDLING-- */ + else *error_code = MPI_SUCCESS; + +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_rwcontig.c b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_rwcontig.c new file mode 100644 index 0000000000..5f1c2321ed --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_rwcontig.c @@ -0,0 +1,208 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + * Copyright (C) 2007 Oak Ridge National Laboratory + * + * Copyright (C) 2008 Sun Microsystems, Lustre group + */ + +#ifdef _STDC_C99 +#define _XOPEN_SOURCE 600 +#else +#define _XOPEN_SOURCE 500 +#endif +#include + +#include +#include +#include "ad_lustre.h" + +#define LUSTRE_MEMALIGN (1<<12) /* to use page_shift */ + +static void ADIOI_LUSTRE_Aligned_Mem_File_Write(ADIO_File fd, const void *buf, int len, + ADIO_Offset offset, int *err); +static void ADIOI_LUSTRE_Aligned_Mem_File_Write(ADIO_File fd, const void *buf, int len, + ADIO_Offset offset, int *err) +{ + int rem, size, nbytes; + if (!(len % fd->d_miniosz) && (len >= fd->d_miniosz)) { + *err = pwrite(fd->fd_direct, buf, len, offset); + } else if (len < fd->d_miniosz) { + *err = pwrite(fd->fd_sys, buf, len, offset); + } else { + rem = len % fd->d_miniosz; + size = len - rem; + nbytes = pwrite(fd->fd_direct, buf, size, offset); + nbytes += pwrite(fd->fd_sys, ((char *)buf) + size, rem, offset+size); + *err = nbytes; + } +} + +static void ADIOI_LUSTRE_Aligned_Mem_File_Read(ADIO_File fd, const void *buf, int len, + ADIO_Offset offset, int *err); +static void ADIOI_LUSTRE_Aligned_Mem_File_Read(ADIO_File fd, const void *buf, int len, + ADIO_Offset offset, int *err) +{ + int rem, size, nbytes; + if (!(len % fd->d_miniosz) && (len >= fd->d_miniosz)) + *err = pread(fd->fd_direct, (void *)buf, len, offset); + else if (len < fd->d_miniosz) + *err = pread(fd->fd_sys, (void *)buf, len, offset); + else { + rem = len % fd->d_miniosz; + size = len - rem; + nbytes = pread(fd->fd_direct, (void *)buf, size, offset); + nbytes += pread(fd->fd_sys, ((char *)buf) + size, rem, offset+size); + *err = nbytes; + } +} + + +static int ADIOI_LUSTRE_Directio(ADIO_File fd, const void *buf, int len, + off_t offset, int rw); +static int ADIOI_LUSTRE_Directio(ADIO_File fd, const void *buf, int len, + off_t offset, int rw) +{ + int err=-1, diff, size=len, nbytes = 0; + void *newbuf; + + if (offset % fd->d_miniosz) { + diff = fd->d_miniosz - (offset % fd->d_miniosz); + diff = ADIOI_MIN(diff, len); + if (rw) + nbytes = pwrite(fd->fd_sys, (void *)buf, diff, offset); + else + nbytes = pread(fd->fd_sys, (void *)buf, diff, offset); + buf = ((char *) buf) + diff; + offset += diff; + size = len - diff; + } + + if (!size) { + return diff; + } + + if (rw) { /* direct I/O enabled */ + if (!(((long) buf) % fd->d_mem)) { + ADIOI_LUSTRE_Aligned_Mem_File_Write(fd, buf, size, offset, &err); + nbytes += err; + } else { + newbuf = (void *) memalign(LUSTRE_MEMALIGN, size); + if (newbuf) { + memcpy(newbuf, buf, size); + ADIOI_LUSTRE_Aligned_Mem_File_Write(fd, newbuf, size, offset, &err); + nbytes += err; + ADIOI_Free(newbuf); + } + else nbytes += pwrite(fd->fd_sys, buf, size, offset); + } + err = nbytes; + } else { + if (!(((long) buf) % fd->d_mem)) { + ADIOI_LUSTRE_Aligned_Mem_File_Read(fd, buf, size, offset, &err); + nbytes += err; + } else { + newbuf = (void *) memalign(LUSTRE_MEMALIGN, size); + if (newbuf) { + ADIOI_LUSTRE_Aligned_Mem_File_Read(fd, newbuf, size, offset, &err); + if (err > 0) memcpy((void *)buf, newbuf, err); + nbytes += err; + ADIOI_Free(newbuf); + } + else nbytes += pread(fd->fd_sys, (void *)buf, size, offset); + } + err = nbytes; + } + return err; +} + +static void ADIOI_LUSTRE_IOContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int io_mode, int *error_code); +static void ADIOI_LUSTRE_IOContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int io_mode, int *error_code) +{ + int err=-1; + MPI_Count datatype_size, len; + static char myname[] = "ADIOI_LUSTRE_IOCONTIG"; + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; + } + + if (!(fd->direct_read || fd->direct_write)) { + if (fd->fp_sys_posn != offset) { + err = lseek(fd->fd_sys, offset, SEEK_SET); + if (err == -1) goto ioerr; + } + + if (io_mode) { +#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 + } else { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_read_a, 0, NULL); +#endif + err = read(fd->fd_sys, (void *)buf, len); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_read_b, 0, NULL); +#endif + } + } else { + err = ADIOI_LUSTRE_Directio(fd, buf, len, offset, io_mode); + } + + if (err == -1) goto ioerr; + fd->fp_sys_posn = offset + err; + + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind += err; + } + +#ifdef HAVE_STATUS_SET_BYTES + if (status) MPIR_Status_set_bytes(status, datatype, err); +#endif + *error_code = MPI_SUCCESS; + +ioerr: + /* --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-- */ +} + +void ADIOI_LUSTRE_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) +{ + ADIOI_LUSTRE_IOContig(fd, buf, count, datatype, file_ptr_type, + offset, status, 1, error_code); +} + +void ADIOI_LUSTRE_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code) +{ + ADIOI_LUSTRE_IOContig(fd, buf, count, datatype, file_ptr_type, + offset, status, 0, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_wrcoll.c b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_wrcoll.c new file mode 100644 index 0000000000..3299ad5af3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_wrcoll.c @@ -0,0 +1,989 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + * Copyright (C) 2007 Oak Ridge National Laboratory + * + * Copyright (C) 2008 Sun Microsystems, Lustre group + */ + +#include "ad_lustre.h" +#include "adio_extern.h" + +/* prototypes of functions used for collective writes only. */ +static void ADIOI_LUSTRE_Exch_and_write(ADIO_File fd, const void *buf, + MPI_Datatype datatype, int nprocs, + int myrank, + ADIOI_Access *others_req, + ADIOI_Access *my_req, + ADIO_Offset *offset_list, + ADIO_Offset *len_list, + int contig_access_count, + int *striping_info, + int **buf_idx, int *error_code); +static void ADIOI_LUSTRE_Fill_send_buffer(ADIO_File fd, const void *buf, + ADIOI_Flatlist_node *flat_buf, + char **send_buf, + ADIO_Offset *offset_list, + ADIO_Offset *len_list, int *send_size, + MPI_Request *requests, + int *sent_to_proc, int nprocs, + int myrank, int contig_access_count, + int *striping_info, + int *send_buf_idx, + int *curr_to_proc, + int *done_to_proc, int iter, + MPI_Aint buftype_extent); +static void ADIOI_LUSTRE_W_Exchange_data(ADIO_File fd, const void *buf, + char *write_buf, + ADIOI_Flatlist_node *flat_buf, + ADIO_Offset *offset_list, + ADIO_Offset *len_list, int *send_size, + int *recv_size, ADIO_Offset off, + int size, int *count, + int *start_pos, + int *sent_to_proc, int nprocs, + int myrank, int buftype_is_contig, + int contig_access_count, + int *striping_info, + ADIOI_Access *others_req, + int *send_buf_idx, + int *curr_to_proc, + int *done_to_proc, int *hole, + int iter, MPI_Aint buftype_extent, + int *buf_idx, + ADIO_Offset **srt_off, int **srt_len, int *srt_num, + int *error_code); +void ADIOI_Heap_merge(ADIOI_Access *others_req, int *count, + ADIO_Offset *srt_off, int *srt_len, int *start_pos, + int nprocs, int nprocs_recv, int total_elements); + +void ADIOI_LUSTRE_WriteStridedColl(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, + int file_ptr_type, ADIO_Offset offset, + ADIO_Status *status, int *error_code) +{ + /* Uses a generalized version of the extended two-phase method described + * in "An Extended Two-Phase Method for Accessing Sections of + * Out-of-Core Arrays", Rajeev Thakur and Alok Choudhary, + * Scientific Programming, (5)4:301--317, Winter 1996. + * http://www.mcs.anl.gov/home/thakur/ext2ph.ps + */ + + ADIOI_Access *my_req; + /* array of nprocs access structures, one for each other process has + this process's request */ + + ADIOI_Access *others_req; + /* array of nprocs access structures, one for each other process + whose request is written by this process. */ + + int i, filetype_is_contig, nprocs, myrank, do_collect = 0; + int contig_access_count = 0, buftype_is_contig, interleave_count = 0; + int *count_my_req_per_proc, count_my_req_procs, count_others_req_procs; + ADIO_Offset orig_fp, start_offset, end_offset, off; + ADIO_Offset *offset_list = NULL, *st_offsets = NULL, *end_offsets = NULL; + ADIO_Offset *len_list = NULL; + int **buf_idx = NULL, *striping_info = NULL; + int old_error, tmp_error; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + orig_fp = fd->fp_ind; + + /* IO patten identification if cb_write isn't disabled */ + if (fd->hints->cb_write != ADIOI_HINT_DISABLE) { + /* For this process's request, calculate the list of offsets and + lengths in the file and determine the start and end offsets. */ + + /* Note: end_offset points to the last byte-offset that will be accessed. + * e.g., if start_offset=0 and 100 bytes to be read, end_offset=99 + */ + + ADIOI_Calc_my_off_len(fd, count, datatype, file_ptr_type, offset, + &offset_list, &len_list, &start_offset, + &end_offset, &contig_access_count); + + /* each process communicates its start and end offsets to other + * processes. The result is an array each of start and end offsets + * stored in order of process rank. + */ + st_offsets = (ADIO_Offset *) ADIOI_Malloc(nprocs * sizeof(ADIO_Offset)); + end_offsets = (ADIO_Offset *) ADIOI_Malloc(nprocs * sizeof(ADIO_Offset)); + MPI_Allgather(&start_offset, 1, ADIO_OFFSET, st_offsets, 1, + ADIO_OFFSET, fd->comm); + MPI_Allgather(&end_offset, 1, ADIO_OFFSET, end_offsets, 1, + ADIO_OFFSET, fd->comm); + /* are the accesses of different processes interleaved? */ + for (i = 1; i < nprocs; i++) + if ((st_offsets[i] < end_offsets[i-1]) && + (st_offsets[i] <= end_offsets[i])) + interleave_count++; + /* This is a rudimentary check for interleaving, but should suffice + for the moment. */ + + /* Two typical access patterns can benefit from collective write. + * 1) the processes are interleaved, and + * 2) the req size is small. + */ + if (interleave_count > 0) { + do_collect = 1; + } else { + do_collect = ADIOI_LUSTRE_Docollect(fd, contig_access_count, + len_list, nprocs); + } + } + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + + /* Decide if collective I/O should be done */ + if ((!do_collect && fd->hints->cb_write == ADIOI_HINT_AUTO) || + fd->hints->cb_write == ADIOI_HINT_DISABLE) { + + /* use independent accesses */ + if (fd->hints->cb_write != ADIOI_HINT_DISABLE) { + ADIOI_Free(offset_list); + ADIOI_Free(len_list); + ADIOI_Free(st_offsets); + ADIOI_Free(end_offsets); + } + + fd->fp_ind = orig_fp; + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + if (buftype_is_contig && filetype_is_contig) { + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + (ADIO_Offset)(fd->etype_size) * offset; + ADIO_WriteContig(fd, buf, count, datatype, + ADIO_EXPLICIT_OFFSET, + off, status, error_code); + } else + ADIO_WriteContig(fd, buf, count, datatype, ADIO_INDIVIDUAL, + 0, status, error_code); + } else { + ADIO_WriteStrided(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); + } + return; + } + + /* Get Lustre hints information */ + ADIOI_LUSTRE_Get_striping_info(fd, &striping_info, 1); + + /* calculate what portions of the access requests of this process are + * located in which process + */ + ADIOI_LUSTRE_Calc_my_req(fd, offset_list, len_list, contig_access_count, + striping_info, nprocs, &count_my_req_procs, + &count_my_req_per_proc, &my_req, + &buf_idx); + + /* based on everyone's my_req, calculate what requests of other processes + * will be accessed by this process. + * count_others_req_procs = number of processes whose requests (including + * this process itself) will be accessed by this process + * count_others_req_per_proc[i] indicates how many separate contiguous + * requests of proc. i will be accessed by this process. + */ + + ADIOI_Calc_others_req(fd, count_my_req_procs, count_my_req_per_proc, + my_req, nprocs, myrank, &count_others_req_procs, + &others_req); + ADIOI_Free(count_my_req_per_proc); + + /* exchange data and write in sizes of no more than stripe_size. */ + ADIOI_LUSTRE_Exch_and_write(fd, buf, datatype, nprocs, myrank, + others_req, my_req, offset_list, len_list, + contig_access_count, striping_info, + buf_idx, error_code); + + /* If this collective write is followed by an independent write, + * it's possible to have those subsequent writes on other processes + * race ahead and sneak in before the read-modify-write completes. + * We carry out a collective communication at the end here so no one + * can start independent i/o before collective I/O completes. + * + * need to do some gymnastics with the error codes so that if something + * went wrong, all processes report error, but if a process has a more + * specific error code, we can still have that process report the + * additional information */ + + old_error = *error_code; + if (*error_code != MPI_SUCCESS) + *error_code = MPI_ERR_IO; + + /* optimization: if only one process performing i/o, we can perform + * a less-expensive Bcast */ +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_postwrite_a, 0, NULL); +#endif + if (fd->hints->cb_nodes == 1) + MPI_Bcast(error_code, 1, MPI_INT, + fd->hints->ranklist[0], fd->comm); + else { + tmp_error = *error_code; + MPI_Allreduce(&tmp_error, error_code, 1, MPI_INT, + MPI_MAX, fd->comm); + } +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_postwrite_b, 0, NULL); +#endif + + if ((old_error != MPI_SUCCESS) && (old_error != MPI_ERR_IO)) + *error_code = old_error; + + + if (!buftype_is_contig) + ADIOI_Delete_flattened(datatype); + + /* free all memory allocated for collective I/O */ + /* free others_req */ + for (i = 0; i < nprocs; i++) { + if (others_req[i].count) { + ADIOI_Free(others_req[i].offsets); + ADIOI_Free(others_req[i].lens); + ADIOI_Free(others_req[i].mem_ptrs); + } + } + ADIOI_Free(others_req); + /* free my_req here */ + for (i = 0; i < nprocs; i++) { + if (my_req[i].count) { + ADIOI_Free(my_req[i].offsets); + ADIOI_Free(my_req[i].lens); + } + } + ADIOI_Free(my_req); + for (i = 0; i < nprocs; i++) { + ADIOI_Free(buf_idx[i]); + } + ADIOI_Free(buf_idx); + ADIOI_Free(offset_list); + ADIOI_Free(len_list); + ADIOI_Free(st_offsets); + ADIOI_Free(end_offsets); + ADIOI_Free(striping_info); + +#ifdef HAVE_STATUS_SET_BYTES + if (status) { + MPI_Count bufsize, size; + /* Don't set status if it isn't needed */ + MPI_Type_size_x(datatype, &size); + bufsize = size * count; + MPIR_Status_set_bytes(status, datatype, bufsize); + } + /* This is a temporary way of filling in status. The right way is to + * keep track of how much data was actually written during collective I/O. + */ +#endif + + fd->fp_sys_posn = -1; /* set it to null. */ +} + +/* If successful, error_code is set to MPI_SUCCESS. Otherwise an error + * code is created and returned in error_code. + */ +static void ADIOI_LUSTRE_Exch_and_write(ADIO_File fd, const void *buf, + MPI_Datatype datatype, int nprocs, + int myrank, ADIOI_Access *others_req, + ADIOI_Access *my_req, + ADIO_Offset *offset_list, + ADIO_Offset *len_list, + int contig_access_count, + int *striping_info, int **buf_idx, + int *error_code) +{ + /* Send data to appropriate processes and write in sizes of no more + * than lustre stripe_size. + * The idea is to reduce the amount of extra memory required for + * collective I/O. If all data were written all at once, which is much + * easier, it would require temp space more than the size of user_buf, + * which is often unacceptable. For example, to write a distributed + * array to a file, where each local array is 8Mbytes, requiring + * at least another 8Mbytes of temp space is unacceptable. + */ + + int hole, i, j, m, flag, ntimes = 1 , max_ntimes, buftype_is_contig; + ADIO_Offset st_loc = -1, end_loc = -1, min_st_loc, max_end_loc; + ADIO_Offset off, req_off, send_off, iter_st_off, *off_list; + ADIO_Offset max_size, step_size = 0; + int real_size, req_len, send_len; + int *recv_curr_offlen_ptr, *recv_count, *recv_size; + int *send_curr_offlen_ptr, *send_size; + int *sent_to_proc, *recv_start_pos; + int *send_buf_idx, *curr_to_proc, *done_to_proc; + int *this_buf_idx; + char *write_buf = NULL; + MPI_Status status; + ADIOI_Flatlist_node *flat_buf = NULL; + MPI_Aint buftype_extent; + int stripe_size = striping_info[0], avail_cb_nodes = striping_info[2]; + int data_sieving = 0; + ADIO_Offset *srt_off = NULL; + int *srt_len = NULL; + int srt_num = 0; + ADIO_Offset block_offset; + int block_len; + + *error_code = MPI_SUCCESS; /* changed below if error */ + /* only I/O errors are currently reported */ + + /* calculate the number of writes of stripe size to be done. + * That gives the no. of communication phases as well. + * Note: + * Because we redistribute data in stripe-contiguous pattern for Lustre, + * each process has the same no. of communication phases. + */ + + for (i = 0; i < nprocs; i++) { + if (others_req[i].count) { + st_loc = others_req[i].offsets[0]; + end_loc = others_req[i].offsets[0]; + break; + } + } + for (i = 0; i < nprocs; i++) { + for (j = 0; j < others_req[i].count; j++) { + st_loc = ADIOI_MIN(st_loc, others_req[i].offsets[j]); + end_loc = ADIOI_MAX(end_loc, (others_req[i].offsets[j] + + others_req[i].lens[j] - 1)); + } + } + /* this process does no writing. */ + if ((st_loc == -1) && (end_loc == -1)) + ntimes = 0; + MPI_Allreduce(&end_loc, &max_end_loc, 1, MPI_LONG_LONG_INT, MPI_MAX, fd->comm); + /* avoid min_st_loc be -1 */ + if (st_loc == -1) + st_loc = max_end_loc; + MPI_Allreduce(&st_loc, &min_st_loc, 1, MPI_LONG_LONG_INT, MPI_MIN, fd->comm); + /* align downward */ + min_st_loc -= min_st_loc % (ADIO_Offset)stripe_size; + + /* Each time, only avail_cb_nodes number of IO clients perform IO, + * so, step_size=avail_cb_nodes*stripe_size IO will be performed at most, + * and ntimes=whole_file_portion/step_size + */ + step_size = (ADIO_Offset) avail_cb_nodes * stripe_size; + max_ntimes = (max_end_loc - min_st_loc + 1) / step_size + + (((max_end_loc - min_st_loc + 1) % step_size) ? 1 : 0); +/* max_ntimes = (int)((max_end_loc - min_st_loc) / step_size + 1); */ + if (ntimes) + write_buf = (char *) ADIOI_Malloc(stripe_size); + + /* calculate the start offset for each iteration */ + off_list = (ADIO_Offset *) ADIOI_Malloc(max_ntimes * sizeof(ADIO_Offset)); + for (m = 0; m < max_ntimes; m ++) + off_list[m] = max_end_loc; + for (i = 0; i < nprocs; i++) { + for (j = 0; j < others_req[i].count; j ++) { + req_off = others_req[i].offsets[j]; + m = (int)((req_off - min_st_loc) / step_size); + off_list[m] = ADIOI_MIN(off_list[m], req_off); + } + } + + recv_curr_offlen_ptr = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + send_curr_offlen_ptr = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* their use is explained below. calloc initializes to 0. */ + + recv_count = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* to store count of how many off-len pairs per proc are satisfied + in an iteration. */ + + send_size = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* total size of data to be sent to each proc. in an iteration. + Of size nprocs so that I can use MPI_Alltoall later. */ + + recv_size = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* total size of data to be recd. from each proc. in an iteration. */ + + sent_to_proc = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* amount of data sent to each proc so far. Used in + ADIOI_Fill_send_buffer. initialized to 0 here. */ + + send_buf_idx = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + curr_to_proc = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + done_to_proc = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* Above three are used in ADIOI_Fill_send_buffer */ + + this_buf_idx = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + + recv_start_pos = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* used to store the starting value of recv_curr_offlen_ptr[i] in + this iteration */ + + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + if (!buftype_is_contig) { + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) + flat_buf = flat_buf->next; + } + MPI_Type_extent(datatype, &buftype_extent); + /* I need to check if there are any outstanding nonblocking writes to + * the file, which could potentially interfere with the writes taking + * place in this collective write call. Since this is not likely to be + * common, let me do the simplest thing possible here: Each process + * completes all pending nonblocking operations before completing. + */ + /*ADIOI_Complete_async(error_code); + if (*error_code != MPI_SUCCESS) return; + MPI_Barrier(fd->comm); + */ + + iter_st_off = min_st_loc; + + /* Although we have recognized the data according to OST index, + * a read-modify-write will be done if there is a hole between the data. + * For example: if blocksize=60, xfersize=30 and stripe_size=100, + * then rank0 will collect data [0, 30] and [60, 90] then write. There + * is a hole in [30, 60], which will cause a read-modify-write in [0, 90]. + * + * To reduce its impact on the performance, we can disable data sieving + * by hint "ds_in_coll". + */ + /* check the hint for data sieving */ + data_sieving = fd->hints->fs_hints.lustre.ds_in_coll; + + for (m = 0; m < max_ntimes; m++) { + /* go through all others_req and my_req to check which will be received + * and sent in this iteration. + */ + + /* Note that MPI guarantees that displacements in filetypes are in + monotonically nondecreasing order and that, for writes, the + filetypes cannot specify overlapping regions in the file. This + simplifies implementation a bit compared to reads. */ + + /* + off = start offset in the file for the data to be written in + this iteration + iter_st_off = start offset of this iteration + real_size = size of data written (bytes) corresponding to off + max_size = possible maximum size of data written in this iteration + req_off = offset in the file for a particular contiguous request minus + what was satisfied in previous iteration + send_off = offset the request needed by other processes in this iteration + req_len = size corresponding to req_off + send_len = size corresponding to send_off + */ + + /* first calculate what should be communicated */ + for (i = 0; i < nprocs; i++) + recv_count[i] = recv_size[i] = send_size[i] = 0; + + off = off_list[m]; + max_size = ADIOI_MIN(step_size, max_end_loc - iter_st_off + 1); + real_size = (int) ADIOI_MIN((off / stripe_size + 1) * stripe_size - + off, + end_loc - off + 1); + + for (i = 0; i < nprocs; i++) { + if (my_req[i].count) { + this_buf_idx[i] = buf_idx[i][send_curr_offlen_ptr[i]]; + for (j = send_curr_offlen_ptr[i]; j < my_req[i].count; j++) { + send_off = my_req[i].offsets[j]; + send_len = my_req[i].lens[j]; + if (send_off < iter_st_off + max_size) { + send_size[i] += send_len; + } else { + break; + } + } + send_curr_offlen_ptr[i] = j; + } + if (others_req[i].count) { + recv_start_pos[i] = recv_curr_offlen_ptr[i]; + for (j = recv_curr_offlen_ptr[i]; j < others_req[i].count; j++) { + req_off = others_req[i].offsets[j]; + req_len = others_req[i].lens[j]; + if (req_off < iter_st_off + max_size) { + recv_count[i]++; + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)write_buf)+req_off-off) == (ADIO_Offset)(MPIR_Upint)(write_buf+req_off-off)); + MPI_Address(write_buf + req_off - off, + &(others_req[i].mem_ptrs[j])); + recv_size[i] += req_len; + } else { + break; + } + } + recv_curr_offlen_ptr[i] = j; + } + } + /* use variable "hole" to pass data_sieving flag into W_Exchange_data */ + hole = data_sieving; + ADIOI_LUSTRE_W_Exchange_data(fd, buf, write_buf, flat_buf, offset_list, + len_list, send_size, recv_size, off, real_size, + recv_count, recv_start_pos, + sent_to_proc, nprocs, myrank, + buftype_is_contig, contig_access_count, + striping_info, others_req, send_buf_idx, + curr_to_proc, done_to_proc, &hole, m, + buftype_extent, this_buf_idx, + &srt_off, &srt_len, &srt_num, error_code); + + if (*error_code != MPI_SUCCESS) + goto over; + + flag = 0; + for (i = 0; i < nprocs; i++) + if (recv_count[i]) { + flag = 1; + break; + } + if (flag) { + /* check whether to do data sieving */ + if(data_sieving == ADIOI_HINT_ENABLE) { + ADIO_WriteContig(fd, write_buf, real_size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, off, &status, + error_code); + } else { + /* if there is no hole, write data in one time; + * otherwise, write data in several times */ + if (!hole) { + ADIO_WriteContig(fd, write_buf, real_size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, off, &status, + error_code); + } else { + block_offset = -1; + block_len = 0; + for (i = 0; i < srt_num; ++i) { + if (srt_off[i] < off + real_size && + srt_off[i] >= off) { + if (block_offset == -1) { + block_offset = srt_off[i]; + block_len = srt_len[i]; + } else { + if (srt_off[i] == block_offset + block_len) { + block_len += srt_len[i]; + } else { + ADIO_WriteContig(fd, + write_buf + block_offset - off, + block_len, + MPI_BYTE, ADIO_EXPLICIT_OFFSET, + block_offset, &status, + error_code); + if (*error_code != MPI_SUCCESS) + goto over; + block_offset = srt_off[i]; + block_len = srt_len[i]; + } + } + } + } + if (block_offset != -1) { + ADIO_WriteContig(fd, + write_buf + block_offset - off, + block_len, + MPI_BYTE, ADIO_EXPLICIT_OFFSET, + block_offset, &status, + error_code); + if (*error_code != MPI_SUCCESS) + goto over; + } + } + } + if (*error_code != MPI_SUCCESS) + goto over; + } + iter_st_off += max_size; + } +over: + if (srt_off) + ADIOI_Free(srt_off); + if (srt_len) + ADIOI_Free(srt_len); + if (ntimes) + ADIOI_Free(write_buf); + ADIOI_Free(recv_curr_offlen_ptr); + ADIOI_Free(send_curr_offlen_ptr); + ADIOI_Free(recv_count); + ADIOI_Free(send_size); + ADIOI_Free(recv_size); + ADIOI_Free(sent_to_proc); + ADIOI_Free(recv_start_pos); + ADIOI_Free(send_buf_idx); + ADIOI_Free(curr_to_proc); + ADIOI_Free(done_to_proc); + ADIOI_Free(this_buf_idx); + ADIOI_Free(off_list); +} + +/* Sets error_code to MPI_SUCCESS if successful, or creates an error code + * in the case of error. + */ +static void ADIOI_LUSTRE_W_Exchange_data(ADIO_File fd, const void *buf, + char *write_buf, + ADIOI_Flatlist_node *flat_buf, + ADIO_Offset *offset_list, + ADIO_Offset *len_list, int *send_size, + int *recv_size, ADIO_Offset off, + int size, int *count, + int *start_pos, + int *sent_to_proc, int nprocs, + int myrank, int buftype_is_contig, + int contig_access_count, + int *striping_info, + ADIOI_Access *others_req, + int *send_buf_idx, + int *curr_to_proc, int *done_to_proc, + int *hole, int iter, + MPI_Aint buftype_extent, + int *buf_idx, + ADIO_Offset **srt_off, int **srt_len, int *srt_num, + int *error_code) +{ + int i, j, nprocs_recv, nprocs_send, err; + char **send_buf = NULL; + MPI_Request *requests, *send_req; + MPI_Datatype *recv_types; + MPI_Status *statuses, status; + int sum_recv; + int data_sieving = *hole; + static char myname[] = "ADIOI_W_EXCHANGE_DATA"; + + /* create derived datatypes for recv */ + nprocs_recv = 0; + for (i = 0; i < nprocs; i++) + if (recv_size[i]) + nprocs_recv++; + + recv_types = (MPI_Datatype *) ADIOI_Malloc((nprocs_recv + 1) * + sizeof(MPI_Datatype)); + /* +1 to avoid a 0-size malloc */ + + j = 0; + for (i = 0; i < nprocs; i++) { + if (recv_size[i]) { + ADIOI_Type_create_hindexed_x(count[i], + &(others_req[i].lens[start_pos[i]]), + &(others_req[i].mem_ptrs[start_pos[i]]), + MPI_BYTE, recv_types + j); + /* absolute displacements; use MPI_BOTTOM in recv */ + MPI_Type_commit(recv_types + j); + j++; + } + } + + /* To avoid a read-modify-write, + * check if there are holes in the data to be written. + * For this, merge the (sorted) offset lists others_req using a heap-merge. + */ + + *srt_num = 0; + for (i = 0; i < nprocs; i++) + *srt_num += count[i]; + if (*srt_off) + *srt_off = (ADIO_Offset *) ADIOI_Realloc(*srt_off, (*srt_num + 1) * sizeof(ADIO_Offset)); + else + *srt_off = (ADIO_Offset *) ADIOI_Malloc((*srt_num + 1) * sizeof(ADIO_Offset)); + if (*srt_len) + *srt_len = (int *) ADIOI_Realloc(*srt_len, (*srt_num + 1) * sizeof(int)); + else + *srt_len = (int *) ADIOI_Malloc((*srt_num + 1) * sizeof(int)); + /* +1 to avoid a 0-size malloc */ + + ADIOI_Heap_merge(others_req, count, *srt_off, *srt_len, start_pos, + nprocs, nprocs_recv, *srt_num); + + /* check if there are any holes */ + *hole = 0; + for (i = 0; i < *srt_num - 1; i++) { + if ((*srt_off)[i] + (*srt_len)[i] < (*srt_off)[i + 1]) { + *hole = 1; + break; + } + } + /* In some cases (see John Bent ROMIO REQ # 835), an odd interaction + * between aggregation, nominally contiguous regions, and cb_buffer_size + * should be handled with a read-modify-write (otherwise we will write out + * more data than we receive from everyone else (inclusive), so override + * hole detection + */ + if (*hole == 0) { + sum_recv = 0; + for (i = 0; i < nprocs; i++) + sum_recv += recv_size[i]; + if (size > sum_recv) + *hole = 1; + } + /* check the hint for data sieving */ + if (data_sieving == ADIOI_HINT_ENABLE && nprocs_recv && *hole) { + ADIO_ReadContig(fd, write_buf, size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, off, &status, &err); + // --BEGIN ERROR HANDLING-- + if (err != MPI_SUCCESS) { + *error_code = MPIO_Err_create_code(err, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_IO, + "**ioRMWrdwr", 0); + ADIOI_Free(recv_types); + return; + } + // --END ERROR HANDLING-- + } + + nprocs_send = 0; + for (i = 0; i < nprocs; i++) + if (send_size[i]) + nprocs_send++; + + if (fd->atomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + requests = (MPI_Request *) ADIOI_Malloc((nprocs_send + 1) * + sizeof(MPI_Request)); + send_req = requests; + } else { + requests = (MPI_Request *) ADIOI_Malloc((nprocs_send + nprocs_recv + 1)* + sizeof(MPI_Request)); + /* +1 to avoid a 0-size malloc */ + + /* post receives */ + j = 0; + for (i = 0; i < nprocs; i++) { + if (recv_size[i]) { + MPI_Irecv(MPI_BOTTOM, 1, recv_types[j], i, + myrank + i + 100 * iter, fd->comm, requests + j); + j++; + } + } + send_req = requests + nprocs_recv; + } + + /* post sends. + * if buftype_is_contig, data can be directly sent from + * user buf at location given by buf_idx. else use send_buf. + */ + if (buftype_is_contig) { + j = 0; + for (i = 0; i < nprocs; i++) + if (send_size[i]) { + ADIOI_Assert(buf_idx[i] != -1); + MPI_Isend(((char *) buf) + buf_idx[i], send_size[i], + MPI_BYTE, i, myrank + i + 100 * iter, fd->comm, + send_req + j); + j++; + } + } else + if (nprocs_send) { + /* buftype is not contig */ + send_buf = (char **) ADIOI_Malloc(nprocs * sizeof(char *)); + for (i = 0; i < nprocs; i++) + if (send_size[i]) + send_buf[i] = (char *) ADIOI_Malloc(send_size[i]); + + ADIOI_LUSTRE_Fill_send_buffer(fd, buf, flat_buf, send_buf, offset_list, + len_list, send_size, send_req, + sent_to_proc, nprocs, myrank, + contig_access_count, striping_info, + send_buf_idx, curr_to_proc, done_to_proc, + iter, buftype_extent); + /* the send is done in ADIOI_Fill_send_buffer */ + } + + /* bug fix from Wei-keng Liao and Kenin Coloma */ + if (fd->atomicity) { + j = 0; + for (i = 0; i < nprocs; i++) { + MPI_Status wkl_status; + if (recv_size[i]) { + MPI_Recv(MPI_BOTTOM, 1, recv_types[j], i, + myrank + i + 100 * iter, fd->comm, &wkl_status); + j++; + } + } + } + + for (i = 0; i < nprocs_recv; i++) + MPI_Type_free(recv_types + i); + ADIOI_Free(recv_types); + + /* bug fix from Wei-keng Liao and Kenin Coloma */ + /* +1 to avoid a 0-size malloc */ + if (fd->atomicity) { + statuses = (MPI_Status *) ADIOI_Malloc((nprocs_send + 1) * + sizeof(MPI_Status)); + } else { + statuses = (MPI_Status *) ADIOI_Malloc((nprocs_send + nprocs_recv + 1) * + sizeof(MPI_Status)); + } + +#ifdef NEEDS_MPI_TEST + i = 0; + if (fd->atomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + while (!i) + MPI_Testall(nprocs_send, send_req, &i, statuses); + } else { + while (!i) + MPI_Testall(nprocs_send + nprocs_recv, requests, &i, statuses); + } +#else + /* bug fix from Wei-keng Liao and Kenin Coloma */ + if (fd->atomicity) + MPI_Waitall(nprocs_send, send_req, statuses); + else + MPI_Waitall(nprocs_send + nprocs_recv, requests, statuses); +#endif + ADIOI_Free(statuses); + ADIOI_Free(requests); + if (!buftype_is_contig && nprocs_send) { + for (i = 0; i < nprocs; i++) + if (send_size[i]) + ADIOI_Free(send_buf[i]); + ADIOI_Free(send_buf); + } +} + +#define ADIOI_BUF_INCR \ +{ \ + while (buf_incr) { \ + size_in_buf = ADIOI_MIN(buf_incr, flat_buf_sz); \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + buf_incr -= size_in_buf; \ + } \ +} + + +#define ADIOI_BUF_COPY \ +{ \ + while (size) { \ + size_in_buf = ADIOI_MIN(size, flat_buf_sz); \ + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + user_buf_idx) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + user_buf_idx)); \ + ADIOI_Assert(size_in_buf == (size_t)size_in_buf); \ + memcpy(&(send_buf[p][send_buf_idx[p]]), \ + ((char *) buf) + user_buf_idx, size_in_buf); \ + send_buf_idx[p] += size_in_buf; \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + size -= size_in_buf; \ + buf_incr -= size_in_buf; \ + } \ + ADIOI_BUF_INCR \ +} + +static void ADIOI_LUSTRE_Fill_send_buffer(ADIO_File fd, const void *buf, + ADIOI_Flatlist_node *flat_buf, + char **send_buf, + ADIO_Offset *offset_list, + ADIO_Offset *len_list, int *send_size, + MPI_Request *requests, + int *sent_to_proc, int nprocs, + int myrank, + int contig_access_count, + int *striping_info, + int *send_buf_idx, + int *curr_to_proc, + int *done_to_proc, int iter, + MPI_Aint buftype_extent) +{ + /* this function is only called if buftype is not contig */ + int i, p, flat_buf_idx, size; + int flat_buf_sz, buf_incr, size_in_buf, jj, n_buftypes; + ADIO_Offset off, len, rem_len, user_buf_idx; + + /* curr_to_proc[p] = amount of data sent to proc. p that has already + * been accounted for so far + * done_to_proc[p] = amount of data already sent to proc. p in + * previous iterations + * user_buf_idx = current location in user buffer + * send_buf_idx[p] = current location in send_buf of proc. p + */ + + for (i = 0; i < nprocs; i++) { + send_buf_idx[i] = curr_to_proc[i] = 0; + done_to_proc[i] = sent_to_proc[i]; + } + jj = 0; + + user_buf_idx = flat_buf->indices[0]; + flat_buf_idx = 0; + n_buftypes = 0; + flat_buf_sz = flat_buf->blocklens[0]; + + /* flat_buf_idx = current index into flattened buftype + * flat_buf_sz = size of current contiguous component in flattened buf + */ + for (i = 0; i < contig_access_count; i++) { + off = offset_list[i]; + rem_len = (ADIO_Offset) len_list[i]; + + /*this request may span to more than one process */ + while (rem_len != 0) { + len = rem_len; + /* NOTE: len value is modified by ADIOI_Calc_aggregator() to be no + * longer than the single region that processor "p" is responsible + * for. + */ + p = ADIOI_LUSTRE_Calc_aggregator(fd, off, &len, striping_info); + + if (send_buf_idx[p] < send_size[p]) { + if (curr_to_proc[p] + len > done_to_proc[p]) { + if (done_to_proc[p] > curr_to_proc[p]) { + size = (int) ADIOI_MIN(curr_to_proc[p] + len - + done_to_proc[p], + send_size[p] - + send_buf_idx[p]); + buf_incr = done_to_proc[p] - curr_to_proc[p]; + ADIOI_BUF_INCR + ADIOI_Assert((curr_to_proc[p] + len - done_to_proc[p]) == (unsigned)(curr_to_proc[p] + len - done_to_proc[p])); + buf_incr = (int) (curr_to_proc[p] + len - + done_to_proc[p]); + ADIOI_Assert((done_to_proc[p] + size) == (unsigned)(done_to_proc[p] + size)); + curr_to_proc[p] = done_to_proc[p] + size; + ADIOI_BUF_COPY + } else { + size = (int) ADIOI_MIN(len, send_size[p] - + send_buf_idx[p]); + buf_incr = (int) len; + ADIOI_Assert((curr_to_proc[p] + size) == (unsigned)((ADIO_Offset)curr_to_proc[p] + size)); + curr_to_proc[p] += size; + ADIOI_BUF_COPY + } + if (send_buf_idx[p] == send_size[p]) { + MPI_Isend(send_buf[p], send_size[p], MPI_BYTE, p, + myrank + p + 100 * iter, fd->comm, + requests + jj); + jj++; + } + } else { + ADIOI_Assert((curr_to_proc[p] + len) == (unsigned)((ADIO_Offset)curr_to_proc[p] + len)); + curr_to_proc[p] += (int) len; + buf_incr = (int) len; + ADIOI_BUF_INCR + } + } else { + buf_incr = (int) len; + ADIOI_BUF_INCR + } + off += len; + rem_len -= len; + } + } + for (i = 0; i < nprocs; i++) + if (send_size[i]) + sent_to_proc[i] = curr_to_proc[i]; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_wrstr.c b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_wrstr.c new file mode 100644 index 0000000000..2f1ffb963a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_lustre/ad_lustre_wrstr.c @@ -0,0 +1,533 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + * Copyright (C) 2007 Oak Ridge National Laboratory + * + * Copyright (C) 2008 Sun Microsystems, Lustre group + */ + +#include "ad_lustre.h" +#include "adio_extern.h" + +#define ADIOI_BUFFERED_WRITE \ +{ \ + if (req_off >= writebuf_off + writebuf_len) { \ + if (writebuf_len) { \ + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, \ + &status1, error_code); \ + if (!(fd->atomicity)) \ + ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, \ + myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowswc", 0); \ + ADIOI_Free(writebuf); \ + return; \ + } \ + } \ + writebuf_off = req_off; \ + /* stripe_size alignment */ \ + writebuf_len = (unsigned) ADIOI_MIN(end_offset - writebuf_off + 1, \ + (writebuf_off / stripe_size + 1) * \ + stripe_size - writebuf_off); \ + if (!(fd->atomicity)) \ + ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + ADIO_ReadContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, \ + writebuf_off, &status1, error_code); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, \ + myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowsrc", 0); \ + ADIOI_Free(writebuf); \ + return; \ + } \ + } \ + write_sz = (unsigned) (ADIOI_MIN(req_len, \ + writebuf_off + writebuf_len - req_off)); \ + ADIOI_Assert((ADIO_Offset)write_sz == \ + ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \ + memcpy(writebuf + req_off - writebuf_off, (char *)buf +userbuf_off, write_sz); \ + while (write_sz != req_len) { \ + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \ + if (!(fd->atomicity)) \ + ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowswc", 0); \ + ADIOI_Free(writebuf); \ + return; \ + } \ + req_len -= write_sz; \ + userbuf_off += write_sz; \ + writebuf_off += writebuf_len; \ + /* stripe_size alignment */ \ + writebuf_len = (unsigned) ADIOI_MIN(end_offset - writebuf_off + 1, \ + (writebuf_off / stripe_size + 1) * \ + stripe_size - writebuf_off); \ + if (!(fd->atomicity)) \ + ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + ADIO_ReadContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, \ + writebuf_off, &status1, error_code); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowsrc", 0); \ + ADIOI_Free(writebuf); \ + return; \ + } \ + write_sz = ADIOI_MIN(req_len, writebuf_len); \ + memcpy(writebuf, (char *)buf + userbuf_off, write_sz); \ + } \ +} + + +/* this macro is used when filetype is contig and buftype is not contig. + it does not do a read-modify-write and does not lock*/ +#define ADIOI_BUFFERED_WRITE_WITHOUT_READ \ +{ \ + if (req_off >= writebuf_off + writebuf_len) { \ + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, \ + error_code); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, \ + myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowswc", 0); \ + ADIOI_Free(writebuf); \ + return; \ + } \ + writebuf_off = req_off; \ + /* stripe_size alignment */ \ + writebuf_len = (unsigned) ADIOI_MIN(end_offset - writebuf_off + 1, \ + (writebuf_off / stripe_size + 1) * \ + stripe_size - writebuf_off); \ + } \ + write_sz = (unsigned) ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off); \ + ADIOI_Assert((ADIO_Offset)write_sz == ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \ + memcpy(writebuf + req_off - writebuf_off, \ + (char *)buf + userbuf_off, write_sz); \ + while (write_sz != req_len) { \ + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowswc", 0); \ + ADIOI_Free(writebuf); \ + return; \ + } \ + req_len -= write_sz; \ + userbuf_off += write_sz; \ + writebuf_off += writebuf_len; \ + /* stripe_size alignment */ \ + writebuf_len = (unsigned) ADIOI_MIN(end_offset - writebuf_off + 1, \ + (writebuf_off / stripe_size + 1) * \ + stripe_size - writebuf_off); \ + write_sz = ADIOI_MIN(req_len, writebuf_len); \ + memcpy(writebuf, (char *)buf + userbuf_off, write_sz); \ + } \ +} + +void ADIOI_LUSTRE_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; + 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; + 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; + 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_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)(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; icount; 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 { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + k = num = buf_count = 0; + i_offset = flat_buf->indices[0]; + j = st_index; + off = offset; + n_filetypes = st_n_filetypes; + fwr_size = st_fwr_size; + bwr_size = flat_buf->blocklens[0]; + + while (num < bufsize) { + size = ADIOI_MIN(fwr_size, bwr_size); + if (size) { + /* lseek(fd->fd_sys, off, SEEK_SET); + err = write(fd->fd_sys, ((char *) buf) + i_offset, size); */ + + req_off = off; + req_len = size; + userbuf_off = i_offset; + ADIOI_BUFFERED_WRITE + } + + new_fwr_size = fwr_size; + new_bwr_size = bwr_size; + + if (size == fwr_size) { +/* reached end of contiguous block in file */ + 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; + + new_fwr_size = flat_file->blocklens[j]; + if (size != bwr_size) { + i_offset += size; + new_bwr_size -= size; + } + } + + if (size == bwr_size) { +/* reached end of contiguous block in memory */ + + k = (k + 1)%flat_buf->count; + buf_count++; + i_offset = (ADIO_Offset)buftype_extent * + (ADIO_Offset)(buf_count/flat_buf->count) + + flat_buf->indices[k]; + new_bwr_size = flat_buf->blocklens[k]; + if (size != fwr_size) { + off += size; + new_fwr_size -= size; + } + } + num += size; + fwr_size = new_fwr_size; + bwr_size = new_bwr_size; + } + } + + /* write the buffer out finally */ + if (writebuf_len) { + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, + writebuf_off, &status1, error_code); + if (!(fd->atomicity)) + ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); + if (*error_code != MPI_SUCCESS) return; + } + if (fd->atomicity) + ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); + + ADIOI_Free(writebuf); + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; + } + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + if (!buftype_is_contig) + ADIOI_Delete_flattened(datatype); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_nfs/Makefile.mk new file mode 100644 index 0000000000..ca25e20cbe --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/Makefile.mk @@ -0,0 +1,28 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_NFS + +noinst_HEADERS += adio/ad_nfs/ad_nfs.h + +romio_other_sources += \ + adio/ad_nfs/ad_nfs_read.c \ + adio/ad_nfs/ad_nfs_open.c \ + adio/ad_nfs/ad_nfs_write.c \ + adio/ad_nfs/ad_nfs_done.c \ + adio/ad_nfs/ad_nfs_fcntl.c \ + adio/ad_nfs/ad_nfs_iread.c \ + adio/ad_nfs/ad_nfs_iwrite.c \ + adio/ad_nfs/ad_nfs_wait.c \ + adio/ad_nfs/ad_nfs_setsh.c \ + adio/ad_nfs/ad_nfs_getsh.c \ + adio/ad_nfs/ad_nfs.c \ + adio/ad_nfs/ad_nfs_resize.c \ + adio/ad_nfs/ad_nfs_features.c + +endif BUILD_AD_NFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs.c new file mode 100644 index 0000000000..725c4d1ead --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs.c @@ -0,0 +1,41 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_NFS_operations = { + ADIOI_NFS_Open, /* Open */ + ADIOI_FAILSAFE_OpenColl, /* OpenColl */ + ADIOI_NFS_ReadContig, /* ReadContig */ + ADIOI_NFS_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_NFS_Fcntl, /* Fcntl */ + ADIOI_GEN_SetInfo, /* SetInfo */ + ADIOI_NFS_ReadStrided, /* ReadStrided */ + ADIOI_NFS_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ + /* Even with lockd running and NFS mounted 'noac', we have been unable to + * gaurantee correct behavior over NFS with asyncronous I/O operations */ + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ + ADIOI_NFS_ReadDone, /* ReadDone */ + ADIOI_NFS_WriteDone, /* WriteDone */ + ADIOI_NFS_ReadComplete, /* ReadComplete */ + ADIOI_NFS_WriteComplete, /* WriteComplete */ + ADIOI_GEN_IreadStrided, /* IreadStrided */ + ADIOI_GEN_IwriteStrided, /* IwriteStrided */ + ADIOI_GEN_Flush, /* Flush */ + ADIOI_NFS_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ + ADIOI_NFS_Feature, /* Features */ + "NFS:" /* fsname: just a string */ +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs.h b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs.h new file mode 100644 index 0000000000..83d394af61 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs.h @@ -0,0 +1,83 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_NFS_INCLUDE +#define AD_NFS_INCLUDE + +#include +#include +#include +#include "adio.h" + +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + +/* Workaround for incomplete set of definitions if __REDIRECT is not + defined and large file support is used in aio.h */ +#if !defined(__REDIRECT) && defined(__USE_FILE_OFFSET64) +#define aiocb aiocb64 +#endif + +int ADIOI_NFS_aio(ADIO_File fd, void *buf, int len, ADIO_Offset offset, + int wr, MPI_Request *request); + +#ifdef SX4 +#define lseek llseek +#endif + +void ADIOI_NFS_Open(ADIO_File fd, int *error_code); +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); +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); +void ADIOI_NFS_IwriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_NFS_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +int ADIOI_NFS_ReadDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +int ADIOI_NFS_WriteDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_NFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_NFS_WriteComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIOI_NFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *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); +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); +void ADIOI_NFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); +void ADIOI_NFS_Get_shared_fp(ADIO_File fd, ADIO_Offset size, ADIO_Offset *shared_fp, + int *error_code); +void ADIOI_NFS_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, int *error_code); +void ADIOI_NFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +int ADIOI_NFS_Feature(ADIO_File fd, int feature_flag); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_done.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_done.c new file mode 100644 index 0000000000..ff688546ca --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_done.c @@ -0,0 +1,19 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +int ADIOI_NFS_ReadDone(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + *error_code = MPI_SUCCESS; + return 1; +} +int ADIOI_NFS_WriteDone(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + return ADIOI_NFS_ReadDone(request, status, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_fcntl.c new file mode 100644 index 0000000000..c73006e6cd --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_fcntl.c @@ -0,0 +1,65 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" +#include "adio_extern.h" +/* #ifdef MPISGI +#include "mpisgi2.h" +#endif */ + +void ADIOI_NFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code) +{ + static char myname[] = "ADIOI_NFS_FCNTL"; + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + ADIOI_READ_LOCK(fd, 0, SEEK_SET, 1); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + fcntl_struct->fsize = lseek(fd->fd_sys, 0, SEEK_END); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + ADIOI_UNLOCK(fd, 0, SEEK_SET, 1); + if (fd->fp_sys_posn != -1) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + lseek(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + } + if (fcntl_struct->fsize == -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; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + ADIOI_GEN_Prealloc(fd, fcntl_struct->diskspace, error_code); + break; + + case ADIO_FCNTL_SET_ATOMICITY: + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + *error_code = MPI_SUCCESS; + break; + + default: + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**flag", "**flag %d", flag); + return; + /* --END ERROR HANDLING-- */ + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_features.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_features.c new file mode 100644 index 0000000000..05b061acf4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_features.c @@ -0,0 +1,24 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "adio.h" +#include "ad_nfs.h" + +int ADIOI_NFS_Feature(ADIO_File fd, int flag) +{ + switch(flag) { + case ADIO_SHARED_FP: + case ADIO_LOCKS: + case ADIO_SEQUENTIAL: + case ADIO_DATA_SIEVING_WRITES: + return 1; + case ADIO_SCALABLE_OPEN: + case ADIO_UNLINK_AFTER_CLOSE: + case ADIO_SCALABLE_RESIZE: + default: + return 0; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_getsh.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_getsh.c new file mode 100644 index 0000000000..974d547cc1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_getsh.c @@ -0,0 +1,105 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +/* returns the current location of the shared_fp in terms of the + no. of etypes relative to the current view, and also increments the + shared_fp by the number of etypes to be accessed (incr) in the read + or write following this function. */ + +void ADIOI_NFS_Get_shared_fp(ADIO_File fd, ADIO_Offset incr, ADIO_Offset *shared_fp, + int *error_code) +{ + ADIO_Offset new_fp; + ssize_t 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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_hints.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_hints.c new file mode 100644 index 0000000000..0e5386d22b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_hints.c @@ -0,0 +1,13 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +void ADIOI_NFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ + ADIOI_GEN_SetInfo(fd, users_info, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_iread.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_iread.c new file mode 100644 index 0000000000..28d2028105 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_iread.c @@ -0,0 +1,37 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +#ifdef ROMIO_HAVE_WORKING_AIO +/* nearly identical to ADIOI_GEN_IreadContig, except we lock around I/O */ +void ADIOI_NFS_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code) +{ + MPI_Count len, typesize; + int aio_errno = 0; + static char myname[] = "ADIOI_NFS_IREADCONTIG"; + + MPI_Type_size_x(datatype, &typesize); + len = count * typesize; + + if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind; + aio_errno = ADIOI_NFS_aio(fd, buf, len, offset, 0, request); + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += len; + + fd->fp_sys_posn = -1; + + if (aio_errno != 0) { + /* --BEGIN ERROR HANDLING-- */ + MPIO_ERR_CREATE_CODE_ERRNO(myname, aio_errno, error_code); + return; + /* --END ERROR HANDLING-- */ + } + else *error_code = MPI_SUCCESS; +} +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_iwrite.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_iwrite.c new file mode 100644 index 0000000000..f27b099fa5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_iwrite.c @@ -0,0 +1,130 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +#include "../../mpi-io/mpioimpl.h" +#include "../../mpi-io/mpioprof.h" +#include "mpiu_greq.h" + +#include + +#ifdef ROMIO_HAVE_WORKING_AIO +static MPIX_Grequest_class ADIOI_GEN_greq_class = 0; +/* this routine is nearly identical to ADIOI_GEN_IwriteContig, except we lock + * around I/O */ +void ADIOI_NFS_IwriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int *error_code) +{ + MPI_Count len, typesize; + int aio_errno = 0; + static char myname[] = "ADIOI_NFS_IWRITECONTIG"; + + MPI_Type_size_x(datatype, &typesize); + len = count * typesize; + + if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind; + aio_errno = ADIOI_NFS_aio(fd, buf, len, offset, 1, request); + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += len; + + fd->fp_sys_posn = -1; + + if (aio_errno != 0) { + /* --BEGIN ERROR HANDLING-- */ + MPIO_ERR_CREATE_CODE_ERRNO(myname, aio_errno, error_code); + return; + /* --END ERROR HANDLING-- */ + } + else *error_code = MPI_SUCCESS; + return; +} +#endif + +/* This function is for implementation convenience. It is not user-visible. + * It takes care of the differences in the interface for nonblocking I/O + * on various Unix machines! If wr==1 write, wr==0 read. + * + * Returns 0 on success, -errno on failure. + */ +#ifdef ROMIO_HAVE_WORKING_AIO +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; + MPI_Status status; + + 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, &status, &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; +} +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_open.c new file mode 100644 index 0000000000..d8763292b9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_open.c @@ -0,0 +1,58 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +void ADIOI_NFS_Open(ADIO_File fd, int *error_code) +{ + int perm, amode; + mode_t old_mask; + static char myname[] = "ADIOI_NFS_OPEN"; + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_a, 0, NULL ); +#endif + fd->fd_sys = open(fd->filename, amode, perm); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_b, 0, NULL ); +#endif + fd->fd_direct = -1; + + if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND)) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + fd->fp_ind = fd->fp_sys_posn = lseek(fd->fd_sys, 0, SEEK_END); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + } + + if (fd->fd_sys == -1) { + *error_code = ADIOI_Err_create_code(myname, fd->filename, errno); + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_read.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_read.c new file mode 100644 index 0000000000..18dfde712c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_read.c @@ -0,0 +1,553 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" +#include "adio_extern.h" + +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; + MPI_Count datatype_size, len; + static char myname[] = "ADIOI_NFS_READCONTIG"; + + 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 + } + if (fd->atomicity) + ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); + else ADIOI_READ_LOCK(fd, offset, SEEK_SET, len); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); +#endif + err = read(fd->fd_sys, buf, len); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + 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) { +#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 + } + if (fd->atomicity) + ADIOI_WRITE_LOCK(fd, offset, SEEK_SET, len); + else ADIOI_READ_LOCK(fd, offset, SEEK_SET, len); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); +#endif + err = read(fd->fd_sys, buf, len); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_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; +} + + + +#ifdef ADIOI_MPE_LOGGING +#define ADIOI_BUFFERED_READ \ +{ \ + if (req_off >= readbuf_off + readbuf_len) { \ + readbuf_off = req_off; \ + readbuf_len = (int) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1));\ + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); \ + lseek(fd->fd_sys, readbuf_off, SEEK_SET);\ + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_READ_LOCK(fd, readbuf_off, SEEK_SET, readbuf_len);\ + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); \ + err = read(fd->fd_sys, readbuf, readbuf_len);\ + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_UNLOCK(fd, readbuf_off, SEEK_SET, readbuf_len);\ + if (err == -1) err_flag = 1; \ + } \ + while (req_len > readbuf_off + readbuf_len - req_off) { \ + partial_read = (int) (readbuf_off + readbuf_len - req_off); \ + tmp_buf = (char *) ADIOI_Malloc(partial_read); \ + memcpy(tmp_buf, readbuf+readbuf_len-partial_read, partial_read); \ + ADIOI_Free(readbuf); \ + readbuf = (char *) ADIOI_Malloc(partial_read + max_bufsize); \ + memcpy(readbuf, tmp_buf, partial_read); \ + ADIOI_Free(tmp_buf); \ + readbuf_off += readbuf_len-partial_read; \ + readbuf_len = (int) (partial_read + ADIOI_MIN(max_bufsize, \ + end_offset-readbuf_off+1)); \ + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); \ + lseek(fd->fd_sys, readbuf_off+partial_read, SEEK_SET);\ + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_READ_LOCK(fd, readbuf_off+partial_read, SEEK_SET, readbuf_len-partial_read);\ + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); \ + err = read(fd->fd_sys, readbuf+partial_read, readbuf_len-partial_read);\ + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_UNLOCK(fd, readbuf_off+partial_read, SEEK_SET, readbuf_len-partial_read);\ + if (err == -1) err_flag = 1; \ + } \ + memcpy((char *)buf + userbuf_off, readbuf+req_off-readbuf_off, req_len); \ +} +#else +#define ADIOI_BUFFERED_READ \ +{ \ + if (req_off >= readbuf_off + readbuf_len) { \ + readbuf_off = req_off; \ + readbuf_len = (int) (ADIOI_MIN(max_bufsize, end_offset-readbuf_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; \ + } \ + while (req_len > readbuf_off + readbuf_len - req_off) { \ + partial_read = (int) (readbuf_off + readbuf_len - req_off); \ + tmp_buf = (char *) ADIOI_Malloc(partial_read); \ + memcpy(tmp_buf, readbuf+readbuf_len-partial_read, partial_read); \ + ADIOI_Free(readbuf); \ + readbuf = (char *) ADIOI_Malloc(partial_read + max_bufsize); \ + memcpy(readbuf, tmp_buf, partial_read); \ + ADIOI_Free(tmp_buf); \ + readbuf_off += readbuf_len-partial_read; \ + readbuf_len = (int) (partial_read + ADIOI_MIN(max_bufsize, \ + end_offset-readbuf_off+1)); \ + lseek(fd->fd_sys, readbuf_off+partial_read, SEEK_SET);\ + if (!(fd->atomicity)) ADIOI_READ_LOCK(fd, readbuf_off+partial_read, SEEK_SET, readbuf_len-partial_read);\ + err = read(fd->fd_sys, readbuf+partial_read, readbuf_len-partial_read);\ + if (!(fd->atomicity)) ADIOI_UNLOCK(fd, readbuf_off+partial_read, SEEK_SET, readbuf_len-partial_read);\ + if (err == -1) err_flag = 1; \ + } \ + memcpy((char *)buf + userbuf_off, readbuf+req_off-readbuf_off, req_len); \ +} +#endif + + +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 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_frd_size, st_n_filetypes, readbuf_len; + int new_brd_size, new_frd_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; jcount; 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; icount; 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; icount; 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 { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + k = num = buf_count = 0; + i = (int) (flat_buf->indices[0]); + j = st_index; + off = offset; + n_filetypes = st_n_filetypes; + frd_size = st_frd_size; + brd_size = flat_buf->blocklens[0]; + + while (num < bufsize) { + size = ADIOI_MIN(frd_size, brd_size); + if (size) { + /* lseek(fd->fd_sys, off, SEEK_SET); + err = read(fd->fd_sys, ((char *) buf) + i, size); */ + + req_off = off; + req_len = size; + userbuf_off = i; + ADIOI_BUFFERED_READ + } + + new_frd_size = frd_size; + new_brd_size = brd_size; + + if (size == frd_size) { +/* reached end of contiguous block in file */ + 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; + + new_frd_size = flat_file->blocklens[j]; + if (size != brd_size) { + i += size; + new_brd_size -= size; + } + } + + if (size == brd_size) { +/* reached end of contiguous block in memory */ + + k = (k + 1)%flat_buf->count; + buf_count++; + i = (int) (buftype_extent*(buf_count/flat_buf->count) + + flat_buf->indices[k]); + new_brd_size = flat_buf->blocklens[k]; + if (size != frd_size) { + off += size; + new_frd_size -= size; + } + } + num += size; + frd_size = new_frd_size; + brd_size = new_brd_size; + } + } + + 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; + } + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, 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 + by ADIOI_BUFFERED_READ. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_resize.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_resize.c new file mode 100644 index 0000000000..d86dfcc77e --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_resize.c @@ -0,0 +1,35 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +/* NFS resize + * + * Note: we resize on all processors to guarantee that all processors + * will have updated cache values. This used to be the generic + * implementation used by the majority of the ADIO implementations. + */ +void ADIOI_NFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int err; + static char myname[] = "ADIOI_NFS_RESIZE"; + + err = ftruncate(fd->fd_sys, size); + + /* --BEGIN ERROR HANDLING-- */ + if (err == -1) { + *error_code = ADIOI_Err_create_code(myname, fd->filename, errno); + return; + } + /* --END ERROR HANDLING-- */ + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_setsh.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_setsh.c new file mode 100644 index 0000000000..42e558cb47 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_setsh.c @@ -0,0 +1,74 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +/* set the shared file pointer to "offset" etypes relative to the current + view */ + +/* +This looks very similar to ADIOI_GEN_Set_shared_fp, except this +function avoids locking the file twice. The generic version does + +Write lock +ADIO_WriteContig +Unlock + +For NFS, ADIOI_NFS_WriteContig does a lock before writing to disable +caching. To avoid the lock being called twice, this version for NFS does + +Write lock +Lseek +Write +Unlock + +*/ + +void ADIOI_NFS_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, int *error_code) +{ + ssize_t err; + MPI_Comm dupcommself; + static char myname[] = "ADIOI_NFS_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)); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + lseek(fd->shared_fp_fd->fd_sys, 0, 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_write_a, 0, NULL ); +#endif + err = write(fd->shared_fp_fd->fd_sys, &offset, sizeof(ADIO_Offset)); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + 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; +} + diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_wait.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_wait.c new file mode 100644 index 0000000000..e1037fc551 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_wait.c @@ -0,0 +1,20 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" + +void ADIOI_NFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + return; +} + + +void ADIOI_NFS_WriteComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + ADIOI_NFS_ReadComplete(request, status, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_write.c b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_write.c new file mode 100644 index 0000000000..660e8682d9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_nfs/ad_nfs_write.c @@ -0,0 +1,679 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_nfs.h" +#include "adio_extern.h" + +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; +} + + + + +#ifdef ADIOI_MPE_LOGGING +#define ADIOI_BUFFERED_WRITE \ +{ \ + if (req_off >= writebuf_off + writebuf_len) { \ + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); \ + lseek(fd->fd_sys, writebuf_off, SEEK_SET); \ + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); \ + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); \ + err = write(fd->fd_sys, writebuf, writebuf_len); \ + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + if (err == -1) err_flag = 1; \ + writebuf_off = req_off; \ + 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); \ + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); \ + lseek(fd->fd_sys, writebuf_off, SEEK_SET); \ + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); \ + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); \ + err = read(fd->fd_sys, writebuf, writebuf_len); \ + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); \ + if (err == -1) { \ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**ioRMWrdwr", 0); \ + goto fn_exit; \ + } \ + } \ + write_sz = (int) (ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \ + memcpy(writebuf+req_off-writebuf_off, (char *)buf +userbuf_off, write_sz);\ + while (write_sz != req_len) { \ + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); \ + lseek(fd->fd_sys, writebuf_off, SEEK_SET); \ + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); \ + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); \ + err = write(fd->fd_sys, writebuf, writebuf_len); \ + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + if (err == -1) err_flag = 1; \ + req_len -= write_sz; \ + userbuf_off += write_sz; \ + writebuf_off += writebuf_len; \ + 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); \ + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); \ + lseek(fd->fd_sys, writebuf_off, SEEK_SET); \ + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); \ + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); \ + err = read(fd->fd_sys, writebuf, writebuf_len); \ + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); \ + if (err == -1) { \ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**ioRMWrdwr", 0); \ + goto fn_exit; \ + } \ + write_sz = ADIOI_MIN(req_len, writebuf_len); \ + memcpy(writebuf, (char *)buf + userbuf_off, write_sz);\ + } \ +} +#else +#define ADIOI_BUFFERED_WRITE \ +{ \ + if (req_off >= writebuf_off + writebuf_len) { \ + lseek(fd->fd_sys, writebuf_off, SEEK_SET); \ + 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; \ + writebuf_off = req_off; \ + 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, \ + "**ioRMWrdwr", 0); \ + goto fn_exit; \ + } \ + } \ + write_sz = (int) (ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \ + memcpy(writebuf+req_off-writebuf_off, (char *)buf +userbuf_off, write_sz);\ + while (write_sz != req_len) { \ + lseek(fd->fd_sys, writebuf_off, SEEK_SET); \ + 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; \ + req_len -= write_sz; \ + userbuf_off += write_sz; \ + writebuf_off += writebuf_len; \ + 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, \ + "**ioRMWrdwr", 0); \ + goto fn_exit; \ + } \ + write_sz = ADIOI_MIN(req_len, writebuf_len); \ + memcpy(writebuf, (char *)buf + userbuf_off, write_sz);\ + } \ +} +#endif + +/* this macro is used when filetype is contig and buftype is not contig. + it does not do a read-modify-write and does not lock*/ +#ifdef ADIOI_MPE_LOGGING +#define ADIOI_BUFFERED_WRITE_WITHOUT_READ \ +{ \ + if (req_off >= writebuf_off + writebuf_len) { \ + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); \ + lseek(fd->fd_sys, writebuf_off, SEEK_SET); \ + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); \ + err = write(fd->fd_sys, writebuf, writebuf_len); \ + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + if (err == -1) err_flag = 1; \ + writebuf_off = req_off; \ + writebuf_len = (int) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\ + } \ + write_sz = (int) (ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \ + memcpy(writebuf+req_off-writebuf_off, (char *)buf +userbuf_off, write_sz);\ + while (write_sz != req_len) { \ + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); \ + lseek(fd->fd_sys, writebuf_off, SEEK_SET); \ + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); \ + err = write(fd->fd_sys, writebuf, writebuf_len); \ + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); \ + if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + if (err == -1) err_flag = 1; \ + req_len -= write_sz; \ + userbuf_off += write_sz; \ + writebuf_off += writebuf_len; \ + writebuf_len = (int) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\ + write_sz = ADIOI_MIN(req_len, writebuf_len); \ + memcpy(writebuf, (char *)buf + userbuf_off, write_sz);\ + } \ +} +#else +#define ADIOI_BUFFERED_WRITE_WITHOUT_READ \ +{ \ + if (req_off >= writebuf_off + writebuf_len) { \ + 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; \ + writebuf_off = req_off; \ + writebuf_len = (int) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\ + } \ + write_sz = (int) (ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \ + memcpy(writebuf+req_off-writebuf_off, (char *)buf +userbuf_off, write_sz);\ + while (write_sz != req_len) { \ + 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; \ + req_len -= write_sz; \ + userbuf_off += write_sz; \ + writebuf_off += writebuf_len; \ + writebuf_len = (int) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\ + write_sz = ADIOI_MIN(req_len, writebuf_len); \ + memcpy(writebuf, (char *)buf + userbuf_off, write_sz);\ + } \ +} +#endif + + +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, 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 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_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_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. */ + + 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; jcount; 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 */ + +/* 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; icount; 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 = (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; icount; 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) { + ADIO_WriteContig(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 == 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 + 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 = 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; + 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; + 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); +#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 = 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 { + 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; + fwr_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i); + } + } + } + else { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + k = num = buf_count = 0; + i = (int) (flat_buf->indices[0]); + j = st_index; + off = offset; + n_filetypes = st_n_filetypes; + fwr_size = st_fwr_size; + bwr_size = flat_buf->blocklens[0]; + + while (num < bufsize) { + size = ADIOI_MIN(fwr_size, bwr_size); + if (size) { + /* lseek(fd->fd_sys, off, SEEK_SET); + err = write(fd->fd_sys, ((char *) buf) + i, size); */ + + req_off = off; + req_len = size; + userbuf_off = i; + ADIOI_BUFFERED_WRITE + } + + new_fwr_size = fwr_size; + new_bwr_size = bwr_size; + + if (size == fwr_size) { +/* reached end of contiguous block in file */ + 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; + + new_fwr_size = flat_file->blocklens[j]; + if (size != bwr_size) { + i += size; + new_bwr_size -= size; + } + } + + if (size == bwr_size) { +/* reached end of contiguous block in memory */ + + k = (k + 1)%flat_buf->count; + buf_count++; + i = (int) (buftype_extent*(buf_count/flat_buf->count) + + flat_buf->indices[k]); + new_bwr_size = flat_buf->blocklens[k]; + if (size != fwr_size) { + off += size; + new_fwr_size -= size; + } + } + num += size; + fwr_size = new_fwr_size; + bwr_size = new_bwr_size; + } + } + + /* 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); + else ADIOI_UNLOCK(fd, start_off, SEEK_SET, end_offset-start_off+1); + + if (err == -1) err_flag = 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; + } + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +fn_exit: + if (writebuf != NULL) ADIOI_Free(writebuf); + + return; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs.c new file mode 100644 index 0000000000..8789fc378c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs.c @@ -0,0 +1,38 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_NTFS_operations = { + ADIOI_NTFS_Open, /* Open */ + ADIOI_FAILSAFE_OpenColl, /* OpenColl */ + ADIOI_NTFS_ReadContig, /* ReadContig */ + ADIOI_NTFS_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_NTFS_Fcntl, /* Fcntl */ + ADIOI_GEN_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_GEN_WriteStrided, /* WriteStrided */ + ADIOI_NTFS_Close, /* Close */ + ADIOI_NTFS_IreadContig, /* IreadContig */ + ADIOI_NTFS_IwriteContig, /* IwriteContig */ + ADIOI_NTFS_ReadDone, /* ReadDone */ + ADIOI_NTFS_WriteDone, /* WriteDone */ + ADIOI_NTFS_ReadComplete, /* ReadComplete */ + ADIOI_NTFS_WriteComplete, /* WriteComplete */ + ADIOI_FAKE_IreadStrided, /* IreadStrided */ + ADIOI_FAKE_IwriteStrided, /* IwriteStrided */ + ADIOI_NTFS_Flush, /* Flush */ + ADIOI_NTFS_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ + ADIOI_NTFS_Feature /* Features */ +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs.h b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs.h new file mode 100644 index 0000000000..aed6168bd8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_NTFS_INCLUDE +#define AD_NTFS_INCLUDE + +#include +#include +#include "adio.h" + +#ifdef HAVE_INT64 +#define DWORDLOW(x) ( (DWORD) ( x & (__int64) 0xFFFFFFFF ) ) +#define DWORDHIGH(x) ( (DWORD) ( (x >> 32) & (__int64) 0xFFFFFFFF ) ) +#define DWORDTOINT64(x,y) ( (__int64) ( ( (__int64 x) << 32 ) + (__int64) y ) ) +#else +#define DWORDLOW(x) x +#define DWORDHIGH(x) 0 +#define DWORDTOINT64(x,y) x +#endif + +int ADIOI_NTFS_aio(ADIO_File fd, void *buf, int len, ADIO_Offset offset, + int wr, void *handle); + +void ADIOI_NTFS_Open(ADIO_File fd, int *error_code); +void ADIOI_NTFS_Close(ADIO_File fd, int *error_code); +void ADIOI_NTFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_NTFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_NTFS_IwriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_NTFS_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +int ADIOI_NTFS_ReadDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +int ADIOI_NTFS_WriteDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_NTFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_NTFS_WriteComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIOI_NTFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIOI_NTFS_IwriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_NTFS_Flush(ADIO_File fd, int *error_code); +void ADIOI_NTFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); + +#define FORMAT_MESSAGE_MIN_SIZE 100 +#define ADIOI_NTFS_ERR_MSG_MAX FORMAT_MESSAGE_MIN_SIZE +void ADIOI_NTFS_Strerror(int error, char *errMsg, int errMsgLen); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_close.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_close.c new file mode 100644 index 0000000000..95022dca77 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_close.c @@ -0,0 +1,30 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +void ADIOI_NTFS_Close(ADIO_File fd, int *error_code) +{ + int err; + static char myname[] = "ADIOI_NTFS_Close"; + + err = CloseHandle(fd->fd_sys); + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + return; + } + /* --END ERROR HANDLING-- */ + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_done.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_done.c new file mode 100644 index 0000000000..9f4967b48b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_done.c @@ -0,0 +1,20 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +int ADIOI_NTFS_ReadDone(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + return 0; +} + + +int ADIOI_NTFS_WriteDone(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + return 0; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_fcntl.c new file mode 100644 index 0000000000..4c7d66cd07 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_fcntl.c @@ -0,0 +1,76 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" +#include "adio_extern.h" + +void ADIOI_NTFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code) +{ + DWORD err; + LONG dwTemp; + static char myname[] = "ADIOI_NTFS_FCNTL"; + + switch(flag) + { + case ADIO_FCNTL_GET_FSIZE: + fcntl_struct->fsize = SetFilePointer(fd->fd_sys, 0, 0, FILE_END); + if (fd->fp_sys_posn != -1) + { + dwTemp = DWORDHIGH(fd->fp_sys_posn); + if (SetFilePointer(fd->fd_sys, DWORDLOW(fd->fp_sys_posn), &dwTemp, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + if (err != NO_ERROR) + { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + return; + } + } + } + /* --BEGIN ERROR HANDLING-- */ + if (fcntl_struct->fsize == INVALID_SET_FILE_POINTER) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + dwTemp = GetLastError(); + ADIOI_NTFS_Strerror(dwTemp, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, "**io", + "**io %s", errMsg); + return; + } + /* --END ERROR HANDLING-- */ + *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + ADIOI_GEN_Prealloc(fd, fcntl_struct->diskspace, error_code); + break; + + case ADIO_FCNTL_SET_ATOMICITY: + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + *error_code = MPI_SUCCESS; + /* + fd->atomicity = 0; + *error_code = MPI_ERR_UNSUPPORTED_OPERATION; + */ + break; + + default: + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**flag", "**flag %d", flag); + return; + /* --END ERROR HANDLING-- */ + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_feature.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_feature.c new file mode 100644 index 0000000000..335b5aed57 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_feature.c @@ -0,0 +1,26 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "adio.h" + +int ADIOI_NTFS_Feature(ADIO_File fd, int flag) +{ + switch(flag) { + /* supported features */ + case ADIO_LOCKS: + case ADIO_SHARED_FP: + case ADIO_ATOMIC_MODE: + case ADIO_DATA_SIEVING_WRITES: + return 1; + break; + /* unsupported features */ + case ADIO_SCALABLE_OPEN: + case ADIO_UNLINK_AFTER_CLOSE: + default: + return 0; + break; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_flush.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_flush.c new file mode 100644 index 0000000000..7656d60fb6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_flush.c @@ -0,0 +1,32 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +void ADIOI_NTFS_Flush(ADIO_File fd, int *error_code) +{ + int err; + static char myname[] = "ADIOI_NTFS_Flush"; + + err = (fd->access_mode & ADIO_RDONLY) ? TRUE : + FlushFileBuffers(fd->fd_sys); + + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + return; + } + /* --END ERROR HANDLING-- */ + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_iread.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_iread.c new file mode 100644 index 0000000000..845401ad44 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_iread.c @@ -0,0 +1,42 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +void ADIOI_NTFS_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int *error_code) +{ + MPI_Count len, typesize; + int err; + static char myname[] = "ADIOI_NTFS_IreadContig"; + + MPI_Type_size_x(datatype, &typesize); + len = count * typesize; + + if (file_ptr_type == ADIO_INDIVIDUAL) + { + offset = fd->fp_ind; + } + err = ADIOI_NTFS_aio(fd, buf, len, offset, 0, request); + if (file_ptr_type == ADIO_INDIVIDUAL) + { + fd->fp_ind += len; + } + + /* --BEGIN ERROR HANDLING-- */ + if (err != MPI_SUCCESS) + { + *error_code = MPIO_Err_create_code(err, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", 0); + return; + } + /* --END ERROR HANDLING-- */ + *error_code = MPI_SUCCESS; + + fd->fp_sys_posn = -1; /* set it to null. */ +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_iwrite.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_iwrite.c new file mode 100644 index 0000000000..40a567e564 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_iwrite.c @@ -0,0 +1,303 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +#include "../../mpi-io/mpioimpl.h" +#include "../../mpi-io/mpioprof.h" +#include "mpiu_greq.h" + +static MPIX_Grequest_class ADIOI_NTFS_greq_class = 0; + +/* Fills the input buffer, errMsg, with the error message + corresponding to error code, error */ +void ADIOI_NTFS_Strerror(int error, char *errMsg, int errMsgLen) +{ + LPTSTR str; + int num_bytes; + num_bytes = FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, + &str, + FORMAT_MESSAGE_MIN_SIZE, + 0); + if (num_bytes == 0) + { + strncpy(errMsg, "\0", errMsgLen); + } + else + { + strncpy(errMsg, str, errMsgLen); + LocalFree(str); + } +} + +/* poll for completion of a single outstanding AIO request */ +int ADIOI_NTFS_aio_poll_fn(void *extra_state, MPI_Status *status) +{ + ADIOI_AIO_Request *aio_req; + int mpi_errno = MPI_SUCCESS; + + /* FIXME: Validate the args -- has it already been done by the + caller ? */ + + aio_req = (ADIOI_AIO_Request *)extra_state; + + /* XXX: test for AIO completion here */ + if(!GetOverlappedResult( aio_req->fd, aio_req->lpOvl, + &(aio_req->nbytes), FALSE)){ + if(GetLastError() == ERROR_IO_INCOMPLETE){ + /* IO in progress */ + /* TODO: need to diddle with status somehow */ + }else{ + /* Error occured */ + /* TODO: unsure how to handle this */ + } + }else{ + mpi_errno = MPI_Grequest_complete(aio_req->req); + if (mpi_errno != MPI_SUCCESS) { + mpi_errno = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + "ADIOI_NTFS_aio_poll_fn", __LINE__, + MPI_ERR_IO, "**mpi_grequest_complete", + 0); + } + } + return mpi_errno; +} + + +/* Wait for completion of one of the outstanding AIO requests */ +int ADIOI_NTFS_aio_wait_fn(int count, void **array_of_states, + double timeout, MPI_Status *status) +{ + int i, mpi_errno = MPI_SUCCESS; + ADIOI_AIO_Request **aio_reqlist; + LPHANDLE lpHandles; + DWORD retObject=0; + + /* FIXME: Validate the args -- has it already been done by the + caller ? */ + aio_reqlist = (ADIOI_AIO_Request **)array_of_states; + lpHandles = (LPHANDLE) ADIOI_Calloc(count, sizeof(HANDLE)); + if (lpHandles == NULL) + { + mpi_errno = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + "ADIOI_NTFS_aio_wait_fn", __LINE__, MPI_ERR_IO, + "**nomem", "**nomem %s", "Event handles"); + return mpi_errno; + } + /* XXX: set-up arrays of outstanding requests */ + for(i=0; ilpOvl->hEvent; + } + + /* XXX: wait for one request to complete */ + /* FIXME: Is the timeout in seconds ? */ + timeout = (timeout <= 0) ? INFINITE : (timeout * 1000); + + if((retObject = WaitForMultipleObjects(count, lpHandles, + FALSE, timeout)) != WAIT_FAILED){ + retObject = retObject - WAIT_OBJECT_0; + if(GetOverlappedResult( aio_reqlist[retObject]->fd, + aio_reqlist[retObject]->lpOvl, &(aio_reqlist[retObject]->nbytes), + FALSE)){ + /* XXX: mark completed requests as 'done'*/ + mpi_errno = MPI_Grequest_complete(aio_reqlist[retObject]->req); + if (mpi_errno != MPI_SUCCESS) { + mpi_errno = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + "ADIOI_NTFS_aio_wait_fn", __LINE__, + MPI_ERR_IO, "**mpi_grequest_complete", + 0); + } + }else{ + if(GetLastError() == ERROR_IO_INCOMPLETE){ + /* IO in progress */ + /* TODO: need to diddle with status somehow */ + }else{ + /* Error occured */ + /* TODO: not sure how to handle this */ + } + } + }else{ + /* TODO: How to handle error while waiting ? */ + } + ADIOI_Free(lpHandles); + return mpi_errno; +} + +int ADIOI_NTFS_aio_query_fn(void *extra_state, MPI_Status *status) +{ + ADIOI_AIO_Request *aio_req; + + aio_req = (ADIOI_AIO_Request *)extra_state; + + + MPI_Status_set_elements(status, MPI_BYTE, aio_req->nbytes); + + /* can never cancel so always true */ + MPI_Status_set_cancelled(status, 0); + + /* choose not to return a value for this */ + status->MPI_SOURCE = MPI_UNDEFINED; + /* tag has no meaning for this generalized request */ + status->MPI_TAG = MPI_UNDEFINED; + /* this generalized request never fails */ + return MPI_SUCCESS; +} + + +int ADIOI_NTFS_aio_free_fn(void *extra_state) +{ + ADIOI_AIO_Request *aio_req; + /* FIXME: Validate the args -- has it already been done by the + caller ? */ + aio_req = (ADIOI_AIO_Request*)extra_state; + CloseHandle(aio_req->lpOvl->hEvent); + ADIOI_Free(aio_req->lpOvl); + ADIOI_Free(aio_req); + return MPI_SUCCESS; +} + +void ADIOI_NTFS_IwriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code) +{ + MPI_Count len, typesize; + int err; + static char myname[] = "ADIOI_NTFS_IwriteContig"; + + MPI_Type_size_x(datatype, &typesize); + len = count * typesize; + + if (file_ptr_type == ADIO_INDIVIDUAL) + { + offset = fd->fp_ind; + } + err = ADIOI_NTFS_aio(fd, buf, len, offset, 1, request); + if (file_ptr_type == ADIO_INDIVIDUAL) + { + fd->fp_ind += len; + } + + /* --BEGIN ERROR HANDLING-- */ + if (err != MPI_SUCCESS) + { + *error_code = MPIO_Err_create_code(err, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", 0); + return; + } + /* --END ERROR HANDLING-- */ + *error_code = MPI_SUCCESS; + + fd->fp_sys_posn = -1; /* set it to null. */ +} + + +/* This function is for implementation convenience. It is not user-visible. + * If wr==1 write, wr==0 read. + * + * Returns MPI_SUCCESS on success, mpi_errno on failure. + */ +int ADIOI_NTFS_aio(ADIO_File fd, void *buf, int len, ADIO_Offset offset, + int wr, MPI_Request *request) +{ + static char myname[] = "ADIOI_NTFS_aio"; + + ADIOI_AIO_Request *aio_req; + static DWORD dwNumWritten, dwNumRead; + BOOL ret_val = FALSE; + FDTYPE fd_sys; + int mpi_errno = MPI_SUCCESS; + DWORD err; + + fd_sys = fd->fd_sys; + + aio_req = (ADIOI_AIO_Request *)ADIOI_Calloc(sizeof(ADIOI_AIO_Request), 1); + if (aio_req == NULL) + { + mpi_errno = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**nomem", "**nomem %s", "AIO_REQ"); + return mpi_errno; + } + aio_req->lpOvl = (LPOVERLAPPED ) ADIOI_Calloc(sizeof(OVERLAPPED), 1); + if (aio_req->lpOvl == NULL) + { + mpi_errno = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**nomem", "**nomem %s", "OVERLAPPED"); + ADIOI_Free(aio_req); + return mpi_errno; + } + aio_req->lpOvl->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (aio_req->lpOvl->hEvent == NULL) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + mpi_errno = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + ADIOI_Free(aio_req->lpOvl); + ADIOI_Free(aio_req); + return mpi_errno; + } + aio_req->lpOvl->Offset = DWORDLOW(offset); + aio_req->lpOvl->OffsetHigh = DWORDHIGH(offset); + aio_req->fd = fd_sys; + + /* XXX: initiate async I/O */ + if (wr) + { + ret_val = WriteFile(fd_sys, buf, len, &dwNumWritten, aio_req->lpOvl); + } + else + { + ret_val = ReadFile(fd_sys, buf, len, &dwNumRead, aio_req->lpOvl); + } + + /* --BEGIN ERROR HANDLING-- */ + if (ret_val == FALSE) + { + mpi_errno = GetLastError(); + if (mpi_errno != ERROR_IO_PENDING) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + ADIOI_NTFS_Strerror(mpi_errno, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + mpi_errno = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + return mpi_errno; + } + mpi_errno = MPI_SUCCESS; + } + /* --END ERROR HANDLING-- */ + + /* XXX: set up generalized request class and request */ + if (ADIOI_NTFS_greq_class == 0) { + mpi_errno = MPIX_Grequest_class_create(ADIOI_NTFS_aio_query_fn, + ADIOI_NTFS_aio_free_fn, MPIU_Greq_cancel_fn, + ADIOI_NTFS_aio_poll_fn, ADIOI_NTFS_aio_wait_fn, + &ADIOI_NTFS_greq_class); + if(mpi_errno != MPI_SUCCESS){ + /* FIXME: Pass appropriate error code to user */ + } + } + mpi_errno = MPIX_Grequest_class_allocate(ADIOI_NTFS_greq_class, aio_req, request); + if(mpi_errno != MPI_SUCCESS){ + /* FIXME: Pass appropriate error code to user */ + } + memcpy(&(aio_req->req), request, sizeof(MPI_Request)); + return mpi_errno; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_open.c new file mode 100644 index 0000000000..3a49418dba --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_open.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +void ADIOI_NTFS_Open(ADIO_File fd, int *error_code) +{ + int err; + int cmode, amode, attrib; + static char myname[] = "ADIOI_NTFS_Open"; + + amode = 0; + cmode = OPEN_EXISTING; +#ifdef USE_WIN_THREADED_IO + attrib = FILE_FLAG_OVERLAPPED; +#else + attrib = FILE_ATTRIBUTE_NORMAL; +#endif + + if (fd->access_mode & ADIO_CREATE) + { + cmode = OPEN_ALWAYS; + } + if (fd->access_mode & ADIO_EXCL) + { + cmode = CREATE_NEW; + } + + if (fd->access_mode & ADIO_RDONLY) + { + amode = GENERIC_READ; + } + if (fd->access_mode & ADIO_WRONLY) + { + amode = GENERIC_WRITE; + } + if (fd->access_mode & ADIO_RDWR) + { + amode = GENERIC_READ | GENERIC_WRITE; + } + + if (fd->access_mode & ADIO_DELETE_ON_CLOSE) + { + attrib = attrib | FILE_FLAG_DELETE_ON_CLOSE; + } + if (fd->access_mode & ADIO_SEQUENTIAL) + { + attrib = attrib | FILE_FLAG_SEQUENTIAL_SCAN; + } + else + { + attrib = attrib | FILE_FLAG_RANDOM_ACCESS; + } + + fd->fd_sys = CreateFile(fd->filename, + amode, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + cmode, + attrib, + NULL); + fd->fd_direct = -1; + + if ((fd->fd_sys != INVALID_HANDLE_VALUE) && (fd->access_mode & ADIO_APPEND)) + { + fd->fp_ind = fd->fp_sys_posn = SetFilePointer(fd->fd_sys, 0, NULL, FILE_END); + if (fd->fp_ind == INVALID_SET_FILE_POINTER) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + if (err != NO_ERROR) + { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + return; + } + } + } + + /* --BEGIN ERROR HANDLING-- */ + if (fd->fd_sys == INVALID_HANDLE_VALUE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + return; + } + /* --END ERROR HANDLING-- */ + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_read.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_read.c new file mode 100644 index 0000000000..7c55c1bc37 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_read.c @@ -0,0 +1,259 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +void ADIOI_NTFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + LONG dwTemp; + DWORD dwNumRead = 0; + int err=-1; + MPI_Count datatype_size, len; + static char myname[] = "ADIOI_NTFS_ReadContig"; + OVERLAPPED *pOvl; + + /* If file pointer is of type ADIO_INDIVIDUAL ignore the offset + and use the current location of file pointer */ + if(file_ptr_type == ADIO_INDIVIDUAL){ + offset = fd->fp_ind; + } + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + pOvl = (OVERLAPPED *) ADIOI_Calloc(sizeof(OVERLAPPED), 1); + if (pOvl == NULL) + { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**nomem", "**nomem %s", "OVERLAPPED"); + return; + } + pOvl->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (pOvl->hEvent == NULL) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + ADIOI_Free(pOvl); + return; + } + pOvl->Offset = DWORDLOW(offset); + pOvl->OffsetHigh = DWORDHIGH(offset); + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) + { + if (fd->fp_sys_posn != offset) + { + dwTemp = DWORDHIGH(offset); + if (SetFilePointer(fd->fd_sys, DWORDLOW(offset), &dwTemp, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + if (err != NO_ERROR) + { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + } + /* + { + ADIO_Fcntl_t fcntl_struct; + int error_code; + ADIO_Fcntl(fd, ADIO_FCNTL_GET_FSIZE, &fcntl_struct, &error_code); + printf("File size b: %d\n", fcntl_struct.fsize); + } + printf("ReadFile(%d bytes)\n", len);fflush(stdout); + */ + err = ReadFile(fd->fd_sys, buf, len, &dwNumRead, pOvl); + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + switch (err) + { + case ERROR_IO_PENDING: + break; + case ERROR_HANDLE_EOF: + /*printf("EOF error\n");fflush(stdout);*/ + SetEvent(pOvl->hEvent); + break; + default: + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + /* --END ERROR HANDLING-- */ + err = GetOverlappedResult(fd->fd_sys, pOvl, &dwNumRead, TRUE); + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + if (err != ERROR_HANDLE_EOF) /* Ignore EOF errors */ + { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, "**io", + "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + /* --END ERROR HANDLING-- */ + if (!CloseHandle(pOvl->hEvent)) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + ADIOI_Free(pOvl); + + fd->fp_sys_posn = offset + (ADIO_Offset)dwNumRead; + /* individual file pointer not updated */ + } + else + { + /* read from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) + { + dwTemp = DWORDHIGH(fd->fp_ind); + if (SetFilePointer(fd->fd_sys, DWORDLOW(fd->fp_ind), &dwTemp, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + if (err != NO_ERROR) + { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + } + /* + { + ADIO_Fcntl_t fcntl_struct; + int error_code; + ADIO_Fcntl(fd, ADIO_FCNTL_GET_FSIZE, &fcntl_struct, &error_code); + printf("File size c: %d\n", fcntl_struct.fsize); + } + printf("ReadFile(%d bytes)\n", len);fflush(stdout); + */ + err = ReadFile(fd->fd_sys, buf, len, &dwNumRead, pOvl); + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + switch (err) + { + case ERROR_IO_PENDING: + break; + case ERROR_HANDLE_EOF: + /*printf("EOF error\n");fflush(stdout);*/ + SetEvent(pOvl->hEvent); + break; + default: + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + /* --END ERROR HANDLING-- */ + err = GetOverlappedResult(fd->fd_sys, pOvl, &dwNumRead, TRUE); + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + if (err != ERROR_HANDLE_EOF) /* Ignore EOF errors */ + { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, "**io", + "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + /* --END ERROR HANDLING-- */ + if (!CloseHandle(pOvl->hEvent)) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + ADIOI_Free(pOvl); + return; + } + ADIOI_Free(pOvl); + + fd->fp_ind = fd->fp_ind + (ADIO_Offset)dwNumRead; + fd->fp_sys_posn = fd->fp_ind; + } + +#ifdef HAVE_STATUS_SET_BYTES + if (err != FALSE) + { + MPIR_Status_set_bytes(status, datatype, dwNumRead); + } +#endif + + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + return; + } + /* --END ERROR HANDLING-- */ + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_resize.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_resize.c new file mode 100644 index 0000000000..0fbeaaf972 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_resize.c @@ -0,0 +1,51 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +void ADIOI_NTFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + LONG dwTemp; + DWORD err; + BOOL result; + static char myname[] = "ADIOI_NTFS_Resize"; + + dwTemp = DWORDHIGH(size); + err = SetFilePointer(fd->fd_sys, DWORDLOW(size), &dwTemp, FILE_BEGIN); + /* --BEGIN ERROR HANDLING-- */ + if (err == INVALID_SET_FILE_POINTER) + { + err = GetLastError(); + if (err != NO_ERROR) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + return; + } + } + /*printf("setting file length to %d\n", size);fflush(stdout);*/ + /* --END ERROR HANDLING-- */ + result = SetEndOfFile(fd->fd_sys); + /* --BEGIN ERROR HANDLING-- */ + if (result == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + return; + } + /* --END ERROR HANDLING-- */ + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_wait.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_wait.c new file mode 100644 index 0000000000..80dfa4d334 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_wait.c @@ -0,0 +1,20 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +void ADIOI_NTFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + return; +} + + +void ADIOI_NTFS_WriteComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + return; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_write.c b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_write.c new file mode 100644 index 0000000000..389e866936 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ntfs/ad_ntfs_write.c @@ -0,0 +1,222 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ntfs.h" + +void ADIOI_NTFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + static char myname[] = "ADIOI_NTFS_WriteContig"; + LONG dwTemp; + DWORD dwNumWritten = 0; + MPI_Count err=-1, datatype_size, len; + OVERLAPPED *pOvl; + + /* If file pointer type in ADIO_INDIVIDUAL then offset should be + ignored and the current location of file pointer should be used */ + if(file_ptr_type == ADIO_INDIVIDUAL){ + offset = fd->fp_ind; + } + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + pOvl = (OVERLAPPED *) ADIOI_Calloc(sizeof(OVERLAPPED), 1); + if (pOvl == NULL) + { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**nomem", "**nomem %s", "OVERLAPPED"); + return; + } + pOvl->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + if (pOvl->hEvent == NULL) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + ADIOI_Free(pOvl); + return; + } + pOvl->Offset = DWORDLOW(offset); + pOvl->OffsetHigh = DWORDHIGH(offset); + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) + { + if (fd->fp_sys_posn != offset) + { + dwTemp = DWORDHIGH(offset); + if (SetFilePointer(fd->fd_sys, DWORDLOW(offset), &dwTemp, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + { + err = GetLastError(); + if (err != NO_ERROR) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + } + /*printf("WriteFile(%d bytes)\n", len);fflush(stdout);*/ + err = WriteFile(fd->fd_sys, buf, len, &dwNumWritten, pOvl); + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + err = GetLastError(); + if (err != ERROR_IO_PENDING) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + /* --END ERROR HANDLING-- */ + err = GetOverlappedResult(fd->fd_sys, pOvl, &dwNumWritten, TRUE); + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, "**io", + "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + /* --END ERROR HANDLING-- */ + if (!CloseHandle(pOvl->hEvent)) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + ADIOI_Free(pOvl); + + fd->fp_sys_posn = offset + dwNumWritten; + /* individual file pointer not updated */ + } + else + { + /* write from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) + { + dwTemp = DWORDHIGH(fd->fp_ind); + if (SetFilePointer(fd->fd_sys, DWORDLOW(fd->fp_ind), &dwTemp, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + { + err = GetLastError(); + if (err != NO_ERROR) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + } + /*printf("WriteFile(%d bytes)\n", len);fflush(stdout);*/ + err = WriteFile(fd->fd_sys, buf, len, &dwNumWritten, pOvl); + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + err = GetLastError(); + if (err != ERROR_IO_PENDING) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + } + /* --END ERROR HANDLING-- */ + err = GetOverlappedResult(fd->fd_sys, pOvl, &dwNumWritten, TRUE); + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, "**io", + "**io %s", errMsg); + CloseHandle(pOvl->hEvent); + ADIOI_Free(pOvl); + return; + } + /* --END ERROR HANDLING-- */ + if (!CloseHandle(pOvl->hEvent)) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", "**io %s", errMsg); + ADIOI_Free(pOvl); + return; + } + ADIOI_Free(pOvl); + + fd->fp_ind = fd->fp_ind + dwNumWritten; + fd->fp_sys_posn = fd->fp_ind; + } + +#ifdef HAVE_STATUS_SET_BYTES + if (err != FALSE) + { + MPIR_Status_set_bytes(status, datatype, dwNumWritten); + } +#endif + + /* --BEGIN ERROR HANDLING-- */ + if (err == FALSE) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + err = GetLastError(); + ADIOI_NTFS_Strerror(err, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", errMsg); + return; + } + /* --END ERROR HANDLING-- */ + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_panfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_panfs/Makefile.mk new file mode 100644 index 0000000000..68e92d5e91 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_panfs/Makefile.mk @@ -0,0 +1,21 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_PANFS + +noinst_HEADERS += adio/ad_panfs/ad_panfs.h + +romio_other_sources += \ + adio/ad_panfs/ad_panfs.c \ + adio/ad_panfs/ad_panfs_open.c \ + adio/ad_panfs/ad_panfs_hints.c \ + adio/ad_panfs/ad_panfs_read.c \ + adio/ad_panfs/ad_panfs_resize.c \ + adio/ad_panfs/ad_panfs_write.c + +endif BUILD_AD_PANFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs.c b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs.c new file mode 100644 index 0000000000..fd9cd93ff8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs.c @@ -0,0 +1,45 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * ad_panfs.c + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_panfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_PANFS_operations = { + ADIOI_PANFS_Open, /* Open */ + ADIOI_GEN_OpenColl, + ADIOI_PANFS_ReadContig, /* ReadContig */ + ADIOI_PANFS_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_GEN_Fcntl, /* Fcntl */ + ADIOI_PANFS_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_GEN_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ +#ifdef ROMIO_HAVE_WORKING_AIO + ADIOI_GEN_IreadContig, /* IreadContig */ + ADIOI_GEN_IwriteContig, /* IwriteContig */ +#else + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ +#endif + ADIOI_GEN_IODone, /* ReadDone */ + ADIOI_GEN_IODone, /* WriteDone */ + ADIOI_GEN_IOComplete, /* ReadComplete */ + ADIOI_GEN_IOComplete, /* WriteComplete */ + ADIOI_GEN_IreadStrided, /* IreadStrided */ + ADIOI_GEN_IwriteStrided, /* IwriteStrided */ + ADIOI_GEN_Flush, /* Flush */ + ADIOI_PANFS_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ + ADIOI_GEN_Feature, + "PANFS: Panasas PanFS" +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs.h b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs.h new file mode 100644 index 0000000000..5f13f64fc3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * ad_panfs.h + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_PANFS_INCLUDE +#define AD_PANFS_INCLUDE + +#include +#include +#include +#include "adio.h" + +#ifndef NO_AIO +#ifdef AIO_SUN +#include +#else +#include +#ifdef NEEDS_ADIOCB_T +typedef struct adiocb adiocb_t; +#endif +#endif +#endif + +void ADIOI_PANFS_Open(ADIO_File fd, int *error_code); +void ADIOI_PANFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); +void ADIOI_PANFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code); +void ADIOI_PANFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +void ADIOI_PANFS_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); + +/* TODO: move this to common code and have all routines retry. */ +/* TODO: also check for EWOULDBLOCK */ +#if defined(NEEDS_USLEEP_DECL) +int usleep(useconds_t usec); +#endif + +/* Delay 1 ms */ +#define AD_PANFS_RETRY_DELAY 1000 + +#define AD_PANFS_RETRY(_op_,_rc_) \ +{ \ + _rc_ = (_op_); \ + while(_rc_ == -1 && errno == EAGAIN) \ + { \ + if(usleep(AD_PANFS_RETRY_DELAY) == -1) \ + { \ + break; \ + } \ + _rc_ = (_op_); \ + } \ +} + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_hints.c b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_hints.c new file mode 100644 index 0000000000..94178ab0cf --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_hints.c @@ -0,0 +1,72 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * ad_panfs_hints.c + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_panfs.h" +#include +#include "hint_fns.h" + +void ADIOI_PANFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ +#if defined(MPICH) || !defined(PRINT_ERR_MSG) + static char myname[] = "ADIOI_PANFS_SETINFO"; +#endif + int gen_error_code; + + *error_code = MPI_SUCCESS; + + if (fd->info == MPI_INFO_NULL) { + /* This must be part of the open call. can set striping parameters + * if necessary. + */ + MPI_Info_create(&(fd->info)); + + /* anticipate concurrent writes in an MPI-IO application */ + ADIOI_Info_set (fd->info, "panfs_concurrent_write", "1"); + + /* has user specified striping parameters + and do they have the same value on all processes? */ + if (users_info != MPI_INFO_NULL) { + + ADIOI_Info_check_and_install_int(fd, users_info, "panfs_concurrent_write", + NULL, myname, error_code); + + ADIOI_Info_check_and_install_int(fd, users_info, "panfs_layout_type", + NULL, myname, error_code); + + ADIOI_Info_check_and_install_int(fd, users_info, "panfs_layout_stripe_unit", + NULL, myname, error_code); + + /* strange: there was a check "layout_type == + * PAN_FS_CLIENT_LAYOUT_TYPE__RAID1_5_PARITY_STRIPE, but + * nothing ever touched layout_type */ + ADIOI_Info_check_and_install_int(fd, users_info, + "panfs_layout_parity_stripe_width", NULL, myname, error_code); + + ADIOI_Info_check_and_install_int(fd, users_info, + "panfs_layout_parity_stripe_depth", NULL, myname, error_code); + + ADIOI_Info_check_and_install_int(fd, users_info, + "panfs_layout_total_num_comps", NULL, myname, error_code); + /* this hint used to check for + * PAN_FS_CLIENT_LAYOUT_TYPE__RAID1_5_PARITY_STRIPE or + * PAN_FS_CLIENT_LAYOUT_TYPE__RAID10, but again, layout_type never + * gets updated */ + ADIOI_Info_check_and_install_int(fd, users_info, + "panfs_layout_visit_policy", NULL, myname, error_code); + } + } + + ADIOI_GEN_SetInfo(fd, users_info, &gen_error_code); + /* If this function is successful, use the error code returned from ADIOI_GEN_SetInfo + * otherwise use the error_code generated by this function + */ + if(*error_code == MPI_SUCCESS) + { + *error_code = gen_error_code; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_open.c new file mode 100644 index 0000000000..d5374ebf44 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_open.c @@ -0,0 +1,348 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * ad_panfs_open.c + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_panfs.h" +#include +#include +#define TEMP_BUFFER_SIZE 64 + +void ADIOI_PANFS_Open(ADIO_File fd, int *error_code) +{ + char* value; + int perm, old_mask, amode, flag; + static char myname[] = "ADIOI_PANFS_OPEN"; + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = ~old_mask & 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + { + pan_fs_client_layout_agg_type_t layout_type = PAN_FS_CLIENT_LAYOUT_TYPE__DEFAULT; + unsigned long int layout_stripe_unit = 0; + unsigned long int layout_parity_stripe_width = 0; + unsigned long int layout_parity_stripe_depth = 0; + unsigned long int layout_total_num_comps = 0; + pan_fs_client_layout_visit_t layout_visit_policy = PAN_FS_CLIENT_LAYOUT_VISIT__ROUND_ROBIN; + int myrank; + + MPI_Comm_rank(fd->comm, &myrank); + + *error_code = MPI_SUCCESS; + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + ADIOI_Info_get(fd->info, "panfs_layout_type", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + layout_type = strtoul(value,NULL,10); + } + ADIOI_Info_get(fd->info, "panfs_layout_stripe_unit", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + layout_stripe_unit = strtoul(value,NULL,10); + } + ADIOI_Info_get(fd->info, "panfs_layout_total_num_comps", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + layout_total_num_comps = strtoul(value,NULL,10); + } + ADIOI_Info_get(fd->info, "panfs_layout_parity_stripe_width", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + layout_parity_stripe_width = strtoul(value,NULL,10); + } + ADIOI_Info_get(fd->info, "panfs_layout_parity_stripe_depth", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + layout_parity_stripe_depth = strtoul(value,NULL,10); + } + ADIOI_Info_get(fd->info, "panfs_layout_visit_policy", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + layout_visit_policy = strtoul(value,NULL,10); + } + ADIOI_Free(value); + + amode = amode | O_CREAT; + /* Check for valid set of hints */ + if ((layout_type < PAN_FS_CLIENT_LAYOUT_TYPE__DEFAULT) || + (layout_type > PAN_FS_CLIENT_LAYOUT_TYPE__RAID10)) + { + FPRINTF(stderr, "%s: panfs_layout_type is not a valid value: %u.\n", myname, layout_type); + MPI_Abort(MPI_COMM_WORLD, 1); + } + if ((layout_type == PAN_FS_CLIENT_LAYOUT_TYPE__RAID0) && + ((layout_stripe_unit == 0) || (layout_total_num_comps == 0))) + { + if(layout_stripe_unit == 0) + { + FPRINTF(stderr, "%s: MPI_Info does not contain the panfs_layout_stripe_unit hint which is necessary to specify a valid RAID0 layout to the PAN_FS_CLIENT_LAYOUT_CREATE_FILE ioctl.\n", myname); + } + if(layout_total_num_comps == 0) + { + FPRINTF(stderr, "%s: MPI_Info does not contain the panfs_layout_total_num_comps hint which is necessary to specify a valid RAID0 layout to the PAN_FS_CLIENT_LAYOUT_CREATE_FILE ioctl.\n", myname); + } + MPI_Abort(MPI_COMM_WORLD, 1); + } + if (layout_type == PAN_FS_CLIENT_LAYOUT_TYPE__RAID1_5_PARITY_STRIPE) + { + if ((layout_stripe_unit == 0) || + (layout_parity_stripe_width == 0) || + (layout_parity_stripe_depth == 0) || + (layout_total_num_comps == 0)) + { + if(layout_stripe_unit == 0) + { + FPRINTF(stderr, "%s: MPI_Info does not contain the panfs_layout_stripe_unit hint which is necessary to specify a valid RAID5 parity stripe layout to the PAN_FS_CLIENT_LAYOUT_CREATE_FILE ioctl.\n", myname); + } + if(layout_total_num_comps == 0) + { + FPRINTF(stderr, "%s: MPI_Info does not contain the panfs_layout_total_num_comps hint which is necessary to specify a valid RAID5 parity stripe layout to the PAN_FS_CLIENT_LAYOUT_CREATE_FILE ioctl.\n", myname); + } + if(layout_parity_stripe_width == 0) + { + FPRINTF(stderr, "%s: MPI_Info does not contain the panfs_layout_parity_stripe_width hint which is necessary to specify a valid RAID5 parity stripe layout to the PAN_FS_CLIENT_LAYOUT_CREATE_FILE ioctl.\n", myname); + } + if(layout_parity_stripe_depth == 0) + { + FPRINTF(stderr, "%s: MPI_Info does not contain the panfs_layout_parity_stripe_depth hint which is necessary to specify a valid RAID5 parity stripe layout to the PAN_FS_CLIENT_LAYOUT_CREATE_FILE ioctl.\n", myname); + } + MPI_Abort(MPI_COMM_WORLD, 1); + } + if ((layout_visit_policy < PAN_FS_CLIENT_LAYOUT_VISIT__ROUND_ROBIN) || + (layout_visit_policy > PAN_FS_CLIENT_LAYOUT_VISIT__ROUND_ROBIN_WITH_HASHED_OFFSET)) + { + FPRINTF(stderr, "%s: panfs_layout_visit_policy is not a valid value: %u.\n", myname, layout_visit_policy); + MPI_Abort(MPI_COMM_WORLD, 1); + } + } + if (layout_type == PAN_FS_CLIENT_LAYOUT_TYPE__RAID10) + { + if ((layout_stripe_unit == 0) || (layout_total_num_comps == 0)) + { + if(layout_stripe_unit == 0) + { + FPRINTF(stderr, "%s: MPI_Info does not contain the panfs_layout_stripe_unit hint which is necessary to specify a valid RAID10 layout to the PAN_FS_CLIENT_LAYOUT_CREATE_FILE ioctl.\n", myname); + } + if(layout_total_num_comps == 0) + { + FPRINTF(stderr, "%s: MPI_Info does not contain the panfs_layout_total_num_comps hint which is necessary to specify a valid RAID10 layout to the PAN_FS_CLIENT_LAYOUT_CREATE_FILE ioctl.\n", myname); + } + MPI_Abort(MPI_COMM_WORLD, 1); + } + if ((layout_visit_policy < PAN_FS_CLIENT_LAYOUT_VISIT__ROUND_ROBIN) || + (layout_visit_policy > PAN_FS_CLIENT_LAYOUT_VISIT__ROUND_ROBIN_WITH_HASHED_OFFSET)) + { + FPRINTF(stderr, "%s: panfs_layout_visit_policy is not a valid value: %u.\n", myname, layout_visit_policy); + MPI_Abort(MPI_COMM_WORLD, 1); + } + } + /* Create the file via ioctl() or open(). ADIOI_PANFS_Open's caller + * already optimizes performance by only calling this function with + * ADIO_CREATE on rank 0. Therefore, we don't need to worry about + * implementing that optimization here. */ + if((layout_type == PAN_FS_CLIENT_LAYOUT_TYPE__RAID0) || (layout_type == PAN_FS_CLIENT_LAYOUT_TYPE__RAID1_5_PARITY_STRIPE) + || (layout_type == PAN_FS_CLIENT_LAYOUT_TYPE__RAID10)) { + pan_fs_client_layout_create_args_t file_create_args; + int fd_dir; + char* slash; + struct stat stat_buf; + int err; + char *path; + + /* Check that the file does not exist before + * trying to create it. The ioctl itself should + * be able to handle this condition. Currently, + * the ioctl will return successfully if the file + * has been previously created. Filed bug 33862 + * to track the problem. + */ + err = stat(fd->filename,&stat_buf); + if((err == -1) && (errno != ENOENT)) + { + FPRINTF(stderr,"%s: Unexpected I/O Error calling stat() on PanFS file: %s.\n", myname, strerror(errno)); + MPI_Abort(MPI_COMM_WORLD, 1); + } + else if (err == 0) + { + FPRINTF(stderr,"%s: Cannot create PanFS file with ioctl when file already exists.\n", myname); + MPI_Abort(MPI_COMM_WORLD, 1); + } + else + { + /* (err == -1) && (errno == ENOENT) */ + /* File does not exist */ + path = ADIOI_Strdup(fd->filename); + slash = strrchr(path, '/'); + if (!slash) + ADIOI_Strncpy(path, ".", 2); + else { + if (slash == path) + *(path + 1) = '\0'; + else *slash = '\0'; + } + + /* create PanFS object */ + memset(&file_create_args,0,sizeof(pan_fs_client_layout_create_args_t)); + /* open directory */ + fd_dir = open(path, O_RDONLY); + if (fd_dir < 0) { + FPRINTF(stderr, "%s: I/O Error opening parent directory to create PanFS file using ioctl: %s.\n", myname, strerror(errno)); + MPI_Abort(MPI_COMM_WORLD, 1); + } + else + { + char *file_name_ptr = fd->filename; + slash = strrchr(fd->filename, '/'); + if (slash) + { + file_name_ptr = slash + 1; + } + /* create file in the directory */ + file_create_args.mode = perm; + file_create_args.version = PAN_FS_CLIENT_LAYOUT_VERSION; + file_create_args.flags = PAN_FS_CLIENT_LAYOUT_CREATE_F__NONE; + ADIOI_Strncpy(file_create_args.filename, file_name_ptr, strlen(fd->filename)+1); + file_create_args.layout.agg_type = layout_type; + file_create_args.layout.layout_is_valid = 1; + if(layout_type == PAN_FS_CLIENT_LAYOUT_TYPE__RAID1_5_PARITY_STRIPE) + { + file_create_args.layout.u.raid1_5_parity_stripe.total_num_comps = layout_total_num_comps; + file_create_args.layout.u.raid1_5_parity_stripe.parity_stripe_width = layout_parity_stripe_width; + file_create_args.layout.u.raid1_5_parity_stripe.parity_stripe_depth = layout_parity_stripe_depth; + file_create_args.layout.u.raid1_5_parity_stripe.stripe_unit = layout_stripe_unit; + file_create_args.layout.u.raid1_5_parity_stripe.layout_visit_policy = layout_visit_policy; + } + else if(layout_type == PAN_FS_CLIENT_LAYOUT_TYPE__RAID0) + { + file_create_args.layout.u.raid0.total_num_comps = layout_total_num_comps; + file_create_args.layout.u.raid0.stripe_unit = layout_stripe_unit; + } + else if(layout_type == PAN_FS_CLIENT_LAYOUT_TYPE__RAID10) + { + file_create_args.layout.u.raid10.total_num_comps = layout_total_num_comps; + file_create_args.layout.u.raid10.stripe_unit = layout_stripe_unit; + file_create_args.layout.u.raid10.layout_visit_policy = layout_visit_policy; + } + err = ioctl(fd_dir, PAN_FS_CLIENT_LAYOUT_CREATE_FILE, &file_create_args); + if (err < 0) { + FPRINTF(stderr, "%s: I/O Error doing ioctl on parent directory to create PanFS file using ioctl: %s.\n", myname, strerror(errno)); + MPI_Abort(MPI_COMM_WORLD, 1); + } + err = close(fd_dir); + } + ADIOI_Free(path); + } + } + else + { + int create_fd = open(fd->filename,amode,perm); + if(create_fd != -1) + { + close(create_fd); + } + else + { + FPRINTF(stderr, "%s: I/O Error creating PanFS file using open: %s.\n", myname, strerror(errno)); + MPI_Abort(MPI_COMM_WORLD, 1); + } + } + } + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + ADIOI_Info_get(fd->info, "panfs_concurrent_write", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + unsigned long int concurrent_write = strtoul(value,NULL,10); + if(concurrent_write == 1) + { + amode = amode | O_CONCURRENT_WRITE; + } + } + ADIOI_Free(value); + + fd->fd_sys = open(fd->filename, amode, perm); + fd->fd_direct = -1; + + if (fd->fd_sys != -1) + { + int rc; + char temp_buffer[TEMP_BUFFER_SIZE]; + pan_fs_client_layout_query_args_t file_query_args; + memset(&file_query_args,0,sizeof(pan_fs_client_layout_query_args_t)); + file_query_args.version = PAN_FS_CLIENT_LAYOUT_VERSION; + rc = ioctl(fd->fd_sys, PAN_FS_CLIENT_LAYOUT_QUERY_FILE, &file_query_args); + if (rc < 0) + { + /* Error - set layout type to unknown */ + ADIOI_Info_set(fd->info, "panfs_layout_type", "PAN_FS_CLIENT_LAYOUT_TYPE__INVALID"); + } + else + { + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.agg_type); + ADIOI_Info_set(fd->info, "panfs_layout_type", temp_buffer); + if (file_query_args.layout.layout_is_valid == 1) + { + switch (file_query_args.layout.agg_type) + { + case PAN_FS_CLIENT_LAYOUT_TYPE__RAID0: + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid0.stripe_unit); + ADIOI_Info_set(fd->info, "panfs_layout_stripe_unit", temp_buffer); + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid0.total_num_comps); + ADIOI_Info_set(fd->info, "panfs_layout_total_num_comps", temp_buffer); + break; + case PAN_FS_CLIENT_LAYOUT_TYPE__RAID1_5_PARITY_STRIPE: + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid1_5_parity_stripe.stripe_unit); + ADIOI_Info_set(fd->info, "panfs_layout_stripe_unit", temp_buffer); + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid1_5_parity_stripe.parity_stripe_width); + ADIOI_Info_set(fd->info, "panfs_layout_parity_stripe_width", temp_buffer); + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid1_5_parity_stripe.parity_stripe_depth); + ADIOI_Info_set(fd->info, "panfs_layout_parity_stripe_depth", temp_buffer); + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid1_5_parity_stripe.total_num_comps); + ADIOI_Info_set(fd->info, "panfs_layout_total_num_comps", temp_buffer); + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid1_5_parity_stripe.layout_visit_policy); + ADIOI_Info_set(fd->info, "panfs_layout_visit_policy", temp_buffer); + break; + case PAN_FS_CLIENT_LAYOUT_TYPE__RAID10: + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid10.stripe_unit); + ADIOI_Info_set(fd->info, "panfs_layout_stripe_unit", temp_buffer); + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid10.total_num_comps); + ADIOI_Info_set(fd->info, "panfs_layout_total_num_comps", temp_buffer); + ADIOI_Snprintf(temp_buffer,TEMP_BUFFER_SIZE,"%u",file_query_args.layout.u.raid10.layout_visit_policy); + ADIOI_Info_set(fd->info, "panfs_layout_visit_policy", temp_buffer); + break; + case PAN_FS_CLIENT_LAYOUT_TYPE__INVALID: + case PAN_FS_CLIENT_LAYOUT_TYPE__DEFAULT: + MPI_Info_set(fd->info, "panfs_layout_type", + "PAN_FS_CLIENT_LAYOUT_TYPE__INVALID"); + default: + break; + } + } + } + } + + if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND)) + fd->fp_ind = fd->fp_sys_posn = lseek(fd->fd_sys, 0, SEEK_END); + + if (fd->fd_sys == -1) { + *error_code = ADIOI_Err_create_code(myname, fd->filename, errno); + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_read.c b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_read.c new file mode 100644 index 0000000000..237e4929de --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_read.c @@ -0,0 +1,68 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_panfs.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +void ADIOI_PANFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + MPI_Count err = -1, datatype_size, len; + static char myname[] = "ADIOI_PANFS_READCONTIG"; + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; + } + + if (fd->fp_sys_posn != offset) { + err = lseek(fd->fd_sys, offset, SEEK_SET); + /* --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-- */ + } + + AD_PANFS_RETRY(read(fd->fd_sys, buf, len),err) + /* --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-- */ + + fd->fp_sys_posn = offset + err; + + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind += err; + } + +#ifdef HAVE_STATUS_SET_BYTES + if (err != -1) MPIR_Status_set_bytes(status, datatype, err); +#endif + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_resize.c b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_resize.c new file mode 100644 index 0000000000..5c41126c4d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_resize.c @@ -0,0 +1,49 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_panfs.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +void ADIOI_PANFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int err; + int myrank; + struct stat stat_buf; + static char myname[] = "ADIOI_PANFS_RESIZE"; + + MPI_Comm_rank(fd->comm, &myrank); + if (!myrank) + { + AD_PANFS_RETRY(ftruncate(fd->fd_sys,size),err); + MPI_Barrier(fd->comm); + } + else + { + MPI_Barrier(fd->comm); + AD_PANFS_RETRY(fstat(fd->fd_sys,&stat_buf),err); + if(((ADIO_Offset)stat_buf.st_size) != size) + { + /* This should never happen otherwise there is a coherency problem. */ + FPRINTF(stderr, "%s: Rank %d: Resize failed: requested=%llu actual=%llu.\n",myname,myrank,size,(unsigned long long)stat_buf.st_size); + MPI_Abort(MPI_COMM_WORLD, 1); + } + } + + /* --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-- */ + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_write.c b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_write.c new file mode 100644 index 0000000000..920d2f473e --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_panfs/ad_panfs_write.c @@ -0,0 +1,68 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_panfs.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +void ADIOI_PANFS_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) +{ + MPI_Count err = -1, datatype_size, len; + static char myname[] = "ADIOI_PANFS_WRITECONTIG"; + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; + } + + if (fd->fp_sys_posn != offset) { + err = lseek(fd->fd_sys, offset, SEEK_SET); + /* --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-- */ + } + + AD_PANFS_RETRY(write(fd->fd_sys, buf, len),err) + /* --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-- */ + + fd->fp_sys_posn = offset + err; + + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind += err; + } + +#ifdef HAVE_STATUS_SET_BYTES + if (err != -1 && status) MPIR_Status_set_bytes(status, datatype, err); +#endif + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_pfs/Makefile.mk new file mode 100644 index 0000000000..3521c07c86 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/Makefile.mk @@ -0,0 +1,26 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_PFS + +noinst_HEADERS += adio/ad_pfs/ad_pfs.h + +romio_other_sources += \ + adio/ad_pfs/ad_pfs_read.c \ + adio/ad_pfs/ad_pfs_open.c \ + adio/ad_pfs/ad_pfs_write.c \ + adio/ad_pfs/ad_pfs_done.c \ + adio/ad_pfs/ad_pfs_fcntl.c \ + adio/ad_pfs/ad_pfs_iread.c \ + adio/ad_pfs/ad_pfs_iwrite.c \ + adio/ad_pfs/ad_pfs_wait.c \ + adio/ad_pfs/ad_pfs_flush.c \ + adio/ad_pfs/ad_pfs_hints.c \ + adio/ad_pfs/ad_pfs.c + +endif BUILD_AD_PFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs.c new file mode 100644 index 0000000000..62a4305205 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs.c @@ -0,0 +1,36 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_PFS_operations = { + ADIOI_PFS_Open, /* Open */ + ADIOI_PFS_ReadContig, /* ReadContig */ + ADIOI_PFS_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_PFS_Fcntl, /* Fcntl */ + ADIOI_PFS_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_GEN_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ + ADIOI_PFS_IreadContig, /* IreadContig */ + ADIOI_PFS_IwriteContig, /* IwriteContig */ + ADIOI_PFS_ReadDone, /* ReadDone */ + ADIOI_PFS_WriteDone, /* WriteDone */ + ADIOI_PFS_ReadComplete, /* ReadComplete */ + ADIOI_PFS_WriteComplete, /* WriteComplete */ + ADIOI_FAKE_IreadStrided, /* IreadStrided */ + ADIOI_FAKE_IwriteStrided, /* IwriteStrided */ + ADIOI_PFS_Flush, /* Flush */ + ADIOI_GEN_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs.h b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs.h new file mode 100644 index 0000000000..fbe055ccf7 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* contains definitions, declarations, and macros specific to the + implementation of ADIO on PFS */ + +#ifndef AD_PFS_INCLUDE +#define AD_PFS_INCLUDE + +#include +#include +#include +#include +#include +#include "adio.h" + +#ifdef tflops +#define lseek eseek +#define _gopen(n,m,i,p) open(n,m,p) +#endif + +/* PFS file-pointer modes (removed most of them because they are unused) */ +#ifndef M_ASYNC +#define M_UNIX 0 +#define M_ASYNC 5 +#endif + +void ADIOI_PFS_Open(ADIO_File fd, int *error_code); +void ADIOI_PFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PFS_IwriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_PFS_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +int ADIOI_PFS_ReadDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +int ADIOI_PFS_WriteDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_PFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_PFS_WriteComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIOI_PFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIOI_PFS_Flush(ADIO_File fd, int *error_code); +void ADIOI_PFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_done.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_done.c new file mode 100644 index 0000000000..60e2d7da29 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_done.c @@ -0,0 +1,57 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +int ADIOI_PFS_ReadDone(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + int done=0; + static char myname[] = "ADIOI_PFS_READDONE"; + + if (*request == ADIO_REQUEST_NULL) { + *error_code = MPI_SUCCESS; + return 1; + } + + if ((*request)->queued) + done = _iodone(*((long *) (*request)->handle)); + else done = 1; /* ADIOI_Complete_Async completed this request, + but request object was not freed. */ + +#ifdef HAVE_STATUS_SET_BYTES + if ((done >= 0) && ((*request)->nbytes != -1)) + MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes); +#endif + + if (done >= 0) { + /* if request is still queued in the system, it is also there + on ADIOI_Async_list. Delete it from there. */ + if ((*request)->queued) ADIOI_Del_req_from_list(request); + + (*request)->fd->async_count--; + if ((*request)->handle) ADIOI_Free((*request)->handle); + ADIOI_Free_request((ADIOI_Req_node *) (*request)); + *request = ADIO_REQUEST_NULL; + } + + if (done == -1 && errno != 0) { + *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; + return done; +} + + +int ADIOI_PFS_WriteDone(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + return ADIOI_PFS_ReadDone(request, status, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_fcntl.c new file mode 100644 index 0000000000..4a2c0fd382 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_fcntl.c @@ -0,0 +1,81 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" +#include "adio_extern.h" + +void ADIOI_PFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code) +{ + int i, err; + int iomod, np_total, np_comm; + static char myname[] = "ADIOI_PFS_FCNTL"; + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + if (!(fd->atomicity)) { + /* in M_ASYNC mode, all processes are not aware of changes + in file size (although the manual says otherwise). Therefore, + temporarily change to M_UNIX and then change + back to M_ASYNC.*/ + MPI_Comm_size(MPI_COMM_WORLD, &np_total); + MPI_Comm_size(fd->comm, &np_comm); + if (np_total == np_comm) { + err = _setiomode(fd->fd_sys, M_UNIX); + err = _setiomode(fd->fd_sys, M_ASYNC); + } + /* else it is M_UNIX anyway, so no problem */ + } + fcntl_struct->fsize = lseek(fd->fd_sys, 0, SEEK_END); + if (fd->fp_sys_posn != -1) + lseek(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); + *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + err = _lsize(fd->fd_sys, fcntl_struct->diskspace, SEEK_SET); + 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; + break; + + case ADIO_FCNTL_SET_ATOMICITY: + MPI_Comm_size(MPI_COMM_WORLD, &np_total); + MPI_Comm_size(fd->comm, &np_comm); + if (np_total == np_comm) { + iomod = (fcntl_struct->atomicity == 0) ? M_ASYNC : M_UNIX; + err = _setiomode(fd->fd_sys, iomod); + } + /* else can't do anything because setiomode is global. but + the file will have been opened with M_UNIX anyway, because + gopen is also global. */ + + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + if (err == -1) { + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); + /* --END ERROR HANDLING-- */ + } + else *error_code = MPI_SUCCESS; + break; + + default: + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPI_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**flag", "**flag %d", flag); + return; + /* --END ERROR HANDLING-- */ + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_flush.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_flush.c new file mode 100644 index 0000000000..98dedc099c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_flush.c @@ -0,0 +1,38 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +void ADIOI_PFS_Flush(ADIO_File fd, int *error_code) +{ + int err, np_total, np_comm; + static char myname[] = "ADIOI_PFS_FLUSH"; + +/* fsync is not actually needed in PFS, because it uses something + called fast-path I/O. However, it doesn't do any harm either. */ + err = fsync(fd->fd_sys); + 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-IO requires that after an fsync all processes must see the same + file size. In PFS M_ASYNC mode, this doesn't automatically happen. + Therefore, if M_ASYNC mode, temporarily change it to M_UNIX mode + and then switch back to M_ASYNC. That updates the file size! */ + + MPI_Comm_size(MPI_COMM_WORLD, &np_total); + MPI_Comm_size(fd->comm, &np_comm); + if ((np_total == np_comm) && (!(fd->atomicity))) { + err = _setiomode(fd->fd_sys, M_UNIX); + err = _setiomode(fd->fd_sys, M_ASYNC); + } + /* else it is M_UNIX anyway. don't do anything. */ +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_hints.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_hints.c new file mode 100644 index 0000000000..407a0eb775 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_hints.c @@ -0,0 +1,174 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +void ADIOI_PFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ + char *value, *value_in_fd; + int flag, tmp_val, str_factor=-1, str_unit=-1, start_iodev=-1; + struct sattr attr; + int err, myrank, fd_sys, perm, amode, old_mask; + + if ( (fd->info) == MPI_INFO_NULL) { + /* This must be part of the open call. can set striping parameters + if necessary. */ + MPI_Info_create(&(fd->info)); + + /* has user specified striping or server buffering parameters + and do they have the same value on all processes? */ + if (users_info != MPI_INFO_NULL) { + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + + ADIOI_Info_get(users_info, "striping_factor", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + str_factor=atoi(value); + tmp_val = str_factor; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + /* --BEGIN ERROR HANDLING-- */ + if (tmp_val != str_factor) { + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, + "striping_factor", + error_code); + return; + } + /* --END ERROR HANDLING-- */ + } + + ADIOI_Info_get(users_info, "striping_unit", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + str_unit=atoi(value); + tmp_val = str_unit; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + /* --BEGIN ERROR HANDLING-- */ + if (tmp_val != str_unit) { + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, + "striping_unit", + error_code); + return; + } + /* --END ERROR HANDLING-- */ + } + + ADIOI_Info_get(users_info, "start_iodevice", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + start_iodev=atoi(value); + tmp_val = start_iodev; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + /* --BEGIN ERROR HANDLING-- */ + if (tmp_val != start_iodev) { + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, + "start_iodevice", + error_code); + return; + } + /* --END ERROR HANDLING-- */ + } + + /* if user has specified striping info, process 0 tries to set it */ + if ((str_factor > 0) || (str_unit > 0) || (start_iodev >= 0)) { + MPI_Comm_rank(fd->comm, &myrank); + if (!myrank) { + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + fd_sys = open(fd->filename, amode, perm); + err = fcntl(fd_sys, F_GETSATTR, &attr); + + if (!err) { + if (str_unit > 0) attr.s_sunitsize = str_unit; + if ((start_iodev >= 0) && + (start_iodev < attr.s_sfactor)) + attr.s_start_sdir = start_iodev; + if ((str_factor > 0) && (str_factor < attr.s_sfactor)) + attr.s_sfactor = str_factor; + + err = fcntl(fd_sys, F_SETSATTR, &attr); + } + + close(fd_sys); + } + + MPI_Barrier(fd->comm); + } + + /* Has user asked for pfs server buffering to be turned on? + If so, mark it as true in fd->info and turn it on in + ADIOI_PFS_Open after the file is opened */ + + ADIOI_Info_get(users_info, "pfs_svr_buf", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && (!strcmp(value, "true"))) + ADIOI_Info_set(fd->info, "pfs_svr_buf", "true"); + else ADIOI_Info_set(fd->info, "pfs_svr_buf", "false"); + + ADIOI_Free(value); + } + else ADIOI_Info_set(fd->info, "pfs_svr_buf", "false"); + + /* set the values for collective I/O and data sieving parameters */ + ADIOI_GEN_SetInfo(fd, users_info, error_code); + } + + else { + /* The file has been opened previously and fd->fd_sys is a valid + file descriptor. cannot set striping parameters now. */ + + /* set the values for collective I/O and data sieving parameters */ + ADIOI_GEN_SetInfo(fd, users_info, error_code); + + /* has user specified value for pfs_svr_buf? */ + if (users_info != MPI_INFO_NULL) { + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + + ADIOI_Info_get(users_info, "pfs_svr_buf", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && (!strcmp(value, "true") || !strcmp(value, "false"))) { + value_in_fd = (char *) + ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + ADIOI_Info_get(fd->info, "pfs_svr_buf", MPI_MAX_INFO_VAL, + value_in_fd, &flag); + if (strcmp(value, value_in_fd)) { + if (!strcmp(value, "true")) { + err = fcntl(fd->fd_sys, F_PFS_SVR_BUF, TRUE); + if (!err) + ADIOI_Info_set(fd->info, "pfs_svr_buf", "true"); + } + else { + err = fcntl(fd->fd_sys, F_PFS_SVR_BUF, FALSE); + if (!err) + ADIOI_Info_set(fd->info, "pfs_svr_buf", "false"); + } + } + ADIOI_Free(value_in_fd); + } + ADIOI_Free(value); + } + + } + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_iread.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_iread.c new file mode 100644 index 0000000000..78b3c592fb --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_iread.c @@ -0,0 +1,81 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +void ADIOI_PFS_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code) +{ + long *id_sys; + int err=-1; + MPI_Count len, typesize; + ADIO_Offset off; + static char myname[] = "ADIOI_PFS_IREADCONTIG"; + + *request = ADIOI_Malloc_request(); + (*request)->optype = ADIOI_READ; + (*request)->fd = fd; + (*request)->datatype = datatype; + + MPI_Type_size_x(datatype, &typesize); + len = count * typesize; + + id_sys = (long *) ADIOI_Malloc(sizeof(long)); + (*request)->handle = (void *) id_sys; + + off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : offset; + + lseek(fd->fd_sys, off, SEEK_SET); + *id_sys = _iread(fd->fd_sys, buf, len); + + if ((*id_sys == -1) && (errno == EQNOMID)) { + /* the man pages say EMREQUEST, but in reality errno is set to EQNOMID! */ + + /* exceeded the max. no. of outstanding requests. */ + + /* complete all previous async. requests */ + /*ADIOI_Complete_async(error_code); */ + if (*error_code != MPI_SUCCESS) return; + + /* try again */ + *id_sys = _iread(fd->fd_sys, buf, len); + + if ((*id_sys == -1) && (errno == EQNOMID)) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); + return; + } + } + else if (*id_sys == -1) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", strerror(errno)); + return; + } + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += len; + + (*request)->queued = 1; + (*request)->nbytes = len; + ADIOI_Add_req_to_list(request); + fd->async_count++; + + fd->fp_sys_posn = -1; /* set it to null. */ + + if (*id_sys == -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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_iwrite.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_iwrite.c new file mode 100644 index 0000000000..5dda2fbdeb --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_iwrite.c @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +void ADIOI_PFS_IwriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int *error_code) +{ + long *id_sys; + ADIO_Offset off; + int err; + MPI_Count len, typesize; + static char myname[] = "ADIOI_PFS_IWRITECONTIG"; + + *request = ADIOI_Malloc_request(); + (*request)->optype = ADIOI_WRITE; + (*request)->fd = fd; + (*request)->datatype = datatype; + + MPI_Type_size_x(datatype, &typesize); + len = count * typesize; + + id_sys = (long *) ADIOI_Malloc(sizeof(long)); + (*request)->handle = (void *) id_sys; + + off = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : offset; + + lseek(fd->fd_sys, off, SEEK_SET); + *id_sys = _iwrite(fd->fd_sys, buf, len); + + if ((*id_sys == -1) && (errno == EQNOMID)) { + /* the man pages say EMREQUEST, but in reality errno is set to EQNOMID! */ + + /* exceeded the max. no. of outstanding requests. */ + + /* complete all previous async. requests */ + ADIOI_Complete_async(error_code); + if (error_code != MPI_SUCCESS) return; + + /* try again */ + *id_sys = _iwrite(fd->fd_sys, buf, len); + + if ((*id_sys == -1) && (errno == EQNOMID)) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); + return; + } + } + else if (*id_sys == -1) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**io", + "**io %s", strerror(errno)); + return; + } + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += len; + + (*request)->queued = 1; + (*request)->nbytes = len; + ADIOI_Add_req_to_list(request); + fd->async_count++; + + fd->fp_sys_posn = -1; /* set it to null. */ + + if (*id_sys == -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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_open.c new file mode 100644 index 0000000000..f814b7c0a1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_open.c @@ -0,0 +1,85 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +void ADIOI_PFS_Open(ADIO_File fd, int *error_code) +{ + int perm, amode, old_mask, np_comm, np_total, err, flag; + char *value; + struct sattr attr; + static char myname[] = "ADIOI_PFS_OPEN"; + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + MPI_Comm_size(MPI_COMM_WORLD, &np_total); + MPI_Comm_size(fd->comm, &np_comm); + + if (np_total == np_comm) + fd->fd_sys = _gopen(fd->filename, amode, M_ASYNC, perm); + else fd->fd_sys = open(fd->filename, amode, perm); + fd->fd_direct = -1; + + if (fd->fd_sys != -1) { + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + + /* if user has asked for pfs server buffering to be turned on, + it will be set to true in fd->info in the earlier call + to ADIOI_PFS_SetInfo. Turn it on now, since we now have a + valid file descriptor. */ + + ADIOI_Info_get(fd->info, "pfs_svr_buf", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && (!strcmp(value, "true"))) { + err = fcntl(fd->fd_sys, F_PFS_SVR_BUF, TRUE); + if (err) ADIOI_Info_set(fd->info, "pfs_svr_buf", "false"); + } + + /* get file striping information and set it in info */ + err = fcntl(fd->fd_sys, F_GETSATTR, &attr); + + if (!err) { + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", attr.s_sunitsize); + ADIOI_Info_set(fd->info, "striping_unit", value); + + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", attr.s_sfactor); + ADIOI_Info_set(fd->info, "striping_factor", value); + + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", attr.s_start_sdir); + ADIOI_Info_set(fd->info, "start_iodevice", value); + } + ADIOI_Free(value); + + if (fd->access_mode & ADIO_APPEND) + fd->fp_ind = fd->fp_sys_posn = lseek(fd->fd_sys, 0, SEEK_END); + } + + if (fd->fd_sys == -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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_read.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_read.c new file mode 100644 index 0000000000..bd3b7e70e4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_read.c @@ -0,0 +1,48 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +void ADIOI_PFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code) +{ + MPI_Count err=-1, datatype_size, len; + static char myname[] = "ADIOI_PFS_READCONTIG"; + + MPI_Type_size_x(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); + } + err = _cread(fd->fd_sys, buf, len); + fd->fp_sys_posn = offset + err; + /* individual file pointer not updated */ + } + else { /* read from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) { + lseek(fd->fd_sys, fd->fp_ind, SEEK_SET); + } + err = _cread(fd->fd_sys, buf, 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 + + 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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_wait.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_wait.c new file mode 100644 index 0000000000..e14159521a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_wait.c @@ -0,0 +1,62 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +void ADIOI_PFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + int err=0; + static char myname[] = "ADIOI_PFS_READCOMPLETE"; + + if (*request == ADIO_REQUEST_NULL) { + *error_code = MPI_SUCCESS; + return; + } + + if ((*request)->queued) { + err = _iowait(*((long *) (*request)->handle)); + 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; + } /* if ((*request)->queued) ... */ + else *error_code = MPI_SUCCESS; +#ifdef HAVE_STATUS_SET_BYTES + if ((*request)->nbytes != -1) + MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes); +#endif + + if ((*request)->queued != -1) { + + /* queued = -1 is an internal hack used when the request must + be completed, but the request object should not be + freed. This is used in ADIOI_Complete_async, because the user + will call MPI_Wait later, which would require status to + be filled. Ugly but works. queued = -1 should be used only + in ADIOI_Complete_async. + This should not affect the user in any way. */ + + /* if request is still queued in the system, it is also there + on ADIOI_Async_list. Delete it from there. */ + if ((*request)->queued) ADIOI_Del_req_from_list(request); + + (*request)->fd->async_count--; + if ((*request)->handle) ADIOI_Free((*request)->handle); + ADIOI_Free_request((ADIOI_Req_node *) (*request)); + *request = ADIO_REQUEST_NULL; + } +} + + +void ADIOI_PFS_WriteComplete(ADIO_Request *request, ADIO_Status *status, int *error_code) +{ + ADIOI_PFS_ReadComplete(request, status, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_write.c b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_write.c new file mode 100644 index 0000000000..c64e976a2b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pfs/ad_pfs_write.c @@ -0,0 +1,49 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pfs.h" + +void ADIOI_PFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + MPI_Count err=-1, datatype_size, len; + static char myname[] = "ADIOI_PFS_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) { + lseek(fd->fd_sys, offset, SEEK_SET); + } + err = _cwrite(fd->fd_sys, buf, len); + fd->fp_sys_posn = offset + err; + /* individual file pointer not updated */ + } + else { /* write from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) { + lseek(fd->fd_sys, fd->fp_ind, SEEK_SET); + } + err = _cwrite(fd->fd_sys, buf, 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 + + 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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_piofs/Makefile.mk new file mode 100644 index 0000000000..4bcbd61f24 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/Makefile.mk @@ -0,0 +1,21 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_PIOFS + +noinst_HEADERS += adio/ad_piofs/ad_piofs.h + +romio_other_sources += \ + adio/ad_piofs/ad_piofs_read.c \ + adio/ad_piofs/ad_piofs_open.c \ + adio/ad_piofs/ad_piofs_write.c \ + adio/ad_piofs/ad_piofs_fcntl.c \ + adio/ad_piofs/ad_piofs_hints.c \ + adio/ad_piofs/ad_piofs.c + +endif BUILD_AD_PIOFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/README b/ompi/mca/io/romio314/romio/adio/ad_piofs/README new file mode 100644 index 0000000000..933677b177 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/README @@ -0,0 +1 @@ +This code is no longer supported. diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs.c b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs.c new file mode 100644 index 0000000000..29d8c3010d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs.c @@ -0,0 +1,37 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_piofs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_PIOFS_operations = { + ADIOI_PIOFS_Open, /* Open */ + ADIOI_PIOFS_ReadContig, /* ReadContig */ + ADIOI_PIOFS_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_PIOFS_Fcntl, /* Fcntl */ + ADIOI_PIOFS_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_PIOFS_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ + ADIOI_FAKE_IODone, /* ReadDone */ + ADIOI_FAKE_IODone, /* WriteDone */ + ADIOI_FAKE_IOComplete, /* ReadComplete */ + ADIOI_FAKE_IOComplete, /* WriteComplete */ + ADIOI_FAKE_IreadStrided, /* IreadStrided */ + ADIOI_FAKE_IwriteStrided, /* IwriteStrided */ + ADIOI_GEN_Flush, /* Flush */ + ADIOI_GEN_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ + ADIOI_PIOFS_Feature, +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs.h b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs.h new file mode 100644 index 0000000000..e9b74c9e87 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs.h @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* contains definitions, declarations, and macros specific to the + implementation of ADIO on PIOFS */ + +#ifndef AD_PIOFS_INCLUDE +#define AD_PIOFS_INCLUDE + +#include +#include +#include +#include +#include +#include "adio.h" + +void ADIOI_PIOFS_Open(ADIO_File fd, int *error_code); +void ADIOI_PIOFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PIOFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PIOFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIOI_PIOFS_WriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PIOFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); + +void ADIOI_PIOFS_Feature(ADIO_File fd, int flag); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_fcntl.c new file mode 100644 index 0000000000..7d4a37cbfd --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_fcntl.c @@ -0,0 +1,77 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_piofs.h" +#include "adio_extern.h" + +void ADIOI_PIOFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code) +{ + MPI_Datatype copy_etype, copy_filetype; + int i, ntimes, err; + ADIO_Offset curr_fsize, alloc_size, size, len, done; + ADIO_Status status; + char *buf; + piofs_change_view_t *piofs_change_view; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_PIOFS_FCNTL"; +#endif + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + fcntl_struct->fsize = llseek(fd->fd_sys, 0, SEEK_END); + if (fd->fp_sys_posn != -1) + llseek(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); + if (fcntl_struct->fsize == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-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); +#endif + } + else *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + ADIOI_GEN_Prealloc(fd, fcntl_struct->diskspace, error_code); + break; + + case ADIO_FCNTL_SET_ATOMICITY: + piofs_change_view = (piofs_change_view_t *) + ADIOI_Malloc(sizeof(piofs_change_view_t)); + piofs_change_view->Vbs = piofs_change_view->Vn = + piofs_change_view->Hbs = piofs_change_view->Hn = 1; + piofs_change_view->subfile = 0; + piofs_change_view->flags = (fcntl_struct->atomicity == 0) + ? (ACTIVE | NORMAL) : (ACTIVE | CAUTIOUS); + err = piofsioctl(fd->fd_sys, PIOFS_CHANGE_VIEW, piofs_change_view); + ADIOI_Free(piofs_change_view); + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + if (err == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-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); +#endif + } + else *error_code = MPI_SUCCESS; + break; + + default: + FPRINTF(stderr, "Unknown flag passed to ADIOI_PIOFS_Fcntl\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_features.c b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_features.c new file mode 100644 index 0000000000..f3b0df6b21 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_features.c @@ -0,0 +1,19 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +int ADIOI_PIOFS_Features(int flag) +{ + switch(flag) { + case ADIO_LOCKS: + case ADIO_SHARED_FP: + case ADIO_ATOMIC_MODE: + case ADIO_DATA_SIEVING_WRITES: + case ADIO_SCALABLE_OPEN: + default: + return 0; + break; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_hints.c b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_hints.c new file mode 100644 index 0000000000..242ebb3f07 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_hints.c @@ -0,0 +1,118 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_piofs.h" + +void ADIOI_PIOFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ + piofs_create_t piofs_create; + piofs_statfs_t piofs_statfs; + char *value, *path, *slash; + int flag, tmp_val, str_factor=-1, str_unit=-1, start_iodev=-1; + int err, myrank, perm, old_mask, nioservers; + + if ((fd->info) == MPI_INFO_NULL) { + /* This must be part of the open call. can set striping parameters + if necessary. */ + MPI_Info_create(&(fd->info)); + + /* has user specified striping parameters + and do they have the same value on all processes? */ + if (users_info != MPI_INFO_NULL) { + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + + ADIOI_Info_get(users_info, "striping_factor", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + str_factor=atoi(value); + tmp_val = str_factor; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + if (tmp_val != str_factor) { + FPRINTF(stderr, "ADIOI_PIOFS_SetInfo: the value for key \"striping_factor\" must be the same on all processes\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + } + + ADIOI_Info_get(users_info, "striping_unit", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + str_unit=atoi(value); + tmp_val = str_unit; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + if (tmp_val != str_unit) { + FPRINTF(stderr, "ADIOI_PIOFS_SetInfo: the value for key \"striping_unit\" must be the same on all processes\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + } + + ADIOI_Info_get(users_info, "start_iodevice", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + start_iodev=atoi(value); + tmp_val = start_iodev; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + if (tmp_val != start_iodev) { + FPRINTF(stderr, "ADIOI_PIOFS_SetInfo: the value for key \"start_iodevice\" must be the same on all processes\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + } + + ADIOI_Free(value); + + /* if user has specified striping info, process 0 tries to set it */ + if ((str_factor > 0) || (str_unit > 0) || (start_iodev >= 0)) { + MPI_Comm_rank(fd->comm, &myrank); + if (!myrank) { + int len; + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + /* to find out the number of I/O servers, I need + the path to the directory containing the file */ + + path = ADIOI_Strdup(fd->filename); + len = strlen(path) + 1; + slash = strrchr(path, '/'); + if (!slash) ADIOI_Strncpy(path, ".", len); + else { + if (slash == path) *(path + 1) = '\0'; + else *slash = '\0'; + } + ADIOI_Strncpy(piofs_statfs.name, path, len); + err = piofsioctl(0, PIOFS_STATFS, &piofs_statfs); + nioservers = (err) ? -1 : piofs_statfs.f_nodes; + + ADIOI_Free(path); + + str_factor = ADIOI_MIN(nioservers, str_factor); + if (start_iodev >= nioservers) start_iodev = -1; + + ADIOI_Strncpy(piofs_create.name, fd->filename, len); + piofs_create.bsu = (str_unit > 0) ? str_unit : -1; + piofs_create.cells = (str_factor > 0) ? str_factor : -1; + piofs_create.permissions = perm; + piofs_create.base_node = (start_iodev >= 0) ? + start_iodev : -1; + piofs_create.flags = 0; + + err = piofsioctl(0, PIOFS_CREATE, &piofs_create); + } + MPI_Barrier(fd->comm); + } + } + } + + /* set the values for collective I/O and data sieving parameters */ + ADIOI_GEN_SetInfo(fd, users_info, error_code); + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_open.c b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_open.c new file mode 100644 index 0000000000..e02e90cf32 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_open.c @@ -0,0 +1,79 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_piofs.h" + +void ADIOI_PIOFS_Open(ADIO_File fd, int *error_code) +{ + int amode, perm, old_mask, err; + piofs_fstat_t piofs_fstat; + char *value; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_PIOFS_OPEN"; +#endif + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + fd->fd_sys = open(fd->filename, amode, perm); + fd->fd_direct = -1; + + llseek(fd->fd_sys, 0, SEEK_SET); +/* required to initiate use of 64-bit offset */ + + if (fd->fd_sys != -1) { + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + + /* get file striping information and set it in info */ + err = piofsioctl(fd->fd_sys, PIOFS_FSTAT, &piofs_fstat); + + if (!err) { + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", piofs_fstat.st_bsu); + ADIOI_Info_set(fd->info, "striping_unit", value); + + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", piofs_fstat.st_cells); + ADIOI_Info_set(fd->info, "striping_factor", value); + + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", piofs_fstat.st_base_node); + ADIOI_Info_set(fd->info, "start_iodevice", value); + } + ADIOI_Free(value); + + if (fd->access_mode & ADIO_APPEND) + fd->fp_ind = fd->fp_sys_posn = llseek(fd->fd_sys, 0, SEEK_END); + } + + if (fd->fd_sys == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-1 */ + *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, + myname, "I/O Error", "%s", strerror(errno)); + ADIOI_Error(ADIO_FILE_NULL, *error_code, myname); +#endif + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_read.c b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_read.c new file mode 100644 index 0000000000..278548656e --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_read.c @@ -0,0 +1,56 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_piofs.h" + +void ADIOI_PIOFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code) +{ + MPI_Count err=-1, datatype_size, len; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_PIOFS_READCONTIG"; +#endif + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + if (fd->fp_sys_posn != offset) { + llseek(fd->fd_sys, offset, SEEK_SET); + } + err = read(fd->fd_sys, buf, len); + fd->fp_sys_posn = offset + err; + /* individual file pointer not updated */ + } + else { /* read from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) { + llseek(fd->fd_sys, fd->fp_ind, SEEK_SET); + } + err = read(fd->fd_sys, buf, 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 + + if (err == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else + *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, + myname, "I/O Error", "%s", strerror(errno)); + ADIOI_Error(fd, *error_code, myname); +#endif + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_write.c b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_write.c new file mode 100644 index 0000000000..4e1c7f1159 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_piofs/ad_piofs_write.c @@ -0,0 +1,344 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_piofs.h" +#include "adio_extern.h" + +void ADIOI_PIOFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code) +{ + MPI_Count err=-1, datatype_size, len; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_PIOFS_WRITECONTIG"; +#endif + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + if (fd->fp_sys_posn != offset) { + llseek(fd->fd_sys, offset, SEEK_SET); + } + err = write(fd->fd_sys, buf, len); + fd->fp_sys_posn = offset + err; + /* individual file pointer not updated */ + } + else { /* write from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) { + llseek(fd->fd_sys, fd->fp_ind, SEEK_SET); + } + err = write(fd->fd_sys, buf, 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 + + if (err == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else + *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, + myname, "I/O Error", "%s", strerror(errno)); + ADIOI_Error(fd, *error_code, myname); +#endif + } + else *error_code = MPI_SUCCESS; +} + + + +void ADIOI_PIOFS_WriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ +/* Since PIOFS does not support file locking, can't do buffered writes + as on Unix */ + +/* offset is in units of etype relative to the filetype. */ + + ADIOI_Flatlist_node *flat_buf, *flat_file; + struct iovec *iov; + int i, j, k, err=-1, bwr_size, fwr_size=0, 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; + MPI_Count filetype_size, etype_size, buftype_size; + MPI_Aint filetype_extent, buftype_extent, indx; + int buf_count, buftype_is_contig, filetype_is_contig; + ADIO_Offset off, disp; + int flag, new_bwr_size, new_fwr_size, err_flag=0; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_PIOFS_WRITESTRIDED"; +#endif + + if (fd->atomicity) { + FPRINTF(stderr, "ROMIO cannot guarantee atomicity of noncontiguous accesses in atomic mode, as PIOFS doesn't support file locking. Use nonatomic mode and its associated semantics.\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + 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; + + if (!buftype_is_contig && filetype_is_contig) { + +/* noncontiguous in memory, contiguous in file. use writev */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + +/* There is a limit of 16 on the number of iovecs for readv/writev! */ + + iov = (struct iovec *) ADIOI_Malloc(16*sizeof(struct iovec)); + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + etype_size * offset; + llseek(fd->fd_sys, off, SEEK_SET); + } + else off = llseek(fd->fd_sys, fd->fp_ind, SEEK_SET); + + k = 0; + for (j=0; jcount; i++) { + iov[k].iov_base = ((char *) buf) + j*buftype_extent + + flat_buf->indices[i]; + iov[k].iov_len = flat_buf->blocklens[i]; + /*FPRINTF(stderr, "%d %d\n", iov[k].iov_base, iov[k].iov_len);*/ + + off += flat_buf->blocklens[i]; + k = (k+1)%16; + + if (!k) { + err = writev(fd->fd_sys, iov, 16); + if (err == -1) err_flag = 1; + } + } + + if (k) { + err = writev(fd->fd_sys, iov, k); + if (err == -1) err_flag = 1; + } + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; + + ADIOI_Free(iov); + if (err_flag) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-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); +#endif + } + else *error_code = MPI_SUCCESS; + } /* if (!buftype_is_contig && filetype_is_contig) ... */ + + else { /* noncontiguous in file */ + +/* split up into several contiguous writes */ + +/* find starting location in the 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; icount; i++) { + if (disp + flat_file->indices[i] + + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[i] + >= offset) { + st_index = i; + fwr_size = 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; icount; 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; + } + + 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; + fwr_size = ADIOI_MIN(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 */ + llseek(fd->fd_sys, off, SEEK_SET); + err = write(fd->fd_sys, ((char *) buf) + i, fwr_size); + if (err == -1) err_flag = 1; + } + 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 { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + k = num = buf_count = 0; + indx = flat_buf->indices[0]; + j = st_index; + off = offset; + bwr_size = flat_buf->blocklens[0]; + + while (num < bufsize) { + size = ADIOI_MIN(fwr_size, bwr_size); + if (size) { + llseek(fd->fd_sys, off, SEEK_SET); + err = write(fd->fd_sys, ((char *) buf) + indx, size); + if (err == -1) err_flag = 1; + } + + new_fwr_size = fwr_size; + new_bwr_size = bwr_size; + + if (size == fwr_size) { +/* reached end of contiguous block in file */ + if (j < (flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + + off = disp + flat_file->indices[j] + + (ADIO_Offset) n_filetypes*filetype_extent; + + new_fwr_size = flat_file->blocklens[j]; + if (size != bwr_size) { + indx += size; + new_bwr_size -= size; + } + } + + if (size == bwr_size) { +/* reached end of contiguous block in memory */ + + k = (k + 1)%flat_buf->count; + buf_count++; + indx = buftype_extent*(buf_count/flat_buf->count) + + flat_buf->indices[k]; + new_bwr_size = flat_buf->blocklens[k]; + if (size != fwr_size) { + off += size; + new_fwr_size -= size; + } + } + num += size; + fwr_size = new_fwr_size; + bwr_size = new_bwr_size; + } + } + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; + if (err_flag) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-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); +#endif + } + else *error_code = MPI_SUCCESS; + } + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_pvfs/Makefile.mk new file mode 100644 index 0000000000..50e7bd0ae6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/Makefile.mk @@ -0,0 +1,26 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_PVFS + +noinst_HEADERS += adio/ad_pvfs/ad_pvfs.h + +romio_other_sources += \ + adio/ad_pvfs/ad_pvfs_close.c \ + adio/ad_pvfs/ad_pvfs_read.c \ + adio/ad_pvfs/ad_pvfs_open.c \ + adio/ad_pvfs/ad_pvfs_write.c \ + adio/ad_pvfs/ad_pvfs_fcntl.c \ + adio/ad_pvfs/ad_pvfs_flush.c \ + adio/ad_pvfs/ad_pvfs_resize.c \ + adio/ad_pvfs/ad_pvfs_hints.c \ + adio/ad_pvfs/ad_pvfs_delete.c \ + adio/ad_pvfs/ad_pvfs.c + +endif BUILD_AD_PVFS + + diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs.c new file mode 100644 index 0000000000..92b6df63e9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs.c @@ -0,0 +1,37 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_PVFS_operations = { + ADIOI_PVFS_Open, /* Open */ + ADIOI_PVFS_ReadContig, /* ReadContig */ + ADIOI_PVFS_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_PVFS_Fcntl, /* Fcntl */ + ADIOI_PVFS_SetInfo, /* SetInfo */ + ADIOI_PVFS_ReadStrided, /* ReadStrided */ + ADIOI_PVFS_WriteStrided, /* WriteStrided */ + ADIOI_PVFS_Close, /* Close */ + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ + ADIOI_FAKE_IODone, /* ReadDone */ + ADIOI_FAKE_IODone, /* WriteDone */ + ADIOI_FAKE_IOComplete, /* ReadComplete */ + ADIOI_FAKE_IOComplete, /* WriteComplete */ + ADIOI_FAKE_IreadStrided, /* IreadStrided */ + ADIOI_FAKE_IwriteStrided, /* IwriteStrided */ + ADIOI_PVFS_Flush, /* Flush */ + ADIOI_PVFS_Resize, /* Resize */ + ADIOI_PVFS_Delete, /* Delete */ + ADIOI_PVFS_Feature, /* Features */ +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs.h b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs.h new file mode 100644 index 0000000000..88e1a9f225 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_PVFS_INCLUDE +#define AD_PVFS_INCLUDE + +#ifndef ROMIOCONF_H_INCLUDED +#include "romioconf.h" +#define ROMIOCONF_H_INCLUDED +#endif +#ifdef ROMIO_PVFS_NEEDS_INT64_DEFINITION +typedef long long int int64_t; +#endif + +#include +#include +#include +#include +#ifdef HAVE_PVFS_H +#include +#endif +#include "adio.h" + +void ADIOI_PVFS_Open(ADIO_File fd, int *error_code); +void ADIOI_PVFS_Close(ADIO_File fd, int *error_code); +void ADIOI_PVFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PVFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PVFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIOI_PVFS_WriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PVFS_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PVFS_Flush(ADIO_File fd, int *error_code); +void ADIOI_PVFS_Delete(char *filename, int *error_code); +void ADIOI_PVFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +void ADIOI_PVFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); + + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_close.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_close.c new file mode 100644 index 0000000000..c2da2e360e --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_close.c @@ -0,0 +1,31 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs.h" + +void ADIOI_PVFS_Close(ADIO_File fd, int *error_code) +{ + int err; + static char myname[] = "ADIOI_PVFS_CLOSE"; + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_close_a, 0, NULL ); +#endif + err = pvfs_close(fd->fd_sys); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_close_b, 0, NULL ); +#endif + fd->fd_sys = -1; + + 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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_delete.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_delete.c new file mode 100644 index 0000000000..0e322ad32a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_delete.c @@ -0,0 +1,24 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs.h" +#include "adio.h" + +void ADIOI_PVFS_Delete(char *filename, int *error_code) +{ + int err; + static char myname[] = "ADIOI_PVFS_DELETE"; + + err = pvfs_unlink(filename); + 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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_fcntl.c new file mode 100644 index 0000000000..eeff250718 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_fcntl.c @@ -0,0 +1,72 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs.h" +#include "adio_extern.h" + +void ADIOI_PVFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code) +{ + static char myname[] = "ADIOI_PVFS_FCNTL"; + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + fcntl_struct->fsize = pvfs_lseek64(fd->fd_sys, 0, SEEK_END); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + if (fd->fp_sys_posn != -1) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + pvfs_lseek64(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + } + if (fcntl_struct->fsize == -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; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + ADIOI_GEN_Prealloc(fd, fcntl_struct->diskspace, error_code); + break; + + case ADIO_FCNTL_SET_ATOMICITY: + fd->atomicity = 0; + /* --BEGIN ERROR HANDLING-- */ + if (fcntl_struct->atomicity != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_UNSUPPORTED_OPERATION, + "PVFS does not support atomic mode", + 0); + return; + } + /* --END ERROR HANDLING-- */ + break; + + default: + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**flag", "**flag %d", flag); + return; + /* --END ERROR HANDLING-- */ + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_flush.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_flush.c new file mode 100644 index 0000000000..340f0cb339 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_flush.c @@ -0,0 +1,36 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs.h" + +void ADIOI_PVFS_Flush(ADIO_File fd, int *error_code) +{ + int err, rank, dummy=0, dummy_in=0; + static char myname[] = "ADIOI_PVFS_FLUSH"; + + /* a collective routine: because we do not cache data in PVFS1, one process + * can initiate the fsync operation and broadcast the result to the others. + * One catch: MPI_File_sync has special meaning with respect to file system + * consistency. Ensure no clients have outstanding write operations. + */ + + MPI_Comm_rank(fd->comm, &rank); + MPI_Reduce(&dummy_in, &dummy, 1, MPI_INT, MPI_SUM, + fd->hints->ranklist[0], fd->comm); + if (rank == fd->hints->ranklist[0]) { + err = pvfs_fsync(fd->fd_sys); + } + MPI_Bcast(&err, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + + 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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_hints.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_hints.c new file mode 100644 index 0000000000..fdc06ed846 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_hints.c @@ -0,0 +1,146 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs.h" + +void ADIOI_PVFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ + char *value; + int flag, tmp_val, str_factor=-1, str_unit=-1, start_iodev=-1; + static char myname[] = "ADIOI_PVFS_SETINFO"; + + if ((fd->info) == MPI_INFO_NULL) { + /* This must be part of the open call. can set striping parameters + if necessary. */ + MPI_Info_create(&(fd->info)); + ADIOI_Info_set(fd->info, "romio_pvfs_listio_read", "disable"); + ADIOI_Info_set(fd->info, "romio_pvfs_listio_write", "disable"); + fd->hints->fs_hints.pvfs.listio_read = ADIOI_HINT_DISABLE; + fd->hints->fs_hints.pvfs.listio_write = ADIOI_HINT_DISABLE; + + /* has user specified any pvfs-specific hints (striping params, listio) + and do they have the same value on all processes? */ + if (users_info != MPI_INFO_NULL) { + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + + ADIOI_Info_get(users_info, "striping_factor", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + str_factor=atoi(value); + tmp_val = str_factor; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + if (tmp_val != str_factor) { + /* --BEGIN ERROR HANDLING-- */ + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, + "striping_factor", + error_code); + return; + /* --END ERROR HANDLING-- */ + } + else ADIOI_Info_set(fd->info, "striping_factor", value); + } + + ADIOI_Info_get(users_info, "striping_unit", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + str_unit=atoi(value); + tmp_val = str_unit; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + if (tmp_val != str_unit) { + /* --BEGIN ERROR HANDLING-- */ + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, + "striping_unit", + error_code); + return; + /* --END ERROR HANDLING-- */ + } + else ADIOI_Info_set(fd->info, "striping_unit", value); + } + + ADIOI_Info_get(users_info, "start_iodevice", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + start_iodev=atoi(value); + tmp_val = start_iodev; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + if (tmp_val != start_iodev) { + /* --BEGIN ERROR HANDLING-- */ + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, + "start_iodevice", + error_code); + return; + /* --END ERROR HANDLING-- */ + } + else ADIOI_Info_set(fd->info, "start_iodevice", value); + } + + ADIOI_Info_get(users_info, "romio_pvfs_listio_read", + MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + if ( !strcmp(value, "enable") || !strcmp(value, "ENABLE")) + { + ADIOI_Info_set(fd->info, "romio_pvfs_listio_read", value); + fd->hints->fs_hints.pvfs.listio_read = ADIOI_HINT_ENABLE; + } else if ( !strcmp(value, "disable") || !strcmp(value, "DISABLE")) + { + ADIOI_Info_set(fd->info , "romio_pvfs_listio_read", value); + fd->hints->fs_hints.pvfs.listio_read = ADIOI_HINT_DISABLE; + } + else if ( !strcmp(value, "automatic") || !strcmp(value, "AUTOMATIC")) + { + ADIOI_Info_set(fd->info, "romio_pvfs_listio_read", value); + fd->hints->fs_hints.pvfs.listio_read = ADIOI_HINT_AUTO; + } + tmp_val = fd->hints->fs_hints.pvfs.listio_read; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + if (tmp_val != fd->hints->fs_hints.pvfs.listio_read) { + /* --BEGIN ERROR HANDLING-- */ + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, + "romio_pvfs_listio_read", + error_code); + return; + /* --END ERROR HANDLING-- */ + } + } + ADIOI_Info_get(users_info, "romio_pvfs_listio_write", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + if ( !strcmp(value, "enable") || !strcmp(value, "ENABLE")) + { + ADIOI_Info_set(fd->info, "romio_pvfs_listio_write", value); + fd->hints->fs_hints.pvfs.listio_write = ADIOI_HINT_ENABLE; + } else if ( !strcmp(value, "disable") || !strcmp(value, "DISABLE")) + { + ADIOI_Info_set(fd->info, "romio_pvfs_listio_write", value); + fd->hints->fs_hints.pvfs.listio_write = ADIOI_HINT_DISABLE; + } + else if ( !strcmp(value, "automatic") || !strcmp(value, "AUTOMATIC")) + { + ADIOI_Info_set(fd->info, "romio_pvfs_listio_write", value); + fd->hints->fs_hints.pvfs.listio_write = ADIOI_HINT_AUTO; + } + tmp_val = fd->hints->fs_hints.pvfs.listio_write; + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + if (tmp_val != fd->hints->fs_hints.pvfs.listio_write) { + /* --BEGIN ERROR HANDLING-- */ + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, + "romio_pvfs_listio_write", + error_code); + return; + /* --END ERROR HANDLING-- */ + } + } + ADIOI_Free(value); + } + } + + /* set the values for collective I/O and data sieving parameters */ + ADIOI_GEN_SetInfo(fd, users_info, error_code); + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_open.c new file mode 100644 index 0000000000..c4fa28805d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_open.c @@ -0,0 +1,90 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs.h" + +void ADIOI_PVFS_Open(ADIO_File fd, int *error_code) +{ + int perm, amode, old_mask, flag; + char *value; + /* some really old versions of pvfs may not have a release nr */ + /* we changed the structure of pvfs_filestat in pvfs-1.5.7 */ + struct pvfs_filestat pstat = {-1,-1,-1}; + static char myname[] = "ADIOI_PVFS_OPEN"; + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = O_META; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + + ADIOI_Info_get(fd->info, "striping_factor", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && (atoi(value) > 0)) pstat.pcount = atoi(value); + + ADIOI_Info_get(fd->info, "striping_unit", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && (atoi(value) > 0)) pstat.ssize = atoi(value); + + ADIOI_Info_get(fd->info, "start_iodevice", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && (atoi(value) >= 0)) pstat.base = atoi(value); + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_a, 0, NULL ); +#endif + fd->fd_sys = pvfs_open64(fd->filename, amode, perm, &pstat, NULL); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_b, 0, NULL ); +#endif + fd->fd_direct = -1; + + if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND)) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + fd->fp_ind = fd->fp_sys_posn = pvfs_lseek64(fd->fd_sys, 0, SEEK_END); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + } + + if (fd->fd_sys != -1) { + pvfs_ioctl(fd->fd_sys, GETMETA, &pstat); + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", pstat.pcount); + ADIOI_Info_set(fd->info, "striping_factor", value); + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", pstat.ssize); + ADIOI_Info_set(fd->info, "striping_unit", value); + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", pstat.base); + ADIOI_Info_set(fd->info, "start_iodevice", value); + } + + ADIOI_Free(value); + + if (fd->fd_sys == -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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_read.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_read.c new file mode 100644 index 0000000000..71b558a5d1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_read.c @@ -0,0 +1,788 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "ad_pvfs.h" + +#ifdef HAVE_PVFS_LISTIO +void ADIOI_PVFS_ReadStridedListIO(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +#endif + +void ADIOI_PVFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code) +{ + MPI_Count err=-1, datatype_size, len; + static char myname[] = "ADIOI_PVFS_READCONTIG"; + + 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 + pvfs_lseek64(fd->fd_sys, offset, 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 = pvfs_read(fd->fd_sys, buf, len); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + if (err>0) + fd->fp_sys_posn = offset + err; + /* individual file pointer not updated */ + } + else { /* read from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + pvfs_lseek64(fd->fd_sys, fd->fp_ind, 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 = pvfs_read(fd->fd_sys, buf, len); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + if (err > 0) + 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 + + 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_PVFS_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ +#ifdef HAVE_PVFS_LISTIO + if ( fd->hints->fs_hints.pvfs.listio_read == ADIOI_HINT_ENABLE) { + ADIOI_PVFS_ReadStridedListIO(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); + return; + } +#endif +/* If hint set to DISABLE or AUTOMATIC, don't use listio */ + ADIOI_GEN_ReadStrided(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); +} + +#ifdef HAVE_PVFS_LISTIO +void ADIOI_PVFS_ReadStridedListIO(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, l, brd_size, frd_size=0, st_index=0; + int sum, n_etypes_in_filetype, size_in_filetype; + MPI_Count bufsize; + int n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0; + 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, disp, start_off; + int flag, st_frd_size, st_n_filetypes; + int new_brd_size, new_frd_size; + + int mem_list_count, file_list_count; + char **mem_offsets; + int64_t *file_offsets; + int *mem_lengths; + int32_t *file_lengths; + int total_blks_to_read; + + int max_mem_list, max_file_list; + + int b_blks_read; + int f_data_read; + int size_read=0, n_read_lists, extra_blks; + + int end_brd_size, end_frd_size; + int start_k, start_j, new_file_read, new_buffer_read; + int start_mem_offset; + +#define MAX_ARRAY_SIZE 1024 + +#ifndef PRINT_ERR_MESG + static char myname[] = "ADIOI_PVFS_ReadStrided"; +#endif + + *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; + + bufsize = buftype_size * count; + + if (!buftype_is_contig && filetype_is_contig) { + +/* noncontiguous in memory, contiguous in file. */ + int64_t file_offsets; + int32_t file_lengths; + + 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; + + file_list_count = 1; + file_offsets = off; + file_lengths = 0; + total_blks_to_read = count*flat_buf->count; + b_blks_read = 0; + + /* allocate arrays according to max usage */ + if (total_blks_to_read > MAX_ARRAY_SIZE) + mem_list_count = MAX_ARRAY_SIZE; + else mem_list_count = total_blks_to_read; + mem_offsets = (char**)ADIOI_Malloc(mem_list_count*sizeof(char*)); + mem_lengths = (int*)ADIOI_Malloc(mem_list_count*sizeof(int)); + + j = 0; + /* step through each block in memory, filling memory arrays */ + while (b_blks_read < total_blks_to_read) { + for (i=0; icount; i++) { + mem_offsets[b_blks_read % MAX_ARRAY_SIZE] = + (char*)((char *)buf + j*buftype_extent + flat_buf->indices[i]); + mem_lengths[b_blks_read % MAX_ARRAY_SIZE] = + flat_buf->blocklens[i]; + file_lengths += flat_buf->blocklens[i]; + b_blks_read++; + if (!(b_blks_read % MAX_ARRAY_SIZE) || + (b_blks_read == total_blks_to_read)) { + + /* in the case of the last read list call, + adjust mem_list_count */ + if (b_blks_read == total_blks_to_read) { + mem_list_count = total_blks_to_read % MAX_ARRAY_SIZE; + /* in case last read list call fills max arrays */ + if (!mem_list_count) mem_list_count = MAX_ARRAY_SIZE; + } + + pvfs_read_list(fd->fd_sys ,mem_list_count, mem_offsets, + mem_lengths, file_list_count, + &file_offsets, &file_lengths); + + /* in the case of the last read list call, leave here */ + if (b_blks_read == total_blks_to_read) break; + + file_offsets += file_lengths; + file_lengths = 0; + } + } /* for (i=0; icount; i++) */ + j++; + } /* while (b_blks_read < total_blks_to_read) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); + /* This isa temporary way of filling in status. The right way is to + keep tracke of how much data was actually read adn placed in buf + by ADIOI_BUFFERED_READ. */ +#endif + ADIOI_Delete_flattened(datatype); + + return; + } /* if (!buftype_is_contig && filetype_is_contig) */ + + /* know file is noncontiguous from above */ + /* 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; + + /* for each case - ADIO_Individual pointer or explicit, find the file + offset in bytes (offset), n_filetypes (how many filetypes into + file to start), frd_size (remaining amount of data in present + file block), and st_index (start point in terms of blocks in + starting filetype) */ + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; /* in bytes */ + n_filetypes = -1; + flag = 0; + while (!flag) { + n_filetypes++; + for (i=0; icount; 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; + } + } + } /* while (!flag) */ + } /* if (file_ptr_type == ADIO_INDIVIDUAL) */ + 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; icount; 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; + } /* else [file_ptr_type != ADIO_INDIVIDUAL] */ + + start_off = offset; + st_frd_size = frd_size; + st_n_filetypes = n_filetypes; + + if (buftype_is_contig && !filetype_is_contig) { + +/* contiguous in memory, noncontiguous in file. should be the most + common case. */ + + int mem_lengths; + char *mem_offsets; + + i = 0; + j = st_index; + n_filetypes = st_n_filetypes; + + mem_list_count = 1; + + /* determine how many blocks in file to read */ + f_data_read = ADIOI_MIN(st_frd_size, bufsize); + total_blks_to_read = 1; + j++; + while (f_data_read < bufsize) { + f_data_read += flat_file->blocklens[j]; + total_blks_to_read++; + if (j<(flat_file->count-1)) j++; + else j = 0; + } + + j = st_index; + n_filetypes = st_n_filetypes; + n_read_lists = total_blks_to_read/MAX_ARRAY_SIZE; + extra_blks = total_blks_to_read%MAX_ARRAY_SIZE; + + mem_offsets = buf; + mem_lengths = 0; + + /* if at least one full readlist, allocate file arrays + at max array size and don't free until very end */ + if (n_read_lists) { + file_offsets = (int64_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int64_t)); + file_lengths = (int32_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int32_t)); + } + /* if there's no full readlist allocate file arrays according + to needed size (extra_blks) */ + else { + file_offsets = (int64_t*)ADIOI_Malloc(extra_blks* + sizeof(int64_t)); + file_lengths = (int32_t*)ADIOI_Malloc(extra_blks* + sizeof(int32_t)); + } + + /* for file arrays that are of MAX_ARRAY_SIZE, build arrays */ + for (i=0; iindices[j]; + file_lengths[k] = flat_file->blocklens[j]; + mem_lengths += file_lengths[k]; + } + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kfd_sys, mem_list_count, + &mem_offsets, &mem_lengths, + file_list_count, file_offsets, + file_lengths); + mem_offsets += mem_lengths; + mem_lengths = 0; + } /* for (i=0; iindices[j]; + if (k == (extra_blks - 1)) { + file_lengths[k] = bufsize - (int32_t) mem_lengths + - (int32_t) mem_offsets + (int32_t) buf; + } + else file_lengths[k] = flat_file->blocklens[j]; + } /* if(i || k) */ + mem_lengths += file_lengths[k]; + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kfd_sys, mem_list_count, &mem_offsets, + &mem_lengths, file_list_count, file_offsets, + file_lengths); + } + } + else { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + size_read = 0; + n_filetypes = st_n_filetypes; + frd_size = st_frd_size; + brd_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + max_mem_list = 0; + max_file_list = 0; + + /* run through and file max_file_list and max_mem_list so that you + can allocate the file and memory arrays less than MAX_ARRAY_SIZE + if possible */ + + while (size_read < bufsize) { + k = start_k; + new_buffer_read = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data read and data to be + read in the next immediate read list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k] + + size_read) > bufsize) { + end_brd_size = new_buffer_read + + flat_buf->blocklens[k] - (bufsize - size_read); + new_buffer_read = bufsize - size_read; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + else new_buffer_read = brd_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + j = start_j; + new_file_read = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_read < new_buffer_read)) { + if(file_list_count) { + if((new_file_read + flat_file->blocklens[j]) > + new_buffer_read) { + end_frd_size = new_buffer_read - new_file_read; + new_file_read = new_buffer_read; + j--; + } + else { + new_file_read += flat_file->blocklens[j]; + end_frd_size = flat_file->blocklens[j]; + } + } + else { + if (frd_size > new_buffer_read) { + new_file_read = new_buffer_read; + frd_size = new_file_read; + } + else new_file_read = frd_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_read < new_buffer_read) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_read = 0; + mem_list_count = 0; + while (new_buffer_read < new_file_read) { + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k]) > + new_file_read) { + end_brd_size = new_file_read - new_buffer_read; + new_buffer_read = new_file_read; + k--; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_read = brd_size; + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_read < new_file_read) */ + } /* if ((new_file_read < new_buffer_read) && (file_list_count + == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + + /* fakes filling the readlist arrays of lengths found above */ + k = start_k; + j = start_j; + for (i=0; iblocklens[k] == end_brd_size) + brd_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + brd_size = flat_buf->blocklens[k] - end_brd_size; + k--; + buf_count--; + } + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iblocklens[j] == end_frd_size) + frd_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + frd_size = flat_file->blocklens[j] - end_frd_size; + j--; + } + } + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; iblocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + + /* this section calculates mem_list_count and file_list_count + and also finds the possibly odd sized last array elements + in new_frd_size and new_brd_size */ + + while (size_read < bufsize) { + k = start_k; + new_buffer_read = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data read and data to be + read in the next immediate read list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k] + + size_read) > bufsize) { + end_brd_size = new_buffer_read + + flat_buf->blocklens[k] - (bufsize - size_read); + new_buffer_read = bufsize - size_read; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + else new_buffer_read = brd_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + j = start_j; + new_file_read = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_read < new_buffer_read)) { + if(file_list_count) { + if((new_file_read + flat_file->blocklens[j]) > + new_buffer_read) { + end_frd_size = new_buffer_read - new_file_read; + new_file_read = new_buffer_read; + j--; + } + else { + new_file_read += flat_file->blocklens[j]; + end_frd_size = flat_file->blocklens[j]; + } + } + else { + if (frd_size > new_buffer_read) { + new_file_read = new_buffer_read; + frd_size = new_file_read; + } + else new_file_read = frd_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_read < new_buffer_read) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_read = 0; + mem_list_count = 0; + while (new_buffer_read < new_file_read) { + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k]) > + new_file_read) { + end_brd_size = new_file_read - new_buffer_read; + new_buffer_read = new_file_read; + k--; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_read = brd_size; + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_read < new_file_read) */ + } /* if ((new_file_read < new_buffer_read) && (file_list_count + == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + + /* fills the allocated readlist arrays */ + k = start_k; + j = start_j; + for (i=0; icount) + + (int)flat_buf->indices[k]); + if(!i) { + mem_lengths[0] = brd_size; + mem_offsets[0] += flat_buf->blocklens[k] - brd_size; + } + else { + if (i == (mem_list_count - 1)) { + mem_lengths[i] = end_brd_size; + if (flat_buf->blocklens[k] == end_brd_size) + brd_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + brd_size = flat_buf->blocklens[k] - end_brd_size; + k--; + buf_count--; + } + } + else { + mem_lengths[i] = flat_buf->blocklens[k]; + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iindices[j] + n_filetypes * + filetype_extent; + if (!i) { + file_lengths[0] = frd_size; + file_offsets[0] += flat_file->blocklens[j] - frd_size; + } + else { + if (i == (file_list_count - 1)) { + file_lengths[i] = end_frd_size; + if (flat_file->blocklens[j] == end_frd_size) + frd_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + frd_size = flat_file->blocklens[j] - end_frd_size; + j--; + } + } + else file_lengths[i] = flat_file->blocklens[j]; + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; ifd_sys,mem_list_count, mem_offsets, + mem_lengths, file_list_count, file_offsets, + file_lengths); + size_read += new_buffer_read; + start_k = k; + start_j = j; + } /* while (size_read < bufsize) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + } + ADIOI_Free(file_offsets); + ADIOI_Free(file_lengths); + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, 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 + by ADIOI_BUFFERED_READ. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} +#endif /* HAVE_PVFS_LISTIO */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_resize.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_resize.c new file mode 100644 index 0000000000..b4b9553633 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_resize.c @@ -0,0 +1,32 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs.h" + +void ADIOI_PVFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int err; + int rank; + static char myname[] = "ADIOI_PVFS_RESIZE"; + + /* because MPI_File_set_size is a collective operation, and PVFS1 clients + * do not cache metadata locally, one client can resize and broadcast the + * result to the others */ + MPI_Comm_rank(fd->comm, &rank); + if (rank == fd->hints->ranklist[0]) { + err = pvfs_ftruncate64(fd->fd_sys, size); + } + MPI_Bcast(&err, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + + 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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_write.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_write.c new file mode 100644 index 0000000000..4e874d99ac --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs/ad_pvfs_write.c @@ -0,0 +1,1175 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs.h" +#include "adio_extern.h" + +#ifdef HAVE_PVFS_LISTIO +void ADIOI_PVFS_WriteStridedListIO(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +#endif + +void ADIOI_PVFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + MPI_Count err=-1, datatype_size, len; + static char myname[] = "ADIOI_PVFS_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 + pvfs_lseek64(fd->fd_sys, offset, 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_write_a, 0, NULL ); +#endif + err = pvfs_write(fd->fd_sys, buf, len); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err > 0) + fd->fp_sys_posn = offset + err; + /* individual file pointer not updated */ + } + else { /* write from curr. location of ind. file pointer */ + if (fd->fp_sys_posn != fd->fp_ind) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + pvfs_lseek64(fd->fd_sys, fd->fp_ind, 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_write_a, 0, NULL ); +#endif + err = pvfs_write(fd->fd_sys, buf, len); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err > 0) + 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 + + 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_PVFS_WriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ +/* Since PVFS does not support file locking, can't do buffered writes + as on Unix */ + +/* 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 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; + MPI_Count filetype_size, etype_size, buftype_size; + MPI_Aint filetype_extent, buftype_extent, indx; + int buf_count, buftype_is_contig, filetype_is_contig; + ADIO_Offset off, disp; + int flag, new_bwr_size, new_fwr_size, err_flag=0; + static char myname[] = "ADIOI_PVFS_WRITESTRIDED"; + +#ifdef HAVE_PVFS_LISTIO + if ( fd->hints->fs_hints.pvfs.listio_write == ADIOI_HINT_ENABLE ) { + ADIOI_PVFS_WriteStridedListIO(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + return; + } +#endif + /* if hint set to DISABLE or AUTOMATIC, don't use listio */ + + /* --BEGIN ERROR HANDLING-- */ + if (fd->atomicity) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_INTERN, + "Atomic mode set in PVFS I/O function", 0); + return; + } + /* --END ERROR HANDLING-- */ + + 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; + + if (!buftype_is_contig && filetype_is_contig) { + char *combine_buf, *combine_buf_ptr; + ADIO_Offset combine_buf_remain; +/* noncontiguous in memory, contiguous in file. use writev */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + /* allocate our "combine buffer" to pack data into before writing */ + combine_buf = (char *) ADIOI_Malloc(fd->hints->ind_wr_buffer_size); + combine_buf_ptr = combine_buf; + combine_buf_remain = fd->hints->ind_wr_buffer_size; + + /* seek to the right spot in the file */ + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + etype_size * offset; +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + pvfs_lseek64(fd->fd_sys, off, SEEK_SET); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + } + else { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + off = pvfs_lseek64(fd->fd_sys, fd->fp_ind, SEEK_SET); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + } + + /* loop through all the flattened pieces. combine into buffer until + * no more will fit, then write. + * + * special case of a given piece being bigger than the combine buffer + * is also handled. + */ + for (j=0; jcount; i++) { + if (flat_buf->blocklens[i] > combine_buf_remain && combine_buf != combine_buf_ptr) { + /* there is data in the buffer; write out the buffer so far */ +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + err = pvfs_write(fd->fd_sys, + combine_buf, + fd->hints->ind_wr_buffer_size - combine_buf_remain); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; + + /* reset our buffer info */ + combine_buf_ptr = combine_buf; + combine_buf_remain = fd->hints->ind_wr_buffer_size; + } + + /* TODO: heuristic for when to not bother to use combine buffer? */ + if (flat_buf->blocklens[i] >= combine_buf_remain) { + /* special case: blocklen is as big as or bigger than the combine buf; + * write directly + */ +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + err = pvfs_write(fd->fd_sys, + ((char *) buf) + j*buftype_extent + flat_buf->indices[i], + flat_buf->blocklens[i]); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; + off += flat_buf->blocklens[i]; /* keep up with the final file offset too */ + } + else { + /* copy more data into combine buffer */ + memcpy(combine_buf_ptr, + ((char *) buf) + j*buftype_extent + flat_buf->indices[i], + flat_buf->blocklens[i]); + combine_buf_ptr += flat_buf->blocklens[i]; + combine_buf_remain -= flat_buf->blocklens[i]; + off += flat_buf->blocklens[i]; /* keep up with the final file offset too */ + } + } + } + + if (combine_buf_ptr != combine_buf) { + /* data left in buffer to write */ +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + err = pvfs_write(fd->fd_sys, + combine_buf, + fd->hints->ind_wr_buffer_size - combine_buf_remain); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; + } + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; + + ADIOI_Free(combine_buf); + + 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; + } /* if (!buftype_is_contig && filetype_is_contig) ... */ + + else { /* noncontiguous in file */ + +/* split up into several contiguous writes */ + +/* find starting location in the 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; icount; i++) { + if (disp + flat_file->indices[i] + + (ADIO_Offset) n_filetypes*filetype_extent + flat_file->blocklens[i] + >= offset) { + st_index = i; + fwr_size = 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; icount; 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; + } + + 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; + fwr_size = ADIOI_MIN(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 */ +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + pvfs_lseek64(fd->fd_sys, 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_write_a, 0, NULL ); +#endif + err = pvfs_write(fd->fd_sys, ((char *) buf) + i, fwr_size); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; + } + 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 { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + k = num = buf_count = 0; + indx = flat_buf->indices[0]; + j = st_index; + off = offset; + bwr_size = flat_buf->blocklens[0]; + + while (num < bufsize) { + size = ADIOI_MIN(fwr_size, bwr_size); + if (size) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + pvfs_lseek64(fd->fd_sys, 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_write_a, 0, NULL ); +#endif + err = pvfs_write(fd->fd_sys, ((char *) buf) + indx, size); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; + } + + new_fwr_size = fwr_size; + new_bwr_size = bwr_size; + + if (size == fwr_size) { +/* reached end of contiguous block in file */ + if (j < (flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + + off = disp + flat_file->indices[j] + + (ADIO_Offset) n_filetypes*filetype_extent; + + new_fwr_size = flat_file->blocklens[j]; + if (size != bwr_size) { + indx += size; + new_bwr_size -= size; + } + } + + if (size == bwr_size) { +/* reached end of contiguous block in memory */ + + k = (k + 1)%flat_buf->count; + buf_count++; + indx = buftype_extent*(buf_count/flat_buf->count) + + flat_buf->indices[k]; + new_bwr_size = flat_buf->blocklens[k]; + if (size != fwr_size) { + off += size; + new_fwr_size -= size; + } + } + num += size; + fwr_size = new_fwr_size; + bwr_size = new_bwr_size; + } + } + + 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; + } + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} + +#ifdef HAVE_PVFS_LISTIO +void ADIOI_PVFS_WriteStridedListIO(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ +/* Since PVFS does not support file locking, can't do buffered writes + as on Unix */ + +/* 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 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; + 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, disp, start_off; + int flag, st_fwr_size, st_n_filetypes; + int new_bwr_size, new_fwr_size, err_flag=0; + + int mem_list_count, file_list_count; + char ** mem_offsets; + int64_t *file_offsets; + int *mem_lengths; + int32_t *file_lengths; + int total_blks_to_write; + + int max_mem_list, max_file_list; + + int b_blks_wrote; + int f_data_wrote; + int size_wrote=0, n_write_lists, extra_blks; + + int end_bwr_size, end_fwr_size; + int start_k, start_j, new_file_write, new_buffer_write; + int start_mem_offset; +#define MAX_ARRAY_SIZE 1024 + static char myname[] = "ADIOI_PVFS_WRITESTRIDED"; + +/* PFS file pointer modes are not relevant here, because PFS does + not support strided accesses. */ + + /* --BEGIN ERROR HANDLING-- */ + if (fd->atomicity) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_INTERN, + "Atomic mode set in PVFS I/O function", 0); + return; + } + /* --END ERROR HANDLING-- */ + + 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; + + if (!buftype_is_contig && filetype_is_contig) { + +/* noncontiguous in memory, contiguous in file. */ + int64_t file_offsets; + int32_t file_lengths; + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + etype_size * offset; +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + pvfs_lseek64(fd->fd_sys, fd->fp_ind, SEEK_SET); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + } + else { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + off = pvfs_lseek64(fd->fd_sys, fd->fp_ind, SEEK_SET); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + } + + file_list_count = 1; + file_offsets = off; + file_lengths = 0; + total_blks_to_write = count*flat_buf->count; + b_blks_wrote = 0; + + /* allocate arrays according to max usage */ + if (total_blks_to_write > MAX_ARRAY_SIZE) + mem_list_count = MAX_ARRAY_SIZE; + else mem_list_count = total_blks_to_write; + mem_offsets = (char**)ADIOI_Malloc(mem_list_count*sizeof(char*)); + mem_lengths = (int*)ADIOI_Malloc(mem_list_count*sizeof(int)); + + j = 0; + /* step through each block in memory, filling memory arrays */ + while (b_blks_wrote < total_blks_to_write) { + for (i=0; icount; i++) { + mem_offsets[b_blks_wrote % MAX_ARRAY_SIZE] = + ((char*)buf + j*buftype_extent + flat_buf->indices[i]); + mem_lengths[b_blks_wrote % MAX_ARRAY_SIZE] = + flat_buf->blocklens[i]; + file_lengths += flat_buf->blocklens[i]; + b_blks_wrote++; + if (!(b_blks_wrote % MAX_ARRAY_SIZE) || + (b_blks_wrote == total_blks_to_write)) { + + /* in the case of the last read list call, + adjust mem_list_count */ + if (b_blks_wrote == total_blks_to_write) { + mem_list_count = total_blks_to_write % MAX_ARRAY_SIZE; + /* in case last read list call fills max arrays */ + if (!mem_list_count) mem_list_count = MAX_ARRAY_SIZE; + } + + pvfs_write_list(fd->fd_sys ,mem_list_count, mem_offsets, + mem_lengths, file_list_count, + &file_offsets, &file_lengths); + + /* in the case of the last read list call, leave here */ + if (b_blks_wrote == total_blks_to_write) break; + + file_offsets += file_lengths; + file_lengths = 0; + } + } /* for (i=0; icount; i++) */ + j++; + } /* while (b_blks_wrote < total_blks_to_write) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + + 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; + + fd->fp_sys_posn = -1; /* clear this. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + ADIOI_Delete_flattened(datatype); + return; + } /* if (!buftype_is_contig && filetype_is_contig) */ + + /* already know that file is noncontiguous from above */ + /* 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; + + /* for each case - ADIO_Individual pointer or explicit, find offset + (file offset in bytes), n_filetypes (how many filetypes into file + to start), fwr_size (remaining amount of data in present file + block), and st_index (start point in terms of blocks in starting + filetype) */ + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; /* in bytes */ + n_filetypes = -1; + flag = 0; + while (!flag) { + n_filetypes++; + for (i=0; icount; i++) { + if (disp + flat_file->indices[i] + + (ADIO_Offset) n_filetypes*filetype_extent + + flat_file->blocklens[i] >= offset) { + st_index = i; + fwr_size = disp + flat_file->indices[i] + + (ADIO_Offset) n_filetypes*filetype_extent + + flat_file->blocklens[i] - offset; + flag = 1; + break; + } + } + } /* while (!flag) */ + } /* if (file_ptr_type == ADIO_INDIVIDUAL) */ + 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; icount; 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; + } /* else [file_ptr_type != ADIO_INDIVIDUAL] */ + + start_off = offset; + st_fwr_size = fwr_size; + st_n_filetypes = n_filetypes; + + if (buftype_is_contig && !filetype_is_contig) { + +/* contiguous in memory, noncontiguous in file. should be the most + common case. */ + + int mem_lengths; + char *mem_offsets; + + i = 0; + j = st_index; + off = offset; + n_filetypes = st_n_filetypes; + + mem_list_count = 1; + + /* determine how many blocks in file to read */ + f_data_wrote = ADIOI_MIN(st_fwr_size, bufsize); + total_blks_to_write = 1; + j++; + while (f_data_wrote < bufsize) { + f_data_wrote += flat_file->blocklens[j]; + total_blks_to_write++; + if (j<(flat_file->count-1)) j++; + else j = 0; + } + + j = st_index; + n_filetypes = st_n_filetypes; + n_write_lists = total_blks_to_write/MAX_ARRAY_SIZE; + extra_blks = total_blks_to_write%MAX_ARRAY_SIZE; + + mem_offsets = buf; + mem_lengths = 0; + + /* if at least one full readlist, allocate file arrays + at max array size and don't free until very end */ + if (n_write_lists) { + file_offsets = (int64_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int64_t)); + file_lengths = (int32_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int32_t)); + } + /* if there's no full readlist allocate file arrays according + to needed size (extra_blks) */ + else { + file_offsets = (int64_t*)ADIOI_Malloc(extra_blks* + sizeof(int64_t)); + file_lengths = (int32_t*)ADIOI_Malloc(extra_blks* + sizeof(int32_t)); + } + + /* for file arrays that are of MAX_ARRAY_SIZE, build arrays */ + for (i=0; iindices[j]; + file_lengths[k] = flat_file->blocklens[j]; + mem_lengths += file_lengths[k]; + } + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kfd_sys, mem_list_count, + &mem_offsets, &mem_lengths, + file_list_count, file_offsets, + file_lengths); + mem_offsets += mem_lengths; + mem_lengths = 0; + } /* for (i=0; iindices[j]; + if (k == (extra_blks - 1)) { + file_lengths[k] = bufsize - (int32_t) mem_lengths + - (int32_t) mem_offsets + (int32_t) buf; + } + else file_lengths[k] = flat_file->blocklens[j]; + } /* if(i || k) */ + mem_lengths += file_lengths[k]; + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kfd_sys, mem_list_count, &mem_offsets, + &mem_lengths, file_list_count, file_offsets, + file_lengths); + } + } + else { + /* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + size_wrote = 0; + n_filetypes = st_n_filetypes; + fwr_size = st_fwr_size; + bwr_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + max_mem_list = 0; + max_file_list = 0; + + /* run through and file max_file_list and max_mem_list so that you + can allocate the file and memory arrays less than MAX_ARRAY_SIZE + if possible */ + + while (size_wrote < bufsize) { + k = start_k; + new_buffer_write = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data read and data to be + read in the next immediate read list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k] + + size_wrote) > bufsize) { + end_bwr_size = new_buffer_write + + flat_buf->blocklens[k] - (bufsize - size_wrote); + new_buffer_write = bufsize - size_wrote; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + else new_buffer_write = bwr_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + j = start_j; + new_file_write = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_write < new_buffer_write)) { + if(file_list_count) { + if((new_file_write + flat_file->blocklens[j]) > + new_buffer_write) { + end_fwr_size = new_buffer_write - new_file_write; + new_file_write = new_buffer_write; + j--; + } + else { + new_file_write += flat_file->blocklens[j]; + end_fwr_size = flat_file->blocklens[j]; + } + } + else { + if (fwr_size > new_buffer_write) { + new_file_write = new_buffer_write; + fwr_size = new_file_write; + } + else new_file_write = fwr_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_write = 0; + mem_list_count = 0; + while (new_buffer_write < new_file_write) { + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k]) > + new_file_write) { + end_bwr_size = new_file_write - + new_buffer_write; + new_buffer_write = new_file_write; + k--; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_write = bwr_size; + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_write < new_file_write) */ + } /* if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + + /* fakes filling the writelist arrays of lengths found above */ + k = start_k; + j = start_j; + for (i=0; iblocklens[k] == end_bwr_size) + bwr_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + bwr_size = flat_buf->blocklens[k] - end_bwr_size; + k--; + buf_count--; + } + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iblocklens[j] == end_fwr_size) + fwr_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + fwr_size = flat_file->blocklens[j] - end_fwr_size; + j--; + } + } + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; iblocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + + /* this section calculates mem_list_count and file_list_count + and also finds the possibly odd sized last array elements + in new_fwr_size and new_bwr_size */ + + while (size_wrote < bufsize) { + k = start_k; + new_buffer_write = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data read and data to be + read in the next immediate read list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k] + + size_wrote) > bufsize) { + end_bwr_size = new_buffer_write + + flat_buf->blocklens[k] - (bufsize - size_wrote); + new_buffer_write = bufsize - size_wrote; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + else new_buffer_write = bwr_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + j = start_j; + new_file_write = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_write < new_buffer_write)) { + if(file_list_count) { + if((new_file_write + flat_file->blocklens[j]) > + new_buffer_write) { + end_fwr_size = new_buffer_write - new_file_write; + new_file_write = new_buffer_write; + j--; + } + else { + new_file_write += flat_file->blocklens[j]; + end_fwr_size = flat_file->blocklens[j]; + } + } + else { + if (fwr_size > new_buffer_write) { + new_file_write = new_buffer_write; + fwr_size = new_file_write; + } + else new_file_write = fwr_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_write = 0; + mem_list_count = 0; + while (new_buffer_write < new_file_write) { + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k]) > + new_file_write) { + end_bwr_size = new_file_write - + new_buffer_write; + new_buffer_write = new_file_write; + k--; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_write = bwr_size; + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_write < new_file_write) */ + } /* if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + + /* fills the allocated readlist arrays */ + k = start_k; + j = start_j; + for (i=0; icount) + + (int)flat_buf->indices[k]); + + if(!i) { + mem_lengths[0] = bwr_size; + mem_offsets[0] += flat_buf->blocklens[k] - bwr_size; + } + else { + if (i == (mem_list_count - 1)) { + mem_lengths[i] = end_bwr_size; + if (flat_buf->blocklens[k] == end_bwr_size) + bwr_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + bwr_size = flat_buf->blocklens[k] - end_bwr_size; + k--; + buf_count--; + } + } + else { + mem_lengths[i] = flat_buf->blocklens[k]; + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iindices[j] + n_filetypes * + filetype_extent; + if (!i) { + file_lengths[0] = fwr_size; + file_offsets[0] += flat_file->blocklens[j] - fwr_size; + } + else { + if (i == (file_list_count - 1)) { + file_lengths[i] = end_fwr_size; + if (flat_file->blocklens[j] == end_fwr_size) + fwr_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + fwr_size = flat_file->blocklens[j] - end_fwr_size; + j--; + } + } + else file_lengths[i] = flat_file->blocklens[j]; + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; ifd_sys,mem_list_count, mem_offsets, + mem_lengths, file_list_count, file_offsets, + file_lengths); + size_wrote += new_buffer_write; + start_k = k; + start_j = j; + } /* while (size_wrote < bufsize) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + } + ADIOI_Free(file_offsets); + ADIOI_Free(file_lengths); + + 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; + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} +#endif /* HAVE_PVFS_LISTIO */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/Makefile.mk new file mode 100644 index 0000000000..4ee9d0fd36 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/Makefile.mk @@ -0,0 +1,34 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_PVFS2 + +noinst_HEADERS += adio/ad_pvfs2/ad_pvfs2.h \ + adio/ad_pvfs2/ad_pvfs2_io.h \ + adio/ad_pvfs2/ad_pvfs2_common.h + +romio_other_sources += \ + adio/ad_pvfs2/ad_pvfs2_close.c \ + adio/ad_pvfs2/ad_pvfs2_read.c \ + adio/ad_pvfs2/ad_pvfs2_open.c \ + adio/ad_pvfs2/ad_pvfs2_write.c \ + adio/ad_pvfs2/ad_pvfs2_fcntl.c \ + adio/ad_pvfs2/ad_pvfs2_flush.c \ + adio/ad_pvfs2/ad_pvfs2_resize.c \ + adio/ad_pvfs2/ad_pvfs2_hints.c \ + adio/ad_pvfs2/ad_pvfs2_delete.c \ + adio/ad_pvfs2/ad_pvfs2.c \ + adio/ad_pvfs2/ad_pvfs2_common.c \ + adio/ad_pvfs2/ad_pvfs2_aio.c \ + adio/ad_pvfs2/ad_pvfs2_read_list_classic.c \ + adio/ad_pvfs2/ad_pvfs2_io_list.c \ + adio/ad_pvfs2/ad_pvfs2_io_dtype.c \ + adio/ad_pvfs2/ad_pvfs2_write_list_classic.c \ + adio/ad_pvfs2/ad_pvfs2_features.c + +endif BUILD_AD_PVFS2 + diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2.c new file mode 100644 index 0000000000..a55c3c8925 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2.c @@ -0,0 +1,47 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs2.h" + +#include "adio.h" + +struct ADIOI_Fns_struct ADIO_PVFS2_operations = { + ADIOI_PVFS2_Open, /* Open */ + ADIOI_SCALEABLE_OpenColl, /* OpenColl */ + ADIOI_PVFS2_ReadContig, /* ReadContig */ + ADIOI_PVFS2_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_PVFS2_Fcntl, /* Fcntl */ + ADIOI_PVFS2_SetInfo, /* SetInfo */ + ADIOI_PVFS2_ReadStrided, /* ReadStrided */ + ADIOI_PVFS2_WriteStrided, /* WriteStrided */ + ADIOI_PVFS2_Close, /* Close */ +#ifdef HAVE_MPI_GREQUEST_EXTENSIONS + ADIOI_PVFS2_IReadContig, /* IreadContig */ + ADIOI_PVFS2_IWriteContig, /* IwriteContig */ +#else + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ +#endif + ADIOI_FAKE_IODone, /* ReadDone */ + ADIOI_FAKE_IODone, /* WriteDone */ + ADIOI_FAKE_IOComplete, /* ReadComplete */ + ADIOI_FAKE_IOComplete, /* WriteComplete */ + ADIOI_FAKE_IreadStrided, /* IreadStrided */ + ADIOI_FAKE_IwriteStrided, /* IwriteStrided */ + ADIOI_PVFS2_Flush, /* Flush */ + ADIOI_PVFS2_Resize, /* Resize */ + ADIOI_PVFS2_Delete, /* Delete */ + ADIOI_PVFS2_Feature, + "PVFS2: the PVFS v2 or OrangeFS file systems" +}; + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2.h b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2.h new file mode 100644 index 0000000000..95c5912376 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2.h @@ -0,0 +1,76 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_PVFS2_INCLUDE +#define AD_PVFS2_INCLUDE + +#include "adio.h" +#ifdef HAVE_PVFS2_H +#include "pvfs2.h" +#endif + +#ifdef PVFS2_VERSION_MAJOR +#include "pvfs2-compat.h" +#endif + +void ADIOI_PVFS2_Open(ADIO_File fd, int *error_code); +void ADIOI_PVFS2_Close(ADIO_File fd, int *error_code); +void ADIOI_PVFS2_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PVFS2_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); +void ADIOI_PVFS2_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIOI_PVFS2_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); +void ADIOI_PVFS2_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PVFS2_Flush(ADIO_File fd, int *error_code); +void ADIOI_PVFS2_Delete(const char *filename, int *error_code); +void ADIOI_PVFS2_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +void ADIOI_PVFS2_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); +int ADIOI_PVFS2_Feature(ADIO_File fd, int flag); + +void ADIOI_PVFS2_IReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Request *request, + int *error_code); +void ADIOI_PVFS2_IWriteContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Request *request, + int *error_code); +void ADIOI_PVFS2_AIO_contig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Request *request, + int flag, int *error_code); +void ADIOI_PVFS2_OldWriteStrided(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_PVFS2_OldReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); + +int ADIOI_PVFS2_WriteStridedListIO(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 ADIOI_PVFS2_WriteStridedDtypeIO(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_aio.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_aio.c new file mode 100644 index 0000000000..88be6f1eaf --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_aio.c @@ -0,0 +1,220 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "ad_pvfs2.h" +#include + +#include "ad_pvfs2_common.h" +#include "mpiu_greq.h" +#include "../../mpi-io/mpioimpl.h" + +#define READ 0 +#define WRITE 1 + +static int ADIOI_PVFS2_greq_class = 0; +int ADIOI_PVFS2_aio_free_fn(void *extra_state); +int ADIOI_PVFS2_aio_poll_fn(void *extra_state, MPI_Status *status); +int ADIOI_PVFS2_aio_wait_fn(int count, void ** array_of_states, + double timeout, MPI_Status *status); + +void ADIOI_PVFS2_IReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Request *request, + int *error_code) +{ + ADIOI_PVFS2_AIO_contig(fd, buf, count, datatype, file_ptr_type, + offset, request, READ, error_code); +} + +void ADIOI_PVFS2_IWriteContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Request *request, + int *error_code) +{ + ADIOI_PVFS2_AIO_contig(fd, (void *)buf, count, datatype, file_ptr_type, + offset, request, WRITE, error_code); +} + +void ADIOI_PVFS2_AIO_contig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Request *request, + int flag, int *error_code) +{ + + int ret; + MPI_Count datatype_size, len; + ADIOI_PVFS2_fs *pvfs_fs; + ADIOI_AIO_Request *aio_req; + static char myname[] = "ADIOI_PVFS2_AIO_contig"; + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + aio_req = (ADIOI_AIO_Request*)ADIOI_Calloc(sizeof(ADIOI_AIO_Request), 1); + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + ret = PVFS_Request_contiguous(len, PVFS_BYTE, &(aio_req->mem_req)); + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in pvfs_request_contig (memory)", 0); + return; + } + /* --END ERROR HANDLING-- */ + + ret = PVFS_Request_contiguous(len, PVFS_BYTE, &(aio_req->file_req)); + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in pvfs_request_contig (file)", 0); + return; + } + /* --END ERROR HANDLING-- */ + + if (file_ptr_type == ADIO_INDIVIDUAL) { + /* copy individual file pointer into offset variable, continue */ + offset = fd->fp_ind; + } + if (flag == READ) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_iread_a, 0, NULL ); +#endif + ret = PVFS_isys_read(pvfs_fs->object_ref, aio_req->file_req, offset, + buf, aio_req->mem_req, &(pvfs_fs->credentials), + &(aio_req->resp_io), &(aio_req->op_id), NULL); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_iread_b, 0, NULL ); +#endif + } else if (flag == WRITE) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_iwrite_a, 0, NULL ); +#endif + ret = PVFS_isys_write(pvfs_fs->object_ref, aio_req->file_req, offset, + buf, aio_req->mem_req, &(pvfs_fs->credentials), + &(aio_req->resp_io), &(aio_req->op_id), NULL); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_iwrite_b, 0, NULL ); +#endif + } + + /* --BEGIN ERROR HANDLING-- */ + if (ret < 0 ) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_isys_io", 0); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + /* posted. defered completion */ + if (ret == 0) { + if (ADIOI_PVFS2_greq_class == 0) { + MPIX_Grequest_class_create(ADIOI_GEN_aio_query_fn, + ADIOI_PVFS2_aio_free_fn, MPIU_Greq_cancel_fn, + ADIOI_PVFS2_aio_poll_fn, ADIOI_PVFS2_aio_wait_fn, + &ADIOI_PVFS2_greq_class); + } + MPIX_Grequest_class_allocate(ADIOI_PVFS2_greq_class, aio_req, request); + memcpy(&(aio_req->req), request, sizeof(*request)); + } + + /* immediate completion */ + if (ret == 1) { + MPIO_Completed_request_create(&fd, len, error_code, request); + } + + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind += len; + } + fd->fp_sys_posn = offset + len; + + *error_code = MPI_SUCCESS; +fn_exit: + return; +} + +int ADIOI_PVFS2_aio_free_fn(void *extra_state) +{ + ADIOI_AIO_Request *aio_req; + aio_req = (ADIOI_AIO_Request*)extra_state; + + PVFS_Request_free(&(aio_req->mem_req)); + PVFS_Request_free(&(aio_req->file_req)); + ADIOI_Free(aio_req); + + return MPI_SUCCESS; +} + +int ADIOI_PVFS2_aio_poll_fn(void *extra_state, MPI_Status *status) +{ + ADIOI_AIO_Request *aio_req; + int ret, error; + + aio_req = (ADIOI_AIO_Request *)extra_state; + + /* BUG: cannot PVFS_sys_testsome: does not work for a specific request */ + ret = PVFS_sys_wait(aio_req->op_id, "ADIOI_PVFS2_aio_poll_fn", &error); + if (ret == 0) { + aio_req->nbytes = aio_req->resp_io.total_completed; + MPI_Grequest_complete(aio_req->req); + return MPI_SUCCESS; + } else + return MPI_UNDEFINED; /* TODO: what's this error? */ +} + +/* wait for multiple requests to complete */ +int ADIOI_PVFS2_aio_wait_fn(int count, void ** array_of_states, + double timeout, MPI_Status *status) +{ + + ADIOI_AIO_Request **aio_reqlist; + PVFS_sys_op_id *op_id_array; + int i,j, greq_count, completed_count=0; + int *error_array; + + aio_reqlist = (ADIOI_AIO_Request **)array_of_states; + + op_id_array = (PVFS_sys_op_id*)ADIOI_Calloc(count, sizeof(PVFS_sys_op_id)); + error_array = (int *)ADIOI_Calloc(count, sizeof(int)); + greq_count = count; + + + /* PVFS-2.6: testsome actually tests all requests and fills in op_id_array + * with the ones that have completed. count is an in/out parameter. + * returns with the number of completed operations. what a mess! */ + while (completed_count < greq_count ) { + count = greq_count; + PVFS_sys_testsome(op_id_array, &count, NULL, error_array, INT_MAX); + completed_count += count; + for (i=0; i< count; i++) { + for (j=0; jop_id) { + aio_reqlist[j]->nbytes = + aio_reqlist[j]->resp_io.total_completed; + MPI_Grequest_complete(aio_reqlist[j]->req); + } + } + } + } + return MPI_SUCCESS; /* TODO: no idea how to deal with errors */ +} + + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_close.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_close.c new file mode 100644 index 0000000000..847dd8341c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_close.c @@ -0,0 +1,28 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs2.h" + +void ADIOI_PVFS2_Close(ADIO_File fd, int *error_code) +{ + ADIOI_Free(fd->fs_ptr); + fd->fs_ptr = NULL; + /* PVFS2 doesn't have a 'close', but MPI-IO semantics dictate that we + * ensure all data has been flushed. + */ + + /* At some point or another it was decided that ROMIO would not + * explicitly flush (other than any local cache) on close, because + * there is no way to *avoid* that overhead if you implement it here + * and don't actually want it. + */ + + *error_code = MPI_SUCCESS; +} +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_common.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_common.c new file mode 100644 index 0000000000..ccd3c1916c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_common.c @@ -0,0 +1,150 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2003 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs2.h" +#include "ad_pvfs2_common.h" +#include +#include +#include +#include + +/* maybe give romio access to the globalconfig struct */ +/* keyval hack to both tell us if we've already initialized pvfs2 and also + * close it down when mpi exits */ +int ADIOI_PVFS2_Initialized = MPI_KEYVAL_INVALID; + +void ADIOI_PVFS2_End(int *error_code) +{ + int ret; + static char myname[] = "ADIOI_PVFS2_END"; + + ret = PVFS_sys_finalize(); + + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0 ) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_finalize", 0); + return; + } + /* --END ERROR HANDLING-- */ + + *error_code = MPI_SUCCESS; +} + +int ADIOI_PVFS2_End_call(MPI_Comm comm, int keyval, + void *attribute_val, void *extra_state) +{ + int error_code; + ADIOI_PVFS2_End(&error_code); + MPI_Keyval_free(&keyval); + return error_code; +} + +void ADIOI_PVFS2_Init(int *error_code ) +{ + int ret; + static char myname[] = "ADIOI_PVFS2_INIT"; + char * ncache_timeout; + + /* do nothing if we've already fired up the pvfs2 interface */ + if (ADIOI_PVFS2_Initialized != MPI_KEYVAL_INVALID) { + *error_code = MPI_SUCCESS; + return; + } + + /* for consistency, we should disable the pvfs2 ncache. If the + * environtment variable is already set, assume a user knows it + * won't be a problem */ + ncache_timeout = getenv("PVFS2_NCACHE_TIMEOUT"); + if (ncache_timeout == NULL ) + setenv("PVFS2_NCACHE_TIMEOUT", "0", 1); + + ret = PVFS_util_init_defaults(); + if (ret < 0 ) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_util_init_defaults", + 0); + PVFS_perror("PVFS_util_init_defaults", ret); + + return; + } + + MPI_Keyval_create(MPI_NULL_COPY_FN, ADIOI_PVFS2_End_call, + &ADIOI_PVFS2_Initialized, (void *)0); + /* just like romio does, we make a dummy attribute so we + * get cleaned up */ + MPI_Attr_put(MPI_COMM_SELF, ADIOI_PVFS2_Initialized, (void *)0); +} + +void ADIOI_PVFS2_makeattribs(PVFS_sys_attr * attribs) +{ + memset(attribs, 0, sizeof(PVFS_sys_attr)); + + attribs->owner = geteuid(); + attribs->group = getegid(); + attribs->perms = 0644; + attribs->mask = PVFS_ATTR_SYS_ALL_SETABLE; + attribs->atime = time(NULL); + attribs->mtime = attribs->atime; + attribs->ctime = attribs->atime; +} + + +void ADIOI_PVFS2_makecredentials(PVFS_credentials * credentials) +{ + memset(credentials, 0, sizeof(PVFS_credentials)); + + PVFS_util_gen_credentials(credentials); +} + +int ADIOI_PVFS2_error_convert(int pvfs_error) +{ + switch(pvfs_error) + { + case PVFS_EPERM: + case PVFS_EACCES: + return MPI_ERR_ACCESS; + case PVFS_ENOENT: + case PVFS_ENXIO: + case PVFS_ENODEV: + return MPI_ERR_NO_SUCH_FILE; + case PVFS_EIO: + return MPI_ERR_IO; + case PVFS_EEXIST: + return MPI_ERR_FILE_EXISTS; + case PVFS_ENOTDIR: /* ??? */ + case PVFS_EISDIR: /* ??? */ + case PVFS_ENAMETOOLONG: + return MPI_ERR_BAD_FILE; + case PVFS_EINVAL: + return MPI_ERR_FILE; + case PVFS_EFBIG: /* ??? */ + case PVFS_ENOSPC: + return MPI_ERR_NO_SPACE; + case PVFS_EROFS: + return MPI_ERR_READ_ONLY; + case PVFS_ENOSYS: + return MPI_ERR_UNSUPPORTED_OPERATION; + /* PVFS does not support quotas */ + case EDQUOT: + return MPI_ERR_QUOTA; + case PVFS_ENOMEM: + return MPI_ERR_INTERN; + default: + return MPI_UNDEFINED; + } + +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_common.h b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_common.h new file mode 100644 index 0000000000..f63f84a27b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_common.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef _AD_PVFS2_COMMON_H +#define _AD_PVFS2_COMMON_H +#include "ad_pvfs2.h" + +/* useful values: + * 0: no debugging + * CLIENT_DEBUG: debug client state machines + */ +#define ADIOI_PVFS2_DEBUG_MASK 0 + + +struct ADIOI_PVFS2_fs_s { + PVFS_object_ref object_ref; + PVFS_credentials credentials; +} ADIOI_PVFS2_fs_s; + +typedef struct ADIOI_PVFS2_fs_s ADIOI_PVFS2_fs; + + +void ADIOI_PVFS2_Init(int *error_code ); +void ADIOI_PVFS2_makeattribs(PVFS_sys_attr * attribs); +void ADIOI_PVFS2_makecredentials(PVFS_credentials * credentials); +void ADIOI_PVFS2_End(int *error_code); +int ADIOI_PVFS2_End_call(MPI_Comm comm, int keyval, + void *attribute_val, void *extra_state); +int ADIOI_PVFS2_error_convert(int pvfs_error); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_delete.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_delete.c new file mode 100644 index 0000000000..f5770bb393 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_delete.c @@ -0,0 +1,69 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs2.h" +#include "adio.h" + +#include "ad_pvfs2_common.h" + +void ADIOI_PVFS2_Delete(const char *filename, int *error_code) +{ + PVFS_credentials credentials; + PVFS_sysresp_getparent resp_getparent; + int ret; + PVFS_fs_id cur_fs; + static char myname[] = "ADIOI_PVFS2_DELETE"; + char pvfs_path[PVFS_NAME_MAX] = {0}; + + ADIOI_PVFS2_Init(error_code); + /* --BEGIN ERROR HANDLING-- */ + if (*error_code != MPI_SUCCESS) + { + /* ADIOI_PVFS2_INIT handles creating error codes itself */ + return; + } + /* --END ERROR HANDLING-- */ + + /* in most cases we'll store the credentials in the fs struct, but we don't + * have one of those in Delete */ + ADIOI_PVFS2_makecredentials(&credentials); + + /* given the filename, figure out which pvfs filesystem it is on */ + ret = PVFS_util_resolve(filename, &cur_fs, pvfs_path, PVFS_NAME_MAX); + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_util_resolve", 0); + return; + } + /* --END ERROR HANDLING-- */ + + ret = PVFS_sys_getparent(cur_fs, pvfs_path, &credentials, &resp_getparent); + + ret = PVFS_sys_remove(resp_getparent.basename, + resp_getparent.parent_ref, &credentials); + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_remove", 0); + return; + } + /* --END ERROR HANDLING-- */ + + *error_code = MPI_SUCCESS; + return; +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_fcntl.c new file mode 100644 index 0000000000..e07291f757 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_fcntl.c @@ -0,0 +1,59 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs2.h" +#include "adio_extern.h" +#include "ad_pvfs2_common.h" + +void ADIOI_PVFS2_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code) +{ + int ret; + ADIOI_PVFS2_fs *pvfs_fs; + PVFS_sysresp_getattr resp_getattr; + static char myname[] = "ADIOI_PVFS2_FCNTL"; + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + ret = PVFS_sys_getattr(pvfs_fs->object_ref, PVFS_ATTR_SYS_SIZE, + &(pvfs_fs->credentials), &resp_getattr); + if (ret != 0 ) { + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_getattr", 0); + /* --END ERROR HANDLING-- */ + } + else { + *error_code = MPI_SUCCESS; + } + fcntl_struct->fsize = resp_getattr.attr.size; + return; + + case ADIO_FCNTL_SET_DISKSPACE: + ADIOI_GEN_Prealloc(fd, fcntl_struct->diskspace, error_code); + break; + + /* --BEGIN ERROR HANDLING-- */ + case ADIO_FCNTL_SET_ATOMICITY: + default: + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**flag", "**flag %d", flag); + /* --END ERROR HANDLING-- */ + } +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_features.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_features.c new file mode 100644 index 0000000000..89a82c129f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_features.c @@ -0,0 +1,23 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "adio.h" +#include "ad_pvfs2.h" + +int ADIOI_PVFS2_Feature(ADIO_File fd, int flag) +{ + switch(flag) { + case ADIO_SCALABLE_OPEN: + case ADIO_SCALABLE_RESIZE: + return 1; + case ADIO_SHARED_FP: + case ADIO_LOCKS: + case ADIO_SEQUENTIAL: + case ADIO_DATA_SIEVING_WRITES: + default: + return 0; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_flush.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_flush.c new file mode 100644 index 0000000000..18061084a8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_flush.c @@ -0,0 +1,55 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs2.h" +#include "ad_pvfs2_common.h" + +/* we want to be a bit clever here: at scale, if every client sends a + * flush request, it will stress the PVFS2 servers with redundant + * PVFS_sys_flush requests. Instead, one process should wait for + * everyone to catch up, do the sync, then broadcast the result. We can + * get away with this thanks to PVFS2's stateless design + */ + +void ADIOI_PVFS2_Flush(ADIO_File fd, int *error_code) +{ + int ret, rank, dummy=0, dummy_in=0; + ADIOI_PVFS2_fs *pvfs_fs; + static char myname[] = "ADIOI_PVFS2_FLUSH"; + + *error_code = MPI_SUCCESS; + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + MPI_Comm_rank(fd->comm, &rank); + + + /* unlike ADIOI_PVFS2_Resize, MPI_File_sync() does not perform any + * syncronization */ + MPI_Reduce(&dummy_in, &dummy, 1, MPI_INT, MPI_SUM, + fd->hints->ranklist[0], fd->comm); + + /* io_worker computed in ADIO_Open */ + if (rank == fd->hints->ranklist[0]) { + ret = PVFS_sys_flush(pvfs_fs->object_ref, &(pvfs_fs->credentials)); + } + MPI_Bcast(&ret, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_flush", 0); + } + /* --END ERROR HANDLING-- */ +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_hints.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_hints.c new file mode 100644 index 0000000000..47522064e3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_hints.c @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include +#include "ad_pvfs2.h" + +#include "hint_fns.h" + +void ADIOI_PVFS2_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ + char *value; + int flag, tmp_value; + static char myname[] = "ADIOI_PVFS_SETINFO"; + + if ((fd->info) == MPI_INFO_NULL) { + /* part of the open call */ + MPI_Info_create(&(fd->info)); + ADIOI_Info_set(fd->info, "romio_pvfs2_debugmask", "0"); + fd->hints->fs_hints.pvfs2.debugmask = 0; + + ADIOI_Info_set(fd->info, "striping_factor", "0"); + fd->hints->striping_factor = 0; + + ADIOI_Info_set(fd->info, "striping_unit", "0"); + fd->hints->striping_unit = 0; + + /* disable the aggressive strided optimizations by default */ + ADIOI_Info_set(fd->info, "romio_pvfs2_posix_read", "disable"); + ADIOI_Info_set(fd->info, "romio_pvfs2_posix_write", "disable"); + fd->hints->fs_hints.pvfs2.posix_read = ADIOI_HINT_DISABLE; + fd->hints->fs_hints.pvfs2.posix_write = ADIOI_HINT_DISABLE; + + ADIOI_Info_set(fd->info, "romio_pvfs2_dtype_read", "disable"); + ADIOI_Info_set(fd->info, "romio_pvfs2_dtype_write", "disable"); + fd->hints->fs_hints.pvfs2.dtype_read = ADIOI_HINT_DISABLE; + fd->hints->fs_hints.pvfs2.dtype_write = ADIOI_HINT_DISABLE; + + ADIOI_Info_set(fd->info, "romio_pvfs2_listio_read", "disable"); + ADIOI_Info_set(fd->info, "romio_pvfs2_listio_write", "disable"); + fd->hints->fs_hints.pvfs2.listio_read = ADIOI_HINT_DISABLE; + fd->hints->fs_hints.pvfs2.listio_write = ADIOI_HINT_DISABLE; + + + /* any user-provided hints? */ + if (users_info != MPI_INFO_NULL) { + value = (char *) ADIOI_Malloc( (MPI_MAX_INFO_VAL+1)*sizeof(char)); + /* pvfs2 debugging */ + ADIOI_Info_get(users_info, "romio_pvfs2_debugmask", + MPI_MAX_INFO_VAL, value, &flag); + if (flag) { + tmp_value = fd->hints->fs_hints.pvfs2.debugmask = + PVFS_debug_eventlog_to_mask(value); + + MPI_Bcast(&tmp_value, 1, MPI_INT, 0, fd->comm); + /* --BEGIN ERROR HANDLING-- */ + if (tmp_value != fd->hints->fs_hints.pvfs2.debugmask) { + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, + "romio_pvfs2_debugmask", + error_code); + return; + } + /* --END ERROR HANDLING-- */ + + ADIOI_Info_set(fd->info, "romio_pvfs2_debugmask", value); + } + + /* the striping factor */ + ADIOI_Info_check_and_install_int(fd, users_info, "striping_factor", + &(fd->hints->striping_factor), myname, error_code); + + + /* the striping unit */ + ADIOI_Info_check_and_install_int(fd, users_info, "striping_unit", + &(fd->hints->striping_unit), myname, error_code); + + /* distribution name */ + ADIOI_Info_get(users_info, "romio_pvfs2_distribution_name", + MPI_MAX_INFO_VAL, value, &flag); + if (flag) { + } + + /* POSIX read */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_pvfs2_posix_read", + &(fd->hints->fs_hints.pvfs2.posix_read), myname, error_code); + + /* POSIX write */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_pvfs2_posix_write", + &(fd->hints->fs_hints.pvfs2.posix_write), myname, error_code); + + /* Datatype read */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_pvfs2_dtype_read", + &(fd->hints->fs_hints.pvfs2.dtype_read), myname, error_code); + + /* Datatype write */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_pvfs2_dtype_write", + &(fd->hints->fs_hints.pvfs2.dtype_write), myname, error_code); + + /* Listio read */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_pvfs2_listio_read", + &(fd->hints->fs_hints.pvfs2.listio_read), myname, error_code); + + /* Datatype write */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_pvfs2_listio_write", + &(fd->hints->fs_hints.pvfs2.listio_write), myname, error_code); + ADIOI_Free(value); + } + } + /* set the values for collective I/O and data sieving parameters */ + ADIOI_GEN_SetInfo(fd, users_info, error_code); + + *error_code = MPI_SUCCESS; +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_io.h b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_io.h new file mode 100644 index 0000000000..aefe0653ec --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_io.h @@ -0,0 +1,79 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 2006 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* Contig I/O helper prototypes */ + +#define READ 0 +#define WRITE 1 + +/* #define DEBUG_CONTIG */ +/* #define DEBUG_LIST */ +/* #define DEBUG_DTYPE */ + +/* Contig I/O helper prototypes */ +int ADIOI_PVFS2_Contig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code, int rw_type); + +/* List I/O helper prototypes */ +int ADIOI_PVFS2_StridedListIO(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code, int rw_type); + +int gen_listio_arr(ADIOI_Flatlist_node *flat_buf, + int *flat_buf_index_p, + int64_t *cur_flat_buf_reg_off_p, + int flat_buf_size, + int flat_buf_extent, + ADIOI_Flatlist_node *flat_file, + int *flat_file_index_p, + int64_t *cur_flat_file_reg_off_p, + int flat_file_size, + int flat_file_extent, + int max_ol_count, + ADIO_Offset disp, + int bytes_into_filetype, + int64_t *bytes_completed, + int64_t total_io_size, + int64_t buf_off_arr[], + int32_t buf_len_arr[], + int32_t *buf_ol_count_p, + int64_t file_off_arr[], + int32_t file_len_arr[], + int32_t *file_ol_count_p); + +void print_buf_file_ol_pairs(int64_t buf_off_arr[], + int32_t buf_len_arr[], + int32_t buf_ol_count, + int64_t file_off_arr[], + int32_t file_len_arr[], + int32_t file_ol_count, + void *buf, + int rw_type); + +/* Datatype I/O helper prototypes */ +int ADIOI_PVFS2_StridedDtypeIO(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code, int rw_type); + +int convert_named(MPI_Datatype *mpi_dtype, + PVFS_Request *pvfs_dtype, int combiner); + +void print_dtype_info(int combiner, + int num_int, + int num_addr, + int num_dtype, + int *arr_int, + MPI_Aint *arr_addr, + MPI_Datatype *arr_dtype); + +int convert_mpi_pvfs2_dtype(MPI_Datatype *mpi_dtype, + PVFS_Request *pvfs_dtype); + diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_io_dtype.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_io_dtype.c new file mode 100644 index 0000000000..09012523b8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_io_dtype.c @@ -0,0 +1,739 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 2006 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include +#include "adio.h" +#include "adio_extern.h" +#include "ad_pvfs2.h" +#include "ad_pvfs2_io.h" +#include "ad_pvfs2_common.h" + +int ADIOI_PVFS2_StridedDtypeIO(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code, + int rw_type) +{ + int ret = -1, filetype_is_contig = -1; + MPI_Count filetype_size = -1; + int num_filetypes = 0, cur_flat_file_reg_off = 0; + PVFS_Request tmp_mem_req, mem_req, tmp_file_req, file_req; + PVFS_sysresp_io resp_io; + ADIO_Offset off = -1, bytes_into_filetype = 0; + MPI_Aint filetype_extent = -1; + int i = -1; + MPI_Count etype_size; + PVFS_size pvfs_disp = -1; + ADIOI_Flatlist_node *flat_file_p = ADIOI_Flatlist; + + /* Use for offseting the PVFS2 filetype */ + int pvfs_blk = 1; + ADIOI_PVFS2_fs *pvfs_fs; + static char myname[] = "ADIOI_PVFS2_STRIDED_DTYPE"; + + memset(&tmp_mem_req, 0, sizeof(PVFS_Request)); + memset(&mem_req, 0, sizeof(PVFS_Request)); + memset(&tmp_file_req, 0, sizeof(PVFS_Request)); + memset(&file_req, 0, sizeof(PVFS_Request)); + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + /* changed below if error */ + *error_code = MPI_SUCCESS; + + /* datatype is the memory type + * fd->filetype is the file type */ + MPI_Type_size_x(fd->filetype, &filetype_size); + if (filetype_size == 0) { + *error_code = MPI_SUCCESS; + return -1; + } + MPI_Type_extent(fd->filetype, &filetype_extent); + MPI_Type_size_x(fd->etype, &etype_size); + if (filetype_size == 0) { + *error_code = MPI_SUCCESS; + return -1; + } + + /* offset is in units of etype relative to the filetype. We + * convert this to off in terms of actual data bytes (the offset + * minus the number of bytes that are not used). We are allowed + * to do this since PVFS2 handles offsets with respect to a + * file_req in bytes, otherwise we would have to convert into a + * pure byte offset as is done in other methods. Explicit offset + * case is handled by using fd->disp and byte-converted off. */ + + pvfs_disp = fd->disp; + if (file_ptr_type == ADIO_INDIVIDUAL) + { + if (filetype_is_contig) + { + off = fd->fp_ind - fd->disp; + } + else + { + int flag = 0; + /* Should have already been flattened in ADIO_Open*/ + while (flat_file_p->type != fd->filetype) + { + flat_file_p = flat_file_p->next; + } + num_filetypes = -1; + while (!flag) + { + num_filetypes++; + for (i = 0; i < flat_file_p->count; i++) + { + /* Start on a non zero-length region */ + if (flat_file_p->blocklens[i]) + { + if (fd->disp + flat_file_p->indices[i] + + (num_filetypes * filetype_extent) + + flat_file_p->blocklens[i] > fd->fp_ind && + fd->disp + flat_file_p->indices[i] <= + fd->fp_ind) + { + cur_flat_file_reg_off = fd->fp_ind - + (fd->disp + flat_file_p->indices[i] + + (num_filetypes * filetype_extent)); + flag = 1; + break; + } + else + bytes_into_filetype += flat_file_p->blocklens[i]; + } + } + } + /* Impossible that we don't find it in this datatype */ + assert(i != flat_file_p->count); + off = bytes_into_filetype + cur_flat_file_reg_off; + } + } + else /* ADIO_EXPLICIT */ + { + off = etype_size * offset; + } + +#ifdef DEBUG_DTYPE + fprintf(stderr, "ADIOI_PVFS2_StridedDtypeIO: (fd->fp_ind=%Ld,fd->disp=%Ld," + " offset=%Ld),(pvfs_disp=%Ld,off=%Ld)\n", + fd->fp_ind, fd->disp, offset, pvfs_disp, off); +#endif + + + /* Convert the MPI memory and file datatypes into + * PVFS2 datatypes */ + ret = convert_mpi_pvfs2_dtype(&datatype, &tmp_mem_req); + if (ret < 0) + { + goto error_state; + } + ret = convert_mpi_pvfs2_dtype(&(fd->filetype), &tmp_file_req); + if (ret < 0) + { + goto error_state; + } + + ret = PVFS_Request_contiguous(count, tmp_mem_req, &mem_req); + if (ret != 0) /* TODO: convert this to MPIO error handling */ + fprintf(stderr, "ADIOI_PVFS2_stridedDtypeIO: error in final" + " CONTIG memory type\n"); + PVFS_Request_free(&tmp_mem_req); + + /* pvfs_disp is used to offset the filetype */ + ret = PVFS_Request_hindexed(1, &pvfs_blk, &pvfs_disp, + tmp_file_req, &file_req); + if (ret != 0) + fprintf(stderr, "ADIOI_PVFS2_StridedDtypeIO: error in final" + " HINDEXED file type\n"); + PVFS_Request_free(&tmp_file_req); + + if (rw_type == READ) + ret = PVFS_sys_read(pvfs_fs->object_ref, file_req, off, buf, + mem_req, &(pvfs_fs->credentials), &resp_io); + else + ret = PVFS_sys_write(pvfs_fs->object_ref, file_req, off, buf, + mem_req, &(pvfs_fs->credentials), &resp_io); + + if (ret != 0) { + fprintf(stderr, "ADIOI_PVFS2_StridedDtypeIO: Warning - PVFS_sys_" + "read/write returned %d and completed %Ld bytes.\n", + ret, (long long)resp_io.total_completed); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_io \n", 0); + goto error_state; + } + + if (file_ptr_type == ADIO_INDIVIDUAL) + { + fd->fp_ind = off += resp_io.total_completed; + } + + error_state: + fd->fp_sys_posn = -1; /* set it to null. */ + + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + +#ifdef DEBUG_DTYPE + fprintf(stderr, "ADIOI_PVFS2_StridedDtypeIO: " + "resp_io.total_completed=%Ld,ret=%d\n", + resp_io.total_completed, ret); +#endif + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, resp_io.total_completed); + /* This is a temporary way of filling in status. The right way is to + * keep track of how much data was actually acccessed by + * ADIOI_BUFFERED operations */ +#endif + return ret; +} + +/* convert_mpi_pvfs2_dtype - Convert a MPI datatype into + * a PVFS2 datatype so that we can natively use the PVFS2 + * datatypes in the PVFS2 I/O calls instead of converting + * all datatypes to the hindexed method + * return 1 - a leaf node + * return 0 - normal return + * return -1 - problems */ + +int convert_mpi_pvfs2_dtype(MPI_Datatype *mpi_dtype, + PVFS_Request *pvfs_dtype) +{ + int num_int = -1, num_addr = -1, num_dtype = -1, + combiner = -1, i = -1, ret = -1, leaf = -1; + int *arr_int = NULL; + MPI_Aint *arr_addr = NULL; + MPI_Datatype *arr_dtype = NULL; + PVFS_Request *old_pvfs_dtype = NULL; + PVFS_Request *old_pvfs_dtype_arr = NULL; + int arr_count = -1; + PVFS_size *pvfs_arr_disp = NULL; + int *pvfs_arr_len = NULL; + + MPI_Type_get_envelope(*mpi_dtype, + &num_int, + &num_addr, + &num_dtype, + &combiner); + + /* Depending on type of datatype do the following + * operations */ + + if (combiner == MPI_COMBINER_NAMED) + { + convert_named(mpi_dtype, pvfs_dtype, combiner); + return 1; + } + + /* Allocate space for the arrays necessary for + * MPI_Type_get_contents */ + + if ((arr_int = ADIOI_Malloc(sizeof(int)*num_int)) == NULL) + { + fprintf(stderr, "Failed to allocate array_int\n"); + return -1; + } + if ((arr_addr = ADIOI_Malloc(sizeof(int)*num_addr)) == NULL) + { + ADIOI_Free(arr_int); + fprintf(stderr, "Failed to allocate array_addr\n"); + return -1; + } + if ((arr_dtype = ADIOI_Malloc(sizeof(MPI_Datatype)*num_dtype)) == NULL) + { + ADIOI_Free(arr_int); + ADIOI_Free(arr_addr); + fprintf(stderr, "Failed to allocate array_dtypes\n"); + return -1; + } + + MPI_Type_get_contents(*mpi_dtype, + num_int, + num_addr, + num_dtype, + arr_int, + arr_addr, + arr_dtype); + + /* If it's not a predefined datatype, it is either a + * derived datatype or a structured datatype */ + + if (combiner != MPI_COMBINER_STRUCT) + { + if ((old_pvfs_dtype = ADIOI_Malloc(sizeof(PVFS_Request))) == NULL) + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "Failed to allocate PVFS_Request\n"); + switch (combiner) + { + case MPI_COMBINER_CONTIGUOUS: + leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); + ret = PVFS_Request_contiguous(arr_int[0], + *old_pvfs_dtype, pvfs_dtype); + break; + case MPI_COMBINER_VECTOR: + leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); + ret = PVFS_Request_vector(arr_int[0], arr_int[1], + arr_int[2], *old_pvfs_dtype, + pvfs_dtype); + break; + case MPI_COMBINER_HVECTOR: + leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); + ret = PVFS_Request_hvector(arr_int[0], arr_int[1], + arr_addr[0], *old_pvfs_dtype, + pvfs_dtype); + break; + /* Both INDEXED and HINDEXED types require PVFS_size + * address arrays. Therefore, we need to copy and + * convert the data from MPI_get_contents() into + * a PVFS_size buffer */ + case MPI_COMBINER_INDEXED: + leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); + if ((pvfs_arr_disp = + ADIOI_Malloc(arr_int[0]*sizeof(PVFS_size))) == 0) + { + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "Failed to allocate pvfs_arr_disp\n"); + } + for (i = 0; i < arr_int[0]; i++) + { + pvfs_arr_disp[i] = + (PVFS_size) arr_int[arr_int[0]+1+i]; + } + ret = PVFS_Request_indexed(arr_int[0], &arr_int[1], + pvfs_arr_disp, + *old_pvfs_dtype, pvfs_dtype); + ADIOI_Free(pvfs_arr_disp); + break; + case MPI_COMBINER_HINDEXED: + leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); + if ((pvfs_arr_disp = + ADIOI_Malloc(arr_int[0]*sizeof(PVFS_size))) == 0) + { + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "Failed to allocate pvfs_arr_disp\n"); + } + for (i = 0; i < arr_int[0]; i++) + { + pvfs_arr_disp[i] = + (PVFS_size) arr_addr[i]; + } + ret = PVFS_Request_hindexed(arr_int[0], &arr_int[1], + (int64_t *)&arr_addr[0], + *old_pvfs_dtype, pvfs_dtype); + ADIOI_Free(pvfs_arr_disp); + break; + case MPI_COMBINER_DUP: + leaf = convert_mpi_pvfs2_dtype(&arr_dtype[0], old_pvfs_dtype); + ret = PVFS_Request_contiguous(1, + *old_pvfs_dtype, pvfs_dtype); + + break; + case MPI_COMBINER_INDEXED_BLOCK: + /* No native PVFS2 support for this operation currently */ + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "INDEXED_BLOCK is unsupported\n"); + break; + case MPI_COMBINER_HINDEXED_BLOCK: + /* No native PVFS2 support for this operation currently */ + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "HINDEXED_BLOCK is unsupported\n"); + break; + case MPI_COMBINER_HINDEXED_INTEGER: + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "HINDEXED_INTEGER is unsupported\n"); + break; + case MPI_COMBINER_STRUCT_INTEGER: + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "STRUCT_INTEGER is unsupported\n"); + break; + case MPI_COMBINER_SUBARRAY: + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "SUBARRAY is unsupported\n"); + break; + case MPI_COMBINER_DARRAY: + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "DARRAY is unsupported\n"); + break; + case MPI_COMBINER_F90_REAL: + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "F90_REAL is unsupported\n"); + break; + case MPI_COMBINER_F90_COMPLEX: + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "F90_COMPLEX is unsupported\n"); + break; + case MPI_COMBINER_F90_INTEGER: + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "F90_INTEGER is unsupported\n"); + break; + case MPI_COMBINER_RESIZED: + ADIOI_Free(old_pvfs_dtype); + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "RESIZED is unsupported\n"); + break; + default: + break; + } + + if (ret != 0) + fprintf(stderr, "Error in PVFS_Request_* " + "for a derived datatype\n"); + +#ifdef DEBUG_DTYPE + print_dtype_info(combiner, + num_int, + num_addr, + num_dtype, + arr_int, + arr_addr, + arr_dtype); +#endif + + if (leaf != 1 && combiner != MPI_COMBINER_DUP) + MPI_Type_free(&arr_dtype[0]); + + ADIOI_Free(arr_int); + ADIOI_Free(arr_addr); + ADIOI_Free(arr_dtype); + + PVFS_Request_free(old_pvfs_dtype); + ADIOI_Free(old_pvfs_dtype); + + return ret; + } + else /* MPI_COMBINER_STRUCT */ + { + MPI_Aint mpi_lb = -1, mpi_extent = -1; + PVFS_offset pvfs_lb = -1; + PVFS_size pvfs_extent = -1; + int has_lb_ub = 0; + + /* When converting into a PVFS_Request_struct, we no longer + * can use MPI_LB and MPI_UB. Therfore, we have to do the + * following. + * We simply ignore all the MPI_LB and MPI_UB types and + * get the lb and extent and pass it on through a + * PVFS resized_req */ + + arr_count = 0; + for (i = 0; i < arr_int[0]; i++) + { + if (arr_dtype[i] != MPI_LB && + arr_dtype[i] != MPI_UB) + { + arr_count++; + } + } + + if (arr_int[0] != arr_count) + { + MPI_Type_get_extent(*mpi_dtype, &mpi_lb, &mpi_extent); + pvfs_lb = mpi_lb; + pvfs_extent = mpi_extent; + if ((pvfs_arr_len = ADIOI_Malloc(arr_count*sizeof(int))) + == NULL) + { + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "Failed to allocate pvfs_arr_len\n"); + } + has_lb_ub = 1; + } + + if ((old_pvfs_dtype_arr + = ADIOI_Malloc(arr_count*sizeof(PVFS_Request))) == NULL) + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "Failed to allocate PVFS_Requests\n"); + + if ((pvfs_arr_disp = ADIOI_Malloc(arr_count*sizeof(PVFS_size))) + == NULL) + { + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "Failed to allocate pvfs_arr_disp\n"); + } + + arr_count = 0; + for (i = 0; i < arr_int[0]; i++) + { + if (arr_dtype[i] != MPI_LB && + arr_dtype[i] != MPI_UB) + { + leaf = convert_mpi_pvfs2_dtype( + &arr_dtype[i], &old_pvfs_dtype_arr[arr_count]); + if (leaf != 1) + MPI_Type_free(&arr_dtype[i]); + pvfs_arr_disp[arr_count] = + (PVFS_size) arr_addr[i]; + if (has_lb_ub) + { + pvfs_arr_len[arr_count] = + arr_int[i+1]; + } + arr_count++; + } + } + + /* If a MPI_UB or MPI_LB did exist, we have to + * resize the datatype */ + if (has_lb_ub) + { + PVFS_Request *tmp_pvfs_dtype = NULL; + if ((tmp_pvfs_dtype = ADIOI_Malloc(sizeof(PVFS_Request))) == NULL) + fprintf(stderr, "convert_mpi_pvfs2_dtype: " + "Failed to allocate PVFS_Request\n"); + + ret = PVFS_Request_struct(arr_count, pvfs_arr_len, + pvfs_arr_disp, + old_pvfs_dtype_arr, tmp_pvfs_dtype); + if (ret != 0) + fprintf(stderr, "Error in PVFS_Request_struct\n"); + + arr_count = 0; + for (i = 0; i < arr_int[0]; i++) + { + if (arr_dtype[i] != MPI_LB && + arr_dtype[i] != MPI_UB) + { + PVFS_Request_free(&old_pvfs_dtype_arr[arr_count]); + arr_count++; + } + } + +#ifdef DEBUG_DTYPE + fprintf(stderr, "STRUCT(WITHOUT %d LB or UB)(%d,[", + arr_int[0] - arr_count, arr_count); + for (i = 0; i < arr_count; i++) + fprintf(stderr, "(%d,%Ld) ", + pvfs_arr_len[i], + pvfs_arr_disp[i]); + fprintf(stderr, "]\n"); + fprintf(stderr, "RESIZED(LB = %Ld, EXTENT = %Ld)\n", + pvfs_lb, pvfs_extent); +#endif + ret = PVFS_Request_resized(*tmp_pvfs_dtype, + pvfs_lb, pvfs_extent, pvfs_dtype); + if (ret != 0) + fprintf(stderr, "Error in PVFS_Request_resize\n"); + + PVFS_Request_free(tmp_pvfs_dtype); + ADIOI_Free(tmp_pvfs_dtype); + } + else /* No MPI_LB or MPI_UB datatypes */ + { + ret = PVFS_Request_struct(arr_int[0], &arr_int[1], + pvfs_arr_disp, + old_pvfs_dtype_arr, pvfs_dtype); + if (ret != 0) + fprintf(stderr, "Error in PVFS_Request_struct\n"); + + for (i = 0; i < arr_int[0]; i++) + { + if (arr_dtype[i] != MPI_LB && + arr_dtype[i] != MPI_UB) + PVFS_Request_free(&old_pvfs_dtype_arr[i]); + } + +#ifdef DEBUG_DTYPE + print_dtype_info(combiner, + num_int, + num_addr, + num_dtype, + arr_int, + arr_addr, + arr_dtype); +#endif + } + + ADIOI_Free(arr_int); + ADIOI_Free(arr_addr); + ADIOI_Free(arr_dtype); + + ADIOI_Free(old_pvfs_dtype_arr); + ADIOI_Free(pvfs_arr_disp); + ADIOI_Free(pvfs_arr_len); + + return ret; + } + + /* Shouldn't have gotten here */ + fprintf(stderr, "convert_mpi_pvfs2_dtype: SERIOUS ERROR\n"); + return -1; +} + +int convert_named(MPI_Datatype *mpi_dtype, + PVFS_Request *pvfs_dtype, int combiner) +{ + int ret = -1; +#ifdef DEBUG_DTYPE + fprintf(stderr, "NAMED"); +#endif + + if (MPI_CHAR == *mpi_dtype) + { + ret = PVFS_Request_contiguous(1, PVFS_CHAR, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_CHAR\n"); +#endif + } + else if ( MPI_BYTE == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_BYTE, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_BYTE\n"); +#endif + } + else if ( MPI_SHORT == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_SHORT, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_SHORT\n"); +#endif + } + else if ( MPI_INT == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_INT, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_INT\n"); +#endif + } + else if ( MPI_LONG == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_LONG, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_LONG\n"); +#endif + } + else if ( MPI_FLOAT == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_FLOAT, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_FLOAT\n"); +#endif + } + else if ( MPI_DOUBLE == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_DOUBLE, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_DOUBLE\n"); +#endif + } + else if ( MPI_UNSIGNED_CHAR == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_UNSIGNED_CHAR, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_UNSIGNED_CHAR\n"); +#endif + } + else if ( MPI_UNSIGNED_SHORT == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_UNSIGNED, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_UNSIGNED_SHORT\n"); +#endif + } + else if ( MPI_UNSIGNED == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_UNSIGNED, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_SHORT\n"); +#endif + } + else if ( MPI_UNSIGNED_LONG == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_UNSIGNED_LONG, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_UNSIGNED_LONG\n"); +#endif + } + else if ( MPI_LONG_DOUBLE == *mpi_dtype ) + { + ret = PVFS_Request_contiguous(1, PVFS_LONG_DOUBLE, pvfs_dtype); +#ifdef DEBUG_DTYPE + fprintf(stderr, "-MPI_LONG_DOUBLE\n"); +#endif + } + else + { + fprintf(stderr, "convert_named: predefined type not found"); + return -1; + } + if (ret != 0) + fprintf(stderr, "convert_named: Datatype creation failed\n"); + return ret; +} + +void print_dtype_info(int combiner, + int num_int, + int num_addr, + int num_dtype, + int *arr_int, + MPI_Aint *arr_addr, + MPI_Datatype *arr_dtype) +{ + int i = -1; + switch (combiner) + { + case MPI_COMBINER_CONTIGUOUS: + fprintf(stderr, "CONTIG(%d)\n", arr_int[0]); + break; + case MPI_COMBINER_VECTOR: + fprintf(stderr, "VECTOR(%d,%d,%d)\n", + arr_int[0], arr_int[1], arr_int[2]); + break; + case MPI_COMBINER_HVECTOR: + fprintf(stderr, "HVECTOR(%d,%d,%ld)\n", + arr_int[0], arr_int[1],arr_addr[0]); + break; + case MPI_COMBINER_INDEXED: + fprintf(stderr, "INDEXED(%d,[", + arr_int[0]); + for (i = 0; i < arr_int[0]; i++) + fprintf(stderr, "(%d,%d) ", + arr_int[1+i], + arr_int[arr_int[0]+1+i]); + fprintf(stderr, "]\n"); + break; + case MPI_COMBINER_HINDEXED: + fprintf(stderr, "HINDEXED(%d,[", + arr_int[0]); + for (i = 0; i < arr_int[0]; i++) + fprintf(stderr, "(%d,%lld) ", + arr_int[1+i], + (long long)arr_addr[i]); + fprintf(stderr, "]\n"); + break; + case MPI_COMBINER_STRUCT: + fprintf(stderr, "STRUCT(%d,[", + arr_int[0]); + for (i = 0; i < arr_int[0]; i++) + fprintf(stderr, "(%d,%lld) ", + arr_int[1+i], + (long long) arr_addr[i]); + fprintf(stderr, "]\n"); + break; + case MPI_COMBINER_DUP: + fprintf(stderr, "DUP\n"); + break; + default: + fprintf(stderr, "no available information on this datatype"); + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_io_list.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_io_list.c new file mode 100644 index 0000000000..c5d03d151c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_io_list.c @@ -0,0 +1,665 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 2006 Unknown (TODO: fix this) + */ + +#include +#include "adio.h" +#include "adio_extern.h" +#include "ad_pvfs2.h" +#include "ad_pvfs2_io.h" +#include "ad_pvfs2_common.h" + +#define COALESCE_REGIONS /* TODO: would we ever want to *not* coalesce? */ +#define MAX_OL_COUNT 64 +int ADIOI_PVFS2_StridedListIO(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code, int rw_type) +{ + /* list I/O parameters */ + int i = -1, ret = -1; + int tmp_filetype_size = -1; + int64_t cur_io_size = 0, io_size = 0; + int etype_size = -1; + int num_etypes_in_filetype = -1, num_filetypes = -1; + int etypes_in_filetype = -1, size_in_filetype = -1; + int bytes_into_filetype = 0; + MPI_Offset total_bytes_accessed = 0; + + /* parameters for offset-length pairs arrays */ + int64_t buf_off_arr[MAX_OL_COUNT]; + int32_t buf_len_arr[MAX_OL_COUNT]; + int64_t file_off_arr[MAX_OL_COUNT]; + int32_t file_len_arr[MAX_OL_COUNT]; + int32_t buf_ol_count = 0; + int32_t file_ol_count = 0; + + /* parameters for flattened memory and file datatypes*/ + int flat_buf_index = 0; + int flat_file_index = 0; + int64_t cur_flat_buf_reg_off = 0; + int64_t cur_flat_file_reg_off = 0; + ADIOI_Flatlist_node *flat_buf_p, *flat_file_p; + MPI_Count buftype_size = -1, filetype_size = -1; + MPI_Aint filetype_extent = -1, buftype_extent = -1;; + int buftype_is_contig = -1, filetype_is_contig = -1; + + /* PVFS2 specific parameters */ + PVFS_Request mem_req, file_req; + ADIOI_PVFS2_fs * pvfs_fs; + PVFS_sysresp_io resp_io; + static char myname[] = "ADIOI_PVFS2_STRIDED_LISTIO"; + + if (fd->atomicity) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "Atomic noncontiguous writes" + " are not supported by PVFS2", 0); + return -1; + } + + MPI_Type_size_x(fd->filetype, &filetype_size); + if (filetype_size == 0) { + *error_code = MPI_SUCCESS; + return -1; + } + MPI_Type_extent(fd->filetype, &filetype_extent); + MPI_Type_size_x(datatype, &buftype_size); + MPI_Type_extent(datatype, &buftype_extent); + io_size = buftype_size*count; + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + /* Flatten the memory datatype + * (file datatype has already been flattened in ADIO open + * unless it is contibuous, then we need to flatten it manually) + * and set the correct buffers for flat_buf and flat_file */ + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + if (buftype_is_contig == 0) + { + ADIOI_Flatten_datatype(datatype); + flat_buf_p = ADIOI_Flatlist; + while (flat_buf_p->type != datatype) + flat_buf_p = flat_buf_p->next; + } + else + { + /* flatten and add to the list */ + flat_buf_p = (ADIOI_Flatlist_node *) ADIOI_Malloc + (sizeof(ADIOI_Flatlist_node)); + flat_buf_p->blocklens = (ADIO_Offset*)ADIOI_Malloc(sizeof(ADIO_Offset)); + flat_buf_p->indices = + (ADIO_Offset *) ADIOI_Malloc(sizeof(ADIO_Offset)); + /* For the buffer, we can optimize the buftype, this is not + * possible with the filetype since it is tiled */ + buftype_size = buftype_size*count; + buftype_extent = buftype_size*count; + flat_buf_p->blocklens[0] = buftype_size; + flat_buf_p->indices[0] = 0; + flat_buf_p->count = 1; + } + if (filetype_is_contig == 0) + { + /* TODO: why does avery say this should already have been + * flattened in Open, but also says contig types don't get + * flattened */ + ADIOI_Flatten_datatype(fd->filetype); + flat_file_p = ADIOI_Flatlist; + while (flat_file_p->type != fd->filetype) + flat_file_p = flat_file_p->next; + } + else + { + /* flatten and add to the list */ + flat_file_p = (ADIOI_Flatlist_node *) ADIOI_Malloc + (sizeof(ADIOI_Flatlist_node)); + flat_file_p->blocklens =(ADIO_Offset*)ADIOI_Malloc(sizeof(ADIO_Offset)); + flat_file_p->indices = + (ADIO_Offset *) ADIOI_Malloc(sizeof(ADIO_Offset)); + flat_file_p->blocklens[0] = filetype_size; + flat_file_p->indices[0] = 0; + flat_file_p->count = 1; + } + + /* Find out where we are in the flattened filetype (the block index, + * how far into the block, and how many bytes_into_filetype) + * If the file_ptr_type == ADIO_INDIVIDUAL we will use disp, fp_ind + * to figure this out (offset should always be zero) + * If file_ptr_type == ADIO_EXPLICIT, we will use disp and offset + * to figure this out. */ + + etype_size = fd->etype_size; + num_etypes_in_filetype = filetype_size / etype_size; + if (file_ptr_type == ADIO_INDIVIDUAL) + { + int flag = 0; + /* Should have already been flattened in ADIO_Open*/ + num_filetypes = -1; + while (!flag) + { + num_filetypes++; + for (i = 0; i < flat_file_p->count; i++) + { + /* Start on a non zero-length region */ + if (flat_file_p->blocklens[i]) + { + if (fd->disp + flat_file_p->indices[i] + + (num_filetypes * filetype_extent) + + flat_file_p->blocklens[i] > fd->fp_ind && + fd->disp + flat_file_p->indices[i] <= + fd->fp_ind) + { + flat_file_index = i; + cur_flat_file_reg_off = fd->fp_ind - + (fd->disp + flat_file_p->indices[i] + + (num_filetypes * filetype_extent)); + flag = 1; + break; + } + else + bytes_into_filetype += flat_file_p->blocklens[i]; + } + } + } + /* Impossible that we don't find it in this datatype */ + assert(i != flat_file_p->count); + } + else + { + num_filetypes = (int) (offset / num_etypes_in_filetype); + etypes_in_filetype = (int) (offset % num_etypes_in_filetype); + size_in_filetype = etypes_in_filetype * etype_size; + + tmp_filetype_size = 0; + for (i=0; icount; i++) { + tmp_filetype_size += flat_file_p->blocklens[i]; + if (tmp_filetype_size > size_in_filetype) + { + flat_file_index = i; + cur_flat_file_reg_off = flat_file_p->blocklens[i] - + (tmp_filetype_size - size_in_filetype); + bytes_into_filetype = offset * filetype_size - + flat_file_p->blocklens[i]; + break; + } + } + } +#ifdef DEBUG_LIST + fprintf(stderr, "ADIOI_PVFS2_StridedListIO: (fd->fp_ind=%Ld,fd->disp=%Ld," + " offset=%Ld)\n(flat_file_index=%d,cur_flat_file_reg_off=%Ld," + "bytes_into_filetype=%d)\n", + fd->fp_ind, fd->disp, offset, flat_file_index, + cur_flat_file_reg_off, bytes_into_filetype); +#endif +#ifdef DEBUG_LIST2 + fprintf(stderr, "flat_buf:\n"); + for (i = 0; i < flat_buf_p->count; i++) + fprintf(stderr, "(offset, length) = (%Ld, %d)\n", + flat_buf_p->indices[i], + flat_buf_p->blocklens[i]); + fprintf(stderr, "flat_file:\n"); + for (i = 0; i < flat_file_p->count; i++) + fprintf(stderr, "(offset, length) = (%Ld, %d)\n", + flat_file_p->indices[i], + flat_file_p->blocklens[i]); +#endif + + /* total data written */ + cur_io_size = 0; + while (cur_io_size != io_size) + { + /* Initialize the temporarily unrolling lists and + * and associated variables */ + buf_ol_count = 0; + file_ol_count = 0; + for (i = 0; i < MAX_OL_COUNT; i++) + { + buf_off_arr[i] = 0; + buf_len_arr[i] = 0; + file_off_arr[i] = 0; + file_len_arr[i] = 0; + } + + /* Generate the offset-length pairs for a + * list I/O operation */ + gen_listio_arr(flat_buf_p, + &flat_buf_index, + &cur_flat_buf_reg_off, + buftype_size, + buftype_extent, + flat_file_p, + &flat_file_index, + &cur_flat_file_reg_off, + filetype_size, + filetype_extent, + MAX_OL_COUNT, + fd->disp, + bytes_into_filetype, + &cur_io_size, + io_size, + buf_off_arr, + buf_len_arr, + &buf_ol_count, + file_off_arr, + file_len_arr, + &file_ol_count); + + assert(buf_ol_count <= MAX_OL_COUNT); + assert(file_ol_count <= MAX_OL_COUNT); +#ifdef DEBUG_LIST2 + print_buf_file_ol_pairs(buf_off_arr, + buf_len_arr, + buf_ol_count, + file_off_arr, + file_len_arr, + file_ol_count, + buf, + rw_type); +#endif +#ifdef DEBUG_LIST2 + do { + int y, z; + fprintf(stderr, "ad_pvfs2_io_list.c::\n"); + for (y = 0; y < buf_ol_count; y++) + { + for (z = 0; z < buf_len_arr[y]; z++) + { + fprintf(stderr, "buf[%d][%d]=%c\n", + y, z, ((char *) buf + buf_off_arr[y])[z]); + } + } + } while (0); +#endif + + /* Run list I/O operation */ + ret = PVFS_Request_hindexed(buf_ol_count, buf_len_arr, + buf_off_arr, PVFS_BYTE, &mem_req); + + ret = PVFS_Request_hindexed(file_ol_count, file_len_arr, + file_off_arr, PVFS_BYTE, &file_req); + if (rw_type == READ) + { + ret = PVFS_sys_read(pvfs_fs->object_ref, file_req, 0, + buf, mem_req, + &(pvfs_fs->credentials), &resp_io); + } + else + { + ret = PVFS_sys_write(pvfs_fs->object_ref, file_req, 0, + buf, mem_req, + &(pvfs_fs->credentials), &resp_io); + } + if (ret != 0) + { + fprintf(stderr, "ADIOI_PVFS2_StridedListIO: Warning - PVFS_sys_" + "read/write returned %d and completed %lld bytes.\n", + ret, (long long)resp_io.total_completed); + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_io \n", 0); + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + goto error_state; + } + total_bytes_accessed += resp_io.total_completed; + + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + } + +#ifdef DEBUG_LIST + fprintf(stderr, "ADIOI_PVFS2_StridedListIO: " + "total_bytes_accessed=%Ld,ret=%d\n", + total_bytes_accessed, ret); +#endif + + if (file_ptr_type == ADIO_INDIVIDUAL) + fd->fp_ind += total_bytes_accessed; + *error_code = MPI_SUCCESS; + +error_state: +#ifdef HAVE_STATUS_SET_BYTES + /* TODO: why the cast? */ + MPIR_Status_set_bytes(status, datatype, total_bytes_accessed); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + if (buftype_is_contig == 0) + ADIOI_Delete_flattened(datatype); + else + { + ADIOI_Free(flat_buf_p->blocklens); + ADIOI_Free(flat_buf_p->indices); + ADIOI_Free(flat_buf_p); + } + + if (filetype_is_contig == 0) + ADIOI_Delete_flattened(fd->filetype); + else + { + ADIOI_Free(flat_file_p->blocklens); + ADIOI_Free(flat_file_p->indices); + ADIOI_Free(flat_file_p); + } + + return 0; +} + +/* To do: Fix the code to coalesce the offset-length pairs for memory + * and file. */ + +/* gen_listio_arr - fills in offset-length pairs for memory and file + * for list I/O */ +int gen_listio_arr(ADIOI_Flatlist_node *flat_buf_p, + int *flat_buf_index_p, + int64_t *cur_flat_buf_reg_off_p, + int flat_buf_size, + int flat_buf_extent, + ADIOI_Flatlist_node *flat_file_p, + int *flat_file_index_p, + int64_t *cur_flat_file_reg_off_p, + int flat_file_size, + int flat_file_extent, + int max_ol_count, + ADIO_Offset disp, + int bytes_into_filetype, + int64_t *bytes_completed, + int64_t total_io_size, + int64_t buf_off_arr[], + int32_t buf_len_arr[], + int32_t *buf_ol_count_p, + int64_t file_off_arr[], + int32_t file_len_arr[], + int32_t *file_ol_count_p) +{ + int region_size = -1; + + /* parameters for flattened memory and file datatypes*/ + int64_t cur_flat_buf_reg_left = 0; + int64_t cur_flat_file_reg_left = 0; + +#ifdef DEBUG_LIST2 + fprintf(stderr, "gen_list_arr:\n"); +#endif + + if ((*buf_ol_count_p) != 0 ||(*file_ol_count_p) != 0) + { + fprintf(stderr, "buf_ol_count != 0 || file_ol_count != 0\n"); + return -1; + } + + /* Start on a non-zero memory and file region + * Note this does not affect the bytes_completed + * since no data is in these regions. Initialize the + * first memory and file offsets. */ + while (flat_buf_p->blocklens[(*flat_buf_index_p)] == 0) + { + (*flat_buf_index_p) = ((*flat_buf_index_p) + 1) % + flat_buf_p->count; + } + buf_off_arr[*buf_ol_count_p] = + (*bytes_completed / flat_buf_size) * + flat_buf_extent + + flat_buf_p->indices[*flat_buf_index_p] + + *cur_flat_buf_reg_off_p; + buf_len_arr[*buf_ol_count_p] = 0; + + while (flat_file_p->blocklens[(*flat_file_index_p)] == 0) + { + (*flat_file_index_p) = ((*flat_file_index_p) + 1) % + flat_file_p->count; + } + file_off_arr[*file_ol_count_p] = disp + + (((bytes_into_filetype + *bytes_completed) / flat_file_size) * + flat_file_extent) + + flat_file_p->indices[*flat_file_index_p] + + *cur_flat_file_reg_off_p; + file_len_arr[*file_ol_count_p] = 0; + +#ifdef DEBUG_LIST2 + fprintf(stderr, "initial buf_off_arr[%d] = %Ld\n", *buf_ol_count_p, + buf_off_arr[*buf_ol_count_p]); + fprintf(stderr, "initial file_off_arr[%d] = %Ld\n", *file_ol_count_p, + file_off_arr[*file_ol_count_p]); +#endif + + while (*bytes_completed != total_io_size + && (*buf_ol_count_p) < max_ol_count + && (*file_ol_count_p) < max_ol_count) + { + /* How much data is left in the current piece in + * the flattened datatypes */ + cur_flat_buf_reg_left = flat_buf_p->blocklens[*flat_buf_index_p] + - *cur_flat_buf_reg_off_p; + cur_flat_file_reg_left = flat_file_p->blocklens[*flat_file_index_p] + - *cur_flat_file_reg_off_p; + +#ifdef DEBUG_LIST2 + fprintf(stderr, + "flat_buf_index=%d flat_buf->blocklens[%d]=%d\n" + "cur_flat_buf_reg_left=%Ld " + "*cur_flat_buf_reg_off_p=%Ld\n" + "flat_file_index=%d flat_file->blocklens[%d]=%d\n" + "cur_flat_file_reg_left=%Ld " + "*cur_flat_file_reg_off_p=%Ld\n" + "bytes_completed=%Ld\n" + "buf_ol_count=%d file_ol_count=%d\n" + "buf_len_arr[%d]=%d file_len_arr[%d]=%d\n\n", + *flat_buf_index_p, *flat_buf_index_p, + flat_buf_p->blocklens[*flat_buf_index_p], + cur_flat_buf_reg_left, + *cur_flat_buf_reg_off_p, + *flat_file_index_p, *flat_file_index_p, + flat_file_p->blocklens[*flat_file_index_p], + cur_flat_file_reg_left, + *cur_flat_file_reg_off_p, + *bytes_completed, + *buf_ol_count_p, *file_ol_count_p, + *buf_ol_count_p, + buf_len_arr[*buf_ol_count_p], + *file_ol_count_p, + file_len_arr[*file_ol_count_p]); +#endif + + /* What is the size of the next contiguous region agreed + * upon by both memory and file regions that does not + * surpass the file size */ + if (cur_flat_buf_reg_left > cur_flat_file_reg_left) + region_size = cur_flat_file_reg_left; + else + region_size = cur_flat_buf_reg_left; + + if (region_size > total_io_size - *bytes_completed) + region_size = total_io_size - *bytes_completed; + + /* Add this piece to both the mem and file arrays + * coalescing offset-length pairs if possible and advance + * the pointers through the flatten mem and file datatypes + * as well Note: no more than a single piece can be done + * since we take the smallest one possible */ + + if (cur_flat_buf_reg_left == region_size) + { +#ifdef DEBUG_LIST2 + fprintf(stderr, "reached end of memory block...\n"); +#endif + (*flat_buf_index_p) = ((*flat_buf_index_p) + 1) % + flat_buf_p->count; + while (flat_buf_p->blocklens[(*flat_buf_index_p)] == 0) + { + (*flat_buf_index_p) = ((*flat_buf_index_p) + 1) % + flat_buf_p->count; + } + *cur_flat_buf_reg_off_p = 0; + +#ifdef COALESCE_REGIONS + if (*buf_ol_count_p != 0) + { + if (buf_off_arr[(*buf_ol_count_p) - 1] + + buf_len_arr[(*buf_ol_count_p) - 1] == + buf_off_arr[*buf_ol_count_p]) + { + buf_len_arr[(*buf_ol_count_p) - 1] += + region_size; + } + else + { + buf_len_arr[*buf_ol_count_p] += region_size; + (*buf_ol_count_p)++; + } + } + else + { +#endif + buf_len_arr[*buf_ol_count_p] += region_size; + (*buf_ol_count_p)++; +#ifdef COALESCE_REGIONS + } +#endif + + /* Don't prepare for the next piece if we have reached + * the limit or else it will segment fault. */ + if ((*buf_ol_count_p) != max_ol_count) + { + buf_off_arr[*buf_ol_count_p] = + ((*bytes_completed + region_size) / flat_buf_size) * + flat_buf_extent + + flat_buf_p->indices[*flat_buf_index_p] + + (*cur_flat_buf_reg_off_p); + buf_len_arr[*buf_ol_count_p] = 0; + } + } + else if (cur_flat_buf_reg_left > region_size) + { +#ifdef DEBUG_LIST2 + fprintf(stderr, "advanced %d in memory block...\n", + region_size); +#endif + (*cur_flat_buf_reg_off_p) += region_size; + buf_len_arr[*buf_ol_count_p] += region_size; + } + else + { + fprintf(stderr, "gen_listio_arr: Error\n"); + } + + /* To calculate the absolute file offset we need to + * add the disp, how many filetypes we have gone through, + * the relative block offset in the filetype and how far + * into the block we have gone. */ + if (cur_flat_file_reg_left == region_size) + { +#ifdef DEBUG_LIST2 + fprintf(stderr, "reached end of file block...\n"); +#endif + (*flat_file_index_p) = ((*flat_file_index_p) + 1) % + flat_file_p->count; + while (flat_file_p->blocklens[(*flat_file_index_p)] == 0) + { + (*flat_file_index_p) = ((*flat_file_index_p) + 1) % + flat_file_p->count; + } + (*cur_flat_file_reg_off_p) = 0; + +#ifdef COALESCE_REGIONS + if (*file_ol_count_p != 0) + { + if (file_off_arr[(*file_ol_count_p) - 1] + + file_len_arr[(*file_ol_count_p) - 1] == + file_off_arr[*file_ol_count_p]) + { + file_len_arr[(*file_ol_count_p) - 1] += + region_size; + } + else + { + file_len_arr[*file_ol_count_p] += region_size; + (*file_ol_count_p)++; + } + } + else + { +#endif + file_len_arr[*file_ol_count_p] += region_size; + (*file_ol_count_p)++; +#ifdef COALESCE_REGIONS + } +#endif + + /* Don't prepare for the next piece if we have reached + * the limit or else it will segment fault. */ + if ((*file_ol_count_p) != max_ol_count) + { + file_off_arr[*file_ol_count_p] = disp + + (((bytes_into_filetype + *bytes_completed + region_size) + / flat_file_size) * + flat_file_extent) + + flat_file_p->indices[*flat_file_index_p] + + (*cur_flat_file_reg_off_p); + file_len_arr[*file_ol_count_p] = 0; + } + } + else if (cur_flat_file_reg_left > region_size) + { +#ifdef DEBUG_LIST2 + fprintf(stderr, "advanced %d in file block...\n", + region_size); +#endif + (*cur_flat_file_reg_off_p) += region_size; + file_len_arr[*file_ol_count_p] += region_size; + } + else + { + fprintf(stderr, "gen_listio_arr: Error\n"); + } +#ifdef DEBUG_LIST2 + fprintf(stderr, + "------------------------------\n\n"); +#endif + *bytes_completed += region_size; + } + /* Increment the count if we stopped in the middle of a + * memory or file region */ + if (*cur_flat_buf_reg_off_p != 0) + (*buf_ol_count_p)++; + if (*cur_flat_file_reg_off_p != 0) + (*file_ol_count_p)++; + + return 0; +} + +void print_buf_file_ol_pairs(int64_t buf_off_arr[], + int32_t buf_len_arr[], + int32_t buf_ol_count, + int64_t file_off_arr[], + int32_t file_len_arr[], + int32_t file_ol_count, + void *buf, + int rw_type) +{ + int i = -1; + + fprintf(stderr, "buf_ol_pairs(offset,length) count = %d\n", + buf_ol_count); + for (i = 0; i < buf_ol_count; i++) + { + fprintf(stderr, "(%lld, %d) ", (long long)buf_off_arr[i], buf_len_arr[i]); + } + fprintf(stderr, "\n"); + + fprintf(stderr, "file_ol_pairs(offset,length) count = %d\n", + file_ol_count); + for (i = 0; i < file_ol_count; i++) + { + fprintf(stderr, "(%lld, %d) ", (long long)file_off_arr[i], file_len_arr[i]); + } + fprintf(stderr, "\n\n"); + +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_open.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_open.c new file mode 100644 index 0000000000..c5d933f42b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_open.c @@ -0,0 +1,246 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs2.h" +#include "ad_pvfs2_common.h" + +/* open_status is helpful for bcasting values around */ +struct open_status_s { + int error; + PVFS_object_ref object_ref; +}; +typedef struct open_status_s open_status; + + /* steps for getting a handle: (it gets a little convoluted, but at least + * it's deterministic) + * . lookup the file. + * . if lookup succeeds, but we were passed MPI_MODE_EXCL, that's an error + * . if lookup fails, the file might not exist. + * in that case, create the file if we were passed MPI_MODE_CREATE + * . if the create fails, that means someone else created the file between + * our call to lookup and our call to create (like if N processors all + * open the same file with MPI_COMM_SELF). Then we can just look up the + * file (which now exists). + * + * the good news is that only one processor does this and broadcasts the + * handle to everyone else in the communicator + */ +static void fake_an_open(PVFS_fs_id fs_id, char *pvfs_name, int access_mode, + int nr_datafiles, PVFS_size strip_size, + ADIOI_PVFS2_fs *pvfs2_fs, + open_status *o_status) +{ + int ret; + PVFS_sysresp_lookup resp_lookup; + PVFS_sysresp_getparent resp_getparent; + PVFS_sysresp_create resp_create; + PVFS_sys_attr attribs; + PVFS_sys_dist* dist; + + ADIOI_PVFS2_makeattribs(&attribs); + if (nr_datafiles > 0 ) { + attribs.dfile_count = nr_datafiles; + attribs.mask |= PVFS_ATTR_SYS_DFILE_COUNT; + } + + dist = NULL; + + memset(&resp_lookup, 0, sizeof(resp_lookup)); + memset(&resp_getparent, 0, sizeof(resp_getparent)); + memset(&resp_create, 0, sizeof(resp_create)); + + + ret = PVFS_sys_lookup(fs_id, pvfs_name, + &(pvfs2_fs->credentials), &resp_lookup, PVFS2_LOOKUP_LINK_FOLLOW); + if ( ret == (-PVFS_ENOENT)) { + if (access_mode & ADIO_CREATE) { + ret = PVFS_sys_getparent(fs_id, pvfs_name, + &(pvfs2_fs->credentials), &resp_getparent); + if (ret < 0) { + FPRINTF(stderr, "pvfs_sys_getparent returns with %d\n", ret); + o_status->error = ret; + return; + } + + /* Set the distribution strip size if specified */ + if (0 < strip_size) { + /* Note that the distribution is hardcoded here */ + dist = PVFS_sys_dist_lookup("simple_stripe"); + ret = PVFS_sys_dist_setparam(dist, + "strip_size", + &strip_size); + if (ret < 0) + { + FPRINTF(stderr, + "pvfs_sys_dist_setparam returns with %d\n", ret); + o_status->error = ret; + } + } + + /* Perform file creation */ +#ifdef HAVE_PVFS2_CREATE_WITHOUT_LAYOUT + ret = PVFS_sys_create(resp_getparent.basename, + resp_getparent.parent_ref, attribs, + &(pvfs2_fs->credentials), dist, &resp_create); +#else + ret = PVFS_sys_create(resp_getparent.basename, + resp_getparent.parent_ref, attribs, + &(pvfs2_fs->credentials), dist, NULL, &resp_create); +#endif + + /* if many creates are happening in this directory, the earlier + * sys_lookup may have returned ENOENT, but the sys_create could + * return EEXISTS. That means the file has been created anyway, so + * less work for us and we can just open it up and return the + * handle */ + if (ret == (-PVFS_EEXIST)) { + ret = PVFS_sys_lookup(fs_id, pvfs_name, + &(pvfs2_fs->credentials), &resp_lookup, + PVFS2_LOOKUP_LINK_FOLLOW); + if ( ret < 0 ) { + o_status->error = ret; + return; + } + o_status->error = ret; + o_status->object_ref = resp_lookup.ref; + return; + } + o_status->object_ref = resp_create.ref; + } else { + FPRINTF(stderr, "cannot create file without MPI_MODE_CREATE\n"); + o_status->error = ret; + return; + } + } else if (access_mode & ADIO_EXCL) { + /* lookup should not succeed if opened with EXCL */ + o_status->error = -PVFS_EEXIST; + return; + } else { + o_status->object_ref = resp_lookup.ref; + } + o_status->error = ret; + return; + +} + + +/* ADIOI_PVFS2_Open: + * one process opens (or creates) the file, then broadcasts the result to the + * remaining processors. + * + * ADIO_Open used to perform an optimization when MPI_MODE_CREATE (and before + * that, MPI_MODE_EXCL) was set. Because PVFS2 handles file lookup and + * creation more scalably than other file systems, ADIO_Open now skips any + * special handling when CREATE is set. */ +void ADIOI_PVFS2_Open(ADIO_File fd, int *error_code) +{ + int rank, ret; + PVFS_fs_id cur_fs; + static char myname[] = "ADIOI_PVFS2_OPEN"; + char pvfs_path[PVFS_NAME_MAX] = {0}; + + ADIOI_PVFS2_fs *pvfs2_fs; + + /* since one process is doing the open, that means one process is also + * doing the error checking. define a struct for both the object reference + * and the error code to broadcast to all the processors */ + + open_status o_status = {0, {0, 0}}; + MPI_Datatype open_status_type; + MPI_Datatype types[2] = {MPI_INT, MPI_BYTE}; + int lens[2] = {1, sizeof(PVFS_object_ref)}; + MPI_Aint offsets[2]; + + pvfs2_fs = (ADIOI_PVFS2_fs *) ADIOI_Malloc(sizeof(ADIOI_PVFS2_fs)); + + /* --BEGIN ERROR HANDLING-- */ + if (pvfs2_fs == NULL) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_UNKNOWN, + "Error allocating memory", 0); + return; + } + /* --END ERROR HANDLING-- */ + + MPI_Comm_rank(fd->comm, &rank); + + ADIOI_PVFS2_Init(error_code); + if (*error_code != MPI_SUCCESS) + { + /* ADIOI_PVFS2_INIT handles creating error codes on its own */ + return; + } + + /* currently everyone gets their own credentials */ + ADIOI_PVFS2_makecredentials(&(pvfs2_fs->credentials)); + + /* one process resolves name and will later bcast to others */ +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_a, 0, NULL ); +#endif + if (rank == fd->hints->ranklist[0] && fd->fs_ptr == NULL) { + /* given the filename, figure out which pvfs filesystem it is on */ + ret = PVFS_util_resolve(fd->filename, &cur_fs, + pvfs_path, PVFS_NAME_MAX); + if (ret < 0 ) { + PVFS_perror("PVFS_util_resolve", ret); + /* TODO: pick a good error for this */ + o_status.error = -1; + } else { + fake_an_open(cur_fs, pvfs_path, + fd->access_mode, fd->hints->striping_factor, + fd->hints->striping_unit, + pvfs2_fs, &o_status); + } + + /* store credentials and object reference in fd */ + pvfs2_fs->object_ref = o_status.object_ref; + fd->fs_ptr = pvfs2_fs; + } +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_b, 0, NULL ); +#endif + + /* broadcast status and (possibly valid) object reference */ + MPI_Address(&o_status.error, &offsets[0]); + MPI_Address(&o_status.object_ref, &offsets[1]); + + MPI_Type_struct(2, lens, offsets, types, &open_status_type); + MPI_Type_commit(&open_status_type); + + /* Assertion: if we hit this Bcast, then all processes collectively + * called this open. + * + * That's because deferred open never happens with PVFS2. + */ + MPI_Bcast(MPI_BOTTOM, 1, open_status_type, fd->hints->ranklist[0], + fd->comm); + MPI_Type_free(&open_status_type); + + /* --BEGIN ERROR HANDLING-- */ + if (o_status.error != 0) + { + ADIOI_Free(pvfs2_fs); + fd->fs_ptr = NULL; + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(o_status.error), + "Unknown error", 0); + /* TODO: FIX STRING */ + return; + } + /* --END ERROR HANDLING-- */ + + pvfs2_fs->object_ref = o_status.object_ref; + fd->fs_ptr = pvfs2_fs; + + *error_code = MPI_SUCCESS; + return; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_read.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_read.c new file mode 100644 index 0000000000..007b4dc393 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_read.c @@ -0,0 +1,169 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "ad_pvfs2.h" +#include "ad_pvfs2_io.h" +#include "ad_pvfs2_common.h" + +void ADIOI_PVFS2_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 ret; + MPI_Count datatype_size, len; + PVFS_Request file_req, mem_req; + PVFS_sysresp_io resp_io; + ADIOI_PVFS2_fs *pvfs_fs; + static char myname[] = "ADIOI_PVFS2_READCONTIG"; + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + ret = PVFS_Request_contiguous(len, PVFS_BYTE, &mem_req); + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in pvfs_request_contig (memory)", 0); + return; + } + /* --END ERROR HANDLING-- */ + + ret = PVFS_Request_contiguous(len, PVFS_BYTE, &file_req); + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in pvfs_request_contig (file)", 0); + return; + } + /* --END ERROR HANDLING-- */ + + if (file_ptr_type == ADIO_INDIVIDUAL) { + /* copy individual file pointer into offset variable, continue */ + offset = fd->fp_ind; + } + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); +#endif + ret = PVFS_sys_read(pvfs_fs->object_ref, file_req, offset, buf, + mem_req, &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0 ) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_read", 0); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind += (int) resp_io.total_completed; + /* TODO: WHY THE INT CAST? */ + } + fd->fp_sys_posn = offset + (int)resp_io.total_completed; + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, resp_io.total_completed); +#endif + + *error_code = MPI_SUCCESS; +fn_exit: + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + return; +} + +static int ADIOI_PVFS2_ReadStridedListIO(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + return ADIOI_PVFS2_StridedListIO(fd, buf, count, + datatype, file_ptr_type, + offset, status, + error_code, READ); +} + +static int ADIOI_PVFS2_ReadStridedDtypeIO(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + return ADIOI_PVFS2_StridedDtypeIO(fd, buf, count, + datatype, file_ptr_type, + offset, status, error_code, + READ); +} + +void ADIOI_PVFS2_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ + /* four ways (to date) that we can carry out strided i/o accesses: + * - naive posix + * - 'true' Datatype (from avery) + * - new List I/O (from avery) + * - classic List I/O (the one that's always been in ROMIO) + * I imagine we'll keep Datatype as an optional optimization, and afer a + * release or two promote it to the default + */ + int ret = -1; + + if (fd->hints->fs_hints.pvfs2.posix_read == ADIOI_HINT_ENABLE) { + ADIOI_GEN_ReadStrided(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + return; + } + if (fd->hints->fs_hints.pvfs2.dtype_read == ADIOI_HINT_ENABLE) { + ret = ADIOI_PVFS2_ReadStridedDtypeIO(fd, buf, count, + datatype, file_ptr_type, + offset, status, error_code); + + /* Fall back to list I/O if datatype I/O didn't work */ + if (ret != 0) + { + fprintf(stderr, + "Falling back to list I/O since datatype I/O failed\n"); + ret = ADIOI_PVFS2_ReadStridedListIO(fd, buf, count, + datatype, file_ptr_type, + offset, status, error_code); + } + return; + } + if (fd->hints->fs_hints.pvfs2.listio_read == ADIOI_HINT_ENABLE) { + ret = ADIOI_PVFS2_ReadStridedListIO(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + return; + } + /* Use classic list I/O if no hints given base case */ + + ADIOI_PVFS2_OldReadStrided(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + return; +} + + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_read_list_classic.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_read_list_classic.c new file mode 100644 index 0000000000..2aee893332 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_read_list_classic.c @@ -0,0 +1,913 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "ad_pvfs2.h" + +#include "ad_pvfs2_common.h" + +void ADIOI_PVFS2_OldReadStrided(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 sum, n_etypes_in_filetype, size_in_filetype; + MPI_Count bufsize; + int n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0; + 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 off, disp, start_off, initial_off; + int flag, st_frd_size, st_n_filetypes; + + int mem_list_count, file_list_count; + PVFS_size *mem_offsets; + int64_t *file_offsets; + int *mem_lengths; + int32_t *file_lengths; + int total_blks_to_read; + + int max_mem_list, max_file_list; + + int b_blks_read; + int f_data_read; + int size_read=0, n_read_lists, extra_blks; + + int end_brd_size, end_frd_size; + int start_k, start_j, new_file_read, new_buffer_read; + int start_mem_offset; + PVFS_Request mem_req, file_req; + ADIOI_PVFS2_fs * pvfs_fs; + PVFS_sysresp_io resp_io; + int err_flag=0; + MPI_Offset total_bytes_read = 0; + static char myname[] = "ADIOI_PVFS2_ReadStrided"; + +#define MAX_ARRAY_SIZE 64 + + *error_code = MPI_SUCCESS; /* changed below if error */ + + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + /* the HDF5 tests showed a bug in this list processing code (see many many + * lines down below). We added a workaround, but common HDF5 file types + * are actually contiguous and do not need the expensive workarond */ + if (!filetype_is_contig) { + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + if (flat_file->count == 1 && !buftype_is_contig) + filetype_is_contig = 1; + } + + 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; + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + if (!buftype_is_contig && filetype_is_contig) { + +/* noncontiguous in memory, contiguous in file. */ + int64_t file_offset; + int32_t file_length; + + 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; + + file_list_count = 1; + file_offset = off; + file_length = 0; + total_blks_to_read = count*flat_buf->count; + b_blks_read = 0; + + /* allocate arrays according to max usage */ + if (total_blks_to_read > MAX_ARRAY_SIZE) + mem_list_count = MAX_ARRAY_SIZE; + else mem_list_count = total_blks_to_read; + mem_offsets = (PVFS_size*)ADIOI_Malloc(mem_list_count*sizeof(PVFS_size)); + mem_lengths = (int*)ADIOI_Malloc(mem_list_count*sizeof(int)); + + /* TODO: CHECK RESULTS OF MEMORY ALLOCATION */ + + j = 0; + /* step through each block in memory, filling memory arrays */ + while (b_blks_read < total_blks_to_read) { + for (i=0; icount; i++) { + mem_offsets[b_blks_read % MAX_ARRAY_SIZE] = + /* TODO: fix this compiler warning */ + ((PVFS_size)buf + j*buftype_extent + flat_buf->indices[i]); + mem_lengths[b_blks_read % MAX_ARRAY_SIZE] = + flat_buf->blocklens[i]; + file_length += flat_buf->blocklens[i]; + b_blks_read++; + if (!(b_blks_read % MAX_ARRAY_SIZE) || + (b_blks_read == total_blks_to_read)) { + + /* in the case of the last read list call, + adjust mem_list_count */ + if (b_blks_read == total_blks_to_read) { + mem_list_count = total_blks_to_read % MAX_ARRAY_SIZE; + /* in case last read list call fills max arrays */ + if (!mem_list_count) mem_list_count = MAX_ARRAY_SIZE; + } + err_flag = PVFS_Request_hindexed(mem_list_count, + mem_lengths, mem_offsets, PVFS_BYTE, &mem_req); + if (err_flag < 0) break; + err_flag = PVFS_Request_contiguous(file_length, + PVFS_BYTE, &file_req); + if (err_flag < 0) break; +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); +#endif + err_flag = PVFS_sys_read(pvfs_fs->object_ref, file_req, + file_offset, PVFS_BOTTOM, mem_req, + &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_sys_read", 0); + goto error_state; + } + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + total_bytes_read += resp_io.total_completed; + /* --END ERROR HANDLING-- */ + + /* in the case of error or the last read list call, + * leave here */ + if (err_flag || b_blks_read == total_blks_to_read) break; + + file_offset += file_length; + file_length = 0; + } + } /* for (i=0; icount; i++) */ + j++; + } /* while (b_blks_read < total_blks_to_read) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + + if (file_ptr_type == ADIO_INDIVIDUAL) + fd->fp_ind += total_bytes_read; + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); + /* This isa temporary way of filling in status. The right way is to + keep tracke of how much data was actually read adn placed in buf + by ADIOI_BUFFERED_READ. */ +#endif + ADIOI_Delete_flattened(datatype); + + return; + } /* if (!buftype_is_contig && filetype_is_contig) */ + + /* know file is noncontiguous from above */ + /* 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; + initial_off = offset; + + + /* for each case - ADIO_Individual pointer or explicit, find the file + offset in bytes (offset), n_filetypes (how many filetypes into + file to start), frd_size (remaining amount of data in present + file block), and st_index (start point in terms of blocks in + starting filetype) */ + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; /* in bytes */ + n_filetypes = -1; + flag = 0; + while (!flag) { + n_filetypes++; + for (i=0; icount; 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; + } + } + } /* while (!flag) */ + } /* if (file_ptr_type == ADIO_INDIVIDUAL) */ + 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; icount; 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; + } /* else [file_ptr_type != ADIO_INDIVIDUAL] */ + + start_off = offset; + st_frd_size = frd_size; + st_n_filetypes = n_filetypes; + + if (buftype_is_contig && !filetype_is_contig) { + +/* contiguous in memory, noncontiguous in file. should be the most + common case. */ + + int mem_length=0; + intptr_t mem_offset; + + i = 0; + j = st_index; + n_filetypes = st_n_filetypes; + + mem_list_count = 1; + + /* determine how many blocks in file to read */ + f_data_read = ADIOI_MIN(st_frd_size, bufsize); + total_blks_to_read = 1; + if (j < (flat_file->count-1)) j++; + else { + j = 0; + n_filetypes++; + } + while (f_data_read < bufsize) { + f_data_read += flat_file->blocklens[j]; + total_blks_to_read++; + if (j<(flat_file->count-1)) j++; + else j = 0; + } + + j = st_index; + n_filetypes = st_n_filetypes; + n_read_lists = total_blks_to_read/MAX_ARRAY_SIZE; + extra_blks = total_blks_to_read%MAX_ARRAY_SIZE; + + mem_offset = (intptr_t)buf; + mem_lengths = 0; + + /* if at least one full readlist, allocate file arrays + at max array size and don't free until very end */ + if (n_read_lists) { + file_offsets = (int64_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int64_t)); + file_lengths = (int32_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int32_t)); + } + /* if there's no full readlist allocate file arrays according + to needed size (extra_blks) */ + else { + file_offsets = (int64_t*)ADIOI_Malloc(extra_blks* + sizeof(int64_t)); + file_lengths = (int32_t*)ADIOI_Malloc(extra_blks* + sizeof(int32_t)); + } + + /* for file arrays that are of MAX_ARRAY_SIZE, build arrays */ + for (i=0; iindices[j]; + file_lengths[k] = flat_file->blocklens[j]; + mem_lengths += file_lengths[k]; + } + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kobject_ref, file_req, 0, + (void *)mem_offset, mem_req, + &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_sys_read", 0); + goto error_state; + } + /* --END ERROR HANDING-- */ + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + + total_bytes_read += resp_io.total_completed; + + mem_offset += mem_length; + mem_lengths = 0; + } /* for (i=0; iindices[j]; + if (k == (extra_blks - 1)) { + file_lengths[k] = bufsize - (int32_t) mem_lengths + - mem_offset + (int32_t) buf; + } + else file_lengths[k] = flat_file->blocklens[j]; + } /* if(i || k) */ + mem_lengths += file_lengths[k]; + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kobject_ref, file_req, 0, + (void *)mem_offset, mem_req, &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_sys_read", 0); + goto error_state; + } + /* --END ERROR HANDLING-- */ + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + total_bytes_read += resp_io.total_completed; + } + } + else { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + size_read = 0; + n_filetypes = st_n_filetypes; + frd_size = st_frd_size; + brd_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + max_mem_list = 0; + max_file_list = 0; + + /* run through and file max_file_list and max_mem_list so that you + can allocate the file and memory arrays less than MAX_ARRAY_SIZE + if possible */ + + while (size_read < bufsize) { + k = start_k; + new_buffer_read = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data read and data to be + read in the next immediate read list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k] + + size_read) > bufsize) { + end_brd_size = new_buffer_read + + flat_buf->blocklens[k] - (bufsize - size_read); + new_buffer_read = bufsize - size_read; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + else new_buffer_read = brd_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + j = start_j; + new_file_read = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_read < new_buffer_read)) { + if(file_list_count) { + if((new_file_read + flat_file->blocklens[j]) > + new_buffer_read) { + end_frd_size = new_buffer_read - new_file_read; + new_file_read = new_buffer_read; + j--; + } + else { + new_file_read += flat_file->blocklens[j]; + end_frd_size = flat_file->blocklens[j]; + } + } + else { + if (frd_size > new_buffer_read) { + new_file_read = new_buffer_read; + frd_size = new_file_read; + } + else new_file_read = frd_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_read < new_buffer_read) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_read = 0; + mem_list_count = 0; + while (new_buffer_read < new_file_read) { + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k]) > + new_file_read) { + end_brd_size = new_file_read - new_buffer_read; + new_buffer_read = new_file_read; + k--; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_read = brd_size; + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_read < new_file_read) */ + } /* if ((new_file_read < new_buffer_read) && (file_list_count + == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + + /* fakes filling the readlist arrays of lengths found above */ + k = start_k; + j = start_j; + for (i=0; iblocklens[k] == end_brd_size) + brd_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + brd_size = flat_buf->blocklens[k] - end_brd_size; + k--; + buf_count--; + } + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iblocklens[j] == end_frd_size) + frd_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + frd_size = flat_file->blocklens[j] - end_frd_size; + j--; + } + } + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; iblocklens[0] ) ) || + ((mem_list_count == 1) && + (new_buffer_read < flat_buf->blocklens[0]) ) || + ((file_list_count == MAX_ARRAY_SIZE) && + (new_file_read < flat_buf->blocklens[0]) ) || + ( (mem_list_count == MAX_ARRAY_SIZE) && + (new_buffer_read < flat_file->blocklens[0])) ) + { + + ADIOI_Delete_flattened(datatype); + ADIOI_GEN_ReadStrided_naive(fd, buf, count, datatype, + file_ptr_type, initial_off, status, error_code); + return; + } + + mem_offsets = (PVFS_size*)ADIOI_Malloc(max_mem_list*sizeof(PVFS_size)); + mem_lengths = (int *)ADIOI_Malloc(max_mem_list*sizeof(int)); + file_offsets = (int64_t *)ADIOI_Malloc(max_file_list*sizeof(int64_t)); + file_lengths = (int32_t *)ADIOI_Malloc(max_file_list*sizeof(int32_t)); + + size_read = 0; + n_filetypes = st_n_filetypes; + frd_size = st_frd_size; + brd_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + + /* this section calculates mem_list_count and file_list_count + and also finds the possibly odd sized last array elements + in new_frd_size and new_brd_size */ + + while (size_read < bufsize) { + k = start_k; + new_buffer_read = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data read and data to be + read in the next immediate read list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k] + + size_read) > bufsize) { + end_brd_size = new_buffer_read + + flat_buf->blocklens[k] - (bufsize - size_read); + new_buffer_read = bufsize - size_read; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + else new_buffer_read = brd_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + j = start_j; + new_file_read = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_read < new_buffer_read)) { + if(file_list_count) { + if((new_file_read + flat_file->blocklens[j]) > + new_buffer_read) { + end_frd_size = new_buffer_read - new_file_read; + new_file_read = new_buffer_read; + j--; + } + else { + new_file_read += flat_file->blocklens[j]; + end_frd_size = flat_file->blocklens[j]; + } + } + else { + if (frd_size > new_buffer_read) { + new_file_read = new_buffer_read; + frd_size = new_file_read; + } + else new_file_read = frd_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_read < new_buffer_read) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_read = 0; + mem_list_count = 0; + while (new_buffer_read < new_file_read) { + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k]) > + new_file_read) { + end_brd_size = new_file_read - new_buffer_read; + new_buffer_read = new_file_read; + k--; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_read = brd_size; + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_read < new_file_read) */ + } /* if ((new_file_read < new_buffer_read) && (file_list_count + == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + + /* fills the allocated readlist arrays */ + k = start_k; + j = start_j; + for (i=0; icount) + + (int)flat_buf->indices[k]); + if(!i) { + mem_lengths[0] = brd_size; + mem_offsets[0] += flat_buf->blocklens[k] - brd_size; + } + else { + if (i == (mem_list_count - 1)) { + mem_lengths[i] = end_brd_size; + if (flat_buf->blocklens[k] == end_brd_size) + brd_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + brd_size = flat_buf->blocklens[k] - end_brd_size; + k--; + buf_count--; + } + } + else { + mem_lengths[i] = flat_buf->blocklens[k]; + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iindices[j] + + ((ADIO_Offset)n_filetypes) * filetype_extent; + if (!i) { + file_lengths[0] = frd_size; + file_offsets[0] += flat_file->blocklens[j] - frd_size; + } + else { + if (i == (file_list_count - 1)) { + file_lengths[i] = end_frd_size; + if (flat_file->blocklens[j] == end_frd_size) + frd_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + frd_size = flat_file->blocklens[j] - end_frd_size; + j--; + } + } + else file_lengths[i] = flat_file->blocklens[j]; + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; iobject_ref, file_req, 0, + PVFS_BOTTOM, mem_req, &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_sys_read", 0); + } + /* --END ERROR HANDLING-- */ + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + total_bytes_read += resp_io.total_completed; + size_read += new_buffer_read; + start_k = k; + start_j = j; + } /* while (size_read < bufsize) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + } + /* Other ADIO routines will convert absolute bytes into counts of datatypes */ + /* when incrementing fp_ind, need to also take into account the file type: + * consider an N-element 1-d subarray with a lb and ub: ( |---xxxxx-----| + * if we wrote N elements, offset needs to point at beginning of type, not + * at empty region at offset N+1) + * + * As we discussed on mpich-discuss in may/june 2009, the code below might + * look wierd, but by putting fp_ind at the last byte written, the next + * time we run through the strided code we'll update the fp_ind to the + * right location. */ + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind = file_offsets[file_list_count-1]+ + file_lengths[file_list_count-1]; + } + + ADIOI_Free(file_offsets); + ADIOI_Free(file_lengths); + + if (err_flag == 0) *error_code = MPI_SUCCESS; + +error_state: + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, 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 + by ADIOI_BUFFERED_READ. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} + diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_resize.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_resize.c new file mode 100644 index 0000000000..db219db0fd --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_resize.c @@ -0,0 +1,56 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs2.h" +#include "ad_pvfs2_common.h" + +/* as with ADIOI_PVFS2_Flush, implement the resize operation in a scalable + * manner. one process does the work, then broadcasts the result to everyone + * else. fortunately, this operation is defined to be collective */ +void ADIOI_PVFS2_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int ret, rank; + ADIOI_PVFS2_fs *pvfs_fs; + static char myname[] = "ADIOI_PVFS2_RESIZE"; + + *error_code = MPI_SUCCESS; + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + MPI_Comm_rank(fd->comm, &rank); + + /* We desginate one node in the communicator to be an 'io_worker' in + * ADIO_Open. This node can perform operations on files and then + * inform the other nodes of the result */ + + /* MPI-IO semantics treat conflicting MPI_File_set_size requests the + * same as conflicting write requests. Thus, a resize from one + * process does not have to be visible to the other processes until a + * syncronization point is reached */ + + if (rank == fd->hints->ranklist[0]) { + ret = PVFS_sys_truncate(pvfs_fs->object_ref, + size, &(pvfs_fs->credentials)); + MPI_Bcast(&ret, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + } else { + MPI_Bcast(&ret, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + } + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_truncate", 0); + return; + } + /* --END ERROR HANDLING-- */ +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_write.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_write.c new file mode 100644 index 0000000000..93e142bb68 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_write.c @@ -0,0 +1,182 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_pvfs2.h" +#include "adio_extern.h" +#include "ad_pvfs2_io.h" +#include "ad_pvfs2_common.h" + +void ADIOI_PVFS2_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 ret; + MPI_Count datatype_size, len; + PVFS_Request file_req, mem_req; + PVFS_sysresp_io resp_io; + ADIOI_PVFS2_fs *pvfs_fs; + static char myname[] = "ADIOI_PVFS2_WRITECONTIG"; + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + ret = PVFS_Request_contiguous(len, PVFS_BYTE, &mem_req); + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_Request_contiguous (memory)", 0); + return; + } + /* --END ERROR HANDLING-- */ + + ret = PVFS_Request_contiguous(len, PVFS_BYTE, &file_req); + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_Request_contiguous (file)", 0); + return; + } + /* --END ERROR HANDLING-- */ + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + ret = PVFS_sys_write(pvfs_fs->object_ref, file_req, offset, (void *)buf, + mem_req, &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_write", 0); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + fd->fp_sys_posn = offset + (int) resp_io.total_completed; + } + else { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + ret = PVFS_sys_write(pvfs_fs->object_ref, file_req, fd->fp_ind, (void *)buf, + mem_req, &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(ret), + "Error in PVFS_sys_write", 0); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + fd->fp_ind += (int)resp_io.total_completed; + fd->fp_sys_posn = fd->fp_ind; + } +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, resp_io.total_completed); +#endif + *error_code = MPI_SUCCESS; +fn_exit: + PVFS_Request_free(&file_req); + PVFS_Request_free(&mem_req); + return; +} + +int ADIOI_PVFS2_WriteStridedListIO(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + return ADIOI_PVFS2_StridedListIO(fd, (void *)buf, count, + datatype, file_ptr_type, + offset, status, + error_code, WRITE); +} + +int ADIOI_PVFS2_WriteStridedDtypeIO(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + return ADIOI_PVFS2_StridedDtypeIO(fd, (void *)buf, count, + datatype, file_ptr_type, + offset, status, error_code, + WRITE); +} + + +void ADIOI_PVFS2_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) +{ + /* four ways (to date) that we can carry out strided i/o accesses: + * - naive posix + * - 'true' Datatype (from avery) + * - new List I/O (from avery) + * - classic List I/O (the one that's always been in ROMIO) + * I imagine we'll keep Datatype as an optional optimization, and afer a + * release or two promote it to the default + */ + + /* a lot of near-duplication from ADIOI_PVFS2_ReadStrided: for + * debugging/testing it's helpful to be able to turn on and off these + * optimizations separately for the read and write cases */ + int ret = -1; + if ( fd->hints->fs_hints.pvfs2.posix_write == ADIOI_HINT_ENABLE) { + ADIOI_GEN_WriteStrided_naive(fd, buf, count, + datatype, file_ptr_type, + offset, status, error_code); + return; + } + if ( fd->hints->fs_hints.pvfs2.dtype_write == ADIOI_HINT_ENABLE) { + ret = ADIOI_PVFS2_WriteStridedDtypeIO(fd, buf, count, + datatype, file_ptr_type, + offset, status, error_code); + + /* Fall back to list I/O if datatype I/O didn't work */ + if (ret != 0) + { + fprintf(stderr, + "Falling back to list I/O since datatype I/O failed\n"); + ret = ADIOI_PVFS2_WriteStridedListIO(fd, buf, count, + datatype, file_ptr_type, + offset, status, error_code); + } + return; + } + /* Use list I/O in the base case */ + if (fd->hints->fs_hints.pvfs2.listio_write == ADIOI_HINT_ENABLE) { + ret = ADIOI_PVFS2_WriteStridedListIO(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + return; + } + + /* Use classic list I/O if no hints given base case */ + ADIOI_PVFS2_OldWriteStrided(fd, buf, count, datatype, + file_ptr_type, offset, status, error_code); + return; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_write_list_classic.c b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_write_list_classic.c new file mode 100644 index 0000000000..f51bf7932d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_pvfs2/ad_pvfs2_write_list_classic.c @@ -0,0 +1,967 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "ad_pvfs2.h" + +#include "ad_pvfs2_common.h" + +void ADIOI_PVFS2_OldWriteStrided(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + /* as with all the other WriteStrided functions, offset is in units of + * etype relative to the filetype */ + + /* Since PVFS2 does not support file locking, can't do buffered writes + as on Unix */ + + ADIOI_Flatlist_node *flat_buf, *flat_file; + int i, j, k, bwr_size, fwr_size=0, st_index=0; + int sum, n_etypes_in_filetype, size_in_filetype; + MPI_Count bufsize; + int n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0; + 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 off, disp, start_off, initial_off; + int flag, st_fwr_size, st_n_filetypes; + int err_flag=0; + + int mem_list_count, file_list_count; + PVFS_size * mem_offsets; + int64_t *file_offsets; + int *mem_lengths; + int32_t *file_lengths; + int total_blks_to_write; + + int max_mem_list, max_file_list; + + int b_blks_wrote; + int f_data_wrote; + int size_wrote=0, n_write_lists, extra_blks; + + int end_bwr_size, end_fwr_size; + int start_k, start_j, new_file_write, new_buffer_write; + int start_mem_offset; + PVFS_Request mem_req, file_req; + ADIOI_PVFS2_fs * pvfs_fs; + PVFS_sysresp_io resp_io; + MPI_Offset total_bytes_written=0; + static char myname[] = "ADIOI_PVFS2_WRITESTRIDED"; + + /* note: don't increase this: several parts of PVFS2 now + * assume this limit*/ +#define MAX_ARRAY_SIZE 64 + + /* --BEGIN ERROR HANDLING-- */ + if (fd->atomicity) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "Atomic noncontiguous writes are not supported by PVFS2", 0); + return; + } + /* --END ERROR HANDLING-- */ + + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + /* the HDF5 tests showed a bug in this list processing code (see many many + * lines down below). We added a workaround, but common HDF5 file types + * are actually contiguous and do not need the expensive workarond */ + if (!filetype_is_contig) { + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + if (flat_file->count == 1 && !buftype_is_contig) + filetype_is_contig = 1; + } + + 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; + + pvfs_fs = (ADIOI_PVFS2_fs*)fd->fs_ptr; + + if (!buftype_is_contig && filetype_is_contig) { + +/* noncontiguous in memory, contiguous in file. */ + int64_t file_offset; + int32_t file_length; + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + etype_size * offset; + } + else off = fd->fp_ind; + + file_list_count = 1; + file_offset = off; + file_length = 0; + total_blks_to_write = count*flat_buf->count; + b_blks_wrote = 0; + + /* allocate arrays according to max usage */ + if (total_blks_to_write > MAX_ARRAY_SIZE) + mem_list_count = MAX_ARRAY_SIZE; + else mem_list_count = total_blks_to_write; + mem_offsets = (PVFS_size*)ADIOI_Malloc(mem_list_count*sizeof(PVFS_size)); + mem_lengths = (int*)ADIOI_Malloc(mem_list_count*sizeof(int)); + + j = 0; + /* step through each block in memory, filling memory arrays */ + while (b_blks_wrote < total_blks_to_write) { + for (i=0; icount; i++) { + mem_offsets[b_blks_wrote % MAX_ARRAY_SIZE] = + /* TODO: fix this warning by casting to an integer that's + * the same size as a char * and /then/ casting to + * PVFS_size */ + ((PVFS_size)buf + j*buftype_extent + flat_buf->indices[i]); + mem_lengths[b_blks_wrote % MAX_ARRAY_SIZE] = + flat_buf->blocklens[i]; + file_length += flat_buf->blocklens[i]; + b_blks_wrote++; + if (!(b_blks_wrote % MAX_ARRAY_SIZE) || + (b_blks_wrote == total_blks_to_write)) { + + /* in the case of the last write list call, + adjust mem_list_count */ + if (b_blks_wrote == total_blks_to_write) { + mem_list_count = total_blks_to_write % MAX_ARRAY_SIZE; + /* in case last write list call fills max arrays */ + if (!mem_list_count) mem_list_count = MAX_ARRAY_SIZE; + } + err_flag = PVFS_Request_hindexed(mem_list_count, + mem_lengths, mem_offsets, + PVFS_BYTE, &mem_req); + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_Request_hindexed (memory)", 0); + break; + } + /* --END ERROR HANDLING-- */ + + err_flag = PVFS_Request_contiguous(file_length, + PVFS_BYTE, &file_req); + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_Request_contiguous (file)", 0); + break; + } + /* --END ERROR HANDLING-- */ + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + err_flag = PVFS_sys_write(pvfs_fs->object_ref, file_req, + file_offset, PVFS_BOTTOM, + mem_req, + &(pvfs_fs->credentials), + &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + total_bytes_written += resp_io.total_completed; + + /* in the case of error or the last write list call, + * leave here */ + /* --BEGIN ERROR HANDLING-- */ + if (err_flag) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_sys_write", 0); + break; + } + /* --END ERROR HANDLING-- */ + if (b_blks_wrote == total_blks_to_write) break; + + file_offset += file_length; + file_length = 0; + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + } + } /* for (i=0; icount; i++) */ + j++; + } /* while (b_blks_wrote < total_blks_to_write) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + + if (file_ptr_type == ADIO_INDIVIDUAL) + fd->fp_ind += total_bytes_written; + + if (!err_flag) *error_code = MPI_SUCCESS; + + fd->fp_sys_posn = -1; /* clear this. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + ADIOI_Delete_flattened(datatype); + return; + } /* if (!buftype_is_contig && filetype_is_contig) */ + + /* already know that file is noncontiguous from above */ + /* 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; + initial_off = offset; + + /* for each case - ADIO_Individual pointer or explicit, find offset + (file offset in bytes), n_filetypes (how many filetypes into file + to start), fwr_size (remaining amount of data in present file + block), and st_index (start point in terms of blocks in starting + filetype) */ + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; /* in bytes */ + n_filetypes = -1; + flag = 0; + while (!flag) { + n_filetypes++; + for (i=0; icount; i++) { + if (disp + flat_file->indices[i] + + ((ADIO_Offset) n_filetypes)*filetype_extent + + flat_file->blocklens[i] >= offset) { + st_index = i; + fwr_size = disp + flat_file->indices[i] + + ((ADIO_Offset) n_filetypes)*filetype_extent + + flat_file->blocklens[i] - offset; + flag = 1; + break; + } + } + } /* while (!flag) */ + } /* if (file_ptr_type == ADIO_INDIVIDUAL) */ + 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; icount; 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; + } /* else [file_ptr_type != ADIO_INDIVIDUAL] */ + + start_off = offset; + st_fwr_size = fwr_size; + st_n_filetypes = n_filetypes; + + if (buftype_is_contig && !filetype_is_contig) { + +/* contiguous in memory, noncontiguous in file. should be the most + common case. */ + + int mem_length; + intptr_t mem_offset; + + i = 0; + j = st_index; + off = offset; + n_filetypes = st_n_filetypes; + + mem_list_count = 1; + + /* determine how many blocks in file to write */ + f_data_wrote = ADIOI_MIN(st_fwr_size, bufsize); + total_blks_to_write = 1; + if (j < (flat_file->count -1)) j++; + else { + j = 0; + n_filetypes++; + } + while (f_data_wrote < bufsize) { + f_data_wrote += flat_file->blocklens[j]; + total_blks_to_write++; + if (j<(flat_file->count-1)) j++; + else j = 0; + } + + j = st_index; + n_filetypes = st_n_filetypes; + n_write_lists = total_blks_to_write/MAX_ARRAY_SIZE; + extra_blks = total_blks_to_write%MAX_ARRAY_SIZE; + + mem_offset = (intptr_t) buf; + mem_length = 0; + + /* if at least one full writelist, allocate file arrays + at max array size and don't free until very end */ + if (n_write_lists) { + file_offsets = (int64_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int64_t)); + file_lengths = (int32_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int32_t)); + } + /* if there's no full writelist allocate file arrays according + to needed size (extra_blks) */ + else { + file_offsets = (int64_t*)ADIOI_Malloc(extra_blks* + sizeof(int64_t)); + file_lengths = (int32_t*)ADIOI_Malloc(extra_blks* + sizeof(int32_t)); + } + + /* for file arrays that are of MAX_ARRAY_SIZE, build arrays */ + for (i=0; iindices[j]; + file_lengths[k] = flat_file->blocklens[j]; + mem_length += file_lengths[k]; + } + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kobject_ref, file_req, 0, + (void *)mem_offset, mem_req, + &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_sys_write", 0); + goto error_state; + } + /* --END ERROR HANDLING-- */ + total_bytes_written += resp_io.total_completed; + + mem_offset += mem_length; + mem_lengths = 0; + PVFS_Request_free(&file_req); + PVFS_Request_free(&mem_req); + + } /* for (i=0; iindices[j]; + if (k == (extra_blks - 1)) { + file_lengths[k] = bufsize - (int32_t) mem_lengths + - mem_offset + (int32_t) buf; + } + else file_lengths[k] = flat_file->blocklens[j]; + } /* if(i || k) */ + mem_lengths += file_lengths[k]; + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kobject_ref, file_req, 0, + (void *)mem_offset, mem_req, + &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_sys_write", 0); + goto error_state; + } + /* --END ERROR HANDLING-- */ + total_bytes_written += resp_io.total_completed; + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + } + } + else { + /* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + size_wrote = 0; + n_filetypes = st_n_filetypes; + fwr_size = st_fwr_size; + bwr_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + max_mem_list = 0; + max_file_list = 0; + + /* run through and file max_file_list and max_mem_list so that you + can allocate the file and memory arrays less than MAX_ARRAY_SIZE + if possible */ + + while (size_wrote < bufsize) { + k = start_k; + new_buffer_write = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data written and data to be + written in the next immediate write list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k] + + size_wrote) > bufsize) { + end_bwr_size = new_buffer_write + + flat_buf->blocklens[k] - (bufsize - size_wrote); + new_buffer_write = bufsize - size_wrote; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + else new_buffer_write = bwr_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + j = start_j; + new_file_write = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_write < new_buffer_write)) { + if(file_list_count) { + if((new_file_write + flat_file->blocklens[j]) > + new_buffer_write) { + end_fwr_size = new_buffer_write - new_file_write; + new_file_write = new_buffer_write; + j--; + } + else { + new_file_write += flat_file->blocklens[j]; + end_fwr_size = flat_file->blocklens[j]; + } + } + else { + if (fwr_size > new_buffer_write) { + new_file_write = new_buffer_write; + fwr_size = new_file_write; + } + else new_file_write = fwr_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_write = 0; + mem_list_count = 0; + while (new_buffer_write < new_file_write) { + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k]) > + new_file_write) { + end_bwr_size = new_file_write - + new_buffer_write; + new_buffer_write = new_file_write; + k--; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_write = bwr_size; + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_write < new_file_write) */ + } /* if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + + /* fakes filling the writelist arrays of lengths found above */ + k = start_k; + j = start_j; + for (i=0; iblocklens[k] == end_bwr_size) + bwr_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + bwr_size = flat_buf->blocklens[k] - end_bwr_size; + k--; + buf_count--; + } + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iblocklens[j] == end_fwr_size) + fwr_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + fwr_size = flat_file->blocklens[j] - end_fwr_size; + j--; + } + } + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; iblocklens[0] ) ) || + ((mem_list_count == 1) && + (new_buffer_write < flat_buf->blocklens[0]) ) || + ((file_list_count == MAX_ARRAY_SIZE) && + (new_file_write < flat_buf->blocklens[0]) ) || + ( (mem_list_count == MAX_ARRAY_SIZE) && + (new_buffer_write < flat_file->blocklens[0])) ) + { + ADIOI_Delete_flattened(datatype); + ADIOI_GEN_WriteStrided_naive(fd, buf, count, datatype, + file_ptr_type, initial_off, status, error_code); + return; + } + + + mem_offsets = (PVFS_size*)ADIOI_Malloc(max_mem_list*sizeof(PVFS_size)); + mem_lengths = (int *)ADIOI_Malloc(max_mem_list*sizeof(int)); + file_offsets = (int64_t *)ADIOI_Malloc(max_file_list*sizeof(int64_t)); + file_lengths = (int32_t *)ADIOI_Malloc(max_file_list*sizeof(int32_t)); + + size_wrote = 0; + n_filetypes = st_n_filetypes; + fwr_size = st_fwr_size; + bwr_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + + /* this section calculates mem_list_count and file_list_count + and also finds the possibly odd sized last array elements + in new_fwr_size and new_bwr_size */ + + while (size_wrote < bufsize) { + k = start_k; + new_buffer_write = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data written and data to be + written in the next immediate write list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k] + + size_wrote) > bufsize) { + end_bwr_size = new_buffer_write + + flat_buf->blocklens[k] - (bufsize - size_wrote); + new_buffer_write = bufsize - size_wrote; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + else new_buffer_write = bwr_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + j = start_j; + new_file_write = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_write < new_buffer_write)) { + if(file_list_count) { + if((new_file_write + flat_file->blocklens[j]) > + new_buffer_write) { + end_fwr_size = new_buffer_write - new_file_write; + new_file_write = new_buffer_write; + j--; + } + else { + new_file_write += flat_file->blocklens[j]; + end_fwr_size = flat_file->blocklens[j]; + } + } + else { + if (fwr_size > new_buffer_write) { + new_file_write = new_buffer_write; + fwr_size = new_file_write; + } + else new_file_write = fwr_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_write = 0; + mem_list_count = 0; + while (new_buffer_write < new_file_write) { + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k]) > + new_file_write) { + end_bwr_size = new_file_write - + new_buffer_write; + new_buffer_write = new_file_write; + k--; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_write = bwr_size; + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_write < new_file_write) */ + } /* if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + + /* fills the allocated writelist arrays */ + k = start_k; + j = start_j; + for (i=0; icount) + + (int)flat_buf->indices[k]); + + if(!i) { + mem_lengths[0] = bwr_size; + mem_offsets[0] += flat_buf->blocklens[k] - bwr_size; + } + else { + if (i == (mem_list_count - 1)) { + mem_lengths[i] = end_bwr_size; + if (flat_buf->blocklens[k] == end_bwr_size) + bwr_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + bwr_size = flat_buf->blocklens[k] - end_bwr_size; + k--; + buf_count--; + } + } + else { + mem_lengths[i] = flat_buf->blocklens[k]; + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iindices[j] + + ((ADIO_Offset)n_filetypes) * filetype_extent; + if (!i) { + file_lengths[0] = fwr_size; + file_offsets[0] += flat_file->blocklens[j] - fwr_size; + } + else { + if (i == (file_list_count - 1)) { + file_lengths[i] = end_fwr_size; + if (flat_file->blocklens[j] == end_fwr_size) + fwr_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + fwr_size = flat_file->blocklens[j] - end_fwr_size; + j--; + } + } + else file_lengths[i] = flat_file->blocklens[j]; + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; iobject_ref, file_req, 0, + PVFS_BOTTOM, mem_req, + &(pvfs_fs->credentials), &resp_io); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_PVFS2_error_convert(err_flag), + "Error in PVFS_sys_write", 0); + goto error_state; + } + /* --END ERROR HANDLING-- */ + + size_wrote += new_buffer_write; + total_bytes_written += resp_io.total_completed; + start_k = k; + start_j = j; + PVFS_Request_free(&mem_req); + PVFS_Request_free(&file_req); + } /* while (size_wrote < bufsize) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + } + /* when incrementing fp_ind, need to also take into account the file type: + * consider an N-element 1-d subarray with a lb and ub: ( |---xxxxx-----| + * if we wrote N elements, offset needs to point at beginning of type, not + * at empty region at offset N+1). + * + * As we discussed on mpich-discuss in may/june 2009, the code below might + * look wierd, but by putting fp_ind at the last byte written, the next + * time we run through the strided code we'll update the fp_ind to the + * right location. */ + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind = file_offsets[file_list_count-1]+ + file_lengths[file_list_count-1]; + } + ADIOI_Free(file_offsets); + ADIOI_Free(file_lengths); + + *error_code = MPI_SUCCESS; + +error_state: + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_sfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_sfs/Makefile.mk new file mode 100644 index 0000000000..2db1ac26cb --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_sfs/Makefile.mk @@ -0,0 +1,19 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_SFS + +noinst_HEADERS += adio/ad_sfs/ad_sfs.h + +romio_other_sources += \ + adio/ad_sfs/ad_sfs_open.c \ + adio/ad_sfs/ad_sfs_fcntl.c \ + adio/ad_sfs/ad_sfs_flush.c \ + adio/ad_sfs/ad_sfs.c + +endif BUILD_AD_SFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_sfs/README b/ompi/mca/io/romio314/romio/adio/ad_sfs/README new file mode 100644 index 0000000000..933677b177 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_sfs/README @@ -0,0 +1 @@ +This code is no longer supported. diff --git a/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs.c b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs.c new file mode 100644 index 0000000000..929dfd97f7 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs.c @@ -0,0 +1,36 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_sfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_SFS_operations = { + ADIOI_SFS_Open, /* Open */ + ADIOI_GEN_ReadContig, /* ReadContig */ + ADIOI_GEN_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_SFS_Fcntl, /* Fcntl */ + ADIOI_GEN_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_GEN_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ + ADIOI_FAKE_IODone, /* ReadDone */ + ADIOI_FAKE_IODone, /* WriteDone */ + ADIOI_FAKE_IOComplete, /* ReadComplete */ + ADIOI_FAKE_IOComplete, /* WriteComplete */ + ADIOI_FAKE_IreadStrided, /* IreadStrided */ + ADIOI_FAKE_IwriteStrided, /* IwriteStrided */ + ADIOI_SFS_Flush, /* Flush */ + ADIOI_GEN_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs.h b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs.h new file mode 100644 index 0000000000..9f029f0558 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs.h @@ -0,0 +1,21 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_SFS_INCLUDE +#define AD_SFS_INCLUDE + +#include +#include +#include +#include "adio.h" + +void ADIOI_SFS_Open(ADIO_File fd, int *error_code); +void ADIOI_SFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIOI_SFS_Flush(ADIO_File fd, int *error_code); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs_fcntl.c new file mode 100644 index 0000000000..533e26a77b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs_fcntl.c @@ -0,0 +1,64 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_sfs.h" +#include "adio_extern.h" + +void ADIOI_SFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code) +{ + int i, ntimes, len; + ADIO_Offset curr_fsize, alloc_size, size, done; + ADIO_Status status; + char *buf; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_SFS_FCNTL"; +#endif + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + /* On SFS, I find that a write from one process, which changes + the file size, does not automatically make the new file size + visible to other processes. Therefore, a sync-barrier-sync is + needed. (Other processes are able to read the data written + though; only file size is returned incorrectly.) */ + + fsync(fd->fd_sys); + MPI_Barrier(fd->comm); + fsync(fd->fd_sys); + + fcntl_struct->fsize = llseek(fd->fd_sys, 0, SEEK_END); + if (fd->fp_sys_posn != -1) + llseek(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); + if (fcntl_struct->fsize == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-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); +#endif + } + else *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + ADIOI_GEN_Prealloc(fd, fcntl_struct->diskspace, error_code); + break; + + case ADIO_FCNTL_SET_ATOMICITY: + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + *error_code = MPI_SUCCESS; + break; + + default: + FPRINTF(stderr, "Unknown flag passed to ADIOI_SFS_Fcntl\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs_flush.c b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs_flush.c new file mode 100644 index 0000000000..8fc7e358cf --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs_flush.c @@ -0,0 +1,27 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_sfs.h" + +void ADIOI_SFS_Flush(ADIO_File fd, int *error_code) +{ +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_SFS_FLUSH"; +#endif + + /* there is no fsync on SX-4 */ +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-1 */ + *error_code = MPIR_Err_setmsg(MPI_ERR_UNSUPPORTED_OPERATION, 1, + myname, (char *) 0, (char *) 0); + ADIOI_Error(fd, *error_code, myname); +#endif +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs_open.c new file mode 100644 index 0000000000..ebeefdcbcb --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_sfs/ad_sfs_open.c @@ -0,0 +1,57 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_sfs.h" + +void ADIOI_SFS_Open(ADIO_File fd, int *error_code) +{ + int perm, old_mask, amode; +#ifndef PRINT_ERR_MSG + static char myname[] = "ADIOI_SFS_OPEN"; +#endif + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + fd->fd_sys = open(fd->filename, amode, perm); + fd->fd_direct = -1; + + if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND)) { + fd->fp_ind = llseek(fd->fd_sys, 0, SEEK_END); + fd->fp_sys_posn = fd->fp_ind; + } + + if (fd->fd_sys == -1) { +#ifdef MPICH + *error_code = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); +#elif defined(PRINT_ERR_MSG) + *error_code = MPI_ERR_UNKNOWN; +#else /* MPICH-1 */ + *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, + myname, "I/O Error", "%s", strerror(errno)); + ADIOI_Error(ADIO_FILE_NULL, *error_code, myname); +#endif + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_testfs/Makefile.mk new file mode 100644 index 0000000000..7f9c617217 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/Makefile.mk @@ -0,0 +1,32 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_TESTFS + +noinst_HEADERS += adio/ad_testfs/ad_testfs.h + +romio_other_sources += \ + adio/ad_testfs/ad_testfs_close.c \ + adio/ad_testfs/ad_testfs_read.c \ + adio/ad_testfs/ad_testfs_rdcoll.c \ + adio/ad_testfs/ad_testfs_wrcoll.c \ + adio/ad_testfs/ad_testfs_open.c \ + adio/ad_testfs/ad_testfs_write.c \ + adio/ad_testfs/ad_testfs_done.c \ + adio/ad_testfs/ad_testfs_fcntl.c \ + adio/ad_testfs/ad_testfs_iread.c \ + adio/ad_testfs/ad_testfs_iwrite.c \ + adio/ad_testfs/ad_testfs_wait.c \ + adio/ad_testfs/ad_testfs_flush.c \ + adio/ad_testfs/ad_testfs_seek.c \ + adio/ad_testfs/ad_testfs_resize.c \ + adio/ad_testfs/ad_testfs_hints.c \ + adio/ad_testfs/ad_testfs_delete.c \ + adio/ad_testfs/ad_testfs.c + +endif BUILD_AD_TESTFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs.c new file mode 100644 index 0000000000..6823468c70 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs.c @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_TESTFS_operations = { + ADIOI_TESTFS_Open, /* Open */ + ADIOI_GEN_OpenColl, /* OpenColl */ + ADIOI_TESTFS_ReadContig, /* ReadContig */ + ADIOI_TESTFS_WriteContig, /* WriteContig */ + ADIOI_TESTFS_ReadStridedColl, /* ReadStridedColl */ + ADIOI_TESTFS_WriteStridedColl, /* WriteStridedColl */ + ADIOI_TESTFS_SeekIndividual, /* SeekIndividual */ + ADIOI_TESTFS_Fcntl, /* Fcntl */ + ADIOI_TESTFS_SetInfo, /* SetInfo */ + ADIOI_TESTFS_ReadStrided, /* ReadStrided */ + ADIOI_TESTFS_WriteStrided, /* WriteStrided */ + ADIOI_TESTFS_Close, /* Close */ + ADIOI_TESTFS_IreadContig, /* IreadContig */ + ADIOI_TESTFS_IwriteContig, /* IwriteContig */ + ADIOI_TESTFS_ReadDone, /* ReadDone */ + ADIOI_TESTFS_WriteDone, /* WriteDone */ + ADIOI_TESTFS_ReadComplete, /* ReadComplete */ + ADIOI_TESTFS_WriteComplete, /* WriteComplete */ + ADIOI_TESTFS_IreadStrided, /* IreadStrided */ + ADIOI_TESTFS_IwriteStrided, /* IwriteStrided */ + ADIOI_TESTFS_Flush, /* Flush */ + ADIOI_TESTFS_Resize, /* Resize */ + ADIOI_TESTFS_Delete, /* Delete */ + ADIOI_GEN_Feature, /* Features */ + "TESTFS: the logging-only file system" +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs.h b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs.h new file mode 100644 index 0000000000..1871bde5b5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_TESTFS_INCLUDE +#define AD_TESTFS_INCLUDE + +#include +#include +#include +#include +#include "adio.h" + +void ADIOI_TESTFS_Open(ADIO_File fd, int *error_code); +void ADIOI_TESTFS_Close(ADIO_File fd, int *error_code); +void ADIOI_TESTFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_TESTFS_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); +void ADIOI_TESTFS_IwriteContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_TESTFS_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +int ADIOI_TESTFS_ReadDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +int ADIOI_TESTFS_WriteDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_TESTFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_TESTFS_WriteComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIOI_TESTFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code); +void ADIOI_TESTFS_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); +void ADIOI_TESTFS_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_TESTFS_WriteStridedColl(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_TESTFS_ReadStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_TESTFS_IreadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_TESTFS_IwriteStrided(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_TESTFS_Flush(ADIO_File fd, int *error_code); +void ADIOI_TESTFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +ADIO_Offset ADIOI_TESTFS_SeekIndividual(ADIO_File fd, ADIO_Offset offset, + int whence, int *error_code); +void ADIOI_TESTFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); +void ADIOI_TESTFS_Get_shared_fp(ADIO_File fd, int size, + ADIO_Offset *shared_fp, + int *error_code); +void ADIOI_TESTFS_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, + int *error_code); +void ADIOI_TESTFS_Delete(const char *filename, int *error_code); + +#endif + + + + diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_close.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_close.c new file mode 100644 index 0000000000..a1b85e600d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_close.c @@ -0,0 +1,22 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_Close(ADIO_File fd, int *error_code) +{ + int myrank, nprocs; + + fd->fd_sys = -1; + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_Close called on %s\n", myrank, + nprocs, fd->filename); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_delete.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_delete.c new file mode 100644 index 0000000000..9a1b6f37e1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_delete.c @@ -0,0 +1,21 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_Delete(const char *filename, int *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_Delete called on %s\n", + myrank, nprocs, filename); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_done.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_done.c new file mode 100644 index 0000000000..2ee3111587 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_done.c @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +int ADIOI_TESTFS_ReadDone(ADIO_Request *request, ADIO_Status *status, int + *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size( MPI_COMM_WORLD, &nprocs ); + MPI_Comm_rank( MPI_COMM_WORLD, &myrank ); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_ReadDone called on ADIO_REQUEST_NULL\n", + myrank, nprocs); + return 1; +} + + +int ADIOI_TESTFS_WriteDone(ADIO_Request *request, ADIO_Status *status, int + *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size( MPI_COMM_WORLD, &nprocs ); + MPI_Comm_rank( MPI_COMM_WORLD, &myrank ); + FPRINTF(stdout, + "[%d/%d] ADIOI_TESTFS_WriteDone called on ADIO_REQUEST_NULL\n", + myrank, nprocs); + return 1; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_fcntl.c new file mode 100644 index 0000000000..8b1e516d9a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_fcntl.c @@ -0,0 +1,49 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" +#include "adio_extern.h" + +void ADIOI_TESTFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code) +{ + int myrank, nprocs; + static char myname[] = "ADIOI_TESTFS_FCNTL"; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_Fcntl called on %s\n", + myrank, nprocs, fd->filename); + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + fcntl_struct->fsize = 0; + *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + *error_code = MPI_SUCCESS; + break; + + case ADIO_FCNTL_SET_ATOMICITY: + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + *error_code = MPI_SUCCESS; + break; + + default: + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**flag", "**flag %d", flag); + return; + /* --END ERROR HANDLING-- */ + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_flush.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_flush.c new file mode 100644 index 0000000000..23d559787d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_flush.c @@ -0,0 +1,21 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_Flush(ADIO_File fd, int *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_Flush called on %s\n", + myrank, nprocs, fd->filename); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_getsh.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_getsh.c new file mode 100644 index 0000000000..2bdb3dceb8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_getsh.c @@ -0,0 +1,23 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_Get_shared_fp(ADIO_File fd, int size, + ADIO_Offset *shared_fp, + int *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_Get_shared_fp called on %s\n", + myrank, nprocs, fd->filename); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_hints.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_hints.c new file mode 100644 index 0000000000..a6c1be9e9f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_hints.c @@ -0,0 +1,27 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" +#ifdef ROMIO_BGL +#include "../ad_bgl/ad_bgl.h" +#endif +void ADIOI_TESTFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_SetInfo called on %s\n", + myrank, nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_GEN_SetInfo\n", + myrank, nprocs); + + ADIOI_GEN_SetInfo(fd, users_info, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_iread.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_iread.c new file mode 100644 index 0000000000..77e862438c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_iread.c @@ -0,0 +1,62 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +/* ADIOI_TESTFS_IreadContig() + * + * Implemented by immediately calling ReadContig() + */ +void ADIOI_TESTFS_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code) +{ + ADIO_Status status; + int myrank, nprocs; + MPI_Count typesize, len; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + MPI_Type_size_x(datatype, &typesize); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_IreadContig called on %s\n", + myrank, nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_TESTFS_ReadContig\n", + myrank, nprocs); + + len = count * typesize; + ADIOI_TESTFS_ReadContig(fd, buf, len, MPI_BYTE, file_ptr_type, + offset, &status, error_code); + + MPIO_Completed_request_create(&fd, len, error_code, request); +} + +void ADIOI_TESTFS_IreadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code) +{ + ADIO_Status status; + int myrank, nprocs; + MPI_Count typesize; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + MPI_Type_size_x(datatype, &typesize); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_IreadStrided called on %s\n", + myrank, nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_TESTFS_ReadStrided\n", + myrank, nprocs); + + ADIOI_TESTFS_ReadStrided(fd, buf, count, datatype, file_ptr_type, + offset, &status, error_code); + MPIO_Completed_request_create(&fd, count*typesize, error_code, request); +} + diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_iwrite.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_iwrite.c new file mode 100644 index 0000000000..e29c9f6ee0 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_iwrite.c @@ -0,0 +1,68 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +#include "mpiu_greq.h" +#include "../../mpi-io/mpioimpl.h" + +/* ADIOI_TESTFS_IwriteContig() + * + * Implemented by immediately calling WriteContig() + */ +void ADIOI_TESTFS_IwriteContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code) +{ + ADIO_Status status; + int myrank, nprocs; + MPI_Count typesize, len; + + *error_code = MPI_SUCCESS; + + MPI_Type_size_x(datatype, &typesize); + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_IwriteContig called on %s\n", + myrank, nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_TESTFS_WriteContig\n", + myrank, nprocs); + + len = count * typesize; + ADIOI_TESTFS_WriteContig(fd, buf, len, MPI_BYTE, file_ptr_type, + offset, &status, error_code); + MPIO_Completed_request_create(&fd, len, error_code, request); + +} + +void ADIOI_TESTFS_IwriteStrided(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code) +{ + ADIO_Status status; + int myrank, nprocs; + MPI_Count typesize; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + MPI_Type_size_x(datatype, &typesize); + + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_IwriteStrided called on %s\n", + myrank, nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_TESTFS_WriteStrided\n", + myrank, nprocs); + + ADIOI_TESTFS_WriteStrided(fd, buf, count, datatype, file_ptr_type, + offset, &status, error_code); + MPIO_Completed_request_create(&fd, count*typesize, error_code, request); + +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_open.c new file mode 100644 index 0000000000..6b1595b99c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_open.c @@ -0,0 +1,23 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_Open(ADIO_File fd, int *error_code) +{ + int myrank, nprocs; + + fd->fd_sys = 1; + fd->fd_direct = -1; + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_Open called on %s\n", myrank, + nprocs, fd->filename); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_rdcoll.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_rdcoll.c new file mode 100644 index 0000000000..5df94458fd --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_rdcoll.c @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_ReadStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_ReadStridedColl called on %s\n", + myrank, nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_GEN_ReadStridedColl\n", + myrank, nprocs); + + ADIOI_GEN_ReadStridedColl(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_read.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_read.c new file mode 100644 index 0000000000..f60a9920f7 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_read.c @@ -0,0 +1,62 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_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 myrank, nprocs; + MPI_Count datatype_size; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + MPI_Type_size_x(datatype, &datatype_size); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_ReadContig called on %s\n", myrank, + nprocs, fd->filename); + if (file_ptr_type != ADIO_EXPLICIT_OFFSET) + { + offset = fd->fp_ind; + fd->fp_ind += datatype_size * count; + fd->fp_sys_posn = fd->fp_ind; + } + else { + fd->fp_sys_posn = offset + datatype_size * count; + } + + FPRINTF(stdout, "[%d/%d] reading (buf = %p, loc = %lld, sz = %lld)\n", + myrank, nprocs, buf, (long long) offset, + (long long) datatype_size * count); + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, datatype_size * count); +#endif +} + +void ADIOI_TESTFS_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_ReadStrided called on %s\n", myrank, + nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_GEN_ReadStrided\n", myrank, + nprocs); + + ADIOI_GEN_ReadStrided(fd, buf, count, datatype, file_ptr_type, offset, + status, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_resize.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_resize.c new file mode 100644 index 0000000000..a4a37eb94b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_resize.c @@ -0,0 +1,21 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_Resize called on %s\n", + myrank, nprocs, fd->filename); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_seek.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_seek.c new file mode 100644 index 0000000000..df6d30a516 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_seek.c @@ -0,0 +1,82 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" +#include "adio_extern.h" + +/* ADIOI_TESTFS_SeekIndividual() + * + * Implements SEEK_SET only (and doesn't test for whence type); all + * other types of whence must be converted before calling this. + * + * Returns an absolute offset in bytes. The offset passed into the call is in + * terms of the etype relative to the filetype, so some calculations are + * necessary. + */ +ADIO_Offset ADIOI_TESTFS_SeekIndividual(ADIO_File fd, ADIO_Offset offset, + int whence, int *error_code) +{ + int myrank, nprocs; + + ADIO_Offset off; + ADIOI_Flatlist_node *flat_file; + int i, n_etypes_in_filetype, n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0, sum; + int size_in_filetype; + int filetype_is_contig; + MPI_Count filetype_size; + MPI_Aint etype_size, filetype_extent; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_SeekIndividual called on %s\n", + myrank, nprocs, fd->filename); + + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + etype_size = fd->etype_size; + + if (filetype_is_contig) off = fd->disp + etype_size * offset; + else { + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + + MPI_Type_extent(fd->filetype, &filetype_extent); + MPI_Type_size_x(fd->filetype, &filetype_size); + if ( ! filetype_size ) { + *error_code = MPI_SUCCESS; + return 0; + } + + n_etypes_in_filetype = filetype_size/etype_size; + ADIOI_Assert((offset / n_etypes_in_filetype) == (int) (offset / n_etypes_in_filetype)); + 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; icount; i++) { + sum += flat_file->blocklens[i]; + + if (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 */ + off = fd->disp + (ADIO_Offset)n_filetypes * (ADIO_Offset)filetype_extent + + abs_off_in_filetype; + } + + fd->fp_ind = off; + + return off; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_setsh.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_setsh.c new file mode 100644 index 0000000000..6fc8a04be9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_setsh.c @@ -0,0 +1,22 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, + int *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_Set_shared_fp called on %s\n", + myrank, nprocs, fd->filename); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_wait.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_wait.c new file mode 100644 index 0000000000..6eef9ef706 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_wait.c @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, int + *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_ReadComplete called \n", + myrank, nprocs); + + /* do something with status set bytes? */ +} + +void ADIOI_TESTFS_WriteComplete(ADIO_Request *request, ADIO_Status *status, int + *error_code) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_WriteComplete called\n", + myrank, nprocs); + + /* do something with status_set_bytes? */ +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_wrcoll.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_wrcoll.c new file mode 100644 index 0000000000..ac11f5847f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_wrcoll.c @@ -0,0 +1,29 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_WriteStridedColl(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 myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_WriteStridedColl called on %s\n", + myrank, nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_GEN_WriteStridedColl\n", + myrank, nprocs); + + ADIOI_GEN_WriteStridedColl(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_write.c b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_write.c new file mode 100644 index 0000000000..e1a59ff010 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_testfs/ad_testfs_write.c @@ -0,0 +1,63 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_testfs.h" +#include "adioi.h" + +void ADIOI_TESTFS_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 myrank, nprocs; + MPI_Count datatype_size; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + MPI_Type_size_x(datatype, &datatype_size); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_WriteContig called on %s\n", myrank, + nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] writing (buf = %p, loc = %lld, sz = %lld)\n", + myrank, nprocs, buf, (long long) offset, + (long long)datatype_size * (long long)count); + + if (file_ptr_type != ADIO_EXPLICIT_OFFSET) + { + fd->fp_ind += datatype_size * count; + fd->fp_sys_posn = fd->fp_ind; + FPRINTF(stdout, "[%d/%d] new file position is %lld\n", myrank, + nprocs, (long long) fd->fp_ind); + } + else { + fd->fp_sys_posn = offset + datatype_size * count; + } + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, datatype_size * count); +#endif +} + +void ADIOI_TESTFS_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) +{ + int myrank, nprocs; + + *error_code = MPI_SUCCESS; + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + FPRINTF(stdout, "[%d/%d] ADIOI_TESTFS_WriteStrided called on %s\n", + myrank, nprocs, fd->filename); + FPRINTF(stdout, "[%d/%d] calling ADIOI_GEN_WriteStrided\n", + myrank, nprocs); + + ADIOI_GEN_WriteStrided(fd, buf, count, datatype, file_ptr_type, offset, + status, error_code); +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_ufs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_ufs/Makefile.mk new file mode 100644 index 0000000000..40ecdb4ae4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ufs/Makefile.mk @@ -0,0 +1,17 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_UFS + +noinst_HEADERS += adio/ad_ufs/ad_ufs.h + +romio_other_sources += \ + adio/ad_ufs/ad_ufs.c \ + adio/ad_ufs/ad_ufs_open.c + +endif BUILD_AD_UFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_ufs/ad_ufs.c b/ompi/mca/io/romio314/romio/adio/ad_ufs/ad_ufs.c new file mode 100644 index 0000000000..66b183ec56 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ufs/ad_ufs.c @@ -0,0 +1,44 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ufs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_UFS_operations = { + ADIOI_UFS_Open, /* Open */ + ADIOI_GEN_OpenColl, /* OpenColl */ + ADIOI_GEN_ReadContig, /* ReadContig */ + ADIOI_GEN_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_GEN_Fcntl, /* Fcntl */ + ADIOI_GEN_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_GEN_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ +#ifdef ROMIO_HAVE_WORKING_AIO + ADIOI_GEN_IreadContig, /* IreadContig */ + ADIOI_GEN_IwriteContig, /* IwriteContig */ +#else + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ +#endif + ADIOI_GEN_IODone, /* ReadDone */ + ADIOI_GEN_IODone, /* WriteDone */ + ADIOI_GEN_IOComplete, /* ReadComplete */ + ADIOI_GEN_IOComplete, /* WriteComplete */ + ADIOI_GEN_IreadStrided, /* IreadStrided */ + ADIOI_GEN_IwriteStrided, /* IwriteStrided */ + ADIOI_GEN_Flush, /* Flush */ + ADIOI_GEN_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ + ADIOI_GEN_Feature, /* Features */ + "UFS: Generic ROMIO driver for all UNIX-like file systems", +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_ufs/ad_ufs.h b/ompi/mca/io/romio314/romio/adio/ad_ufs/ad_ufs.h new file mode 100644 index 0000000000..5ad27439b3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ufs/ad_ufs.h @@ -0,0 +1,57 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_UNIX_INCLUDE +#define AD_UNIX_INCLUDE + +#include +#include +#include +#include "adio.h" + +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + +/* Workaround for incomplete set of definitions if __REDIRECT is not + defined and large file support is used in aio.h */ +#if !defined(__REDIRECT) && defined(__USE_FILE_OFFSET64) +#define aiocb aiocb64 +#endif + +int ADIOI_UFS_aio(ADIO_File fd, void *buf, int len, ADIO_Offset offset, + int wr, void *handle); + +void ADIOI_UFS_Open(ADIO_File fd, int *error_code); +void ADIOI_UFS_IwriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_UFS_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +int ADIOI_UFS_ReadDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +int ADIOI_UFS_WriteDone(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_UFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIOI_UFS_WriteComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIOI_UFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_ufs/ad_ufs_open.c b/ompi/mca/io/romio314/romio/adio/ad_ufs/ad_ufs_open.c new file mode 100644 index 0000000000..9d5a2a1174 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_ufs/ad_ufs_open.c @@ -0,0 +1,58 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_ufs.h" + +void ADIOI_UFS_Open(ADIO_File fd, int *error_code) +{ + int perm, old_mask, amode; + static char myname[] = "ADIOI_UFS_OPEN"; + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_a, 0, NULL ); +#endif + fd->fd_sys = open(fd->filename, amode, perm); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_b, 0, NULL ); +#endif + fd->fd_direct = -1; + + if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND)) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + fd->fp_ind = fd->fp_sys_posn = lseek(fd->fd_sys, 0, SEEK_END); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + } + + if (fd->fd_sys == -1) { + *error_code = ADIOI_Err_create_code(myname, fd->filename, errno); + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_xfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_xfs/Makefile.mk new file mode 100644 index 0000000000..9a2d7078a3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_xfs/Makefile.mk @@ -0,0 +1,22 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_XFS + +noinst_HEADERS += adio/ad_xfs/ad_xfs.h + +romio_other_sources += \ + adio/ad_xfs/ad_xfs.c \ + adio/ad_xfs/ad_xfs_fcntl.c \ + adio/ad_xfs/ad_xfs_hints.c \ + adio/ad_xfs/ad_xfs_open.c \ + adio/ad_xfs/ad_xfs_read.c \ + adio/ad_xfs/ad_xfs_resize.c \ + adio/ad_xfs/ad_xfs_write.c + +endif BUILD_AD_XFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs.c b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs.c new file mode 100644 index 0000000000..b748a8a637 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs.c @@ -0,0 +1,44 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_xfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_XFS_operations = { + ADIOI_XFS_Open, /* Open */ + ADIOI_GEN_OpenColl, /* OpenColl */ + ADIOI_XFS_ReadContig, /* ReadContig */ + ADIOI_XFS_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_XFS_Fcntl, /* Fcntl */ + ADIOI_XFS_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_GEN_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ +#if defined(ROMIO_HAVE_WORKING_AIO) + ADIOI_GEN_IreadContig, /* IreadContig */ + ADIOI_GEN_IwriteContig, /* IwriteContig */ +#else + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ +#endif /* ROMIO_HAVE_WORKING_AIO */ + ADIOI_GEN_IODone, /* ReadDone */ + ADIOI_GEN_IODone, /* WriteDone */ + ADIOI_GEN_IOComplete, /* ReadComplete */ + ADIOI_GEN_IOComplete, /* WriteComplete */ + ADIOI_GEN_IreadStrided, /* IreadStrided */ + ADIOI_GEN_IwriteStrided, /* IwriteStrided */ + ADIOI_GEN_Flush, /* Flush */ + ADIOI_XFS_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ + ADIOI_GEN_Feature, /* Features */ + "XFS: SGI XFS" +}; diff --git a/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs.h b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs.h new file mode 100644 index 0000000000..1a4d4ccc1b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_XFS_INCLUDE +#define AD_XFS_INCLUDE + +#ifdef _STDC_C99 +#define _XOPEN_SOURCE 600 +#else +#define _XOPEN_SOURCE 500 +#endif +#include +#include +#include +#include "adio.h" + +#if defined(MPISGI) +#include "xfs/xfs_fs.h" +#ifndef __USE_LARGEFILE64 +#define __USE_LARGEFILE64 +#endif +typedef struct aiocb64 aiocb64_t; +#endif + +void ADIOI_XFS_Open(ADIO_File fd, int *error_code); +void ADIOI_XFS_Close(ADIO_File fd, int *error_code); +void ADIOI_XFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_XFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_XFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIOI_XFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +void ADIOI_XFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_fcntl.c new file mode 100644 index 0000000000..1f19081afc --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_fcntl.c @@ -0,0 +1,81 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_xfs.h" +#include "adio_extern.h" +#include + +#ifndef HAVE_LSEEK64 +#define lseek64 lseek +#endif + +void ADIOI_XFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code) +{ + int i, err; +#if defined(LINUX) && defined(MPISGI) + struct xfs_flock64 fl; +#else + struct flock64 fl; +#endif + static char myname[] = "ADIOI_XFS_FCNTL"; + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + fcntl_struct->fsize = lseek64(fd->fd_sys, 0, SEEK_END); + if (fcntl_struct->fsize == -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; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + i = 0; + fl.l_start = 0; + fl.l_whence = SEEK_SET; + fl.l_len = fcntl_struct->diskspace; + +#if defined(LINUX) && defined(MPISGI) + err = ioctl(fd->fd_sys, XFS_IOC_RESVSP64, &fl); +#else + err = fcntl(fd->fd_sys, F_RESVSP64, &fl); +#endif + + if (err) i = 1; + if (fcntl_struct->diskspace > lseek64(fd->fd_sys, 0, SEEK_END)) { + /* also need to set the file size */ + err = ftruncate64(fd->fd_sys, fcntl_struct->diskspace); + if (err) i = 1; + } + + if (i == 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; + break; + + case ADIO_FCNTL_SET_ATOMICITY: + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + *error_code = MPI_SUCCESS; + break; + + default: + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**flag", "**flag %d", flag); + return; + /* --END ERROR HANDLING-- */ + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_hints.c b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_hints.c new file mode 100644 index 0000000000..0fe0e832f4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_hints.c @@ -0,0 +1,97 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_xfs.h" +#include "adio_extern.h" + +static unsigned xfs_direct_read_chunk_size; +static unsigned xfs_direct_write_chunk_size; + +void ADIOI_XFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ + char *value, * c; + int flag; + static char xfs_initialized = 0; + + if (fd->info == MPI_INFO_NULL) MPI_Info_create(&(fd->info)); + + ADIOI_Info_set(fd->info, "direct_read", "false"); + ADIOI_Info_set(fd->info, "direct_write", "false"); + fd->direct_read = fd->direct_write = 0; + + if (!xfs_initialized) { + xfs_initialized = 1; + c = getenv("MPIO_DIRECT_READ_CHUNK_SIZE"); + if (c) { + int io; + io = atoi(c); + if (io <= 0) { + fprintf(stderr, +"MPI: Ignoring an invalid setting for MPIO_DIRECT_READ_CHUNK_SIZE.\n" +" It must be set to a positive integer value.\n"); + } else { + xfs_direct_read_chunk_size = io; + } + } else { + xfs_direct_read_chunk_size = 0; + } + + c = getenv("MPIO_DIRECT_WRITE_CHUNK_SIZE"); + if (c) { + int io; + io = atoi(c); + if (io <= 0) { + fprintf(stderr, +"MPI: Ignoring an invalid setting for MPIO_DIRECT_WRITE_CHUNK_SIZE.\n" +" It must be set to a positive integer value.\n"); + } else { + xfs_direct_write_chunk_size = io; + } + } else { + xfs_direct_write_chunk_size = 0; + } + } + + if (!fd->hints->initialized) { + fd->hints->fs_hints.xfs.read_chunk_sz = + xfs_direct_read_chunk_size; + fd->hints->fs_hints.xfs.write_chunk_sz = + xfs_direct_write_chunk_size; + } + + /* has user specified values for keys "direct_read" and "direct write"? */ + if (users_info != MPI_INFO_NULL) { + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + + ADIOI_Info_get(users_info, "direct_read", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && !strcmp(value, "true")) { + ADIOI_Info_set(fd->info, "direct_read", "true"); + fd->direct_read = 1; + } + + ADIOI_Info_get(users_info, "direct_write", MPI_MAX_INFO_VAL, + value, &flag); + if (flag && !strcmp(value, "true")) { + ADIOI_Info_set(fd->info, "direct_write", "true"); + fd->direct_write = 1; + } + + ADIOI_Free(value); + } + + /* set the values for collective I/O and data sieving parameters */ + ADIOI_GEN_SetInfo(fd, users_info, error_code); + + /* Environment variables override MPI_Info hints */ + if (ADIOI_Direct_read) fd->direct_read = 1; + if (ADIOI_Direct_write) fd->direct_write = 1; + + /* environment variables checked in ADIO_Init */ + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_open.c new file mode 100644 index 0000000000..5c0a9a2b8a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_open.c @@ -0,0 +1,111 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#define _GNU_SOURCE // for O_DIRECT + +#include "ad_xfs.h" +#include +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifndef HAVE_LSEEK64 +#define lseek64 lseek +#endif + +void ADIOI_XFS_Open(ADIO_File fd, int *error_code) +{ + int perm, amode, amode_direct, factor; + unsigned int old_mask; + struct dioattr st; + static char myname[] = "ADIOI_XFS_OPEN"; + unsigned read_chunk_sz = fd->hints->fs_hints.xfs.read_chunk_sz; + unsigned write_chunk_sz = fd->hints->fs_hints.xfs.write_chunk_sz; + + if (fd->perm == ADIO_PERM_NULL) { + old_mask = umask(022); + umask(old_mask); + perm = old_mask ^ 0666; + } + else perm = fd->perm; + + amode = 0; + if (fd->access_mode & ADIO_CREATE) + amode = amode | O_CREAT; + if (fd->access_mode & ADIO_RDONLY) + amode = amode | O_RDONLY; + if (fd->access_mode & ADIO_WRONLY) + amode = amode | O_WRONLY; + if (fd->access_mode & ADIO_RDWR) + amode = amode | O_RDWR; + + amode_direct = amode | O_DIRECT; + + if (fd->access_mode & ADIO_EXCL) + amode = amode | O_EXCL; + + fd->fd_sys = open(fd->filename, amode, perm); + + fd->fd_direct = open(fd->filename, amode_direct, perm); + if (fd->fd_direct != -1) { + +#if defined(MPISGI) + ioctl(fd->fd_direct, XFS_IOC_DIOINFO, &st); +#else + fcntl(fd->fd_direct, F_DIOINFO, &st); +#endif + + fd->d_mem = st.d_mem; + fd->d_miniosz = st.d_miniosz; + + if (read_chunk_sz == 0) { + fd->hints->fs_hints.xfs.read_chunk_sz = st.d_maxiosz; + } else { + /* + * MPIO_DIRECT_READ_CHUNK_SIZE was set. + * Make read_chunk_sz a multiple of d_miniosz. + */ + factor = read_chunk_sz / fd->d_miniosz; + if (factor == 0 || read_chunk_sz != fd->d_miniosz * factor) { + fd->hints->fs_hints.xfs.read_chunk_sz = + fd->d_miniosz * (factor + 1); + } + } + + if (write_chunk_sz == 0) { + fd->hints->fs_hints.xfs.write_chunk_sz = st.d_maxiosz; + } else { + /* + * MPIO_DIRECT_WRITE_CHUNK_SIZE was set. + * Make write_chunk_sz a multiple of d_miniosz. + */ + factor = write_chunk_sz / fd->d_miniosz; + if (factor == 0 || write_chunk_sz != fd->d_miniosz * factor) { + fd->hints->fs_hints.xfs.write_chunk_sz = + fd->d_miniosz * (factor + 1); + } + } + + if (fd->d_mem > XFS_MEMALIGN) { + FPRINTF(stderr, "MPI: Run-time Direct-IO memory alignment, %d, does not match compile-time value, %d.\n", + fd->d_mem, XFS_MEMALIGN); + FPRINTF(stderr, "MPI: Report this error and rerun with Direct-IO disabled.\n"); + close(fd->fd_direct); + fd->fd_direct = -1; + } + } + + if ((fd->fd_sys != -1) && (fd->access_mode & ADIO_APPEND)) + fd->fp_ind = lseek64(fd->fd_sys, 0, SEEK_END); + + fd->fp_sys_posn = -1; /* set it to null because we use pread/pwrite */ + + if ((fd->fd_sys == -1) || (fd->fd_direct == -1)) { + *error_code = ADIOI_Err_create_code(mymame, fd->filename, errno); + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_read.c b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_read.c new file mode 100644 index 0000000000..c3c237cc15 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_read.c @@ -0,0 +1,152 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_xfs.h" +#ifdef HAVE_MALLOC_H +#include +#endif + +/* style: allow:free:2 sig:0 */ + +static void ADIOI_XFS_Aligned_Mem_File_Read(ADIO_File fd, void *buf, int len, + ADIO_Offset offset, int *err); + +void ADIOI_XFS_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 diff, size, nbytes; + MPI_Count err=-1, datatype_size, len; + void *newbuf; + static char myname[] = "ADIOI_XFS_READCONTIG"; + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + fd->fp_sys_posn = -1; /* set it to null, since we are using pread */ + + if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind; + + if (!(fd->direct_read)) /* direct I/O not enabled */ + err = pread(fd->fd_sys, buf, len, offset); + else { /* direct I/O enabled */ + + /* (1) if mem_aligned && file_aligned + use direct I/O to read up to correct io_size + use buffered I/O for remaining */ + + if (!(((long) buf) % fd->d_mem) && !(offset % fd->d_miniosz)) + ADIOI_XFS_Aligned_Mem_File_Read(fd, buf, len, offset, &err); + + /* (2) if !file_aligned + use buffered I/O to read up to file_aligned + At that point, if still mem_aligned, use (1) + else copy into aligned buf and then use (1) */ + else if (offset % fd->d_miniosz) { + diff = fd->d_miniosz - (offset % fd->d_miniosz); + diff = ADIOI_MIN(diff, len); + nbytes = pread(fd->fd_sys, buf, diff, offset); + + buf = ((char *) buf) + diff; + offset += diff; + size = len - diff; + if (!(((long) buf) % fd->d_mem)) { + ADIOI_XFS_Aligned_Mem_File_Read(fd, buf, size, offset, &err); + nbytes += err; + } + else { + newbuf = (void *) memalign(XFS_MEMALIGN, size); + if (newbuf) { + ADIOI_XFS_Aligned_Mem_File_Read(fd, newbuf, size, offset, &err); + if (err > 0) memcpy(buf, newbuf, err); + nbytes += err; + ADIOI_Free(newbuf); + } + else nbytes += pread(fd->fd_sys, buf, size, offset); + } + err = nbytes; + } + + /* (3) if !mem_aligned && file_aligned + copy into aligned buf, then use (1) */ + else { + newbuf = (void *) memalign(XFS_MEMALIGN, len); + if (newbuf) { + ADIOI_XFS_Aligned_Mem_File_Read(fd, newbuf, len, offset, &err); + if (err > 0) memcpy(buf, newbuf, err); + ADIOI_Free(newbuf); + } + else err = pread(fd->fd_sys, buf, len, offset); + } + } + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += err; + +#ifdef HAVE_STATUS_SET_BYTES + if (err != -1) MPIR_Status_set_bytes(status, datatype, err); +#endif + + 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_XFS_Aligned_Mem_File_Read(ADIO_File fd, void *buf, int len, + ADIO_Offset offset, int *err) +{ + int ntimes, rem, newrem, i, size, nbytes; + unsigned read_chunk_sz = fd->hints->fs_hints.xfs.read_chunk_sz; + + /* memory buffer is aligned, offset in file is aligned, + io_size may or may not be of the right size. + use direct I/O to read up to correct io_size, + use buffered I/O for remaining. */ + + if (!(len % fd->d_miniosz) && + (len >= fd->d_miniosz) && (len <= read_chunk_sz)) + *err = pread(fd->fd_direct, buf, len, offset); + else if (len < fd->d_miniosz) + *err = pread(fd->fd_sys, buf, len, offset); + else if (len > read_chunk_sz) { + ntimes = len/(read_chunk_sz); + rem = len - ntimes * read_chunk_sz; + nbytes = 0; + for (i=0; ifd_direct, ((char *)buf) + i * read_chunk_sz, + read_chunk_sz, offset); + offset += read_chunk_sz; + } + if (rem) { + if (!(rem % fd->d_miniosz)) + nbytes += pread(fd->fd_direct, + ((char *)buf) + ntimes * read_chunk_sz, rem, offset); + else { + newrem = rem % fd->d_miniosz; + size = rem - newrem; + if (size) { + nbytes += pread(fd->fd_direct, + ((char *)buf) + ntimes * read_chunk_sz, size, offset); + offset += size; + } + nbytes += pread(fd->fd_sys, + ((char *)buf) + ntimes * read_chunk_sz + size, newrem, offset); + } + } + *err = nbytes; + } + else { + rem = len % fd->d_miniosz; + size = len - rem; + nbytes = pread(fd->fd_direct, buf, size, offset); + nbytes += pread(fd->fd_sys, (char *)buf + size, rem, offset+size); + *err = nbytes; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_resize.c b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_resize.c new file mode 100644 index 0000000000..8caf8b48bd --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_resize.c @@ -0,0 +1,22 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_xfs.h" + +void ADIOI_XFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int err; + static char myname[] = "ADIOI_XFS_RESIZE"; + + err = ftruncate64(fd->fd_sys, size); + 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; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_write.c b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_write.c new file mode 100644 index 0000000000..9ab82768f7 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_xfs/ad_xfs_write.c @@ -0,0 +1,171 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_xfs.h" + +#ifdef HAVE_MALLOC_H +#include +#endif + +/* style: allow:free:2 sig:0 */ + +static int ADIOI_XFS_Aligned_Mem_File_Write(ADIO_File fd, void *buf, + ADIO_Offset len, ADIO_Offset offset); + +void ADIOI_XFS_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 diff, size; + MPI_Count err=-1, datatype_size; + ssize_t len; + void *newbuf; + static char myname[] = "ADIOI_XFS_WRITECONTIG"; + + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * count; + + fd->fp_sys_posn = -1; /* set it to null, since we are using pwrite */ + + if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind; + + if (!(fd->direct_write)) { /* direct I/O not enabled */ + err = pwrite(fd->fd_sys, buf, len, offset); + if (err < 0) {goto leaving;} + } else { /* direct I/O enabled */ + + /* (1) if mem_aligned && file_aligned + use direct I/O to write up to correct io_size + use buffered I/O for remaining */ + + if (!(((long) buf) % fd->d_mem) && !(offset % fd->d_miniosz)) { + err = ADIOI_XFS_Aligned_Mem_File_Write(fd, buf, len, offset); + if (err < 0) {goto leaving;} + + /* (2) if !file_aligned + use buffered I/O to write up to file_aligned + At that point, if still mem_aligned, use (1) + else copy into aligned buf and then use (1) */ + } else if (offset % fd->d_miniosz) { + diff = fd->d_miniosz - (offset % fd->d_miniosz); + diff = ADIOI_MIN(diff, len); + err = pwrite(fd->fd_sys, buf, diff, offset); + if (err < 0) {goto leaving;} + + buf = ((char *) buf) + diff; + offset += diff; + size = len - diff; + if (!(((long) buf) % fd->d_mem)) { + err = ADIOI_XFS_Aligned_Mem_File_Write(fd, buf, size, offset); + if (err < 0) {goto leaving;} + } + else { + newbuf = (void *) memalign(XFS_MEMALIGN, size); + if (newbuf) { + memcpy(newbuf, buf, size); + err = ADIOI_XFS_Aligned_Mem_File_Write(fd, newbuf, size, offset); + ADIOI_Free(newbuf); + if (err < 0) {goto leaving;} + } else { + err = pwrite(fd->fd_sys, buf, size, offset); + if (err < 0) {goto leaving;} + } + } + } + + /* (3) if !mem_aligned && file_aligned + copy into aligned buf, then use (1) */ + else { + newbuf = (void *) memalign(XFS_MEMALIGN, len); + if (newbuf) { + memcpy(newbuf, buf, len); + err = ADIOI_XFS_Aligned_Mem_File_Write(fd, newbuf, len, offset); + ADIOI_Free(newbuf); + } else { + err = pwrite(fd->fd_sys, buf, len, offset); + } + + if (err < 0) {goto leaving;} + } + } + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += len; + +#ifdef HAVE_STATUS_SET_BYTES + if (err != -1) MPIR_Status_set_bytes(status, datatype, len); +#endif +leaving: + 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; +} + + +static int +ADIOI_XFS_Aligned_Mem_File_Write(ADIO_File fd, void *buf, ADIO_Offset len, + ADIO_Offset offset) +{ + unsigned write_chunk_sz = fd->hints->fs_hints.xfs.write_chunk_sz; + ADIO_Offset nbytes, rem, newrem, size; + int ntimes, i; + + /* memory buffer is aligned, offset in file is aligned, + io_size may or may not be of the right size. + use direct I/O to write up to correct io_size, + use buffered I/O for remaining. */ + + if (!(len % fd->d_miniosz) && + (len >= fd->d_miniosz) && (len <= write_chunk_sz)) { + nbytes = pwrite(fd->fd_direct, buf, len, offset); + if (nbytes < 0) {return -1;} + } else if (len < fd->d_miniosz) { + nbytes = pwrite(fd->fd_sys, buf, len, offset); + if (nbytes < 0) {return -1;} + } else if (len > write_chunk_sz) { + ntimes = len/(write_chunk_sz); + rem = len - ntimes * write_chunk_sz; + nbytes = 0; + for (i=0; ifd_direct, ((char *)buf) + i * write_chunk_sz, + write_chunk_sz, offset); + offset += write_chunk_sz; + if (nbytes < 0) {return -1;} + } + if (rem) { + if (!(rem % fd->d_miniosz)) { + nbytes = pwrite(fd->fd_direct, + ((char *)buf) + ntimes * write_chunk_sz, rem, offset); + if (nbytes < 0) {return -1;} + } else { + newrem = rem % fd->d_miniosz; + size = rem - newrem; + if (size) { + nbytes = pwrite(fd->fd_direct, + ((char *)buf) + ntimes * write_chunk_sz, size, offset); + offset += size; + if (nbytes < 0) {return -1;} + } + nbytes = pwrite(fd->fd_sys, + ((char *)buf) + ntimes * write_chunk_sz + size, newrem, offset); + if (nbytes < 0) {return -1;} + } + } + } + else { + rem = len % fd->d_miniosz; + size = len - rem; + nbytes = pwrite(fd->fd_direct, buf, size, offset); + if (nbytes < 0) {return -1;} + nbytes = pwrite(fd->fd_sys, (char *)buf + size, rem, offset+size); + if (nbytes < 0) {return -1;} + } + + return 0; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/Makefile.mk b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/Makefile.mk new file mode 100644 index 0000000000..a26e59c8e0 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/Makefile.mk @@ -0,0 +1,27 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_AD_ZOIDFS + +noinst_HEADERS += adio/ad_zoidfs/ad_zoidfs.h adio/ad_zoidfs/ad_zoidfs_common.h + +romio_other_sources += \ + adio/ad_zoidfs/ad_zoidfs.c \ + adio/ad_zoidfs/ad_zoidfs_close.c \ + adio/ad_zoidfs/ad_zoidfs_common.c \ + adio/ad_zoidfs/ad_zoidfs_delete.c \ + adio/ad_zoidfs/ad_zoidfs_fcntl.c \ + adio/ad_zoidfs/ad_zoidfs_flush.c \ + adio/ad_zoidfs/ad_zoidfs_io.c \ + adio/ad_zoidfs/ad_zoidfs_open.c \ + adio/ad_zoidfs/ad_zoidfs_resize.c \ + adio/ad_zoidfs/ad_zoidfs_features.c \ + adio/ad_zoidfs/ad_zoidfs_read_list.c \ + adio/ad_zoidfs/ad_zoidfs_write_list.c + +endif BUILD_AD_ZOIDFS + diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs.c new file mode 100644 index 0000000000..a0eadfba69 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs.c @@ -0,0 +1,42 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_zoidfs.h" + +/* adioi.h has the ADIOI_Fns_struct define */ +#include "adioi.h" + +struct ADIOI_Fns_struct ADIO_ZOIDFS_operations = { + ADIOI_ZOIDFS_Open, /* Open */ + ADIOI_SCALEABLE_OpenColl, /* OpenColl */ + ADIOI_ZOIDFS_ReadContig, /* ReadContig */ + ADIOI_ZOIDFS_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_ZOIDFS_Fcntl, /* Fcntl */ + ADIOI_GEN_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_ZOIDFS_WriteStrided, /* WriteStrided */ + ADIOI_ZOIDFS_Close, /* Close */ + ADIOI_FAKE_IreadContig, /* IreadContig */ + ADIOI_FAKE_IwriteContig, /* IwriteContig */ + ADIOI_FAKE_IODone, /* ReadDone */ + ADIOI_FAKE_IODone, /* WriteDone */ + ADIOI_FAKE_IOComplete, /* ReadComplete */ + ADIOI_FAKE_IOComplete, /* WriteComplete */ + ADIOI_FAKE_IreadStrided, /* IreadStrided */ + ADIOI_FAKE_IwriteStrided, /* IwriteStrided */ + ADIOI_ZOIDFS_Flush, /* Flush */ + ADIOI_ZOIDFS_Resize, /* Resize */ + ADIOI_ZOIDFS_Delete, /* Delete */ + ADIOI_ZOIDFS_Feature, +}; + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs.h b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs.h new file mode 100644 index 0000000000..d4999b6622 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef AD_ZOIDFS_INCLUDE +#define AD_ZOIDFS_INCLUDE + +#include "adio.h" +#ifdef HAVE_ZOIDFS_H +#include "zoidfs.h" +#endif + + +typedef zoidfs_handle_t ADIOI_ZOIDFS_object; + +void ADIOI_ZOIDFS_Open(ADIO_File fd, int *error_code); +void ADIOI_ZOIDFS_Close(ADIO_File fd, int *error_code); +void ADIOI_ZOIDFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_ZOIDFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_ZOIDFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIOI_ZOIDFS_WriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_ZOIDFS_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_ZOIDFS_Flush(ADIO_File fd, int *error_code); +void ADIOI_ZOIDFS_Delete(char *filename, int *error_code); +void ADIOI_ZOIDFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +void ADIOI_ZOIDFS_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); +int ADIOI_ZOIDFS_Feature(ADIO_File fd, int flag); +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_close.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_close.c new file mode 100644 index 0000000000..0126783aa3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_close.c @@ -0,0 +1,25 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_zoidfs.h" + +void ADIOI_ZOIDFS_Close(ADIO_File fd, int *error_code) +{ + ADIOI_Free(fd->fs_ptr); + fd->fs_ptr = NULL; + + /* At some point or another it was decided that ROMIO would not + * explicitly flush (other than any local cache) on close, because + * there is no way to *avoid* that overhead if you implement it here + * and don't actually want it. + */ + + *error_code = MPI_SUCCESS; +} +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_common.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_common.c new file mode 100644 index 0000000000..018d439aaa --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_common.c @@ -0,0 +1,126 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2003 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_zoidfs.h" +#include "ad_zoidfs_common.h" +#include +#include + +/* keyval hack to both tell us if we've already initialized zoidfs and also + * close it down when mpi exits */ +int ADIOI_ZOIDFS_Initialized = MPI_KEYVAL_INVALID; + +void ADIOI_ZOIDFS_End(int *error_code) +{ + int ret; + static char myname[] = "ADIOI_ZOIDFS_END"; + + ret = zoidfs_finalize(); + + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0 ) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(ret), + "Error in zoidfs_finalize", 0); + return; + } + /* --END ERROR HANDLING-- */ + + *error_code = MPI_SUCCESS; +} + +int ADIOI_ZOIDFS_End_call(MPI_Comm comm, int keyval, + void *attribute_val, void *extra_state) +{ + int error_code; + ADIOI_ZOIDFS_End(&error_code); + MPI_Keyval_free(&keyval); + return error_code; +} + +void ADIOI_ZOIDFS_Init(int rank, int *error_code ) +{ + int ret; + static char myname[] = "ADIOI_ZOIDFS_INIT"; + + /* do nothing if we've already fired up the zoidfs interface */ + if (ADIOI_ZOIDFS_Initialized != MPI_KEYVAL_INVALID) { + *error_code = MPI_SUCCESS; + return; + } + + ret = zoidfs_init(); + if (ret < 0 ) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(ret), + "Error in zoidfs_init", + 0); + return; + } + + MPI_Keyval_create(MPI_NULL_COPY_FN, ADIOI_ZOIDFS_End_call, + &ADIOI_ZOIDFS_Initialized, (void *)0); + /* just like romio does, we make a dummy attribute so we + * get cleaned up */ + MPI_Attr_put(MPI_COMM_SELF, ADIOI_ZOIDFS_Initialized, (void *)0); +} + +void ADIOI_ZOIDFS_makeattribs(zoidfs_sattr_t * attribs) +{ + memset(attribs, 0, sizeof(zoidfs_sattr_t)); + + attribs->mask = ZOIDFS_ATTR_MODE; + attribs->mode = 0644; +} + +int ADIOI_ZOIDFS_error_convert(int error) +{ + switch (error) + { + case ZFSERR_PERM: /* ??? */ + case ZFSERR_ACCES: + return MPI_ERR_ACCESS; + case ZFSERR_NOENT: + case ZFSERR_NXIO: /* ??? */ + case ZFSERR_NODEV: /* ??? */ + return MPI_ERR_NO_SUCH_FILE; + case ZFSERR_IO: + return MPI_ERR_IO; + case ZFSERR_EXIST: + return MPI_ERR_FILE_EXISTS; + case ZFSERR_NOTDIR: /* ??? */ + case ZFSERR_ISDIR: /* ??? */ + case ZFSERR_NAMETOOLONG: + return MPI_ERR_BAD_FILE; + case ZFSERR_INVAL: + case ZFSERR_STALE: + return MPI_ERR_FILE; + case ZFSERR_FBIG: /* ??? */ + case ZFSERR_NOSPC: + return MPI_ERR_NO_SPACE; + case ZFSERR_ROFS: + return MPI_ERR_READ_ONLY; + case ZFSERR_NOTIMPL: + return MPI_ERR_UNSUPPORTED_OPERATION; + case ZFSERR_DQUOT: + return MPI_ERR_QUOTA; + /* case ZFSERR_NOTEMPTY: */ + /* case ZFSERR_WFLUSH: */ + /* case ZFSERR_OTHER: */ + case ZFSERR_NOMEM: + return MPI_ERR_INTERN; + default: + return MPI_UNDEFINED; + } +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_common.h b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_common.h new file mode 100644 index 0000000000..ba985b4922 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_common.h @@ -0,0 +1,43 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifndef _AD_ZOIDFS_COMMON_H +#define _AD_ZOIDFS_COMMON_H +#include "ad_zoidfs.h" + +/* The ESTALE problem: + * The IO forwarding protocol can respond to any call with ESTALE, which means + * the handle upon which that call operates has expired from the metadata + * cache. We thus wrap any zoidfs routine (expr) in this macro. + * + * ROMIO stores the filename in the ADIOI_File structrue (fd), so we can always + * re-lookup in response to ESTALE */ + +#define NO_STALE(ret, fd, handle_p, expr) \ + do { \ + (ret) = (expr); \ + while ((ret) == ZFSERR_STALE) { \ + /* lookup again */ \ + (ret) = zoidfs_lookup(NULL, NULL, (fd)->filename, \ + (zoidfs_handle_t*)((fd)->fs_ptr), ZOIDFS_NO_OP_HINT); \ + if ((ret) == ZFS_OK) { \ + *((ADIOI_ZOIDFS_object*)handle_p) \ + = *((ADIOI_ZOIDFS_object*)((fd)->fs_ptr)); \ + /* re-execute the expr with new handle */ \ + (ret) = (expr); \ + } \ + } \ + } while (0) + +void ADIOI_ZOIDFS_Init(int rank, int *error_code ); +void ADIOI_ZOIDFS_makeattribs(zoidfs_sattr_t * attribs); +void ADIOI_ZOIDFS_End(int *error_code); +int ADIOI_ZOIDFS_End_call(MPI_Comm comm, int keyval, + void *attribute_val, void *extra_state); +int ADIOI_ZOIDFS_error_convert(int error); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_delete.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_delete.c new file mode 100644 index 0000000000..87193147a5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_delete.c @@ -0,0 +1,45 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_zoidfs.h" +#include "adio.h" + +#include "ad_zoidfs_common.h" + +void ADIOI_ZOIDFS_Delete(char *filename, int *error_code) +{ + int ret; + static char myname[] = "ADIOI_ZOIDFS_DELETE"; + + ADIOI_ZOIDFS_Init(0, error_code); + /* --BEGIN ERROR HANDLING-- */ + if (*error_code != MPI_SUCCESS) + { + /* ADIOI_ZOIDFS_INIT handles creating error codes itself */ + return; + } + /* --END ERROR HANDLING-- */ + + ret = zoidfs_remove(NULL, NULL, filename, NULL, ZOIDFS_NO_OP_HINT); + /* --BEGIN ERROR HANDLING-- */ + if (ret != ZFS_OK) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(ret), + "Error in zoidfs_remove", 0); + return; + } + /* --END ERROR HANDLING-- */ + + *error_code = MPI_SUCCESS; + return; +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_fcntl.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_fcntl.c new file mode 100644 index 0000000000..22c26714d8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_fcntl.c @@ -0,0 +1,60 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_zoidfs.h" +#include "adio_extern.h" +#include "ad_zoidfs_common.h" + +void ADIOI_ZOIDFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code) +{ + int ret; + zoidfs_attr_t attr; + ADIOI_ZOIDFS_object *zoidfs_obj_ptr; + static char myname[] = "ADIOI_ZOIDFS_FCNTL"; + + zoidfs_obj_ptr = (ADIOI_ZOIDFS_object*)fd->fs_ptr; + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: + attr.mask = ZOIDFS_ATTR_SIZE; + NO_STALE(ret, fd, zoidfs_obj_ptr, + zoidfs_getattr(zoidfs_obj_ptr, &attr, ZOIDFS_NO_OP_HINT)); + if ( !(attr.mask & ZOIDFS_ATTR_SIZE) || (ret != ZFS_OK ) ) { + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(ret), + "Error in zoidfs_getattr", 0); + /* --END ERROR HANDLING-- */ + } + else { + *error_code = MPI_SUCCESS; + } + fcntl_struct->fsize = attr.size; + return; + + case ADIO_FCNTL_SET_DISKSPACE: + ADIOI_GEN_Prealloc(fd, fcntl_struct->diskspace, error_code); + break; + + /* --BEGIN ERROR HANDLING-- */ + case ADIO_FCNTL_SET_ATOMICITY: + default: + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**flag", "**flag %d", flag); + /* --END ERROR HANDLING-- */ + } +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_features.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_features.c new file mode 100644 index 0000000000..a3f5c1467e --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_features.c @@ -0,0 +1,22 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "adio.h" +#include "ad_zoidfs.h" + +int ADIOI_ZOIDFS_Feature(ADIO_File fd, int flag) +{ + switch(flag) { + case ADIO_SCALABLE_OPEN: + return 1; + case ADIO_SHARED_FP: + case ADIO_LOCKS: + case ADIO_SEQUENTIAL: + case ADIO_DATA_SIEVING_WRITES: + default: + return 0; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_flush.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_flush.c new file mode 100644 index 0000000000..8ec0b8d551 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_flush.c @@ -0,0 +1,52 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_zoidfs.h" +#include "ad_zoidfs_common.h" + +/* we want to be a bit clever here: at scale, if every client sends a + * flush request, it will stress the file system with redundant + * commit requests. Instead, one process should wait for + * everyone to catch up, do the sync, then broadcast the result. + */ + +void ADIOI_ZOIDFS_Flush(ADIO_File fd, int *error_code) +{ + int ret, rank, dummy=0, dummy_in=0; + ADIOI_ZOIDFS_object *zoidfs_obj_ptr; + static char myname[] = "ADIOI_ZOIDFS_FLUSH"; + + *error_code = MPI_SUCCESS; + + zoidfs_obj_ptr = (ADIOI_ZOIDFS_object*)fd->fs_ptr; + + MPI_Comm_rank(fd->comm, &rank); + + /* collective call to ensure no outstanding write requests. reduce is + * slightly less expensvie than barrier */ + MPI_Reduce(&dummy_in, &dummy, 1, MPI_INT, MPI_SUM, + fd->hints->ranklist[0], fd->comm); + + if (rank == fd->hints->ranklist[0]) { + ret = zoidfs_commit(zoidfs_obj_ptr, ZOIDFS_NO_OP_HINT); + } + MPI_Bcast(&ret, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + + /* --BEGIN ERROR HANDLING-- */ + if (ret != 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(ret), + "Error in zoidfs_commit", 0); + } + /* --END ERROR HANDLING-- */ +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_io.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_io.c new file mode 100644 index 0000000000..337c92f410 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_io.c @@ -0,0 +1,96 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "ad_zoidfs.h" + +#include "ad_zoidfs_common.h" + +#define ZOIDFS_READ 0 +#define ZOIDFS_WRITE 1 + +static void ZOIDFS_IOContig(ADIO_File fd, void * buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int flag, int *error_code) +{ + int ret; + MPI_Count datatype_size; + uint64_t file_len; + size_t mem_len; + ADIOI_ZOIDFS_object *zoidfs_obj_ptr; + uint64_t file_offset = offset; + static char myname[] = "ADIOI_ZOIDFS_IOCONTIG"; + + zoidfs_obj_ptr = (ADIOI_ZOIDFS_object*)fd->fs_ptr; + + MPI_Type_size_x(datatype, &datatype_size); + file_len = mem_len = datatype_size * count; + + if (file_ptr_type == ADIO_INDIVIDUAL) { + file_offset = fd->fp_ind; + } + + if (flag == ZOIDFS_READ) { + NO_STALE(ret, fd, zoidfs_obj_ptr, + zoidfs_read(zoidfs_obj_ptr, + 1, &buf, &mem_len, + 1, &file_offset, &file_len, ZOIDFS_NO_OP_HINT)); + } else { + NO_STALE(ret, fd, zoidfs_obj_ptr, + zoidfs_write(zoidfs_obj_ptr, + 1, (const void **)&buf, &mem_len, + 1, &file_offset, &file_len, ZOIDFS_NO_OP_HINT)); + } + /* --BEGIN ERROR HANDLING-- */ + if (ret != ZFS_OK ) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(ret), + "Error in ZOIDFS I/O", 0); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind += file_len; + } + fd->fp_sys_posn = file_offset + file_len; + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, file_len); +#endif + + *error_code = MPI_SUCCESS; + +fn_exit: + return; +} + +void ADIOI_ZOIDFS_ReadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + ZOIDFS_IOContig(fd, buf, count, datatype, file_ptr_type, + offset, status, ZOIDFS_READ, error_code); +} + +void ADIOI_ZOIDFS_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + ZOIDFS_IOContig(fd, buf, count, datatype, file_ptr_type, + offset, status, ZOIDFS_WRITE, error_code); +} + + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_open.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_open.c new file mode 100644 index 0000000000..55fb950a3e --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_open.c @@ -0,0 +1,153 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 2007 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_zoidfs.h" +#include "ad_zoidfs_common.h" + +/* open_status is helpful for bcasting values around */ +struct open_status_s { + int error; + zoidfs_handle_t handle; +}; +typedef struct open_status_s open_status; + +static void fake_an_open(char *fname, int access_mode, + int nr_datafiles, MPI_Offset strip_size, + ADIOI_ZOIDFS_object *zoidfs_ptr, + open_status *o_status) +{ + int ret, created; + zoidfs_sattr_t attribs; + zoidfs_handle_t handle; + + ADIOI_ZOIDFS_makeattribs(&attribs); + + /* zoidfs_create succeeds even if a file already exists, so we can do + * our job with fewer calls than in other cases. However, we need to + * be careful with ADIO_EXCL. + */ + if (access_mode & ADIO_CREATE) { + ret = zoidfs_create(NULL, NULL, + fname, &attribs, &handle, &created, ZOIDFS_NO_OP_HINT); + if ((ret == ZFS_OK) && !created && (access_mode & ADIO_EXCL)) { + /* lookup should not succeed if opened with EXCL */ + o_status->error = ZFSERR_EXIST; + return; + } + } + else { + ret = zoidfs_lookup(NULL, NULL, fname, &handle, ZOIDFS_NO_OP_HINT); + } + + o_status->error = ret; + o_status->handle = handle; + return; +} + + +/* ADIOI_ZOIDFS_Open: + * one process opens (or creates) the file, then broadcasts the result to the + * remaining processors. + * + * ADIO_Open used to perform an optimization when MPI_MODE_CREATE (and before + * that, MPI_MODE_EXCL) was set. Because ZoidFS handles file lookup and + * creation more scalably than traditional file systems, ADIO_Open now skips any + * special handling when CREATE is set. */ +void ADIOI_ZOIDFS_Open(ADIO_File fd, int *error_code) +{ + int rank; + static char myname[] = "ADIOI_ZOIDFS_OPEN"; + ADIOI_ZOIDFS_object *zoidfs_obj_ptr; + + /* since one process is doing the open, that means one process is also + * doing the error checking. define a struct for both the object reference + * and the error code to broadcast to all the processors */ + + open_status o_status; + MPI_Datatype open_status_type; + MPI_Datatype types[2] = {MPI_INT, MPI_BYTE}; + int lens[2] = {1, sizeof(ADIOI_ZOIDFS_object)}; + MPI_Aint offsets[2]; + + memset(&o_status, 0, sizeof(o_status)); + zoidfs_obj_ptr = (ADIOI_ZOIDFS_object *) + ADIOI_Malloc(sizeof(ADIOI_ZOIDFS_object)); + /* --BEGIN ERROR HANDLING-- */ + if (zoidfs_obj_ptr == NULL) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_UNKNOWN, + "Error allocating memory", 0); + return; + } + /* --END ERROR HANDLING-- */ + + MPI_Comm_rank(fd->comm, &rank); + + ADIOI_ZOIDFS_Init(rank, error_code); + if (*error_code != MPI_SUCCESS) + { + /* ADIOI_ZOIDFS_INIT handles creating error codes on its own */ + ADIOI_Free(zoidfs_obj_ptr); + return; + } + + /* one process resolves name and will later bcast to others */ +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_a, 0, NULL ); +#endif + if (rank == fd->hints->ranklist[0] && fd->fs_ptr == NULL) { + fake_an_open(fd->filename, fd->access_mode, + fd->hints->striping_factor, + fd->hints->striping_unit, + zoidfs_obj_ptr, &o_status); + /* store credentials and object reference in fd */ + *zoidfs_obj_ptr = o_status.handle; + fd->fs_ptr = zoidfs_obj_ptr; + } +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_open_b, 0, NULL ); +#endif + + /* broadcast status and (possibly valid) object reference */ + MPI_Address(&o_status.error, &offsets[0]); + MPI_Address(&o_status.handle, &offsets[1]); + + MPI_Type_struct(2, lens, offsets, types, &open_status_type); + MPI_Type_commit(&open_status_type); + + /* Assertion: if we hit this Bcast, then all processes collectively + * called this open. + * + * That's because deferred open never happens with this fs. + */ + MPI_Bcast(MPI_BOTTOM, 1, open_status_type, fd->hints->ranklist[0], + fd->comm); + MPI_Type_free(&open_status_type); + + /* --BEGIN ERROR HANDLING-- */ + if (o_status.error != ZFS_OK) + { + ADIOI_Free(zoidfs_obj_ptr); + fd->fs_ptr = NULL; + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(o_status.error), + "Unknown error", 0); + /* TODO: FIX STRING */ + return; + } + /* --END ERROR HANDLING-- */ + + *zoidfs_obj_ptr = o_status.handle; + fd->fs_ptr = zoidfs_obj_ptr; + + *error_code = MPI_SUCCESS; + return; +} diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_read_list.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_read_list.c new file mode 100644 index 0000000000..d48a06c1bd --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_read_list.c @@ -0,0 +1,830 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "ad_zoidfs.h" + +#include "ad_zoidfs_common.h" + +/* Copied from ADIOI_PVFS2_OldReadStrided. It would be good to have fewer + * copies of this code... */ +void ADIOI_ZOIDFS_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 sum, n_etypes_in_filetype, size_in_filetype; + MPI_Count bufsize; + int n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0; + 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 off, disp, start_off, initial_off; + int flag, st_frd_size, st_n_filetypes; + + size_t mem_list_count, file_list_count; + void ** mem_offsets; + uint64_t *file_offsets; + size_t *mem_lengths; + uint64_t *file_lengths; + int total_blks_to_read; + + int max_mem_list, max_file_list; + + int b_blks_read; + int f_data_read; + int size_read=0, n_read_lists, extra_blks; + + int end_brd_size, end_frd_size; + int start_k, start_j, new_file_read, new_buffer_read; + int start_mem_offset; + ADIOI_ZOIDFS_object * zoidfs_obj_ptr; + int err_flag=0; + MPI_Offset total_bytes_read = 0; + static char myname[] = "ADIOI_ZOIDFS_ReadStrided"; + + /* note: I don't know what zoidfs will do if you pass it a super-long list, + * so let's keep with the PVFS limit for now */ +#define MAX_ARRAY_SIZE 64 + + *error_code = MPI_SUCCESS; /* changed below if error */ + + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + /* the HDF5 tests showed a bug in this list processing code (see many many + * lines down below). We added a workaround, but common HDF5 file types + * are actually contiguous and do not need the expensive workarond */ + if (!filetype_is_contig) { + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + if (flat_file->count == 1 && !buftype_is_contig) + filetype_is_contig = 1; + } + + 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; + + zoidfs_obj_ptr = (ADIOI_ZOIDFS_object *)fd->fs_ptr; + + if (!buftype_is_contig && filetype_is_contig) { + +/* noncontiguous in memory, contiguous in file. */ + uint64_t file_offsets; + uint64_t file_lengths; + + 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; + + file_list_count = 1; + file_offsets = off; + file_lengths = 0; + total_blks_to_read = count*flat_buf->count; + b_blks_read = 0; + + /* allocate arrays according to max usage */ + if (total_blks_to_read > MAX_ARRAY_SIZE) + mem_list_count = MAX_ARRAY_SIZE; + else mem_list_count = total_blks_to_read; + mem_offsets = (void*)ADIOI_Malloc(mem_list_count*sizeof(void*)); + mem_lengths = (size_t*)ADIOI_Malloc(mem_list_count*sizeof(size_t)); + + /* TODO: CHECK RESULTS OF MEMORY ALLOCATION */ + + j = 0; + /* step through each block in memory, filling memory arrays */ + while (b_blks_read < total_blks_to_read) { + for (i=0; icount; i++) { + mem_offsets[b_blks_read % MAX_ARRAY_SIZE] = + buf + j*buftype_extent + flat_buf->indices[i]; + mem_lengths[b_blks_read % MAX_ARRAY_SIZE] = + flat_buf->blocklens[i]; + file_lengths += flat_buf->blocklens[i]; + b_blks_read++; + if (!(b_blks_read % MAX_ARRAY_SIZE) || + (b_blks_read == total_blks_to_read)) { + + /* in the case of the last read list call, + adjust mem_list_count */ + if (b_blks_read == total_blks_to_read) { + mem_list_count = total_blks_to_read % MAX_ARRAY_SIZE; + /* in case last read list call fills max arrays */ + if (!mem_list_count) mem_list_count = MAX_ARRAY_SIZE; + } +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); +#endif + NO_STALE(err_flag, fd, zoidfs_obj_ptr, + zoidfs_read(zoidfs_obj_ptr, + mem_list_count, + mem_offsets, mem_lengths, + 1, &file_offsets, &file_lengths, ZOIDFS_NO_OP_HINT)); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != ZFS_OK) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(err_flag), + "Error in zoidfs_read", 0); + goto error_state; + } + total_bytes_read += file_lengths; + /* --END ERROR HANDLING-- */ + + /* in the case of error or the last read list call, + * leave here */ + if (err_flag || b_blks_read == total_blks_to_read) break; + + file_offsets += file_lengths; + file_lengths = 0; + } + } /* for (i=0; icount; i++) */ + j++; + } /* while (b_blks_read < total_blks_to_read) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + + if (file_ptr_type == ADIO_INDIVIDUAL) + fd->fp_ind += total_bytes_read; + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); + /* This isa temporary way of filling in status. The right way is to + keep tracke of how much data was actually read adn placed in buf + by ADIOI_BUFFERED_READ. */ +#endif + ADIOI_Delete_flattened(datatype); + + return; + } /* if (!buftype_is_contig && filetype_is_contig) */ + + /* know file is noncontiguous from above */ + /* 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; + initial_off = offset; + + + /* for each case - ADIO_Individual pointer or explicit, find the file + offset in bytes (offset), n_filetypes (how many filetypes into + file to start), frd_size (remaining amount of data in present + file block), and st_index (start point in terms of blocks in + starting filetype) */ + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; /* in bytes */ + n_filetypes = -1; + flag = 0; + while (!flag) { + n_filetypes++; + for (i=0; icount; i++) { + if (disp + flat_file->indices[i] + + ((ADIO_Offset) n_filetypes)*filetype_extent + + flat_file->blocklens[i] >= offset) { + st_index = i; + frd_size = disp + flat_file->indices[i] + + ((ADIO_Offset) n_filetypes)*filetype_extent + + flat_file->blocklens[i] - offset; + flag = 1; + break; + } + } + } /* while (!flag) */ + } /* if (file_ptr_type == ADIO_INDIVIDUAL) */ + 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; icount; 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; + } /* else [file_ptr_type != ADIO_INDIVIDUAL] */ + + start_off = offset; + st_frd_size = frd_size; + st_n_filetypes = n_filetypes; + + if (buftype_is_contig && !filetype_is_contig) { + +/* contiguous in memory, noncontiguous in file. should be the most + common case. */ + + /* only one memory off-len pair, so no array here */ + size_t mem_lengths; + size_t mem_offsets; + + i = 0; + j = st_index; + n_filetypes = st_n_filetypes; + + mem_list_count = 1; + + /* determine how many blocks in file to read */ + f_data_read = ADIOI_MIN(st_frd_size, bufsize); + total_blks_to_read = 1; + if (j < (flat_file->count-1)) j++; + else { + j = 0; + n_filetypes++; + } + while (f_data_read < bufsize) { + f_data_read += flat_file->blocklens[j]; + total_blks_to_read++; + if (j<(flat_file->count-1)) j++; + else j = 0; + } + + j = st_index; + n_filetypes = st_n_filetypes; + n_read_lists = total_blks_to_read/MAX_ARRAY_SIZE; + extra_blks = total_blks_to_read%MAX_ARRAY_SIZE; + + mem_offsets = (size_t)buf; + mem_lengths = 0; + + /* if at least one full readlist, allocate file arrays + at max array size and don't free until very end */ + if (n_read_lists) { + file_offsets = (int64_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int64_t)); + file_lengths = (uint64_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(uint64_t)); + } + /* if there's no full readlist allocate file arrays according + to needed size (extra_blks) */ + else { + file_offsets = (int64_t*)ADIOI_Malloc(extra_blks* + sizeof(int64_t)); + file_lengths = (uint64_t*)ADIOI_Malloc(extra_blks* + sizeof(uint64_t)); + } + + /* for file arrays that are of MAX_ARRAY_SIZE, build arrays */ + for (i=0; iindices[j]; + file_lengths[k] = flat_file->blocklens[j]; + mem_lengths += file_lengths[k]; + } + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kindices[j]; + if (k == (extra_blks - 1)) { + file_lengths[k] = bufsize - mem_lengths + - mem_offsets + (size_t)buf; + } + else file_lengths[k] = flat_file->blocklens[j]; + } /* if(i || k) */ + mem_lengths += file_lengths[k]; + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; ktype != datatype) flat_buf = flat_buf->next; + + size_read = 0; + n_filetypes = st_n_filetypes; + frd_size = st_frd_size; + brd_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + max_mem_list = 0; + max_file_list = 0; + + /* run through and file max_file_list and max_mem_list so that you + can allocate the file and memory arrays less than MAX_ARRAY_SIZE + if possible */ + + while (size_read < bufsize) { + k = start_k; + new_buffer_read = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data read and data to be + read in the next immediate read list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k] + + size_read) > bufsize) { + end_brd_size = new_buffer_read + + flat_buf->blocklens[k] - (bufsize - size_read); + new_buffer_read = bufsize - size_read; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + else new_buffer_read = brd_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + j = start_j; + new_file_read = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_read < new_buffer_read)) { + if(file_list_count) { + if((new_file_read + flat_file->blocklens[j]) > + new_buffer_read) { + end_frd_size = new_buffer_read - new_file_read; + new_file_read = new_buffer_read; + j--; + } + else { + new_file_read += flat_file->blocklens[j]; + end_frd_size = flat_file->blocklens[j]; + } + } + else { + if (frd_size > new_buffer_read) { + new_file_read = new_buffer_read; + frd_size = new_file_read; + } + else new_file_read = frd_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_read < new_buffer_read) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_read = 0; + mem_list_count = 0; + while (new_buffer_read < new_file_read) { + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k]) > + new_file_read) { + end_brd_size = new_file_read - new_buffer_read; + new_buffer_read = new_file_read; + k--; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_read = brd_size; + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_read < new_file_read) */ + } /* if ((new_file_read < new_buffer_read) && (file_list_count + == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + + /* fakes filling the readlist arrays of lengths found above */ + k = start_k; + j = start_j; + for (i=0; iblocklens[k] == end_brd_size) + brd_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + brd_size = flat_buf->blocklens[k] - end_brd_size; + k--; + buf_count--; + } + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iblocklens[j] == end_frd_size) + frd_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + frd_size = flat_file->blocklens[j] - end_frd_size; + j--; + } + } + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; iblocklens[0] ) ) || + ((mem_list_count == 1) && + (new_buffer_read < flat_buf->blocklens[0]) ) || + ((file_list_count == MAX_ARRAY_SIZE) && + (new_file_read < flat_buf->blocklens[0]) ) || + ( (mem_list_count == MAX_ARRAY_SIZE) && + (new_buffer_read < flat_file->blocklens[0])) ) + { + + ADIOI_Delete_flattened(datatype); + ADIOI_GEN_ReadStrided_naive(fd, buf, count, datatype, + file_ptr_type, initial_off, status, error_code); + return; + } + + mem_offsets = (void *)ADIOI_Malloc(max_mem_list*sizeof(void *)); + mem_lengths = (size_t*)ADIOI_Malloc(max_mem_list*sizeof(size_t)); + file_offsets = (uint64_t *)ADIOI_Malloc(max_file_list*sizeof(uint64_t)); + file_lengths = (uint64_t *)ADIOI_Malloc(max_file_list*sizeof(uint64_t)); + + size_read = 0; + n_filetypes = st_n_filetypes; + frd_size = st_frd_size; + brd_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + + /* this section calculates mem_list_count and file_list_count + and also finds the possibly odd sized last array elements + in new_frd_size and new_brd_size */ + + while (size_read < bufsize) { + k = start_k; + new_buffer_read = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data read and data to be + read in the next immediate read list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k] + + size_read) > bufsize) { + end_brd_size = new_buffer_read + + flat_buf->blocklens[k] - (bufsize - size_read); + new_buffer_read = bufsize - size_read; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + else new_buffer_read = brd_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + j = start_j; + new_file_read = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_read < new_buffer_read)) { + if(file_list_count) { + if((new_file_read + flat_file->blocklens[j]) > + new_buffer_read) { + end_frd_size = new_buffer_read - new_file_read; + new_file_read = new_buffer_read; + j--; + } + else { + new_file_read += flat_file->blocklens[j]; + end_frd_size = flat_file->blocklens[j]; + } + } + else { + if (frd_size > new_buffer_read) { + new_file_read = new_buffer_read; + frd_size = new_file_read; + } + else new_file_read = frd_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_read < new_buffer_read) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_read = 0; + mem_list_count = 0; + while (new_buffer_read < new_file_read) { + if(mem_list_count) { + if((new_buffer_read + flat_buf->blocklens[k]) > + new_file_read) { + end_brd_size = new_file_read - new_buffer_read; + new_buffer_read = new_file_read; + k--; + } + else { + new_buffer_read += flat_buf->blocklens[k]; + end_brd_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_read = brd_size; + if (brd_size > (bufsize - size_read)) { + new_buffer_read = bufsize - size_read; + brd_size = new_buffer_read; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_read < new_file_read) */ + } /* if ((new_file_read < new_buffer_read) && (file_list_count + == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_read < bufsize-size_read)) */ + + /* fills the allocated readlist arrays */ + k = start_k; + j = start_j; + for (i=0; icount) + + flat_buf->indices[k]; + if(!i) { + mem_lengths[0] = brd_size; + mem_offsets[0] += flat_buf->blocklens[k] - brd_size; + } + else { + if (i == (mem_list_count - 1)) { + mem_lengths[i] = end_brd_size; + if (flat_buf->blocklens[k] == end_brd_size) + brd_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + brd_size = flat_buf->blocklens[k] - end_brd_size; + k--; + buf_count--; + } + } + else { + mem_lengths[i] = flat_buf->blocklens[k]; + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iindices[j] + + ((ADIO_Offset)n_filetypes) * filetype_extent; + if (!i) { + file_lengths[0] = frd_size; + file_offsets[0] += flat_file->blocklens[j] - frd_size; + } + else { + if (i == (file_list_count - 1)) { + file_lengths[i] = end_frd_size; + if (flat_file->blocklens[j] == end_frd_size) + frd_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + frd_size = flat_file->blocklens[j] - end_frd_size; + j--; + } + } + else file_lengths[i] = flat_file->blocklens[j]; + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; ifp_ind = file_offsets[file_list_count-1]+ + file_lengths[file_list_count-1]; + } + + ADIOI_Free(file_offsets); + ADIOI_Free(file_lengths); + + if (err_flag == 0) *error_code = MPI_SUCCESS; + +error_state: + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, 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 + by ADIOI_BUFFERED_READ. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} + diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_resize.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_resize.c new file mode 100644 index 0000000000..60d2fcaba2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_resize.c @@ -0,0 +1,53 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "ad_zoidfs.h" +#include "ad_zoidfs_common.h" + +/* as with flush, implement the resize operation in a scalable + * manner. one process does the work, then broadcasts the result to everyone + * else. fortunately, this operation is defined to be collective */ +void ADIOI_ZOIDFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int ret, rank; + ADIOI_ZOIDFS_object *zoidfs_obj_ptr; + static char myname[] = "ADIOI_ZOIDFS_RESIZE"; + + *error_code = MPI_SUCCESS; + + zoidfs_obj_ptr = (ADIOI_ZOIDFS_object *)fd->fs_ptr; + + MPI_Comm_rank(fd->comm, &rank); + + + /* MPI-IO semantics treat conflicting MPI_File_set_size requests the + * same as conflicting write requests. Thus, a resize from one + * process does not have to be visible to the other processes until a + * syncronization point is reached */ + + if (rank == fd->hints->ranklist[0]) { + NO_STALE(ret, fd, zoidfs_obj_ptr, + zoidfs_resize(zoidfs_obj_ptr, size, ZOIDFS_NO_OP_HINT)); + MPI_Bcast(&ret, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + } else { + MPI_Bcast(&ret, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + } + /* --BEGIN ERROR HANDLING-- */ + if (ret != ZFS_OK) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(ret), + "Error in zoidfs_resize", 0); + return; + } + /* --END ERROR HANDLING-- */ +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_write_list.c b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_write_list.c new file mode 100644 index 0000000000..8ca0594fe5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/ad_zoidfs/ad_zoidfs_write_list.c @@ -0,0 +1,861 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "ad_zoidfs.h" + +#include "ad_zoidfs_common.h" + +/* Copied from ADIOI_PVFS2_OldWriteStrided. It would be good to have fewer + * copies of this code... */ +void ADIOI_ZOIDFS_WriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + /* as with all the other WriteStrided functions, offset is in units of + * etype relative to the filetype */ + + /* Since zoidfs does not support file locking, can't do buffered writes + as on Unix */ + + ADIOI_Flatlist_node *flat_buf, *flat_file; + int i, j, k, bwr_size, fwr_size=0, st_index=0; + int sum, n_etypes_in_filetype, size_in_filetype; + MPI_Count bufsize; + int n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0; + 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 off, disp, start_off, initial_off; + int flag, st_fwr_size, st_n_filetypes; + int err_flag=0; + + size_t mem_list_count, file_list_count; + const void ** mem_offsets; + uint64_t *file_offsets; + size_t *mem_lengths; + uint64_t *file_lengths; + int total_blks_to_write; + + int max_mem_list, max_file_list; + + int b_blks_wrote; + int f_data_wrote; + int size_wrote=0, n_write_lists, extra_blks; + + int end_bwr_size, end_fwr_size; + int start_k, start_j, new_file_write, new_buffer_write; + int start_mem_offset; + ADIOI_ZOIDFS_object *zoidfs_obj_ptr; + MPI_Offset total_bytes_written=0; + static char myname[] = "ADIOI_ZOIDFS_WRITESTRIDED"; + + /* note: I don't know what zoidfs will do if you pass it a super-long list, + * so let's keep with the PVFS limit for now */ +#define MAX_ARRAY_SIZE 64 + + /* --BEGIN ERROR HANDLING-- */ + if (fd->atomicity) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "Atomic noncontiguous writes are not supported by ZOIDFS", 0); + return; + } + /* --END ERROR HANDLING-- */ + + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + /* the HDF5 tests showed a bug in this list processing code (see many many + * lines down below). We added a workaround, but common HDF5 file types + * are actually contiguous and do not need the expensive workarond */ + if (!filetype_is_contig) { + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + if (flat_file->count == 1 && !buftype_is_contig) + filetype_is_contig = 1; + } + + 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; + + zoidfs_obj_ptr = (ADIOI_ZOIDFS_object*)fd->fs_ptr; + + if (!buftype_is_contig && filetype_is_contig) { + +/* noncontiguous in memory, contiguous in file. */ + uint64_t file_offsets; + uint64_t file_lengths; + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + etype_size * offset; + } + else off = fd->fp_ind; + + file_list_count = 1; + file_offsets = off; + file_lengths = 0; + total_blks_to_write = count*flat_buf->count; + b_blks_wrote = 0; + + /* allocate arrays according to max usage */ + if (total_blks_to_write > MAX_ARRAY_SIZE) + mem_list_count = MAX_ARRAY_SIZE; + else mem_list_count = total_blks_to_write; + mem_offsets = (void*)ADIOI_Malloc(mem_list_count*sizeof(void*)); + mem_lengths = (size_t*)ADIOI_Malloc(mem_list_count*sizeof(size_t)); + + j = 0; + /* step through each block in memory, filling memory arrays */ + while (b_blks_wrote < total_blks_to_write) { + for (i=0; icount; i++) { + mem_offsets[b_blks_wrote % MAX_ARRAY_SIZE] = + buf + + j*buftype_extent + + flat_buf->indices[i]; + mem_lengths[b_blks_wrote % MAX_ARRAY_SIZE] = + flat_buf->blocklens[i]; + file_lengths += flat_buf->blocklens[i]; + b_blks_wrote++; + if (!(b_blks_wrote % MAX_ARRAY_SIZE) || + (b_blks_wrote == total_blks_to_write)) { + + /* in the case of the last write list call, + adjust mem_list_count */ + if (b_blks_wrote == total_blks_to_write) { + mem_list_count = total_blks_to_write % MAX_ARRAY_SIZE; + /* in case last write list call fills max arrays */ + if (!mem_list_count) mem_list_count = MAX_ARRAY_SIZE; + } +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + NO_STALE(err_flag, fd, zoidfs_obj_ptr, + zoidfs_write(zoidfs_obj_ptr, + mem_list_count, + mem_offsets, mem_lengths, + 1, &file_offsets, &file_lengths, ZOIDFS_NO_OP_HINT)); + + /* --BEGIN ERROR HANDLING-- */ + if (err_flag != ZFS_OK) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(err_flag), + "Error in zoidfs_write", 0); + break; + } +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + total_bytes_written += file_lengths; + + /* in the case of error or the last write list call, + * leave here */ + /* --BEGIN ERROR HANDLING-- */ + if (err_flag) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + ADIOI_ZOIDFS_error_convert(err_flag), + "Error in zoidfs_write", 0); + break; + } + /* --END ERROR HANDLING-- */ + if (b_blks_wrote == total_blks_to_write) break; + + file_offsets += file_lengths; + file_lengths = 0; + } + } /* for (i=0; icount; i++) */ + j++; + } /* while (b_blks_wrote < total_blks_to_write) */ + ADIOI_Free(mem_offsets); + ADIOI_Free(mem_lengths); + + if (file_ptr_type == ADIO_INDIVIDUAL) + fd->fp_ind += total_bytes_written; + + if (!err_flag) *error_code = MPI_SUCCESS; + + fd->fp_sys_posn = -1; /* clear this. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + ADIOI_Delete_flattened(datatype); + return; + } /* if (!buftype_is_contig && filetype_is_contig) */ + + /* already know that file is noncontiguous from above */ + /* 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; + initial_off = offset; + + /* for each case - ADIO_Individual pointer or explicit, find offset + (file offset in bytes), n_filetypes (how many filetypes into file + to start), fwr_size (remaining amount of data in present file + block), and st_index (start point in terms of blocks in starting + filetype) */ + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; /* in bytes */ + n_filetypes = -1; + flag = 0; + while (!flag) { + n_filetypes++; + for (i=0; icount; i++) { + if (disp + flat_file->indices[i] + + ((ADIO_Offset) n_filetypes)*filetype_extent + + flat_file->blocklens[i] >= offset) { + st_index = i; + fwr_size = disp + flat_file->indices[i] + + ((ADIO_Offset) n_filetypes)*filetype_extent + + flat_file->blocklens[i] - offset; + flag = 1; + break; + } + } + } /* while (!flag) */ + } /* if (file_ptr_type == ADIO_INDIVIDUAL) */ + 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; icount; 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; + } /* else [file_ptr_type != ADIO_INDIVIDUAL] */ + + start_off = offset; + st_fwr_size = fwr_size; + st_n_filetypes = n_filetypes; + + if (buftype_is_contig && !filetype_is_contig) { + +/* contiguous in memory, noncontiguous in file. should be the most + common case. */ + + /* only one memory off-len pair, so no array */ + size_t mem_lengths; + size_t mem_offsets; + + i = 0; + j = st_index; + off = offset; + n_filetypes = st_n_filetypes; + + mem_list_count = 1; + + /* determine how many blocks in file to write */ + f_data_wrote = ADIOI_MIN(st_fwr_size, bufsize); + total_blks_to_write = 1; + if (j < (flat_file->count -1)) j++; + else { + j = 0; + n_filetypes++; + } + while (f_data_wrote < bufsize) { + f_data_wrote += flat_file->blocklens[j]; + total_blks_to_write++; + if (j<(flat_file->count-1)) j++; + else j = 0; + } + + j = st_index; + n_filetypes = st_n_filetypes; + n_write_lists = total_blks_to_write/MAX_ARRAY_SIZE; + extra_blks = total_blks_to_write%MAX_ARRAY_SIZE; + + mem_offsets = (size_t)buf; + mem_lengths = 0; + + /* if at least one full writelist, allocate file arrays + at max array size and don't free until very end */ + if (n_write_lists) { + file_offsets = (int64_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(int64_t)); + file_lengths = (uint64_t*)ADIOI_Malloc(MAX_ARRAY_SIZE* + sizeof(uint64_t)); + } + /* if there's no full writelist allocate file arrays according + to needed size (extra_blks) */ + else { + file_offsets = (int64_t*)ADIOI_Malloc(extra_blks* + sizeof(int64_t)); + file_lengths = (uint64_t*)ADIOI_Malloc(extra_blks* + sizeof(uint64_t)); + } + + /* for file arrays that are of MAX_ARRAY_SIZE, build arrays */ + for (i=0; iindices[j]; + file_lengths[k] = flat_file->blocklens[j]; + mem_lengths += file_lengths[k]; + } + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; kindices[j]; + /* XXX: double-check these casts */ + if (k == (extra_blks - 1)) { + file_lengths[k] = bufsize + - mem_lengths - mem_offsets + (size_t)buf; + } + else file_lengths[k] = flat_file->blocklens[j]; + } /* if(i || k) */ + mem_lengths += file_lengths[k]; + if (j<(flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (k=0; ktype != datatype) flat_buf = flat_buf->next; + + size_wrote = 0; + n_filetypes = st_n_filetypes; + fwr_size = st_fwr_size; + bwr_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + max_mem_list = 0; + max_file_list = 0; + + /* run through and file max_file_list and max_mem_list so that you + can allocate the file and memory arrays less than MAX_ARRAY_SIZE + if possible */ + + while (size_wrote < bufsize) { + k = start_k; + new_buffer_write = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data written and data to be + written in the next immediate write list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k] + + size_wrote) > bufsize) { + end_bwr_size = new_buffer_write + + flat_buf->blocklens[k] - (bufsize - size_wrote); + new_buffer_write = bufsize - size_wrote; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + else new_buffer_write = bwr_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + j = start_j; + new_file_write = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_write < new_buffer_write)) { + if(file_list_count) { + if((new_file_write + flat_file->blocklens[j]) > + new_buffer_write) { + end_fwr_size = new_buffer_write - new_file_write; + new_file_write = new_buffer_write; + j--; + } + else { + new_file_write += flat_file->blocklens[j]; + end_fwr_size = flat_file->blocklens[j]; + } + } + else { + if (fwr_size > new_buffer_write) { + new_file_write = new_buffer_write; + fwr_size = new_file_write; + } + else new_file_write = fwr_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_write = 0; + mem_list_count = 0; + while (new_buffer_write < new_file_write) { + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k]) > + new_file_write) { + end_bwr_size = new_file_write - + new_buffer_write; + new_buffer_write = new_file_write; + k--; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_write = bwr_size; + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_write < new_file_write) */ + } /* if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + + /* fakes filling the writelist arrays of lengths found above */ + k = start_k; + j = start_j; + for (i=0; iblocklens[k] == end_bwr_size) + bwr_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + bwr_size = flat_buf->blocklens[k] - end_bwr_size; + k--; + buf_count--; + } + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iblocklens[j] == end_fwr_size) + fwr_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + fwr_size = flat_file->blocklens[j] - end_fwr_size; + j--; + } + } + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; iblocklens[0] ) ) || + ((mem_list_count == 1) && + (new_buffer_write < flat_buf->blocklens[0]) ) || + ((file_list_count == MAX_ARRAY_SIZE) && + (new_file_write < flat_buf->blocklens[0]) ) || + ( (mem_list_count == MAX_ARRAY_SIZE) && + (new_buffer_write < flat_file->blocklens[0])) ) + { + ADIOI_Delete_flattened(datatype); + ADIOI_GEN_WriteStrided_naive(fd, buf, count, datatype, + file_ptr_type, initial_off, status, error_code); + return; + } + + + mem_offsets = (void *)ADIOI_Malloc(max_mem_list*sizeof(void *)); + mem_lengths = (size_t*)ADIOI_Malloc(max_mem_list*sizeof(size_t)); + file_offsets = (uint64_t *)ADIOI_Malloc(max_file_list*sizeof(uint64_t)); + file_lengths = (uint64_t*)ADIOI_Malloc(max_file_list*sizeof(uint64_t)); + + size_wrote = 0; + n_filetypes = st_n_filetypes; + fwr_size = st_fwr_size; + bwr_size = flat_buf->blocklens[0]; + buf_count = 0; + start_mem_offset = 0; + start_k = k = 0; + start_j = st_index; + + /* this section calculates mem_list_count and file_list_count + and also finds the possibly odd sized last array elements + in new_fwr_size and new_bwr_size */ + + while (size_wrote < bufsize) { + k = start_k; + new_buffer_write = 0; + mem_list_count = 0; + while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) { + /* find mem_list_count and file_list_count such that both are + less than MAX_ARRAY_SIZE, the sum of their lengths are + equal, and the sum of all the data written and data to be + written in the next immediate write list is less than + bufsize */ + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k] + + size_wrote) > bufsize) { + end_bwr_size = new_buffer_write + + flat_buf->blocklens[k] - (bufsize - size_wrote); + new_buffer_write = bufsize - size_wrote; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + else new_buffer_write = bwr_size; + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + j = start_j; + new_file_write = 0; + file_list_count = 0; + while ((file_list_count < MAX_ARRAY_SIZE) && + (new_file_write < new_buffer_write)) { + if(file_list_count) { + if((new_file_write + flat_file->blocklens[j]) > + new_buffer_write) { + end_fwr_size = new_buffer_write - new_file_write; + new_file_write = new_buffer_write; + j--; + } + else { + new_file_write += flat_file->blocklens[j]; + end_fwr_size = flat_file->blocklens[j]; + } + } + else { + if (fwr_size > new_buffer_write) { + new_file_write = new_buffer_write; + fwr_size = new_file_write; + } + else new_file_write = fwr_size; + } + file_list_count++; + if (j < (flat_file->count - 1)) j++; + else j = 0; + + k = start_k; + if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) { + new_buffer_write = 0; + mem_list_count = 0; + while (new_buffer_write < new_file_write) { + if(mem_list_count) { + if((new_buffer_write + flat_buf->blocklens[k]) > + new_file_write) { + end_bwr_size = new_file_write - + new_buffer_write; + new_buffer_write = new_file_write; + k--; + } + else { + new_buffer_write += flat_buf->blocklens[k]; + end_bwr_size = flat_buf->blocklens[k]; + } + } + else { + new_buffer_write = bwr_size; + if (bwr_size > (bufsize - size_wrote)) { + new_buffer_write = bufsize - size_wrote; + bwr_size = new_buffer_write; + } + } + mem_list_count++; + k = (k + 1)%flat_buf->count; + } /* while (new_buffer_write < new_file_write) */ + } /* if ((new_file_write < new_buffer_write) && + (file_list_count == MAX_ARRAY_SIZE)) */ + } /* while ((mem_list_count < MAX_ARRAY_SIZE) && + (new_buffer_write < bufsize-size_wrote)) */ + + /* fills the allocated writelist arrays */ + k = start_k; + j = start_j; + for (i=0; icount) + + flat_buf->indices[k]; + + if(!i) { + mem_lengths[0] = bwr_size; + mem_offsets[0] += flat_buf->blocklens[k] - bwr_size; + } + else { + if (i == (mem_list_count - 1)) { + mem_lengths[i] = end_bwr_size; + if (flat_buf->blocklens[k] == end_bwr_size) + bwr_size = flat_buf->blocklens[(k+1)% + flat_buf->count]; + else { + bwr_size = flat_buf->blocklens[k] - end_bwr_size; + k--; + buf_count--; + } + } + else { + mem_lengths[i] = flat_buf->blocklens[k]; + } + } + buf_count++; + k = (k + 1)%flat_buf->count; + } /* for (i=0; iindices[j] + + ((ADIO_Offset)n_filetypes) * filetype_extent; + if (!i) { + file_lengths[0] = fwr_size; + file_offsets[0] += flat_file->blocklens[j] - fwr_size; + } + else { + if (i == (file_list_count - 1)) { + file_lengths[i] = end_fwr_size; + if (flat_file->blocklens[j] == end_fwr_size) + fwr_size = flat_file->blocklens[(j+1)% + flat_file->count]; + else { + fwr_size = flat_file->blocklens[j] - end_fwr_size; + j--; + } + } + else file_lengths[i] = flat_file->blocklens[j]; + } + if (j < flat_file->count - 1) j++; + else { + j = 0; + n_filetypes++; + } + } /* for (i=0; ifp_ind = file_offsets[file_list_count-1]+ + file_lengths[file_list_count-1]; + } + ADIOI_Free(file_offsets); + ADIOI_Free(file_lengths); + + *error_code = MPI_SUCCESS; + +error_state: + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/Makefile.mk b/ompi/mca/io/romio314/romio/adio/common/Makefile.mk new file mode 100644 index 0000000000..6cfd118bc2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/Makefile.mk @@ -0,0 +1,73 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +romio_other_sources += \ + adio/common/ad_aggregate.c \ + adio/common/ad_aggregate_new.c \ + adio/common/ad_close.c \ + adio/common/ad_coll_build_req_new.c \ + adio/common/ad_coll_exch_new.c \ + adio/common/ad_darray.c \ + adio/common/ad_delete.c \ + adio/common/ad_done.c \ + adio/common/ad_done_fake.c \ + adio/common/ad_end.c \ + adio/common/ad_fcntl.c \ + adio/common/ad_features.c \ + adio/common/ad_flush.c \ + adio/common/ad_fstype.c \ + adio/common/ad_get_sh_fp.c \ + adio/common/ad_hints.c \ + adio/common/ad_init.c \ + adio/common/ad_io_coll.c \ + adio/common/ad_iopen.c \ + adio/common/ad_iread.c \ + adio/common/ad_iread_fake.c \ + adio/common/ad_iwrite.c \ + adio/common/ad_iwrite_fake.c \ + adio/common/ad_open.c \ + adio/common/ad_opencoll.c \ + adio/common/ad_opencoll_failsafe.c \ + adio/common/ad_opencoll_scalable.c \ + adio/common/ad_prealloc.c \ + adio/common/ad_read.c \ + adio/common/ad_read_coll.c \ + adio/common/ad_read_str.c \ + adio/common/ad_read_str_naive.c \ + adio/common/ad_resize.c \ + adio/common/ad_seek.c \ + adio/common/ad_set_sh_fp.c \ + adio/common/ad_set_view.c \ + adio/common/ad_subarray.c \ + adio/common/ad_wait.c \ + adio/common/ad_wait_fake.c \ + adio/common/ad_write.c \ + adio/common/ad_write_coll.c \ + adio/common/ad_write_nolock.c \ + adio/common/ad_write_str.c \ + adio/common/ad_write_str_naive.c \ + adio/common/adi_close.c \ + adio/common/byte_offset.c \ + adio/common/cb_config_list.c \ + adio/common/eof_offset.c \ + adio/common/error.c \ + adio/common/flatten.c \ + adio/common/get_fp_posn.c \ + adio/common/greq_fns.c \ + adio/common/heap-sort.c \ + adio/common/iscontig.c \ + adio/common/lock.c \ + adio/common/malloc.c \ + adio/common/shfp_fname.c \ + adio/common/status_setb.c \ + adio/common/strfns.c \ + adio/common/system_hints.c \ + adio/common/hint_fns.c \ + adio/common/ad_threaded_io.c \ + adio/common/p2p_aggregation.c \ + adio/common/utils.c + diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_aggregate.c b/ompi/mca/io/romio314/romio/adio/common/ad_aggregate.c new file mode 100644 index 0000000000..55b55440df --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_aggregate.c @@ -0,0 +1,515 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997-2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + +#undef AGG_DEBUG + +/* This file contains four functions: + * + * ADIOI_Calc_aggregator() + * ADIOI_Calc_file_domains() + * ADIOI_Calc_my_req() + * ADIOI_Calc_others_req() + * + * The last three of these were originally in ad_read_coll.c, but they are + * also shared with ad_write_coll.c. I felt that they were better kept with + * the rest of the shared aggregation code. + */ + +/* Discussion of values available from above: + * + * ADIO_Offset st_offsets[0..nprocs-1] + * ADIO_Offset end_offsets[0..nprocs-1] + * These contain a list of start and end offsets for each process in + * the communicator. For example, an access at loc 10, size 10 would + * have a start offset of 10 and end offset of 19. + * int nprocs + * number of processors in the collective I/O communicator + * ADIO_Offset min_st_offset + * ADIO_Offset fd_start[0..nprocs_for_coll-1] + * starting location of "file domain"; region that a given process will + * perform aggregation for (i.e. actually do I/O) + * ADIO_Offset fd_end[0..nprocs_for_coll-1] + * start + size - 1 roughly, but it can be less, or 0, in the case of + * uneven distributions + */ + +/* ADIOI_Calc_aggregator() + * + * The intention here is to implement a function which provides basically + * the same functionality as in Rajeev's original version of + * ADIOI_Calc_my_req(). He used a ceiling division approach to assign the + * file domains, and we use the same approach here when calculating the + * location of an offset/len in a specific file domain. Further we assume + * this same distribution when calculating the rank_index, which is later + * used to map to a specific process rank in charge of the file domain. + * + * A better (i.e. more general) approach would be to use the list of file + * domains only. This would be slower in the case where the + * original ceiling division was used, but it would allow for arbitrary + * distributions of regions to aggregators. We'd need to know the + * nprocs_for_coll in that case though, which we don't have now. + * + * Note a significant difference between this function and Rajeev's old code: + * this code doesn't necessarily return a rank in the range + * 0..nprocs_for_coll; instead you get something in 0..nprocs. This is a + * result of the rank mapping; any set of ranks in the communicator could be + * used now. + * + * Returns an integer representing a rank in the collective I/O communicator. + * + * The "len" parameter is also modified to indicate the amount of data + * actually available in this file domain. + */ +int ADIOI_Calc_aggregator(ADIO_File fd, + ADIO_Offset off, + ADIO_Offset min_off, + ADIO_Offset *len, + ADIO_Offset fd_size, + ADIO_Offset *fd_start, + ADIO_Offset *fd_end) +{ + int rank_index, rank; + ADIO_Offset avail_bytes; + + ADIOI_UNREFERENCED_ARG(fd_start); + + /* get an index into our array of aggregators */ + rank_index = (int) ((off - min_off + fd_size)/ fd_size - 1); + + if (fd->hints->striping_unit > 0) { + /* wkliao: implementation for file domain alignment + fd_start[] and fd_end[] have been aligned with file lock + boundaries when returned from ADIOI_Calc_file_domains() so cannot + just use simple arithmatic as above */ + rank_index = 0; + while (off > fd_end[rank_index]) rank_index++; + } + + /* we index into fd_end with rank_index, and fd_end was allocated to be no + * bigger than fd->hins->cb_nodes. If we ever violate that, we're + * overrunning arrays. Obviously, we should never ever hit this abort */ + if (rank_index >= fd->hints->cb_nodes || rank_index < 0) { + FPRINTF(stderr, "Error in ADIOI_Calc_aggregator(): rank_index(%d) >= fd->hints->cb_nodes (%d) fd_size=%lld off=%lld\n", + rank_index,fd->hints->cb_nodes,fd_size,off); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + /* remember here that even in Rajeev's original code it was the case that + * different aggregators could end up with different amounts of data to + * aggregate. here we use fd_end[] to make sure that we know how much + * data this aggregator is working with. + * + * the +1 is to take into account the end vs. length issue. + */ + avail_bytes = fd_end[rank_index] + 1 - off; + if (avail_bytes < *len) { + /* this file domain only has part of the requested contig. region */ + *len = avail_bytes; + } + + /* map our index to a rank */ + /* NOTE: FOR NOW WE DON'T HAVE A MAPPING...JUST DO 0..NPROCS_FOR_COLL */ + rank = fd->hints->ranklist[rank_index]; + + return rank; +} + +void ADIOI_Calc_file_domains(ADIO_Offset *st_offsets, ADIO_Offset + *end_offsets, int nprocs, int nprocs_for_coll, + ADIO_Offset *min_st_offset_ptr, + ADIO_Offset **fd_start_ptr, ADIO_Offset + **fd_end_ptr, int min_fd_size, + ADIO_Offset *fd_size_ptr, + int striping_unit) +{ +/* Divide the I/O workload among "nprocs_for_coll" processes. This is + done by (logically) dividing the file into file domains (FDs); each + process may directly access only its own file domain. */ + + ADIO_Offset min_st_offset, max_end_offset, *fd_start, *fd_end, fd_size; + int i; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5004, 0, NULL); +#endif + +#ifdef AGG_DEBUG + FPRINTF(stderr, "ADIOI_Calc_file_domains: %d aggregator(s)\n", + nprocs_for_coll); +#endif + +/* find min of start offsets and max of end offsets of all processes */ + + min_st_offset = st_offsets[0]; + max_end_offset = end_offsets[0]; + + for (i=1; i 0) { + ADIO_Offset end_off; + int rem_front, rem_back; + + /* align fd_end[0] to the nearest file lock boundary */ + fd_start[0] = min_st_offset; + end_off = fd_start[0] + fd_size; + rem_front = end_off % striping_unit; + rem_back = striping_unit - rem_front; + if (rem_front < rem_back) + end_off -= rem_front; + else + end_off += rem_back; + fd_end[0] = end_off - 1; + + /* align fd_end[i] to the nearest file lock boundary */ + for (i=1; i max_end_offset) + fd_start[i] = fd_end[i] = -1; + if (fd_end[i] > max_end_offset) + fd_end[i] = max_end_offset; + } + + *fd_size_ptr = fd_size; + *min_st_offset_ptr = min_st_offset; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5005, 0, NULL); +#endif +} + + +/* ADIOI_Calc_my_req() - calculate what portions of the access requests + * of this process are located in the file domains of various processes + * (including this one) + */ +void ADIOI_Calc_my_req(ADIO_File fd, ADIO_Offset *offset_list, ADIO_Offset *len_list, + int contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset *fd_start, + ADIO_Offset *fd_end, ADIO_Offset fd_size, + int nprocs, + int *count_my_req_procs_ptr, + int **count_my_req_per_proc_ptr, + ADIOI_Access **my_req_ptr, + int **buf_idx_ptr) +/* Possibly reconsider if buf_idx's are ok as int's, or should they be aints/offsets? + They are used as memory buffer indices so it seems like the 2G limit is in effect */ +{ + int *count_my_req_per_proc, count_my_req_procs, *buf_idx; + int i, l, proc; + ADIO_Offset fd_len, rem_len, curr_idx, off; + ADIOI_Access *my_req; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5024, 0, NULL); +#endif + + *count_my_req_per_proc_ptr = (int *) ADIOI_Calloc(nprocs,sizeof(int)); + count_my_req_per_proc = *count_my_req_per_proc_ptr; +/* count_my_req_per_proc[i] gives the no. of contig. requests of this + process in process i's file domain. calloc initializes to zero. + I'm allocating memory of size nprocs, so that I can do an + MPI_Alltoall later on.*/ + + buf_idx = (int *) ADIOI_Malloc(nprocs*sizeof(int)); +/* buf_idx is relevant only if buftype_is_contig. + buf_idx[i] gives the index into user_buf where data received + from proc. i should be placed. This allows receives to be done + without extra buffer. This can't be done if buftype is not contig. */ + + /* initialize buf_idx to -1 */ + for (i=0; i < nprocs; i++) buf_idx[i] = -1; + + /* one pass just to calculate how much space to allocate for my_req; + * contig_access_count was calculated way back in ADIOI_Calc_my_off_len() + */ + for (i=0; i < contig_access_count; i++) { + /* short circuit offset/len processing if len == 0 + * (zero-byte read/write */ + if (len_list[i] == 0) + continue; + off = offset_list[i]; + fd_len = len_list[i]; + /* note: we set fd_len to be the total size of the access. then + * ADIOI_Calc_aggregator() will modify the value to return the + * amount that was available from the file domain that holds the + * first part of the access. + */ + proc = ADIOI_Calc_aggregator(fd, off, min_st_offset, &fd_len, fd_size, + fd_start, fd_end); + count_my_req_per_proc[proc]++; + + /* figure out how much data is remaining in the access (i.e. wasn't + * part of the file domain that had the starting byte); we'll take + * care of this data (if there is any) in the while loop below. + */ + rem_len = len_list[i] - fd_len; + + while (rem_len != 0) { + off += fd_len; /* point to first remaining byte */ + fd_len = rem_len; /* save remaining size, pass to calc */ + proc = ADIOI_Calc_aggregator(fd, off, min_st_offset, &fd_len, + fd_size, fd_start, fd_end); + + count_my_req_per_proc[proc]++; + rem_len -= fd_len; /* reduce remaining length by amount from fd */ + } + } + +/* now allocate space for my_req, offset, and len */ + + *my_req_ptr = (ADIOI_Access *) + ADIOI_Malloc(nprocs*sizeof(ADIOI_Access)); + my_req = *my_req_ptr; + + count_my_req_procs = 0; + for (i=0; i < nprocs; i++) { + if (count_my_req_per_proc[i]) { + my_req[i].offsets = (ADIO_Offset *) + ADIOI_Malloc(count_my_req_per_proc[i] * sizeof(ADIO_Offset)); + my_req[i].lens = + ADIOI_Malloc(count_my_req_per_proc[i] * sizeof(ADIO_Offset)); + count_my_req_procs++; + } + my_req[i].count = 0; /* will be incremented where needed + later */ + } + +/* now fill in my_req */ + curr_idx = 0; + for (i=0; i 0) { + FPRINTF(stdout, "data needed from %d (count = %d):\n", i, + my_req[i].count); + for (l=0; l < my_req[i].count; l++) { + FPRINTF(stdout, " off[%d] = %lld, len[%d] = %d\n", l, + my_req[i].offsets[l], l, my_req[i].lens[l]); + } + FPRINTF(stdout, "buf_idx[%d] = 0x%x\n", i, buf_idx[i]); + } + } +#endif + + *count_my_req_procs_ptr = count_my_req_procs; + *buf_idx_ptr = buf_idx; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5025, 0, NULL); +#endif +} + + + +void ADIOI_Calc_others_req(ADIO_File fd, int count_my_req_procs, + int *count_my_req_per_proc, + ADIOI_Access *my_req, + int nprocs, int myrank, + int *count_others_req_procs_ptr, + ADIOI_Access **others_req_ptr) +{ +/* determine what requests of other processes lie in this process's + file domain */ + +/* count_others_req_procs = number of processes whose requests lie in + this process's file domain (including this process itself) + count_others_req_per_proc[i] indicates how many separate contiguous + requests of proc. i lie in this process's file domain. */ + + int *count_others_req_per_proc, count_others_req_procs; + int i, j; + MPI_Request *requests; + MPI_Status *statuses; + ADIOI_Access *others_req; + +/* first find out how much to send/recv and from/to whom */ +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5026, 0, NULL); +#endif + count_others_req_per_proc = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + + MPI_Alltoall(count_my_req_per_proc, 1, MPI_INT, + count_others_req_per_proc, 1, MPI_INT, fd->comm); + + *others_req_ptr = (ADIOI_Access *) + ADIOI_Malloc(nprocs*sizeof(ADIOI_Access)); + others_req = *others_req_ptr; + + count_others_req_procs = 0; + for (i=0; icomm, &requests[j]); + j++; + MPI_Irecv(others_req[i].lens, others_req[i].count, + ADIO_OFFSET, i, i+myrank+1, fd->comm, &requests[j]); + j++; + } + } + + for (i=0; i < nprocs; i++) { + if (my_req[i].count) { + MPI_Isend(my_req[i].offsets, my_req[i].count, + ADIO_OFFSET, i, i+myrank, fd->comm, &requests[j]); + j++; + MPI_Isend(my_req[i].lens, my_req[i].count, + ADIO_OFFSET, i, i+myrank+1, fd->comm, &requests[j]); + j++; + } + } + + if (j) { + statuses = (MPI_Status *) ADIOI_Malloc(j * sizeof(MPI_Status)); + MPI_Waitall(j, requests, statuses); + ADIOI_Free(statuses); + } + + ADIOI_Free(requests); + ADIOI_Free(count_others_req_per_proc); + + *count_others_req_procs_ptr = count_others_req_procs; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5027, 0, NULL); +#endif +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_aggregate_new.c b/ompi/mca/io/romio314/romio/adio/common/ad_aggregate_new.c new file mode 100644 index 0000000000..ba5af6b0c3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_aggregate_new.c @@ -0,0 +1,284 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif +#include +/* #define DEBUG */ + +void ADIOI_Calc_file_realms_user_size (ADIO_File fd, int fr_size, + int nprocs_for_coll, + ADIO_Offset *file_realm_st_offs, + MPI_Datatype *file_realm_types); +void ADIOI_Calc_file_realms_aar (ADIO_File fd, int nprocs_for_coll, + int pfr_enabled, + ADIO_Offset min_st_offset, + ADIO_Offset max_end_offset, + ADIO_Offset *file_realm_st_offs, + MPI_Datatype *file_realm_types); +void ADIOI_Calc_file_realms_fsize (ADIO_File fd, + int nprocs_for_coll, + ADIO_Offset max_end_offset, + ADIO_Offset *file_realm_st_offs, + MPI_Datatype *file_realm_types); +void ADIOI_Create_fr_simpletype (int size, int nprocs_for_coll, + MPI_Datatype *simpletype); +static void align_fr (int fr_size, ADIO_Offset fr_off, int alignment, + int *aligned_fr_size, ADIO_Offset *aligned_fr_off); +void ADIOI_Verify_fr (int nprocs_for_coll, ADIO_Offset *file_realm_st_offs, + MPI_Datatype *file_realm_types); + +void ADIOI_Calc_file_realms (ADIO_File fd, ADIO_Offset min_st_offset, + ADIO_Offset max_end_offset) +{ + int nprocs_for_coll; + int file_realm_calc_type; + + MPI_Datatype *file_realm_types = NULL; + ADIO_Offset *file_realm_st_offs = NULL; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5004, 0, NULL); +#endif +#ifdef DEBUG + printf ("ADIOI_Calc_file_realms\n"); +#endif + + nprocs_for_coll = fd->hints->cb_nodes; + file_realm_calc_type = fd->hints->cb_fr_type; + + /* If PFRs are disabled we know these pointers are not allocated */ + if (fd->hints->cb_pfr != ADIOI_HINT_ENABLE) { + fd->file_realm_st_offs = NULL; + fd->file_realm_types = NULL; + } + + if (nprocs_for_coll == 1) { + /* if there's only one aggregator, we can reset the file + * realms every single time */ + if (fd->file_realm_st_offs == NULL) + { + file_realm_st_offs = (ADIO_Offset *) + ADIOI_Malloc (sizeof(ADIO_Offset)); + file_realm_types = (MPI_Datatype *) + ADIOI_Malloc (sizeof(MPI_Datatype)); + } + else + { + file_realm_st_offs = fd->file_realm_st_offs; + file_realm_types = fd->file_realm_types; + } + *file_realm_st_offs = min_st_offset; + MPI_Type_contiguous ((max_end_offset - min_st_offset + 1), MPI_BYTE, + file_realm_types); + MPI_Type_commit (file_realm_types); + ADIOI_Add_contig_flattened (*file_realm_types); + } + else if (fd->file_realm_st_offs == NULL) { + file_realm_st_offs = (ADIO_Offset *) + ADIOI_Malloc (nprocs_for_coll * sizeof(ADIO_Offset)); + file_realm_types = (MPI_Datatype *) + ADIOI_Malloc (nprocs_for_coll * sizeof(MPI_Datatype)); + + if (file_realm_calc_type == ADIOI_FR_AAR) { + ADIOI_Calc_file_realms_aar (fd, nprocs_for_coll, + fd->hints->cb_pfr, + min_st_offset, max_end_offset, + file_realm_st_offs, file_realm_types); + /* flatten file realm datatype for future use - only one + * because all are the same*/ + ADIOI_Flatten_datatype (file_realm_types[0]); + } + else if (file_realm_calc_type == ADIOI_FR_FSZ) { + ADIOI_Calc_file_realms_fsize (fd, nprocs_for_coll, max_end_offset, + file_realm_st_offs, + file_realm_types); + /* flatten file realm datatype for future use - only one + * because all are the same*/ + ADIOI_Flatten_datatype (file_realm_types[0]); + } + else if (file_realm_calc_type == ADIOI_FR_USR_REALMS) { + /* copy user provided realm datatypes and realm offsets in + * hints to file descriptor. may also want to verify that + * the provided file realms are covering (for pfr at + * least) and non-overlapping */ + } + else if (file_realm_calc_type > 0) { + ADIOI_Calc_file_realms_user_size (fd, file_realm_calc_type, + nprocs_for_coll, + file_realm_st_offs, + file_realm_types); + /* flatten file realm datatype for future use - only one + * because all are the same */ + ADIOI_Flatten_datatype (file_realm_types[0]); + } + } + fd->file_realm_st_offs = file_realm_st_offs; + fd->file_realm_types = file_realm_types; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5005, 0, NULL); +#endif +} + +void ADIOI_Calc_file_realms_user_size (ADIO_File fd, int fr_size, + int nprocs_for_coll, + ADIO_Offset *file_realm_st_offs, + MPI_Datatype *file_realm_types) +{ + int i; + int aligned_fr_size; + ADIO_Offset aligned_fr_off; + MPI_Datatype simpletype; + + align_fr(fr_size, 0, fd->hints->cb_fr_alignment, &aligned_fr_size, + &aligned_fr_off); + fr_size = aligned_fr_size; + ADIOI_Create_fr_simpletype (fr_size, nprocs_for_coll, &simpletype); + + if (fd->hints->cb_pfr == ADIOI_HINT_ENABLE) + file_realm_st_offs[0] = 0; + else + file_realm_st_offs[0] = aligned_fr_off; + file_realm_types[0] = simpletype; +#ifdef DEBUG + printf ("file_realm[0] = (%lld, %d)\n", file_realm_st_offs[0], + fr_size); +#endif + + for (i=1; i < nprocs_for_coll; i++) + { + file_realm_st_offs[i] = file_realm_st_offs[i-1] + fr_size; + file_realm_types[i] = simpletype; +#ifdef DEBUG + printf ("file_realm[%d] = (%lld, %d)\n", i, file_realm_st_offs[i], + aligned_fr_size); +#endif + } +} + +/* takes an extra romio_cb_pfr param to decide whether file realms + * should start at byte 0 of the file*/ +void ADIOI_Calc_file_realms_aar (ADIO_File fd, int nprocs_for_coll, int cb_pfr, + ADIO_Offset min_st_offset, + ADIO_Offset max_end_offset, + ADIO_Offset *file_realm_st_offs, + MPI_Datatype *file_realm_types) +{ + int fr_size, aligned_fr_size, i; + MPI_Datatype simpletype; + ADIO_Offset aligned_start_off; + char value[9]; + + fr_size = (max_end_offset - min_st_offset + nprocs_for_coll) / + nprocs_for_coll; + align_fr(fr_size, min_st_offset, fd->hints->cb_fr_alignment, + &aligned_fr_size, &aligned_start_off); + fr_size = aligned_fr_size; + ADIOI_Create_fr_simpletype (fr_size, nprocs_for_coll, &simpletype); + if (cb_pfr == ADIOI_HINT_ENABLE) + file_realm_st_offs[0] = 0; + else + file_realm_st_offs[0] = aligned_start_off; + file_realm_types[0] = simpletype; + +#ifdef DEBUG + printf ("file_realm[0] = (%lld, %d)\n", file_realm_st_offs[0], + fr_size); +#endif + for (i=1; i < nprocs_for_coll; i++) + { + file_realm_st_offs[i] = file_realm_st_offs[i-1] + fr_size; + file_realm_types[i] = simpletype; +#ifdef DEBUG + printf ("file_realm[%d] = (%lld, %d)\n", i, file_realm_st_offs[i], + fr_size); +#endif + } + if (fd->hints->cb_pfr == ADIOI_HINT_ENABLE) { + sprintf (value, "%d", fr_size); + ADIOI_Info_set (fd->info, "romio_cb_fr_type", value); + } +} + +void ADIOI_Calc_file_realms_fsize (ADIO_File fd, int nprocs_for_coll, + ADIO_Offset max_end_offset, + ADIO_Offset *file_realm_st_offs, + MPI_Datatype *file_realm_types) +{ + int fr_size, aligned_fr_size, error_code, i; + int fsize; + ADIO_Offset aligned_fr_off; + ADIO_Fcntl_t fcntl_struct; + MPI_Datatype simpletype; + + ADIO_Fcntl (fd, ADIO_FCNTL_GET_FSIZE, &fcntl_struct, &error_code); + + /* use impending file size since a write call may lengthen the file */ + fsize = ADIOI_MAX (fcntl_struct.fsize, max_end_offset+1); + fr_size = (fsize + nprocs_for_coll - 1) / nprocs_for_coll; + align_fr(fr_size, 0, fd->hints->cb_fr_alignment, + &aligned_fr_size, &aligned_fr_off); + ADIOI_Create_fr_simpletype (fr_size, nprocs_for_coll, &simpletype); + + for (i=0; i < nprocs_for_coll; i++) + { + file_realm_st_offs[i] = fr_size * i; + file_realm_types[i] = simpletype; + } +} + +/* creates a datatype with an empty trailing edge */ +void ADIOI_Create_fr_simpletype (int size, int nprocs_for_coll, + MPI_Datatype *simpletype) +{ + int count=2, blocklens[2]; + MPI_Aint indices[2]; + MPI_Datatype old_types[2]; + + blocklens[0] = size; + blocklens[1] = 1; + indices[0] = 0; + indices[1] = size*nprocs_for_coll; + old_types[0] = MPI_BYTE; + old_types[1] = MPI_UB; + + MPI_Type_struct (count, blocklens, indices, old_types, simpletype); + + MPI_Type_commit (simpletype); +} + +/* Verify that file realms are covering (PFRs) and non-overlapping */ +void ADIOI_Verify_fr (int nprocs_for_coll, ADIO_Offset *file_realm_st_offs, + MPI_Datatype *file_realm_types) +{ +} + +int ADIOI_Agg_idx (int rank, ADIO_File fd) { + int i, cb_nodes, *ranklist; + cb_nodes = fd->hints->cb_nodes; + ranklist = fd->hints->ranklist; + + for (i=0; i +#endif + +void ADIO_Close(ADIO_File fd, int *error_code) +{ + int i, j, k, combiner, myrank, err, is_contig; + static char myname[] = "ADIO_CLOSE"; + + if (fd->async_count) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(errno)); + return; + } + + /* because of deferred open, this warants a bit of explaining. First, if + * we've done aggregation, + * then close the file. Then, if any process left has done independent + * i/o, close the file. Otherwise, we'll skip the fs-specific close and + * just say everything is a-ok. + * + * XXX: is it ok for those processes with a "real" communicator and those + * with "MPI_COMM_SELF" to both call ADIOI_xxx_Close at the same time ? + * everyone who ever opened the file will close it. Is order important? Is + * timing important? + */ + if (fd->hints->deferred_open && fd->is_agg) { + (*(fd->fns->ADIOI_xxx_Close))(fd, error_code); + } else { + if(fd->is_open) { + (*(fd->fns->ADIOI_xxx_Close))(fd, error_code); + } else { + *error_code = MPI_SUCCESS; + } + + } + + if (fd->access_mode & ADIO_DELETE_ON_CLOSE) { + /* if we are doing aggregation and deferred open, then it's possible + * that rank 0 does not have access to the file. make sure only an + * aggregator deletes the file.*/ + MPI_Comm_rank(fd->comm, &myrank); + if (myrank == fd->hints->ranklist[0]) { + ADIO_Delete(fd->filename, &err); + } + MPI_Barrier(fd->comm); + } + + if (fd->fortran_handle != -1) { + ADIOI_Ftable[fd->fortran_handle] = MPI_FILE_NULL; + } + + if (fd->hints && fd->hints->ranklist) ADIOI_Free(fd->hints->ranklist); + if (fd->hints && fd->hints->cb_config_list) ADIOI_Free(fd->hints->cb_config_list); + + /* This BlueGene platform-specific free must be done in the common code + * because the malloc's for these hint data structures are done at the + * scope of ADIO_Open within the SetInfo call (ADIOI_GPFS_SetInfo which + * calls ADIOI_BG_gen_agg_ranklist). They cannot be done in the + * ADIOI_GPFS_Close because of the file creation case where the + * ADIOI_GPFS_Close and re-open via ADIOI_GPFS_Open are done which results + * in a double-free - ADIOI_GPFS_Open does not redo the SetInfo... */ +#ifdef BGQPLATFORM + if (fd->hints && fd->hints->fs_hints.bg.bridgelist) + ADIOI_Free(fd->hints->fs_hints.bg.bridgelist); + if (fd->hints && fd->hints->fs_hints.bg.bridgelistnum) + ADIOI_Free(fd->hints->fs_hints.bg.bridgelistnum); +#endif + + /* Persistent File Realms */ + if (fd->hints->cb_pfr == ADIOI_HINT_ENABLE) { + /* AAR, FSIZE, and User provided uniform File realms */ + if (1) { + ADIOI_Delete_flattened (fd->file_realm_types[0]); + MPI_Type_free (&fd->file_realm_types[0]); + } + else { + for (i=0; ihints->cb_nodes; i++) { + ADIOI_Datatype_iscontig(fd->file_realm_types[i], &is_contig); + if (!is_contig) + ADIOI_Delete_flattened(fd->file_realm_types[i]); + MPI_Type_free (&fd->file_realm_types[i]); + } + } + ADIOI_Free(fd->file_realm_st_offs); + ADIOI_Free(fd->file_realm_types); + } + if (fd->hints) ADIOI_Free(fd->hints); + + + + MPI_Comm_free(&(fd->comm)); + ADIOI_Free(fd->filename); + + MPI_Type_get_envelope(fd->etype, &i, &j, &k, &combiner); + if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->etype)); + + ADIOI_Datatype_iscontig(fd->filetype, &is_contig); + if (!is_contig) ADIOI_Delete_flattened(fd->filetype); + + MPI_Type_get_envelope(fd->filetype, &i, &j, &k, &combiner); + if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->filetype)); + + MPI_Info_free(&(fd->info)); + + if (fd->io_buf != NULL) ADIOI_Free(fd->io_buf); + + /* memory for fd is freed in MPI_File_close */ +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_coll_build_req_new.c b/ompi/mca/io/romio314/romio/adio/common/ad_coll_build_req_new.c new file mode 100644 index 0000000000..2ea97545f9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_coll_build_req_new.c @@ -0,0 +1,2084 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include +#include "adio.h" +#include "adio_extern.h" +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif +#include "heap-sort.h" + +/* +#define DEBUG1 +#define DEBUG2 +#define DEBUG3 +*/ +/* #define DEBUG_HEAP */ + +#define DTYPE_SKIP + +#ifdef DEBUG3 +static char *off_type_name[MAX_OFF_TYPE] = {"TEMP_OFFSETS", + "REAL_OFFSETS"}; +#endif + +/* Simple function to return the size of the view_state. */ +static inline ADIO_Offset view_state_get_cur_sz(view_state *tmp_view_state_p, + int op_type) +{ + flatten_state *tmp_state_p = NULL; + switch(op_type) + { + case TEMP_OFF: + tmp_state_p = &(tmp_view_state_p->tmp_state); + break; + case REAL_OFF: + tmp_state_p = &(tmp_view_state_p->cur_state); + break; + default: + fprintf(stderr, "op_type invalid\n"); + } + return tmp_state_p->cur_sz; +} + +/* Simple function to return the len of the next piece of the view_state. */ +static inline ADIO_Offset view_state_get_next_len(view_state *tmp_view_state_p, + int op_type) +{ + flatten_state *tmp_state_p = NULL; + switch(op_type) + { + case TEMP_OFF: + tmp_state_p = &(tmp_view_state_p->tmp_state); + break; + case REAL_OFF: + tmp_state_p = &(tmp_view_state_p->cur_state); + break; + default: + fprintf(stderr, "op_type invalid\n"); + } + return (ADIO_Offset) + tmp_view_state_p->flat_type_p->blocklens[tmp_state_p->idx] - + tmp_state_p->cur_reg_off; +} + +/* Add up to a region of a file view and no larger than a max size. + * The view_state is always consistent with the abs_off and where the + * index and cur_reg_off point to. The regions should be coalesced if + * possible later on. */ +static inline int view_state_add_region( + ADIO_Offset max_sz, + view_state *tmp_view_state_p, + ADIO_Offset *st_reg_p, + ADIO_Offset *tmp_reg_sz_p, + int op_type) +{ + ADIOI_Flatlist_node *tmp_flat_type_p = NULL; + flatten_state *tmp_state_p = NULL; + int64_t data_sz = 0; + +#ifdef AGGREGATION_PROFILE + /* MPE_Log_event (5020, 0, NULL); */ +#endif + + switch(op_type) + { + case TEMP_OFF: + tmp_state_p = &(tmp_view_state_p->tmp_state); + break; + case REAL_OFF: + tmp_state_p = &(tmp_view_state_p->cur_state); + break; + default: + fprintf(stderr, "op_type invalid\n"); + } + + tmp_flat_type_p = tmp_view_state_p->flat_type_p; + + *st_reg_p = tmp_state_p->abs_off; + + /* Should be looking at some data (or it's a zero len blocklens + * (i.e. placeholder). */ + assert(tmp_state_p->cur_reg_off != + tmp_flat_type_p->blocklens[tmp_state_p->idx]); + /* Shouldn't have been called if the view_state is done. */ + assert(tmp_state_p->cur_sz != tmp_view_state_p->sz); + + /* Make sure we are not in a non-zero region in the flat_type */ + assert(tmp_flat_type_p->blocklens[tmp_state_p->idx] != 0); + +#ifdef DEBUG3 + fprintf(stderr, "view_state:(blocklens[%Ld]=%d,cur_reg_off=%Ld," + "max_sz=%Ld)\n", tmp_state_p->idx, + tmp_flat_type_p->blocklens[tmp_state_p->idx], + tmp_state_p->cur_reg_off, max_sz); +#endif + + /* Can it add the whole piece? */ + if (tmp_flat_type_p->blocklens[tmp_state_p->idx] - + tmp_state_p->cur_reg_off <= max_sz) + { + data_sz = tmp_flat_type_p->blocklens[tmp_state_p->idx] - + tmp_state_p->cur_reg_off; + + tmp_state_p->cur_sz += data_sz; + + /* Advance the abs_off to the beginning of the next piece */ + if (tmp_flat_type_p->count == 1) + { + assert(tmp_flat_type_p->blocklens[tmp_state_p->idx] != 0); + tmp_state_p->abs_off += data_sz; +#ifdef DEBUG3 + fprintf(stderr, "view_state_add_region: %s contig type " + "(old abs_off=%Ld,abs_off=%Ld,cur_sz=%Ld,reg size=%Ld)\n", + off_type_name[op_type], tmp_state_p->abs_off - data_sz, + tmp_state_p->abs_off, tmp_state_p->cur_sz, data_sz); +#endif + } + else + { + /* Is this the last region in the datatype? */ + if (tmp_state_p->idx == (tmp_flat_type_p->count - 1)) + { + tmp_state_p->abs_off += data_sz - + tmp_flat_type_p->indices[tmp_flat_type_p->count-1] - + tmp_flat_type_p->blocklens[tmp_flat_type_p->count-1] + + tmp_view_state_p->ext; +#ifdef DEBUG3 + fprintf(stderr, "view_state_add_region: %s last region for type " + "(old abs_off=%Ld,abs_off=%Ld,cur_sz=%Ld,reg size=%Ld)\n", + off_type_name[op_type], tmp_state_p->abs_off - data_sz, + tmp_state_p->abs_off, tmp_state_p->cur_sz, data_sz); +#endif + } + else + { + tmp_state_p->abs_off += + tmp_flat_type_p->indices[tmp_state_p->idx + 1] - + (tmp_flat_type_p->indices[tmp_state_p->idx] + + tmp_state_p->cur_reg_off); +#ifdef DEBUG3 + fprintf(stderr, "view_state_add_region: %s inner region type " + "(old abs_off=%Ld,abs_off=%Ld,cur_sz=%Ld,reg size=%Ld)\n", + off_type_name[op_type], tmp_state_p->abs_off - + (tmp_flat_type_p->indices[tmp_state_p->idx + 1] - + (tmp_flat_type_p->indices[tmp_state_p->idx] + + tmp_state_p->cur_reg_off)), tmp_state_p->abs_off, + tmp_state_p->cur_sz, data_sz); +#endif + } + /* Increment idx to next non-zero region in the flat_type */ + do { + tmp_state_p->idx = + (tmp_state_p->idx + 1) % tmp_flat_type_p->count; + } while (tmp_flat_type_p->blocklens[tmp_state_p->idx] == 0); + } + tmp_state_p->cur_reg_off = 0; + } + else /* Add part of the piece */ + { + data_sz = max_sz; + tmp_state_p->cur_reg_off += data_sz; + tmp_state_p->abs_off += data_sz; + tmp_state_p->cur_sz += data_sz; +#ifdef DEBUG3 + fprintf(stderr, "view_state_add_region: %s partial region type " + "(cur_reg_off=%Ld,abs_off=%Ld,cur_sz=%Ld,reg size=%Ld\n", + off_type_name[op_type], tmp_state_p->cur_reg_off, + tmp_state_p->abs_off, tmp_state_p->cur_sz, data_sz); +#endif + } + + *tmp_reg_sz_p = data_sz; +#ifdef AGGREGATION_PROFILE + /* MPE_Log_event (5021, 0, NULL); */ +#endif + return 0; +} + +/* Set up the abs_off, idx, and cur_reg_off of a view_state for the + * tmp_state or the cur_state. */ +int ADIOI_init_view_state(int file_ptr_type, + int nprocs, + view_state *view_state_arr, + int op_type) +{ + ADIOI_Flatlist_node *tmp_flat_type_p = NULL; + ADIO_Offset tmp_off_used = 0, st_reg = 0, tmp_reg_sz = 0; + int i; + flatten_state *tmp_state_p = NULL; + view_state *tmp_view_p = NULL; + + for (i = 0; i < nprocs; i++) + { + switch(op_type) + { + case TEMP_OFF: + tmp_state_p = &(view_state_arr[i].tmp_state); + break; + case REAL_OFF: + tmp_state_p = &(view_state_arr[i].cur_state); + break; + default: + fprintf(stderr, "op_type invalid\n"); + } + + tmp_view_p = &(view_state_arr[i]); + tmp_flat_type_p = tmp_view_p->flat_type_p; + + if (file_ptr_type == ADIO_INDIVIDUAL) + tmp_state_p->abs_off = tmp_view_p->fp_ind; + else + tmp_state_p->abs_off = tmp_view_p->disp; + + tmp_off_used = 0; + + /* initialize tmp_state idx */ + while (tmp_flat_type_p->blocklens[tmp_state_p->idx] == 0) + tmp_state_p->idx = (tmp_state_p->idx + 1) % tmp_flat_type_p->count; + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) + tmp_state_p->abs_off += tmp_flat_type_p->indices[tmp_state_p->idx]; + + /* Initialize the abs_off by moving into the datatype + * byte_off bytes. Since we only do this in the beginning, we + * make the assumption that pieces are added whole until the last + * piece which MAY be partial. */ + while (tmp_off_used != tmp_view_p->byte_off) + { + view_state_add_region( + tmp_view_p->byte_off - tmp_off_used, + &(view_state_arr[i]), &st_reg, &tmp_reg_sz, + op_type); + } + + /* Re-initialize the cur_size so that the abs_off was set to + * the proper position while the actual size = 0.*/ + tmp_state_p->cur_sz = 0; +#ifdef DEBUG1 + fprintf(stderr, "init_view_state: %s (idx=%d,byte_off=%Ld," + "abs_off=%Ld,reg_off=%Ld,sz=%Ld)\n", off_type_name[op_type], + i, tmp_view_p->byte_off, tmp_state_p->abs_off, + tmp_state_p->cur_reg_off, tmp_view_p->sz); +#endif + + } + return 0; +} + +/* Return the next file realm offset and length for this datatype state + * within a particular file realm. */ +static inline int get_next_fr_off(ADIO_File fd, + ADIO_Offset off, + ADIO_Offset fr_st_off, + MPI_Datatype *fr_type_p, + ADIO_Offset *fr_next_off_p, + ADIO_Offset *fr_max_len_p) +{ + MPI_Aint fr_extent = -1; + ADIO_Offset tmp_off, off_rem; + ADIOI_Flatlist_node *fr_node_p = ADIOI_Flatlist; + int i = -1, fr_dtype_ct = 0; + + /* Should have already been flattened in calc_file_realms() */ + while (fr_node_p->type != (*fr_type_p)) + fr_node_p = fr_node_p->next; + assert(fr_node_p != NULL); + + /* Did we get to the first region of the file realm? */ + if (off - fr_st_off < 0) + { + *fr_next_off_p = fr_st_off + fr_node_p->indices[0]; + *fr_max_len_p = fr_node_p->blocklens[0]; + return 0; + } + + /* Calculate how many times to loop through the fr_type + * and where the next fr_off is. */ + MPI_Type_extent(*fr_type_p, &fr_extent); + tmp_off = off - fr_st_off; + fr_dtype_ct = tmp_off / fr_extent; + off_rem = tmp_off % fr_extent; + for (i = 0; i < fr_node_p->count; i++) + { + if (off_rem < fr_node_p->indices[i]) + { + *fr_next_off_p = fr_st_off + + (fr_dtype_ct * fr_extent) + fr_node_p->indices[i]; + *fr_max_len_p = fr_node_p->blocklens[i]; + return 0; + } + else if (off_rem < fr_node_p->indices[i] + fr_node_p->blocklens[i]) + { + *fr_next_off_p = off; + *fr_max_len_p = fr_node_p->blocklens[i] - + (off_rem - fr_node_p->indices[i]); + return off; + } + } + + /* Shouldn't get here. */ + fprintf(stderr, "get_next_fr_off: Couldn't find the correct " + "location of the next offset for this file realm.\n"); + return -1; +} + +/* Look in all the view states for the first offset within a given + * file realm. Report the end of a contiguous region within the file + * realm (possibly more than the actual view state may be able to + * process contiguously). */ +static inline int find_next_off(ADIO_File fd, + view_state *view_state_p, + ADIO_Offset fr_st_off, + MPI_Datatype *fr_type_p, + int op_type, + ADIO_Offset *cur_off_p, + ADIO_Offset *cur_reg_max_len_p) +{ + ADIOI_Flatlist_node *tmp_flat_type_p = NULL; + ADIO_Offset tmp_off = -1, fr_next_off = -1, fr_max_len = -1, + tmp_fr_max_len = -1; + int ret = 0; + flatten_state *tmp_state_p = NULL; + ADIO_Offset tmp_st_off = 0, tmp_reg_sz = 0; +#ifdef DTYPE_SKIP + int skip_type_ct; +#endif + +#ifdef AGGREGATION_PROFILE + /* MPE_Log_event (5022, 0, NULL); */ +#endif + + switch(op_type) + { + case TEMP_OFF: + tmp_state_p = &(view_state_p->tmp_state); + break; + case REAL_OFF: + tmp_state_p = &(view_state_p->cur_state); + break; + default: + fprintf(stderr, "op_type invalid\n"); + } + + tmp_flat_type_p = view_state_p->flat_type_p; + + /* Can we use this proc? */ + if (tmp_state_p->cur_sz < view_state_p->sz) { + tmp_st_off = 0; + tmp_reg_sz = 0; + /* If the current region is not within the file realm, advance + * the state until it is and calculate the end of the next file + * realm in fr_max_len. */ + ret = get_next_fr_off(fd, + tmp_state_p->abs_off, + fr_st_off, + fr_type_p, + &fr_next_off, + &fr_max_len); + + while ((tmp_state_p->abs_off < fr_next_off) && + (tmp_state_p->cur_sz != view_state_p->sz)) + { + + /* While this might appear to be erroneous at first, + * view_state_add_region can only add a single piece at a + * time. Therefore, it will never overshoot the beginning + * of the next file realm. When it finally does enter the + * next file realm it will not be able to go beyond its + * first piece. */ + +#ifdef DTYPE_SKIP + if (tmp_flat_type_p->count > 1) { + /* let's see if we can skip whole datatypes */ + skip_type_ct = (fr_next_off - tmp_state_p->abs_off) / + view_state_p->ext; + if (skip_type_ct > 0) { + /* before we go on, let's check if we've actually + * finished up already */ + tmp_state_p->cur_sz += skip_type_ct * + view_state_p->type_sz; + if (tmp_state_p->cur_sz >= view_state_p->sz) { + tmp_state_p->cur_sz = view_state_p->sz; + break; + } + tmp_state_p->abs_off += skip_type_ct * view_state_p->ext; + } + } +#endif + view_state_add_region( + fr_next_off - tmp_state_p->abs_off, + view_state_p, + &tmp_st_off, + &tmp_reg_sz, + op_type); + + ret = get_next_fr_off(fd, + tmp_state_p->abs_off, + fr_st_off, + fr_type_p, + &fr_next_off, + &fr_max_len); + } + + if (tmp_state_p->cur_sz != view_state_p->sz) { + tmp_off = tmp_state_p->abs_off; + /* Calculate how much of the remaining file realm there is from the + * current offset */ + tmp_fr_max_len = fr_next_off + fr_max_len - tmp_off; + } + } + + *cur_off_p = tmp_off; + *cur_reg_max_len_p = tmp_fr_max_len; +#ifdef AGGREGATION_PROFILE + /* MPE_Log_event (5023, 0, NULL); */ +#endif + return ret; +} + +/* Upon completion of a full collective buffer, end of a file realm + * region (data sieving), or the end of all I/O for an aggregator, we + * should return a list of MPI_Datatypes that correspond to client + * communication into a collective buffer, a list of corresponding + * sizes, and an aggregate MPI_Datatype which will be used as a + * filetype in MPI_File_write/read on the aggregator. */ +int ADIOI_Build_agg_reqs(ADIO_File fd, int rw_type, int nprocs, + view_state *client_file_view_state_arr, + MPI_Datatype *client_comm_dtype_arr, + ADIO_Offset *client_comm_sz_arr, + ADIO_Offset *agg_dtype_offset_p, + MPI_Datatype *agg_dtype_p) +{ + MPI_Aint **client_disp_arr = NULL, *agg_disp_arr = NULL; + int **client_blk_arr = NULL, *agg_blk_arr = NULL; + ADIO_Offset tmp_coll_buf_sz = 0, st_reg = 0, act_reg_sz = 0; + ADIO_Offset cur_off = -1, cur_reg_max_len = -1; + ADIO_Offset ds_fr_end = -1; + ADIO_Offset *fr_st_off_arr = fd->file_realm_st_offs; + MPI_Datatype *fr_type_arr = fd->file_realm_types; + int *client_ol_ct_arr = NULL; + int *client_ol_cur_ct_arr = NULL; + int agg_ol_ct = 0, agg_ol_cur_ct = 0; + int cur_off_proc = -1; + int next_off_idx = -1; + int i = 0, j = 0, all_done = -1; + int agg_idx = fd->my_cb_nodes_index; + heap_t offset_heap; + ADIO_Offset next_off = -1, next_reg_max_len = -1; + + /* Used for coalescing ol pairs next to each other. */ + ADIO_Offset *client_comm_next_off_arr = NULL; + ADIO_Offset agg_next_off = -1; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5016, 0, NULL); +#endif + + memset(client_comm_sz_arr, 0, nprocs*sizeof(ADIO_Offset)); + + if ((client_comm_next_off_arr = (ADIO_Offset *) + ADIOI_Malloc(nprocs*sizeof(ADIO_Offset))) == NULL) + { + fprintf(stderr, "ADIOI_Build_agg_reqs: malloc client_next_off_arr " + "failed\n"); + return -1; + } + + if ((client_ol_ct_arr = (int *) ADIOI_Calloc(nprocs, sizeof(int))) == NULL) + { + fprintf(stderr, "ADIOI_Build_agg_reqs: " + "malloc client_ol_ct_arr failed\n"); + return -1; + } + if ((client_ol_cur_ct_arr = + (int *) ADIOI_Calloc(nprocs, sizeof(int))) == NULL) + { + fprintf(stderr, "ADIOI_Build_agg_reqs: " + "malloc client_ol_cur_ct_arr failed\n"); + return -1; + } + + /* On the first pass see how many offset-length pairs are + * necessary for each client. Then allocate the correct amount of + * offset-length pairs for describing the collective buffer. All + * data is processed in order by the aggregator's file realm. On + * the second pass, set the offset-length pairs to the correct + * values. */ + for (i = 0; i < MAX_OFF_TYPE; i++) + { + memset(client_comm_next_off_arr, -1, nprocs*sizeof(ADIO_Offset)); + tmp_coll_buf_sz = 0; + ds_fr_end = -1; + + /* initialize heap */ + ADIOI_Heap_create(&offset_heap, nprocs); + offset_heap.size = 0; + + for (j=0; j 0)) { + ADIOI_Heap_insert(&offset_heap, cur_off, j, cur_reg_max_len); +#ifdef DEBUG_HEAP + printf ("initial: inserting offset %lld with " + "cur_reg_max_len = %lld for p%d\n", + cur_off, cur_reg_max_len, j); +#endif + } + + } + if (!offset_heap.size) + ADIOI_Heap_insert(&offset_heap, -1, -1, -1); + + while (tmp_coll_buf_sz < fd->hints->cb_buffer_size) + { + /* Find the next process with the next region within the + * file realm and the maximum amount that can be added for + * this particular file realm as a contiguous region. */ + ADIOI_Heap_extract_min(&offset_heap, &cur_off, &cur_off_proc, + &cur_reg_max_len); +#ifdef DEBUG_HEAP + printf ("extracted cur_off %lld from proc %d\n", + cur_off, cur_off_proc); +#endif + + if (cur_off == -1) + break; + +#ifdef DEBUG3 + fprintf(stderr, "ADIOI_Build_agg_reqs: %s proc %d start/add to" + " list (max_reg_fr=%Ld,tmp_coll_buf_sz=%Ld," + "cb_buffer_size=%d)\n", off_type_name[i], cur_off_proc, + cur_reg_max_len, tmp_coll_buf_sz, + fd->hints->cb_buffer_size); +#endif + + /* We process only contiguous file realm regions if we are + * using data sieving. Note that we only do this for + * writes since reads can be data sieved across each other + * without consistency issues. */ + if ((fd->hints->ds_write == ADIOI_HINT_ENABLE || + fd->hints->ds_write == ADIOI_HINT_AUTO) && + rw_type == ADIOI_WRITE && fd->hints->cb_nodes > 1) + { +#ifdef DEBUG2 + fprintf(stderr, "ADIOI_Build_agg_reqs: " + "Warning - Data sieving writes on\n"); +#endif + if (ds_fr_end == -1) + { + ds_fr_end = cur_off + cur_reg_max_len; +#ifdef DEBUG1 + fprintf(stderr, "ADIOI_Build_agg_reqs: " + "cur_off=%Ld, cur_reg_max_len=%Ld\n" + "Data sieving file realm end initialized to %Ld\n", + cur_off, + cur_reg_max_len, + ds_fr_end); +#endif + } + else + { + /* The next off switched file realms, so we will stop + * here. */ + if (ds_fr_end != cur_off + cur_reg_max_len) + { +#ifdef DEBUG1 + fprintf(stderr, "ADIOI_Build_agg_reqs: " + "Data sieving file realm end changed from " + "%Ld to %Ld\n", ds_fr_end, + cur_off + cur_reg_max_len); +#endif + break; + } + } + } + + /* Add up to the end of the file realm or the collective + * buffer. */ + if (cur_reg_max_len > (fd->hints->cb_buffer_size - + tmp_coll_buf_sz)) + cur_reg_max_len = fd->hints->cb_buffer_size - tmp_coll_buf_sz; + + view_state_add_region( + cur_reg_max_len, + &(client_file_view_state_arr[cur_off_proc]), + &st_reg, &act_reg_sz, i); + + switch(i) + { + case TEMP_OFF: + /* Increment the ol list count for each proc and + * the used part of the collective buffer if the + * next region is not adjacent to the previous + * region. */ + if (client_comm_next_off_arr[cur_off_proc] != + tmp_coll_buf_sz) + { + (client_ol_ct_arr[cur_off_proc])++; + } + client_comm_next_off_arr[cur_off_proc] = + tmp_coll_buf_sz + act_reg_sz; + + if (agg_next_off != st_reg) + agg_ol_ct++; + agg_next_off = st_reg + act_reg_sz; + break; + case REAL_OFF: + /* Add this region to the proper client ol list if + * the next region is not adjacent to the previous + * region. */ + next_off_idx = client_ol_cur_ct_arr[cur_off_proc]; + if (client_comm_next_off_arr[cur_off_proc] != + tmp_coll_buf_sz) + { + client_disp_arr[cur_off_proc][next_off_idx] = + tmp_coll_buf_sz; + client_blk_arr[cur_off_proc][next_off_idx] = + act_reg_sz; + (client_ol_cur_ct_arr[cur_off_proc])++; + } + else + { + client_blk_arr[cur_off_proc][next_off_idx - 1] + += act_reg_sz; + } + client_comm_sz_arr[cur_off_proc] += act_reg_sz; + client_comm_next_off_arr[cur_off_proc] = + tmp_coll_buf_sz + act_reg_sz; + + /* Add to the aggregator filetype if the next + * region is not adjacent to the previous + * region. */ + if (agg_next_off != st_reg) + { + /* this will enable initial offsets much further into + * the file than an MPI_Aint */ + if (!agg_ol_cur_ct) + *agg_dtype_offset_p = st_reg; + agg_disp_arr[agg_ol_cur_ct] = st_reg - + (MPI_Aint) *agg_dtype_offset_p; + agg_blk_arr[agg_ol_cur_ct] = act_reg_sz; + agg_ol_cur_ct++; + } + else + { + agg_blk_arr[agg_ol_cur_ct - 1] += act_reg_sz; + } + agg_next_off = st_reg + act_reg_sz; + + break; + default: + fprintf(stderr, "ADIOI_Build_agg_reqs: Impossible type\n"); + } + tmp_coll_buf_sz += act_reg_sz; + + find_next_off(fd, + &client_file_view_state_arr[cur_off_proc], + fr_st_off_arr[agg_idx], + &(fr_type_arr[agg_idx]), + i, + &next_off, + &next_reg_max_len); + + if ((next_off != -1) || (!offset_heap.size)) { + ADIOI_Heap_insert(&offset_heap, next_off, cur_off_proc, + next_reg_max_len); +#ifdef DEBUG_HEAP + printf ("inserting offset %lld for p%d\n", next_off, + cur_off_proc); +#endif + } + } + + if (i == TEMP_OFF) + { + /* Allocate offset-length pairs for creating hindexed + * MPI_Datatypes for both the client and the aggregator. */ + if ((client_disp_arr = (MPI_Aint **) + ADIOI_Malloc(nprocs*sizeof(MPI_Aint *))) == NULL) + { + fprintf(stderr, "ADIOI_Build_agg_reqs: malloc " + "client_disp_arr failed\n"); + return -1; + } + if ((client_blk_arr = (int **) ADIOI_Malloc( + nprocs*sizeof(int *))) == NULL) + { + ADIOI_Free(client_disp_arr); + fprintf(stderr, "ADIOI_Build_agg_reqs: malloc " + "client_blk_arr failed\n"); + return -1; + } + for (j = 0; j < nprocs; j++) + { + if ((client_disp_arr[j] = (MPI_Aint *) ADIOI_Malloc( + client_ol_ct_arr[j]*sizeof(MPI_Aint))) == NULL) + { + fprintf(stderr, "ADIOI_Build_agg_reqs: malloc " + "client_disp_arr[%d] failed\n", j); + return -1; + } + if ((client_blk_arr[j] = (int *) + ADIOI_Malloc(client_ol_ct_arr[j]*sizeof(int))) == NULL) + { + ADIOI_Free(client_disp_arr[j]); + fprintf(stderr, "ADIOI_Build_agg_reqs: malloc " + "client_blk_arr[%d] failed\n", j); + return -1; + } + } + + if (agg_ol_ct > 0) + { + if ((agg_disp_arr = (MPI_Aint *) ADIOI_Malloc( + agg_ol_ct*sizeof(MPI_Aint))) == NULL) + { + fprintf(stderr, + "ADIOI_Build_agg_reqs: malloc disp_arr failed\n"); + return -1; + } + if ((agg_blk_arr = (int *) + ADIOI_Malloc(agg_ol_ct*sizeof(int))) == NULL) + { + ADIOI_Free(agg_disp_arr); + fprintf(stderr, + "ADIOI_Build_agg_reqs: malloc blk_arr failed\n"); + return -1; + } + } + } + ADIOI_Heap_free(&offset_heap); + } + + /* Let the clients know if this aggregator is totally finished + * with all possible client requests. */ + all_done = 1; + for (i = 0; i < nprocs; i++) + { + if ((client_file_view_state_arr[i].cur_state.cur_sz != + client_file_view_state_arr[i].sz) || + client_comm_sz_arr[i] != 0) + { + all_done = 0; + break; + } + } + if (all_done == 1) + { + for (i = 0; i < nprocs; i++) + { + client_comm_sz_arr[i] = -1; + } + } + + /* Quick check to make sure we found all the ol pairs we thought + * we did */ + for (i = 0; i < nprocs; i++) + { + if (client_ol_cur_ct_arr[i] != client_ol_ct_arr[i]) + { + fprintf(stderr, "ADIOI_Build_agg_reqs: ERROR Process %d " + "processed only %d out of %d ol pairs\n", i, + client_ol_cur_ct_arr[i], + client_ol_ct_arr[i]); + return -1; + } + } +#ifdef DEBUG1 + fprintf(stderr, "ADIOI_Build_agg_reqs:(client,ol_pairs,size_req)="); + for (i = 0; i < nprocs; i++) + { + fprintf(stderr, "(%d,%d,%Ld)", i, client_ol_ct_arr[i], + client_comm_sz_arr[i]); + if (i != nprocs - 1) + fprintf(stderr, ","); + } + fprintf(stderr, "\n"); +#endif +#ifdef DEBUG1 + fprintf(stderr, "ADIOI_Build_agg_reqs: Generated %d of %d " + "aggregate offset-length pairs\n", agg_ol_cur_ct, agg_ol_ct); +#endif +#ifdef DEBUG2 + for (i = 0; i < nprocs; i++) + { + if (client_ol_ct_arr[i] > 0) + { + fprintf(stderr, "ADIOI_Build_agg_reqs: p %d (off,len) = ", i); + for (j = 0; j < client_ol_ct_arr[i]; j++) + { + fprintf(stderr, "[%d](%d,%d) ", j, + client_disp_arr[i][j], + client_blk_arr[i][j]); + } + fprintf(stderr, "\n"); + } + } + if (agg_ol_ct) { + fprintf(stderr, "ADIOI_Build_agg_reqs:agg_type(off,len)="); + for (i = 0; i < agg_ol_ct; i++) + { + fprintf(stderr, "[%d](%d,%d)", + i, agg_disp_arr[i], agg_blk_arr[i]); + if (i != agg_ol_ct - 1) + fprintf(stderr, ","); + } + fprintf(stderr, "\n"); + } +#endif + + assert(agg_ol_cur_ct == agg_ol_ct); + + /* Create all the client and aggregate MPI_Datatypes */ + for (i = 0; i < nprocs; i++) + { + if (client_comm_sz_arr[i] > 0) + { + MPI_Type_hindexed(client_ol_ct_arr[i], client_blk_arr[i], + client_disp_arr[i], MPI_BYTE, + &(client_comm_dtype_arr[i])); + MPI_Type_commit(&(client_comm_dtype_arr[i])); + } + else + { + client_comm_dtype_arr[i] = MPI_BYTE; + } + ADIOI_Free(client_blk_arr[i]); + ADIOI_Free(client_disp_arr[i]); + } + ADIOI_Free(client_blk_arr); + ADIOI_Free(client_disp_arr); + + if (agg_ol_ct > 0) { + if (agg_ol_ct == 1) + MPI_Type_contiguous (agg_blk_arr[0], MPI_BYTE, agg_dtype_p); + else if (agg_ol_ct > 1) + MPI_Type_hindexed(agg_ol_ct, agg_blk_arr, agg_disp_arr, MPI_BYTE, + agg_dtype_p); + + MPI_Type_commit(agg_dtype_p); + + ADIOI_Free(agg_disp_arr); + ADIOI_Free(agg_blk_arr); + } + ADIOI_Free(client_ol_ct_arr); + ADIOI_Free(client_ol_cur_ct_arr); + ADIOI_Free(client_comm_next_off_arr); +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5017, 0, NULL); +#endif + return 0; +} + +/* All sizes from all aggregators are gathered on the clients, which + * then call this function, which will generate the comm datatypes for + * each aggregator (agg_comm_dtype_arr) in the upcoming + * MPI_Alltoallw() */ +int ADIOI_Build_client_reqs(ADIO_File fd, + int nprocs, + view_state *my_mem_view_state_arr, + view_state *agg_file_view_state_arr, + ADIO_Offset *agg_comm_sz_arr, + MPI_Datatype *agg_comm_dtype_arr) +{ + MPI_Aint **agg_disp_arr = NULL; + int **agg_blk_arr = NULL; + view_state *tmp_mem_state_p = NULL, *tmp_file_state_p = NULL; + ADIO_Offset total_agg_comm_sz = 0, cur_total_agg_comm_sz = 0; + ADIO_Offset st_reg = 0, act_reg_sz = 0, tmp_reg_sz = 0; + ADIO_Offset cur_off = -1, cur_reg_max_len = -1; + ADIO_Offset tmp_cur_off = -1, tmp_cur_reg_max_len = -1; + ADIO_Offset agg_mem_st_reg = 0, agg_mem_act_reg_sz = 0; + ADIO_Offset *fr_st_off_arr = fd->file_realm_st_offs; + ADIO_Offset *agg_comm_cur_sz_arr = NULL; + MPI_Datatype *fr_type_arr = fd->file_realm_types; + int *agg_ol_ct_arr = NULL; + int *agg_ol_cur_ct_arr = NULL; + int tmp_agg_fr_idx = -1; + int cur_off_proc = -1; + int i = 0, j = 0; + int agg_next_off_idx = -1; + /* Used for coalescing ol pairs next to each other. */ + ADIO_Offset *agg_mem_next_off_arr = NULL; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5018, 0, NULL); +#endif + +#ifdef DEBUG + fprintf(stderr, "ADIOI_Build_client_reqs:(agg,size_req)="); + for (i = 0; i < nprocs; i++) + { + int tmp_agg_idx = ADIOI_Agg_idx(i, fd); + if (tmp_agg_idx >= 0) + { + fprintf(stderr, "(%d,%Ld)", i, agg_comm_sz_arr[i]); + if (i != fd->hints->cb_nodes - 1) + fprintf(stderr, ","); + } + fprintf(stderr, "\n"); + } +#endif + + if ((agg_mem_next_off_arr = (ADIO_Offset *) ADIOI_Malloc( + nprocs*sizeof(ADIO_Offset))) == NULL) + { + fprintf(stderr, "ADIOI_Build_client_reqs: malloc agg_mem_next_off_arr" + "failed\n"); + return -1; + } + + if ((agg_comm_cur_sz_arr = (ADIO_Offset *) + ADIOI_Malloc(nprocs*sizeof(ADIO_Offset))) == NULL) + { + fprintf(stderr, "ADIOI_Build_client_reqs: malloc agg_comm_cur_sz_arr" + " failed\n"); + return -1; + } + if ((agg_ol_ct_arr = (int *) ADIOI_Calloc(nprocs, sizeof(int))) + == NULL) + { + fprintf(stderr, "ADIOI_Build_client_reqs: " + "malloc agg_ol_ct_arr failed\n"); + return -1; + } + if ((agg_ol_cur_ct_arr = (int *) ADIOI_Calloc(nprocs, sizeof(int))) + == NULL) + { + fprintf(stderr, "ADIOI_Build_client_reqs: " + "malloc agg_ol_cur_ct_arr failed\n"); + return -1; + } + + for (i = 0; i < nprocs; i++) + { + if (agg_comm_sz_arr[i] > 0) + total_agg_comm_sz += agg_comm_sz_arr[i]; + } + + /* On the first pass see how many offset-length pairs are + * necessary for each aggregator. Then allocate the correct + * amount of offset-length pairs for handling each aggregator's + * particular data size. On the last pass, we actually create the + * offset-length pairs. */ + for (i = 0; i < MAX_OFF_TYPE; i++) + { + cur_total_agg_comm_sz = 0; + memset(agg_comm_cur_sz_arr, 0, nprocs*sizeof(ADIO_Offset)); + memset(agg_mem_next_off_arr, -1, nprocs*sizeof(ADIO_Offset)); + while (total_agg_comm_sz > cur_total_agg_comm_sz) + { + /* Look for the next aggregator offset among all the + * aggregators and their respective file realms. */ + cur_off = -1; + for (j = 0; j < nprocs; j++) + { + tmp_agg_fr_idx = ADIOI_Agg_idx(j, fd); + assert(tmp_agg_fr_idx < fd->hints->cb_nodes); + + /* If this process is not an aggregator or we have + * finished all the bytes for this aggregator, move + * along. */ + if (tmp_agg_fr_idx < 0 || + agg_comm_cur_sz_arr[j] == agg_comm_sz_arr[j]) + { + continue; + } + + find_next_off(fd, + &(agg_file_view_state_arr[j]), + fr_st_off_arr[tmp_agg_fr_idx], + &(fr_type_arr[tmp_agg_fr_idx]), + i, + &tmp_cur_off, + &tmp_cur_reg_max_len); + if (tmp_cur_off == -1) + continue; + + if ((cur_off == -1) || + (cur_off > tmp_cur_off)) + { + cur_off_proc = j; + cur_off = tmp_cur_off; + cur_reg_max_len = tmp_cur_reg_max_len; + } + } + + assert(cur_off_proc != -1); + + /* Add up to the end of the file realm or as many bytes + * are left for this particular aggregator in the client's + * filetype */ + if (cur_reg_max_len > agg_comm_sz_arr[cur_off_proc] - + agg_comm_cur_sz_arr[cur_off_proc]) + { + cur_reg_max_len = agg_comm_sz_arr[cur_off_proc] - + agg_comm_cur_sz_arr[cur_off_proc]; + } + assert(cur_reg_max_len > 0); + + view_state_add_region( + cur_reg_max_len, + &(agg_file_view_state_arr[cur_off_proc]), + &st_reg, &act_reg_sz, i); + +#ifdef DEBUG2 + fprintf(stderr, "ADIOI_Build_client_reqs: %s File region" + " (proc=%d,off=%Ld,sz=%Ld)\n", + off_type_name[i], cur_off_proc, + cur_off, act_reg_sz); +#endif + + /* Before translating the file regions to memory regions, + * we first must advance to the proper point in the + * mem_view_state for this aggregator to match the + * file_view_state. */ + tmp_file_state_p = &(agg_file_view_state_arr[cur_off_proc]); + tmp_mem_state_p = &(my_mem_view_state_arr[cur_off_proc]); + assert(view_state_get_cur_sz(tmp_file_state_p, i) - act_reg_sz >= + view_state_get_cur_sz(tmp_mem_state_p, i)); + while (view_state_get_cur_sz(tmp_file_state_p, i) - act_reg_sz != + view_state_get_cur_sz(tmp_mem_state_p, i)) + { + ADIO_Offset fill_st_reg = -1, fill_reg_sz = -1; + view_state_add_region( + view_state_get_cur_sz(tmp_file_state_p, i) - act_reg_sz - + view_state_get_cur_sz(tmp_mem_state_p, i), + tmp_mem_state_p, + &fill_st_reg, + &fill_reg_sz, i); + } + + /* Based on how large the act_reg_sz 1. Figure out how + * many memory offset-length pairs are necessary. 2. Set + * the offset-length pairs. */ + tmp_reg_sz = 0; + while (tmp_reg_sz != act_reg_sz) + { + view_state_add_region( + act_reg_sz - tmp_reg_sz, + tmp_mem_state_p, + &agg_mem_st_reg, &agg_mem_act_reg_sz, + i); + tmp_reg_sz += agg_mem_act_reg_sz; + +#ifdef DEBUG2 + fprintf(stderr, "ADIOI_Build_client_reqs: Mem region %s" + "(proc=%d,off=%Ld,sz=%Ld)\n", + off_type_name[i], cur_off_proc, + agg_mem_st_reg, agg_mem_act_reg_sz); +#endif + agg_comm_cur_sz_arr[cur_off_proc] += agg_mem_act_reg_sz; + cur_total_agg_comm_sz += agg_mem_act_reg_sz; + switch(i) + { + case TEMP_OFF: + /* Increment the ol list count a particular + * aggregator if next region is not adjacent + * to the previous region. */ + if (agg_mem_next_off_arr[cur_off_proc] != + agg_mem_st_reg) + { + agg_ol_ct_arr[cur_off_proc]++; + } + agg_mem_next_off_arr[cur_off_proc] = + agg_mem_st_reg + agg_mem_act_reg_sz; + break; + case REAL_OFF: + /* Set the ol list for the memtypes that will + * map to each aggregator, coaslescing if + * possible. */ + agg_next_off_idx = agg_ol_cur_ct_arr[cur_off_proc]; + if (agg_mem_next_off_arr[cur_off_proc] != + agg_mem_st_reg) + { + agg_disp_arr[cur_off_proc][agg_next_off_idx] = + agg_mem_st_reg; + agg_blk_arr[cur_off_proc][agg_next_off_idx] = + agg_mem_act_reg_sz; + (agg_ol_cur_ct_arr[cur_off_proc])++; + } + else + { + agg_blk_arr[cur_off_proc][agg_next_off_idx - 1] + += agg_mem_act_reg_sz; + } + agg_mem_next_off_arr[cur_off_proc] = + agg_mem_st_reg + agg_mem_act_reg_sz; + break; + default: + fprintf(stderr, "ADIOI_Build_client_reqs: " + "Impossible type\n"); + } + } + } + + /* On the first pass, allocate the memory structures for + * creating the MPI_hindexed type. */ + if (i == TEMP_OFF) + { + /* Allocate offset-length pairs for creating hindexed + * MPI_Datatypes for each aggregator */ + if ((agg_disp_arr = (MPI_Aint **) + ADIOI_Malloc(nprocs*sizeof(MPI_Aint *))) == NULL) + { + fprintf(stderr, + "ADIOI_Build_client_reqs: malloc agg_disp_arr failed\n"); + return -1; + } + if ((agg_blk_arr = (int **) ADIOI_Malloc(nprocs*sizeof(int *))) + == NULL) + { + ADIOI_Free(agg_disp_arr); + fprintf(stderr, + "ADIOI_Build_client_reqs: malloc agg_blk_arr failed\n"); + return -1; + } + for (j = 0; j < nprocs; j++) + { + if ((agg_disp_arr[j] = (MPI_Aint *) + ADIOI_Malloc(agg_ol_ct_arr[j]*sizeof(MPI_Aint))) == NULL) + { + fprintf(stderr, "ADIOI_Build_client_reqs: malloc " + "agg_disp_arr[%d] failed\n", j); + return -1; + } + if ((agg_blk_arr[j] = (int *) + ADIOI_Malloc(agg_ol_ct_arr[j]*sizeof(int))) == NULL) + { + ADIOI_Free(agg_disp_arr[j]); + fprintf(stderr, "ADIOI_Build_client_reqs: malloc " + "agg_blk_arr[%d] failed\n", j); + return -1; + } + } + } + } + +#ifdef DEBUG + fprintf(stderr, "ADIOI_Build_client_reqs:(agg,cur_ol_count=ol_count)="); + for (i = 0; i < nprocs; i++) + { + int tmp_agg_idx = ADIOI_Agg_idx(i, fd); + if (tmp_agg_idx >= 0) + { + fprintf(stderr, "(%d,%d=%d)", i, agg_ol_cur_ct_arr[i], + agg_ol_ct_arr[i]); + assert(agg_ol_ct_arr[i] == agg_ol_cur_ct_arr[i]); + if (tmp_agg_idx != fd->hints->cb_nodes - 1) + fprintf(stderr, ","); + } + } + fprintf(stderr, "\n"); +#endif + +#ifdef DEBUG2 + for (i = 0; i < nprocs; i++) + { + if (agg_ol_ct_arr[i] > 0) + { + fprintf(stderr, "ADIOI_Build_client_reqs: p %d (off,len) = ", i); + for (j = 0; j < agg_ol_ct_arr[i]; j++) + { + fprintf(stderr, "[%d](%d,%d) ", j, + agg_disp_arr[i][j], + agg_blk_arr[i][j]); + } + fprintf(stderr, "\n"); + } + } +#endif + + /* Create all the aggregator MPI_Datatypes */ + for (i = 0; i < nprocs; i++) + { + if (agg_comm_sz_arr[i] > 0) + { + MPI_Type_hindexed(agg_ol_ct_arr[i], agg_blk_arr[i], + agg_disp_arr[i], MPI_BYTE, + &(agg_comm_dtype_arr[i])); + MPI_Type_commit(&(agg_comm_dtype_arr[i])); + } + else + { + agg_comm_dtype_arr[i] = MPI_BYTE; + } + ADIOI_Free(agg_blk_arr[i]); + ADIOI_Free(agg_disp_arr[i]); + } + ADIOI_Free(agg_blk_arr); + ADIOI_Free(agg_disp_arr); + + ADIOI_Free(agg_mem_next_off_arr); + ADIOI_Free(agg_comm_cur_sz_arr); + ADIOI_Free(agg_ol_ct_arr); + ADIOI_Free(agg_ol_cur_ct_arr); +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5019, 0, NULL); +#endif + return 0; +} +/* ADIOI_Build_client_pre_req allows a client to calculate the memtype + * offset-length pairs up (up to a limit - max_pre_req_sz or max + * ol_ct). It basically allows ADIOI_Build_client_req to do less work. + * If it called and there already exist some preprocessed memtype + * offset-length pairs, it will exit immediately if a limit has been + * reached or if will add on the old limites to reach the new + * limits. */ + +int ADIOI_Build_client_pre_req(ADIO_File fd, + int agg_rank, int agg_idx, + view_state *my_mem_view_state_p, + view_state *agg_file_view_state_p, + ADIO_Offset max_pre_req_sz, + int max_ol_ct) +{ + ADIO_Offset act_reg_sz = 0, tmp_reg_sz = 0; + ADIO_Offset cur_off = -1, cur_reg_max_len = -1; + ADIO_Offset agg_mem_st_reg = 0, agg_mem_act_reg_sz = 0; + int agg_ol_ct = 0, agg_ol_cur_ct = 0; + int i, agg_next_off_idx = -1; + + ADIO_Offset cur_sz = 0, max_sz = 0, agg_mem_next_off = -1; + ADIO_Offset fill_st_reg = -1, fill_reg_sz = -1; + ADIO_Offset *fr_st_off_arr = fd->file_realm_st_offs; + MPI_Datatype *fr_type_arr = fd->file_realm_types; + MPI_Aint *tmp_disp_arr = NULL; + int *tmp_blk_arr = NULL, exit_loop = -1; + flatten_state *tmp_mem_state_p = NULL, *tmp_file_state_p = NULL; +#ifdef DTYPE_SKIP + int skip_type_ct; +#endif + if (agg_idx < 0 || agg_idx >= fd->hints->cb_nodes) + { + fprintf(stderr, "ADIOI_Build_client_pre_req: Invalid agg_idx %d\n", + agg_idx); + return -1; + } + + if (agg_file_view_state_p->cur_state.cur_sz == + agg_file_view_state_p->sz || max_pre_req_sz <= 0 || + max_ol_ct <= 0) + { +#ifdef DEBUG1 + fprintf(stderr, + "ADIOI_Build_client_pre_req: Nothing to preprocess\n"); +#endif + return 0; + } + + /* The new limits have already been surpassed by what already + * exists. Otherwise we will use the next restrictions */ + if ((my_mem_view_state_p->pre_sz >= max_pre_req_sz) || + (my_mem_view_state_p->pre_ol_ct >= max_ol_ct)) + { +#ifdef DEBUG1 + fprintf(stderr, + "ADIOI_Build_client_pre_req: Old values surpass new " + "pre_req values\n"); +#endif + return 0; + } + + /* General idea is to first advance the filetype to the file realm + * and then the memtype to the filetype. The memtype is advanced + * further by peeking at the filetype and then the filetype is + * advanced. */ + for (i = 0; i < MAX_OFF_TYPE; i++) + { + switch(i) + { + case TEMP_OFF: + tmp_mem_state_p = &(my_mem_view_state_p->tmp_state); + tmp_file_state_p = &(agg_file_view_state_p->tmp_state); + break; + case REAL_OFF: + tmp_mem_state_p = &(my_mem_view_state_p->cur_state); + tmp_file_state_p = &(agg_file_view_state_p->cur_state); + break; + default: + fprintf(stderr, "ADIOI_Build_client_pre_req: " + "Invalid off type %d\n", i); + } + + if (i == TEMP_OFF && my_mem_view_state_p->pre_sz > 0) + { + cur_sz = my_mem_view_state_p->pre_sz; + agg_ol_ct = my_mem_view_state_p->pre_ol_ct; + /* Save the old arrays */ + tmp_disp_arr = my_mem_view_state_p->pre_disp_arr; + tmp_blk_arr = my_mem_view_state_p->pre_blk_arr; + my_mem_view_state_p->pre_disp_arr = NULL; + my_mem_view_state_p->pre_blk_arr = NULL; + agg_mem_next_off = + tmp_disp_arr[agg_ol_ct - 1] + tmp_blk_arr[agg_ol_ct - 1]; + } + else if (i == REAL_OFF && my_mem_view_state_p->pre_sz > 0) + { + cur_sz = my_mem_view_state_p->pre_sz; + agg_ol_cur_ct = my_mem_view_state_p->pre_ol_ct; + + /* Copy the old data to the new data, freeing the old + * arrays */ + memcpy(my_mem_view_state_p->pre_disp_arr, tmp_disp_arr, + my_mem_view_state_p->pre_ol_ct * sizeof(MPI_Aint)); + memcpy(my_mem_view_state_p->pre_blk_arr, tmp_blk_arr, + my_mem_view_state_p->pre_ol_ct * sizeof(int)); + + ADIOI_Free(tmp_disp_arr); + ADIOI_Free(tmp_blk_arr); + + agg_mem_next_off = + my_mem_view_state_p->pre_disp_arr[agg_ol_cur_ct - 1] + + my_mem_view_state_p->pre_blk_arr[agg_ol_cur_ct - 1]; + } + else + { + cur_sz = 0; + } + + /* Max_pre_req_sz may be larger than the amount of data left + * to preprocess */ + if (max_pre_req_sz - cur_sz > + agg_file_view_state_p->sz - tmp_file_state_p->cur_sz) + { + max_sz = cur_sz + + agg_file_view_state_p->sz - tmp_file_state_p->cur_sz; + } + else + max_sz = max_pre_req_sz; + + assert(cur_sz != max_sz); +#ifdef DEBUG1 + fprintf(stderr, + "ADIOI_Build_client_pre_req: (cur_sz=%Ld,agg_ol_ct=%d," + "agg_mem_next_off=%Ld,max_sz=%Ld,max_ol_ct=%d)\n", + cur_sz, agg_ol_ct, agg_mem_next_off, max_sz, max_ol_ct); +#endif + while (cur_sz < max_sz) + { + find_next_off(fd, agg_file_view_state_p, + fr_st_off_arr[agg_rank], + &(fr_type_arr[agg_rank]), + i, + &cur_off, + &cur_reg_max_len); + + /* find_next_off may show that the file_view_state is done + * even if cur_sz != max_sz since find_next_off may + * advance the file_view_state to the end here and realize + * that it is done. */ + if (cur_off == -1) + break; + + assert(cur_off != -1); + + /* Before translating the file regions to memory regions, + * we first must advance to the proper point in the + * mem_view_state for this aggregator to match the + * file_view_state. */ + while (tmp_file_state_p->cur_sz != tmp_mem_state_p->cur_sz) + { +#ifdef DTYPE_SKIP + if (my_mem_view_state_p->flat_type_p->count > 1) { + /* let's see if we can skip whole memory datatypes */ + skip_type_ct = + (tmp_file_state_p->cur_sz - tmp_mem_state_p->cur_sz) / + my_mem_view_state_p->type_sz; + if (skip_type_ct > 0) { + tmp_mem_state_p->cur_sz += + skip_type_ct * my_mem_view_state_p->type_sz; + tmp_mem_state_p->abs_off += + skip_type_ct * my_mem_view_state_p->ext; + if (tmp_mem_state_p->cur_sz == + tmp_file_state_p->cur_sz) + break; + } + } +#endif + view_state_add_region( + tmp_file_state_p->cur_sz - tmp_mem_state_p->cur_sz, + my_mem_view_state_p, + &fill_st_reg, + &fill_reg_sz, i); + } + + /* Now that the filetype and memtype are advanced to the + * same position, add memtype ol-pairs while we have not + * overstepped the min(end of the current piece in the + * file view, end of the file realm, data left in + * max_sz) */ + + if (cur_reg_max_len > + view_state_get_next_len(agg_file_view_state_p, i)) + cur_reg_max_len = + view_state_get_next_len(agg_file_view_state_p, i); + + if (cur_reg_max_len > max_sz - cur_sz) + cur_reg_max_len = max_sz - cur_sz; + + assert(cur_reg_max_len > 0); + + /* Add memtype ol pairs while we have not passed + * cur_reg_max_len or the max number of ol pairs + * allowed */ + act_reg_sz = 0; + exit_loop = 0; + while ((act_reg_sz < cur_reg_max_len) && + (exit_loop == 0)) + { + view_state_add_region( + cur_reg_max_len - act_reg_sz, + my_mem_view_state_p, + &agg_mem_st_reg, &agg_mem_act_reg_sz, + i); + act_reg_sz += agg_mem_act_reg_sz; + +#ifdef DEBUG2 + fprintf(stderr, "ADIOI_Build_client_pre_req: %s Mem region" + "(proc=%d,off=%Ld,sz=%Ld)\n", + off_type_name[i], agg_rank, agg_mem_st_reg, + agg_mem_act_reg_sz); +#endif + switch(i) + { + case TEMP_OFF: + /* Increment the ol list count if the next + * region is not adjacent to the previous + * region. */ + if (agg_mem_next_off != agg_mem_st_reg) + { + agg_ol_ct++; + if (agg_ol_ct == max_ol_ct) + exit_loop = 1; + } + agg_mem_next_off = + agg_mem_st_reg + agg_mem_act_reg_sz; + break; + case REAL_OFF: + /* Set the ol list for the memtype that + * will map to our aggregator, coaslescing + * if possible. */ + agg_next_off_idx = agg_ol_cur_ct; + if (agg_mem_next_off != agg_mem_st_reg) + { + my_mem_view_state_p-> + pre_disp_arr[agg_next_off_idx] = + agg_mem_st_reg; + my_mem_view_state_p-> + pre_blk_arr[agg_next_off_idx] = + agg_mem_act_reg_sz; + agg_ol_cur_ct++; + if (agg_ol_cur_ct == agg_ol_ct) + exit_loop = 1; + } + else + { + my_mem_view_state_p-> + pre_blk_arr[agg_next_off_idx - 1] + += agg_mem_act_reg_sz; + } + agg_mem_next_off = + agg_mem_st_reg + agg_mem_act_reg_sz; + break; + default: + fprintf(stderr, "ADIOI_Build_client_pre_req: " + "Impossible type\n"); + } + } + + /* Advance the filetype flatten state appropriately to + * match the data advanced in the memtype flatten state. + * Should only take at most a single view_state_add_region + * call since the memtype cannot proceed beyond the end of + * a contig piece in the file type. */ + view_state_add_region(act_reg_sz - tmp_reg_sz, + agg_file_view_state_p, + &fill_st_reg, &fill_reg_sz, i); +#ifdef DEBUG2 + fprintf(stderr, "ADIOI_Build_client_pre_req: %s File region" + " (proc=%d,off=%Ld,sz=%Ld)\n", + off_type_name[i], agg_rank, fill_st_reg, fill_reg_sz); +#endif + if (fill_reg_sz != act_reg_sz) + { + fprintf(stderr, "ADIOI_Build_client_pre_req: " + "view_state_add_region failed to match the memtype\n"); + return -1; + } + + cur_sz += act_reg_sz; + } + + /* On the first pass, allocate the memory structures for + * storing the preprocessed information */ + if (i == TEMP_OFF) + { + if ((my_mem_view_state_p->pre_disp_arr = (MPI_Aint *) + ADIOI_Malloc(agg_ol_ct * sizeof(MPI_Aint))) == NULL) + { + fprintf(stderr, "ADIOI_Build_client_pre_req: malloc " + "pre_disp_arr of size %ld failed\n", + (long int)agg_ol_ct * sizeof(MPI_Aint)); + return -1; + } + if ((my_mem_view_state_p->pre_blk_arr = (int *) + ADIOI_Malloc(agg_ol_ct * sizeof(int))) == NULL) + { + ADIOI_Free(my_mem_view_state_p->pre_disp_arr); + fprintf(stderr, "ADIOI_Build_client_pre_req: malloc " + "agg_blk_arr of size %ld failed\n", + (long int)agg_ol_ct * sizeof(int)); + return -1; + } + } + } + + my_mem_view_state_p->pre_sz = cur_sz; + my_mem_view_state_p->pre_ol_ct = agg_ol_ct; + +#ifdef DEBUG1 + fprintf(stderr, "ADIOI_Build_client_pre_req:(agg=%d,cur_ol_count=%d" + "=ol_count=%d)\n", + agg_rank, my_mem_view_state_p->pre_ol_ct, agg_ol_ct); +#endif + +#ifdef DEBUG2 + if (agg_ol_ct > 0) + { + fprintf(stderr, "ADIOI_Build_client_pre_req: agg=%d,pre_sz=%Ld " + "(off,len) = \n", agg_rank, my_mem_view_state_p->pre_sz); + for (i = 0; i < my_mem_view_state_p->pre_ol_ct; i++) + { + fprintf(stderr, "[%d](%d,%d) ", i, + my_mem_view_state_p->pre_disp_arr[i], + my_mem_view_state_p->pre_blk_arr[i]); + if (i % 5 == 0 && i != 0) + fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + } +#endif + + return 0; +} + +/* process_pre_req() allows ADIOI_Build_client_req to use the pre_req + * information. */ + +static int process_pre_req(ADIO_File fd, + int agg_rank, + int agg_idx, + view_state *my_mem_view_state_p, + view_state *agg_file_view_state_p, + ADIO_Offset agg_comm_sz, + int off_type, + MPI_Aint *agg_disp_arr, + int *agg_blk_arr, + ADIO_Offset *agg_comm_pre_sz_p, + ADIO_Offset *agg_comm_cur_sz_p, + ADIO_Offset *agg_comm_sz_p, + int *agg_ol_cur_ct_p, + int *agg_ol_ct_p, + ADIO_Offset *agg_mem_next_off_p) +{ + int i, has_partial = 0; + MPI_Aint partial_disp = 0; + int partial_len = 0; + ADIO_Offset tmp_agg_comm_pre_sz = 0; + + assert (my_mem_view_state_p->pre_sz > 0); + switch(off_type) + { + case TEMP_OFF: + /* Use only some of the precalculated data */ + if (my_mem_view_state_p->pre_sz > *agg_comm_sz_p) + { + for (i = 0; i < my_mem_view_state_p->pre_ol_ct; i++) + { + if ((my_mem_view_state_p->pre_blk_arr[i] + + *agg_comm_pre_sz_p) > *agg_comm_sz_p) + { + has_partial = 1; + partial_len = *agg_comm_sz_p - *agg_comm_pre_sz_p; + *agg_comm_pre_sz_p = *agg_comm_sz_p; + i++; + break; + } + else if ((my_mem_view_state_p->pre_blk_arr[i] + + *agg_comm_pre_sz_p) == *agg_comm_sz_p) + { + *agg_comm_pre_sz_p += + my_mem_view_state_p->pre_blk_arr[i]; + i++; + break; + } + else + *agg_comm_pre_sz_p += + my_mem_view_state_p->pre_blk_arr[i]; + } + + if (has_partial == 1) + { + *agg_mem_next_off_p = + my_mem_view_state_p->pre_disp_arr[i - 1] + + partial_len; + } + else + { + *agg_mem_next_off_p = + my_mem_view_state_p->pre_disp_arr[i - 1] + + my_mem_view_state_p->pre_blk_arr[i - 1]; + } + + *agg_comm_cur_sz_p = *agg_comm_pre_sz_p; + *agg_ol_ct_p = i; + + } + else /* Use all the precalculated data */ + { + *agg_comm_pre_sz_p = my_mem_view_state_p->pre_sz; + *agg_comm_cur_sz_p = *agg_comm_pre_sz_p; + *agg_ol_ct_p = my_mem_view_state_p->pre_ol_ct; + *agg_mem_next_off_p = + my_mem_view_state_p->pre_disp_arr[ + my_mem_view_state_p->pre_ol_ct - 1] + + my_mem_view_state_p->pre_blk_arr[ + my_mem_view_state_p->pre_ol_ct - 1]; + } +#ifdef DEBUG1 + fprintf(stderr, "process_pre_req: TEMP_OFF " + "agg_comm_pre_sz=%Ld,agg_comm_cur_sz=%Ld,agg_ol_ct=%d\n", + *agg_comm_pre_sz_p, *agg_comm_cur_sz_p, *agg_ol_ct_p); +#endif + assert(*agg_comm_cur_sz_p <= *agg_comm_sz_p); + break; + case REAL_OFF: + /* Set the ol list for the memtype that will map to our + * aggregator, coaslescing if possible. */ + for (i = 0; i < my_mem_view_state_p->pre_ol_ct; i++) + { + agg_disp_arr[i] = my_mem_view_state_p->pre_disp_arr[i]; + agg_blk_arr[i] = my_mem_view_state_p->pre_blk_arr[i]; + + if ((my_mem_view_state_p->pre_blk_arr[i] + + tmp_agg_comm_pre_sz) > *agg_comm_pre_sz_p) + { + has_partial = 1; + agg_blk_arr[i] = *agg_comm_pre_sz_p - tmp_agg_comm_pre_sz; + tmp_agg_comm_pre_sz = *agg_comm_pre_sz_p; + partial_disp = my_mem_view_state_p->pre_disp_arr[i] + + agg_blk_arr[i]; + partial_len = my_mem_view_state_p->pre_blk_arr[i] - + agg_blk_arr[i]; + i++; + break; + } + else if ((my_mem_view_state_p->pre_blk_arr[i] + + tmp_agg_comm_pre_sz) == *agg_comm_pre_sz_p) + { + tmp_agg_comm_pre_sz += + my_mem_view_state_p->pre_blk_arr[i]; + i++; + break; + } + else + tmp_agg_comm_pre_sz += + my_mem_view_state_p->pre_blk_arr[i]; + } + *agg_mem_next_off_p = agg_disp_arr[i - 1] + agg_blk_arr[i - 1]; + *agg_ol_cur_ct_p = i; + *agg_comm_cur_sz_p = *agg_comm_pre_sz_p; + + /* Clean up the ol pairs we used */ + if ((i < my_mem_view_state_p->pre_ol_ct) || (has_partial == 1)) + { + int remain_ol_ct = + my_mem_view_state_p->pre_ol_ct - i + has_partial; + MPI_Aint *new_pre_disp_arr = NULL; + int *new_pre_blk_arr = NULL; + + if ((new_pre_disp_arr = (MPI_Aint *) + ADIOI_Malloc(remain_ol_ct * sizeof(MPI_Aint))) == NULL) + { + fprintf(stderr, "process_pre_req: malloc " + "new_pre_disp_arr failed\n"); + return -1; + } + if ((new_pre_blk_arr = (int *) + ADIOI_Malloc(remain_ol_ct * sizeof(int))) == NULL) + { + fprintf(stderr, "process_pre_req: malloc " + "new_pre_blk_arr failed\n"); + return -1; + } + + memcpy(new_pre_disp_arr, + &(my_mem_view_state_p->pre_disp_arr[i - has_partial]), + remain_ol_ct * sizeof(MPI_Aint)); + memcpy(new_pre_blk_arr, + &(my_mem_view_state_p->pre_blk_arr[i - has_partial]), + remain_ol_ct * sizeof(int)); + + /* Set the partial len of the first piece */ + if (has_partial == 1) + { + /* new_pre_disp_arr[remain_ol_ct - 1] = partial_disp; + new_pre_blk_arr[remain_ol_ct - 1] = partial_len; */ + new_pre_disp_arr[0] = partial_disp; + new_pre_blk_arr[0] = partial_len; + } + + ADIOI_Free(my_mem_view_state_p->pre_disp_arr); + ADIOI_Free(my_mem_view_state_p->pre_blk_arr); + + my_mem_view_state_p->pre_disp_arr = new_pre_disp_arr; + my_mem_view_state_p->pre_blk_arr = new_pre_blk_arr; + my_mem_view_state_p->pre_ol_ct = remain_ol_ct; + my_mem_view_state_p->pre_sz -= *agg_comm_pre_sz_p; + } + else /* Used all the precalculated ol pairs */ + { + ADIOI_Free(my_mem_view_state_p->pre_disp_arr); + ADIOI_Free(my_mem_view_state_p->pre_blk_arr); + + my_mem_view_state_p->pre_disp_arr = NULL; + my_mem_view_state_p->pre_blk_arr = NULL; + my_mem_view_state_p->pre_ol_ct = 0; + my_mem_view_state_p->pre_sz = 0; + } +#ifdef DEBUG1 + fprintf(stderr, "process_pre_req: REAL_OFF " + "agg_comm_pre_sz=%Ld,agg_comm_cur_sz=%Ld,agg_ol_ct=%d," + "agg_ol_cur_ct=%d\n", + *agg_comm_pre_sz_p, *agg_comm_cur_sz_p, *agg_ol_ct_p, + *agg_ol_cur_ct_p); +#endif + break; + default: + fprintf(stderr, "process_pre_req: Invalid off_type %d\n", + off_type); + } + return 0; +} + +/* ADIOI_Build_client_req() creates a memory datatype to transfer data + * to/from a particular aggregator. */ + +int ADIOI_Build_client_req(ADIO_File fd, + int agg_rank, + int agg_idx, + view_state *my_mem_view_state_p, + view_state *agg_file_view_state_p, + ADIO_Offset agg_comm_sz, + MPI_Datatype *agg_comm_dtype_p) +{ + MPI_Aint *agg_disp_arr = NULL; + int *agg_blk_arr = NULL; + ADIO_Offset st_reg = 0, act_reg_sz = 0, tmp_reg_sz = 0; + ADIO_Offset cur_off = -1, cur_reg_max_len = -1; + ADIO_Offset agg_mem_st_reg = 0, agg_mem_act_reg_sz = 0; + int agg_ol_ct = 0, agg_ol_cur_ct = 0; + int i = 0, agg_next_off_idx = -1; + ADIO_Offset agg_mem_next_off = 0, agg_comm_cur_sz = 0, agg_comm_pre_sz = 0; + ADIO_Offset *fr_st_off_arr = fd->file_realm_st_offs; + MPI_Datatype *fr_type_arr = fd->file_realm_types; + flatten_state *tmp_mem_state_p = NULL, *tmp_file_state_p = NULL; +#ifdef DTYPE_SKIP + int skip_type_ct; +#endif + + if (agg_idx < 0 || agg_idx >= fd->hints->cb_nodes) + { +#ifdef DEBUG1 + fprintf(stderr, "ADIOI_Build_client_req: agg_rank %d does not map " + "to a valid node in cb_node\n", agg_rank); +#endif + return 0; + } + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5018, 0, NULL); +#endif + +#ifdef DEBUG1 + fprintf(stderr, "ADIOI_Build_client_req:(agg=%d,size_req=%Ld)\n", + agg_idx, agg_comm_sz); +#endif + + /* On the first pass see how many offset-length pairs are + * necessary for each aggregator. Then allocate the correct + * amount of offset-length pairs for handling each aggregator's + * particular data size. On the last pass, we actually create the + * offset-length pairs. */ + for (i = 0; i < MAX_OFF_TYPE; i++) + { + switch(i) + { + case TEMP_OFF: + tmp_mem_state_p = &(my_mem_view_state_p->tmp_state); + tmp_file_state_p = &(agg_file_view_state_p->tmp_state); + break; + case REAL_OFF: + tmp_mem_state_p = &(my_mem_view_state_p->cur_state); + tmp_file_state_p = &(agg_file_view_state_p->cur_state); + break; + default: + fprintf(stderr, "ADIOI_Build_client_pre_req: " + "Invalid off type %d\n", i); + } + + agg_comm_cur_sz = 0; + agg_mem_next_off = -1; + + /* First try to preprocess anything we can */ + if (my_mem_view_state_p->pre_sz > 0) + { + process_pre_req(fd, + agg_rank, + agg_idx, + my_mem_view_state_p, + agg_file_view_state_p, + agg_comm_sz, + i, + agg_disp_arr, + agg_blk_arr, + &agg_comm_pre_sz, + &agg_comm_cur_sz, + &agg_comm_sz, + &agg_ol_cur_ct, + &agg_ol_ct, + &agg_mem_next_off); + } + + while (agg_comm_cur_sz < agg_comm_sz) + { + find_next_off(fd, agg_file_view_state_p, + fr_st_off_arr[agg_idx], + &(fr_type_arr[agg_idx]), + i, + &cur_off, + &cur_reg_max_len); + + assert(cur_off != -1); + + /* Add up to the end of the file realm or as many bytes + * are left for this particular aggregator in the client's + * filetype */ + if (cur_reg_max_len > (agg_comm_sz - agg_comm_cur_sz)) + { + cur_reg_max_len = agg_comm_sz - agg_comm_cur_sz; + } + assert(cur_reg_max_len > 0); + + view_state_add_region( + cur_reg_max_len, + agg_file_view_state_p, + &st_reg, &act_reg_sz, i); + +#ifdef DEBUG2 + fprintf(stderr, "ADIOI_Build_client_req: %s File region" + " (proc=%d,off=%Ld,sz=%Ld)\n", + off_type_name[i], agg_rank, cur_off, act_reg_sz); +#endif + + /* Before translating the file regions to memory regions, + * we first must advance to the proper point in the + * mem_view_state for this aggregator to match the + * file_view_state. */ + + assert(tmp_file_state_p->cur_sz - act_reg_sz >= + tmp_mem_state_p->cur_sz); + + while (tmp_file_state_p->cur_sz - act_reg_sz != + tmp_mem_state_p->cur_sz) + { + ADIO_Offset fill_st_reg = -1, fill_reg_sz = -1; +#ifdef DTYPE_SKIP + if (my_mem_view_state_p->flat_type_p->count > 1) { + /* let's see if we can skip whole memory datatypes */ + skip_type_ct = + (tmp_file_state_p->cur_sz - act_reg_sz - + tmp_mem_state_p->cur_sz) / + my_mem_view_state_p->type_sz; + if (skip_type_ct > 0) { + tmp_mem_state_p->cur_sz += + skip_type_ct * my_mem_view_state_p->type_sz; + tmp_mem_state_p->abs_off += + skip_type_ct * my_mem_view_state_p->ext; + if ((tmp_mem_state_p->cur_sz - act_reg_sz) == + tmp_file_state_p->cur_sz) + break; + } + } +#endif + view_state_add_region( + tmp_file_state_p->cur_sz - + act_reg_sz - tmp_mem_state_p->cur_sz, + my_mem_view_state_p, + &fill_st_reg, + &fill_reg_sz, i); + } + + /* Based on how large the act_reg_sz is, first figure + * out how many memory offset-length pairs are + * necessary and then set the offset-length pairs. */ + tmp_reg_sz = 0; + while (tmp_reg_sz != act_reg_sz) + { + view_state_add_region( + act_reg_sz - tmp_reg_sz, + my_mem_view_state_p, + &agg_mem_st_reg, &agg_mem_act_reg_sz, + i); + tmp_reg_sz += agg_mem_act_reg_sz; + +#ifdef DEBUG2 + fprintf(stderr, "ADIOI_Build_client_req: %s Mem region" + "(off=%Ld,sz=%Ld)\n", + off_type_name[i], agg_mem_st_reg, + agg_mem_act_reg_sz); +#endif + agg_comm_cur_sz += agg_mem_act_reg_sz; + switch(i) + { + case TEMP_OFF: + /* Increment the ol list count if the next + * region is not adjacent to the previous + * region. */ + if (agg_mem_next_off != agg_mem_st_reg) + { + agg_ol_ct++; + } + agg_mem_next_off = + agg_mem_st_reg + agg_mem_act_reg_sz; + break; + case REAL_OFF: + /* Set the ol list for the memtype that + * will map to our aggregator, coaslescing + * if possible. */ + agg_next_off_idx = agg_ol_cur_ct; + if (agg_mem_next_off != agg_mem_st_reg) + { + agg_disp_arr[agg_next_off_idx] = + agg_mem_st_reg; + agg_blk_arr[agg_next_off_idx] = + agg_mem_act_reg_sz; + agg_ol_cur_ct++; + } + else + { + agg_blk_arr[agg_next_off_idx - 1] + += agg_mem_act_reg_sz; + } + agg_mem_next_off = + agg_mem_st_reg + agg_mem_act_reg_sz; + break; + default: + fprintf(stderr, "ADIOI_Build_client_req: " + "Impossible type\n"); + } + } + } + + /* On the first pass, allocate the memory structures for + * creating the MPI_hindexed type. */ + if (i == TEMP_OFF) + { + /* Allocate offset-length pairs for creating hindexed + * MPI_Datatypes for each aggregator */ + if ((agg_disp_arr = (MPI_Aint *) + ADIOI_Malloc(agg_ol_ct * sizeof(MPI_Aint))) == NULL) + { + fprintf(stderr, "ADIOI_Build_client_req: malloc " + "agg_disp_arr of size %ld failed\n", + (long int)agg_ol_ct * sizeof(MPI_Aint)); + return -1; + } + if ((agg_blk_arr = (int *) + ADIOI_Malloc(agg_ol_ct * sizeof(int))) == NULL) + { + ADIOI_Free(agg_disp_arr); + fprintf(stderr, "ADIOI_Build_client_req: malloc " + "agg_blk_arr of size %ld failed\n", + (long int)agg_ol_ct * sizeof(int)); + return -1; + } + } + } + + assert(agg_ol_ct == agg_ol_cur_ct); +#ifdef DEBUG1 + fprintf(stderr, + "ADIOI_Build_client_req:(agg=%d,cur_ol_count=%d=ol_count=%d)\n", + agg_rank, agg_ol_cur_ct, agg_ol_ct); +#endif + +#ifdef DEBUG2 + if (agg_ol_ct > 0) + { + fprintf(stderr, "ADIOI_Build_client_req: p %d (off,len) = ", agg_rank); + for (i = 0; i < agg_ol_ct; i++) + { + fprintf(stderr, "[%d](%d,%d) ", i, + agg_disp_arr[i], agg_blk_arr[i]); + if (i % 5 == 0 && i != 0) + fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + } +#endif +#ifdef DEBUG1 + fprintf(stderr, + "ADIOI_Build_client_req:(agg=%d,pre_ol_count=%d)\n", + agg_idx, my_mem_view_state_p->pre_ol_ct); +#endif + +#ifdef DEBUG2 + if (my_mem_view_state_p->pre_sz > 0) + { + fprintf(stderr, "ADIOI_Build_client_req: p %d pre(off,len) = ", + agg_idx); + for (i = 0; i < my_mem_view_state_p->pre_ol_ct; i++) + { + fprintf(stderr, "[%d](%d,%d) ", i, + my_mem_view_state_p->pre_disp_arr[i], + my_mem_view_state_p->pre_blk_arr[i]); + if (i % 5 == 0 && i != 0) + fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + } +#endif + + /* Create the aggregator MPI_Datatype */ + if (agg_comm_sz > 0) + { + MPI_Type_hindexed(agg_ol_ct, agg_blk_arr, agg_disp_arr, MPI_BYTE, + agg_comm_dtype_p); + MPI_Type_commit(agg_comm_dtype_p); + } + else + { + *agg_comm_dtype_p = MPI_BYTE; + } + + ADIOI_Free(agg_blk_arr); + ADIOI_Free(agg_disp_arr); + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5019, 0, NULL); +#endif + return 0; +} + + diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_coll_exch_new.c b/ompi/mca/io/romio314/romio/adio/common/ad_coll_exch_new.c new file mode 100644 index 0000000000..d121589d69 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_coll_exch_new.c @@ -0,0 +1,509 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include +#include "adio.h" +#include "adio_extern.h" +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + +/* +#define DEBUG +#define DEBUG2 +*/ + +#define COUNT_EXCH 0 +#define BLOCK_LENS 1 +#define INDICES 2 +#define FPIND_DISP_OFF_SZ 3 + + +typedef struct { + int count; + ADIO_Offset fp_ind; + ADIO_Offset disp; + ADIO_Offset byte_off; + ADIO_Offset sz; + ADIO_Offset ext; + ADIO_Offset type_sz; +} amount_and_extra_data_t; + +/* Debugging function to print out an ADIOI_Flatlist_node. */ +void ADIOI_Print_flatlist_node(ADIOI_Flatlist_node *flatlist_node_p) +{ + int i; + if (flatlist_node_p == NULL) + { + fprintf(stderr, "print flatlist node of NULL ptr\n"); + return; + } + fprintf(stderr, "print flatlist node count = %d (idx,blocklen)\n", + (int)flatlist_node_p->count); + for (i = 0; i < flatlist_node_p->count; i++) + { + if (i % 5 == 0 && i != 0) + { + fprintf(stderr, "%d=(%lld,%lld)\n", i, (long long)flatlist_node_p->indices[i], + (long long)flatlist_node_p->blocklens[i]); + } + else + fprintf(stderr, "%d=(%lld,%lld) ", i, (long long)flatlist_node_p->indices[i], + (long long)flatlist_node_p->blocklens[i]); + } + fprintf(stderr, "\n"); +} + +/* Since ADIOI_Flatten_datatype won't add a contig datatype to the + * ADIOI_Flatlist, we can force it to do so with this function. */ +ADIOI_Flatlist_node * ADIOI_Add_contig_flattened(MPI_Datatype contig_type) +{ + MPI_Count contig_type_sz = -1; + ADIOI_Flatlist_node *flat_node_p = ADIOI_Flatlist; + + /* Add contig type to the end of the list if it doesn't already + * exist. */ + while (flat_node_p->next) + { + if (flat_node_p->type == contig_type) + return flat_node_p; + flat_node_p = flat_node_p->next; + } + if (flat_node_p->type == contig_type) + return flat_node_p; + + MPI_Type_size_x(contig_type, &contig_type_sz); + if ((flat_node_p->next = (ADIOI_Flatlist_node *) ADIOI_Malloc + (sizeof(ADIOI_Flatlist_node))) == NULL) + { + fprintf(stderr, "ADIOI_Add_contig_flattened: malloc next failed\n"); + } + flat_node_p = flat_node_p->next; + flat_node_p->type = contig_type; + if ((flat_node_p->blocklens = (ADIO_Offset *) ADIOI_Malloc(sizeof(ADIO_Offset))) == NULL) + { + fprintf(stderr, "ADIOI_Flatlist_node: malloc blocklens failed\n"); + } + if ((flat_node_p->indices = (ADIO_Offset *) + ADIOI_Malloc(sizeof(ADIO_Offset))) == NULL) + { + fprintf(stderr, "ADIOI_Flatlist_node: malloc indices failed\n"); + } + flat_node_p->blocklens[0] = contig_type_sz; + flat_node_p->indices[0] = 0; + flat_node_p->count = 1; + flat_node_p->next = NULL; + return flat_node_p; +} + +/* ADIOI_Exchange_file_views - Sends all the aggregators the file + * views and file view states of the clients. It fills in the + * client_file_view_state_arr for the aggregators and the + * my_mem_view_state for the client. It also initializes the + * agg_file_view_state for all clients, which is the view for each + * aggregator of a client's filetype. */ +void ADIOI_Exch_file_views(int myrank, int nprocs, int file_ptr_type, + ADIO_File fd, int count, + MPI_Datatype datatype, ADIO_Offset off, + view_state *my_mem_view_state_arr, + view_state *agg_file_view_state_arr, + view_state *client_file_view_state_arr) +{ + /* Convert my own fileview to an ADIOI_Flattened type and a + * disp. MPI_Alltoall the count of ADIOI_Flatlist nodes. + * MPI_Isend/Irecv the block_lens, indices of ADIOI_Flatlist node + * to/from each of the aggregators with the rest of the file view + * state. */ + + int i = -1, j = -1; + amount_and_extra_data_t *send_count_arr = NULL; + amount_and_extra_data_t *recv_count_arr = NULL; + int send_req_arr_sz = 0; + int recv_req_arr_sz = 0; + MPI_Request *send_req_arr = NULL, *recv_req_arr = NULL; + MPI_Status *statuses = NULL; + ADIO_Offset disp_off_sz_ext_typesz[6]; + MPI_Aint memtype_extent, filetype_extent; + int ret = -1; + + /* parameters for datatypes */ + ADIOI_Flatlist_node *flat_mem_p = NULL, *flat_file_p = NULL; + MPI_Count memtype_sz = -1; + int memtype_is_contig = -1; + ADIO_Offset filetype_sz = -1; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5014, 0, NULL); +#endif + /* The memtype will be freed after the call. The filetype will be + * freed in the close and should have been flattened in the file + * view. */ + MPI_Type_size_x(datatype, &memtype_sz); + MPI_Type_extent(datatype, &memtype_extent); + if (memtype_sz == memtype_extent) { + memtype_is_contig = 1; + flat_mem_p = ADIOI_Add_contig_flattened(datatype); + flat_mem_p->blocklens[0] = memtype_sz*count; + } + else { + ADIOI_Flatten_datatype(datatype); + flat_mem_p = ADIOI_Flatlist; + while (flat_mem_p->type != datatype) + flat_mem_p = flat_mem_p->next; + } + + MPI_Type_extent(fd->filetype, &filetype_extent); + MPI_Type_size_x(fd->filetype, &filetype_sz); + if (filetype_extent == filetype_sz) { + flat_file_p = ADIOI_Add_contig_flattened(fd->filetype); + flat_file_p->blocklens[0] = memtype_sz*count; + filetype_extent = memtype_sz*count; + filetype_sz = filetype_extent; + } + else { + flat_file_p = ADIOI_Flatlist; + while (flat_file_p->type != fd->filetype) + flat_file_p = flat_file_p->next; + } + + disp_off_sz_ext_typesz[0] = fd->fp_ind; + disp_off_sz_ext_typesz[1] = fd->disp; + disp_off_sz_ext_typesz[2] = off; + disp_off_sz_ext_typesz[3] = memtype_sz*count; + disp_off_sz_ext_typesz[4] = (ADIO_Offset) filetype_extent; + disp_off_sz_ext_typesz[5] = (ADIO_Offset) filetype_sz; + + if (fd->hints->cb_alltoall != ADIOI_HINT_DISABLE) { + recv_count_arr = ADIOI_Calloc(nprocs, sizeof(amount_and_extra_data_t)); + send_count_arr = ADIOI_Calloc(nprocs, sizeof(amount_and_extra_data_t)); + } else { + send_count_arr = ADIOI_Calloc(fd->hints->cb_nodes, + sizeof(amount_and_extra_data_t)); + + /* only aggregators receive data */ + if (fd->is_agg) { + recv_count_arr = ADIOI_Calloc(nprocs, + sizeof(amount_and_extra_data_t)); + recv_req_arr = ADIOI_Malloc (nprocs * sizeof(MPI_Request)); + for (i=0; i < nprocs; i++) + MPI_Irecv (&recv_count_arr[i], sizeof(amount_and_extra_data_t), + MPI_BYTE, i, COUNT_EXCH, fd->comm, &recv_req_arr[i]); + } + + /* only send data to aggregators */ + send_req_arr = ADIOI_Calloc (fd->hints->cb_nodes, sizeof(MPI_Request)); + for (i=0; i < fd->hints->cb_nodes; i++) { + send_count_arr[i].count = flat_file_p->count; + send_count_arr[i].fp_ind = disp_off_sz_ext_typesz[0]; + send_count_arr[i].disp = disp_off_sz_ext_typesz[1]; + send_count_arr[i].byte_off = disp_off_sz_ext_typesz[2]; + send_count_arr[i].sz = disp_off_sz_ext_typesz[3]; + send_count_arr[i].ext = disp_off_sz_ext_typesz[4]; + send_count_arr[i].type_sz = disp_off_sz_ext_typesz[5]; + MPI_Isend (&send_count_arr[i], sizeof(amount_and_extra_data_t), + MPI_BYTE, fd->hints->ranklist[i], COUNT_EXCH, fd->comm, + &send_req_arr[i]); + } + } + + + /* Every client has to build mem and file view_states for each aggregator. + * We initialize their values here. and we also initialize + * send_count_arr */ + + if (memtype_is_contig) { + /* if memory is contigous, we now replace memtype_sz and + * memtype_extent with the full access size */ + memtype_sz *= count; + memtype_extent = memtype_sz; + } + + for (i = 0; i < fd->hints->cb_nodes; i++) + { + int tmp_agg_idx = fd->hints->ranklist[i]; + memset(&(my_mem_view_state_arr[tmp_agg_idx]), 0, sizeof(view_state)); + my_mem_view_state_arr[tmp_agg_idx].sz = + disp_off_sz_ext_typesz[3]; + my_mem_view_state_arr[tmp_agg_idx].ext = + (ADIO_Offset) memtype_extent; + my_mem_view_state_arr[tmp_agg_idx].type_sz = + (ADIO_Offset) memtype_sz; + my_mem_view_state_arr[tmp_agg_idx].flat_type_p = flat_mem_p; + ADIOI_init_view_state(file_ptr_type, + 1, + &(my_mem_view_state_arr[tmp_agg_idx]), + TEMP_OFF); + ADIOI_init_view_state(file_ptr_type, + 1, + &(my_mem_view_state_arr[tmp_agg_idx]), + REAL_OFF); + + memset(&(agg_file_view_state_arr[tmp_agg_idx]), 0, sizeof(view_state)); + agg_file_view_state_arr[tmp_agg_idx].fp_ind = + disp_off_sz_ext_typesz[0]; + agg_file_view_state_arr[tmp_agg_idx].disp = + disp_off_sz_ext_typesz[1]; + agg_file_view_state_arr[tmp_agg_idx].byte_off = + disp_off_sz_ext_typesz[2]; + agg_file_view_state_arr[tmp_agg_idx].sz = + disp_off_sz_ext_typesz[3]; + agg_file_view_state_arr[tmp_agg_idx].ext = + disp_off_sz_ext_typesz[4]; + agg_file_view_state_arr[tmp_agg_idx].type_sz = + disp_off_sz_ext_typesz[5]; + agg_file_view_state_arr[tmp_agg_idx].flat_type_p = flat_file_p; + + ADIOI_init_view_state(file_ptr_type, + 1, + &(agg_file_view_state_arr[tmp_agg_idx]), + TEMP_OFF); + ADIOI_init_view_state(file_ptr_type, + 1, + &(agg_file_view_state_arr[tmp_agg_idx]), + REAL_OFF); + + if (fd->hints->cb_alltoall != ADIOI_HINT_DISABLE) { + send_count_arr[tmp_agg_idx].count = flat_file_p->count; + send_count_arr[tmp_agg_idx].fp_ind = disp_off_sz_ext_typesz[0]; + send_count_arr[tmp_agg_idx].disp = disp_off_sz_ext_typesz[1]; + send_count_arr[tmp_agg_idx].byte_off = disp_off_sz_ext_typesz[2]; + send_count_arr[tmp_agg_idx].sz = disp_off_sz_ext_typesz[3]; + send_count_arr[tmp_agg_idx].ext = disp_off_sz_ext_typesz[4]; + send_count_arr[tmp_agg_idx].type_sz = disp_off_sz_ext_typesz[5]; + } + } + +#ifdef DEBUG2 + fprintf(stderr, "my own flattened memtype: "); + ADIOI_Print_flatlist_node(flat_mem_p); + fprintf(stderr, "my own flattened filetype: "); + ADIOI_Print_flatlist_node(flat_file_p); +#endif + + if (fd->hints->cb_alltoall != ADIOI_HINT_DISABLE) { + ret = MPI_Alltoall(send_count_arr, sizeof(amount_and_extra_data_t), + MPI_BYTE, + recv_count_arr, sizeof(amount_and_extra_data_t), + MPI_BYTE, fd->comm); + if (ret != MPI_SUCCESS) + { + fprintf(stderr, "ADIOI_Exchange_file_views: MPI_Alltoall failed " + "with error %d", ret); + return; + } + } else { + statuses = (MPI_Status *) ADIOI_Malloc(1 + nprocs * sizeof(MPI_Status)); + if (fd->is_agg) { + MPI_Waitall(nprocs, recv_req_arr, statuses); + ADIOI_Free(recv_req_arr); + } + MPI_Waitall(fd->hints->cb_nodes, send_req_arr, statuses); + ADIOI_Free(statuses); + ADIOI_Free(send_req_arr); + } +#ifdef DEBUG2 + if (fd->hints->cb_alltoall != ADIOI_HINT_DISABLE) { + fprintf(stderr, "send_count_arr:"); + for (i = 0; i < nprocs; i++) + { + fprintf(stderr, "[%d]=%d ", i, send_count_arr[i].count); + } + fprintf(stderr, "\n"); + fprintf(stderr, "recv_count_arr:"); + for (i = 0; i < nprocs; i++) + { + fprintf(stderr, "[%d]=%d ", i, recv_count_arr[i].count); + } + fprintf(stderr, "\n"); + } else { + fprintf(stderr, "send_count_arr:"); + for (i = 0; i < fd->hints->cb_nodes; i++) + { + fprintf(stderr, "[%d]=%d ", i, send_count_arr[i].count); + } + fprintf(stderr, "\n"); + if (fd->is_agg) { + fprintf(stderr, "recv_count_arr:"); + for (i = 0; i < nprocs; i++) + { + fprintf(stderr, "[%d]=%d ", i, recv_count_arr[i].count); + } + fprintf(stderr, "\n"); + } + } +#endif + + if (fd->hints->cb_alltoall == ADIOI_HINT_DISABLE) { + for (i=0; i < fd->hints->cb_nodes; i++) + if (send_count_arr[i].count > 0) + send_req_arr_sz++; + } + /* Figure out how many counts to send/recv */ + for (i = 0; i < nprocs; i++) + { + if (fd->hints->cb_alltoall != ADIOI_HINT_DISABLE) { + if (send_count_arr[i].count > 0) + send_req_arr_sz++; + } + /* Only aggregators should recv*/ + if (fd->is_agg) { + if (recv_count_arr[i].count > 0) + { + if ((client_file_view_state_arr[i].flat_type_p = + (ADIOI_Flatlist_node *) ADIOI_Malloc( + sizeof(ADIOI_Flatlist_node))) == NULL) + { + fprintf(stderr, "ADIOI_Exchange_file_views: malloc " + "flat_type_p failed\n"); + } + client_file_view_state_arr[i].flat_type_p->count = + recv_count_arr[i].count; + client_file_view_state_arr[i].flat_type_p->indices = + (ADIO_Offset *) ADIOI_Calloc(recv_count_arr[i].count, + sizeof(ADIO_Offset)); + client_file_view_state_arr[i].flat_type_p->blocklens = + (ADIO_Offset *) ADIOI_Calloc(recv_count_arr[i].count, + sizeof(ADIO_Offset)); + + /* Copy the extra data out of the stuff we Alltoall'd */ + memcpy (&client_file_view_state_arr[i].fp_ind, + &recv_count_arr[i].fp_ind, + 6*sizeof(ADIO_Offset)); + + recv_req_arr_sz++; + } + } + } + + /* Since ADIOI_Calloc may do other things we add the +1 + * to avoid a 0-size malloc */ + send_req_arr = (MPI_Request *) ADIOI_Calloc(2*(send_req_arr_sz)+1, + sizeof(MPI_Request)); + + j = 0; + if (recv_req_arr_sz > 0) { + assert (fd->is_agg); + recv_req_arr = (MPI_Request *) ADIOI_Calloc(2*(recv_req_arr_sz), + sizeof(MPI_Request)); + for (i = 0; i < nprocs; i++) { + if (recv_count_arr[i].count > 0) { + MPI_Irecv(client_file_view_state_arr[i].flat_type_p->indices, + recv_count_arr[i].count, ADIO_OFFSET, i, + INDICES, fd->comm, &recv_req_arr[j]); + j++; + MPI_Irecv(client_file_view_state_arr[i].flat_type_p->blocklens, + recv_count_arr[i].count, ADIO_OFFSET, i, + BLOCK_LENS, fd->comm, &recv_req_arr[j]); + j++; + } + } + } + + if (fd->hints->cb_alltoall != ADIOI_HINT_DISABLE) { + j = 0; + for (i = 0; i < nprocs; i++) { + if (send_count_arr[i].count > 0) { + MPI_Isend(flat_file_p->indices, + send_count_arr[i].count, ADIO_OFFSET, i, + INDICES, fd->comm, &send_req_arr[j]); + j++; + MPI_Isend(flat_file_p->blocklens, + send_count_arr[i].count, ADIO_OFFSET, i, + BLOCK_LENS, fd->comm, &send_req_arr[j]); + j++; + } + } + } else { + j = 0; + for (i = 0; i < fd->hints->cb_nodes; i++) { + if (send_count_arr[i].count > 0) { + MPI_Isend(flat_file_p->indices, + send_count_arr[i].count, ADIO_OFFSET, + fd->hints->ranklist[i], INDICES, fd->comm, + &send_req_arr[j]); + j++; + MPI_Isend(flat_file_p->blocklens, + send_count_arr[i].count, ADIO_OFFSET, + fd->hints->ranklist[i], BLOCK_LENS, fd->comm, + &send_req_arr[j]); + j++; + } + } + } + + /* Since ADIOI_Malloc may do other things we add the +1 + * to avoid a 0-size malloc */ + statuses = (MPI_Status *) + ADIOI_Malloc(1 + 2 * ADIOI_MAX(send_req_arr_sz,recv_req_arr_sz) + * sizeof(MPI_Status)); + + if (send_req_arr_sz > 0) { + MPI_Waitall(2 * send_req_arr_sz, send_req_arr, statuses); + ADIOI_Free(send_count_arr); + ADIOI_Free(send_req_arr); + } + if (recv_req_arr_sz > 0) { + MPI_Waitall(2 * recv_req_arr_sz, recv_req_arr, statuses); + ADIOI_Free(recv_count_arr); + ADIOI_Free(recv_req_arr); + } + ADIOI_Free(statuses); + + if (fd->is_agg == 1) + { + ADIOI_init_view_state(file_ptr_type, + nprocs, + client_file_view_state_arr, + TEMP_OFF); + ADIOI_init_view_state(file_ptr_type, + nprocs, + client_file_view_state_arr, + REAL_OFF); + } + +#ifdef DEBUG + if (fd->is_agg == 1) + { + ADIOI_Flatlist_node *fr_node_p = ADIOI_Flatlist; + for (i = 0; i < nprocs; i++) + { + fprintf(stderr, "client_file_view_state_arr[%d]=(fp_ind=%Ld," + "disp=%Ld,byte_off=%Ld,sz=%Ld,ext=%Ld\n", i, + client_file_view_state_arr[i].fp_ind, + client_file_view_state_arr[i].disp, + client_file_view_state_arr[i].byte_off, + client_file_view_state_arr[i].sz, + client_file_view_state_arr[i].ext); + } + + while (fr_node_p->type != + fd->file_realm_types[fd->my_cb_nodes_index]) + fr_node_p = fr_node_p->next; + assert(fr_node_p != NULL); + + fprintf(stderr, "my file realm (idx=%d,st_off=%Ld) ", + fd->my_cb_nodes_index, + fd->file_realm_st_offs[fd->my_cb_nodes_index]); + ADIOI_Print_flatlist_node(fr_node_p); + } +#endif + +#ifdef DEBUG2 + if (fd->is_agg == 1) + { + for (i = 0; i < nprocs; i++) + { + fprintf(stderr, "client_file_view_state_arr[%d]: ", i); + ADIOI_Print_flatlist_node( + client_file_view_state_arr[i].flat_type_p); + } + } +#endif +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5015, 0, NULL); +#endif +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_darray.c b/ompi/mca/io/romio314/romio/adio/common/ad_darray.c new file mode 100644 index 0000000000..23715c412f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_darray.c @@ -0,0 +1,295 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +static int MPIOI_Type_block(int *array_of_gsizes, int dim, int ndims, int nprocs, + int rank, int darg, int order, MPI_Aint orig_extent, + MPI_Datatype type_old, MPI_Datatype *type_new, + MPI_Aint *st_offset); +static int MPIOI_Type_cyclic(int *array_of_gsizes, int dim, int ndims, int nprocs, + int rank, int darg, int order, MPI_Aint orig_extent, + MPI_Datatype type_old, MPI_Datatype *type_new, + MPI_Aint *st_offset); + + +int ADIO_Type_create_darray(int size, int rank, int ndims, + int *array_of_gsizes, int *array_of_distribs, + int *array_of_dargs, int *array_of_psizes, + int order, MPI_Datatype oldtype, + MPI_Datatype *newtype) +{ + MPI_Datatype type_old, type_new=MPI_DATATYPE_NULL, types[3]; + int procs, tmp_rank, i, tmp_size, blklens[3], *coords; + MPI_Aint *st_offsets, orig_extent, disps[3]; + + MPI_Type_extent(oldtype, &orig_extent); + +/* calculate position in Cartesian grid as MPI would (row-major + ordering) */ + coords = (int *) ADIOI_Malloc(ndims*sizeof(int)); + procs = size; + tmp_rank = rank; + for (i=0; i=0; i--) { + switch(array_of_distribs[i]) { + case MPI_DISTRIBUTE_BLOCK: + MPIOI_Type_block(array_of_gsizes, i, ndims, array_of_psizes[i], + coords[i], array_of_dargs[i], order, + orig_extent, type_old, &type_new, + st_offsets+i); + break; + case MPI_DISTRIBUTE_CYCLIC: + MPIOI_Type_cyclic(array_of_gsizes, i, ndims, + array_of_psizes[i], coords[i], + array_of_dargs[i], order, + orig_extent, type_old, &type_new, + st_offsets+i); + break; + case MPI_DISTRIBUTE_NONE: + /* treat it as a block distribution on 1 process */ + MPIOI_Type_block(array_of_gsizes, i, ndims, array_of_psizes[i], + coords[i], MPI_DISTRIBUTE_DFLT_DARG, order, orig_extent, + type_old, &type_new, st_offsets+i); + break; + } + if (i != ndims-1) MPI_Type_free(&type_old); + type_old = type_new; + } + + /* add displacement and UB */ + disps[1] = st_offsets[ndims-1]; + tmp_size = 1; + for (i=ndims-2; i>=0; i--) { + tmp_size *= array_of_gsizes[i+1]; + disps[1] += (MPI_Aint)tmp_size*st_offsets[i]; + } + } + + disps[1] *= orig_extent; + + disps[2] = orig_extent; + for (i=0; idim; i--) stride *= (MPI_Aint)array_of_gsizes[i]; + MPI_Type_hvector(mysize, 1, stride, type_old, type_new); + } + + } + + *st_offset = (MPI_Aint)blksize * (MPI_Aint)rank; + /* in terms of no. of elements of type oldtype in this dimension */ + if (mysize == 0) *st_offset = 0; + + return MPI_SUCCESS; +} + + +/* Returns MPI_SUCCESS on success, an MPI error code on failure. Code above + * needs to call MPIO_Err_return_xxx. + */ +static int MPIOI_Type_cyclic(int *array_of_gsizes, int dim, int ndims, int nprocs, + int rank, int darg, int order, MPI_Aint orig_extent, + MPI_Datatype type_old, MPI_Datatype *type_new, + MPI_Aint *st_offset) +{ +/* nprocs = no. of processes in dimension dim of grid + rank = coordinate of this process in dimension dim */ + int blksize, i, blklens[3], st_index, end_index, local_size, rem, count; + MPI_Aint stride, disps[3]; + MPI_Datatype type_tmp, types[3]; + + if (darg == MPI_DISTRIBUTE_DFLT_DARG) blksize = 1; + else blksize = darg; + + /* --BEGIN ERROR HANDLING-- */ + if (blksize <= 0) { + return MPI_ERR_ARG; + } + /* --END ERROR HANDLING-- */ + + st_index = rank*blksize; + end_index = array_of_gsizes[dim] - 1; + + if (end_index < st_index) local_size = 0; + else { + local_size = ((end_index - st_index + 1)/(nprocs*blksize))*blksize; + rem = (end_index - st_index + 1) % (nprocs*blksize); + local_size += ADIOI_MIN(rem, blksize); + } + + count = local_size/blksize; + rem = local_size % blksize; + + stride = (MPI_Aint)nprocs*(MPI_Aint)blksize*orig_extent; + if (order == MPI_ORDER_FORTRAN) + for (i=0; idim; i--) stride *= (MPI_Aint)array_of_gsizes[i]; + + MPI_Type_hvector(count, blksize, stride, type_old, type_new); + + if (rem) { + /* if the last block is of size less than blksize, include + it separately using MPI_Type_struct */ + + types[0] = *type_new; + types[1] = type_old; + disps[0] = 0; + disps[1] = (MPI_Aint)count*stride; + blklens[0] = 1; + blklens[1] = rem; + + MPI_Type_struct(2, blklens, disps, types, &type_tmp); + + MPI_Type_free(type_new); + *type_new = type_tmp; + } + + /* In the first iteration, we need to set the displacement in that + dimension correctly. */ + if ( ((order == MPI_ORDER_FORTRAN) && (dim == 0)) || + ((order == MPI_ORDER_C) && (dim == ndims-1)) ) { + types[0] = MPI_LB; + disps[0] = 0; + types[1] = *type_new; + disps[1] = (MPI_Aint)rank * (MPI_Aint)blksize * orig_extent; + types[2] = MPI_UB; + disps[2] = orig_extent * (MPI_Aint)array_of_gsizes[dim]; + blklens[0] = blklens[1] = blklens[2] = 1; + MPI_Type_struct(3, blklens, disps, types, &type_tmp); + MPI_Type_free(type_new); + *type_new = type_tmp; + + *st_offset = 0; /* set it to 0 because it is taken care of in + the struct above */ + } + else { + *st_offset = (MPI_Aint)rank * (MPI_Aint)blksize; + /* st_offset is in terms of no. of elements of type oldtype in + * this dimension */ + } + + if (local_size == 0) *st_offset = 0; + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_delete.c b/ompi/mca/io/romio314/romio/adio/common/ad_delete.c new file mode 100644 index 0000000000..ae78d7e0a7 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_delete.c @@ -0,0 +1,24 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +void ADIOI_GEN_Delete(const char *filename, int *error_code) +{ + int err; + static char myname[] = "ADIOI_GEN_DELETE"; + + err = unlink(filename); + if (err == -1) { + *error_code = ADIOI_Err_create_code(myname, filename, errno); + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_done.c b/ompi/mca/io/romio314/romio/adio/common/ad_done.c new file mode 100644 index 0000000000..fe489780b6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_done.c @@ -0,0 +1,47 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + +/* Workaround for incomplete set of definitions if __REDIRECT is not + defined and large file support is used in aio.h */ +#if !defined(__REDIRECT) && defined(__USE_FILE_OFFSET64) +#define aiocb aiocb64 +#endif + +/* ADIOI_GEN_IODone + * + * This code handles two distinct cases. If ROMIO_HAVE_WORKING_AIO is not + * defined, then I/O was done as a blocking call earlier. In that case + * we have nothing much to do other than set the bytes transferred and + * free the request. + * + * If ROMIO_HAVE_WORKING_AIO is defined, then we may need to wait for I/O + * to complete. + */ +int ADIOI_GEN_IODone(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + return 0; + +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_done_fake.c b/ompi/mca/io/romio314/romio/adio/common/ad_done_fake.c new file mode 100644 index 0000000000..59da5755e0 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_done_fake.c @@ -0,0 +1,20 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +/* Generic implementation of ReadDone/WriteDone simply sets the + * bytes field in the status structure and frees the request. + * + * Same function is used for both reads and writes. + */ +int ADIOI_FAKE_IODone(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + /* should not ever get called now */ + return 1; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_end.c b/ompi/mca/io/romio314/romio/adio/common/ad_end.c new file mode 100644 index 0000000000..ea4dfeb74d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_end.c @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +void ADIO_End(int *error_code) +{ + ADIOI_Flatlist_node *curr, *next; + ADIOI_Datarep *datarep, *datarep_next; + +/* FPRINTF(stderr, "reached end\n"); */ + + /* if a default errhandler was set on MPI_FILE_NULL then we need to ensure + * that our reference to that errhandler is released */ + PMPI_File_set_errhandler(MPI_FILE_NULL, MPI_ERRORS_RETURN); + +/* delete the flattened datatype list */ + curr = ADIOI_Flatlist; + while (curr) { + if (curr->blocklens) ADIOI_Free(curr->blocklens); + if (curr->indices) ADIOI_Free(curr->indices); + next = curr->next; + ADIOI_Free(curr); + curr = next; + } + ADIOI_Flatlist = NULL; + +/* free file and info tables used for Fortran interface */ + if (ADIOI_Ftable) ADIOI_Free(ADIOI_Ftable); +#ifndef HAVE_MPI_INFO + if (MPIR_Infotable) ADIOI_Free(MPIR_Infotable); +#endif + + +/* free the memory allocated for a new data representation, if any */ + datarep = ADIOI_Datarep_head; + while (datarep) { + datarep_next = datarep->next; + ADIOI_Free(datarep->name); + ADIOI_Free(datarep); + datarep = datarep_next; + } + + if( ADIOI_syshints != MPI_INFO_NULL) + MPI_Info_free(&ADIOI_syshints); + + MPI_Op_free(&ADIO_same_amode); + + *error_code = MPI_SUCCESS; +} + + + +/* This is the delete callback function associated with + ADIO_Init_keyval when MPI_COMM_SELF is freed */ + +int ADIOI_End_call(MPI_Comm comm, int keyval, void *attribute_val, void + *extra_state) +{ + int error_code; + + ADIOI_UNREFERENCED_ARG(comm); + ADIOI_UNREFERENCED_ARG(attribute_val); + ADIOI_UNREFERENCED_ARG(extra_state); + + MPI_Keyval_free(&keyval); + + /* The end call will be called after all possible uses of this keyval, even + * if a file was opened with MPI_COMM_SELF. Note, this assumes LIFO + * MPI_COMM_SELF attribute destruction behavior mandated by MPI-2.2. */ + if (ADIOI_cb_config_list_keyval != MPI_KEYVAL_INVALID) + MPI_Keyval_free(&ADIOI_cb_config_list_keyval); + + ADIO_End(&error_code); + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_fcntl.c b/ompi/mca/io/romio314/romio/adio/common/ad_fcntl.c new file mode 100644 index 0000000000..62067573dd --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_fcntl.c @@ -0,0 +1,64 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2005 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +void ADIOI_GEN_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code) +{ + static char myname[] = "ADIOI_GEN_FCNTL"; + + switch(flag) { + case ADIO_FCNTL_GET_FSIZE: +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + fcntl_struct->fsize = lseek(fd->fd_sys, 0, SEEK_END); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + if (fd->fp_sys_posn != -1) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + lseek(fd->fd_sys, fd->fp_sys_posn, SEEK_SET); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + } + if (fcntl_struct->fsize == -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; + break; + + case ADIO_FCNTL_SET_DISKSPACE: + ADIOI_GEN_Prealloc(fd, fcntl_struct->diskspace, error_code); + break; + + case ADIO_FCNTL_SET_ATOMICITY: + fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; + *error_code = MPI_SUCCESS; + break; + + /* --BEGIN ERROR HANDLING-- */ + default: + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**flag", "**flag %d", flag); + /* --END ERROR HANDLING-- */ + } +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_features.c b/ompi/mca/io/romio314/romio/adio/common/ad_features.c new file mode 100644 index 0000000000..480a42c6fe --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_features.c @@ -0,0 +1,26 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "adio.h" + +int ADIOI_GEN_Feature(ADIO_File fd, int flag) +{ + switch(flag) { + case ADIO_LOCKS: + case ADIO_SHARED_FP: + case ADIO_ATOMIC_MODE: + case ADIO_DATA_SIEVING_WRITES: + case ADIO_UNLINK_AFTER_CLOSE: + case ADIO_TWO_PHASE: + case ADIO_SCALABLE_RESIZE: + return 1; + break; + case ADIO_SCALABLE_OPEN: + default: + return 0; + break; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_flush.c b/ompi/mca/io/romio314/romio/adio/common/ad_flush.c new file mode 100644 index 0000000000..3ace6778bf --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_flush.c @@ -0,0 +1,35 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +void ADIOI_GEN_Flush(ADIO_File fd, int *error_code) +{ + int err; + static char myname[] = "ADIOI_GEN_FLUSH"; + + /* the deferred-open optimization may mean that a file has not been opened + * on this processor */ + if (fd->is_open > 0) { + err = fsync(fd->fd_sys); + /* --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-- */ + } + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_fstype.c b/ompi/mca/io/romio314/romio/adio/common/ad_fstype.c new file mode 100644 index 0000000000..c89b560e54 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_fstype.c @@ -0,0 +1,872 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* This file is quickly becoming the single one, outside the ADIO + * implementations, which has "what ADIO components are built in" code in it. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_PVFS_H +#include "pvfs.h" +#endif + +#ifdef HAVE_PVFS2_H +#include "pvfs2.h" +#endif + +#ifdef HAVE_ZOIDFS_H +#include "zoidfs.h" +#endif + +#ifdef HAVE_GPFS_H +#include "gpfs.h" +#endif + +/* Notes on detection process: + * + * There are three more "general" mechanisms that we use for detecting + * file system type: + * - struct statfs's f_type field + * - struct statvfs's f_basetype field + * - struct stat's st_fstype field + * + * Otherwise we'll fall back on some OS-specific approach. + */ + +#ifdef HAVE_STRUCT_STATFS +# ifdef HAVE_SYS_VFS_H +# include +# endif +# ifdef HAVE_SYS_STATVFS_H +# include +# endif +# ifdef HAVE_SYS_PARAM_H +# include +# endif +# ifdef HAVE_SYS_MOUNT_H +# include +# endif + /* On Linux platforms, linux/nfs_fs.h is all messed up and cannot be + * reliably included. + */ +# if defined(ROMIO_NFS) && !defined(NFS_SUPER_MAGIC) +# define NFS_SUPER_MAGIC 0x6969 +# endif + +# if defined(ROMIO_PANFS) && !defined(PAN_KERNEL_FS_CLIENT_SUPER_MAGIC) +# define PAN_KERNEL_FS_CLIENT_SUPER_MAGIC 0xAAD7AAEA +# endif +#endif + +# if defined(ROMIO_XFS) && !defined(XFS_SUPER_MAGIC) +# define XFS_SUPER_MAGIC 0x58465342 +# endif + +#if !defined(PVFS2_SUPER_MAGIC) +#define PVFS2_SUPER_MAGIC (0x20030528) +#endif + +#if defined(ROMIO_GPFS) && !defined(GPFS_SUPER_MAGIC) +# define GPFS_SUPER_MAGIC 0x47504653 +#endif + +#ifdef ROMIO_HAVE_STRUCT_STATVFS_WITH_F_BASETYPE +# ifdef HAVE_SYS_STATVFS_H +# include +# endif +# ifdef HAVE_SYS_VFS_H +# include +# endif +# ifdef HAVE_SYS_PARAM_H +# include +# endif +# ifdef HAVE_SYS_MOUNT_H +# include +# endif +#endif + +#ifdef ROMIO_HAVE_STRUCT_STAT_WITH_ST_FSTYPE +# ifdef HAVE_SYS_TYPES_H +# include +# endif +# ifdef HAVE_SYS_STAT_H +# include +# endif +#endif + +/* ADIO_FileSysType_parentdir is only used if one of these is defined. + By including this test, we avoid warnings about unused static functions + from the compiler */ +#if defined(ROMIO_HAVE_STRUCT_STATVFS_WITH_F_BASETYPE) || \ + defined(HAVE_STRUCT_STATFS) || \ + defined(ROMIO_HAVE_STRUCT_STAT_WITH_ST_FSTYPE) +#ifndef ROMIO_NTFS +#define ROMIO_NEEDS_ADIOPARENTDIR +static void ADIO_FileSysType_parentdir(const char *filename, char **dirnamep); +#endif +#endif +static void ADIO_FileSysType_prefix(const char *filename, int *fstype, + int *error_code); +static void ADIO_FileSysType_fncall(const char *filename, int *fstype, + int *error_code); + +/* + ADIO_FileSysType_parentdir - determines a string pathname for the + parent directory of a given filename. + +Input Parameters: +. filename - pointer to file name character array + +Output Parameters: +. dirnamep - pointer to location in which to store a pointer to a string + + Note that the caller should free the memory located at the pointer returned + after the string is no longer needed. +*/ +#ifdef ROMIO_NEEDS_ADIOPARENTDIR + +/* In a strict ANSI environment, S_ISLNK may not be defined. Fix that + here. We assume that S_ISLNK is *always* defined as a macro. If + that is not universally true, then add a test to the romio + configure that trys to link a program that references S_ISLNK */ +#if !defined(S_ISLNK) +# if defined(S_IFLNK) + /* Check for the link bit */ +# define S_ISLNK(mode) ((mode) & S_IFLNK) +# else + /* no way to check if it is a link, so say false */ +# define S_ISLNK(mode) 0 +# endif +#endif /* !(S_ISLNK) */ + +/* ADIO_FileSysType_parentdir + * + * Returns pointer to string in dirnamep; that string is allocated with + * strdup and must be free()'d. + */ +static void ADIO_FileSysType_parentdir(const char *filename, char **dirnamep) +{ + int err; + char *dir = NULL, *slash; + struct stat statbuf; + + err = lstat(filename, &statbuf); + + if (err || (!S_ISLNK(statbuf.st_mode))) { + /* no such file, or file is not a link; these are the "normal" + * cases where we can just return the parent directory. + */ + dir = ADIOI_Strdup(filename); + } + else { + /* filename is a symlink. we've presumably already tried + * to stat it and found it to be missing (dangling link), + * but this code doesn't care if the target is really there + * or not. + */ + ssize_t namelen; + char *linkbuf; + + linkbuf = ADIOI_Malloc(PATH_MAX+1); + namelen = readlink(filename, linkbuf, PATH_MAX+1); + if (namelen == -1) { + /* something strange has happened between the time that + * we determined that this was a link and the time that + * we attempted to read it; punt and use the old name. + */ + dir = ADIOI_Strdup(filename); + } + else { + /* successfully read the link */ + linkbuf[namelen] = '\0'; /* readlink doesn't null terminate */ + dir = ADIOI_Strdup(linkbuf); + ADIOI_Free(linkbuf); + } + } + + slash = strrchr(dir, '/'); + if (!slash) ADIOI_Strncpy(dir, ".", 2); + else { + if (slash == dir) *(dir + 1) = '\0'; + else *slash = '\0'; + } + + *dirnamep = dir; + return; +} +#endif /* ROMIO_NTFS */ + +/* + ADIO_FileSysType_fncall - determines the file system type for a given file + using a system-dependent function call + +Input Parameters: +. filename - pointer to file name character array + +Output Parameters: +. fstype - location in which to store file system type (ADIO_XXX) +. error_code - location in which to store error code + + MPI_SUCCESS is stored in the location pointed to by error_code on success. + + This function is used by MPI_File_open() and MPI_File_delete() to determine + file system type. Most other functions use the type which is stored when the + file is opened. + */ +static void ADIO_FileSysType_fncall(const char *filename, int *fstype, int *error_code) +{ +#if defined (ROMIO_HAVE_STRUCT_STATVFS_WITH_F_BASETYPE) || defined (HAVE_STRUCT_STATFS) || defined (ROMIO_HAVE_STRUCT_STAT_WITH_ST_FSTYPE) + int err; +#endif + +#ifdef ROMIO_HAVE_STRUCT_STATVFS_WITH_F_BASETYPE + struct statvfs vfsbuf; +#endif +#ifdef HAVE_STRUCT_STATFS + struct statfs fsbuf; +#endif +#ifdef ROMIO_HAVE_STRUCT_STAT_WITH_ST_FSTYPE + struct stat sbuf; +#endif + static char myname[] = "ADIO_RESOLVEFILETYPE_FNCALL"; + +/* NFS can get stuck and end up returing ESTALE "forever" */ +#define MAX_ESTALE_RETRY 10000 + int retry_cnt; + + *error_code = MPI_SUCCESS; + +#ifdef ROMIO_HAVE_STRUCT_STATVFS_WITH_F_BASETYPE + /* rare: old solaris machines */ + retry_cnt=0; + do { + err = statvfs(filename, &vfsbuf); + } while (err && (errno == ESTALE) && retry_cnt++ < MAX_ESTALE_RETRY); + + if (err) { + /* ENOENT may be returned in two cases: + * 1) no directory entry for "filename" + * 2) "filename" is a dangling symbolic link + * + * ADIO_FileSysType_parentdir tries to deal with both cases. + */ + if (errno == ENOENT) { + char *dir; + ADIO_FileSysType_parentdir(filename, &dir); + err = statvfs(dir, &vfsbuf); + + ADIOI_Free(dir); + } + else { + *error_code = ADIOI_Err_create_code(myname, filename, errno); + if(*error_code != MPI_SUCCESS) return; + } + } + + /* --BEGIN ERROR HANDLING-- */ + if (err) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_NO_SUCH_FILE, + "**filename", "**filename %s", filename); + return; + } + /* --END ERROR HANDLING-- */ + + /* FPRINTF(stderr, "%s\n", vfsbuf.f_basetype); */ + if (!strncmp(vfsbuf.f_basetype, "nfs", 3)) { + *fstype = ADIO_NFS; + return; + } + if (!strncmp(vfsbuf.f_basetype, "xfs", 3)) { + *fstype = ADIO_XFS; + return; + } + +# ifdef ROMIO_UFS + /* if UFS support is enabled, default to that */ + *fstype = ADIO_UFS; + return; +# endif + + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_NO_SUCH_FILE, + "**filename", "**filename %s", filename); + /* --END ERROR HANDLING-- */ +#endif /* STATVFS APPROACH */ + +#if defined(HAVE_STRUCT_STATFS) && defined(HAVE_STATFS) + /* common automagic fs-detection logic for any modern POSX-compliant + * environment */ + retry_cnt = 0; + do { + err = statfs(filename, &fsbuf); + } while (err && (errno == ESTALE) && retry_cnt++ < MAX_ESTALE_RETRY); + + if (err) { + if(errno == ENOENT) { + char *dir; + ADIO_FileSysType_parentdir(filename, &dir); + err = statfs(dir, &fsbuf); + ADIOI_Free(dir); + } + else { + *error_code = ADIOI_Err_create_code(myname, filename, errno); + if(*error_code != MPI_SUCCESS) return; + } + } + + /* --BEGIN ERROR HANDLING-- */ + if (err) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_NO_SUCH_FILE, + "**filename", "**filename %s", filename); + return; + } + /* --END ERROR HANDLING-- */ + +# ifdef ROMIO_HAVE_STRUCT_STATFS_WITH_F_FSTYPENAME + /* uncommon: maybe only on Darwin ? */ + if ( !strncmp("nfs",fsbuf.f_fstypename,3) ) { + *fstype = ADIO_NFS; + return; + } +# endif + + +#ifdef ROMIO_GPFS + if (fsbuf.f_type == GPFS_SUPER_MAGIC) { + *fstype = ADIO_GPFS; + return; + } +#endif + + /* FPRINTF(stderr, "%d\n", fsbuf.f_type);*/ +# ifdef NFS_SUPER_MAGIC + if (fsbuf.f_type == NFS_SUPER_MAGIC) { + *fstype = ADIO_NFS; + return; + } +# endif + +#ifdef ROMIO_LUSTRE +# ifndef LL_SUPER_MAGIC +# define LL_SUPER_MAGIC 0x0BD00BD0 +# endif + if (fsbuf.f_type == LL_SUPER_MAGIC) { + *fstype = ADIO_LUSTRE; + return; + } +#endif + +# ifdef PAN_KERNEL_FS_CLIENT_SUPER_MAGIC + if (fsbuf.f_type == PAN_KERNEL_FS_CLIENT_SUPER_MAGIC) { + *fstype = ADIO_PANFS; + return; + } +# endif + +# ifdef MOUNT_NFS + if (fsbuf.f_type == MOUNT_NFS) { + *fstype = ADIO_NFS; + return; + } +# endif + +# ifdef MOUNT_PFS + if (fsbuf.f_type == MOUNT_PFS) { + *fstype = ADIO_PFS; + return; + } +# endif + +# ifdef PVFS_SUPER_MAGIC + if (fsbuf.f_type == PVFS_SUPER_MAGIC) { + *fstype = ADIO_PVFS; + return; + } +# endif + +# ifdef PVFS2_SUPER_MAGIC + if (fsbuf.f_type == PVFS2_SUPER_MAGIC) { + *fstype = ADIO_PVFS2; + return; + } +# endif + +# ifdef XFS_SUPER_MAGIC + if (fsbuf.f_type == XFS_SUPER_MAGIC) { + *fstype = ADIO_XFS; + return; + } +# endif + +# ifdef ROMIO_UFS + /* if UFS support is enabled, default to that */ + *fstype = ADIO_UFS; + return; +# endif + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_NO_SUCH_FILE, + "**filename", "**filename %s", filename); + /* --END ERROR HANDLING-- */ +#endif /* STATFS APPROACH */ + +#ifdef ROMIO_HAVE_STRUCT_STAT_WITH_ST_FSTYPE + /* rare: maybe old NEC SX or SGI IRIX machines */ + retry_cnt = 0; + do { + err = stat(filename, &sbuf); + } while (err && (errno == ESTALE) && retry_cnt++ < MAX_ESTALE_RETRY); + + if (err) { + if(errno == ENOENT) { + char *dir; + ADIO_FileSysType_parentdir(filename, &dir); + err = stat(dir, &sbuf); + ADIOI_Free(dir); + } + else{ + *error_code = ADIOI_Err_create_code(myname, filename, errno); + if(*error_code != MPI_SUCCESS) return; + } + } + + if (err) { + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_NO_SUCH_FILE, + "**filename", "**filename %s", filename); + /* --END ERROR HANDLING-- */ + return; + } + else { + if (!strcmp(sbuf.st_fstype, "nfs")) *fstype = ADIO_NFS; + else *fstype = ADIO_SFS; /* assuming SX4 for now */ + } +#endif /* STAT APPROACH */ + +#ifdef ROMIO_NTFS + ADIOI_UNREFERENCED_ARG(filename); + ADIOI_UNREFERENCED_ARG(error_code); + *fstype = ADIO_NTFS; /* only supported FS on Windows */ +#elif defined(ROMIO_NFS) + *fstype = ADIO_NFS; +#elif defined(ROMIO_UFS) + *fstype = ADIO_UFS; +#else + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_NO_SUCH_FILE, + "**filename", "**filename %s", filename); + /* --END ERROR HANDLING-- */ +#endif +} + +/* all proceeses opening, creating, or deleting a file end up invoking several + * stat system calls (unless a fs prefix is given). Cary out this file system + * detection in a more scalable way by having rank 0 stat the file and broadcast the result (fs type and error code) to the other mpi processes */ + +static void ADIO_FileSysType_fncall_scalable(MPI_Comm comm, const char *filename, int * file_system, int * error_code) +{ + int rank; + int buf[2]; + MPI_Comm_rank(comm, &rank); + + if (rank == 0) { + ADIO_FileSysType_fncall(filename, file_system, error_code); + buf[0] = *file_system; + buf[1] = *error_code; + } + MPI_Bcast(buf, 2, MPI_INT, 0, comm); + *file_system = buf[0]; + *error_code = buf[1]; +} + + + +/* + ADIO_FileSysType_prefix - determines file system type for a file using + a prefix on the file name. upper layer should have already determined + that a prefix is present. + +Input Parameters: +. filename - path to file, including prefix (xxx:) + +Output Parameters: +. fstype - pointer to integer in which to store file system type (ADIO_XXX) +. error_code - pointer to integer in which to store error code + + Returns MPI_SUCCESS in error_code on success. Filename not having a prefix + is considered an error. Except for on Windows systems where the default is NTFS. + + */ +static void ADIO_FileSysType_prefix(const char *filename, int *fstype, int *error_code) +{ + static char myname[] = "ADIO_RESOLVEFILETYPE_PREFIX"; + *error_code = MPI_SUCCESS; + + if (!strncmp(filename, "pfs:", 4) || !strncmp(filename, "PFS:", 4)) { + *fstype = ADIO_PFS; + } + else if (!strncmp(filename, "piofs:", 6) || !strncmp(filename, "PIOFS:", 6)) { + *fstype = ADIO_PIOFS; + } + else if (!strncmp(filename, "ufs:", 4) || !strncmp(filename, "UFS:", 4)) { + *fstype = ADIO_UFS; + } + else if (!strncmp(filename, "nfs:", 4) || !strncmp(filename, "NFS:", 4)) { + *fstype = ADIO_NFS; + } + else if (!strncmp(filename, "panfs:", 6) || !strncmp(filename, "PANFS:", 6)) { + *fstype = ADIO_PANFS; + } + else if (!strncmp(filename, "hfs:", 4) || !strncmp(filename, "HFS:", 4)) { + *fstype = ADIO_HFS; + } + else if (!strncmp(filename, "xfs:", 4) || !strncmp(filename, "XFS:", 4)) { + *fstype = ADIO_XFS; + } + else if (!strncmp(filename, "sfs:", 4) || !strncmp(filename, "SFS:", 4)) { + *fstype = ADIO_SFS; + } + else if (!strncmp(filename, "pvfs:", 5) || !strncmp(filename, "PVFS:", 5)) { + *fstype = ADIO_PVFS; + } + else if (!strncmp(filename, "pvfs2:", 6)||!strncmp(filename, "PVFS2:", 6)) { + *fstype = ADIO_PVFS2; + } + else if (!strncmp(filename, "zoidfs:", 7)|| + !strncmp(filename, "ZOIDFS:", 7)) { + *fstype = ADIO_ZOIDFS; + } + else if (!strncmp(filename, "testfs:", 7) + || !strncmp(filename, "TESTFS:", 7)) + { + *fstype = ADIO_TESTFS; + } + else if (!strncmp(filename, "ftp:", 4) + || !strncmp(filename, "gsiftp:", 7)) + { + *fstype = ADIO_GRIDFTP; + } + else if (!strncmp(filename, "lustre:", 7) + || !strncmp(filename, "LUSTRE:", 7)) + { + *fstype = ADIO_LUSTRE; + } + else if (!strncmp(filename, "gpfs:", 5) || !strncmp(filename, "GPFS:", 5)) { + *fstype = ADIO_GPFS; + } + else { +#ifdef ROMIO_NTFS + *fstype = ADIO_NTFS; +#else + *fstype = 0; + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_NO_SUCH_FILE, + "**filename", "**filename %s", filename); + /* --END ERROR HANDLING-- */ +#endif + } +} + +/*@ + ADIO_ResolveFileType - determines file system type and operations from + file name string; this is a collective call + +Input Parameters: +. comm - communicator across which collective open is performed +. filename - name of file (string) + +Output Parameters: +. fstype - (pointer to) int holding file system type +. ops - (address of) pointer to table of valid file operations +. error_code - (pointer to) int holding error code + +Notes: +This code used to be in MPI_File_open(), but it has been moved into here in +order to clean things up. The goal is to separate all this "did we compile +for this fs type" code from the MPI layer and also to introduce the ADIOI_Fns +tables in a reasonable way. -- Rob, 06/06/2001 +@*/ +void ADIO_ResolveFileType(MPI_Comm comm, const char *filename, int *fstype, + ADIOI_Fns **ops, int *error_code) +{ + int myerrcode, file_system, min_code, max_code; + char *tmp; + static char myname[] = "ADIO_RESOLVEFILETYPE"; + char * p; + + file_system = -1; + if (filename == NULL) { + *error_code = ADIOI_Err_create_code(myname, filename, ENOENT); + return; + } + tmp = strchr(filename, ':'); + if (!tmp) { + int have_nfs_enabled=0; + *error_code = MPI_SUCCESS; + /* no prefix; use system-dependent function call to determine type */ + /* Optimization: we can reduce the 'storm of stats' that result from + * thousands of mpi processes determinig file type this way. Let us + * have just one process stat the file and broadcast the result to + * everyone else. + * - Note that we will not catch cases like + * http://www.mcs.anl.gov/web-mail-archive/lists/mpich-discuss/2007/08/msg00042.html + * (edit: now http://lists.mcs.anl.gov/pipermail/mpich-discuss/2007-August/002648.html) + * + * where file systems are not mounted or available on other processes, + * but we'll catch those a few functions later in ADIO_Open + * - Note that if we have NFS enabled, we might have a situation where, + * for example, /home/user/data.out is UFS on one process but NFS on + * others, so we won't perform this optimization if NFS is enabled. + * - Another point: error codes and file system types are broadcast to + * all members of the communicator, so we get to skip the allreduce + * steps*/ + +#ifdef ROMIO_NFS + have_nfs_enabled=1; +#endif + if (!have_nfs_enabled) { + ADIO_FileSysType_fncall_scalable(comm, filename, &file_system, &myerrcode); + if (myerrcode != MPI_SUCCESS) { + *error_code = myerrcode; + return; + } + } else { + ADIO_FileSysType_fncall(filename, &file_system, &myerrcode); + + /* the check for file system type will hang if any process got + * an error in ADIO_FileSysType_fncall. Processes encountering + * an error will return early, before the collective file + * system type check below. This case could happen if a full + * path exists on one node but not on others, and no prefix + * like ufs: was provided. see discussion at + * http://www.mcs.anl.gov/web-mail-archive/lists/mpich-discuss/2007/08/msg00042.html + * (edit: now + * http://lists.mcs.anl.gov/pipermail/mpich-discuss/2007-August/002648.html) + */ + + MPI_Allreduce(&myerrcode, &max_code, 1, MPI_INT, MPI_MAX, comm); + if (max_code != MPI_SUCCESS) { + *error_code = max_code; + return; + } + /* ensure everyone came up with the same file system type */ + MPI_Allreduce(&file_system, &min_code, 1, MPI_INT, + MPI_MIN, comm); + if (min_code == ADIO_NFS) file_system = ADIO_NFS; + } + } + else { + /* prefix specified; just match via prefix and assume everyone got + * the same thing. + * + * perhaps we should have this code go through the allreduce as well? + */ + ADIO_FileSysType_prefix(filename, &file_system, &myerrcode); + if (myerrcode != MPI_SUCCESS) { + *error_code = myerrcode; + return; + } + } + + /* lastly, there may be situations where one cannot override the file + * system detection with a prefix -- maybe the file name is passed to both + * posix and MPI-IO routines, or maybe the file name is hard-coded into an + * application. + * Assumes all processes set the same environment varialble. + * Values: the same prefix you would stick on a file path. e.g. pvfs2: -- + * including the colon! */ + p = getenv("ROMIO_FSTYPE_FORCE"); + if (p != NULL) { + ADIO_FileSysType_prefix(p, &file_system, &myerrcode); + if (myerrcode != MPI_SUCCESS) { + *error_code = myerrcode; + return; + } + } + + /* verify that we support this file system type and set ops pointer */ + if (file_system == ADIO_PFS) { +#ifndef ROMIO_PFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_PFS_operations; +#endif + } + if (file_system == ADIO_PIOFS) { +#ifndef ROMIO_PIOFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_PIOFS_operations; +#endif + } + if (file_system == ADIO_UFS) { +#ifndef ROMIO_UFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_UFS_operations; +#endif + } + if (file_system == ADIO_NFS) { +#ifndef ROMIO_NFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_NFS_operations; +#endif + } + if (file_system == ADIO_PANFS) { +#ifndef ROMIO_PANFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_PANFS_operations; +#endif + } + if (file_system == ADIO_HFS) { +#ifndef ROMIO_HFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_HFS_operations; +#endif + } + if (file_system == ADIO_XFS) { +#ifndef ROMIO_XFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_XFS_operations; +#endif + } + if (file_system == ADIO_SFS) { +#ifndef ROMIO_SFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_SFS_operations; +#endif + } + if (file_system == ADIO_PVFS) { +#ifndef ROMIO_PVFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_PVFS_operations; +#endif + } + if (file_system == ADIO_PVFS2) { +#ifndef ROMIO_PVFS2 + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_PVFS2_operations; +#endif + } + if (file_system == ADIO_NTFS) { +#ifndef ROMIO_NTFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_NTFS_operations; +#endif + } + if (file_system == ADIO_TESTFS) { +#ifndef ROMIO_TESTFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_TESTFS_operations; +#endif + } + + if (file_system == ADIO_GPFS) { +#ifndef ROMIO_GPFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_GPFS_operations; +#endif + } + + if (file_system == ADIO_GRIDFTP) { +#ifndef ROMIO_GRIDFTP + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_GRIDFTP_operations; +#endif + } + if (file_system == ADIO_LUSTRE) { +#ifndef ROMIO_LUSTRE + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, MPI_ERR_IO, "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_LUSTRE_operations; +#endif + } + if (file_system == ADIO_ZOIDFS) { +#ifndef ROMIO_ZOIDFS + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iofstypeunsupported", 0); + return; +#else + *ops = &ADIO_ZOIDFS_operations; +#endif + } + *error_code = MPI_SUCCESS; + *fstype = file_system; + return; +} +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_get_sh_fp.c b/ompi/mca/io/romio314/romio/adio/common/ad_get_sh_fp.c new file mode 100644 index 0000000000..1213327790 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_get_sh_fp.c @@ -0,0 +1,74 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +/* returns the current location of the shared_fp in terms of the + no. of etypes relative to the current view, and also increments the + shared_fp by the number of etypes to be accessed (incr) in the read + or write following this function. */ + +void ADIOI_NFS_Get_shared_fp(ADIO_File fd, ADIO_Offset incr, ADIO_Offset *shared_fp, + int *error_code); + +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)); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_hints.c b/ompi/mca/io/romio314/romio/adio/common/ad_hints.c new file mode 100644 index 0000000000..1bc74f1a55 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_hints.c @@ -0,0 +1,309 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "hint_fns.h" + +void ADIOI_GEN_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code) +{ +/* if fd->info is null, create a new info object. + Initialize fd->info to default values. + Initialize fd->hints to default values. + Examine the info object passed by the user. If it contains values that + ROMIO understands, override the default. */ + + MPI_Info info; + char *value; + int flag, nprocs=0, len; + int ok_to_override_cb_nodes=0; + static char myname[] = "ADIOI_GEN_SETINFO"; + + + /* if we've already set up default hints and the user has not asked us to + * process any hints (MPI_INFO_NULL), then we can short-circuit hint + * processing */ + if (fd->hints->initialized && fd->info == MPI_INFO_NULL) { + *error_code = MPI_SUCCESS; + return; + } + + if (fd->info == MPI_INFO_NULL) MPI_Info_create(&(fd->info)); + info = fd->info; + + MPI_Comm_size(fd->comm, &nprocs); + + /* Note that fd->hints is allocated at file open time; thus it is + * not necessary to allocate it, or check for allocation, here. + */ + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + if (value == NULL) { + *error_code = MPIO_Err_create_code(*error_code, + MPIR_ERR_RECOVERABLE, + myname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + return; + } + + /* initialize info and hints to default values if they haven't been + * previously initialized + */ + if (!fd->hints->initialized) { + + /* buffer size for collective I/O */ + ADIOI_Info_set(info, "cb_buffer_size", ADIOI_CB_BUFFER_SIZE_DFLT); + fd->hints->cb_buffer_size = atoi(ADIOI_CB_BUFFER_SIZE_DFLT); + + /* default is to let romio automatically decide when to use + * collective buffering + */ + ADIOI_Info_set(info, "romio_cb_read", "automatic"); + fd->hints->cb_read = ADIOI_HINT_AUTO; + ADIOI_Info_set(info, "romio_cb_write", "automatic"); + fd->hints->cb_write = ADIOI_HINT_AUTO; + + fd->hints->cb_config_list = NULL; + + /* number of processes that perform I/O in collective I/O */ + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", nprocs); + ADIOI_Info_set(info, "cb_nodes", value); + fd->hints->cb_nodes = nprocs; + + /* hint indicating that no indep. I/O will be performed on this file */ + ADIOI_Info_set(info, "romio_no_indep_rw", "false"); + fd->hints->no_indep_rw = 0; + + /* hint instructing the use of persistent file realms */ + ADIOI_Info_set(info, "romio_cb_pfr", "disable"); + fd->hints->cb_pfr = ADIOI_HINT_DISABLE; + + /* hint guiding the assignment of persistent file realms */ + ADIOI_Info_set(info, "romio_cb_fr_types", "aar"); + fd->hints->cb_fr_type = ADIOI_FR_AAR; + + /* hint to align file realms with a certain byte value */ + ADIOI_Info_set(info, "romio_cb_fr_alignment", "1"); + fd->hints->cb_fr_alignment = 1; + + /* hint to set a threshold percentage for a datatype's size/extent at + * which data sieving should be done in collective I/O */ + ADIOI_Info_set(info, "romio_cb_ds_threshold", "0"); + fd->hints->cb_ds_threshold = 0; + + /* hint to switch between point-to-point or all-to-all for two-phase */ + ADIOI_Info_set(info, "romio_cb_alltoall", "automatic"); + fd->hints->cb_alltoall = ADIOI_HINT_AUTO; + + /* deferred_open derived from no_indep_rw and cb_{read,write} */ + fd->hints->deferred_open = 0; + + /* buffer size for data sieving in independent reads */ + ADIOI_Info_set(info, "ind_rd_buffer_size", ADIOI_IND_RD_BUFFER_SIZE_DFLT); + fd->hints->ind_rd_buffer_size = atoi(ADIOI_IND_RD_BUFFER_SIZE_DFLT); + + /* buffer size for data sieving in independent writes */ + ADIOI_Info_set(info, "ind_wr_buffer_size", ADIOI_IND_WR_BUFFER_SIZE_DFLT); + fd->hints->ind_wr_buffer_size = atoi(ADIOI_IND_WR_BUFFER_SIZE_DFLT); + + /* default is to let romio automatically decide when to use data + * sieving + */ + ADIOI_Info_set(info, "romio_ds_read", "automatic"); + fd->hints->ds_read = ADIOI_HINT_AUTO; + ADIOI_Info_set(info, "romio_ds_write", "automatic"); + fd->hints->ds_write = ADIOI_HINT_AUTO; + + /* still to do: tune this a bit for a variety of file systems. there's + * no good default value so just leave it unset */ + fd->hints->min_fdomain_size = 0; + fd->hints->striping_unit = 0; + + fd->hints->initialized = 1; + + /* ADIO_Open sets up collective buffering arrays. If we are in this + * path from say set_file_view, then we've don't want to adjust the + * array: we'll get a segfault during collective i/o. We only want to + * look at the users cb_nodes if it's open time */ + ok_to_override_cb_nodes = 1; + + } + + /* add in user's info if supplied */ + if (users_info != MPI_INFO_NULL) { + ADIOI_Info_check_and_install_int(fd, users_info, "cb_buffer_size", + &(fd->hints->cb_buffer_size), myname, error_code); + + /* aligning file realms to certain sizes (e.g. stripe sizes) + * may benefit I/O performance */ + ADIOI_Info_check_and_install_int(fd, users_info, "romio_cb_fr_alignment", + &(fd->hints->cb_fr_alignment), myname, error_code); + + /* for collective I/O, try to be smarter about when to do data sieving + * using a specific threshold for the datatype size/extent + * (percentage 0-100%) */ + ADIOI_Info_check_and_install_int(fd, users_info, "romio_cb_ds_threshold", + &(fd->hints->cb_ds_threshold), myname, error_code); + + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_alltoall", + &(fd->hints->cb_alltoall), myname, error_code); + + /* new hints for enabling/disabling coll. buffering on + * reads/writes + */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_read", + &(fd->hints->cb_read), myname, error_code); + if (fd->hints->cb_read == ADIOI_HINT_DISABLE) { + /* romio_cb_read overrides no_indep_rw */ + ADIOI_Info_set(info, "romio_no_indep_rw", "false"); + fd->hints->no_indep_rw = ADIOI_HINT_DISABLE; + } + + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_write", + &(fd->hints->cb_write), myname, error_code); + if (fd->hints->cb_write == ADIOI_HINT_DISABLE) { + /* romio_cb_write overrides no_indep_rw */ + ADIOI_Info_set(info, "romio_no_indep_rw", "false"); + fd->hints->no_indep_rw = ADIOI_HINT_DISABLE; + } + + /* enable/disable persistent file realms for collective I/O */ + /* may want to check for no_indep_rdwr hint as well */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_pfr", + &(fd->hints->cb_pfr), myname, error_code); + + + /* file realm assignment types ADIOI_FR_AAR(0), + ADIOI_FR_FSZ(-1), ADIOI_FR_USR_REALMS(-2), all others specify + a regular fr size in bytes. probably not the best way... */ + ADIOI_Info_check_and_install_int(fd, users_info, "romio_cb_fr_type", + &(fd->hints->cb_fr_type), myname, error_code); + + /* Has the user indicated all I/O will be done collectively? */ + ADIOI_Info_check_and_install_true(fd, users_info, "romio_no_indep_rw", + &(fd->hints->no_indep_rw), myname, error_code); + if (fd->hints->no_indep_rw == 1) { + /* if 'no_indep_rw' set, also hint that we will do + * collective buffering: if we aren't doing independent io, + * then we have to do collective */ + ADIOI_Info_set(info, "romio_cb_write", "enable"); + ADIOI_Info_set(info, "romio_cb_read", "enable"); + fd->hints->cb_read = 1; + fd->hints->cb_write = 1; + } + /* new hints for enabling/disabling data sieving on + * reads/writes + */ + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_ds_read", + &(fd->hints->ds_read), myname, error_code); + ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_ds_write", + &(fd->hints->ds_write), myname, error_code); + + if (ok_to_override_cb_nodes) { + /* MPI_File_open path sets up some data structrues that don't + * get resized in the MPI_File_set_view path, so ignore + * cb_nodes in the set_view case */ + ADIOI_Info_check_and_install_int(fd, users_info, "cb_nodes", + &(fd->hints->cb_nodes), myname, error_code); + if ((fd->hints->cb_nodes <= 0) || (fd->hints->cb_nodes > nprocs)) { + /* can't ask for more aggregators than mpi processes, though it + * might be interesting to think what such oversubscription + * might mean... someday */ + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", nprocs); + ADIOI_Info_set(info, "cb_nodes", value); + fd->hints->cb_nodes = nprocs; + } + } /* if (ok_to_override_cb_nodes) */ + + ADIOI_Info_check_and_install_int(fd, users_info, "ind_wr_buffer_size", + &(fd->hints->ind_wr_buffer_size), myname, error_code); + ADIOI_Info_check_and_install_int(fd, users_info, "ind_rd_buffer_size", + &(fd->hints->ind_rd_buffer_size), myname, error_code); + + if (fd->hints->cb_config_list == NULL) { + /* only set cb_config_list if it isn't already set. Note that + * since we set it below, this ensures that the cb_config_list hint + * will be set at file open time either by the user or to the + * default */ + /* if it has been set already, we ignore it the second time. + * otherwise we would get an error if someone used the same info + * value with a cb_config_list value in it in a couple of calls, + * which would be irritating. */ + ADIOI_Info_check_and_install_str(fd, users_info, "cb_config_list", + &(fd->hints->cb_config_list), myname, error_code); + + } + ADIOI_Info_check_and_install_int(fd, users_info, "romio_min_fdomain_size", + &(fd->hints->min_fdomain_size), myname, error_code); + + /* Now we use striping unit in common code so we should + process hints for it. */ + ADIOI_Info_check_and_install_int(fd, users_info, "striping_unit", + &(fd->hints->striping_unit), myname, error_code); + } + + /* Begin hint post-processig: some hints take precidence over or conflict + * with others, or aren't supported by some file systems */ + + /* handle cb_config_list default value here; avoids an extra + * free/alloc and insures it is always set + */ + if (fd->hints->cb_config_list == NULL) { + ADIOI_Info_set(info, "cb_config_list", ADIOI_CB_CONFIG_LIST_DFLT); + len = (strlen(ADIOI_CB_CONFIG_LIST_DFLT)+1) * sizeof(char); + fd->hints->cb_config_list = ADIOI_Malloc(len); + if (fd->hints->cb_config_list == NULL) { + *error_code = MPIO_Err_create_code(*error_code, + MPIR_ERR_RECOVERABLE, + myname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + return; + } + ADIOI_Strncpy(fd->hints->cb_config_list, ADIOI_CB_CONFIG_LIST_DFLT, len); + } + /* deferred_open won't be set by callers, but if the user doesn't + * explicitly disable collecitve buffering (two-phase) and does hint that + * io w/o independent io is going on, we'll set this internal hint as a + * convenience */ + if ( ( (fd->hints->cb_read != ADIOI_HINT_DISABLE) \ + && (fd->hints->cb_write != ADIOI_HINT_DISABLE)\ + && fd->hints->no_indep_rw ) ) { + fd->hints->deferred_open = 1; + } else { + /* setting romio_no_indep_rw enable and romio_cb_{read,write} + * disable at the same time doesn't make sense. honor + * romio_cb_{read,write} and force the no_indep_rw hint to + * 'disable' */ + ADIOI_Info_set(info, "romio_no_indep_rw", "false"); + fd->hints->no_indep_rw = 0; + fd->hints->deferred_open = 0; + } + + if (ADIO_Feature(fd, ADIO_DATA_SIEVING_WRITES) == 0) { + /* disable data sieving for fs that do not + support file locking */ + ADIOI_Info_get(info, "ind_wr_buffer_size", MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + /* get rid of this value if it is set */ + ADIOI_Info_delete(info, "ind_wr_buffer_size"); + } + /* note: leave ind_wr_buffer_size alone; used for other cases + * as well. -- Rob Ross, 04/22/2003 + */ + ADIOI_Info_set(info, "romio_ds_write", "disable"); + fd->hints->ds_write = ADIOI_HINT_DISABLE; + } + + ADIOI_Free(value); + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_init.c b/ompi/mca/io/romio314/romio/adio/common/ad_init.c new file mode 100644 index 0000000000..88e75a5251 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_init.c @@ -0,0 +1,134 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +ADIOI_Flatlist_node *ADIOI_Flatlist = NULL; +ADIOI_Datarep *ADIOI_Datarep_head = NULL; + /* list of datareps registered by the user */ + +/* for f2c and c2f conversion */ +ADIO_File *ADIOI_Ftable = NULL; +int ADIOI_Ftable_ptr = 0, ADIOI_Ftable_max = 0; +ADIO_Request *ADIOI_Reqtable = NULL; +int ADIOI_Reqtable_ptr = 0, ADIOI_Reqtable_max = 0; +#ifndef HAVE_MPI_INFO +MPI_Info *MPIR_Infotable = NULL; +int MPIR_Infotable_ptr = 0, MPIR_Infotable_max = 0; +#endif + +MPI_Info ADIOI_syshints = MPI_INFO_NULL; + +MPI_Op ADIO_same_amode=MPI_OP_NULL; + +#if defined(ROMIO_XFS) || defined(ROMIO_LUSTRE) +int ADIOI_Direct_read = 0, ADIOI_Direct_write = 0; +#endif + +int ADIO_Init_keyval=MPI_KEYVAL_INVALID; + +MPI_Errhandler ADIOI_DFLT_ERR_HANDLER = MPI_ERRORS_RETURN; + + +static void my_consensus(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype) +{ + int i, *in, *inout; + in = (int*)invec; + inout = (int*)inoutvec; + + for (i=0; i< *len; i++) { + if (in[i] != inout[i]) + inout[i] = ADIO_AMODE_NOMATCH; + } + return; +} + +void ADIO_Init(int *argc, char ***argv, int *error_code) +{ +#if defined(ROMIO_XFS) || defined(ROMIO_LUSTRE) + char *c; +#endif + + ADIOI_UNREFERENCED_ARG(argc); + ADIOI_UNREFERENCED_ARG(argv); + +#ifdef ROMIO_INSIDE_MPICH + MPIR_Ext_init(); +#endif + +/* initialize the linked list containing flattened datatypes */ + ADIOI_Flatlist = (ADIOI_Flatlist_node *) ADIOI_Malloc(sizeof(ADIOI_Flatlist_node)); + ADIOI_Flatlist->type = MPI_DATATYPE_NULL; + ADIOI_Flatlist->next = NULL; + ADIOI_Flatlist->blocklens = NULL; + ADIOI_Flatlist->indices = NULL; + +#if defined(ROMIO_XFS) || defined(ROMIO_LUSTRE) + c = getenv("MPIO_DIRECT_READ"); + if (c && (!strcmp(c, "true") || !strcmp(c, "TRUE"))) + ADIOI_Direct_read = 1; + else ADIOI_Direct_read = 0; + c = getenv("MPIO_DIRECT_WRITE"); + if (c && (!strcmp(c, "true") || !strcmp(c, "TRUE"))) + ADIOI_Direct_write = 1; + else ADIOI_Direct_write = 0; +#endif + + +#ifdef ADIOI_MPE_LOGGING + { + MPE_Log_get_state_eventIDs( &ADIOI_MPE_open_a, &ADIOI_MPE_open_b ); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_read_a, &ADIOI_MPE_read_b ); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_write_a, &ADIOI_MPE_write_b ); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_lseek_a, &ADIOI_MPE_lseek_b ); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_close_a, &ADIOI_MPE_close_b ); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_writelock_a, + &ADIOI_MPE_writelock_b ); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_readlock_a, + &ADIOI_MPE_readlock_b ); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_unlock_a, &ADIOI_MPE_unlock_b ); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_postwrite_a, + &ADIOI_MPE_postwrite_b ); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_openinternal_a, + &ADIOI_MPE_openinternal_b); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_stat_a, &ADIOI_MPE_stat_b); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_iread_a, &ADIOI_MPE_iread_b); + MPE_Log_get_state_eventIDs( &ADIOI_MPE_iwrite_a, &ADIOI_MPE_iwrite_b); + + int comm_world_rank; + MPI_Comm_rank( MPI_COMM_WORLD, &comm_world_rank ); + + if ( comm_world_rank == 0 ) { + MPE_Describe_state( ADIOI_MPE_open_a, ADIOI_MPE_open_b, + "open", "orange" ); + MPE_Describe_state( ADIOI_MPE_read_a, ADIOI_MPE_read_b, + "read", "green" ); + MPE_Describe_state( ADIOI_MPE_write_a, ADIOI_MPE_write_b, + "write", "blue" ); + MPE_Describe_state( ADIOI_MPE_lseek_a, ADIOI_MPE_lseek_b, + "lseek", "red" ); + MPE_Describe_state( ADIOI_MPE_close_a, ADIOI_MPE_close_b, + "close", "grey" ); + MPE_Describe_state( ADIOI_MPE_writelock_a, ADIOI_MPE_writelock_b, + "writelock", "plum" ); + MPE_Describe_state( ADIOI_MPE_readlock_a, ADIOI_MPE_readlock_b, + "readlock", "magenta" ); + MPE_Describe_state( ADIOI_MPE_unlock_a, ADIOI_MPE_unlock_b, + "unlock", "purple" ); + MPE_Describe_state( ADIOI_MPE_postwrite_a, ADIOI_MPE_postwrite_b, + "postwrite", "ivory" ); + MPE_Describe_state( ADIOI_MPE_openinternal_a, ADIOI_MPE_openinternal_b, "open system", "blue"); + MPE_Describe_state( ADIOI_MPE_stat_a, ADIOI_MPE_stat_b, "stat", "purple"); + MPE_Describe_state( ADIOI_MPE_iread_a, ADIOI_MPE_iread_b, "iread", "purple"); + MPE_Describe_state( ADIOI_MPE_iwrite_a, ADIOI_MPE_iwrite_b, "iwrite", "purple"); + } + } +#endif + + *error_code = MPI_SUCCESS; + MPI_Op_create(my_consensus, 1, &ADIO_same_amode); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_io_coll.c b/ompi/mca/io/romio314/romio/adio/common/ad_io_coll.c new file mode 100644 index 0000000000..7e980e1e1d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_io_coll.c @@ -0,0 +1,1135 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "assert.h" +#include "adio.h" +#include "adio_extern.h" +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + +/* #define ALLTOALL */ + +/* #define DEBUG */ +/* #define DEBUG2 */ /* print buffers */ + +#define USE_PRE_REQ + +static void Exch_data_amounts (ADIO_File fd, int nprocs, + ADIO_Offset *client_comm_sz_arr, + ADIO_Offset *agg_comm_sz_arr, + int *client_alltoallw_counts, + int *agg_alltoallw_counts, + int *aggregators_done); +static void post_aggregator_comm (MPI_Comm comm, int rw_type, int nproc, + void *cb_buf, + MPI_Datatype *client_comm_dtype_arr, + ADIO_Offset *client_comm_sz_arr, + MPI_Request **requests, + int *aggregators_client_count_p); + +static void post_client_comm (ADIO_File fd, int rw_type, + int agg_rank, void *buf, + MPI_Datatype agg_comm_dtype, + int agg_alltoallw_count, + MPI_Request *request); + +/* Avery Ching and Kenin Columa's reworked two-phase algorithm. Key features + * - persistent file domains + * - an option to use alltoall instead of point-to-point + */ +void ADIOI_IOStridedColl (ADIO_File fd, void *buf, int count, int rdwr, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, + int *error_code) +{ + ADIO_Offset min_st_offset=0, max_end_offset=0; + ADIO_Offset st_end_offset[2]; + ADIO_Offset *all_st_end_offsets = NULL; + int filetype_is_contig, buftype_is_contig, is_contig; + ADIO_Offset off; + int interleave_count = 0, i, nprocs, myrank, nprocs_for_coll; + int cb_enable; + ADIO_Offset bufsize; + MPI_Aint extent; +#ifdef DEBUG2 + MPI_Aint bufextent; +#endif + MPI_Count size; + int agg_rank; + + ADIO_Offset agg_disp; /* aggregated file offset */ + MPI_Datatype agg_dtype; /* aggregated file datatype */ + + int aggregators_done = 0; + ADIO_Offset buffered_io_size = 0; + + int *alltoallw_disps; + + int *alltoallw_counts; + int *client_alltoallw_counts; + int *agg_alltoallw_counts; + + char *cb_buf = NULL; + + MPI_Datatype *client_comm_dtype_arr; /* aggregator perspective */ + MPI_Datatype *agg_comm_dtype_arr; /* client perspective */ + ADIO_Offset *client_comm_sz_arr; /* aggregator perspective */ + ADIO_Offset *agg_comm_sz_arr; /* client perspective */ + + /* file views for each client and aggregator */ + view_state *client_file_view_state_arr = NULL; + view_state *agg_file_view_state_arr = NULL; + /* mem views for local process */ + view_state *my_mem_view_state_arr = NULL; + + MPI_Status *agg_comm_statuses = NULL; + MPI_Request *agg_comm_requests = NULL; + MPI_Status *client_comm_statuses = NULL; + MPI_Request *client_comm_requests = NULL; + int aggs_client_count = 0; + int clients_agg_count = 0; + + MPI_Comm_size (fd->comm, &nprocs); + MPI_Comm_rank (fd->comm, &myrank); +#ifdef DEBUG + fprintf (stderr, "p%d: entering ADIOI_IOStridedColl\n", myrank); +#endif +#ifdef AGGREGATION_PROFILE + if (rdwr == ADIOI_READ) + MPE_Log_event (5010, 0, NULL); + else + MPE_Log_event (5012, 0, NULL); +#endif + + /* I need to check if there are any outstanding nonblocking writes + to the file, which could potentially interfere with the writes + taking place in this collective write call. Since this is not + likely to be common, let me do the simplest thing possible here: + Each process completes all pending nonblocking operations before + completing. */ + + nprocs_for_coll = fd->hints->cb_nodes; + + if (rdwr == ADIOI_READ) + cb_enable = fd->hints->cb_read; + else + cb_enable = fd->hints->cb_write; + + /* only check for interleaving if cb_read isn't disabled */ + if (cb_enable != ADIOI_HINT_DISABLE) { + /* find the starting and ending byte of my I/O access */ + ADIOI_Calc_bounds (fd, count, datatype, file_ptr_type, offset, + &st_end_offset[0], &st_end_offset[1]); + + /* allocate an array of start/end pairs */ + all_st_end_offsets = (ADIO_Offset *) + ADIOI_Malloc (2*nprocs*sizeof(ADIO_Offset)); + MPI_Allgather (st_end_offset, 2, ADIO_OFFSET, all_st_end_offsets, 2, + ADIO_OFFSET, fd->comm); + + min_st_offset = all_st_end_offsets[0]; + max_end_offset = all_st_end_offsets[1]; + + for (i=1; ifiletype, &filetype_is_contig); + + if ((cb_enable == ADIOI_HINT_DISABLE + || (!interleave_count && (cb_enable == ADIOI_HINT_AUTO))) + && (fd->hints->cb_pfr != ADIOI_HINT_ENABLE)){ + if (cb_enable != ADIOI_HINT_DISABLE) { + ADIOI_Free (all_st_end_offsets); + } + + if (buftype_is_contig && filetype_is_contig) { + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + (fd->etype_size) * offset; + if (rdwr == ADIOI_READ) + ADIO_ReadContig(fd, buf, count, datatype, + ADIO_EXPLICIT_OFFSET, off, status, + error_code); + else + ADIO_WriteContig(fd, buf, count, datatype, + ADIO_EXPLICIT_OFFSET, off, status, + error_code); + } + else { + if (rdwr == ADIOI_READ) + ADIO_ReadContig(fd, buf, count, datatype, ADIO_INDIVIDUAL, + 0, status, error_code); + else + ADIO_WriteContig(fd, buf, count, datatype, ADIO_INDIVIDUAL, + 0, status, error_code); + } + } + else { + if (rdwr == ADIOI_READ) + ADIO_ReadStrided(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); + else + ADIO_WriteStrided(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); + } + return; + } + + MPI_Type_extent(datatype, &extent); +#ifdef DEBUG2 + bufextent = extent * count; +#endif + MPI_Type_size_x(datatype, &size); + bufsize = size * (MPI_Count)count; + + /* Calculate file realms */ + if ((fd->hints->cb_pfr != ADIOI_HINT_ENABLE) || + (fd->file_realm_types == NULL)) + ADIOI_Calc_file_realms (fd, min_st_offset, max_end_offset); + + my_mem_view_state_arr = (view_state *) + ADIOI_Calloc (1, nprocs * sizeof(view_state)); + agg_file_view_state_arr = (view_state *) + ADIOI_Calloc (1, nprocs * sizeof(view_state)); + client_comm_sz_arr = (ADIO_Offset *) + ADIOI_Calloc (1, nprocs * sizeof(ADIO_Offset)); + + if (fd->is_agg) { + client_file_view_state_arr = (view_state *) + ADIOI_Calloc (1, nprocs * sizeof(view_state)); + } + else { + client_file_view_state_arr = NULL; + } + + /* Alltoallw doesn't like a null array even if the counts are + * zero. If you do not include this code, it will fail. */ + client_comm_dtype_arr = (MPI_Datatype *) + ADIOI_Calloc (1, nprocs * sizeof(MPI_Datatype)); + if (!fd->is_agg) + for (i = 0; i < nprocs; i++) + client_comm_dtype_arr[i] = MPI_BYTE; + + ADIOI_Exch_file_views (myrank, nprocs, file_ptr_type, fd, count, + datatype, offset, my_mem_view_state_arr, + agg_file_view_state_arr, + client_file_view_state_arr); + + agg_comm_sz_arr = (ADIO_Offset *) + ADIOI_Calloc (1, nprocs * sizeof(ADIO_Offset)); + agg_comm_dtype_arr = (MPI_Datatype *) + ADIOI_Malloc (nprocs * sizeof(MPI_Datatype)); + if (fd->is_agg) { + ADIOI_Build_agg_reqs (fd, rdwr, nprocs, + client_file_view_state_arr, + client_comm_dtype_arr, + client_comm_sz_arr, + &agg_disp, + &agg_dtype); + buffered_io_size = 0; + for (i=0; i 0) + buffered_io_size += client_comm_sz_arr[i]; + } + } +#ifdef USE_PRE_REQ + else + { + /* Example use of ADIOI_Build_client_pre_req. to an + * appropriate section */ + + for (i = 0; i < fd->hints->cb_nodes; i++) + { + agg_rank = fd->hints->ranklist[(i+myrank)%fd->hints->cb_nodes]; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5040, 0, NULL); +#endif + ADIOI_Build_client_pre_req( + fd, agg_rank, (i+myrank)%fd->hints->cb_nodes, + &(my_mem_view_state_arr[agg_rank]), + &(agg_file_view_state_arr[agg_rank]), + 2*1024*1024, + 64*1024); +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5041, 0, NULL); +#endif + } + } +#endif + + + if (fd->is_agg) + cb_buf = (char *) ADIOI_Malloc (fd->hints->cb_buffer_size); + alltoallw_disps = (int *) ADIOI_Calloc (nprocs, sizeof(int)); + alltoallw_counts = client_alltoallw_counts = (int *) + ADIOI_Calloc (2*nprocs, sizeof(int)); + agg_alltoallw_counts = &alltoallw_counts[nprocs]; + + if (fd->hints->cb_alltoall == ADIOI_HINT_DISABLE) { + /* aggregators pre-post all Irecv's for incoming data from clients */ + if ((fd->is_agg) && (rdwr == ADIOI_WRITE)) + post_aggregator_comm(fd->comm, rdwr, nprocs, cb_buf, + client_comm_dtype_arr, + client_comm_sz_arr, + &agg_comm_requests, + &aggs_client_count); + } + /* Aggregators send amounts for data requested to clients */ + Exch_data_amounts (fd, nprocs, client_comm_sz_arr, agg_comm_sz_arr, + client_alltoallw_counts, agg_alltoallw_counts, + &aggregators_done); + +#ifdef DEBUG + fprintf (stderr, "client_alltoallw_counts[ "); + for (i=0; ihints->cb_alltoall == ADIOI_HINT_DISABLE) { + /* clients should build datatypes for local memory locations + for data communication with aggregators and post + communication as the datatypes are built */ + + client_comm_requests = (MPI_Request *) + ADIOI_Calloc (fd->hints->cb_nodes, sizeof(MPI_Request)); + + for (i = 0; i < fd->hints->cb_nodes; i++) + { + clients_agg_count = 0; + agg_rank = fd->hints->ranklist[(i+myrank)%fd->hints->cb_nodes]; + if (agg_comm_sz_arr[agg_rank] > 0) { + ADIOI_Build_client_req(fd, agg_rank, + (i+myrank)%fd->hints->cb_nodes, + &(my_mem_view_state_arr[agg_rank]), + &(agg_file_view_state_arr[agg_rank]), + agg_comm_sz_arr[agg_rank], + &(agg_comm_dtype_arr[agg_rank])); + +#ifdef AGGREGATION_PROFILE + if (i == 0) + MPE_Log_event (5038, 0, NULL); +#endif + post_client_comm (fd, rdwr, agg_rank, buf, + agg_comm_dtype_arr[agg_rank], + agg_alltoallw_counts[agg_rank], + &client_comm_requests[clients_agg_count]); + clients_agg_count++; + } + } +#ifdef AGGREGATION_PROFILE + if (!clients_agg_count) + MPE_Log_event(5039, 0, NULL); +#endif + + if (rdwr == ADIOI_READ) { + if (fd->is_agg && buffered_io_size) { + ADIOI_IOFiletype (fd, cb_buf, buffered_io_size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, agg_disp, agg_dtype, + ADIOI_READ, status, error_code); + if (*error_code != MPI_SUCCESS) return; + MPI_Type_free (&agg_dtype); + } + +#ifdef DEBUG + fprintf (stderr, "expecting from [agg](disp,size,cnt)="); + for (i=0; i < nprocs; i++) { + MPI_Type_size_x (agg_comm_dtype_arr[i], &size); + fprintf (stderr, "[%d](%d,%d,%d)", i, alltoallw_disps[i], + size, agg_alltoallw_counts[i]); + if (i != nprocs - 1) + fprintf(stderr, ","); + } + fprintf (stderr, "]\n"); + if (fd->is_agg) { + fprintf (stderr, "sending to [client](disp,size,cnt)="); + for (i=0; i < nprocs; i++) { + if (fd->is_agg) + MPI_Type_size_x (client_comm_dtype_arr[i], &size); + else + size = -1; + + fprintf (stderr, "[%d](%d,%d,%d)", i, alltoallw_disps[i], + size, client_alltoallw_counts[i]); + if (i != nprocs - 1) + fprintf(stderr, ","); + } + fprintf (stderr,"\n"); + } + fflush (NULL); +#endif + /* aggregators post all Isends for outgoing data to clients */ + if (fd->is_agg) + post_aggregator_comm(fd->comm, rdwr, nprocs, cb_buf, + client_comm_dtype_arr, + client_comm_sz_arr, + &agg_comm_requests, + &aggs_client_count); + + if (fd->is_agg && aggs_client_count) { + agg_comm_statuses = ADIOI_Malloc(aggs_client_count * + sizeof(MPI_Status)); + MPI_Waitall(aggs_client_count, agg_comm_requests, + agg_comm_statuses); +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5033, 0, NULL); +#endif + ADIOI_Free (agg_comm_requests); + ADIOI_Free (agg_comm_statuses); + } + + if (clients_agg_count) { + client_comm_statuses = ADIOI_Malloc(clients_agg_count * + sizeof(MPI_Status)); + MPI_Waitall(clients_agg_count, client_comm_requests, + client_comm_statuses); +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5039, 0, NULL); +#endif + ADIOI_Free (client_comm_requests); + ADIOI_Free (client_comm_statuses); + } + +#ifdef DEBUG2 + fprintf (stderr, "buffered_io_size = %lld\n", buffered_io_size); + if (fd->is_agg && buffered_io_size) { + fprintf (stderr, "buf = ["); + for (i=0; iis_agg && buffered_io_size) { + assert (aggs_client_count != 0); + /* make sure we actually have the data to write out */ + agg_comm_statuses = (MPI_Status *) + ADIOI_Malloc (aggs_client_count*sizeof(MPI_Status)); + + MPI_Waitall (aggs_client_count, agg_comm_requests, + agg_comm_statuses); +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5033, 0, NULL); +#endif + ADIOI_Free (agg_comm_requests); + ADIOI_Free (agg_comm_statuses); +#ifdef DEBUG2 + fprintf (stderr, "cb_buf = ["); + for (i=0; iis_agg && buffered_io_size) { + ADIOI_IOFiletype (fd, cb_buf, buffered_io_size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, agg_disp, agg_dtype, + ADIOI_READ, status, error_code); + if (*error_code != MPI_SUCCESS) return; + MPI_Type_free (&agg_dtype); + } + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5032, 0, NULL); +#endif + MPI_Alltoallw (cb_buf, client_alltoallw_counts, alltoallw_disps, + client_comm_dtype_arr, + buf, agg_alltoallw_counts , alltoallw_disps, + agg_comm_dtype_arr, + fd->comm); +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5033, 0, NULL); +#endif + } + else { /* Write Case */ +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5032, 0, NULL); +#endif + MPI_Alltoallw (buf, agg_alltoallw_counts, alltoallw_disps, + agg_comm_dtype_arr, + cb_buf, client_alltoallw_counts, alltoallw_disps, + client_comm_dtype_arr, + fd->comm); +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5033, 0, NULL); +#endif + if (fd->is_agg && buffered_io_size) { + ADIOI_IOFiletype (fd, cb_buf, buffered_io_size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, agg_disp, agg_dtype, + ADIOI_WRITE, status, error_code); + if (*error_code != MPI_SUCCESS) return; + MPI_Type_free (&agg_dtype); + } + } + } + + /* Free (uncommit) datatypes for reuse */ + if (fd->is_agg) { + if (buffered_io_size > 0) { + for (i=0; i 0) + MPI_Type_free (&client_comm_dtype_arr[i]); + } + } + } + for (i=0; i 0) + MPI_Type_free (&agg_comm_dtype_arr[i]); + } + + /* figure out next set up requests */ + if (fd->is_agg) { + ADIOI_Build_agg_reqs (fd, rdwr, nprocs, + client_file_view_state_arr, + client_comm_dtype_arr, + client_comm_sz_arr, + &agg_disp, + &agg_dtype); + buffered_io_size = 0; + for (i=0; i 0) + buffered_io_size += client_comm_sz_arr[i]; + } + } +#ifdef USE_PRE_REQ + else { + /* Example use of ADIOI_Build_client_pre_req. to an + * appropriate section */ + for (i = 0; i < fd->hints->cb_nodes; i++) + { + agg_rank = fd->hints->ranklist[(i+myrank)%fd->hints->cb_nodes]; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5040, 0, NULL); +#endif + ADIOI_Build_client_pre_req( + fd, agg_rank, (i+myrank)%fd->hints->cb_nodes, + &(my_mem_view_state_arr[agg_rank]), + &(agg_file_view_state_arr[agg_rank]), + 2*1024*1024, + 64*1024); +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5041, 0, NULL); +#endif + } + } +#endif + + /* aggregators pre-post all Irecv's for incoming data from + * clients. if nothing is needed, agg_comm_requests is not + * allocated */ + if (fd->hints->cb_alltoall == ADIOI_HINT_DISABLE) { + if ((fd->is_agg) && (rdwr == ADIOI_WRITE)) + post_aggregator_comm(fd->comm, rdwr, nprocs, cb_buf, + client_comm_dtype_arr, + client_comm_sz_arr, + &agg_comm_requests, + &aggs_client_count); + } + + /* Aggregators send amounts for data requested to clients */ + Exch_data_amounts (fd, nprocs, client_comm_sz_arr, agg_comm_sz_arr, + client_alltoallw_counts, agg_alltoallw_counts, + &aggregators_done); + + } + + /* Clean up */ + + if (fd->hints->cb_pfr != ADIOI_HINT_ENABLE) { + /* AAR, FSIZE, and User provided uniform File realms */ + if (1) { + ADIOI_Delete_flattened (fd->file_realm_types[0]); + MPI_Type_free (&fd->file_realm_types[0]); + } + else { + for (i=0; ihints->cb_nodes; i++) { + ADIOI_Datatype_iscontig(fd->file_realm_types[i], &is_contig); + if (!is_contig) + ADIOI_Delete_flattened(fd->file_realm_types[i]); + MPI_Type_free (&fd->file_realm_types[i]); + } + } + ADIOI_Free (fd->file_realm_types); + ADIOI_Free (fd->file_realm_st_offs); + } + + /* This memtype must be deleted from the ADIOI_Flatlist or else it + * will match incorrectly with other datatypes which use this + * pointer. */ + ADIOI_Delete_flattened(datatype); + ADIOI_Delete_flattened(fd->filetype); + + if (fd->is_agg) { + if (buffered_io_size > 0) + MPI_Type_free (&agg_dtype); + for (i=0; iindices); + ADIOI_Free (client_file_view_state_arr[i].flat_type_p->blocklens); + ADIOI_Free (client_file_view_state_arr[i].flat_type_p); + } + ADIOI_Free (client_file_view_state_arr); + ADIOI_Free (cb_buf); + } + for (i = 0; i 0) + MPI_Type_free (&agg_comm_dtype_arr[i]); + + ADIOI_Free (client_comm_sz_arr); + ADIOI_Free (client_comm_dtype_arr); + ADIOI_Free (my_mem_view_state_arr); + ADIOI_Free (agg_file_view_state_arr); + ADIOI_Free (agg_comm_sz_arr); + ADIOI_Free (agg_comm_dtype_arr); + ADIOI_Free (alltoallw_disps); + ADIOI_Free (alltoallw_counts); + ADIOI_Free (all_st_end_offsets); + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, 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 during collective I/O. */ +#endif + fd->fp_sys_posn = -1; /* set it to null. */ +#ifdef AGGREGATION_PROFILE + if (rdwr == ADIOI_READ) + MPE_Log_event (5011, 0, NULL); + else + MPE_Log_event (5013, 0, NULL); +#endif +} + + +/* Some of this code is from the old Calc_my_off_len() function. + * It calculates the 1st and last byte accessed */ +void ADIOI_Calc_bounds (ADIO_File fd, int count, MPI_Datatype buftype, + int file_ptr_type, ADIO_Offset offset, + ADIO_Offset *st_offset, ADIO_Offset *end_offset) +{ + MPI_Count filetype_size, buftype_size, etype_size; + int sum; + MPI_Aint filetype_extent; + ADIO_Offset total_io; + int filetype_is_contig; + ADIO_Offset i, remainder; + ADIOI_Flatlist_node *flat_file; + + ADIO_Offset st_byte_off, end_byte_off; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5000, 0, NULL); +#endif + + if (!count) { + /* Max signed positive value for ADIO_Offset + * (arch. dependent?). is there a better way? */ + memset (st_offset, 8, sizeof(ADIO_Offset)); + *st_offset = *st_offset / 2; + *end_offset = -1; + return; + } + + ADIOI_Datatype_iscontig (fd->filetype, &filetype_is_contig); + + MPI_Type_size_x (fd->filetype, &filetype_size); + MPI_Type_extent (fd->filetype, &filetype_extent); + MPI_Type_size_x (fd->etype, &etype_size); + MPI_Type_size_x (buftype, &buftype_size); + + total_io = buftype_size * count; + + if (filetype_is_contig) { + if (file_ptr_type == ADIO_INDIVIDUAL) + st_byte_off = fd->fp_ind; + else + st_byte_off = fd->disp + etype_size * offset; + + end_byte_off = st_byte_off + total_io - 1; + } + else { + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + + /* we need to take care of some weirdness since fd->fp_ind + points at an accessible byte in file. the first accessible + byte in the file is not necessarily the first byte, nor is + it necessarily the first off/len pair in the filetype. */ + if (file_ptr_type == ADIO_INDIVIDUAL) { + st_byte_off = fd->fp_ind; + /* find end byte of I/O (may be in middle of an etype) */ + + /* calculate byte starting point of first filetype */ + end_byte_off = (ADIO_Offset) + ((fd->fp_ind - fd->disp - flat_file->indices[0]) / + filetype_extent) * filetype_extent + fd->disp + + flat_file->indices[0]; + /* number of absolute bytes into first filetype */ + remainder = (fd->fp_ind - fd->disp - flat_file->indices[0]) % + filetype_extent; + if (remainder) { + /* find how many file viewable bytes into first filetype */ + sum = 0; + for (i=0; icount; i++) { + sum += flat_file->blocklens[i]; + if ((flat_file->indices[i] - flat_file->indices[0] + + flat_file->blocklens[i]) >= remainder) { + sum -= (flat_file->blocklens[i] - (sum - remainder)); + break; + } + } + total_io += sum; + } + /* byte starting point of last filetype */ + end_byte_off += (total_io - 1) / filetype_size * filetype_extent; + /* number of bytes into last filetype */ + remainder = total_io % filetype_size; + if (!remainder) { + for (i=flat_file->count - 1; i>=0; i--) { + if (flat_file->blocklens[i]) break; + } + assert (i > -1); + end_byte_off += flat_file->indices[i] + + flat_file->blocklens[i] - 1; + end_byte_off -= flat_file->indices[0]; + } + else { + sum = 0; + for (i=0; icount; i++) { + sum += flat_file->blocklens[i]; + if (sum >= remainder) { + end_byte_off += flat_file->indices[i] + + flat_file->blocklens[i] - sum + remainder - 1; + break; + } + } + end_byte_off -= flat_file->indices[0]; + } + } + else { + /* find starting byte of I/O (must be aligned with an etype) */ + /* byte starting point of starting filetype */ + st_byte_off = fd->disp + ((offset * etype_size) / filetype_size) * + filetype_extent; + /* number of file viewable bytes into starting filetype */ + remainder = (etype_size * offset) % filetype_size; + + sum = 0; + for (i=0; icount; i++) { + sum += flat_file->blocklens[i]; + if (sum >= remainder) { + if (sum == remainder) + st_byte_off += flat_file->indices[i+1]; + else + st_byte_off += flat_file->indices[i] + + flat_file->blocklens[i] - sum + remainder; + break; + } + } + + /* find end byte of I/O (may be in middle of an etype) */ + /* byte starting point of last filetype */ + end_byte_off = fd->disp + (offset * etype_size + total_io) / + filetype_size * filetype_extent; + /* number of bytes into last filetype */ + remainder = (offset * etype_size + total_io) % filetype_size; + + if (!remainder) { + /* the last non-zero off/len pair */ + for (i=flat_file->count-1; i>=0; i--) { + if (flat_file->blocklens[i]) break; + } + assert (i >= 0); + /* back up a whole filetype, and put back up to the + * last byte of the last non-zero offlen pair */ + /* end_byte_off = (end_byte_off - filetype_extent) + + flat_file->indices[i] + + flat_file->blocklens[i] - 1; */ + /* equivalent of above commented out equation */ + end_byte_off -= filetype_extent - flat_file->indices[i] - + flat_file->blocklens[i] + 1; + } + else { + sum = 0; + for (i=0; icount; i++) { + sum += flat_file->blocklens[i]; + if (sum >= remainder) { + end_byte_off += flat_file->indices[i] + + flat_file->blocklens[i] - sum + remainder - 1; + break; + } + } + } + } + } + + *st_offset = st_byte_off; + *end_offset = end_byte_off; +#ifdef DEBUG + printf ("st_offset = %lld\nend_offset = %lld\n", + st_byte_off, end_byte_off); +#endif +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5001, 0, NULL); +#endif +} + +/* wrapper function for ADIO_WriteStrided and ADIO_ReadStrided. Used + * by new 2 phase code to pass an arbitrary file type directly to + * WriteStrided call without affecting existing code. For the new 2 + * phase code, we really only need to set a custom_ftype, and we can + * assume that this uses MPI_BYTE for the etype, and disp is 0 */ +void ADIOI_IOFiletype(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Datatype custom_ftype, + int rdwr, ADIO_Status *status, int *error_code) +{ + MPI_Datatype user_filetype; + MPI_Datatype user_etype; + ADIO_Offset user_disp; + int user_ind_wr_buffer_size; + int user_ind_rd_buffer_size; + int f_is_contig, m_is_contig; + int user_ds_read, user_ds_write; + MPI_Aint f_extent; + MPI_Count f_size; + int f_ds_percent; /* size/extent */ + +#ifdef AGGREGATION_PROFILE + if (rdwr == ADIOI_READ) + MPE_Log_event(5006, 0, NULL); + else + MPE_Log_event(5008, 0, NULL); +#endif + MPI_Type_extent(custom_ftype, &f_extent); + MPI_Type_size_x(custom_ftype, &f_size); + f_ds_percent = 100 * f_size / f_extent; + + /* temporarily store file view information */ + user_filetype = fd->filetype; + user_etype = fd->etype; + user_disp = fd->disp; + user_ds_read = fd->hints->ds_read; + user_ds_write = fd->hints->ds_write; + /* temporarily override the independent I/O datasieve buffer size */ + user_ind_wr_buffer_size = fd->hints->ind_wr_buffer_size; + user_ind_rd_buffer_size = fd->hints->ind_rd_buffer_size; + + /* set new values for temporary file view */ + fd->filetype = custom_ftype; + fd->etype = MPI_BYTE; + /* set new values for independent I/O datasieve buffer size */ + fd->hints->ind_wr_buffer_size = fd->hints->cb_buffer_size; + fd->hints->ind_rd_buffer_size = fd->hints->cb_buffer_size; + /* decide whether or not to do datasieving */ +#ifdef DEBUG + printf ("f_ds_percent = %d cb_ds_threshold = %d\n", f_ds_percent, + fd->hints->cb_ds_threshold); +#endif + if (f_ds_percent >= fd->hints->cb_ds_threshold) { + fd->hints->ds_read = ADIOI_HINT_ENABLE; + fd->hints->ds_write = ADIOI_HINT_ENABLE; + } + else { + fd->hints->ds_read = ADIOI_HINT_DISABLE; + fd->hints->ds_write = ADIOI_HINT_DISABLE; + } + + /* flatten the new filetype since the strided calls expect it to + * have been flattened in set file view. in the two phase code, + * the datatype passed down should always be MPI_BYTE, and + * therefore contiguous, but just for completeness sake, we'll + * check the memory datatype anyway */ + ADIOI_Datatype_iscontig(custom_ftype, &f_is_contig); + ADIOI_Datatype_iscontig(datatype, &m_is_contig); + if (!f_is_contig) + ADIOI_Flatten_datatype (custom_ftype); + + /* make appropriate Read/Write calls. Let ROMIO figure out file + * system specific stuff. */ + if (f_is_contig && m_is_contig) { + fd->disp = 0; + if (rdwr == ADIOI_READ) + ADIO_ReadContig(fd, buf, count, datatype, file_ptr_type, offset, + status, error_code); + else + ADIO_WriteContig(fd, buf, count, datatype, file_ptr_type, offset, + status, error_code); + } + else { + fd->disp = offset; + if (rdwr == ADIOI_READ) + ADIO_ReadStrided(fd, buf, count, datatype, file_ptr_type, 0, + status, error_code); + else + ADIO_WriteStrided(fd, buf, count, datatype, file_ptr_type, 0, + status, error_code); + } + + /* Delete flattened temporary filetype */ + if (!f_is_contig) + ADIOI_Delete_flattened (custom_ftype); + + /* restore the user specified file view to cover our tracks */ + fd->filetype = user_filetype; + fd->etype = user_etype; + fd->disp = user_disp; + fd->hints->ds_read = user_ds_read; + fd->hints->ds_write = user_ds_write; + fd->hints->ind_wr_buffer_size = user_ind_wr_buffer_size; + fd->hints->ind_rd_buffer_size = user_ind_rd_buffer_size; +#ifdef AGGREGATION_PROFILE + if (rdwr == ADIOI_READ) + MPE_Log_event (5007, 0, NULL); + else + MPE_Log_event (5009, 0, NULL); +#endif +} + +static void Exch_data_amounts (ADIO_File fd, int nprocs, + ADIO_Offset *client_comm_sz_arr, + ADIO_Offset *agg_comm_sz_arr, + int *client_alltoallw_counts, + int *agg_alltoallw_counts, + int *aggregators_done) +{ + int i; + int recv_idx; + MPI_Request *recv_requests; + MPI_Request *send_requests; + MPI_Status status; + MPI_Status *send_statuses; + /* Aggregators send amounts for data requested to clients */ + if (fd->hints->cb_alltoall != ADIOI_HINT_DISABLE) { + MPI_Alltoall (client_comm_sz_arr, sizeof(ADIO_Offset), MPI_BYTE, + agg_comm_sz_arr, sizeof(ADIO_Offset), MPI_BYTE, + fd->comm); + + if (fd->is_agg) { + for (i=0; i 0) + client_alltoallw_counts[i] = 1; + else + client_alltoallw_counts[i] = 0; + } + *aggregators_done = 0; + for (i=0; i 0) + agg_alltoallw_counts[i] = 1; + else + agg_alltoallw_counts[i] = 0; + } + } else { + /* let's see if we can't reduce some communication as well as + * overlap some communication and work */ + + recv_requests = ADIOI_Malloc (fd->hints->cb_nodes * sizeof(MPI_Request)); + /* post all receives - only receive from aggregators */ + for (i = 0; i < fd->hints->cb_nodes; i++) + MPI_Irecv (&agg_comm_sz_arr[fd->hints->ranklist[i]], + sizeof(ADIO_Offset), MPI_BYTE, fd->hints->ranklist[i], + AMT_TAG, fd->comm, &recv_requests[i]); + + /* Barrier is needed here if we're worried about unexpected + * messages being dropped */ + /* MPI_Barrier (fd->comm); */ + send_requests = NULL; + if (fd->is_agg) { + /* only aggregators send data */ + send_requests = ADIOI_Malloc (nprocs * sizeof(MPI_Request)); + + /* post all sends */ + for (i = 0; i < nprocs; i++) { + MPI_Isend (&client_comm_sz_arr[i], sizeof(ADIO_Offset), + MPI_BYTE, i, AMT_TAG, fd->comm, &send_requests[i]); + + if (client_comm_sz_arr[i] > 0) + client_alltoallw_counts[i] = 1; + else + client_alltoallw_counts[i] = 0; + } + } + + *aggregators_done = 0; + for (i=0; i < fd->hints->cb_nodes; i++) { + MPI_Waitany (fd->hints->cb_nodes, recv_requests, &recv_idx, &status); + if (agg_comm_sz_arr[fd->hints->ranklist[recv_idx]] == -1) + *aggregators_done = *aggregators_done + 1; + else if (agg_comm_sz_arr[fd->hints->ranklist[recv_idx]] > 0) + agg_alltoallw_counts[fd->hints->ranklist[recv_idx]] = 1; + else + agg_alltoallw_counts[fd->hints->ranklist[recv_idx]] = 0; + } + + ADIOI_Free (recv_requests); + if (fd->is_agg) { + /* wait for all sends to complete */ + send_statuses = ADIOI_Malloc (nprocs * sizeof (MPI_Status)); + MPI_Waitall (nprocs, send_requests, send_statuses); + ADIOI_Free (send_requests); + ADIOI_Free (send_statuses); + } + } +} + +static void post_aggregator_comm (MPI_Comm comm, int rw_type, + int nproc, void *cb_buf, + MPI_Datatype *client_comm_dtype_arr, + ADIO_Offset *client_comm_sz_arr, + MPI_Request **requests_p, + int *aggs_client_count_p) +{ + int aggs_client_count = 0; + MPI_Request *requests; + int i; + +#ifdef DEBUG + printf ("posting aggregator communication\n"); +#endif + + for (i=0; i < nproc; i++) + if (client_comm_sz_arr[i] > 0) + aggs_client_count++; +#ifdef DEBUG + printf ("aggregator needs to talk to %d clients\n", + aggs_client_count); +#endif + *aggs_client_count_p = aggs_client_count; + if (aggs_client_count) { + requests = (MPI_Request *) + ADIOI_Malloc (aggs_client_count * sizeof(MPI_Request)); + aggs_client_count = 0; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5032, 0, NULL); +#endif + for (i=0; i < nproc; i++) { + if (client_comm_sz_arr[i] > 0) { + if (rw_type == ADIOI_WRITE) + MPI_Irecv (cb_buf, 1, client_comm_dtype_arr[i], i, + DATA_TAG, comm, + &requests[aggs_client_count]); + else + MPI_Isend (cb_buf, 1, client_comm_dtype_arr[i], i, + DATA_TAG, comm, + &requests[aggs_client_count]); + + aggs_client_count++; + } + } + *requests_p = requests; + } +} + +static void post_client_comm (ADIO_File fd, int rw_type, + int agg_rank, void *buf, + MPI_Datatype agg_comm_dtype, + int agg_alltoallw_count, + MPI_Request *request) +{ + if (agg_alltoallw_count) { + if (rw_type == ADIOI_READ) + MPI_Irecv (buf, 1, agg_comm_dtype, agg_rank, DATA_TAG, fd->comm, + request); + else + MPI_Isend (buf, 1, agg_comm_dtype, agg_rank, DATA_TAG, fd->comm, + request); + } +} + + + diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_iopen.c b/ompi/mca/io/romio314/romio/adio/common/ad_iopen.c new file mode 100644 index 0000000000..5deeaa2cde --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_iopen.c @@ -0,0 +1,21 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2002 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +void ADIO_ImmediateOpen(ADIO_File fd, int *error_code) +{ + MPI_Comm tmp_comm; + tmp_comm = fd->comm; + /* some file systems might try to be clever inside their open routine. + * e.g. Blue Gene does a stat-and-broadcast */ + fd->comm = MPI_COMM_SELF; + (*(fd->fns->ADIOI_xxx_Open))(fd, error_code); + fd->is_open = 1; + fd->comm = tmp_comm; + +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_iread.c b/ompi/mca/io/romio314/romio/adio/common/ad_iread.c new file mode 100644 index 0000000000..74c342ab93 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_iread.c @@ -0,0 +1,91 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + +#include "mpiu_greq.h" + +#ifdef ROMIO_HAVE_WORKING_AIO +/* ADIOI_GEN_IreadContig + * + * This code handles two distinct cases. If ROMIO_HAVE_WORKING_AIO is not + * defined, then I/O is performed in a blocking manner. Otherwise we post + * an asynchronous I/O operation using the appropriate aio routines. + * + * In the aio case we rely on ADIOI_GEN_aio(), which is implemented in + * common/ad_iwrite.c. + */ +void ADIOI_GEN_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Request *request, + int *error_code) +{ + MPI_Count len, typesize; + int aio_errno = 0; + static char myname[] = "ADIOI_GEN_IREADCONTIG"; + + MPI_Type_size_x(datatype, &typesize); + ADIOI_Assert((count * typesize) == ((ADIO_Offset)(unsigned)count * (ADIO_Offset)typesize)); + len = count * typesize; + + if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind; + aio_errno = ADIOI_GEN_aio(fd, buf, len, offset, 0, request); + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += len; + + fd->fp_sys_posn = -1; + + /* --BEGIN ERROR HANDLING-- */ + if (aio_errno != 0) { + MPIO_ERR_CREATE_CODE_ERRNO(myname, aio_errno, error_code); + return; + } + /* --END ERROR HANDLING-- */ + + *error_code = MPI_SUCCESS; +} +#endif + +/* Generic implementation of IreadStrided calls the blocking ReadStrided + * immediately. + */ +void ADIOI_GEN_IreadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code) +{ + ADIO_Status status; + MPI_Count typesize; + MPI_Offset nbytes=0; + + /* Call the blocking function. It will create an error code + * if necessary. + */ + ADIO_ReadStrided(fd, buf, count, datatype, file_ptr_type, + offset, &status, error_code); + + if (*error_code == MPI_SUCCESS) { + MPI_Type_size_x(datatype, &typesize); + nbytes = (MPI_Offset)count*(MPI_Offset)typesize; + } + MPIO_Completed_request_create(&fd, nbytes, error_code, request); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_iread_fake.c b/ompi/mca/io/romio314/romio/adio/common/ad_iread_fake.c new file mode 100644 index 0000000000..b5cbd1da27 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_iread_fake.c @@ -0,0 +1,61 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpiu_greq.h" + +/* Generic implementation of IreadContig calls the blocking ReadContig + * immediately. + */ +void ADIOI_FAKE_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code) +{ + ADIO_Status status; + MPI_Count typesize; + MPI_Offset len; + + MPI_Type_size_x(datatype, &typesize); + len = (MPI_Offset)count * (MPI_Offset)typesize; + + /* Call the blocking function. It will create an error code + * if necessary. + */ + ADIOI_Assert(len == (int) len); /* the count is an int parm */ + ADIO_ReadContig(fd, buf, (int)len, MPI_BYTE, file_ptr_type, offset, + &status, error_code); + if (*error_code != MPI_SUCCESS) { + len=0; + } + MPIO_Completed_request_create(&fd, len, error_code, request); +} + + +/* Generic implementation of IreadStrided calls the blocking ReadStrided + * immediately. + */ +void ADIOI_FAKE_IreadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code) +{ + ADIO_Status status; + MPI_Count typesize; + MPI_Offset nbytes=0; + + /* Call the blocking function. It will create an error code + * if necessary. + */ + ADIO_ReadStrided(fd, buf, count, datatype, file_ptr_type, + offset, &status, error_code); + if (*error_code == MPI_SUCCESS) { + MPI_Type_size_x(datatype, &typesize); + nbytes = (MPI_Offset)count*(MPI_Offset)typesize; + } + MPIO_Completed_request_create(&fd, nbytes, error_code, request); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_iwrite.c b/ompi/mca/io/romio314/romio/adio/common/ad_iwrite.c new file mode 100644 index 0000000000..8177718ff8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_iwrite.c @@ -0,0 +1,342 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif +#include + +#include "../../mpi-io/mpioimpl.h" +#include "../../mpi-io/mpioprof.h" +#include "mpiu_greq.h" +/* Workaround for incomplete set of definitions if __REDIRECT is not + defined and large file support is used in aio.h */ +#if !defined(__REDIRECT) && defined(__USE_FILE_OFFSET64) +#define aiocb aiocb64 +#endif + +#ifdef ROMIO_HAVE_WORKING_AIO + +static MPIX_Grequest_class ADIOI_GEN_greq_class = 0; + +/* ADIOI_GEN_IwriteContig + * + * This code handles only the case where ROMIO_HAVE_WORKING_AIO is + * defined. We post an asynchronous I/O operations using the appropriate aio + * routines. Otherwise, the ADIOI_Fns_struct will point to the FAKE + * version. + */ +void ADIOI_GEN_IwriteContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code) +{ + MPI_Count len, typesize; + int aio_errno = 0; + static char myname[] = "ADIOI_GEN_IWRITECONTIG"; + + MPI_Type_size_x(datatype, &typesize); + len = count * typesize; + ADIOI_Assert(len == (int)((ADIO_Offset)count * (ADIO_Offset)typesize)); /* the count is an int parm */ + + if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind; + /* Cast away the const'ness of 'buf' as ADIOI_GEN_aio is used for + * both read and write calls */ + aio_errno = ADIOI_GEN_aio(fd, (char *) buf, len, offset, 1, request); + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += len; + + fd->fp_sys_posn = -1; + + /* --BEGIN ERROR HANDLING-- */ + if (aio_errno != 0) { + MPIO_ERR_CREATE_CODE_ERRNO(myname, aio_errno, error_code); + return; + } + /* --END ERROR HANDLING-- */ + + *error_code = MPI_SUCCESS; +} +/* This function is for implementation convenience. + * It takes care of the differences in the interface for nonblocking I/O + * on various Unix machines! If wr==1 write, wr==0 read. + * + * Returns 0 on success, -errno on failure. + */ +int ADIOI_GEN_aio(ADIO_File fd, void *buf, int len, ADIO_Offset offset, + int wr, MPI_Request *request) +{ + int err=-1, fd_sys; + + int error_code; + struct aiocb *aiocbp=NULL; + ADIOI_AIO_Request *aio_req=NULL; + MPI_Status status; +#if defined(ROMIO_XFS) + unsigned maxiosz = wr ? fd->hints->fs_hints.xfs.write_chunk_sz : + fd->hints->fs_hints.xfs.read_chunk_sz; +#endif /* ROMIO_XFS */ + + fd_sys = fd->fd_sys; + +#if defined(ROMIO_XFS) + /* Use Direct I/O if desired and properly aligned */ + if (fd->fns == &ADIO_XFS_operations && + ((wr && fd->direct_write) || (!wr && fd->direct_read)) && + !(((long) buf) % fd->d_mem) && !(offset % fd->d_miniosz) && + !(len % fd->d_miniosz) && (len >= fd->d_miniosz) && + (len <= maxiosz)) { + fd_sys = fd->fd_direct; + } +#endif /* ROMIO_XFS */ + + 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 + +#ifndef ROMIO_HAVE_AIO_CALLS_NEED_FILEDES +#ifndef ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_FILDES +#error 'No fildes set for aio structure' +#endif + 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 + + if (err == -1) { + if (errno == EAGAIN || errno == ENOSYS) { + /* exceeded the max. no. of outstanding requests. + or, aio routines are not actually implemented + treat this as a blocking request and return. */ + if (wr) + ADIO_WriteContig(fd, buf, len, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, offset, &status, &error_code); + else + ADIO_ReadContig(fd, buf, len, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, offset, &status, &error_code); + + MPIO_Completed_request_create(&fd, len, &error_code, request); + if (aiocbp != NULL) ADIOI_Free(aiocbp); + if (aio_req != NULL) ADIOI_Free(aio_req); + return 0; + } else { + return 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; +} +#endif + + +/* Generic implementation of IwriteStrided calls the blocking WriteStrided + * immediately. + */ +void ADIOI_GEN_IwriteStrided(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Request *request, + int *error_code) +{ + ADIO_Status status; + MPI_Count typesize; + MPI_Offset nbytes=0; + + /* Call the blocking function. It will create an error code + * if necessary. + */ + ADIO_WriteStrided(fd, buf, count, datatype, file_ptr_type, + offset, &status, error_code); + + if (*error_code == MPI_SUCCESS) { + MPI_Type_size_x(datatype, &typesize); + nbytes = (MPI_Offset)count * (MPI_Offset)typesize; + } + MPIO_Completed_request_create(&fd, nbytes, error_code, request); +} + +#ifdef ROMIO_HAVE_WORKING_AIO +/* generic POSIX aio completion test routine */ +int ADIOI_GEN_aio_poll_fn(void *extra_state, MPI_Status *status) +{ + ADIOI_AIO_Request *aio_req; + int errcode=MPI_SUCCESS; + + aio_req = (ADIOI_AIO_Request *)extra_state; + + /* aio_error returns an ERRNO value */ + errno = aio_error(aio_req->aiocbp); + if (errno == EINPROGRESS) { + /* TODO: need to diddle with status somehow */ + } + else if (errno == ECANCELED) { + /* TODO: unsure how to handle this */ + } else if (errno == 0) { + ssize_t n = aio_return(aio_req->aiocbp); + aio_req->nbytes = n; + errcode = MPI_Grequest_complete(aio_req->req); + /* --BEGIN ERROR HANDLING-- */ + if (errcode != MPI_SUCCESS) { + errcode = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + "ADIOI_GEN_aio_poll_fn", __LINE__, + MPI_ERR_IO, "**mpi_grequest_complete", + 0); + } + /* --END ERROR HANDLING-- */ + } + return errcode; +} + +/* wait for multiple requests to complete */ +int ADIOI_GEN_aio_wait_fn(int count, void ** array_of_states, + double timeout, MPI_Status *status) +{ + const struct aiocb **cblist; + int err, errcode=MPI_SUCCESS; + int nr_complete=0; + double starttime; + struct timespec aio_timer; + struct timespec *aio_timer_p = NULL; + + ADIOI_AIO_Request **aio_reqlist; + int i; + + aio_reqlist = (ADIOI_AIO_Request **)array_of_states; + + cblist = (const struct aiocb**) ADIOI_Calloc(count, sizeof(struct aiocb*)); + + starttime = MPI_Wtime(); + if (timeout >0) { + aio_timer.tv_sec = (time_t)timeout; + aio_timer.tv_nsec = timeout - aio_timer.tv_sec; + aio_timer_p = &aio_timer; + } + for (i=0; i< count; i++) + { + cblist[i] = aio_reqlist[i]->aiocbp; + } + + while(nr_complete < count) { + do { + err = aio_suspend(cblist, count, aio_timer_p); + } while (err < 0 && errno == EINTR); + if (err == 0) + { /* run through the list of requests, and mark all the completed + ones as done */ + for (i=0; i< count; i++) + { + /* aio_error returns an ERRNO value */ + if (aio_reqlist[i]->aiocbp == NULL) + continue; + errno = aio_error(aio_reqlist[i]->aiocbp); + if (errno == 0) { + ssize_t n = aio_return(aio_reqlist[i]->aiocbp); + aio_reqlist[i]->nbytes = n; + errcode = MPI_Grequest_complete(aio_reqlist[i]->req); + if (errcode != MPI_SUCCESS) { + errcode = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + "ADIOI_GEN_aio_wait_fn", + __LINE__, MPI_ERR_IO, + "**mpi_grequest_complete", 0); + } + ADIOI_Free(aio_reqlist[i]->aiocbp); + aio_reqlist[i]->aiocbp = NULL; + cblist[i] = NULL; + nr_complete++; + } + /* TODO: need to handle error conditions somehow*/ + } + } /* TODO: also need to handle errors here */ + if ( (timeout > 0) && (timeout < (MPI_Wtime() - starttime) )) + break; + } + + if (cblist != NULL) ADIOI_Free(cblist); + return errcode; +} + +int ADIOI_GEN_aio_free_fn(void *extra_state) +{ + ADIOI_AIO_Request *aio_req; + aio_req = (ADIOI_AIO_Request*)extra_state; + + if (aio_req->aiocbp != NULL) + ADIOI_Free(aio_req->aiocbp); + ADIOI_Free(aio_req); + + return MPI_SUCCESS; +} +#endif /* working AIO */ + +int ADIOI_GEN_aio_query_fn(void *extra_state, MPI_Status *status) +{ + ADIOI_AIO_Request *aio_req; + + aio_req = (ADIOI_AIO_Request *)extra_state; + + MPI_Status_set_elements_x(status, MPI_BYTE, aio_req->nbytes); + + /* can never cancel so always true */ + MPI_Status_set_cancelled(status, 0); + + /* choose not to return a value for this */ + status->MPI_SOURCE = MPI_UNDEFINED; + /* tag has no meaning for this generalized request */ + status->MPI_TAG = MPI_UNDEFINED; + /* this generalized request never fails */ + return MPI_SUCCESS; +} +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_iwrite_fake.c b/ompi/mca/io/romio314/romio/adio/common/ad_iwrite_fake.c new file mode 100644 index 0000000000..6210942e66 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_iwrite_fake.c @@ -0,0 +1,65 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#include "mpiu_greq.h" + +/* Generic implementation of IwriteContig calls the blocking WriteContig + * immediately. + */ +void ADIOI_FAKE_IwriteContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code) +{ + ADIO_Status status; + MPI_Offset len; + MPI_Count typesize; + MPI_Offset nbytes=0; + + MPI_Type_size_x(datatype, &typesize); + len = (MPI_Offset)count * (MPI_Offset)typesize; + + /* Call the blocking function. It will create an error code + * if necessary. + */ + ADIOI_Assert(len == (int) len); /* the count is an int parm */ + ADIO_WriteContig(fd, buf, (int)len, MPI_BYTE, file_ptr_type, offset, + &status, error_code); + if (*error_code == MPI_SUCCESS) { + MPI_Type_size_x(datatype, &typesize); + nbytes = (MPI_Offset)count*(MPI_Offset)typesize; + } + MPIO_Completed_request_create(&fd, nbytes, error_code, request); + +} + + +/* Generic implementation of IwriteStrided calls the blocking WriteStrided + * immediately. + */ +void ADIOI_FAKE_IwriteStrided(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code) +{ + ADIO_Status status; + MPI_Count typesize; + MPI_Offset nbytes=0; + + /* Call the blocking function. It will create an error code + * if necessary. + */ + ADIO_WriteStrided(fd, buf, count, datatype, file_ptr_type, + offset, &status, error_code); + if (*error_code == MPI_SUCCESS) { + MPI_Type_size_x(datatype, &typesize); + nbytes = (MPI_Offset)count * (MPI_Offset)typesize; + } + MPIO_Completed_request_create(&fd, nbytes, error_code, request); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_open.c b/ompi/mca/io/romio314/romio/adio/common/ad_open.c new file mode 100644 index 0000000000..7d69280057 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_open.c @@ -0,0 +1,315 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "adio_cb_config_list.h" + +#include "mpio.h" + +static int is_aggregator(int rank, ADIO_File fd); +static int uses_generic_read(ADIO_File fd); +static int uses_generic_write(ADIO_File fd); +static int build_cb_config_list(ADIO_File fd, + MPI_Comm orig_comm, MPI_Comm comm, + int rank, int procs, int *error_code); + +MPI_File ADIO_Open(MPI_Comm orig_comm, + MPI_Comm comm, const char *filename, int file_system, + ADIOI_Fns *ops, + int access_mode, ADIO_Offset disp, MPI_Datatype etype, + MPI_Datatype filetype, + MPI_Info info, int perm, int *error_code) +{ + MPI_File mpi_fh; + ADIO_File fd; + int err, rank, procs; + static char myname[] = "ADIO_OPEN"; + int max_error_code; + MPI_Info dupinfo; + int syshints_processed, can_skip; + char *p; + + *error_code = MPI_SUCCESS; + + /* obtain MPI_File handle */ + mpi_fh = MPIO_File_create(sizeof(struct ADIOI_FileD)); + if (mpi_fh == MPI_FILE_NULL) { + } + fd = MPIO_File_resolve(mpi_fh); + + fd->cookie = ADIOI_FILE_COOKIE; + fd->fp_ind = disp; + fd->fp_sys_posn = 0; + fd->comm = comm; /* dup'ed in MPI_File_open */ + fd->filename = ADIOI_Strdup(filename); + fd->file_system = file_system; + fd->fs_ptr = NULL; + + fd->fns = ops; + + fd->disp = disp; + fd->split_coll_count = 0; + fd->shared_fp_fd = ADIO_FILE_NULL; + fd->atomicity = 0; + fd->etype = etype; /* MPI_BYTE by default */ + fd->filetype = filetype; /* MPI_BYTE by default */ + fd->etype_size = 1; /* default etype is MPI_BYTE */ + + fd->file_realm_st_offs = NULL; + fd->file_realm_types = NULL; + + fd->perm = perm; + + fd->async_count = 0; + + fd->fortran_handle = -1; + + fd->err_handler = ADIOI_DFLT_ERR_HANDLER; + + MPI_Comm_rank(comm, &rank); + MPI_Comm_size(comm, &procs); +/* create and initialize info object */ + fd->hints = (ADIOI_Hints *)ADIOI_Calloc(1, sizeof(struct ADIOI_Hints_struct)); + if (fd->hints == NULL) { + *error_code = MPIO_Err_create_code(*error_code, + MPIR_ERR_RECOVERABLE, + myname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + goto fn_exit; + } + fd->hints->cb_config_list = NULL; + fd->hints->ranklist = NULL; + fd->hints->initialized = 0; + fd->info = MPI_INFO_NULL; + + /* move system-wide hint processing *back* into open, but this time the + * hintfile reader will do a scalable read-and-broadcast. The global + * ADIOI_syshints will get initialized at first open. subsequent open + * calls will just use result from first open. + * + * We have two goals here: + * 1: avoid processing the hintfile multiple times + * 2: have all processes participate in hintfile processing (so we can read-and-broadcast) + * + * a code might do an "initialize from 0", so we can only skip hint + * processing once everyone has particpiated in hint processing */ + if (ADIOI_syshints == MPI_INFO_NULL) + syshints_processed = 0; + else + syshints_processed = 1; + + MPI_Allreduce(&syshints_processed, &can_skip, 1, MPI_INT, MPI_MIN, fd->comm); + if (!can_skip) { + if (ADIOI_syshints == MPI_INFO_NULL) + MPI_Info_create(&ADIOI_syshints); + ADIOI_process_system_hints(fd, ADIOI_syshints); + } + + ADIOI_incorporate_system_hints(info, ADIOI_syshints, &dupinfo); + ADIO_SetInfo(fd, dupinfo, &err); + if (dupinfo != MPI_INFO_NULL) { + *error_code = MPI_Info_free(&dupinfo); + if (*error_code != MPI_SUCCESS) + goto fn_exit; + } + ADIOI_Info_set(fd->info, "romio_filesystem_type", fd->fns->fsname); + + /* Instead of repeatedly allocating this buffer in collective read/write, + * allocating up-front might make memory management on small platforms + * (e.g. Blue Gene) more efficent */ + fd->io_buf = ADIOI_Malloc(fd->hints->cb_buffer_size); + + /* deferred open: + * we can only do this optimization if 'fd->hints->deferred_open' is set + * (which means the user hinted 'no_indep_rw' and collective buffering). + * Furthermore, we only do this if our collective read/write routines use + * our generic function, and not an fs-specific routine (we can defer opens + * only if we use our aggreagation code). */ + if (fd->hints->deferred_open && + !(uses_generic_read(fd) \ + && uses_generic_write(fd))) { + fd->hints->deferred_open = 0; + } + if (ADIO_Feature(fd, ADIO_SCALABLE_OPEN)) + /* disable deferred open on these fs so that scalable broadcast + * will always use the propper communicator */ + fd->hints->deferred_open = 0; + + + /* on BlueGene, the cb_config_list is built when hints are processed. No + * one else does that right now */ + if (fd->hints->ranklist == NULL) { + build_cb_config_list(fd, orig_comm, comm, rank, procs, error_code); + if (*error_code != MPI_SUCCESS) + goto fn_exit; + } + /* for debugging, it can be helpful to see the hints selected */ + p = getenv("ROMIO_PRINT_HINTS"); + if (rank == 0 && p != NULL ) { + ADIOI_Info_print_keyvals(fd->info); + } + + fd->is_open = 0; + fd->my_cb_nodes_index = -2; + fd->is_agg = is_aggregator(rank, fd); + /* deferred open used to split the communicator to create an "aggregator + * communicator", but we only used it as a way to indicate that deferred + * open happened. fd->is_open and fd->is_agg are sufficient */ + + /* actual opens start here */ + /* generic open: one process opens to create the file, all others open */ + /* nfs open: everybody opens or else you'll end up with "file not found" + * due to stupid nfs consistency semantics */ + /* scalable open: one process opens and broadcasts results to everyone */ + + ADIOI_OpenColl(fd, rank, access_mode, error_code); + + fn_exit: + MPI_Allreduce(error_code, &max_error_code, 1, MPI_INT, MPI_MAX, comm); + if (max_error_code != MPI_SUCCESS) { + + /* If the file was successfully opened, close it */ + if (*error_code == MPI_SUCCESS) { + + /* in the deferred open case, only those who have actually + opened the file should close it */ + if (fd->hints->deferred_open) { + if (fd->is_agg) { + (*(fd->fns->ADIOI_xxx_Close))(fd, error_code); + } + } + else { + (*(fd->fns->ADIOI_xxx_Close))(fd, error_code); + } + } + if (fd->filename) ADIOI_Free(fd->filename); + if (fd->hints->ranklist) ADIOI_Free(fd->hints->ranklist); + if (fd->hints->cb_config_list) ADIOI_Free(fd->hints->cb_config_list); + if (fd->hints) ADIOI_Free(fd->hints); + if (fd->info != MPI_INFO_NULL) MPI_Info_free(&(fd->info)); + if (fd->io_buf) ADIOI_Free(fd->io_buf); + ADIOI_Free(fd); + fd = ADIO_FILE_NULL; + if (*error_code == MPI_SUCCESS) + { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, + "**oremote_fail", 0); + } + } + + return fd; +} + +/* a simple linear search. possible enancement: add a my_cb_nodes_index member + * ( index into cb_nodes, else -1 if not aggregator ) for faster lookups + * + * fd->hints->cb_nodes is the number of aggregators + * fd->hints->ranklist[] is an array of the ranks of aggregators + * + * might want to move this to adio/common/cb_config_list.c + */ +int is_aggregator(int rank, ADIO_File fd ) { + int i; + + if (fd->my_cb_nodes_index == -2) { + for (i=0; i< fd->hints->cb_nodes; i++ ) { + if ( rank == fd->hints->ranklist[i] ) { + fd->my_cb_nodes_index = i; + return 1; + } + } + fd->my_cb_nodes_index = -1; + } + else if (fd->my_cb_nodes_index != -1) + return 1; + + return 0; +} + +/* + * If file system implements some version of two-phase -- doesn't have to be + * generic -- we can still carry out the defered open optimization + */ +static int uses_generic_read(ADIO_File fd) +{ + if (ADIO_Feature(fd, ADIO_TWO_PHASE)) + return 1; + return 0; +} + +static int uses_generic_write(ADIO_File fd) +{ + if (ADIO_Feature(fd, ADIO_TWO_PHASE)) + return 1; + return 0; +} + +static int build_cb_config_list(ADIO_File fd, + MPI_Comm orig_comm, MPI_Comm comm, + int rank, int procs, int *error_code) +{ + ADIO_cb_name_array array; + int *tmp_ranklist; + int rank_ct; + char *value; + static char myname[] = "ADIO_OPEN cb_config_list"; + + /* gather the processor name array if we don't already have it */ + /* this has to be done early in ADIO_Open so that we can cache the name + * array in both the dup'd communicator (in case we want it later) and the + * original communicator */ + ADIOI_cb_gather_name_array(orig_comm, comm, &array); + +/* parse the cb_config_list and create a rank map on rank 0 */ + if (rank == 0) { + tmp_ranklist = (int *) ADIOI_Malloc(sizeof(int) * procs); + if (tmp_ranklist == NULL) { + *error_code = MPIO_Err_create_code(*error_code, + MPIR_ERR_RECOVERABLE, + myname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + return 0; + } + + rank_ct = ADIOI_cb_config_list_parse(fd->hints->cb_config_list, + array, tmp_ranklist, + fd->hints->cb_nodes); + + /* store the ranklist using the minimum amount of memory */ + if (rank_ct > 0) { + fd->hints->ranklist = (int *) ADIOI_Malloc(sizeof(int) * rank_ct); + memcpy(fd->hints->ranklist, tmp_ranklist, sizeof(int) * rank_ct); + } + ADIOI_Free(tmp_ranklist); + fd->hints->cb_nodes = rank_ct; + /* TEMPORARY -- REMOVE WHEN NO LONGER UPDATING INFO FOR FS-INDEP. */ + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", rank_ct); + ADIOI_Info_set(fd->info, "cb_nodes", value); + ADIOI_Free(value); + } + + ADIOI_cb_bcast_rank_map(fd); + if (fd->hints->cb_nodes <= 0) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**ioagnomatch", 0); + fd = ADIO_FILE_NULL; + } + return 0; +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_opencoll.c b/ompi/mca/io/romio314/romio/adio/common/ad_opencoll.c new file mode 100644 index 0000000000..467a322a34 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_opencoll.c @@ -0,0 +1,129 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2007 UChicago/Argonne LLC + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +/* Generic version of a "collective open". Assumes a "real" underlying + * file system (meaning no wonky consistency semantics like NFS). + * + * optimization: by having just one process create a file, close it, + * then have all N processes open it, we can possibly avoid contention + * for write locks on a directory for some file systems. + * + * Happy side-effect: exclusive create (error if file already exists) + * just falls out + * + * Note: this is not a "scalable open" (c.f. "The impact of file systems + * on MPI-IO scalability"). + */ + +void ADIOI_GEN_OpenColl(ADIO_File fd, int rank, + int access_mode, int *error_code) +{ + int orig_amode_excl, orig_amode_wronly; + MPI_Comm tmp_comm; + + orig_amode_excl = access_mode; + + if (access_mode & ADIO_CREATE ){ + if(rank == fd->hints->ranklist[0]) { + /* remove delete_on_close flag if set */ + if (access_mode & ADIO_DELETE_ON_CLOSE) + fd->access_mode = access_mode ^ ADIO_DELETE_ON_CLOSE; + else + fd->access_mode = access_mode; + + tmp_comm = fd->comm; + fd->comm = MPI_COMM_SELF; + (*(fd->fns->ADIOI_xxx_Open))(fd, error_code); + fd->comm = tmp_comm; + MPI_Bcast(error_code, 1, MPI_INT, \ + fd->hints->ranklist[0], fd->comm); + /* if no error, close the file and reopen normally below */ + if (*error_code == MPI_SUCCESS) + (*(fd->fns->ADIOI_xxx_Close))(fd, error_code); + + fd->access_mode = access_mode; /* back to original */ + } + else MPI_Bcast(error_code, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + + if (*error_code != MPI_SUCCESS) { + return; + } + else { + /* turn off CREAT (and EXCL if set) for real multi-processor open */ + access_mode ^= ADIO_CREATE; + if (access_mode & ADIO_EXCL) + access_mode ^= ADIO_EXCL; + } + } + fd->blksize = 1024*1024*4; /* this large default value should be good for + most file systems. any ROMIO driver is free + to stat the file and find an optimial value */ + + /* if we are doing deferred open, non-aggregators should return now */ + if (fd->hints->deferred_open ) { + if (!(fd->is_agg)) { + /* we might have turned off EXCL for the aggregators. + * restore access_mode that non-aggregators get the right + * value from get_amode */ + fd->access_mode = orig_amode_excl; + /* In file-system specific open, a driver might collect some + * information via stat(). Deferred open means not every process + * participates in fs-specific open, but they all participate in + * this open call. Broadcast a bit of information in case + * lower-level file system driver (e.g. 'bluegene') collected it + * (not all do)*/ + MPI_Bcast(&(fd->blksize), 1, MPI_LONG, fd->hints->ranklist[0], fd->comm); + *error_code = MPI_SUCCESS; + ADIOI_Assert(fd->blksize > 0); + return; + } + } + +/* For writing with data sieving, a read-modify-write is needed. If + the file is opened for write_only, the read will fail. Therefore, + if write_only, open the file as read_write, but record it as write_only + in fd, so that get_amode returns the right answer. */ + + /* observation from David Knaak: file systems that do not support data + * sieving do not need to change the mode */ + + orig_amode_wronly = access_mode; + if ( (access_mode & ADIO_WRONLY) && + ADIO_Feature(fd, ADIO_DATA_SIEVING_WRITES) ) { + access_mode = access_mode ^ ADIO_WRONLY; + access_mode = access_mode | ADIO_RDWR; + } + fd->access_mode = access_mode; + + (*(fd->fns->ADIOI_xxx_Open))(fd, error_code); + + /* if error, may be it was due to the change in amode above. + therefore, reopen with access mode provided by the user.*/ + fd->access_mode = orig_amode_wronly; + if (*error_code != MPI_SUCCESS) + (*(fd->fns->ADIOI_xxx_Open))(fd, error_code); + + /* if we turned off EXCL earlier, then we should turn it back on */ + if (fd->access_mode != orig_amode_excl) fd->access_mode = orig_amode_excl; + + /* broadcast a bit of information (blocksize for now) to all proceses in + * communicator, not just those who participated in open */ + MPI_Bcast(&(fd->blksize), 1, MPI_LONG, fd->hints->ranklist[0], fd->comm); + /* file domain code will get terribly confused in a hard-to-debug way if + * gpfs blocksize not sensible */ + ADIOI_Assert( fd->blksize > 0); + /* for deferred open: this process has opened the file (because if we are + * not an aggregaor and we are doing deferred open, we returned earlier)*/ + fd->is_open = 1; + +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_opencoll_failsafe.c b/ompi/mca/io/romio314/romio/adio/common/ad_opencoll_failsafe.c new file mode 100644 index 0000000000..e7ac8719e8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_opencoll_failsafe.c @@ -0,0 +1,88 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2007 UChicago/Argonne LLC + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + + +/* this "collective" open is useful for frankly broken file systems such + * as NFS where a create from one client might not be immediately + * visible on another */ + +void ADIOI_FAILSAFE_OpenColl(ADIO_File fd, int rank, + int access_mode, int *error_code) +{ + int orig_amode_excl, orig_amode_wronly; + + orig_amode_excl = access_mode; + if ((access_mode & ADIO_CREATE) && (access_mode & ADIO_EXCL)) { + /* the open should fail if the file exists. Only *1* process + * should check this. Otherwise, if all processes try to check + * and the file does not exist, one process will create the file + * and others who reach later will return error. */ + if(rank == fd->hints->ranklist[0]) { + fd->access_mode = access_mode; + (*(fd->fns->ADIOI_xxx_Open))(fd, error_code); + MPI_Bcast(error_code, 1, MPI_INT, \ + fd->hints->ranklist[0], fd->comm); + /* if no error, close the file and reopen normally below */ + if (*error_code == MPI_SUCCESS) + (*(fd->fns->ADIOI_xxx_Close))(fd, error_code); + } + else MPI_Bcast(error_code, 1, MPI_INT, + fd->hints->ranklist[0], fd->comm); + if (*error_code != MPI_SUCCESS) { + return; + } + else { + /* turn off EXCL for real open */ + access_mode = access_mode ^ ADIO_EXCL; + } + } + /* if we are doing deferred open, non-aggregators should return now */ + if (fd->hints->deferred_open && !(fd->is_agg)) { + /* we might have turned off EXCL for the aggregators. + * restore access_mode that non-aggregators get the right + * value from get_amode */ + fd->access_mode = orig_amode_excl; + *error_code = MPI_SUCCESS; + return; + } + +/* For writing with data sieving, a read-modify-write is needed. If + the file is opened for write_only, the read will fail. Therefore, + if write_only, open the file as read_write, but record it as write_only + in fd, so that get_amode returns the right answer. */ + + orig_amode_wronly = access_mode; + if (access_mode & ADIO_WRONLY) { + access_mode = access_mode ^ ADIO_WRONLY; + access_mode = access_mode | ADIO_RDWR; + } + fd->access_mode = access_mode; + + (*(fd->fns->ADIOI_xxx_Open))(fd, error_code); + + /* if error, may be it was due to the change in amode above. + therefore, reopen with access mode provided by the user.*/ + fd->access_mode = orig_amode_wronly; + if (*error_code != MPI_SUCCESS) + (*(fd->fns->ADIOI_xxx_Open))(fd, error_code); + + if(*error_code != MPI_SUCCESS) return; + /* if we turned off EXCL earlier, then we should turn it back on */ + if (fd->access_mode != orig_amode_excl) fd->access_mode = orig_amode_excl; + + /* for deferred open: this process has opened the file (because if we are + * not an aggregaor and we are doing deferred open, we returned earlier)*/ + fd->is_open = 1; +} + + + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_opencoll_scalable.c b/ompi/mca/io/romio314/romio/adio/common/ad_opencoll_scalable.c new file mode 100644 index 0000000000..1c472017f5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_opencoll_scalable.c @@ -0,0 +1,55 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2007 UChicago/Argonne LLC + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +/* + * Scalable open: for file systems capable of having one process + * create/open a file and broadcast the result to everyone else. + * - Does not need one process to create the file + * - Does not need special handling for CREATE|EXCL + */ +void ADIOI_SCALEABLE_OpenColl(ADIO_File fd, int rank, + int access_mode, int *error_code) +{ + int orig_amode_wronly; + + /* if we are doing deferred open, non-aggregators should return now */ + if (fd->hints->deferred_open && !(fd->is_agg)) { + *error_code = MPI_SUCCESS; + return; + } + + /* For writing with data sieving, a read-modify-write is needed. If + the file is opened for write_only, the read will fail. Therefore, + if write_only, open the file as read_write, but record it as + write_only in fd, so that get_amode returns the right answer. */ + + orig_amode_wronly = access_mode; + if (access_mode & ADIO_WRONLY) { + access_mode = access_mode ^ ADIO_WRONLY; + access_mode = access_mode | ADIO_RDWR; + } + fd->access_mode = access_mode; + + (*(fd->fns->ADIOI_xxx_Open))(fd, error_code); + + /* if error, may be it was due to the change in amode above. + therefore, reopen with access mode provided by the user.*/ + fd->access_mode = orig_amode_wronly; + if (*error_code != MPI_SUCCESS) + (*(fd->fns->ADIOI_xxx_Open))(fd, error_code); + + /* for deferred open: this process has opened the file (because if we are + * not an aggregaor and we are doing deferred open, we returned earlier)*/ + fd->is_open = 1; + +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_prealloc.c b/ompi/mca/io/romio314/romio/adio/common/ad_prealloc.c new file mode 100644 index 0000000000..9462f775aa --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_prealloc.c @@ -0,0 +1,91 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +/* this used to be implemented in every file system as an fcntl, but the code + * is identical for all file systems without a real "preallocate" system call. + * This naive approach will get the job done, but not in a terribly efficient + * manner. + */ +void ADIOI_GEN_Prealloc(ADIO_File fd, ADIO_Offset diskspace, int *error_code) +{ + ADIO_Offset curr_fsize, alloc_size, size, len, done, ntimes; + ADIO_Status status; + int i; + char *buf; + ADIO_Fcntl_t *fcntl_struct; + static char myname[] = "ADIOI_GEN_PREALLOC"; + + /* will be called by one process only */ + /* On file systems with no preallocation function, we have to + explicitly write + to allocate space. Since there could be holes in the file, + we need to read up to the current file size, write it back, + and then write beyond that depending on how much + preallocation is needed. + read/write in sizes of no more than ADIOI_PREALLOC_BUFSZ */ + + /*curr_fsize = fd->fp_ind; */ + fcntl_struct = (ADIO_Fcntl_t *) ADIOI_Malloc(sizeof(ADIO_Fcntl_t)); + ADIO_Fcntl(fd, ADIO_FCNTL_GET_FSIZE, fcntl_struct, error_code); + + curr_fsize = fcntl_struct->fsize; /* don't rely on fd->fp_ind: might be + working on a pre-existing file */ + alloc_size = diskspace; + + size = ADIOI_MIN(curr_fsize, alloc_size); + + ntimes = (size + ADIOI_PREALLOC_BUFSZ - 1)/ADIOI_PREALLOC_BUFSZ; + buf = (char *) ADIOI_Malloc(ADIOI_PREALLOC_BUFSZ); + done = 0; + + for (i=0; i curr_fsize) { + memset(buf, 0, ADIOI_PREALLOC_BUFSZ); + size = alloc_size - curr_fsize; + ntimes = (size + ADIOI_PREALLOC_BUFSZ - 1)/ADIOI_PREALLOC_BUFSZ; + for (i=0; i + +#include "adio.h" +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif +#ifdef ROMIO_GPFS +# include "adio/ad_gpfs/ad_gpfs_tuning.h" +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif + +void ADIOI_GEN_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; + ADIO_Offset len, bytes_xfered=0; + size_t rd_count; + static char myname[] = "ADIOI_GEN_READCONTIG"; +#ifdef ROMIO_GPFS + double io_time=0; +#endif + char *p; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5034, 0, NULL); +#endif + MPI_Type_size_x(datatype, &datatype_size); + len = datatype_size * (ADIO_Offset)count; + +#ifdef ROMIO_GPFS + io_time = MPI_Wtime(); + if (gpfsmpio_timing) { + gpfsmpio_prof_cr[ GPFSMPIO_CIO_DATA_SIZE ] += len; + } +#endif + + if (file_ptr_type == ADIO_INDIVIDUAL) { + offset = fd->fp_ind; + } + + p=buf; + while (bytes_xfered < len) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_a, 0, NULL ); +#endif + rd_count = len - bytes_xfered; + /* stupid FreeBSD and Darwin do not like a count larger than a signed + int, even though size_t is eight bytes... */ + if (rd_count > INT_MAX) + rd_count = INT_MAX; +#ifdef ROMIO_GPFS + if (gpfsmpio_devnullio) + err = pread(fd->null_fd, p, rd_count, offset+bytes_xfered); + else +#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)); + fd->fp_sys_posn = -1; + return; + } + /* --END ERROR HANDLING-- */ + if (err == 0) { + /* end of file */ + break; + } + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_read_b, 0, NULL ); +#endif + bytes_xfered += err; + p += err; + } +#ifdef ROMIO_GPFS + if (gpfsmpio_timing) gpfsmpio_prof_cr[ GPFSMPIO_CIO_T_POSI_RW ] += (MPI_Wtime() - io_time); +#endif + fd->fp_sys_posn = offset + bytes_xfered; + + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind += bytes_xfered; + } + +#ifdef HAVE_STATUS_SET_BYTES + /* what if we only read half a datatype? */ + /* bytes_xfered could be larger than int */ + if (err != -1) MPIR_Status_set_bytes(status, datatype, bytes_xfered); +#endif + + *error_code = MPI_SUCCESS; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5035, 0, NULL); +#endif +#ifdef ROMIO_GPFS + if (gpfsmpio_timing) gpfsmpio_prof_cr[ GPFSMPIO_CIO_T_MPIO_RW ] += (MPI_Wtime() - io_time); +#endif +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_read_coll.c b/ompi/mca/io/romio314/romio/adio/common/ad_read_coll.c new file mode 100644 index 0000000000..c5202a3e72 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_read_coll.c @@ -0,0 +1,1066 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +#ifdef USE_DBG_LOGGING + #define RDCOLL_DEBUG 1 +#endif +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + +/* prototypes of functions used for collective reads only. */ +static void ADIOI_Read_and_exch(ADIO_File fd, void *buf, MPI_Datatype + datatype, int nprocs, + int myrank, ADIOI_Access + *others_req, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, + ADIO_Offset + min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *buf_idx, int *error_code); +static void ADIOI_R_Exchange_data(ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, ADIO_Offset *offset_list, ADIO_Offset + *len_list, int *send_size, int *recv_size, + int *count, int *start_pos, + int *partial_send, + int *recd_from_proc, int nprocs, + int myrank, int + buftype_is_contig, int contig_access_count, + ADIO_Offset min_st_offset, + ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + ADIOI_Access *others_req, + int iter, + MPI_Aint buftype_extent, int *buf_idx); +static void ADIOI_Fill_user_buffer(ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, char **recv_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, + unsigned *recv_size, + MPI_Request *requests, MPI_Status *statuses, + int *recd_from_proc, int nprocs, + int contig_access_count, + ADIO_Offset min_st_offset, + ADIO_Offset fd_size, ADIO_Offset *fd_start, + ADIO_Offset *fd_end, + MPI_Aint buftype_extent); + + +void ADIOI_GEN_ReadStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ +/* Uses a generalized version of the extended two-phase method described + in "An Extended Two-Phase Method for Accessing Sections of + Out-of-Core Arrays", Rajeev Thakur and Alok Choudhary, + Scientific Programming, (5)4:301--317, Winter 1996. + http://www.mcs.anl.gov/home/thakur/ext2ph.ps */ + + ADIOI_Access *my_req; + /* array of nprocs structures, one for each other process in + whose file domain this process's request lies */ + + ADIOI_Access *others_req; + /* array of nprocs structures, one for each other process + whose request lies in this process's file domain. */ + + int i, filetype_is_contig, nprocs, nprocs_for_coll, myrank; + int contig_access_count=0, interleave_count = 0, buftype_is_contig; + int *count_my_req_per_proc, count_my_req_procs, count_others_req_procs; + ADIO_Offset start_offset, end_offset, orig_fp, fd_size, min_st_offset, off; + ADIO_Offset *offset_list = NULL, *st_offsets = NULL, *fd_start = NULL, + *fd_end = NULL, *end_offsets = NULL; + ADIO_Offset *len_list = NULL; + int *buf_idx = NULL; + +#ifdef HAVE_STATUS_SET_BYTES + MPI_Count bufsize, size; +#endif + + if (fd->hints->cb_pfr != ADIOI_HINT_DISABLE) { + ADIOI_IOStridedColl (fd, buf, count, ADIOI_READ, datatype, + file_ptr_type, offset, status, error_code); + return; + } + + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + /* number of aggregators, cb_nodes, is stored in the hints */ + nprocs_for_coll = fd->hints->cb_nodes; + orig_fp = fd->fp_ind; + + /* only check for interleaving if cb_read isn't disabled */ + if (fd->hints->cb_read != ADIOI_HINT_DISABLE) { + /* For this process's request, calculate the list of offsets and + lengths in the file and determine the start and end offsets. */ + + /* Note: end_offset points to the last byte-offset that will be accessed. + e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/ + + ADIOI_Calc_my_off_len(fd, count, datatype, file_ptr_type, offset, + &offset_list, &len_list, &start_offset, + &end_offset, &contig_access_count); + +#ifdef RDCOLL_DEBUG + for (i=0; icomm); + MPI_Allgather(&end_offset, 1, ADIO_OFFSET, end_offsets, 1, + ADIO_OFFSET, fd->comm); + + /* are the accesses of different processes interleaved? */ + for (i=1; ihints->cb_read == ADIOI_HINT_DISABLE + || (!interleave_count && (fd->hints->cb_read == ADIOI_HINT_AUTO))) + { + /* don't do aggregation */ + if (fd->hints->cb_read != ADIOI_HINT_DISABLE) { + ADIOI_Free(offset_list); + ADIOI_Free(len_list); + ADIOI_Free(st_offsets); + ADIOI_Free(end_offsets); + } + + fd->fp_ind = orig_fp; + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + if (buftype_is_contig && filetype_is_contig) { + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + (fd->etype_size) * offset; + ADIO_ReadContig(fd, buf, count, datatype, ADIO_EXPLICIT_OFFSET, + off, status, error_code); + } + else ADIO_ReadContig(fd, buf, count, datatype, ADIO_INDIVIDUAL, + 0, status, error_code); + } + else ADIO_ReadStrided(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); + + return; + } + + /* We're going to perform aggregation of I/O. Here we call + * ADIOI_Calc_file_domains() to determine what processes will handle I/O + * to what regions. We pass nprocs_for_coll into this function; it is + * used to determine how many processes will perform I/O, which is also + * the number of regions into which the range of bytes must be divided. + * These regions are called "file domains", or FDs. + * + * When this function returns, fd_start, fd_end, fd_size, and + * min_st_offset will be filled in. fd_start holds the starting byte + * location for each file domain. fd_end holds the ending byte location. + * min_st_offset holds the minimum byte location that will be accessed. + * + * Both fd_start[] and fd_end[] are indexed by an aggregator number; this + * needs to be mapped to an actual rank in the communicator later. + * + */ + ADIOI_Calc_file_domains(st_offsets, end_offsets, nprocs, + nprocs_for_coll, &min_st_offset, + &fd_start, &fd_end, + fd->hints->min_fdomain_size, &fd_size, + fd->hints->striping_unit); + + /* calculate where the portions of the access requests of this process + * are located in terms of the file domains. this could be on the same + * process or on other processes. this function fills in: + * count_my_req_procs - number of processes (including this one) for which + * this process has requests in their file domain + * count_my_req_per_proc - count of requests for each process, indexed + * by rank of the process + * my_req[] - array of data structures describing the requests to be + * performed by each process (including self). indexed by rank. + * buf_idx[] - array of locations into which data can be directly moved; + * this is only valid for contiguous buffer case + */ + ADIOI_Calc_my_req(fd, offset_list, len_list, contig_access_count, + min_st_offset, fd_start, fd_end, fd_size, + nprocs, &count_my_req_procs, + &count_my_req_per_proc, &my_req, + &buf_idx); + + /* perform a collective communication in order to distribute the + * data calculated above. fills in the following: + * count_others_req_procs - number of processes (including this + * one) which have requests in this process's file domain. + * count_others_req_per_proc[] - number of separate contiguous + * requests from proc i lie in this process's file domain. + */ + ADIOI_Calc_others_req(fd, count_my_req_procs, + count_my_req_per_proc, my_req, + nprocs, myrank, &count_others_req_procs, + &others_req); + + /* my_req[] and count_my_req_per_proc aren't needed at this point, so + * let's free the memory + */ + ADIOI_Free(count_my_req_per_proc); + for (i=0; ifp_sys_posn = -1; /* set it to null. */ +} + +void ADIOI_Calc_my_off_len(ADIO_File fd, int bufcount, MPI_Datatype + datatype, int file_ptr_type, ADIO_Offset + offset, ADIO_Offset **offset_list_ptr, ADIO_Offset + **len_list_ptr, ADIO_Offset *start_offset_ptr, + ADIO_Offset *end_offset_ptr, int + *contig_access_count_ptr) +{ + MPI_Count filetype_size, etype_size; + MPI_Count buftype_size; + int i, j, k; + ADIO_Offset i_offset; + ADIO_Offset frd_size=0, old_frd_size=0; + int st_index=0; + ADIO_Offset n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0; + ADIO_Offset bufsize; + ADIO_Offset sum, n_etypes_in_filetype, size_in_filetype; + int contig_access_count, filetype_is_contig; + ADIO_Offset *len_list; + MPI_Aint filetype_extent, filetype_lb; + ADIOI_Flatlist_node *flat_file; + ADIO_Offset *offset_list, off, end_offset=0, disp; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5028, 0, NULL); +#endif + +/* For this process's request, calculate the list of offsets and + lengths in the file and determine the start and end offsets. */ + + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + MPI_Type_size_x(fd->filetype, &filetype_size); + MPI_Type_extent(fd->filetype, &filetype_extent); + MPI_Type_lb(fd->filetype, &filetype_lb); + MPI_Type_size_x(datatype, &buftype_size); + etype_size = fd->etype_size; + + if ( ! filetype_size ) { + *contig_access_count_ptr = 0; + *offset_list_ptr = (ADIO_Offset *) ADIOI_Malloc(2*sizeof(ADIO_Offset)); + *len_list_ptr = (ADIO_Offset *) ADIOI_Malloc(2*sizeof(ADIO_Offset)); + /* 2 is for consistency. everywhere I malloc one more than needed */ + + offset_list = *offset_list_ptr; + len_list = *len_list_ptr; + offset_list[0] = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : + fd->disp + (ADIO_Offset)etype_size * offset; + len_list[0] = 0; + *start_offset_ptr = offset_list[0]; + *end_offset_ptr = offset_list[0] + len_list[0] - 1; + + return; + } + + if (filetype_is_contig) { + *contig_access_count_ptr = 1; + *offset_list_ptr = (ADIO_Offset *) ADIOI_Malloc(2*sizeof(ADIO_Offset)); + *len_list_ptr = (ADIO_Offset *) ADIOI_Malloc(2*sizeof(ADIO_Offset)); + /* 2 is for consistency. everywhere I malloc one more than needed */ + + offset_list = *offset_list_ptr; + len_list = *len_list_ptr; + offset_list[0] = (file_ptr_type == ADIO_INDIVIDUAL) ? fd->fp_ind : + fd->disp + (ADIO_Offset)etype_size * offset; + len_list[0] = (ADIO_Offset)bufcount * (ADIO_Offset)buftype_size; + *start_offset_ptr = offset_list[0]; + *end_offset_ptr = offset_list[0] + len_list[0] - 1; + + /* update file pointer */ + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = *end_offset_ptr + 1; + } + + else { + + /* First calculate what size of offset_list and len_list to allocate */ + + /* filetype already flattened in ADIO_Open or ADIO_Fcntl */ + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + disp = fd->disp; + +#ifdef RDCOLL_DEBUG + { + int ii; + DBG_FPRINTF(stderr, "flattened %3lld : ", flat_file->count ); + for (ii=0; iicount; ii++) { + DBG_FPRINTF(stderr, "%16lld:%-16lld", flat_file->indices[ii], flat_file->blocklens[ii] ); + } + DBG_FPRINTF(stderr, "\n" ); + } +#endif + 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; icount; 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; icount; 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 + n_filetypes* (ADIO_Offset)filetype_extent + + abs_off_in_filetype; + } + + /* calculate how much space to allocate for offset_list, len_list */ + + old_frd_size = frd_size; + contig_access_count = i_offset = 0; + j = st_index; + bufsize = (ADIO_Offset)buftype_size * (ADIO_Offset)bufcount; + frd_size = ADIOI_MIN(frd_size, bufsize); + while (i_offset < bufsize) { + if (frd_size) contig_access_count++; + i_offset += frd_size; + j = (j + 1) % flat_file->count; + frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset); + } + + /* allocate space for offset_list and len_list */ + + *offset_list_ptr = (ADIO_Offset *) + ADIOI_Malloc((contig_access_count+1)*sizeof(ADIO_Offset)); + *len_list_ptr = (ADIO_Offset *) ADIOI_Malloc((contig_access_count+1)*sizeof(ADIO_Offset)); + /* +1 to avoid a 0-size malloc */ + + offset_list = *offset_list_ptr; + len_list = *len_list_ptr; + + /* find start offset, end offset, and fill in offset_list and len_list */ + + *start_offset_ptr = offset; /* calculated above */ + + i_offset = k = 0; + j = st_index; + off = offset; + frd_size = ADIOI_MIN(old_frd_size, bufsize); + while (i_offset < bufsize) { + if (frd_size) { + offset_list[k] = off; + len_list[k] = frd_size; + k++; + } + i_offset += frd_size; + end_offset = off + frd_size - 1; + + /* Note: end_offset points to the last byte-offset that will be accessed. + e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/ + + 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; + /* hit end of flattened filetype; start at beginning + * again */ + } + off = disp + flat_file->indices[j] + + n_filetypes* (ADIO_Offset)filetype_extent; + frd_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset); + } + } + + /* update file pointer */ + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; + + *contig_access_count_ptr = contig_access_count; + *end_offset_ptr = end_offset; + } +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5029, 0, NULL); +#endif +} + +static void ADIOI_Read_and_exch(ADIO_File fd, void *buf, MPI_Datatype + datatype, int nprocs, + int myrank, ADIOI_Access + *others_req, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *buf_idx, int *error_code) +{ +/* Read in sizes of no more than coll_bufsize, an info parameter. + Send data to appropriate processes. + Place recd. data in user buf. + The idea is to reduce the amount of extra memory required for + collective I/O. If all data were read all at once, which is much + easier, it would require temp space more than the size of user_buf, + which is often unacceptable. For example, to read a distributed + array from a file, where each local array is 8Mbytes, requiring + at least another 8Mbytes of temp space is unacceptable. */ + + int i, j, m, ntimes, max_ntimes, buftype_is_contig; + ADIO_Offset st_loc=-1, end_loc=-1, off, done, real_off, req_off; + char *read_buf = NULL, *tmp_buf; + int *curr_offlen_ptr, *count, *send_size, *recv_size; + int *partial_send, *recd_from_proc, *start_pos; + /* Not convinced end_loc-st_loc couldn't be > int, so make these offsets*/ + ADIO_Offset real_size, size, for_curr_iter, for_next_iter; + int req_len, flag, rank; + MPI_Status status; + ADIOI_Flatlist_node *flat_buf=NULL; + MPI_Aint buftype_extent; + int coll_bufsize; + + *error_code = MPI_SUCCESS; /* changed below if error */ + /* only I/O errors are currently reported */ + +/* calculate the number of reads of size coll_bufsize + to be done by each process and the max among all processes. + That gives the no. of communication phases as well. + coll_bufsize is obtained from the hints object. */ + + coll_bufsize = fd->hints->cb_buffer_size; + + /* grab some initial values for st_loc and end_loc */ + for (i=0; i < nprocs; i++) { + if (others_req[i].count) { + st_loc = others_req[i].offsets[0]; + end_loc = others_req[i].offsets[0]; + break; + } + } + + /* now find the real values */ + for (i=0; i < nprocs; i++) + for (j=0; jcomm); + + read_buf = fd->io_buf; /* Allocated at open time */ + + curr_offlen_ptr = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* its use is explained below. calloc initializes to 0. */ + + count = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* to store count of how many off-len pairs per proc are satisfied + in an iteration. */ + + partial_send = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* if only a portion of the last off-len pair is sent to a process + in a particular iteration, the length sent is stored here. + calloc initializes to 0. */ + + send_size = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* total size of data to be sent to each proc. in an iteration */ + + recv_size = (int *) ADIOI_Malloc(nprocs * sizeof(int)); + /* total size of data to be recd. from each proc. in an iteration. + Of size nprocs so that I can use MPI_Alltoall later. */ + + recd_from_proc = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* amount of data recd. so far from each proc. Used in + ADIOI_Fill_user_buffer. initialized to 0 here. */ + + start_pos = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* used to store the starting value of curr_offlen_ptr[i] in + this iteration */ + + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + if (!buftype_is_contig) { + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + } + MPI_Type_extent(datatype, &buftype_extent); + + done = 0; + off = st_loc; + for_curr_iter = for_next_iter = 0; + + MPI_Comm_rank(fd->comm, &rank); + + for (m=0; mio_buf); + fd->io_buf = (char *) ADIOI_Malloc(for_next_iter+coll_bufsize); + memcpy(fd->io_buf, tmp_buf, for_next_iter); + read_buf = fd->io_buf; + ADIOI_Free(tmp_buf); + } + + off += size; + done += size; + } + + for (i=0; icomm); + + nprocs_recv = 0; + for (i=0; i < nprocs; i++) if (recv_size[i]) nprocs_recv++; + + nprocs_send = 0; + for (i=0; icomm, requests+j); + j++; + buf_idx[i] += recv_size[i]; + } + } + else { +/* allocate memory for recv_buf and post receives */ + recv_buf = (char **) ADIOI_Malloc(nprocs * sizeof(char*)); + for (i=0; i < nprocs; i++) + if (recv_size[i]) recv_buf[i] = + (char *) ADIOI_Malloc(recv_size[i]); + + j = 0; + for (i=0; i < nprocs; i++) + if (recv_size[i]) { + MPI_Irecv(recv_buf[i], recv_size[i], MPI_BYTE, i, + myrank+i+100*iter, fd->comm, requests+j); + j++; +#ifdef RDCOLL_DEBUG + DBG_FPRINTF(stderr, "node %d, recv_size %d, tag %d \n", + myrank, recv_size[i], myrank+i+100*iter); +#endif + } + } + +/* create derived datatypes and send data */ + + j = 0; + for (i=0; icomm, requests+nprocs_recv+j); + MPI_Type_free(&send_type); + if (partial_send[i]) others_req[i].lens[k] = tmp; + j++; + } + } + + statuses = (MPI_Status *) ADIOI_Malloc((nprocs_send+nprocs_recv+1) * \ + sizeof(MPI_Status)); + /* +1 to avoid a 0-size malloc */ + + /* wait on the receives */ + if (nprocs_recv) { +#ifdef NEEDS_MPI_TEST + j = 0; + while (!j) MPI_Testall(nprocs_recv, requests, &j, statuses); +#else + MPI_Waitall(nprocs_recv, requests, statuses); +#endif + + /* if noncontiguous, to the copies from the recv buffers */ + if (!buftype_is_contig) + ADIOI_Fill_user_buffer(fd, buf, flat_buf, recv_buf, + offset_list, len_list, (unsigned*)recv_size, + requests, statuses, recd_from_proc, + nprocs, contig_access_count, + min_st_offset, fd_size, fd_start, fd_end, + buftype_extent); + } + + /* wait on the sends*/ + MPI_Waitall(nprocs_send, requests+nprocs_recv, statuses+nprocs_recv); + + ADIOI_Free(statuses); + ADIOI_Free(requests); + + if (!buftype_is_contig) { + for (i=0; i < nprocs; i++) + if (recv_size[i]) ADIOI_Free(recv_buf[i]); + ADIOI_Free(recv_buf); + } +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5033, 0, NULL); +#endif +} + +#define ADIOI_BUF_INCR \ +{ \ + while (buf_incr) { \ + size_in_buf = ADIOI_MIN(buf_incr, flat_buf_sz); \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + buf_incr -= size_in_buf; \ + } \ +} + + +#define ADIOI_BUF_COPY \ +{ \ + while (size) { \ + size_in_buf = ADIOI_MIN(size, flat_buf_sz); \ + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + user_buf_idx) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + user_buf_idx)); \ + ADIOI_Assert(size_in_buf == (size_t)size_in_buf); \ + memcpy(((char *) buf) + user_buf_idx, \ + &(recv_buf[p][recv_buf_idx[p]]), size_in_buf); \ + recv_buf_idx[p] += size_in_buf; /* already tested (size_t)size_in_buf*/ \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + size -= size_in_buf; \ + buf_incr -= size_in_buf; \ + } \ + ADIOI_BUF_INCR \ +} + +static void ADIOI_Fill_user_buffer(ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, char **recv_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, + unsigned *recv_size, + MPI_Request *requests, MPI_Status *statuses, + int *recd_from_proc, int nprocs, + int contig_access_count, + ADIO_Offset min_st_offset, + ADIO_Offset fd_size, ADIO_Offset *fd_start, + ADIO_Offset *fd_end, + MPI_Aint buftype_extent) +{ + +/* this function is only called if buftype is not contig */ + + int i, p, flat_buf_idx; + ADIO_Offset flat_buf_sz, size_in_buf, buf_incr, size; + int n_buftypes; + ADIO_Offset off, len, rem_len, user_buf_idx; + /* Not sure unsigned is necessary, but it makes the math safer */ + unsigned *curr_from_proc, *done_from_proc, *recv_buf_idx; + + ADIOI_UNREFERENCED_ARG(requests); + ADIOI_UNREFERENCED_ARG(statuses); + +/* curr_from_proc[p] = amount of data recd from proc. p that has already + been accounted for so far + done_from_proc[p] = amount of data already recd from proc. p and + filled into user buffer in previous iterations + user_buf_idx = current location in user buffer + recv_buf_idx[p] = current location in recv_buf of proc. p */ + curr_from_proc = (unsigned *) ADIOI_Malloc(nprocs * sizeof(unsigned)); + done_from_proc = (unsigned *) ADIOI_Malloc(nprocs * sizeof(unsigned)); + recv_buf_idx = (unsigned *) ADIOI_Malloc(nprocs * sizeof(unsigned)); + + for (i=0; i < nprocs; i++) { + recv_buf_idx[i] = curr_from_proc[i] = 0; + done_from_proc[i] = recd_from_proc[i]; + } + + user_buf_idx = flat_buf->indices[0]; + flat_buf_idx = 0; + n_buftypes = 0; + flat_buf_sz = flat_buf->blocklens[0]; + + /* flat_buf_idx = current index into flattened buftype + flat_buf_sz = size of current contiguous component in + flattened buf */ + + for (i=0; i done_from_proc[p]) { + if (done_from_proc[p] > curr_from_proc[p]) { + size = ADIOI_MIN(curr_from_proc[p] + len - + done_from_proc[p], recv_size[p]-recv_buf_idx[p]); + buf_incr = done_from_proc[p] - curr_from_proc[p]; + ADIOI_BUF_INCR + buf_incr = curr_from_proc[p]+len-done_from_proc[p]; + ADIOI_Assert((done_from_proc[p] + size) == (unsigned)((ADIO_Offset)done_from_proc[p] + size)); + curr_from_proc[p] = done_from_proc[p] + size; + ADIOI_BUF_COPY + } + else { + size = ADIOI_MIN(len,recv_size[p]-recv_buf_idx[p]); + buf_incr = len; + ADIOI_Assert((curr_from_proc[p] + size) == (unsigned)((ADIO_Offset)curr_from_proc[p] + size)); + curr_from_proc[p] += (unsigned) size; + ADIOI_BUF_COPY + } + } + else { + ADIOI_Assert((curr_from_proc[p] + len) == (unsigned)((ADIO_Offset)curr_from_proc[p] + len)); + curr_from_proc[p] += (unsigned) len; + buf_incr = len; + ADIOI_BUF_INCR + } + } + else { + buf_incr = len; + ADIOI_BUF_INCR + } + off += len; + rem_len -= len; + } + } + for (i=0; i < nprocs; i++) + if (recv_size[i]) recd_from_proc[i] = curr_from_proc[i]; + + ADIOI_Free(curr_from_proc); + ADIOI_Free(done_from_proc); + ADIOI_Free(recv_buf_idx); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_read_str.c b/ompi/mca/io/romio314/romio/adio/common/ad_read_str.c new file mode 100644 index 0000000000..bec361b9d8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_read_str.c @@ -0,0 +1,407 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +#define ADIOI_BUFFERED_READ \ +{ \ + if (req_off >= readbuf_off + readbuf_len) { \ + readbuf_off = req_off; \ + readbuf_len = (unsigned) (ADIOI_MIN(max_bufsize, end_offset-readbuf_off+1));\ + ADIO_ReadContig(fd, readbuf, readbuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, readbuf_off, &status1, error_code); \ + if (*error_code != MPI_SUCCESS) return; \ + } \ + while (req_len > readbuf_off + readbuf_len - req_off) { \ + ADIOI_Assert((readbuf_off + readbuf_len - req_off) == (int) (readbuf_off + readbuf_len - req_off));\ + partial_read = (int) (readbuf_off + readbuf_len - req_off); \ + tmp_buf = (char *) ADIOI_Malloc(partial_read); \ + memcpy(tmp_buf, readbuf+readbuf_len-partial_read, partial_read); \ + ADIOI_Free(readbuf); \ + readbuf = (char *) ADIOI_Malloc(partial_read + max_bufsize); \ + memcpy(readbuf, tmp_buf, partial_read); \ + ADIOI_Free(tmp_buf); \ + readbuf_off += readbuf_len-partial_read; \ + readbuf_len = (unsigned) (partial_read + ADIOI_MIN(max_bufsize, \ + end_offset-readbuf_off+1)); \ + ADIO_ReadContig(fd, readbuf+partial_read, readbuf_len-partial_read, \ + MPI_BYTE, ADIO_EXPLICIT_OFFSET, readbuf_off+partial_read, \ + &status1, error_code); \ + if (*error_code != MPI_SUCCESS) return; \ + } \ + ADIOI_Assert(req_len == (size_t)req_len); \ + memcpy((char *)buf + userbuf_off, readbuf+req_off-readbuf_off, req_len); \ +} + + +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. */ + + 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 = off + bufsize - 1; + readbuf_off = off; + readbuf = (char *) ADIOI_Malloc(max_bufsize); + readbuf_len = (unsigned) (ADIOI_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; jcount; 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 */ + +/* 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; icount; 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; icount; 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 = ADIOI_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 = ADIOI_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 = ADIOI_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 = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset); + } + } + } + else { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + k = num = buf_count = 0; + i_offset = flat_buf->indices[0]; + j = st_index; + off = offset; + n_filetypes = st_n_filetypes; + frd_size = st_frd_size; + brd_size = flat_buf->blocklens[0]; + + while (num < bufsize) { + size = ADIOI_MIN(frd_size, brd_size); + if (size) { + /* lseek(fd->fd_sys, off, SEEK_SET); + err = read(fd->fd_sys, ((char *) buf) + i, size); */ + + req_off = off; + req_len = size; + userbuf_off = i_offset; + ADIOI_BUFFERED_READ + } + + new_frd_size = frd_size; + new_brd_size = brd_size; + + if (size == frd_size) { +/* reached end of contiguous block in file */ + 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; + + new_frd_size = flat_file->blocklens[j]; + if (size != brd_size) { + i_offset += size; + new_brd_size -= size; + } + } + + if (size == brd_size) { +/* reached end of contiguous block in memory */ + + k = (k + 1)%flat_buf->count; + buf_count++; + i_offset = ((ADIO_Offset)buftype_extent*(ADIO_Offset)(buf_count/flat_buf->count) + + flat_buf->indices[k]); + new_brd_size = flat_buf->blocklens[k]; + if (size != frd_size) { + off += size; + new_frd_size -= size; + } + } + ADIOI_Assert(((ADIO_Offset)num + size) == (unsigned)(num + size)); + num += size; + frd_size = new_frd_size; + brd_size = new_brd_size; + } + } + + 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); /* malloced in the buffered_read macro */ + } + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, 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 + by ADIOI_BUFFERED_READ. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_read_str_naive.c b/ompi/mca/io/romio314/romio/adio/common/ad_read_str_naive.c new file mode 100644 index 0000000000..d616bd883a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_read_str_naive.c @@ -0,0 +1,384 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +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; + ADIO_Offset size, brd_size, frd_size=0, req_len, sum; + int b_index; + int n_etypes_in_filetype; + ADIO_Offset n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0; + MPI_Count bufsize, filetype_size, buftype_size, size_in_filetype; + ADIO_Offset etype_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, 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_x(fd->filetype, &filetype_size); + if ( ! filetype_size ) { +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, buftype, 0); +#endif + *error_code = MPI_SUCCESS; + return; + } + + MPI_Type_extent(fd->filetype, &filetype_extent); + MPI_Type_size_x(buftype, &buftype_size); + MPI_Type_extent(buftype, &buftype_extent); + etype_size = fd->etype_size; + + ADIOI_Assert((buftype_size * count) == ((ADIO_Offset)buftype_size * (ADIO_Offset)count)); + 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) && ADIO_Feature(fd, ADIO_LOCKS)) + { + 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 = (ADIO_Offset)b_count*(ADIO_Offset)buftype_extent + + flat_buf->indices[b_index]; + req_off = off; + req_len = flat_buf->blocklens[b_index]; + + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + userbuf_off) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + userbuf_off)); + ADIOI_Assert(req_len == (int) req_len); + 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) && 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; + + } + + else { /* noncontiguous in file */ + int f_index, st_index = 0; + ADIO_Offset st_n_filetypes; + ADIO_Offset st_frd_size; + 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] + + n_filetypes*(ADIO_Offset)filetype_extent + + flat_file->blocklens[f_index] >= start_off) + { + /* this block contains our starting position */ + + st_index = f_index; + frd_size = disp + flat_file->indices[f_index] + + n_filetypes*(ADIO_Offset)filetype_extent + + flat_file->blocklens[f_index] - start_off; + flag = 1; + break; + } + } + } + } + else { + n_etypes_in_filetype = filetype_size/etype_size; + n_filetypes = offset / n_etypes_in_filetype; + etype_in_filetype = (int) (offset % n_etypes_in_filetype); + size_in_filetype = (unsigned)etype_in_filetype * (unsigned)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 + n_filetypes*(ADIO_Offset)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] + + n_filetypes*(ADIO_Offset)filetype_extent; + frd_size = ADIOI_MIN(flat_file->blocklens[f_index], + bufsize-(unsigned)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) && ADIO_Feature(fd, ADIO_LOCKS)) + { + 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; + + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + userbuf_off) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + userbuf_off)); + ADIOI_Assert(req_len == (int) req_len); + 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] + + n_filetypes*(ADIO_Offset)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] + + n_filetypes*(ADIO_Offset)filetype_extent; + frd_size = ADIOI_MIN(flat_file->blocklens[f_index], + bufsize-(unsigned)userbuf_off); + } + } + } + else { + ADIO_Offset i_offset, 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_offset = 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) { + ADIO_Offset 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_offset; + + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + userbuf_off) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + userbuf_off)); + ADIOI_Assert(req_len == (int) req_len); + 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] + + n_filetypes*(ADIO_Offset)filetype_extent; + + new_frd_size = flat_file->blocklens[f_index]; + if (size != brd_size) { + i_offset += 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_offset = 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) && (fd->file_system != ADIO_PVFS2)) + { + 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); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_resize.c b/ompi/mca/io/romio314/romio/adio/common/ad_resize.c new file mode 100644 index 0000000000..a6be2c1760 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_resize.c @@ -0,0 +1,38 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +void ADIOI_GEN_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) +{ + int err, rank; + static char myname[] = "ADIOI_GEN_RESIZE"; + + MPI_Comm_rank(fd->comm, &rank); + + /* first aggregator performs ftruncate() */ + if (rank == fd->hints->ranklist[0]) { + ADIOI_Assert(size == (off_t) size); + err = ftruncate(fd->fd_sys, (off_t)size); + } + + /* bcast return value */ + MPI_Bcast(&err, 1, MPI_INT, fd->hints->ranklist[0], fd->comm); + + /* --BEGIN ERROR HANDLING-- */ + if (err == -1) { + *error_code = ADIOI_Err_create_code(myname, fd->filename, errno); + return; + } + /* --END ERROR HANDLING-- */ + + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_seek.c b/ompi/mca/io/romio314/romio/adio/common/ad_seek.c new file mode 100644 index 0000000000..ceaf6f2d62 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_seek.c @@ -0,0 +1,86 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +ADIO_Offset ADIOI_GEN_SeekIndividual(ADIO_File fd, ADIO_Offset offset, + int whence, int *error_code) +{ +/* implemented for whence=SEEK_SET only. SEEK_CUR and SEEK_END must + be converted to the equivalent with SEEK_SET before calling this + routine. */ +/* offset is in units of etype relative to the filetype */ + + ADIO_Offset off; + ADIOI_Flatlist_node *flat_file; + + int i; + ADIO_Offset n_etypes_in_filetype, n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0; + ADIO_Offset size_in_filetype, sum; + MPI_Count filetype_size, etype_size; + int filetype_is_contig; + MPI_Aint filetype_extent; + + ADIOI_UNREFERENCED_ARG(whence); + + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + etype_size = fd->etype_size; + + if (filetype_is_contig) off = fd->disp + etype_size * offset; + else { + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + + MPI_Type_extent(fd->filetype, &filetype_extent); + MPI_Type_size_x(fd->filetype, &filetype_size); + if ( ! filetype_size ) { + /* Since offset relative to the filetype size, we can't + do compute the offset when that result is zero. + Return zero for the offset for now */ + *error_code = MPI_SUCCESS; + return 0; + } + + 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; icount; i++) { + sum += flat_file->blocklens[i]; + if (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 */ + off = fd->disp + n_filetypes * filetype_extent + + abs_off_in_filetype; + } + +/* + * we used to call lseek here and update both fp_ind and fp_sys_posn, but now + * we don't seek and only update fp_ind (ROMIO's idea of where we are in the + * file). We leave the system file descriptor and fp_sys_posn alone. + * The fs-specifc ReadContig and WriteContig will seek to the correct place in + * the file before reading/writing if the 'offset' parameter doesn't match + * fp_sys_posn + */ + fd->fp_ind = off; + + *error_code = MPI_SUCCESS; + + return off; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_set_sh_fp.c b/ompi/mca/io/romio314/romio/adio/common/ad_set_sh_fp.c new file mode 100644 index 0000000000..c55f2efe5a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_set_sh_fp.c @@ -0,0 +1,45 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +/* set the shared file pointer to "offset" etypes relative to the current + view */ + +void ADIOI_NFS_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, int *error_code); + +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)); +} + diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_set_view.c b/ompi/mca/io/romio314/romio/adio/common/ad_set_view.c new file mode 100644 index 0000000000..31aa6c6dd5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_set_view.c @@ -0,0 +1,77 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +/* this used to be implemented in every file system as an fcntl. It makes + * deferred open easier if we know ADIO_Fcntl will always need a file to really + * be open. set_view doesn't modify anything related to the open files. + */ +void ADIO_Set_view(ADIO_File fd, ADIO_Offset disp, MPI_Datatype etype, + MPI_Datatype filetype, MPI_Info info, int *error_code) +{ + int combiner, i, j, k, err, filetype_is_contig; + MPI_Datatype copy_etype, copy_filetype; + ADIOI_Flatlist_node *flat_file; + /* free copies of old etypes and filetypes and delete flattened + version of filetype if necessary */ + + MPI_Type_get_envelope(fd->etype, &i, &j, &k, &combiner); + if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->etype)); + + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + if (!filetype_is_contig) ADIOI_Delete_flattened(fd->filetype); + + MPI_Type_get_envelope(fd->filetype, &i, &j, &k, &combiner); + if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->filetype)); + + /* set new info */ + ADIO_SetInfo(fd, info, &err); + + /* set new etypes and filetypes */ + + MPI_Type_get_envelope(etype, &i, &j, &k, &combiner); + if (combiner == MPI_COMBINER_NAMED) fd->etype = etype; + else { + MPI_Type_contiguous(1, etype, ©_etype); + MPI_Type_commit(©_etype); + fd->etype = copy_etype; + } + MPI_Type_get_envelope(filetype, &i, &j, &k, &combiner); + if (combiner == MPI_COMBINER_NAMED) + fd->filetype = filetype; + else { + MPI_Type_contiguous(1, filetype, ©_filetype); + MPI_Type_commit(©_filetype); + fd->filetype = copy_filetype; + ADIOI_Flatten_datatype(fd->filetype); + /* this function will not flatten the filetype if it turns out + to be all contiguous. */ + } + + MPI_Type_size_x(fd->etype, &(fd->etype_size)); + fd->disp = disp; + + /* reset MPI-IO file pointer to point to the first byte that can + be accessed in this view. */ + + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + if (filetype_is_contig) fd->fp_ind = disp; + else { + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) + flat_file = flat_file->next; + for (i=0; icount; i++) { + if (flat_file->blocklens[i]) { + fd->fp_ind = disp + flat_file->indices[i]; + break; + } + } + } + *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_subarray.c b/ompi/mca/io/romio314/romio/adio/common/ad_subarray.c new file mode 100644 index 0000000000..c4597646ad --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_subarray.c @@ -0,0 +1,98 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +int ADIO_Type_create_subarray(int ndims, + int *array_of_sizes, + int *array_of_subsizes, + int *array_of_starts, + int order, + MPI_Datatype oldtype, + MPI_Datatype *newtype) +{ + MPI_Aint extent, disps[3], size; + int i, blklens[3]; + MPI_Datatype tmp1, tmp2, types[3]; + + MPI_Type_extent(oldtype, &extent); + + if (order == MPI_ORDER_FORTRAN) { + /* dimension 0 changes fastest */ + if (ndims == 1) { + MPI_Type_contiguous(array_of_subsizes[0], oldtype, &tmp1); + } + else { + MPI_Type_vector(array_of_subsizes[1], + array_of_subsizes[0], + array_of_sizes[0], oldtype, &tmp1); + + size = (MPI_Aint)array_of_sizes[0]*extent; + for (i=2; i=0; i--) { + size *= (MPI_Aint)array_of_sizes[i+1]; + MPI_Type_hvector(array_of_subsizes[i], 1, size, tmp1, &tmp2); + MPI_Type_free(&tmp1); + tmp1 = tmp2; + } + } + + /* add displacement and UB */ + disps[1] = array_of_starts[ndims-1]; + size = 1; + for (i=ndims-2; i>=0; i--) { + size *= (MPI_Aint)array_of_sizes[i+1]; + disps[1] += size*(MPI_Aint)array_of_starts[i]; + } + } + + disps[1] *= extent; + + disps[2] = extent; + for (i=0; i +/* Function for running in another thread for doing the file reading while the + * main thread is doing data aggregation - useful only when multiple rounds are + * needed due to file size relative to the read buffer size and number of + * aggregators */ + +void *ADIOI_IO_Thread_Func(void *vptr_args) { + ADIOI_IO_ThreadFuncData *args = (ADIOI_IO_ThreadFuncData*)vptr_args; + + ADIOI_Assert(args->size == (int)(args->size)); + + if (args->io_kind == ADIOI_READ) { + ADIO_ReadContig(args->fd, args->buf, args->size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, args->offset, + &(args->status), &(args->error_code)); + } else { + ADIO_WriteContig(args->fd, args->buf, args->size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, args->offset, + &(args->status), &(args->error_code)); + } + pthread_exit(&(args->error_code)); + return NULL; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_wait.c b/ompi/mca/io/romio314/romio/adio/common/ad_wait.c new file mode 100644 index 0000000000..2112ee8fb6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_wait.c @@ -0,0 +1,47 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + +/* Workaround for incomplete set of definitions if __REDIRECT is not + defined and large file support is used in aio.h */ +#if !defined(__REDIRECT) && defined(__USE_FILE_OFFSET64) +#define aiocb aiocb64 +#endif + +/* ADIOI_GEN_IOComplete + * + * This code handles two distinct cases. If ROMIO_HAVE_WORKING_AIO is + * not defined, then I/O was performed by a blocking call already. In + * that case all we need to do is optionally set the bytes in the + * status structure and free the request. + * + * If ROMIO_HAVE_WORKING_AIO is defined, then we may need to wait for I/O + * to complete. + */ +void ADIOI_GEN_IOComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + return; + +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_wait_fake.c b/ompi/mca/io/romio314/romio/adio/common/ad_wait_fake.c new file mode 100644 index 0000000000..16947baa1f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_wait_fake.c @@ -0,0 +1,20 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +/* Generic implementation of ReadComplete/WriteComplete simply sets the + * bytes field in the status structure and frees the request. + * + * Same function is used for both reads and writes. + */ +void ADIOI_FAKE_IOComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code) +{ + *error_code = MPI_SUCCESS; + return; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_write.c b/ompi/mca/io/romio314/romio/adio/common/ad_write.c new file mode 100644 index 0000000000..ad318e4117 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_write.c @@ -0,0 +1,119 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + + +#ifdef _STDC_C99 +#define _XOPEN_SOURCE 600 +#else +#define _XOPEN_SOURCE 500 +#endif +#include + +#include "adio.h" +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + +#ifdef ROMIO_GPFS +#include "adio/ad_gpfs/ad_gpfs_tuning.h" +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif + + +void ADIOI_GEN_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; + ADIO_Offset len, bytes_xfered=0; + size_t wr_count; + static char myname[] = "ADIOI_GEN_WRITECONTIG"; +#ifdef ROMIO_GPFS + double io_time=0; +#endif + char * p; + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5036, 0, NULL); +#endif + + MPI_Type_size_x(datatype, &datatype_size); + len = (ADIO_Offset)datatype_size * (ADIO_Offset)count; + +#ifdef ROMIO_GPFS + io_time = MPI_Wtime(); + if (gpfsmpio_timing) { + gpfsmpio_prof_cw[ GPFSMPIO_CIO_DATA_SIZE ] += len; + } +#endif + + 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; + /* Frustrating! FreeBSD and OS X do not like a count larger than 2^31 */ + if (wr_count > INT_MAX) + wr_count = INT_MAX; + +#ifdef ROMIO_GPFS + if (gpfsmpio_devnullio) + err = pwrite(fd->null_fd, p, wr_count, offset+bytes_xfered); + else +#endif + 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 + bytes_xfered += err; + p += err; + } + +#ifdef ROMIO_GPFS + if (gpfsmpio_timing) gpfsmpio_prof_cw[ GPFSMPIO_CIO_T_POSI_RW ] += (MPI_Wtime() - io_time); +#endif + fd->fp_sys_posn = offset + bytes_xfered; + + if (file_ptr_type == ADIO_INDIVIDUAL) { + fd->fp_ind += bytes_xfered; + } + +#ifdef ROMIO_GPFS + if (gpfsmpio_timing) gpfsmpio_prof_cw[ GPFSMPIO_CIO_T_MPIO_RW ] += (MPI_Wtime() - io_time); +#endif + +#ifdef HAVE_STATUS_SET_BYTES + /* bytes_xfered could be larger than int */ + if (err != -1 && status) MPIR_Status_set_bytes(status, datatype, bytes_xfered); +#endif + + *error_code = MPI_SUCCESS; +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5037, 0, NULL); +#endif +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_write_coll.c b/ompi/mca/io/romio314/romio/adio/common/ad_write_coll.c new file mode 100644 index 0000000000..d585f9e09f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_write_coll.c @@ -0,0 +1,1088 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +#ifdef AGGREGATION_PROFILE +#include "mpe.h" +#endif + +/* prototypes of functions used for collective writes only. */ +static void ADIOI_Exch_and_write(ADIO_File fd, void *buf, MPI_Datatype + datatype, int nprocs, int myrank, + ADIOI_Access + *others_req, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *buf_idx, int *error_code); +static void ADIOI_W_Exchange_data(ADIO_File fd, void *buf, char *write_buf, + ADIOI_Flatlist_node *flat_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, int *send_size, + int *recv_size, ADIO_Offset off, int size, + int *count, int *start_pos, int *partial_recv, + int *sent_to_proc, int nprocs, + int myrank, int + buftype_is_contig, int contig_access_count, + ADIO_Offset min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + ADIOI_Access *others_req, + int *send_buf_idx, int *curr_to_proc, + int *done_to_proc, int *hole, int iter, + MPI_Aint buftype_extent, int *buf_idx, int *error_code); +static void ADIOI_Fill_send_buffer(ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, char **send_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, int *send_size, + MPI_Request *requests, int *sent_to_proc, + int nprocs, int myrank, + int contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *send_buf_idx, int *curr_to_proc, + int *done_to_proc, int iter, + MPI_Aint buftype_extent); +void ADIOI_Heap_merge(ADIOI_Access *others_req, int *count, + ADIO_Offset *srt_off, int *srt_len, int *start_pos, + int nprocs, int nprocs_recv, int total_elements); + + +void ADIOI_GEN_WriteStridedColl(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code) +{ +/* Uses a generalized version of the extended two-phase method described + in "An Extended Two-Phase Method for Accessing Sections of + Out-of-Core Arrays", Rajeev Thakur and Alok Choudhary, + Scientific Programming, (5)4:301--317, Winter 1996. + http://www.mcs.anl.gov/home/thakur/ext2ph.ps */ + + ADIOI_Access *my_req; + /* array of nprocs access structures, one for each other process in + whose file domain this process's request lies */ + + ADIOI_Access *others_req; + /* array of nprocs access structures, one for each other process + whose request lies in this process's file domain. */ + + int i, filetype_is_contig, nprocs, nprocs_for_coll, myrank; + int contig_access_count=0, interleave_count = 0, buftype_is_contig; + int *count_my_req_per_proc, count_my_req_procs, count_others_req_procs; + ADIO_Offset orig_fp, start_offset, end_offset, fd_size, min_st_offset, off; + ADIO_Offset *offset_list = NULL, *st_offsets = NULL, *fd_start = NULL, + *fd_end = NULL, *end_offsets = NULL; + int *buf_idx = NULL; + ADIO_Offset *len_list = NULL; + int old_error, tmp_error; + + if (fd->hints->cb_pfr != ADIOI_HINT_DISABLE) { + /* Cast away const'ness as the below function is used for read + * and write */ + ADIOI_IOStridedColl (fd, (char *) buf, count, ADIOI_WRITE, datatype, + file_ptr_type, offset, status, error_code); + return; + } + + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + +/* the number of processes that actually perform I/O, nprocs_for_coll, + * is stored in the hints off the ADIO_File structure + */ + nprocs_for_coll = fd->hints->cb_nodes; + orig_fp = fd->fp_ind; + + /* only check for interleaving if cb_write isn't disabled */ + if (fd->hints->cb_write != ADIOI_HINT_DISABLE) { + /* For this process's request, calculate the list of offsets and + lengths in the file and determine the start and end offsets. */ + + /* Note: end_offset points to the last byte-offset that will be accessed. + e.g., if start_offset=0 and 100 bytes to be read, end_offset=99*/ + + ADIOI_Calc_my_off_len(fd, count, datatype, file_ptr_type, offset, + &offset_list, &len_list, &start_offset, + &end_offset, &contig_access_count); + + /* each process communicates its start and end offsets to other + processes. The result is an array each of start and end offsets stored + in order of process rank. */ + + st_offsets = (ADIO_Offset *) ADIOI_Malloc(nprocs*sizeof(ADIO_Offset)); + end_offsets = (ADIO_Offset *) ADIOI_Malloc(nprocs*sizeof(ADIO_Offset)); + + MPI_Allgather(&start_offset, 1, ADIO_OFFSET, st_offsets, 1, + ADIO_OFFSET, fd->comm); + MPI_Allgather(&end_offset, 1, ADIO_OFFSET, end_offsets, 1, + ADIO_OFFSET, fd->comm); + + /* are the accesses of different processes interleaved? */ + for (i=1; ihints->cb_write == ADIOI_HINT_DISABLE || + (!interleave_count && (fd->hints->cb_write == ADIOI_HINT_AUTO))) + { + /* use independent accesses */ + if (fd->hints->cb_write != ADIOI_HINT_DISABLE) { + ADIOI_Free(offset_list); + ADIOI_Free(len_list); + ADIOI_Free(st_offsets); + ADIOI_Free(end_offsets); + } + + fd->fp_ind = orig_fp; + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + + if (buftype_is_contig && filetype_is_contig) { + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + (ADIO_Offset)(fd->etype_size) * offset; + ADIO_WriteContig(fd, buf, count, datatype, + ADIO_EXPLICIT_OFFSET, + off, status, error_code); + } + else ADIO_WriteContig(fd, buf, count, datatype, ADIO_INDIVIDUAL, + 0, status, error_code); + } + else ADIO_WriteStrided(fd, buf, count, datatype, file_ptr_type, + offset, status, error_code); + + return; + } + +/* Divide the I/O workload among "nprocs_for_coll" processes. This is + done by (logically) dividing the file into file domains (FDs); each + process may directly access only its own file domain. */ + + ADIOI_Calc_file_domains(st_offsets, end_offsets, nprocs, + nprocs_for_coll, &min_st_offset, + &fd_start, &fd_end, + fd->hints->min_fdomain_size, &fd_size, + fd->hints->striping_unit); + + +/* calculate what portions of the access requests of this process are + located in what file domains */ + + ADIOI_Calc_my_req(fd, offset_list, len_list, contig_access_count, + min_st_offset, fd_start, fd_end, fd_size, + nprocs, &count_my_req_procs, + &count_my_req_per_proc, &my_req, + &buf_idx); + +/* based on everyone's my_req, calculate what requests of other + processes lie in this process's file domain. + count_others_req_procs = number of processes whose requests lie in + this process's file domain (including this process itself) + count_others_req_per_proc[i] indicates how many separate contiguous + requests of proc. i lie in this process's file domain. */ + + ADIOI_Calc_others_req(fd, count_my_req_procs, + count_my_req_per_proc, my_req, + nprocs, myrank, + &count_others_req_procs, &others_req); + + ADIOI_Free(count_my_req_per_proc); + for (i=0; i < nprocs; i++) { + if (my_req[i].count) { + ADIOI_Free(my_req[i].offsets); + ADIOI_Free(my_req[i].lens); + } + } + ADIOI_Free(my_req); + +/* exchange data and write in sizes of no more than coll_bufsize. */ + /* Cast away const'ness for the below function */ + ADIOI_Exch_and_write(fd, (char *) buf, datatype, nprocs, myrank, + others_req, offset_list, + len_list, contig_access_count, min_st_offset, + fd_size, fd_start, fd_end, buf_idx, error_code); + + /* If this collective write is followed by an independent write, + * it's possible to have those subsequent writes on other processes + * race ahead and sneak in before the read-modify-write completes. + * We carry out a collective communication at the end here so no one + * can start independent i/o before collective I/O completes. + * + * need to do some gymnastics with the error codes so that if something + * went wrong, all processes report error, but if a process has a more + * specific error code, we can still have that process report the + * additional information */ + + old_error = *error_code; + if (*error_code != MPI_SUCCESS) *error_code = MPI_ERR_IO; + + /* optimization: if only one process performing i/o, we can perform + * a less-expensive Bcast */ +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_postwrite_a, 0, NULL ); +#endif + if (fd->hints->cb_nodes == 1) + MPI_Bcast(error_code, 1, MPI_INT, + fd->hints->ranklist[0], fd->comm); + else { + tmp_error = *error_code; + MPI_Allreduce(&tmp_error, error_code, 1, MPI_INT, + MPI_MAX, fd->comm); + } +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_postwrite_b, 0, NULL ); +#endif +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5012, 0, NULL); +#endif + + if ( (old_error != MPI_SUCCESS) && (old_error != MPI_ERR_IO) ) + *error_code = old_error; + + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); + +/* free all memory allocated for collective I/O */ + + for (i=0; ifp_sys_posn = -1; /* set it to null. */ +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5013, 0, NULL); +#endif +} + + + +/* If successful, error_code is set to MPI_SUCCESS. Otherwise an error + * code is created and returned in error_code. + */ +static void ADIOI_Exch_and_write(ADIO_File fd, void *buf, MPI_Datatype + datatype, int nprocs, + int myrank, + ADIOI_Access + *others_req, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int contig_access_count, + ADIO_Offset min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *buf_idx, int *error_code) +{ +/* Send data to appropriate processes and write in sizes of no more + than coll_bufsize. + The idea is to reduce the amount of extra memory required for + collective I/O. If all data were written all at once, which is much + easier, it would require temp space more than the size of user_buf, + which is often unacceptable. For example, to write a distributed + array to a file, where each local array is 8Mbytes, requiring + at least another 8Mbytes of temp space is unacceptable. */ + + /* Not convinced end_loc-st_loc couldn't be > int, so make these offsets*/ + ADIO_Offset size=0; + int hole, i, j, m, ntimes, max_ntimes, buftype_is_contig; + ADIO_Offset st_loc=-1, end_loc=-1, off, done, req_off; + char *write_buf=NULL; + int *curr_offlen_ptr, *count, *send_size, req_len, *recv_size; + int *partial_recv, *sent_to_proc, *start_pos, flag; + int *send_buf_idx, *curr_to_proc, *done_to_proc; + MPI_Status status; + ADIOI_Flatlist_node *flat_buf=NULL; + MPI_Aint buftype_extent; + int info_flag, coll_bufsize; + char *value; + static char myname[] = "ADIOI_EXCH_AND_WRITE"; + + *error_code = MPI_SUCCESS; /* changed below if error */ + /* only I/O errors are currently reported */ + +/* calculate the number of writes of size coll_bufsize + to be done by each process and the max among all processes. + That gives the no. of communication phases as well. */ + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + ADIOI_Info_get(fd->info, "cb_buffer_size", MPI_MAX_INFO_VAL, value, + &info_flag); + coll_bufsize = atoi(value); + ADIOI_Free(value); + + + for (i=0; i < nprocs; i++) { + if (others_req[i].count) { + st_loc = others_req[i].offsets[0]; + end_loc = others_req[i].offsets[0]; + break; + } + } + + for (i=0; i < nprocs; i++) + for (j=0; j < others_req[i].count; j++) { + st_loc = ADIOI_MIN(st_loc, others_req[i].offsets[j]); + end_loc = ADIOI_MAX(end_loc, (others_req[i].offsets[j] + + others_req[i].lens[j] - 1)); + } + +/* ntimes=ceiling_div(end_loc - st_loc + 1, coll_bufsize)*/ + + ntimes = (int) ((end_loc - st_loc + coll_bufsize)/coll_bufsize); + + if ((st_loc==-1) && (end_loc==-1)) { + ntimes = 0; /* this process does no writing. */ + } + + MPI_Allreduce(&ntimes, &max_ntimes, 1, MPI_INT, MPI_MAX, + fd->comm); + + write_buf = fd->io_buf; + + curr_offlen_ptr = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* its use is explained below. calloc initializes to 0. */ + + count = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* to store count of how many off-len pairs per proc are satisfied + in an iteration. */ + + partial_recv = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* if only a portion of the last off-len pair is recd. from a process + in a particular iteration, the length recd. is stored here. + calloc initializes to 0. */ + + send_size = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* total size of data to be sent to each proc. in an iteration. + Of size nprocs so that I can use MPI_Alltoall later. */ + + recv_size = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* total size of data to be recd. from each proc. in an iteration.*/ + + sent_to_proc = (int *) ADIOI_Calloc(nprocs, sizeof(int)); + /* amount of data sent to each proc so far. Used in + ADIOI_Fill_send_buffer. initialized to 0 here. */ + + send_buf_idx = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + curr_to_proc = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + done_to_proc = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* Above three are used in ADIOI_Fill_send_buffer*/ + + start_pos = (int *) ADIOI_Malloc(nprocs*sizeof(int)); + /* used to store the starting value of curr_offlen_ptr[i] in + this iteration */ + + ADIOI_Datatype_iscontig(datatype, &buftype_is_contig); + if (!buftype_is_contig) { + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + } + MPI_Type_extent(datatype, &buftype_extent); + + +/* I need to check if there are any outstanding nonblocking writes to + the file, which could potentially interfere with the writes taking + place in this collective write call. Since this is not likely to be + common, let me do the simplest thing possible here: Each process + completes all pending nonblocking operations before completing. */ + + /*ADIOI_Complete_async(error_code); + if (*error_code != MPI_SUCCESS) return; + MPI_Barrier(fd->comm); + */ + + done = 0; + off = st_loc; + + for (m=0; m < ntimes; m++) { + /* go through all others_req and check which will be satisfied + by the current write */ + + /* Note that MPI guarantees that displacements in filetypes are in + monotonically nondecreasing order and that, for writes, the + filetypes cannot specify overlapping regions in the file. This + simplifies implementation a bit compared to reads. */ + + /* off = start offset in the file for the data to be written in + this iteration + size = size of data written (bytes) corresponding to off + req_off = off in file for a particular contiguous request + minus what was satisfied in previous iteration + req_size = size corresponding to req_off */ + + /* first calculate what should be communicated */ + + for (i=0; i < nprocs; i++) count[i] = recv_size[i] = 0; + + size = ADIOI_MIN((unsigned)coll_bufsize, end_loc-st_loc+1-done); + + for (i=0; i < nprocs; i++) { + if (others_req[i].count) { + start_pos[i] = curr_offlen_ptr[i]; + for (j=curr_offlen_ptr[i]; jcomm); + + /* create derived datatypes for recv */ + + nprocs_recv = 0; + for (i=0; i srt_len[0]) srt_len[0] = new_len; + } + else + break; + } + if (i < sum || size != srt_len[0]) /* hole in middle or end */ + *hole = 1; + } + + ADIOI_Free(srt_off); + ADIOI_Free(srt_len); + } + + if (nprocs_recv) { + if (*hole) { + ADIO_ReadContig(fd, write_buf, size, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, off, &status, &err); + /* --BEGIN ERROR HANDLING-- */ + if (err != MPI_SUCCESS) { + *error_code = MPIO_Err_create_code(err, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_IO, + "**ioRMWrdwr", 0); + return; + } + /* --END ERROR HANDLING-- */ + } + } + + nprocs_send = 0; + for (i=0; i < nprocs; i++) if (send_size[i]) nprocs_send++; + + if (fd->atomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + requests = (MPI_Request *) + ADIOI_Malloc((nprocs_send+1)*sizeof(MPI_Request)); + send_req = requests; + } + else { + requests = (MPI_Request *) + ADIOI_Malloc((nprocs_send+nprocs_recv+1)*sizeof(MPI_Request)); + /* +1 to avoid a 0-size malloc */ + + /* post receives */ + j = 0; + for (i=0; icomm, requests+j); + j++; + } + } + send_req = requests + nprocs_recv; + } + +/* post sends. if buftype_is_contig, data can be directly sent from + user buf at location given by buf_idx. else use send_buf. */ + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5032, 0, NULL); +#endif + if (buftype_is_contig) { + j = 0; + for (i=0; i < nprocs; i++) + if (send_size[i]) { + MPI_Isend(((char *) buf) + buf_idx[i], send_size[i], + MPI_BYTE, i, myrank+i+100*iter, fd->comm, + send_req+j); + j++; + buf_idx[i] += send_size[i]; + } + } + else if (nprocs_send) { + /* buftype is not contig */ + send_buf = (char **) ADIOI_Malloc(nprocs*sizeof(char*)); + for (i=0; i < nprocs; i++) + if (send_size[i]) + send_buf[i] = (char *) ADIOI_Malloc(send_size[i]); + + ADIOI_Fill_send_buffer(fd, buf, flat_buf, send_buf, + offset_list, len_list, send_size, + send_req, + sent_to_proc, nprocs, myrank, + contig_access_count, + min_st_offset, fd_size, fd_start, fd_end, + send_buf_idx, curr_to_proc, done_to_proc, iter, + buftype_extent); + /* the send is done in ADIOI_Fill_send_buffer */ + } + + if (fd->atomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + j = 0; + for (i=0; icomm, &wkl_status); + j++; + } + } + } + + for (i=0; iatomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + statuses = (MPI_Status *) ADIOI_Malloc((nprocs_send+1) * \ + sizeof(MPI_Status)); + /* +1 to avoid a 0-size malloc */ + } + else { + statuses = (MPI_Status *) ADIOI_Malloc((nprocs_send+nprocs_recv+1) * \ + sizeof(MPI_Status)); + /* +1 to avoid a 0-size malloc */ + } + +#ifdef NEEDS_MPI_TEST + i = 0; + if (fd->atomicity) { + /* bug fix from Wei-keng Liao and Kenin Coloma */ + while (!i) MPI_Testall(nprocs_send, send_req, &i, statuses); + } + else { + while (!i) MPI_Testall(nprocs_send+nprocs_recv, requests, &i, statuses); + } +#else + if (fd->atomicity) + /* bug fix from Wei-keng Liao and Kenin Coloma */ + MPI_Waitall(nprocs_send, send_req, statuses); + else + MPI_Waitall(nprocs_send+nprocs_recv, requests, statuses); +#endif + +#ifdef AGGREGATION_PROFILE + MPE_Log_event (5033, 0, NULL); +#endif + ADIOI_Free(statuses); + ADIOI_Free(requests); + if (!buftype_is_contig && nprocs_send) { + for (i=0; i < nprocs; i++) + if (send_size[i]) ADIOI_Free(send_buf[i]); + ADIOI_Free(send_buf); + } +} + +#define ADIOI_BUF_INCR \ +{ \ + while (buf_incr) { \ + size_in_buf = ADIOI_MIN(buf_incr, flat_buf_sz); \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + buf_incr -= size_in_buf; \ + } \ +} + + +#define ADIOI_BUF_COPY \ +{ \ + while (size) { \ + size_in_buf = ADIOI_MIN(size, flat_buf_sz); \ + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + user_buf_idx) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + user_buf_idx)); \ + ADIOI_Assert(size_in_buf == (size_t)size_in_buf); \ + memcpy(&(send_buf[p][send_buf_idx[p]]), \ + ((char *) buf) + user_buf_idx, size_in_buf); \ + send_buf_idx[p] += size_in_buf; \ + user_buf_idx += size_in_buf; \ + flat_buf_sz -= size_in_buf; \ + if (!flat_buf_sz) { \ + if (flat_buf_idx < (flat_buf->count - 1)) flat_buf_idx++; \ + else { \ + flat_buf_idx = 0; \ + n_buftypes++; \ + } \ + user_buf_idx = flat_buf->indices[flat_buf_idx] + \ + (ADIO_Offset)n_buftypes*(ADIO_Offset)buftype_extent; \ + flat_buf_sz = flat_buf->blocklens[flat_buf_idx]; \ + } \ + size -= size_in_buf; \ + buf_incr -= size_in_buf; \ + } \ + ADIOI_BUF_INCR \ +} + + + + + +static void ADIOI_Fill_send_buffer(ADIO_File fd, void *buf, ADIOI_Flatlist_node + *flat_buf, char **send_buf, ADIO_Offset + *offset_list, ADIO_Offset *len_list, int *send_size, + MPI_Request *requests, int *sent_to_proc, + int nprocs, int myrank, + int contig_access_count, + ADIO_Offset min_st_offset, ADIO_Offset fd_size, + ADIO_Offset *fd_start, ADIO_Offset *fd_end, + int *send_buf_idx, int *curr_to_proc, + int *done_to_proc, int iter, + MPI_Aint buftype_extent) +{ +/* this function is only called if buftype is not contig */ + + int i, p, flat_buf_idx; + ADIO_Offset flat_buf_sz, size_in_buf, buf_incr, size; + int jj, n_buftypes; + ADIO_Offset off, len, rem_len, user_buf_idx; + +/* curr_to_proc[p] = amount of data sent to proc. p that has already + been accounted for so far + done_to_proc[p] = amount of data already sent to proc. p in + previous iterations + user_buf_idx = current location in user buffer + send_buf_idx[p] = current location in send_buf of proc. p */ + + for (i=0; i < nprocs; i++) { + send_buf_idx[i] = curr_to_proc[i] = 0; + done_to_proc[i] = sent_to_proc[i]; + } + jj = 0; + + user_buf_idx = flat_buf->indices[0]; + flat_buf_idx = 0; + n_buftypes = 0; + flat_buf_sz = flat_buf->blocklens[0]; + + /* flat_buf_idx = current index into flattened buftype + flat_buf_sz = size of current contiguous component in + flattened buf */ + + for (i=0; i done_to_proc[p]) { + if (done_to_proc[p] > curr_to_proc[p]) { + size = ADIOI_MIN(curr_to_proc[p] + len - + done_to_proc[p], send_size[p]-send_buf_idx[p]); + buf_incr = done_to_proc[p] - curr_to_proc[p]; + ADIOI_BUF_INCR + ADIOI_Assert((curr_to_proc[p] + len - done_to_proc[p]) == (unsigned)(curr_to_proc[p] + len - done_to_proc[p])); + buf_incr = curr_to_proc[p] + len - done_to_proc[p]; + ADIOI_Assert((done_to_proc[p] + size) == (unsigned)(done_to_proc[p] + size)); + /* ok to cast: bounded by cb buffer size */ + curr_to_proc[p] = done_to_proc[p] + (int)size; + ADIOI_BUF_COPY + } + else { + size = ADIOI_MIN(len,send_size[p]-send_buf_idx[p]); + buf_incr = len; + ADIOI_Assert((curr_to_proc[p] + size) == (unsigned)((ADIO_Offset)curr_to_proc[p] + size)); + curr_to_proc[p] += size; + ADIOI_BUF_COPY + } + if (send_buf_idx[p] == send_size[p]) { + MPI_Isend(send_buf[p], send_size[p], MPI_BYTE, p, + myrank+p+100*iter, fd->comm, requests+jj); + jj++; + } + } + else { + ADIOI_Assert((curr_to_proc[p] + len) == (unsigned)((ADIO_Offset)curr_to_proc[p] + len)); + curr_to_proc[p] += len; + buf_incr = len; + ADIOI_BUF_INCR + } + } + else { + buf_incr = len; + ADIOI_BUF_INCR + } + off += len; + rem_len -= len; + } + } + for (i=0; i < nprocs; i++) + if (send_size[i]) sent_to_proc[i] = curr_to_proc[i]; +} + + + +void ADIOI_Heap_merge(ADIOI_Access *others_req, int *count, + ADIO_Offset *srt_off, int *srt_len, int *start_pos, + int nprocs, int nprocs_recv, int total_elements) +{ + typedef struct { + ADIO_Offset *off_list; + ADIO_Offset *len_list; + int nelem; + } heap_struct; + + heap_struct *a, tmp; + int i, j, heapsize, l, r, k, smallest; + + a = (heap_struct *) ADIOI_Malloc((nprocs_recv+1)*sizeof(heap_struct)); + + j = 0; + for (i=0; i=0; i--) { + /* Heapify(a, i, heapsize); Algorithm from Cormen et al. pg. 143 + modified for a heap with smallest element at root. I have + removed the recursion so that there are no function calls. + Function calls are too expensive. */ + k = i; + for(;;) { + l = 2*(k+1) - 1; + r = 2*(k+1); + + if ((l < heapsize) && + (*(a[l].off_list) < *(a[k].off_list))) + smallest = l; + else smallest = k; + + if ((r < heapsize) && + (*(a[r].off_list) < *(a[smallest].off_list))) + smallest = r; + + if (smallest != k) { + tmp.off_list = a[k].off_list; + tmp.len_list = a[k].len_list; + tmp.nelem = a[k].nelem; + + a[k].off_list = a[smallest].off_list; + a[k].len_list = a[smallest].len_list; + a[k].nelem = a[smallest].nelem; + + a[smallest].off_list = tmp.off_list; + a[smallest].len_list = tmp.len_list; + a[smallest].nelem = tmp.nelem; + + k = smallest; + } + else break; + } + } + + for (i=0; i + +#include "adio.h" +#include "adio_extern.h" + + +/* #define IO_DEBUG 1 */ +void ADIOI_NOLOCK_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) +{ +/* borrowed from old-school PVFS (v1) code. A driver for file systems that + * cannot or do not support client-side buffering + * Does not do data sieving optimization + * Does contain write-combining optimization for noncontig in memory, contig in + * file + */ + +/* offset is in units of etype relative to the filetype. */ + + ADIOI_Flatlist_node *flat_buf, *flat_file; + int j, k, st_index=0; + off_t err_lseek=-1; + ssize_t err=-1; + ADIO_Offset fwr_size=0, bwr_size, new_bwr_size, new_fwr_size, i_offset, num; + ADIO_Offset bufsize, n_etypes_in_filetype; + ADIO_Offset n_filetypes, etype_in_filetype, size, sum; + ADIO_Offset abs_off_in_filetype=0, size_in_filetype; + MPI_Count filetype_size, etype_size, buftype_size; + MPI_Aint filetype_extent, buftype_extent, indx; + int buf_count, buftype_is_contig, filetype_is_contig; + ADIO_Offset off, disp; + int flag, err_flag=0; + static char myname[] = "ADIOI_NOLOCK_WRITESTRIDED"; +#ifdef IO_DEBUG + int rank,nprocs; +#endif + + /* --BEGIN ERROR HANDLING-- */ + if (fd->atomicity) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_INTERN, + "Atomic mode set in I/O function", 0); + return; + } + /* --END ERROR HANDLING-- */ + + 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; + } + +#ifdef IO_DEBUG + MPI_Comm_rank(fd->comm, &rank); + MPI_Comm_size(fd->comm, &nprocs); +#endif + + 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)(unsigned)buftype_size * (ADIO_Offset)count)); + bufsize = buftype_size * count; + + if (!buftype_is_contig && filetype_is_contig) { + char *combine_buf, *combine_buf_ptr; + ADIO_Offset combine_buf_remain; +/* noncontiguous in memory, contiguous in file. use writev */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + /* allocate our "combine buffer" to pack data into before writing */ + combine_buf = (char *) ADIOI_Malloc(fd->hints->ind_wr_buffer_size); + combine_buf_ptr = combine_buf; + combine_buf_remain = fd->hints->ind_wr_buffer_size; + + /* seek to the right spot in the file */ + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = fd->disp + etype_size * offset; + lseek(fd->fd_sys, off, SEEK_SET); + } + else off = lseek(fd->fd_sys, fd->fp_ind, SEEK_SET); + + /* loop through all the flattened pieces. combine into buffer until + * no more will fit, then write. + * + * special case of a given piece being bigger than the combine buffer + * is also handled. + */ + for (j=0; jcount; i++) { + if (flat_buf->blocklens[i] > combine_buf_remain && combine_buf != combine_buf_ptr) { + /* there is data in the buffer; write out the buffer so far */ +#ifdef IO_DEBUG + printf("[%d/%d] nc mem c file (0) writing loc = %Ld sz = %Ld\n", + rank, nprocs, off, + fd->hints->ind_wr_buffer_size-combine_buf_remain); +#endif +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + err = write(fd->fd_sys, + combine_buf, + fd->hints->ind_wr_buffer_size - combine_buf_remain); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; + + /* reset our buffer info */ + combine_buf_ptr = combine_buf; + combine_buf_remain = fd->hints->ind_wr_buffer_size; + } + + /* TODO: heuristic for when to not bother to use combine buffer? */ + if (flat_buf->blocklens[i] >= combine_buf_remain) { + /* special case: blocklen is as big as or bigger than the combine buf; + * write directly + */ +#ifdef IO_DEBUG + printf("[%d/%d] nc mem c file (1) writing loc = %Ld sz = %d\n", + rank, nprocs, off, + flat_buf->blocklens[i]); +#endif + ADIOI_Assert(flat_buf->blocklens[i] == (unsigned)flat_buf->blocklens[i]); + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + (ADIO_Offset)j*(ADIO_Offset)buftype_extent + flat_buf->indices[i]) == (ADIO_Offset)((MPIR_Upint)buf + (ADIO_Offset)j*(ADIO_Offset)buftype_extent + flat_buf->indices[i])); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + err = write(fd->fd_sys, + ((char *) buf) + (ADIO_Offset)j*(ADIO_Offset)buftype_extent + flat_buf->indices[i], + (unsigned)flat_buf->blocklens[i]); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; + off += flat_buf->blocklens[i]; /* keep up with the final file offset too */ + } + else { + /* copy more data into combine buffer */ + memcpy(combine_buf_ptr, + ((char *) buf) + j*buftype_extent + flat_buf->indices[i], + flat_buf->blocklens[i]); + combine_buf_ptr += flat_buf->blocklens[i]; + combine_buf_remain -= flat_buf->blocklens[i]; + off += flat_buf->blocklens[i]; /* keep up with the final file offset too */ + } + } + } + + if (combine_buf_ptr != combine_buf) { + /* data left in buffer to write */ +#ifdef IO_DEBUG + printf("[%d/%d] nc mem c file (2) writing loc = %Ld sz = %Ld\n", + rank, nprocs, off, + fd->hints->ind_wr_buffer_size-combine_buf_remain); +#endif +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + err = write(fd->fd_sys, + combine_buf, + fd->hints->ind_wr_buffer_size - combine_buf_remain); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; + } + + if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind = off; + + ADIOI_Free(combine_buf); + + 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; + } /* if (!buftype_is_contig && filetype_is_contig) ... */ + + else { /* noncontiguous in file */ + +/* split up into several contiguous writes */ + +/* find starting location in the 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) { + int i; + n_filetypes++; + for (i=0; icount; i++) { + if (disp + flat_file->indices[i] + + n_filetypes*(ADIO_Offset)filetype_extent + flat_file->blocklens[i] + >= offset) { + st_index = i; + fwr_size = disp + flat_file->indices[i] + + n_filetypes*(ADIO_Offset)filetype_extent + + flat_file->blocklens[i] - offset; + flag = 1; + break; + } + } + } + } + else { + int i; + 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; icount; 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 + n_filetypes*(ADIO_Offset)filetype_extent + abs_off_in_filetype; + } + + 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; + fwr_size = ADIOI_MIN(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 */ +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_lseek_a, 0, NULL); +#endif +#ifdef IO_DEBUG + printf("[%d/%d] c mem nc file writing loc = %Ld sz = %d\n", + rank, nprocs, off, fwr_size); +#endif + err_lseek = lseek(fd->fd_sys, off, SEEK_SET); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_lseek_b, 0, NULL); +#endif + if (err_lseek == -1) err_flag = 1; +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_write_a, 0, NULL); +#endif + err = write(fd->fd_sys, ((char *) buf) + i_offset, fwr_size); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event(ADIOI_MPE_write_b, 0, NULL); +#endif + if (err == -1) err_flag = 1; + } + 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 { + if (j < (flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + off = disp + flat_file->indices[j] + + n_filetypes*(ADIO_Offset)filetype_extent; + fwr_size = ADIOI_MIN(flat_file->blocklens[j], bufsize-i_offset); + } + } + } + else { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + k = num = buf_count = 0; + indx = flat_buf->indices[0]; + j = st_index; + off = offset; + bwr_size = flat_buf->blocklens[0]; + + while (num < bufsize) { + size = ADIOI_MIN(fwr_size, bwr_size); + if (size) { +#ifdef IO_DEBUG + printf("[%d/%d] nc mem nc file writing loc = %Ld sz = %d\n", + rank, nprocs, off, size); +#endif +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_a, 0, NULL ); +#endif + lseek(fd->fd_sys, off, SEEK_SET); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_lseek_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_a, 0, NULL ); +#endif + ADIOI_Assert(size == (size_t) size); + ADIOI_Assert(off == (off_t) off); + err = write(fd->fd_sys, ((char *) buf) + indx, size); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_write_b, 0, NULL ); +#endif + if (err == -1) err_flag = 1; + } + + new_fwr_size = fwr_size; + new_bwr_size = bwr_size; + + if (size == fwr_size) { +/* reached end of contiguous block in file */ + if (j < (flat_file->count - 1)) j++; + else { + j = 0; + n_filetypes++; + } + + off = disp + flat_file->indices[j] + + n_filetypes*(ADIO_Offset)filetype_extent; + + new_fwr_size = flat_file->blocklens[j]; + if (size != bwr_size) { + indx += size; + new_bwr_size -= size; + } + } + + if (size == bwr_size) { +/* reached end of contiguous block in memory */ + + k = (k + 1)%flat_buf->count; + buf_count++; + indx = buftype_extent*(buf_count/flat_buf->count) + + flat_buf->indices[k]; + new_bwr_size = flat_buf->blocklens[k]; + if (size != fwr_size) { + off += size; + new_fwr_size -= size; + } + } + num += size; + fwr_size = new_fwr_size; + bwr_size = new_bwr_size; + } + } + + 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; + } + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_write_str.c b/ompi/mca/io/romio314/romio/adio/common/ad_write_str.c new file mode 100644 index 0000000000..f3b6c8960b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_write_str.c @@ -0,0 +1,490 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +#define ADIOI_BUFFERED_WRITE \ +{ \ + if (req_off >= writebuf_off + writebuf_len) { \ + if (writebuf_len) { \ + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \ + if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowswc", 0); \ + goto fn_exit; \ + } \ + } \ + writebuf_off = req_off; \ + writebuf_len = (unsigned) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\ + if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + ADIO_ReadContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowsrc", 0); \ + goto fn_exit; \ + } \ + } \ + write_sz = (unsigned) (ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \ + ADIOI_Assert((ADIO_Offset)write_sz == ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off));\ + memcpy(writebuf+req_off-writebuf_off, (char *)buf +userbuf_off, write_sz);\ + while (write_sz != req_len) { \ + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \ + if (!(fd->atomicity)) ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowswc", 0); \ + goto fn_exit; \ + } \ + req_len -= write_sz; \ + userbuf_off += write_sz; \ + writebuf_off += writebuf_len; \ + writebuf_len = (unsigned) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\ + if (!(fd->atomicity)) ADIOI_WRITE_LOCK(fd, writebuf_off, SEEK_SET, writebuf_len); \ + ADIO_ReadContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowsrc", 0); \ + goto fn_exit; \ + } \ + write_sz = ADIOI_MIN(req_len, writebuf_len); \ + memcpy(writebuf, (char *)buf + userbuf_off, write_sz);\ + } \ +} + + +/* this macro is used when filetype is contig and buftype is not contig. + it does not do a read-modify-write and does not lock*/ +#define ADIOI_BUFFERED_WRITE_WITHOUT_READ \ +{ \ + if (req_off >= writebuf_off + writebuf_len) { \ + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowswc", 0); \ + goto fn_exit; \ + } \ + writebuf_off = req_off; \ + writebuf_len = (unsigned) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\ + } \ + write_sz = (unsigned) (ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off)); \ + ADIOI_Assert((ADIO_Offset)write_sz == ADIOI_MIN(req_len, writebuf_off + writebuf_len - req_off));\ + memcpy(writebuf+req_off-writebuf_off, (char *)buf +userbuf_off, write_sz);\ + while (write_sz != req_len) { \ + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, \ + ADIO_EXPLICIT_OFFSET, writebuf_off, &status1, error_code); \ + if (*error_code != MPI_SUCCESS) { \ + *error_code = MPIO_Err_create_code(*error_code, \ + MPIR_ERR_RECOVERABLE, myname, \ + __LINE__, MPI_ERR_IO, \ + "**iowswc", 0); \ + goto fn_exit; \ + } \ + req_len -= write_sz; \ + userbuf_off += write_sz; \ + writebuf_off += writebuf_len; \ + writebuf_len = (unsigned) (ADIOI_MIN(max_bufsize,end_offset-writebuf_off+1));\ + write_sz = ADIOI_MIN(req_len, writebuf_len); \ + memcpy(writebuf, (char *)buf + userbuf_off, write_sz);\ + } \ +} +void ADIOI_GEN_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; + ADIO_Offset i_offset, sum, size_in_filetype; + int i, j, k, st_index=0; + ADIO_Offset num, size, n_filetypes, etype_in_filetype, st_n_filetypes; + ADIO_Offset n_etypes_in_filetype, abs_off_in_filetype=0; + 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; + unsigned writebuf_len, max_bufsize, write_sz; + MPI_Aint bufsize; + ADIO_Status status1; + ADIO_Offset new_bwr_size, new_fwr_size, st_fwr_size, fwr_size=0, bwr_size, req_len; + static char myname[] = "ADIOI_GEN_WriteStrided"; + + if (fd->hints->ds_write == ADIOI_HINT_DISABLE) { + /* if user has disabled data sieving on reads, 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_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) == ((MPI_Count)buftype_size * (ADIO_Offset)count)); + bufsize = buftype_size * count; + +/* get max_bufsize from the info object. */ + + max_bufsize = fd->hints->ind_wr_buffer_size; + + 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 = off + bufsize - 1; + writebuf_off = off; + writebuf = (char *) ADIOI_Malloc(max_bufsize); + writebuf_len = (unsigned) (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; jcount; 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, end_offset-start_off+1); + + if (*error_code != MPI_SUCCESS) goto fn_exit; + + 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; icount; 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; icount; 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 = 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(max_bufsize); + memset(writebuf, -1, 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; + 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 { +/* noncontiguous in memory as well as in file */ + + ADIOI_Flatten_datatype(datatype); + flat_buf = ADIOI_Flatlist; + while (flat_buf->type != datatype) flat_buf = flat_buf->next; + + k = num = buf_count = 0; + i_offset = flat_buf->indices[0]; + j = st_index; + off = offset; + n_filetypes = st_n_filetypes; + fwr_size = st_fwr_size; + bwr_size = flat_buf->blocklens[0]; + + while (num < bufsize) { + size = ADIOI_MIN(fwr_size, bwr_size); + if (size) { + /* lseek(fd->fd_sys, off, SEEK_SET); + err = write(fd->fd_sys, ((char *) buf) + i_offset, size); */ + + req_off = off; + req_len = size; + userbuf_off = i_offset; + ADIOI_BUFFERED_WRITE + } + + new_fwr_size = fwr_size; + new_bwr_size = bwr_size; + + if (size == fwr_size) { +/* reached end of contiguous block in file */ + 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; + + new_fwr_size = flat_file->blocklens[j]; + if (size != bwr_size) { + i_offset += size; + new_bwr_size -= size; + } + } + + if (size == bwr_size) { +/* reached end of contiguous block in memory */ + + k = (k + 1)%flat_buf->count; + buf_count++; + i_offset = (ADIO_Offset)buftype_extent*(ADIO_Offset)(buf_count/flat_buf->count) + + flat_buf->indices[k]; + new_bwr_size = flat_buf->blocklens[k]; + if (size != fwr_size) { + off += size; + new_fwr_size -= size; + } + } + num += size; + fwr_size = new_fwr_size; + bwr_size = new_bwr_size; + } + } + + /* write the buffer out finally */ + if (writebuf_len) { + ADIO_WriteContig(fd, writebuf, writebuf_len, MPI_BYTE, ADIO_EXPLICIT_OFFSET, + writebuf_off, &status1, error_code); + if (!(fd->atomicity)) + ADIOI_UNLOCK(fd, writebuf_off, SEEK_SET, writebuf_len); + if (*error_code != MPI_SUCCESS) goto fn_exit; + } + 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; + } + + fd->fp_sys_posn = -1; /* set it to null. */ + +#ifdef HAVE_STATUS_SET_BYTES + /* datatypes returning negagive values, probably related to tt 1893 */ + MPIR_Status_set_bytes(status, datatype, bufsize); +/* This is a temporary way of filling in status. The right way is to + keep track of how much data was actually written by ADIOI_BUFFERED_WRITE. */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(datatype); +fn_exit: + if (writebuf != NULL) ADIOI_Free(writebuf); +} + diff --git a/ompi/mca/io/romio314/romio/adio/common/ad_write_str_naive.c b/ompi/mca/io/romio314/romio/adio/common/ad_write_str_naive.c new file mode 100644 index 0000000000..f59c02d427 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/ad_write_str_naive.c @@ -0,0 +1,383 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +void ADIOI_GEN_WriteStrided_naive(ADIO_File fd, const 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; + /* bwr == buffer write; fwr == file write */ + ADIO_Offset bwr_size, fwr_size=0, sum, size_in_filetype; + int b_index; + MPI_Count bufsize; + ADIO_Offset n_etypes_in_filetype; + ADIO_Offset size, n_filetypes, etype_in_filetype; + ADIO_Offset abs_off_in_filetype=0, 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, 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_x(fd->filetype, &filetype_size); + if ( ! filetype_size ) { +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, buftype, 0); +#endif + *error_code = MPI_SUCCESS; + return; + } + + MPI_Type_extent(fd->filetype, &filetype_extent); + MPI_Type_size_x(buftype, &buftype_size); + MPI_Type_extent(buftype, &buftype_extent); + etype_size = fd->etype_size; + + ADIOI_Assert((buftype_size * count) == ((ADIO_Offset)(unsigned)buftype_size * (ADIO_Offset)count)); + 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 + (ADIO_Offset)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) && ADIO_Feature(fd, ADIO_LOCKS)) + { + 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 = (ADIO_Offset)b_count*(ADIO_Offset)buftype_extent + + flat_buf->indices[b_index]; + req_off = off; + req_len = flat_buf->blocklens[b_index]; + + ADIOI_Assert(req_len == (int) req_len); + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + userbuf_off) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + userbuf_off)); + ADIO_WriteContig(fd, + (char *) buf + userbuf_off, + (int)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) && 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; + + } + + else { /* noncontiguous in file */ + int f_index, st_index = 0; + ADIO_Offset st_fwr_size, 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_fwr_size - size of the data in the first filetype block + * that we will write (accounts for being part-way + * into writing 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] + + n_filetypes*(ADIO_Offset)filetype_extent + + flat_file->blocklens[f_index] >= start_off) + { + /* this block contains our starting position */ + + st_index = f_index; + fwr_size = disp + flat_file->indices[f_index] + + n_filetypes*(ADIO_Offset)filetype_extent + + flat_file->blocklens[f_index] - start_off; + flag = 1; + break; + } + } + } + } + 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 (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; + fwr_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 + n_filetypes*(ADIO_Offset)filetype_extent + + abs_off_in_filetype; + } + + st_fwr_size = fwr_size; + st_n_filetypes = n_filetypes; + + /* start_off, st_n_filetypes, st_index, and st_fwr_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 written, end_offset=99 + */ + userbuf_off = 0; + f_index = st_index; + off = start_off; + fwr_size = ADIOI_MIN(st_fwr_size, bufsize); + while (userbuf_off < bufsize) { + userbuf_off += fwr_size; + end_offset = off + fwr_size - 1; + + if (f_index < (flat_file->count - 1)) f_index++; + else { + f_index = 0; + n_filetypes++; + } + + off = disp + flat_file->indices[f_index] + + n_filetypes*(ADIO_Offset)filetype_extent; + fwr_size = ADIOI_MIN(flat_file->blocklens[f_index], + bufsize-(unsigned)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_fwr_size + */ + + /* 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); + } + + 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; + fwr_size = ADIOI_MIN(st_fwr_size, bufsize); + + /* while there is still space in the buffer, write more data */ + while (userbuf_off < bufsize) { + if (fwr_size) { + /* TYPE_UB and TYPE_LB can result in + fwr_size = 0. save system call in such cases */ + req_off = off; + req_len = fwr_size; + + ADIOI_Assert(req_len == (int) req_len); + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + userbuf_off) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + userbuf_off)); + ADIO_WriteContig(fd, + (char *) buf + userbuf_off, + (int)req_len, + MPI_BYTE, + ADIO_EXPLICIT_OFFSET, + req_off, + &status1, + error_code); + if (*error_code != MPI_SUCCESS) return; + } + userbuf_off += fwr_size; + + if (off + fwr_size < disp + flat_file->indices[f_index] + + flat_file->blocklens[f_index] + + n_filetypes*(ADIO_Offset)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 += fwr_size; + } + /* did not reach end of contiguous block in filetype. + * no more I/O needed. off is incremented by fwr_size. + */ + else { + if (f_index < (flat_file->count - 1)) f_index++; + else { + f_index = 0; + n_filetypes++; + } + off = disp + flat_file->indices[f_index] + + n_filetypes*(ADIO_Offset)filetype_extent; + fwr_size = ADIOI_MIN(flat_file->blocklens[f_index], + bufsize-(unsigned)userbuf_off); + } + } + } + else { + ADIO_Offset i_offset, 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_offset = flat_buf->indices[0]; + f_index = st_index; + off = start_off; + n_filetypes = st_n_filetypes; + fwr_size = st_fwr_size; + bwr_size = flat_buf->blocklens[0]; + + /* while we haven't read size * count bytes, keep going */ + while (tmp_bufsize < bufsize) { + ADIO_Offset new_bwr_size = bwr_size, new_fwr_size = fwr_size; + + size = ADIOI_MIN(fwr_size, bwr_size); + if (size) { + req_off = off; + req_len = size; + userbuf_off = i_offset; + + ADIOI_Assert(req_len == (int) req_len); + ADIOI_Assert((((ADIO_Offset)(MPIR_Upint)buf) + userbuf_off) == (ADIO_Offset)(MPIR_Upint)((MPIR_Upint)buf + userbuf_off)); + ADIO_WriteContig(fd, + (char *) buf + userbuf_off, + (int)req_len, + MPI_BYTE, + ADIO_EXPLICIT_OFFSET, + req_off, + &status1, + error_code); + if (*error_code != MPI_SUCCESS) return; + } + + if (size == fwr_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] + + n_filetypes*(ADIO_Offset)filetype_extent; + + new_fwr_size = flat_file->blocklens[f_index]; + if (size != bwr_size) { + i_offset += size; + new_bwr_size -= size; + } + } + + if (size == bwr_size) { + /* reached end of contiguous block in memory */ + + b_index = (b_index + 1)%flat_buf->count; + buf_count++; + i_offset = (ADIO_Offset)buftype_extent*(ADIO_Offset)(buf_count/flat_buf->count) + + flat_buf->indices[b_index]; + new_bwr_size = flat_buf->blocklens[b_index]; + if (size != fwr_size) { + off += size; + new_fwr_size -= size; + } + } + tmp_bufsize += size; + fwr_size = new_fwr_size; + bwr_size = new_bwr_size; + } + } + + /* unlock the file region if we locked it */ + 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; + } /* 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 written and placed in buf + */ +#endif + + if (!buftype_is_contig) ADIOI_Delete_flattened(buftype); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/adi_close.c b/ompi/mca/io/romio314/romio/adio/common/adi_close.c new file mode 100644 index 0000000000..cdc1873785 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/adi_close.c @@ -0,0 +1,45 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + + + +void ADIOI_GEN_Close(ADIO_File fd, int *error_code) +{ + int err, derr=0; + static char myname[] = "ADIOI_GEN_CLOSE"; + +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_close_a, 0, NULL ); +#endif + err = close(fd->fd_sys); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_close_b, 0, NULL ); +#endif + if (fd->fd_direct >= 0) { +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_close_a, 0, NULL ); +#endif + derr = close(fd->fd_direct); +#ifdef ADIOI_MPE_LOGGING + MPE_Log_event( ADIOI_MPE_close_b, 0, NULL ); +#endif + } + + fd->fd_sys = -1; + fd->fd_direct = -1; + + if (err == -1 || derr == -1) { + *error_code = ADIOI_Err_create_code(myname, fd->filename, errno); + } + else *error_code = MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/async_list.c b/ompi/mca/io/romio314/romio/adio/common/async_list.c new file mode 100644 index 0000000000..239dbe587b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/async_list.c @@ -0,0 +1,170 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +ADIOI_Async_node *ADIOI_Malloc_async_node(void) +{ +/* returns a pointer to a new node that can be added to ADIOI_Async_list. + To reduce the number of system calls, mallocs NUM nodes at a time + and maintains list of available nodes. Supplies a node from this + list if available, else mallocs a new set of NUM and provides one + from that set. Is NUM=100 a good number? */ + +#define NUM 100 + + ADIOI_Async_node *curr, *ptr; + int i; + + if (!ADIOI_Async_avail_head) { + ADIOI_Async_avail_head = (ADIOI_Async_node *) + ADIOI_Malloc(NUM*sizeof(ADIOI_Async_node)); + curr = ADIOI_Async_avail_head; + for (i=1; inext = ADIOI_Async_avail_head+i; + curr = curr->next; + } + curr->next = NULL; + ADIOI_Async_avail_tail = curr; + + /* keep track of malloced area that needs to be freed later */ + if (!ADIOI_Malloc_async_tail) { + ADIOI_Malloc_async_tail = (ADIOI_Malloc_async *) + ADIOI_Malloc(sizeof(ADIOI_Malloc_async)); + ADIOI_Malloc_async_head = ADIOI_Malloc_async_tail; + ADIOI_Malloc_async_head->ptr = ADIOI_Async_avail_head; + ADIOI_Malloc_async_head->next = NULL; + } + else { + ADIOI_Malloc_async_tail->next = (ADIOI_Malloc_async *) + ADIOI_Malloc(sizeof(ADIOI_Malloc_async)); + ADIOI_Malloc_async_tail = ADIOI_Malloc_async_tail->next; + ADIOI_Malloc_async_tail->ptr = ADIOI_Async_avail_head; + ADIOI_Malloc_async_tail->next = NULL; + } + } + + ptr = ADIOI_Async_avail_head; + ADIOI_Async_avail_head = ADIOI_Async_avail_head->next; + if (!ADIOI_Async_avail_head) ADIOI_Async_avail_tail = NULL; + + return ptr; +} + + +void ADIOI_Free_async_node(ADIOI_Async_node *node) +{ +/* moves this node to available pool. does not actually free it. */ + + if (!ADIOI_Async_avail_tail) + ADIOI_Async_avail_head = ADIOI_Async_avail_tail = node; + else { + ADIOI_Async_avail_tail->next = node; + ADIOI_Async_avail_tail = node; + } + node->next = NULL; +} + + +void ADIOI_Add_req_to_list(ADIO_Request *request) +{ +/* add request to list of outstanding requests */ + + ADIOI_Async_node *curr; + + if (!ADIOI_Async_list_head) { + ADIOI_Async_list_head = ADIOI_Malloc_async_node(); + ADIOI_Async_list_head->request = request; + ADIOI_Async_list_head->prev = ADIOI_Async_list_head->next = NULL; + ADIOI_Async_list_tail = ADIOI_Async_list_head; + (*request)->ptr_in_async_list = ADIOI_Async_list_head; + } + else { + curr = ADIOI_Async_list_tail; + curr->next = ADIOI_Malloc_async_node(); + ADIOI_Async_list_tail = curr->next; + ADIOI_Async_list_tail->request = request; + ADIOI_Async_list_tail->prev = curr; + ADIOI_Async_list_tail->next = NULL; + (*request)->ptr_in_async_list = ADIOI_Async_list_tail; + } +} + +/* Sets error_code to MPI_SUCCESS on success, creates an error code on + * failure. + */ +void ADIOI_Complete_async(int *error_code) +{ +/* complete all outstanding async I/O operations so that new ones can be + initiated. Remove them all from async_list. */ + + ADIO_Status status; + ADIO_Request *request; + ADIOI_Async_node *tmp; + static char myname[] = "ADIOI_Complete_async"; + + *error_code = MPI_SUCCESS; + + while (ADIOI_Async_list_head) { + request = ADIOI_Async_list_head->request; + (*request)->queued = -1; /* ugly internal hack that prevents + ADIOI_xxxComplete from freeing the request object. + This is required, because the user will call MPI_Wait + later, which would require status to be filled. */ + switch ((*request)->optype) { + case ADIOI_READ: +/* (*((*request)->fd->fns->ADIOI_xxx_ReadComplete))(request, + &status,error_code);*/ + ADIO_ReadComplete(request, &status, error_code); + break; + case ADIOI_WRITE: +/* (*((*request)->fd->fns->ADIOI_xxx_WriteComplete))(request, + &status, error_code);*/ + ADIO_WriteComplete(request, &status, error_code); + break; + default: + /* --BEGIN ERROR HANDLING-- */ + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_INTERN, + "Unknown request optype", 0); + return; + /* --END ERROR HANDLING-- */ + } + (*request)->queued = 0; /* dequeued, but request object not + freed */ + + tmp = ADIOI_Async_list_head; + ADIOI_Async_list_head = ADIOI_Async_list_head->next; + ADIOI_Free_async_node(tmp); + } + ADIOI_Async_list_tail = NULL; +} + + +void ADIOI_Del_req_from_list(ADIO_Request *request) +{ +/* Delete a request that has already been completed from the async + list and move it to the list of available nodes. Typically called + from within an ADIO_Test/ADIO_Wait. */ + + ADIOI_Async_node *curr, *prev, *next; + + curr = (*request)->ptr_in_async_list; + prev = curr->prev; + + if (prev) prev->next = curr->next; + else ADIOI_Async_list_head = curr->next; + + next = curr->next; + if (next) next->prev = prev; + else ADIOI_Async_list_tail = prev; + + ADIOI_Free_async_node(curr); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/byte_offset.c b/ompi/mca/io/romio314/romio/adio/common/byte_offset.c new file mode 100644 index 0000000000..df0a240849 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/byte_offset.c @@ -0,0 +1,52 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +/* Returns the absolute byte position in the file corresponding to + "offset" etypes relative to the current view. */ + +void ADIOI_Get_byte_offset(ADIO_File fd, ADIO_Offset offset, ADIO_Offset *disp) +{ + ADIOI_Flatlist_node *flat_file; + int i; + ADIO_Offset n_filetypes, etype_in_filetype, sum, abs_off_in_filetype=0, size_in_filetype; + MPI_Count n_etypes_in_filetype, filetype_size, etype_size; + int filetype_is_contig; + MPI_Aint filetype_extent; + + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + etype_size = fd->etype_size; + + if (filetype_is_contig) *disp = fd->disp + etype_size * offset; + else { +/* filetype already flattened in ADIO_Open */ + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + + MPI_Type_size_x(fd->filetype, &filetype_size); + 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; icount; i++) { + sum += flat_file->blocklens[i]; + if (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 */ + MPI_Type_extent(fd->filetype, &filetype_extent); + *disp = fd->disp + n_filetypes * ADIOI_AINT_CAST_TO_OFFSET filetype_extent + abs_off_in_filetype; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/common/cb_config_list.c b/ompi/mca/io/romio314/romio/adio/common/cb_config_list.c new file mode 100644 index 0000000000..626709f844 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/cb_config_list.c @@ -0,0 +1,755 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* cb_config_list.c + * + * The important, externally used functions from this file are: + * ADIOI_cb_bcast_rank_map() + * ADIOI_cb_gather_name_array() + * ADIOI_cb_config_list_parse() + * ADIOI_cb_copy_name_array() + * ADIOI_cb_delete_name_array() + * + * Prototypes for these are in adio/include/adio_cb_config_list.h + */ + +#include "adio.h" +#include "mpi.h" +#include "adio_cb_config_list.h" +#include +#include +#include + +/* token types */ +#define AGG_WILDCARD 1 +#define AGG_STRING 2 +#define AGG_COMMA 3 +#define AGG_COLON 4 +#define AGG_ERROR -1 +#define AGG_EOS 0 + +#undef CB_CONFIG_LIST_DEBUG + +/* a couple of globals keep things simple */ +int ADIOI_cb_config_list_keyval = MPI_KEYVAL_INVALID; +static char *yylval; +static char *token_ptr; + +/* internal stuff */ +static int get_max_procs(int cb_nodes); +static int match_procs(char *name, int max_per_proc, char *procnames[], + char used_procnames[], + int nr_procnames, int ranks[], int nr_ranks, + int *nr_ranks_allocated); +static int match_this_proc(char *name, int cur_proc, int max_matches, + char *procnames[], char used_procnames[], + int nr_procnames, int ranks[], + int nr_ranks, int nr_ranks_allocated); +static int find_name(char *name, char *procnames[], char used_procnames[], + int nr_procnames, int start_ind); +static int cb_config_list_lex(void); + + +/* ADIOI_cb_bcast_rank_map() - broadcast the rank array + * + * Parameters: + * fd - ADIO_File for which update is occurring. cb_nodes and ranklist + * parameters must be up-to-date on rank 0 of the fd->comm. + * + * should probably be a void fn. + */ +int ADIOI_cb_bcast_rank_map(ADIO_File fd) +{ + int my_rank; + char *value; + int error_code = MPI_SUCCESS; + static char myname[] = "ADIOI_cb_bcast_rank_map"; + char *p; + int i; + + MPI_Bcast(&(fd->hints->cb_nodes), 1, MPI_INT, 0, fd->comm); + if (fd->hints->cb_nodes > 0) { + MPI_Comm_rank(fd->comm, &my_rank); + if (my_rank != 0) { + fd->hints->ranklist = ADIOI_Malloc(fd->hints->cb_nodes*sizeof(int)); + if (fd->hints->ranklist == NULL) { + error_code = MPIO_Err_create_code(error_code, + MPIR_ERR_RECOVERABLE, + myname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + return error_code; + } + } + MPI_Bcast(fd->hints->ranklist, fd->hints->cb_nodes, MPI_INT, 0, + fd->comm); + } + /* TEMPORARY -- REMOVE WHEN NO LONGER UPDATING INFO FOR + * FS-INDEP. */ + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", fd->hints->cb_nodes); + ADIOI_Info_set(fd->info, "cb_nodes", value); + p = value; + /* the (by MPI rank) list of aggregators can be larger than + * MPI_MAX_INFO_VAL, so we will simply truncate when we reach capacity. I + * wasn't clever enough to figure out how to rewind and put '...' at the + * end in the truncate case */ + for (i=0; i< fd->hints->cb_nodes; i++) { + int incr, remain = (MPI_MAX_INFO_VAL) - (p-value); + incr = ADIOI_Snprintf(p, remain, "%d ", fd->hints->ranklist[i]); + if (incr >= remain) break; + p += incr; + } + ADIOI_Info_set(fd->info, "romio_aggregator_list", value); + ADIOI_Free(value); + + return 0; +} + +/* ADIOI_cb_gather_name_array() - gather a list of processor names from all processes + * in a communicator and store them on rank 0. + * + * This is a collective call on the communicator(s) passed in. + * + * Obtains a rank-ordered list of processor names from the processes in + * "dupcomm". + * + * Returns 0 on success, -1 on failure. + * + * NOTE: Needs some work to cleanly handle out of memory cases! + */ +int ADIOI_cb_gather_name_array(MPI_Comm comm, + MPI_Comm dupcomm, + ADIO_cb_name_array *arrayp) +{ + char my_procname[MPI_MAX_PROCESSOR_NAME], **procname = 0; + int *procname_len = NULL, my_procname_len, *disp = NULL, i; + int commsize, commrank, found; + ADIO_cb_name_array array = NULL; + int alloc_size; + + if (ADIOI_cb_config_list_keyval == MPI_KEYVAL_INVALID) { + /* cleaned up by ADIOI_End_call */ + MPI_Keyval_create((MPI_Copy_function *) ADIOI_cb_copy_name_array, + (MPI_Delete_function *) ADIOI_cb_delete_name_array, + &ADIOI_cb_config_list_keyval, NULL); + } + else { + MPI_Attr_get(comm, ADIOI_cb_config_list_keyval, (void *) &array, &found); + if (found) { + ADIOI_Assert(array != NULL); + *arrayp = array; + return 0; + } + } + + MPI_Comm_size(dupcomm, &commsize); + MPI_Comm_rank(dupcomm, &commrank); + + MPI_Get_processor_name(my_procname, &my_procname_len); + + /* allocate space for everything */ + array = (ADIO_cb_name_array) ADIOI_Malloc(sizeof(*array)); + if (array == NULL) { + return -1; + } + array->refct = 2; /* we're going to associate this with two comms */ + + if (commrank == 0) { + /* process 0 keeps the real list */ + array->namect = commsize; + + array->names = (char **) ADIOI_Malloc(sizeof(char *) * commsize); + if (array->names == NULL) { + return -1; + } + procname = array->names; /* simpler to read */ + + procname_len = (int *) ADIOI_Malloc(commsize * sizeof(int)); + if (procname_len == NULL) { + return -1; + } + } + else { + /* everyone else just keeps an empty list as a placeholder */ + array->namect = 0; + array->names = NULL; + } + /* gather lengths first */ + MPI_Gather(&my_procname_len, 1, MPI_INT, + procname_len, 1, MPI_INT, 0, dupcomm); + + if (commrank == 0) { +#ifdef CB_CONFIG_LIST_DEBUG + for (i=0; i < commsize; i++) { + FPRINTF(stderr, "len[%d] = %d\n", i, procname_len[i]); + } +#endif + + alloc_size = 0; + for (i=0; i < commsize; i++) { + /* add one to the lengths because we need to count the + * terminator, and we are going to use this list of lengths + * again in the gatherv. + */ + alloc_size += ++procname_len[i]; + } + + procname[0] = ADIOI_Malloc(alloc_size); + if (procname[0] == NULL) { + return -1; + } + + for (i=1; i < commsize; i++) { + procname[i] = procname[i-1] + procname_len[i-1]; + } + + /* create our list of displacements for the gatherv. we're going + * to do everything relative to the start of the region allocated + * for procname[0] + */ + disp = ADIOI_Malloc(commsize * sizeof(int)); + disp[0] = 0; + for (i=1; i < commsize; i++) { + disp[i] = (int) (procname[i] - procname[0]); + } + + } + + /* now gather strings */ + if (commrank == 0) { + MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR, + procname[0], procname_len, disp, MPI_CHAR, + 0, dupcomm); + } + else { + /* if we didn't do this, we would need to allocate procname[] + * on all processes...which seems a little silly. + */ + MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR, + NULL, NULL, NULL, MPI_CHAR, 0, dupcomm); + } + + if (commrank == 0) { + /* no longer need the displacements or lengths */ + ADIOI_Free(disp); + ADIOI_Free(procname_len); + +#ifdef CB_CONFIG_LIST_DEBUG + for (i=0; i < commsize; i++) { + FPRINTF(stderr, "name[%d] = %s\n", i, procname[i]); + } +#endif + } + + /* store the attribute; we want to store SOMETHING on all processes + * so that they can all tell if we have gone through this procedure + * or not for the given communicator. + * + * specifically we put it on both the original comm, so we can find + * it next time an open is performed on this same comm, and on the + * dupcomm, so we can use it in I/O operations. + */ + MPI_Attr_put(comm, ADIOI_cb_config_list_keyval, array); + MPI_Attr_put(dupcomm, ADIOI_cb_config_list_keyval, array); + *arrayp = array; + return 0; +} + + +/* ADIOI_cb_config_list_parse() - parse the cb_config_list and build the + * ranklist + * + * Parameters: + * (pretty self explanatory) + * + * Returns number of ranks allocated in parsing, -1 on error. + */ +int ADIOI_cb_config_list_parse(char *config_list, + ADIO_cb_name_array array, + int ranklist[], + int cb_nodes) +{ + int token, max_procs, cur_rank = 0, nr_procnames; + char *cur_procname, *cur_procname_p, **procnames; + char *used_procnames; + + nr_procnames = array->namect; + procnames = array->names; + + /* nothing big goes on the stack */ + /* we use info val here and for yylval because we know the string + * cannot be any bigger than this. + */ + cur_procname = ADIOI_Malloc((MPI_MAX_INFO_VAL+1) * sizeof(char)); + if (cur_procname == NULL) { + return -1; + } + + yylval = ADIOI_Malloc((MPI_MAX_INFO_VAL+1) * sizeof(char)); + if (yylval == NULL) { + ADIOI_Free(cur_procname); + return -1; + } + + token_ptr = config_list; + + /* right away let's make sure cb_nodes isn't too big */ + if (cb_nodes > nr_procnames) cb_nodes = nr_procnames; + + /* used_procnames is used as a mask so that we don't have to destroy + * our procnames array + */ + used_procnames = ADIOI_Malloc(array->namect * sizeof(char)); + if (used_procnames == NULL) { + ADIOI_Free(cur_procname); + ADIOI_Free(yylval); + yylval = NULL; + return -1; + } + memset(used_procnames, 0, array->namect); + + /* optimization for "*:*"; arguably this could be done before we + * build the list of processor names...but that would make things + * messy. + */ + if (strcmp(config_list, "*:*") == 0) { + for (cur_rank = 0; cur_rank < cb_nodes; cur_rank++) { + ranklist[cur_rank] = cur_rank; + } + ADIOI_Free(cur_procname); + ADIOI_Free(yylval); + yylval = NULL; + ADIOI_Free(used_procnames); + return cb_nodes; + } + + while (cur_rank < cb_nodes) { + token = cb_config_list_lex(); + + if (token == AGG_EOS) { + ADIOI_Free(cur_procname); + ADIOI_Free(yylval); + yylval = NULL; + ADIOI_Free(used_procnames); + return cur_rank; + } + + if (token != AGG_WILDCARD && token != AGG_STRING) { + /* maybe ignore and try to keep going? */ + FPRINTF(stderr, "error parsing config list\n"); + ADIOI_Free(cur_procname); + ADIOI_Free(yylval); + yylval = NULL; + ADIOI_Free(used_procnames); + return cur_rank; + } + + if (token == AGG_WILDCARD) { + cur_procname_p = NULL; + } + else { + /* AGG_STRING is the only remaining case */ + /* save procname (for now) */ + ADIOI_Strncpy(cur_procname, yylval, MPI_MAX_INFO_VAL+1); + cur_procname_p = cur_procname; + } + + /* after we have saved the current procname, we can grab max_procs */ + max_procs = get_max_procs(cb_nodes); + +#ifdef CB_CONFIG_LIST_DEBUG + if (token == AGG_WILDCARD) { + FPRINTF(stderr, "looking for *:%d\n", max_procs); + } + else { + FPRINTF(stderr, "looking for %s:%d\n", cur_procname, max_procs); + } +#endif + + /* do the matching for this piece of the cb_config_list */ + match_procs(cur_procname_p, max_procs, procnames, used_procnames, + nr_procnames, ranklist, cb_nodes, &cur_rank); + } + ADIOI_Free(cur_procname); + ADIOI_Free(yylval); + yylval = NULL; + ADIOI_Free(used_procnames); + return cur_rank; +} + +/* ADIOI_cb_copy_name_array() - attribute copy routine + */ +int ADIOI_cb_copy_name_array(MPI_Comm comm, + int keyval, + void *extra, + void *attr_in, + void **attr_out, + int *flag) +{ + ADIO_cb_name_array array; + + ADIOI_UNREFERENCED_ARG(comm); + ADIOI_UNREFERENCED_ARG(keyval); + ADIOI_UNREFERENCED_ARG(extra); + + array = (ADIO_cb_name_array) attr_in; + if (array != NULL) array->refct++; + + *attr_out = attr_in; + *flag = 1; /* make a copy in the new communicator */ + + return MPI_SUCCESS; +} + +/* ADIOI_cb_delete_name_array() - attribute destructor + */ +int ADIOI_cb_delete_name_array(MPI_Comm comm, + int keyval, + void *attr_val, + void *extra) +{ + ADIO_cb_name_array array; + + ADIOI_UNREFERENCED_ARG(comm); + ADIOI_UNREFERENCED_ARG(extra); + + array = (ADIO_cb_name_array) attr_val; + ADIOI_Assert(array != NULL); + array->refct--; + + if (array->refct <= 0) { + /* time to free the structures (names, array of ptrs to names, struct) + */ + if (array->namect) { + /* Note that array->names[i], where i > 0, + * are just pointers into the allocated region array->names[0] + */ + ADIOI_Free(array->names[0]); + } + if (array->names != NULL) ADIOI_Free(array->names); + ADIOI_Free(array); + } + return MPI_SUCCESS; +} + +/* match_procs() - given a name (or NULL for wildcard) and a max. number + * of aggregator processes (per processor name), this + * matches in the procnames[] array and puts appropriate + * ranks in the ranks array. + * + * Parameters: + * name - processor name (or NULL for wildcard) + * max_per_proc - maximum # of processes to use for aggregation from a + * single processor + * procnames - array of processor names + * nr_procnames - length of procnames array + * ranks - array of process ranks + * nr_ranks - length of process ranks array (also max. # of aggregators) + * nr_ranks_allocated - # of array entries which have been filled in, + * which is also the index to the first empty entry + * + * Returns number of matches. + */ +static int match_procs(char *name, + int max_per_proc, + char *procnames[], + char used_procnames[], + int nr_procnames, + int ranks[], + int nr_ranks, + int *nr_ranks_allocated) +{ + int wildcard_proc, cur_proc, old_nr_allocated, ret; + + /* save this so we can report on progress */ + old_nr_allocated = *nr_ranks_allocated; + + if (name == NULL) { + /* wildcard case */ + + /* optimize for *:0 case */ + if (max_per_proc == 0) { + /* loop through procnames and mark them all as used */ + for (cur_proc = 0; cur_proc < nr_procnames; cur_proc++) { + used_procnames[cur_proc] = 1; + } + return 0; + } + + /* the plan here is to start at the beginning of the procnames + * array looking for processor names to apply the wildcard to. + * + * we set wildcard_proc to 0 here but do the search inside the + * while loop so that we aren't starting our search from the + * beginning of the procnames array each time. + */ + wildcard_proc = 0; + + while (nr_ranks - *nr_ranks_allocated > 0) { + /* find a name */ + while ((wildcard_proc < nr_procnames) && + (used_procnames[wildcard_proc] != 0)) + { + wildcard_proc++; + } + + if (wildcard_proc == nr_procnames) { + /* we have used up the entire procnames list */ + return *nr_ranks_allocated - old_nr_allocated; + } + +#ifdef CB_CONFIG_LIST_DEBUG + FPRINTF(stderr, "performing wildcard match (*:%d) starting with %s (%d)\n", + max_per_proc, procnames[wildcard_proc], wildcard_proc); +#endif + + cur_proc = wildcard_proc; + +#ifdef CB_CONFIG_LIST_DEBUG + FPRINTF(stderr, " assigning name %s (%d) to rank %d in mapping\n", + procnames[cur_proc], cur_proc, *nr_ranks_allocated); +#endif + + /* alloc max_per_proc from this host; cur_proc points to + * the first one. We want to save this name for use in + * our while loop. + */ + ranks[*nr_ranks_allocated] = cur_proc; + *nr_ranks_allocated = *nr_ranks_allocated + 1; + cur_proc++; + + /* so, to accomplish this we use the match_this_proc() to + * alloc max_per_proc-1. we increment cur_proc so that the + * procnames[] entry doesn't get trashed. then AFTER the call + * we clean up the first instance of the name. + */ + ret = match_this_proc(procnames[wildcard_proc], cur_proc, + max_per_proc-1, procnames, used_procnames, + nr_procnames, + ranks, nr_ranks, *nr_ranks_allocated); + if (ret > 0) *nr_ranks_allocated = *nr_ranks_allocated + ret; + + /* clean up and point wildcard_proc to the next entry, since + * we know that this one is NULL now. + */ + used_procnames[wildcard_proc] = 1; + wildcard_proc++; + } + } + else { + /* specific host was specified; this one is easy */ +#ifdef CB_CONFIG_LIST_DEBUG + FPRINTF(stderr, "performing name match (%s:%d)\n", name, max_per_proc); +#endif + + ret = match_this_proc(name, 0, max_per_proc, procnames, used_procnames, + nr_procnames, ranks, nr_ranks, + *nr_ranks_allocated); + if (ret > 0) *nr_ranks_allocated = *nr_ranks_allocated + ret; + } + return *nr_ranks_allocated - old_nr_allocated; +} + +/* match_this_proc() - find each instance of processor name "name" in + * the "procnames" array, starting with index "cur_proc" + * and add the first "max_matches" into the "ranks" + * array. remove all instances of "name" from + * "procnames". + * + * Parameters: + * name - processor name to match + * cur_proc - index into procnames[] at which to start matching + * procnames - array of processor names + * used_procnames - array of values indicating if a given procname has + * been allocated or removed already + * nr_procnames - length of procnames array + * ranks - array of processor ranks + * nr_ranks - length of ranks array + * nr_ranks_allocated - number of ranks already filled in, or the next + * entry to fill in (equivalent) + * + * Returns number of ranks filled in (allocated). + */ +static int match_this_proc(char *name, + int cur_proc, + int max_matches, + char *procnames[], + char used_procnames[], + int nr_procnames, + int ranks[], + int nr_ranks, + int nr_ranks_allocated) +{ + int ranks_remaining, nr_to_alloc, old_nr_allocated; + + old_nr_allocated = nr_ranks_allocated; + + /* calculate how many ranks we want to allocate */ + ranks_remaining = nr_ranks - nr_ranks_allocated; + nr_to_alloc = (max_matches < ranks_remaining) ? + max_matches : ranks_remaining; + + while (nr_to_alloc > 0) { + cur_proc = find_name(name, procnames, used_procnames, nr_procnames, + cur_proc); + if (cur_proc < 0) { + /* didn't find it */ + return nr_ranks_allocated - old_nr_allocated; + } + + /* need bounds checking on ranks */ +#ifdef CB_CONFIG_LIST_DEBUG + FPRINTF(stderr, " assigning name %s (%d) to rank %d in mapping\n", + procnames[cur_proc], cur_proc, nr_ranks_allocated); +#endif + + ranks[nr_ranks_allocated] = cur_proc; + nr_ranks_allocated++; + used_procnames[cur_proc] = 1; + + cur_proc++; + nr_to_alloc--; + } + + /* take all other instances of this host out of the list */ + while (cur_proc >= 0) { + cur_proc = find_name(name, procnames, used_procnames, nr_procnames, + cur_proc); + if (cur_proc >= 0) { +#ifdef CB_CONFIG_LIST_DEBUG + FPRINTF(stderr, " taking name %s (%d) out of procnames\n", + procnames[cur_proc], cur_proc); +#endif + used_procnames[cur_proc] = 1; + cur_proc++; + } + } + return nr_ranks_allocated - old_nr_allocated; +} + + +/* find_name() - finds the first entry in procnames[] which matches name, + * starting at index start_ind + * + * Returns an index [0..nr_procnames-1] on success, -1 if not found. + */ +static int find_name(char *name, + char *procnames[], + char used_procnames[], + int nr_procnames, + int start_ind) +{ + int i; + + for (i=start_ind; i < nr_procnames; i++) { + if (!used_procnames[i] && !strcmp(name, procnames[i])) break; + } + + if (i < nr_procnames) return i; + else return -1; +} + +/* get_max_procs() - grab the maximum number of processes to use out of + * the cb_config_list string + * + * Parameters: + * cb_nodes - cb_nodes value. this is returned when a "*" is encountered + * as the max_procs value. + * + * Returns # of processes, or -1 on error. + */ +static int get_max_procs(int cb_nodes) +{ + int token, max_procs = -1; + char *errptr; + + token = cb_config_list_lex(); + + switch(token) { + case AGG_EOS: + case AGG_COMMA: + return 1; + case AGG_COLON: + token = cb_config_list_lex(); + if (token != AGG_WILDCARD && token != AGG_STRING) return -1; + if (token == AGG_WILDCARD) max_procs = cb_nodes; + else if (token == AGG_STRING) { + max_procs = (int)strtol(yylval, &errptr, 10); + if (*errptr != '\0') { + /* some garbage value; default to 1 */ + max_procs = 1; + } + } + /* strip off next comma (if there is one) */ + token = cb_config_list_lex(); + if (token != AGG_COMMA && token != AGG_EOS) return -1; + + /* return max_procs */ + if (max_procs < 0) return -1; + else return max_procs; + } + return -1; +} + + +/* cb_config_list_lex() - lexical analyzer for cb_config_list language + * + * Returns a token of types defined at top of this file. + */ +#if defined(ROMIO_GPFS) +/* On BlueGene, the ',' character shows up in get_processor_name, so we have to + * use a different delimiter */ +#define COLON ':' +#define COMMA ';' +#define DELIMS ":;" +#else +/* these tokens work for every other platform */ +#define COLON ':' +#define COMMA ',' +#define DELIMS ":," +#endif + +static int cb_config_list_lex(void) +{ + int slen; + + if (*token_ptr == '\0') return AGG_EOS; + + slen = (int)strcspn(token_ptr, DELIMS); + + if (*token_ptr == COLON) { + token_ptr++; + return AGG_COLON; + } + if (*token_ptr == COMMA) { + token_ptr++; + return AGG_COMMA; + } + + if (*token_ptr == '*') { + /* make sure that we don't have characters after the '*' */ + if (slen == 1) { + token_ptr++; + return AGG_WILDCARD; + } + else return AGG_ERROR; + } + + /* last case: some kind of string. for now we copy the string. */ + + /* it would be a good idea to look at the string and make sure that + * it doesn't have any illegal characters in it. in particular we + * should ensure that no one tries to use wildcards with strings + * (e.g. "ccn*"). + */ + ADIOI_Strncpy(yylval, token_ptr, slen); + yylval[slen] = '\0'; + token_ptr += slen; + return AGG_STRING; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/eof_offset.c b/ompi/mca/io/romio314/romio/adio/common/eof_offset.c new file mode 100644 index 0000000000..0fb3539fc1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/eof_offset.c @@ -0,0 +1,78 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +/* return the current end of file in etype units relative to the + current view */ + +void ADIOI_Get_eof_offset(ADIO_File fd, ADIO_Offset *eof_offset) +{ + MPI_Count filetype_size; + int error_code, filetype_is_contig; + ADIO_Offset fsize, disp, sum=0, size_in_file, n_filetypes, rem, etype_size; + int flag, i; + ADIO_Fcntl_t *fcntl_struct; + MPI_Aint filetype_extent; + ADIOI_Flatlist_node *flat_file; + + /* find the eof in bytes */ + fcntl_struct = (ADIO_Fcntl_t *) ADIOI_Malloc(sizeof(ADIO_Fcntl_t)); + ADIO_Fcntl(fd, ADIO_FCNTL_GET_FSIZE, fcntl_struct, &error_code); + fsize = fcntl_struct->fsize; + ADIOI_Free(fcntl_struct); + + /* Find the offset in etype units corresponding to eof. + The eof could lie in a hole in the current view, or in the + middle of an etype. In that case the offset will be the offset + corresponding to the start of the next etype in the current view.*/ + + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + etype_size = fd->etype_size; + + if (filetype_is_contig) + *eof_offset = (fsize - fd->disp + etype_size - 1)/etype_size; + /* ceiling division in case fsize is not a multiple of etype_size;*/ + else { + /* filetype already flattened in ADIO_Open */ + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) + flat_file = flat_file->next; + + MPI_Type_size_x(fd->filetype, &filetype_size); + MPI_Type_extent(fd->filetype, &filetype_extent); + + disp = fd->disp; + n_filetypes = -1; + flag = 0; + while (!flag) { + sum = 0; + n_filetypes++; + for (i=0; icount; i++) { + sum += flat_file->blocklens[i]; + if (disp + flat_file->indices[i] + + n_filetypes* ADIOI_AINT_CAST_TO_OFFSET filetype_extent + + flat_file->blocklens[i] >= fsize) { + if (disp + flat_file->indices[i] + + n_filetypes * ADIOI_AINT_CAST_TO_OFFSET filetype_extent >= fsize) + sum -= flat_file->blocklens[i]; + else { + rem = (disp + flat_file->indices[i] + + n_filetypes* ADIOI_AINT_CAST_TO_OFFSET filetype_extent + + flat_file->blocklens[i] - fsize); + sum -= rem; + } + flag = 1; + break; + } + } + } + size_in_file = n_filetypes*(ADIO_Offset)filetype_size + sum; + *eof_offset = (size_in_file+etype_size-1)/etype_size; /* ceiling division */ + } +} diff --git a/ompi/mca/io/romio314/romio/adio/common/error.c b/ompi/mca/io/romio314/romio/adio/common/error.c new file mode 100644 index 0000000000..e990a5e181 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/error.c @@ -0,0 +1,127 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +/* NOTE: THIS FUNCTION IS DEPRECATED AND ONLY EXISTS HERE BECAUSE + * SOME DEPRECATED ADIO IMPLEMENTATIONS STILL CALL IT (SFS, HFS, PIOFS). + */ +int ADIOI_Error(ADIO_File fd, int error_code, char *string) +{ + char buf[MPI_MAX_ERROR_STRING]; + int myrank, result_len; + MPI_Errhandler err_handler; + + if (fd == ADIO_FILE_NULL) err_handler = ADIOI_DFLT_ERR_HANDLER; + else err_handler = fd->err_handler; + + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + if (err_handler == MPI_ERRORS_ARE_FATAL) { + MPI_Error_string(error_code, buf, &result_len); + FPRINTF(stderr, "[%d] - %s : %s\n", myrank, string, buf); + MPI_Abort(MPI_COMM_WORLD, 1); + } + else if (err_handler != MPI_ERRORS_RETURN) { + /* MPI_File_call_errorhandler(fd, error_code); */ + + FPRINTF(stderr, "Only MPI_ERRORS_RETURN and MPI_ERRORS_ARE_FATAL are currently supported as error handlers for files\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + return error_code; +} +/* Check for special error codes for those MPI error + classes that relate to particular problems. + Returns an MPI error code corresponding to "my_errno", for function "myname" + * and the given file, "filename". */ +int ADIOI_Err_create_code(const char *myname, const char *filename, int my_errno) +{ + int error_code = MPI_SUCCESS; + if(!my_errno) return MPI_SUCCESS; + + /* --BEGIN ERROR HANDLING-- */ + switch(my_errno) { + case EACCES: + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_ACCESS, + "**fileaccess", + "**fileaccess %s", + filename ); + break; + case ENAMETOOLONG: + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_BAD_FILE, + "**filenamelong", + "**filenamelong %s %d", + filename, + strlen(filename)); + break; + case ENOENT: + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_NO_SUCH_FILE, + "**filenoexist", + "**filenoexist %s", + filename); + break; + case EISDIR: + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_BAD_FILE, + "**filenamedir", + "**filenamedir %s", + filename); + break; + case EROFS: + /* Read only file or file system and write access requested */ + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_READ_ONLY, + "**ioneedrd", 0 ); + break; + case EEXIST: + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_FILE_EXISTS, + "**fileexist", 0); + break; + case ENOTDIR: + case ELOOP: + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_BAD_FILE, + "**filenamedir", + "**filenamedir %s", + filename); + break; + case ENOSPC: + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_NO_SPACE, + "**filenospace", 0); + break; + case EDQUOT: + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_QUOTA, + "**filequota", 0); + + default: + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, "**io", + "**io %s", strerror(my_errno)); + break; + } + /* --END ERROR HANDLING-- */ + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/flatten.c b/ompi/mca/io/romio314/romio/adio/common/flatten.c new file mode 100644 index 0000000000..86c2875e55 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/flatten.c @@ -0,0 +1,1168 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +/* #ifdef MPISGI +#include "mpisgi2.h" +#endif */ + +#ifdef USE_DBG_LOGGING + #define FLATTEN_DEBUG 1 +#endif + +void ADIOI_Optimize_flattened(ADIOI_Flatlist_node *flat_type); +/* flatten datatype and add it to Flatlist */ +void ADIOI_Flatten_datatype(MPI_Datatype datatype) +{ +#ifdef HAVE_MPIR_TYPE_FLATTEN + MPI_Aint flatten_idx; +#endif + MPI_Count curr_index=0; + int is_contig; + ADIOI_Flatlist_node *flat, *prev=0; + + /* check if necessary to flatten. */ + + /* is it entirely contiguous? */ + ADIOI_Datatype_iscontig(datatype, &is_contig); + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten_datatype:: is_contig %#X\n",is_contig); + #endif + if (is_contig) return; + + /* has it already been flattened? */ + flat = ADIOI_Flatlist; + while (flat) { + if (flat->type == datatype) { + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten_datatype:: found datatype %#X\n", datatype); + #endif + return; + } + else { + prev = flat; + flat = flat->next; + } + } + + /* flatten and add to the list */ + flat = prev; + flat->next = (ADIOI_Flatlist_node *)ADIOI_Malloc(sizeof(ADIOI_Flatlist_node)); + flat = flat->next; + + flat->type = datatype; + flat->next = NULL; + flat->blocklens = NULL; + flat->indices = NULL; + + flat->count = ADIOI_Count_contiguous_blocks(datatype, &curr_index); +#ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten_datatype:: count %llX, cur_idx = %#llX\n",flat->count,curr_index); +#endif +/* DBG_FPRINTF(stderr, "%d\n", flat->count);*/ + + if (flat->count) { + flat->blocklens = (ADIO_Offset *) ADIOI_Malloc(flat->count * sizeof(ADIO_Offset)); + flat->indices = (ADIO_Offset *) ADIOI_Malloc(flat->count * sizeof(ADIO_Offset)); + } + + curr_index = 0; +#ifdef HAVE_MPIR_TYPE_FLATTEN + flatten_idx = (MPI_Aint) flat->count; + MPIR_Type_flatten(datatype, flat->indices, flat->blocklens, &flatten_idx); + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten_datatype:: MPIR_Type_flatten\n"); + #endif +#else + ADIOI_Flatten(datatype, flat, 0, &curr_index); + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten_datatype:: ADIOI_Flatten\n"); + #endif + + ADIOI_Optimize_flattened(flat); +#endif +/* debug */ +#ifdef FLATTEN_DEBUG + { + int i; + for (i=0; icount; i++) + DBG_FPRINTF(stderr,"ADIOI_Flatten_datatype:: i %#X, blocklens %#llX, indices %#llX\n", + i, + flat->blocklens[i], + flat->indices[i] + ); + } +#endif + +} + +/* ADIOI_Flatten() + * + * Assumption: input datatype is not a basic!!!! + */ +void ADIOI_Flatten(MPI_Datatype datatype, ADIOI_Flatlist_node *flat, + ADIO_Offset st_offset, MPI_Count *curr_index) +{ + int i, k, m, n, basic_num, nonzeroth, is_hindexed_block=0; + int combiner, old_combiner, old_is_contig; + int nints, nadds, ntypes, old_nints, old_nadds, old_ntypes; + /* By using ADIO_Offset we preserve +/- sign and + avoid >2G integer arithmetic problems */ + ADIO_Offset top_count; + MPI_Count j, old_size, prev_index, num; + MPI_Aint old_extent;/* Assume extents are non-negative */ + int *ints; + MPI_Aint *adds; /* Make no assumptions about +/- sign on these */ + MPI_Datatype *types; + MPI_Type_get_envelope(datatype, &nints, &nadds, &ntypes, &combiner); + ints = (int *) ADIOI_Malloc((nints+1)*sizeof(int)); + adds = (MPI_Aint *) ADIOI_Malloc((nadds+1)*sizeof(MPI_Aint)); + types = (MPI_Datatype *) ADIOI_Malloc((ntypes+1)*sizeof(MPI_Datatype)); + MPI_Type_get_contents(datatype, nints, nadds, ntypes, ints, adds, types); + + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: st_offset %#llX, curr_index %#llX\n",st_offset,*curr_index); + DBG_FPRINTF(stderr,"ADIOI_Flatten:: nints %#X, nadds %#X, ntypes %#X\n",nints, nadds, ntypes); + for(i=0; i< nints; ++i) + { + DBG_FPRINTF(stderr,"ADIOI_Flatten:: ints[%d]=%#X\n",i,ints[i]); + } + for(i=0; i< nadds; ++i) + { + DBG_FPRINTF(stderr,"ADIOI_Flatten:: adds[%d]="MPI_AINT_FMT_HEX_SPEC"\n",i,adds[i]); + } + for(i=0; i< ntypes; ++i) + { + DBG_FPRINTF(stderr,"ADIOI_Flatten:: types[%d]=%#llX\n",i,(unsigned long long)(unsigned long)types[i]); + } + #endif + /* Chapter 4, page 83: when processing datatypes, note this item from the + * standard: + Most datatype constructors have replication count or block length + arguments. Allowed values are non-negative integers. If the value is + zero, no elements are generated in the type map and there is no effect + on datatype bounds or extent. */ + + switch (combiner) { +#ifdef MPIIMPL_HAVE_MPI_COMBINER_DUP + case MPI_COMBINER_DUP: + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_DUP\n"); + #endif + MPI_Type_get_envelope(types[0], &old_nints, &old_nadds, + &old_ntypes, &old_combiner); + ADIOI_Datatype_iscontig(types[0], &old_is_contig); + if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig)) + ADIOI_Flatten(types[0], flat, st_offset, curr_index); + break; +#endif +#ifdef MPIIMPL_HAVE_MPI_COMBINER_SUBARRAY + case MPI_COMBINER_SUBARRAY: + { + int dims = ints[0]; + MPI_Datatype stype; + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_SUBARRAY\n"); + #endif + + ADIO_Type_create_subarray(dims, + &ints[1], /* sizes */ + &ints[dims+1], /* subsizes */ + &ints[2*dims+1], /* starts */ + ints[3*dims+1], /* order */ + types[0], /* type */ + &stype); + ADIOI_Flatten(stype, flat, st_offset, curr_index); + MPI_Type_free(&stype); + } + break; +#endif +#ifdef MPIIMPL_HAVE_MPI_COMBINER_DARRAY + case MPI_COMBINER_DARRAY: + { + int dims = ints[2]; + MPI_Datatype dtype; + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_DARRAY\n"); + #endif + + ADIO_Type_create_darray(ints[0], /* size */ + ints[1], /* rank */ + dims, + &ints[3], /* gsizes */ + &ints[dims+3], /* distribs */ + &ints[2*dims+3], /* dargs */ + &ints[3*dims+3], /* psizes */ + ints[4*dims+3], /* order */ + types[0], + &dtype); + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_DARRAY indices[%#X] %#llX, flat->blocklens[%#X] %#llX, st_offset %#llX, curr_index %#llX);\n", + 0, flat->indices[0], 0, flat->blocklens[0], st_offset, *curr_index); + #endif + ADIOI_Flatten(dtype, flat, st_offset, curr_index); + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_DARRAY >ADIOI_Flatten(dtype, flat->indices[%#X] %#llX, flat->blocklens[%#X] %#llX, st_offset %#llX, curr_index %#llX);\n", + 0, flat->indices[0], 0, flat->blocklens[0], st_offset, *curr_index); + #endif + MPI_Type_free(&dtype); + } + break; +#endif + case MPI_COMBINER_CONTIGUOUS: + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_CONTIGUOUS\n"); + #endif + top_count = ints[0]; + MPI_Type_get_envelope(types[0], &old_nints, &old_nadds, + &old_ntypes, &old_combiner); + ADIOI_Datatype_iscontig(types[0], &old_is_contig); + + prev_index = *curr_index; + if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig)) + ADIOI_Flatten(types[0], flat, st_offset, curr_index); + + if (prev_index == *curr_index) { +/* simplest case, made up of basic or contiguous types */ + j = *curr_index; + flat->indices[j] = st_offset; + MPI_Type_size_x(types[0], &old_size); + flat->blocklens[j] = top_count * old_size; + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: simple flat->indices[%#llX] %#llX, flat->blocklens[%#llX] %#llX\n",j, flat->indices[j], j, flat->blocklens[j]); + #endif + (*curr_index)++; + } + else { +/* made up of noncontiguous derived types */ + j = *curr_index; + num = *curr_index - prev_index; + +/* The noncontiguous types have to be replicated count times */ + MPI_Type_extent(types[0], &old_extent); + for (m=1; mindices[j] = flat->indices[j-num] + ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[j] = flat->blocklens[j-num]; + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: derived flat->indices[%#llX] %#llX, flat->blocklens[%#llX] %#llX\n",j, flat->indices[j], j, flat->blocklens[j]); + #endif + j++; + } + } + *curr_index = j; + } + break; + + case MPI_COMBINER_VECTOR: + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_VECTOR\n"); + #endif + top_count = ints[0]; + MPI_Type_get_envelope(types[0], &old_nints, &old_nadds, + &old_ntypes, &old_combiner); + ADIOI_Datatype_iscontig(types[0], &old_is_contig); + + prev_index = *curr_index; + if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig)) + ADIOI_Flatten(types[0], flat, st_offset, curr_index); + + if (prev_index == *curr_index) { +/* simplest case, vector of basic or contiguous types */ + /* By using ADIO_Offset we preserve +/- sign and + avoid >2G integer arithmetic problems */ + ADIO_Offset blocklength = ints[1], stride = ints[2]; + j = *curr_index; + flat->indices[j] = st_offset; + MPI_Type_size_x(types[0], &old_size); + flat->blocklens[j] = blocklength * old_size; + for (i=j+1; iindices[i] = flat->indices[i-1] + stride * old_size; + flat->blocklens[i] = flat->blocklens[j]; + } + *curr_index = i; + } + else { +/* vector of noncontiguous derived types */ + /* By using ADIO_Offset we preserve +/- sign and + avoid >2G integer arithmetic problems */ + ADIO_Offset blocklength = ints[1], stride = ints[2]; + + j = *curr_index; + num = *curr_index - prev_index; + +/* The noncontiguous types have to be replicated blocklen times + and then strided. Replicate the first one. */ + MPI_Type_extent(types[0], &old_extent); + for (m=1; mindices[j] = flat->indices[j-num] + ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[j] = flat->blocklens[j-num]; + j++; + } + } + *curr_index = j; + +/* Now repeat with strides. */ + num = *curr_index - prev_index; + for (i=1; iindices[j] = flat->indices[j-num] + stride * ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[j] = flat->blocklens[j-num]; + j++; + } + } + *curr_index = j; + } + break; + + case MPI_COMBINER_HVECTOR: + case MPI_COMBINER_HVECTOR_INTEGER: + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_HVECTOR_INTEGER\n"); + #endif + top_count = ints[0]; + MPI_Type_get_envelope(types[0], &old_nints, &old_nadds, + &old_ntypes, &old_combiner); + ADIOI_Datatype_iscontig(types[0], &old_is_contig); + + prev_index = *curr_index; + if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig)) + ADIOI_Flatten(types[0], flat, st_offset, curr_index); + + if (prev_index == *curr_index) { +/* simplest case, vector of basic or contiguous types */ + /* By using ADIO_Offset we preserve +/- sign and + avoid >2G integer arithmetic problems */ + ADIO_Offset blocklength = ints[1]; + j = *curr_index; + flat->indices[j] = st_offset; + MPI_Type_size_x(types[0], &old_size); + flat->blocklens[j] = blocklength * old_size; + for (i=j+1; iindices[i] = flat->indices[i-1] + adds[0]; + flat->blocklens[i] = flat->blocklens[j]; + } + *curr_index = i; + } + else { +/* vector of noncontiguous derived types */ + /* By using ADIO_Offset we preserve +/- sign and + avoid >2G integer arithmetic problems */ + ADIO_Offset blocklength = ints[1]; + + j = *curr_index; + num = *curr_index - prev_index; + +/* The noncontiguous types have to be replicated blocklen times + and then strided. Replicate the first one. */ + MPI_Type_extent(types[0], &old_extent); + for (m=1; mindices[j] = flat->indices[j-num] + ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[j] = flat->blocklens[j-num]; + j++; + } + } + *curr_index = j; + +/* Now repeat with strides. */ + num = *curr_index - prev_index; + for (i=1; iindices[j] = flat->indices[j-num] + adds[0]; + flat->blocklens[j] = flat->blocklens[j-num]; + j++; + } + } + *curr_index = j; + } + break; + + case MPI_COMBINER_INDEXED: + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_INDEXED\n"); + #endif + top_count = ints[0]; + MPI_Type_get_envelope(types[0], &old_nints, &old_nadds, + &old_ntypes, &old_combiner); + ADIOI_Datatype_iscontig(types[0], &old_is_contig); + MPI_Type_extent(types[0], &old_extent); + + prev_index = *curr_index; + if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig)) + { + /* By using ADIO_Offset we preserve +/- sign and + avoid >2G integer arithmetic problems */ + ADIO_Offset stride = ints[top_count+1]; + ADIOI_Flatten(types[0], flat, + st_offset+stride* ADIOI_AINT_CAST_TO_OFFSET old_extent, curr_index); + } + + if (prev_index == *curr_index) { +/* simplest case, indexed type made up of basic or contiguous types */ + j = *curr_index; + for (i=j, nonzeroth=i; i2G integer arithmetic problems */ + ADIO_Offset blocklength = ints[1+i-j], stride = ints[top_count+1+i-j]; + if (blocklength > 0) { + flat->indices[nonzeroth] = + st_offset + stride* ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[nonzeroth] = + blocklength* ADIOI_AINT_CAST_TO_OFFSET old_extent; + nonzeroth++; + } else { + flat->count--; /* don't count/consider any zero-length blocklens */ + } + } + *curr_index = i; + } + else { +/* indexed type made up of noncontiguous derived types */ + + j = *curr_index; + num = *curr_index - prev_index; + basic_num = num; + +/* The noncontiguous types have to be replicated blocklens[i] times + and then strided. Replicate the first one. */ + for (m=1; mblocklens[j-num] > 0) { + flat->indices[nonzeroth] = + flat->indices[nonzeroth-num] + ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[nonzeroth] = + flat->blocklens[nonzeroth-num]; + j++; + nonzeroth++; + } else { + flat->count --; + } + } + } + *curr_index = j; + +/* Now repeat with strides. */ + for (i=1; i2G integer arithmetic problems */ + ADIO_Offset stride = ints[top_count+1+i]-ints[top_count+i]; + if (flat->blocklens[j-num] > 0 ) { + flat->indices[nonzeroth] = + flat->indices[j-num] + stride* ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[nonzeroth] = flat->blocklens[j-num]; + j++; + nonzeroth++; + } else { + flat->count--; + } + } + *curr_index = j; + for (m=1; mblocklens[j-basic_num] > 0) { + flat->indices[nonzeroth] = + flat->indices[j-basic_num] + ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[nonzeroth] = flat->blocklens[j-basic_num]; + j++; + nonzeroth++; + } else { + flat->count --; + } + } + } + *curr_index = j; + } + } + break; + +#if defined HAVE_DECL_MPI_COMBINER_HINDEXED_BLOCK && HAVE_DECL_MPI_COMBINER_HINDEXED_BLOCK + case MPI_COMBINER_HINDEXED_BLOCK: + is_hindexed_block=1; + /* deliberate fall-through */ +#endif + case MPI_COMBINER_INDEXED_BLOCK: + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_INDEXED_BLOCK\n"); + #endif + top_count = ints[0]; + MPI_Type_get_envelope(types[0], &old_nints, &old_nadds, + &old_ntypes, &old_combiner); + ADIOI_Datatype_iscontig(types[0], &old_is_contig); + MPI_Type_extent(types[0], &old_extent); + + prev_index = *curr_index; + if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig)) + { + /* By using ADIO_Offset we preserve +/- sign and + avoid >2G integer arithmetic problems */ + ADIO_Offset stride = ints[1+1]; + if (is_hindexed_block) { + ADIOI_Flatten(types[0], flat, + st_offset+adds[0], curr_index); + } else { + ADIOI_Flatten(types[0], flat, + st_offset+stride* ADIOI_AINT_CAST_TO_OFFSET old_extent, curr_index); + } + } + + if (prev_index == *curr_index) { +/* simplest case, indexed type made up of basic or contiguous types */ + j = *curr_index; + for (i=j; i2G integer arithmetic problems */ + ADIO_Offset blocklength = ints[1]; + if (is_hindexed_block) { + flat->indices[i] = st_offset + adds[i-j]; + } else { + ADIO_Offset stride = ints[1+1+i-j]; + flat->indices[i] = st_offset + + stride* ADIOI_AINT_CAST_TO_OFFSET old_extent; + } + flat->blocklens[i] = blocklength* ADIOI_AINT_CAST_TO_OFFSET old_extent; + } + *curr_index = i; + } + else { +/* vector of noncontiguous derived types */ + + j = *curr_index; + num = *curr_index - prev_index; + +/* The noncontiguous types have to be replicated blocklens[i] times + and then strided. Replicate the first one. */ + for (m=1; mindices[j] = flat->indices[j-num] + + ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[j] = flat->blocklens[j-num]; + j++; + } + } + *curr_index = j; + +/* Now repeat with strides. */ + num = *curr_index - prev_index; + for (i=1; iindices[j] = flat->indices[j-num] + + adds[i] - adds[i-1]; + } else { + /* By using ADIO_Offset we preserve +/- sign and + avoid >2G integer arithmetic problems */ + ADIO_Offset stride = ints[2+i]-ints[1+i]; + flat->indices[j] = flat->indices[j-num] + + stride* ADIOI_AINT_CAST_TO_OFFSET old_extent; + } + flat->blocklens[j] = flat->blocklens[j-num]; + j++; + } + } + *curr_index = j; + } + break; + + case MPI_COMBINER_HINDEXED: + case MPI_COMBINER_HINDEXED_INTEGER: + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_HINDEXED_INTEGER\n"); + #endif + top_count = ints[0]; + MPI_Type_get_envelope(types[0], &old_nints, &old_nadds, + &old_ntypes, &old_combiner); + ADIOI_Datatype_iscontig(types[0], &old_is_contig); + + prev_index = *curr_index; + if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig)) + { + ADIOI_Flatten(types[0], flat, st_offset+adds[0], curr_index); + } + + if (prev_index == *curr_index) { +/* simplest case, indexed type made up of basic or contiguous types */ + j = *curr_index; + MPI_Type_size_x(types[0], &old_size); + for (i=j, nonzeroth=j; i 0) { + /* By using ADIO_Offset we preserve +/- sign and + avoid >2G integer arithmetic problems */ + ADIO_Offset blocklength = ints[1+i-j]; + flat->indices[nonzeroth] = st_offset + adds[i-j]; + flat->blocklens[nonzeroth] = blocklength*old_size; + nonzeroth++; + } else { + flat->count--; + } + } + *curr_index = i; + } + else { +/* indexed type made up of noncontiguous derived types */ + + j = *curr_index; + num = *curr_index - prev_index; + basic_num = num; + +/* The noncontiguous types have to be replicated blocklens[i] times + and then strided. Replicate the first one. */ + MPI_Type_extent(types[0], &old_extent); + for (m=1; mblocklens[j-num] > 0) { + flat->indices[nonzeroth] = + flat->indices[j-num] + ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[nonzeroth] = flat->blocklens[j-num]; + j++; + nonzeroth++; + } else { + flat->count--; + } + } + } + *curr_index = j; + +/* Now repeat with strides. */ + for (i=1; iblocklens[j-num] > 0) { + flat->indices[nonzeroth] = + flat->indices[j-num] + adds[i] - adds[i-1]; + flat->blocklens[nonzeroth] = flat->blocklens[j-num]; + j++; + nonzeroth++; + } else { + flat->count--; + } + } + *curr_index = j; + for (m=1; mblocklens[j-basic_num] >0) { + flat->indices[nonzeroth] = + flat->indices[j-basic_num] + ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[nonzeroth] = flat->blocklens[j-basic_num]; + j++; + nonzeroth++; + } + } + } + *curr_index = j; + } + } + break; + + case MPI_COMBINER_STRUCT: + case MPI_COMBINER_STRUCT_INTEGER: + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_STRUCT_INTEGER\n"); + #endif + top_count = ints[0]; + for (n=0; n2G integer arithmetic problems */ + if (ints[1+n] > 0 || types[n] == MPI_LB || types[n] == MPI_UB) { + ADIO_Offset blocklength = ints[1+n]; + j = *curr_index; + flat->indices[j] = st_offset + adds[n]; + MPI_Type_size_x(types[n], &old_size); + flat->blocklens[j] = blocklength * old_size; +#ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: simple adds[%#X] "MPI_AINT_FMT_HEX_SPEC", flat->indices[%#llX] %#llX, flat->blocklens[%#llX] %#llX\n",n,adds[n],j, flat->indices[j], j, flat->blocklens[j]); +#endif + (*curr_index)++; + } + } + else { +/* current type made up of noncontiguous derived types */ + + j = *curr_index; + num = *curr_index - prev_index; + +/* The current type has to be replicated blocklens[n] times */ + MPI_Type_extent(types[n], &old_extent); + for (m=1; mindices[j] = + flat->indices[j-num] + ADIOI_AINT_CAST_TO_OFFSET old_extent; + flat->blocklens[j] = flat->blocklens[j-num]; +#ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: simple old_extent "MPI_AINT_FMT_HEX_SPEC", flat->indices[%#llX] %#llX, flat->blocklens[%#llX] %#llX\n",old_extent,j, flat->indices[j], j, flat->blocklens[j]); +#endif + j++; + } + } + *curr_index = j; + } + } + break; + + case MPI_COMBINER_RESIZED: + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: MPI_COMBINER_RESIZED\n"); + #endif + + /* This is done similar to a type_struct with an lb, datatype, ub */ + + /* handle the Lb */ + j = *curr_index; + flat->indices[j] = st_offset + adds[0]; + /* this zero-length blocklens[] element, unlike eleswhere in the + * flattening code, is correct and is used to indicate a lower bound + * marker */ + flat->blocklens[j] = 0; + + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: simple adds[%#X] "MPI_AINT_FMT_HEX_SPEC", flat->indices[%#llX] %#llX, flat->blocklens[%#llX] %#llX\n",0,adds[0],j, flat->indices[j], j, flat->blocklens[j]); + #endif + + (*curr_index)++; + + /* handle the datatype */ + + MPI_Type_get_envelope(types[0], &old_nints, &old_nadds, + &old_ntypes, &old_combiner); + ADIOI_Datatype_iscontig(types[0], &old_is_contig); + + if ((old_combiner != MPI_COMBINER_NAMED) && (!old_is_contig)) { + ADIOI_Flatten(types[0], flat, st_offset+adds[0], curr_index); + } + else { + /* current type is basic or contiguous */ + j = *curr_index; + flat->indices[j] = st_offset; + MPI_Type_size_x(types[0], &old_size); + flat->blocklens[j] = old_size; + + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: simple adds[%#X] "MPI_AINT_FMT_HEX_SPEC", flat->indices[%#llX] %#llX, flat->blocklens[%#llX] %#llX\n",0,adds[0],j, flat->indices[j], j, flat->blocklens[j]); + #endif + + (*curr_index)++; + } + + /* take care of the extent as a UB */ + j = *curr_index; + flat->indices[j] = st_offset + adds[0] + adds[1]; + /* again, zero-element ok: an upper-bound marker explicitly set by the + * constructor of this resized type */ + flat->blocklens[j] = 0; + + #ifdef FLATTEN_DEBUG + DBG_FPRINTF(stderr,"ADIOI_Flatten:: simple adds[%#X] "MPI_AINT_FMT_HEX_SPEC", flat->indices[%#llX] %#llX, flat->blocklens[%#llX] %#llX\n",1,adds[1],j, flat->indices[j], j, flat->blocklens[j]); + #endif + + (*curr_index)++; + + break; + + default: + /* TODO: FIXME (requires changing prototypes to return errors...) */ + DBG_FPRINTF(stderr, "Error: Unsupported datatype passed to ADIOI_Flatten\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + +#ifndef MPISGI +/* There is a bug in SGI's impl. of MPI_Type_get_contents. It doesn't + return new datatypes. Therefore no need to free. */ + for (i=0; icount - 1); i++) { + if ((flat_type->indices[i] + flat_type->blocklens[i] != + flat_type->indices[i + 1])) + opt_blocks++; + } + + /* if we can't reduce the number of blocks, quit now */ + if (opt_blocks == flat_type->count) return; + + opt_blocklens = (ADIO_Offset *) ADIOI_Malloc(opt_blocks * sizeof(ADIO_Offset)); + opt_indices = (ADIO_Offset *)ADIOI_Malloc(opt_blocks*sizeof(ADIO_Offset)); + + /* fill in new blocklists */ + opt_blocklens[0] = flat_type->blocklens[0]; + opt_indices[0] = flat_type->indices[0]; + j = 0; + for (i=0; i < (flat_type->count - 1); i++) { + if ((flat_type->indices[i] + flat_type->blocklens[i] == + flat_type->indices[i + 1])) + opt_blocklens[j] += flat_type->blocklens[i + 1]; + else { + j++; + opt_indices[j] = flat_type->indices[i + 1]; + opt_blocklens[j] = flat_type->blocklens[i + 1]; + } + } + flat_type->count = opt_blocks; + ADIOI_Free(flat_type->blocklens); + ADIOI_Free(flat_type->indices); + flat_type->blocklens = opt_blocklens; + flat_type->indices = opt_indices; + return; +} + +void ADIOI_Delete_flattened(MPI_Datatype datatype) +{ + ADIOI_Flatlist_node *flat, *prev; + + prev = flat = ADIOI_Flatlist; + while (flat && (flat->type != datatype)) { + prev = flat; + flat = flat->next; + } + if (flat) { + prev->next = flat->next; + if (flat->blocklens) ADIOI_Free(flat->blocklens); + if (flat->indices) ADIOI_Free(flat->indices); + ADIOI_Free(flat); + } +} diff --git a/ompi/mca/io/romio314/romio/adio/common/get_fp_posn.c b/ompi/mca/io/romio314/romio/adio/common/get_fp_posn.c new file mode 100644 index 0000000000..671dde3eb3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/get_fp_posn.c @@ -0,0 +1,60 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" +#include "adioi.h" + +/* returns the current position of the individual file pointer + in etype units relative to the current view. */ + +void ADIOI_Get_position(ADIO_File fd, ADIO_Offset *offset) +{ + ADIOI_Flatlist_node *flat_file; + int i, flag; + MPI_Count filetype_size, etype_size; + int filetype_is_contig; + MPI_Aint filetype_extent; + ADIO_Offset disp, byte_offset, sum=0, size_in_file, n_filetypes, frd_size; + + ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); + etype_size = fd->etype_size; + + if (filetype_is_contig) *offset = (fd->fp_ind - fd->disp)/etype_size; + else { +/* filetype already flattened in ADIO_Open */ + flat_file = ADIOI_Flatlist; + while (flat_file->type != fd->filetype) flat_file = flat_file->next; + + MPI_Type_size_x(fd->filetype, &filetype_size); + MPI_Type_extent(fd->filetype, &filetype_extent); + + disp = fd->disp; + byte_offset = fd->fp_ind; + n_filetypes = -1; + flag = 0; + while (!flag) { + sum = 0; + n_filetypes++; + for (i=0; icount; i++) { + sum += flat_file->blocklens[i]; + if (disp + flat_file->indices[i] + + n_filetypes* ADIOI_AINT_CAST_TO_OFFSET filetype_extent + flat_file->blocklens[i] + >= byte_offset) { + frd_size = disp + flat_file->indices[i] + + n_filetypes * ADIOI_AINT_CAST_TO_OFFSET filetype_extent + + flat_file->blocklens[i] - byte_offset; + sum -= frd_size; + flag = 1; + break; + } + } + } + size_in_file = n_filetypes * (ADIO_Offset)filetype_size + sum; + *offset = size_in_file/etype_size; + } +} diff --git a/ompi/mca/io/romio314/romio/adio/common/greq_fns.c b/ompi/mca/io/romio314/romio/adio/common/greq_fns.c new file mode 100644 index 0000000000..aff8ff77e5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/greq_fns.c @@ -0,0 +1,31 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpiu_greq.h" + +/* In cases where nonblocking operation will carry out blocking version, + * instantiate and complete a generalized request */ + +void MPIO_Completed_request_create(MPI_File *fh, MPI_Offset bytes, + int *error_code, MPI_Request *request) +{ + MPI_Status *status; + status = (MPI_Status *)ADIOI_Malloc(sizeof(MPI_Status)); + + status->MPI_ERROR = *error_code; +#ifdef HAVE_STATUS_SET_BYTES + MPIR_Status_set_bytes(status, MPI_BYTE, bytes); +#endif + /* --BEGIN ERROR HANDLING-- */ + if (*error_code != MPI_SUCCESS) + *error_code = MPIO_Err_return_file(*fh, *error_code); + /* --END ERROR HANDLING-- */ + MPI_Grequest_start(MPIU_Greq_query_fn, MPIU_Greq_free_fn, + MPIU_Greq_cancel_fn, status, request); + MPI_Grequest_complete(*request); +} diff --git a/ompi/mca/io/romio314/romio/adio/common/heap-sort.c b/ompi/mca/io/romio314/romio/adio/common/heap-sort.c new file mode 100644 index 0000000000..025a1a74c4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/heap-sort.c @@ -0,0 +1,133 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include +#include +#include +#include +#include "heap-sort.h" + +#define NOEXP2 + +static void heapify(heap_t *heap, int i); + +/* From Introduction To Algorithms by Cormen, Leiserson, and Rivest */ + +static inline int parent(int i) { + return (i/2); +} + +static inline int left(int i) { + return (2*i); +} + +static inline int right(int i) { + return (2*i + 1); +} + +int ADIOI_Heap_create(heap_t *heap, int size) { + heap->size = size; + heap->nodes = (heap_node_t *) ADIOI_Calloc (size, sizeof(heap_node_t)); + if (heap->nodes == NULL) + return 1; + else + return 0; +} + +void ADIOI_Heap_free(heap_t *heap) { + ADIOI_Free(heap->nodes); +} + +/* should suppress unused warnings on GCC */ +static void build_heap(heap_t *heap) ATTRIBUTE((unused, used)); + +static void build_heap(heap_t *heap) +{ + int i; + for (i=(heap->size/2-1); i >= 0; i--) + heapify(heap, i); +} + +static void heapify(heap_t *heap, int i) { + int l, r, smallest; + heap_node_t *nodes; + heap_node_t tmp_node; + + nodes = heap->nodes; + + l = left(i); + r = right(i); + + if ((l <= heap->size) && (nodes[l].offset < nodes[i].offset)) + smallest = l; + else + smallest = i; + + if ((r <= heap->size) && (nodes[r].offset < nodes[smallest].offset)) + smallest = r; + + if (smallest != i) { + tmp_node = nodes[i]; + nodes[i] = nodes[smallest]; + nodes[smallest] = tmp_node; + heapify(heap, smallest); + } +} + +void ADIOI_Heap_insert(heap_t *heap, ADIO_Offset offset, int proc, + ADIO_Offset reg_max_len) { + heap_node_t *nodes; + int i; + nodes = heap->nodes; + i = ++heap->size - 1; + while ((i > 0) && (nodes[parent(i)].offset > offset)) { + nodes[i] = nodes[parent(i)]; + i = parent(i); + } + nodes[i].offset = offset; + nodes[i].proc = proc; + nodes[i].reg_max_len = reg_max_len; +} + +void ADIOI_Heap_extract_min(heap_t *heap, ADIO_Offset* offset, int *proc, + ADIO_Offset *reg_max_len) { + heap_node_t *nodes; + nodes = heap->nodes; + + assert (heap->size > 0); + *offset = nodes[0].offset; + *proc = nodes[0].proc; + *reg_max_len = nodes[0].reg_max_len; + nodes[0] = nodes[heap->size-1]; + heap->size--; + heapify(heap, 0); +} + +/* should suppress unused warnings on GCC */ +static void print_heap(heap_t *heap) ATTRIBUTE((unused, used)); + +static void print_heap(heap_t *heap) +{ +#ifndef NOEXP2 + int i; + double level = 0; + int next_level_idx = 1; + + printf ("heap->size = %d\n", heap->size); + printf ("offsets:\n"); + for (i=0; i < heap->size; i++) { + printf ("%lld ", heap->nodes[i].offset); + + if ((i+1) == next_level_idx) { + printf ("\n"); + next_level_idx += (int) exp2(level+1); + level++; + } + } + printf ("\n"); +#endif +} diff --git a/ompi/mca/io/romio314/romio/adio/common/hint_fns.c b/ompi/mca/io/romio314/romio/adio/common/hint_fns.c new file mode 100644 index 0000000000..34c898bdfe --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/hint_fns.c @@ -0,0 +1,184 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2013 UChicago/Argonne, LLC + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "hint_fns.h" + + +int ADIOI_Info_check_and_install_int(ADIO_File fd, MPI_Info info, const char *key, + int *local_cache, char *funcname, int *error_code) +{ + int intval, tmp_val, flag; + char *value; + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + if (value == NULL) { + *error_code = MPIO_Err_create_code(*error_code, + MPIR_ERR_RECOVERABLE, + funcname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + return -1; + } + + ADIOI_Info_get(info, key, MPI_MAX_INFO_VAL, value, &flag); + if (flag) { + intval = atoi(value); + tmp_val = intval; + + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + /* --BEGIN ERROR HANDLING-- */ + if (tmp_val != intval) { + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(funcname, + key, + error_code); + return -1; + } + /* --END ERROR HANDLING-- */ + + ADIOI_Info_set(fd->info, key, value); + /* some file systems do not cache hints in the fd struct */ + if (local_cache != NULL) *local_cache = intval; + } + ADIOI_Free(value); + return 0; +} + +int ADIOI_Info_check_and_install_enabled(ADIO_File fd, MPI_Info info, const char *key, + int *local_cache, char *funcname, int *error_code) +{ + int tmp_val, flag; + char *value; + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + if (value == NULL) { + *error_code = MPIO_Err_create_code(*error_code, + MPIR_ERR_RECOVERABLE, + funcname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + return -1; + } + + ADIOI_Info_get(info, key, MPI_MAX_INFO_VAL, value, &flag); + if (flag) { + if (!strcmp(value, "enable") || !strcmp(value, "ENABLE")) { + ADIOI_Info_set(fd->info, key, value); + *local_cache = ADIOI_HINT_ENABLE; + } + else if (!strcmp(value, "disable") || !strcmp(value, "DISABLE")) { + ADIOI_Info_set(fd->info, key, value); + *local_cache = ADIOI_HINT_DISABLE; + } + else if (!strcmp(value, "automatic") || !strcmp(value, "AUTOMATIC")) + { + ADIOI_Info_set(fd->info, key, value); + *local_cache = ADIOI_HINT_AUTO; + } + + tmp_val = *local_cache; + + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + /* --BEGIN ERROR HANDLING-- */ + if (tmp_val != *local_cache) { + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(funcname, + key, + error_code); + return -1; + } + /* --END ERROR HANDLING-- */ + } + ADIOI_Free(value); + return 0; +} +int ADIOI_Info_check_and_install_true(ADIO_File fd, MPI_Info info, const char *key, + int *local_cache, char *funcname, int *error_code) +{ + int flag, tmp_val; + char *value; + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + if (value == NULL) { + *error_code = MPIO_Err_create_code(*error_code, + MPIR_ERR_RECOVERABLE, + funcname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + return -1; + } + + ADIOI_Info_get(info, key, MPI_MAX_INFO_VAL, value, &flag); + if (flag) { + if (!strcmp(value, "true") || !strcmp(value, "TRUE")) { + ADIOI_Info_set(fd->info, key, value); + *local_cache = 1; + } + else if (!strcmp(value, "false") || !strcmp(value, "FALSE")) { + ADIOI_Info_set(fd->info, key, value); + *local_cache = 0; + } + tmp_val = *local_cache; + + MPI_Bcast(&tmp_val, 1, MPI_INT, 0, fd->comm); + /* --BEGIN ERROR HANDLING-- */ + if (tmp_val != *local_cache) { + MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(funcname, + key, + error_code); + return -1; + } + /* --END ERROR HANDLING-- */ + } + + ADIOI_Free(value); + return 0; +} +int ADIOI_Info_check_and_install_str(ADIO_File fd, MPI_Info info, const char *key, + char **local_cache, char *funcname, int *error_code) +{ + int flag; + size_t len; + char *value; + + value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char)); + if (value == NULL) { + *error_code = MPIO_Err_create_code(*error_code, + MPIR_ERR_RECOVERABLE, + funcname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + return -1; + } + + ADIOI_Info_get(info, key, MPI_MAX_INFO_VAL, + value, &flag); + if (flag) { + ADIOI_Info_set(fd->info, "cb_config_list", value); + len = (strlen(value)+1) * sizeof(char); + *local_cache = ADIOI_Malloc(len); + if (*local_cache == NULL) { + *error_code = MPIO_Err_create_code(*error_code, + MPIR_ERR_RECOVERABLE, + funcname, + __LINE__, + MPI_ERR_OTHER, + "**nomem2",0); + return -1; + } + ADIOI_Strncpy(*local_cache, value, len); + } + /* if it has been set already, we ignore it the second time. + * otherwise we would get an error if someone used the same + * info value with a cb_config_list value in it in a couple + * of calls, which would be irritating. */ + ADIOI_Free(value); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/adio/common/iscontig.c b/ompi/mca/io/romio314/romio/adio/common/iscontig.c new file mode 100644 index 0000000000..3c8aa712f4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/iscontig.c @@ -0,0 +1,105 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +/* #ifdef MPISGI +#include "mpisgi2.h" +#endif */ + +#if defined(MPICH) +/* MPICH also provides this routine */ +void MPIR_Datatype_iscontig(MPI_Datatype datatype, int *flag); + +void ADIOI_Datatype_iscontig(MPI_Datatype datatype, int *flag) +{ + MPIR_Datatype_iscontig(datatype, flag); + + /* if the datatype is reported as contigous, check if the true_lb is + * non-zero, and if so, mark the datatype as noncontiguous */ + if (*flag) { + MPI_Aint true_extent, true_lb; + + MPI_Type_get_true_extent(datatype, &true_lb, &true_extent); + + if (true_lb > 0) + *flag = 0; + } +} + +#elif (defined(MPIHP) && defined(HAVE_MPI_INFO)) +/* i.e. HPMPI 1.4 only */ + +int hpmp_dtiscontig(MPI_Datatype datatype); + +void ADIOI_Datatype_iscontig(MPI_Datatype datatype, int *flag) +{ + *flag = hpmp_dtiscontig(datatype); +} + +#elif (defined(MPISGI) && !defined(NO_MPI_SGI_type_is_contig)) + +int MPI_SGI_type_is_contig(MPI_Datatype datatype); + +void ADIOI_Datatype_iscontig(MPI_Datatype datatype, int *flag) +{ + MPI_Aint displacement; + MPI_Type_lb(datatype, &distplacement); + + /* SGI's MPI_SGI_type_is_contig() returns true for indexed + * datatypes with holes at the beginning, which causes + * problems with ROMIO's use of this function. + */ + *flag = MPI_SGI_type_is_contig(datatype) && (displacement == 0); +} + +#elif defined(OMPI_BUILDING) && OMPI_BUILDING + +/* void ADIOI_Datatype_iscontig(MPI_Datatype datatype, int *flag) is defined + * and implemented in OpenMPI itself */ + +#else + +void ADIOI_Datatype_iscontig(MPI_Datatype datatype, int *flag) +{ + int nints, nadds, ntypes, combiner; + int *ints, ni, na, nt, cb; + MPI_Aint *adds; + MPI_Datatype *types; + + MPI_Type_get_envelope(datatype, &nints, &nadds, &ntypes, &combiner); + + switch (combiner) { + case MPI_COMBINER_NAMED: + *flag = 1; + break; + case MPI_COMBINER_CONTIGUOUS: + ints = (int *) ADIOI_Malloc((nints+1)*sizeof(int)); + adds = (MPI_Aint *) ADIOI_Malloc((nadds+1)*sizeof(MPI_Aint)); + types = (MPI_Datatype *) ADIOI_Malloc((ntypes+1)*sizeof(MPI_Datatype)); + MPI_Type_get_contents(datatype, nints, nadds, ntypes, ints, + adds, types); + ADIOI_Datatype_iscontig(types[0], flag); + +#ifndef MPISGI +/* There is a bug in SGI's impl. of MPI_Type_get_contents. It doesn't + return new datatypes. Therefore no need to free. */ + MPI_Type_get_envelope(types[0], &ni, &na, &nt, &cb); + if (cb != MPI_COMBINER_NAMED) MPI_Type_free(types); +#endif + + ADIOI_Free(ints); + ADIOI_Free(adds); + ADIOI_Free(types); + break; + default: + *flag = 0; + break; + } + + /* This function needs more work. It should check for contiguity + in other cases as well.*/ +} +#endif diff --git a/ompi/mca/io/romio314/romio/adio/common/lock.c b/ompi/mca/io/romio314/romio/adio/common/lock.c new file mode 100644 index 0000000000..2590d77433 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/lock.c @@ -0,0 +1,225 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef ROMIO_NTFS +/* This assumes that lock will always remain in the common directory and + * that the ntfs directory will always be called ad_ntfs. */ +#include "..\ad_ntfs\ad_ntfs.h" +int ADIOI_Set_lock(FDTYPE fd, int cmd, int type, ADIO_Offset offset, int whence, + ADIO_Offset len) +{ + static char myname[] = "ADIOI_Set_lock"; + int ret_val, error_code = MPI_SUCCESS; + OVERLAPPED Overlapped; + DWORD dwFlags; + + ADIOI_UNREFERENCED_ARG(whence); + + if (len == 0) return MPI_SUCCESS; + + dwFlags = type; + + Overlapped.hEvent = /*0;*/CreateEvent(NULL, TRUE, FALSE, NULL); +#ifdef HAVE_INT64 + Overlapped.Offset = ( (DWORD) ( offset & (__int64) 0xFFFFFFFF ) ); + Overlapped.OffsetHigh = ( (DWORD) ( (offset >> 32) & (__int64) 0xFFFFFFFF ) ); + + if (cmd == ADIOI_LOCK_CMD) + { + /*printf("locking %d\n", (int)fd);fflush(stdout);*/ + ret_val = LockFileEx(fd, dwFlags, 0, + ( (DWORD) ( len & (__int64) 0xFFFFFFFF ) ), + ( (DWORD) ( (len >> 32) & (__int64) 0xFFFFFFFF ) ), + &Overlapped); + } + else + { + /*printf("unlocking %d\n", (int)fd);fflush(stdout);*/ + ret_val = UnlockFileEx(fd, 0, + ( (DWORD) ( len & (__int64) 0xFFFFFFFF ) ), + ( (DWORD) ( (len >> 32) & (__int64) 0xFFFFFFFF ) ), + &Overlapped); + } +#else + Overlapped.Offset = offset; + Overlapped.OffsetHigh = 0; + + if (cmd == ADIOI_LOCK_CMD) + { + /*printf("locking %d\n", (int)fd);fflush(stdout);*/ + ret_val = LockFileEx(fd, dwFlags, 0, len, 0, &Overlapped); + } + else + { + /*printf("unlocking %d\n", (int)fd);fflush(stdout);*/ + ret_val = UnlockFileEx(fd, 0, len, 0, &Overlapped); + } +#endif + + if (!ret_val) + { + char errMsg[ADIOI_NTFS_ERR_MSG_MAX]; + /* + FPRINTF(stderr, "File locking failed in ADIOI_Set_lock.\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + */ + ret_val = GetLastError(); + if (ret_val == ERROR_IO_PENDING) + { + DWORD dummy; + ret_val = GetOverlappedResult(fd, &Overlapped, &dummy, TRUE); + if (ret_val) + { + CloseHandle(Overlapped.hEvent); + return MPI_SUCCESS; + } + ret_val = GetLastError(); + } + ADIOI_NTFS_Strerror(ret_val, errMsg, ADIOI_NTFS_ERR_MSG_MAX); + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_IO, "**io", "**io %s", errMsg); + } + CloseHandle(Overlapped.hEvent); + + return error_code; +} +#else +int ADIOI_Set_lock(FDTYPE fd, int cmd, int type, ADIO_Offset offset, int whence, + ADIO_Offset len) +{ + int err, error_code, err_count = 0, sav_errno; + struct flock lock; + + if (len == 0) return MPI_SUCCESS; + + + /* Depending on the compiler flags and options, struct flock + may not be defined with types that are the same size as + ADIO_Offsets. */ +/* FIXME: This is a temporary hack until we use flock64 where + available. It also doesn't fix the broken Solaris header sys/types.h + header file, which declars off_t as a UNION ! Configure tests to + see if the off64_t is a union if large file support is requested; + if so, it does not select large file support. +*/ +#ifdef NEEDS_INT_CAST_WITH_FLOCK + lock.l_type = type; + lock.l_start = (int)offset; + lock.l_whence = whence; + lock.l_len = (int)len; +#else + lock.l_type = type; + lock.l_whence = whence; + lock.l_start = offset; + lock.l_len = len; +#endif + + sav_errno = errno; /* save previous errno in case we recover from retryable errors */ + errno = 0; + do { + err = fcntl(fd, cmd, &lock); +#ifdef USE_DBG_LOGGING +/* if (MPIU_DBG_SELECTED(ROMIO,TERSE)) */ + { + if (err && ((errno == EINTR) || (errno == EINPROGRESS))) + { + if((err_count < 5) || (err_count > 9995)) + { + fprintf(stderr, "File locking failed in ADIOI_Set_lock(fd %#X,cmd %s/%#X,type %s/%#X,whence %#X) with return value %#X and errno %#X. Retry (%d).\n", + fd, + ((cmd == F_GETLK )? "F_GETLK" : + ((cmd == F_SETLK )? "F_SETLK" : + ((cmd == F_SETLKW )? "F_SETLKW" : "UNEXPECTED"))), + cmd, + ((type == F_RDLCK )? "F_RDLCK" : + ((type == F_WRLCK )? "F_WRLCK" : + ((type == F_UNLCK )? "F_UNLOCK" : "UNEXPECTED"))), + type, + whence, err, errno, err_count); + perror("ADIOI_Set_lock:"); + fprintf(stderr,"ADIOI_Set_lock:offset %#llx, length %#llx\n",(unsigned long long)offset, (unsigned long long)len); + } + } + } +#endif + } while (err && ((errno == EINTR) || ((errno == EINPROGRESS) && (++err_count < 10000)))); + + if (err && (errno != EBADF)) { + /* FIXME: This should use the error message system, + especially for MPICH */ + FPRINTF(stderr, "This requires fcntl(2) to be implemented. As of 8/25/2011 it is not. Generic MPICH Message: File locking failed in ADIOI_Set_lock(fd %X,cmd %s/%X,type %s/%X,whence %X) with return value %X and errno %X.\n" + "- If the file system is NFS, you need to use NFS version 3, ensure that the lockd daemon is running on all the machines, and mount the directory with the 'noac' option (no attribute caching).\n" + "- If the file system is LUSTRE, ensure that the directory is mounted with the 'flock' option.\n", + fd, + ((cmd == F_GETLK )? "F_GETLK" : + ((cmd == F_SETLK )? "F_SETLK" : + ((cmd == F_SETLKW )? "F_SETLKW" : "UNEXPECTED"))), + cmd, + ((type == F_RDLCK )? "F_RDLCK" : + ((type == F_WRLCK )? "F_WRLCK" : + ((type == F_UNLCK )? "F_UNLOCK" : "UNEXPECTED"))), + type, + whence, err, errno); + perror("ADIOI_Set_lock:"); + FPRINTF(stderr,"ADIOI_Set_lock:offset %llu, length %llu\n",(unsigned long long)offset, (unsigned long long)len); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if(!err) /* report fcntl failure errno's (EBADF), otherwise */ + errno = sav_errno; /* restore previous errno in case we recovered from retryable errors */ + + error_code = (err == 0) ? MPI_SUCCESS : MPI_ERR_UNKNOWN; + return error_code; +} +#endif + +#if (defined(ROMIO_HFS) || defined(ROMIO_XFS)) +int ADIOI_Set_lock64(FDTYPE fd, int cmd, int type, ADIO_Offset offset, + int whence, + ADIO_Offset len) +{ + int err, error_code; + struct flock64 lock; + + if (len == 0) return MPI_SUCCESS; + + lock.l_type = type; + lock.l_start = offset; + lock.l_whence = whence; + lock.l_len = len; + + do { + err = fcntl(fd, cmd, &lock); + } while (err && (errno == EINTR)); + + if (err && (errno != EBADF)) { + FPRINTF(stderr, "File locking failed in ADIOI_Set_lock64(fd %X,cmd %s/%X,type %s/%X,whence %X) with return value %X and errno %X.\n" + "If the file system is NFS, you need to use NFS version 3, ensure that the lockd daemon is running on all the machines, and mount the directory with the 'noac' option (no attribute caching).\n", + fd, + ((cmd == F_GETLK )? "F_GETLK" : + ((cmd == F_SETLK )? "F_SETLK" : + ((cmd == F_SETLKW )? "F_SETLKW" : + ((cmd == F_GETLK64 )? "F_GETLK64" : + ((cmd == F_SETLK64 )? "F_SETLK64" : + ((cmd == F_SETLKW64)? "F_SETLKW64" : "UNEXPECTED")))))), + cmd, + ((type == F_RDLCK )? "F_RDLCK" : + ((type == F_WRLCK )? "F_WRLCK" : + ((type == F_UNLCK )? "F_UNLOCK" : "UNEXPECTED"))), + type, + whence, err, errno); + perror("ADIOI_Set_lock64:"); + FPRINTF(stderr,"ADIOI_Set_lock:offset %llu, length %llu\n",(unsigned long long)offset, (unsigned long long)len); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + error_code = (err == 0) ? MPI_SUCCESS : MPI_ERR_UNKNOWN; + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/adio/common/malloc.c b/ompi/mca/io/romio314/romio/adio/common/malloc.c new file mode 100644 index 0000000000..73c5a70705 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/malloc.c @@ -0,0 +1,113 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* These are routines for allocating and deallocating memory. + They should be called as ADIOI_Malloc(size) and + ADIOI_Free(ptr). In adio.h, they are macro-replaced to + ADIOI_Malloc(size,__LINE__,__FILE__) and + ADIOI_Free(ptr,__LINE__,__FILE__). + + Later on, add some tracing and error checking, similar to + MPID_trmalloc. */ + +#include "adio.h" +#include "mpi.h" +#include +#include +#include "mpipr.h" + +#ifdef HAVE_MALLOC_H +#include +#endif + +/* for the style checker */ +/* style: allow:malloc:1 sig:0 */ +/* style: allow:free:1 sig:0 */ +/* style: allow:calloc:1 sig:0 */ +/* style: allow:realloc:1 sig:0 */ + +#define FPRINTF fprintf + +void *ADIOI_Malloc_fn(size_t size, int lineno, const char *fname); +void *ADIOI_Calloc_fn(size_t nelem, size_t elsize, int lineno, const char *fname); +void *ADIOI_Realloc_fn(void *ptr, size_t size, int lineno, const char *fname); +void ADIOI_Free_fn(void *ptr, int lineno, const char *fname); + +void *ADIOI_Malloc_fn(size_t size, int lineno, const char *fname) +{ + void *new; + +#ifdef ROMIO_XFS + new = (void *) memalign(XFS_MEMALIGN, size); +#else +#ifdef HAVE_MPIU_FUNCS + new = (void *) MPIU_trmalloc(size, lineno, fname); +#else + new = (void *) malloc(size); +#endif +#endif + if (!new && size) { + FPRINTF(stderr, "Out of memory in file %s, line %d\n", fname, lineno); + MPI_Abort(MPI_COMM_WORLD, 1); + } + DBG_FPRINTF(stderr, "ADIOI_Malloc %s:<%d> %p (%#zX)\n", fname, lineno, new, size); + return new; +} + + +void *ADIOI_Calloc_fn(size_t nelem, size_t elsize, int lineno, const char *fname) +{ + void *new; + +#ifdef HAVE_MPIU_FUNCS + new = (void *) MPIU_trcalloc(nelem, elsize, lineno, fname); +#else + new = (void *) calloc(nelem, elsize); +#endif + if (!new && nelem) { + FPRINTF(stderr, "Out of memory in file %s, line %d\n", fname, lineno); + MPI_Abort(MPI_COMM_WORLD, 1); + } + DBG_FPRINTF(stderr, "ADIOI_Calloc %s:<%d> %p\n", fname, lineno, new); + return new; +} + + +void *ADIOI_Realloc_fn(void *ptr, size_t size, int lineno, const char *fname) +{ + void *new; + +#ifdef HAVE_MPIU_FUNCS + new = (void *) MPIU_trrealloc(ptr, size, lineno, fname); +#else + new = (void *) realloc(ptr, size); +#endif + if (!new && size) { + FPRINTF(stderr, "realloc failed in file %s, line %d\n", fname, lineno); + MPI_Abort(MPI_COMM_WORLD, 1); + } + DBG_FPRINTF(stderr, "ADIOI_Realloc %s:<%d> %p\n", fname, lineno, new); + return new; +} + + +void ADIOI_Free_fn(void *ptr, int lineno, const char *fname) +{ + DBG_FPRINTF(stderr, "ADIOI_Free %s:<%d> %p\n", fname, lineno, ptr); + if (!ptr) { + FPRINTF(stderr, "Attempt to free null pointer in file %s, line %d\n", fname, lineno); + MPI_Abort(MPI_COMM_WORLD, 1); + } + +#ifdef HAVE_MPIU_FUNCS + MPIU_trfree(ptr, lineno, fname); +#else + free(ptr); +#endif +} + + diff --git a/ompi/mca/io/romio314/romio/adio/common/p2p_aggregation.c b/ompi/mca/io/romio314/romio/adio/common/p2p_aggregation.c new file mode 100644 index 0000000000..89e891bea4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/p2p_aggregation.c @@ -0,0 +1,910 @@ +#include "adio.h" +#include "adio_extern.h" +#include "../ad_gpfs/ad_gpfs_tuning.h" + +#include + +/* #define p2pcontigtrace 1 */ + +void ADIOI_P2PContigWriteAggregation(ADIO_File fd, + const void *buf, + int *error_code, + ADIO_Offset *st_offsets, + ADIO_Offset *end_offsets, + ADIO_Offset *fd_start, + ADIO_Offset* fd_end) +{ + + *error_code = MPI_SUCCESS; /* initialize to success */ + +#ifdef ROMIO_GPFS + double startTimeBase,endTimeBase; +#endif + + MPI_Status status; + pthread_t io_thread; + void *thread_ret; + ADIOI_IO_ThreadFuncData io_thread_args; + + int nprocs,myrank; + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + ADIO_Offset myOffsetStart = st_offsets[myrank], myOffsetEnd = end_offsets[myrank]; + + int myAggRank = -1; /* if I am an aggregor this is my index into fd->hints->ranklist */ + int iAmUsedAgg = 0; + +#ifdef ROMIO_GPFS + startTimeBase = MPI_Wtime(); +#endif + + int naggs = fd->hints->cb_nodes; + int coll_bufsize = fd->hints->cb_buffer_size; +#ifdef ROMIO_GPFS + if (gpfsmpio_pthreadio == 1) { + /* split buffer in half for a kind of double buffering with the threads*/ + coll_bufsize = fd->hints->cb_buffer_size/2; + } +#endif + + int j; + for (j=0;jhints->ranklist[j] == myrank) { + myAggRank = j; + if (fd_end[j] > fd_start[j]) { + iAmUsedAgg = 1; + } + } + } + + /* Determine how much data and to whom I need to send. For source proc + * targets, also determine the target file domain offsets locally to + * reduce communication overhead */ + int *targetAggsForMyData = (int *)ADIOI_Malloc(naggs * sizeof(int)); + ADIO_Offset *targetAggsForMyDataFDStart = (ADIO_Offset *)ADIOI_Malloc(naggs * sizeof(ADIO_Offset)); + ADIO_Offset *targetAggsForMyDataFDEnd = (ADIO_Offset *)ADIOI_Malloc(naggs * sizeof(ADIO_Offset)); + int numTargetAggs = 0; + int i; + for (i=0;i= fd_start[i]) && (myOffsetStart <= fd_end[i])) || ((myOffsetEnd >= fd_start[i]) && (myOffsetEnd <= fd_end[i]))) { + targetAggsForMyData[numTargetAggs] = fd->hints->ranklist[i]; + targetAggsForMyDataFDStart[numTargetAggs] = fd_start[i]; + targetAggsForMyDataFDEnd[numTargetAggs] = fd_end[i]; + numTargetAggs++; + } + } + + /* these 3 arrays track info on the procs that feed an aggregtor */ + int *sourceProcsForMyData=NULL; + int *remainingDataAmountToGetPerProc=NULL; + ADIO_Offset *remainingDataOffsetToGetPerProc=NULL; + + int numSourceProcs = 0; + + if (iAmUsedAgg) { /* for the used aggregators figure out how much data I + need from what procs */ + + /* count numSourceProcs so we know how large to make the arrays */ + for (i=0;i= fd_start[myAggRank]) && (st_offsets[i] <= fd_end[myAggRank])) || ((end_offsets[i] >= fd_start[myAggRank]) && (end_offsets[i] <= fd_end[myAggRank]))) + numSourceProcs++; + + sourceProcsForMyData = (int *)ADIOI_Malloc(numSourceProcs * sizeof(int)); + remainingDataAmountToGetPerProc = (int *)ADIOI_Malloc(numSourceProcs * sizeof(int)); + remainingDataOffsetToGetPerProc = (ADIO_Offset *)ADIOI_Malloc(numSourceProcs * sizeof(ADIO_Offset)); + + /* everybody has the st_offsets and end_offsets for all ranks so if I am a + * used aggregator go thru them and figure out which ranks have data that + * falls into my file domain assigned to me */ + numSourceProcs = 0; + for (i=0;i= fd_start[myAggRank]) && (st_offsets[i] <= fd_end[myAggRank])) || ((end_offsets[i] >= fd_start[myAggRank]) && (end_offsets[i] <= fd_end[myAggRank]))) { + sourceProcsForMyData[numSourceProcs] = i; + if ( ((st_offsets[i] >= fd_start[myAggRank]) && (st_offsets[i] <= fd_end[myAggRank])) && ((end_offsets[i] >= fd_start[myAggRank]) && (end_offsets[i] <= fd_end[myAggRank]))) { + remainingDataAmountToGetPerProc[numSourceProcs] = (end_offsets[i] - st_offsets[i])+1; + remainingDataOffsetToGetPerProc[numSourceProcs] = st_offsets[i]; + } + else if ((st_offsets[i] >= fd_start[myAggRank]) && (st_offsets[i] <= fd_end[myAggRank])) {/* starts in this fd and goes past it */ + remainingDataAmountToGetPerProc[numSourceProcs] = (fd_end[myAggRank] - st_offsets[i]) +1; + remainingDataOffsetToGetPerProc[numSourceProcs] = st_offsets[i]; + } + else { /* starts in fd before this and ends in it */ + remainingDataAmountToGetPerProc[numSourceProcs] = (end_offsets[i] - fd_start[myAggRank]) +1; + remainingDataOffsetToGetPerProc[numSourceProcs] = fd_start[myAggRank]; + } +#ifdef p2pcontigtrace + printf("getting %ld bytes from source proc %d in fd rank %d with borders %ld to %ld\n",remainingDataAmountToGetPerProc[numSourceProcs],i,fd->hints->ranklist[myAggRank],fd_start[myAggRank],fd_end[myAggRank]); +#endif + numSourceProcs++; + } + } + } + + int *amountOfDataReqestedByTargetAgg = (int *)ADIOI_Malloc(naggs * sizeof(int)); + for (i=0;iio_buf; + char *write_buf1 = fd->io_buf + coll_bufsize; + + /* start off pointing to the first buffer. If we use the 2nd buffer (threaded + * case) we'll swap later */ + char *write_buf = write_buf0; + + /* compute number of rounds */ + ADIO_Offset numberOfRounds = (ADIO_Offset)((((ADIO_Offset)(end_offsets[nprocs-1]-st_offsets[0]))/((ADIO_Offset)((ADIO_Offset)coll_bufsize*(ADIO_Offset)naggs)))) + 1; + + int currentWriteBuf = 0; + int useIOBuffer = 0; +#ifdef ROMIO_GPFS + if (gpfsmpio_pthreadio && (numberOfRounds>1)) { + useIOBuffer = 1; + io_thread = pthread_self(); + } +#endif + + ADIO_Offset currentRoundFDStart = 0; + ADIO_Offset currentRoundFDEnd = 0; + + if (iAmUsedAgg) { + currentRoundFDStart = fd_start[myAggRank]; + } + + int *dataSizeGottenThisRoundPerProc = (int *)ADIOI_Malloc(numSourceProcs * sizeof(int)); + int *mpiRequestMapPerProc = (int *)ADIOI_Malloc(numSourceProcs * sizeof(int)); + int *targetAggIndexesForMyDataThisRound = (int *)ADIOI_Malloc(numTargetAggs * sizeof(int)); + int *sendBufferOffsetsThisRound = (int *)ADIOI_Malloc(numTargetAggs * sizeof(int)); + int *bufferAmountsToSendThisRound = (int *)ADIOI_Malloc(numTargetAggs * sizeof(int)); + +#ifdef ROMIO_GPFS + endTimeBase = MPI_Wtime(); + gpfsmpio_prof_cw[GPFSMPIO_CIO_T_MYREQ] += (endTimeBase-startTimeBase); + startTimeBase = MPI_Wtime(); +#endif + + /* each iteration of this loop writes a coll_bufsize portion of the file + * domain */ + int roundIter; + for (roundIter=0;roundIter= targetAggsForMyDataFDStart[i]) && (myOffsetStart <= targetAggsForMyDataFDEnd[i])) || + ((myOffsetEnd >= targetAggsForMyDataFDStart[i]) && (myOffsetEnd <= targetAggsForMyDataFDEnd[i]))) { + /* we know that we need to send data to this target agg at some point, now need to figure out how much this round */ + + /* here are the offsets currently being collected by the aggregator during this round */ + ADIO_Offset currentRoundFDStartForMyTargetAgg = (ADIO_Offset)((ADIO_Offset)targetAggsForMyDataFDStart[i] + (ADIO_Offset)((ADIO_Offset)roundIter*(ADIO_Offset)coll_bufsize)); + ADIO_Offset currentRoundFDEndForMyTargetAgg = (ADIO_Offset)((ADIO_Offset)targetAggsForMyDataFDStart[i] + (ADIO_Offset)((ADIO_Offset)(roundIter+1)*(ADIO_Offset)coll_bufsize) - (ADIO_Offset)1); + if (currentRoundFDEndForMyTargetAgg > targetAggsForMyDataFDEnd[i]) + currentRoundFDEndForMyTargetAgg = targetAggsForMyDataFDEnd[i]; + +#ifdef p2pcontigtrace + printf("roundIter %d target iter %d targetAggsForMyData is %d myOffsetStart is %ld myOffsetEnd is %ld targetAggsForMyDataFDStart is %ld targetAggsForMyDataFDEnd is %ld currentRoundFDStartForMyTargetAgg is %ld currentRoundFDEndForMyTargetAgg is %ld\n", + roundIter,i,targetAggsForMyData[i],myOffsetStart,myOffsetEnd, + targetAggsForMyDataFDStart[i],targetAggsForMyDataFDEnd[i], + currentRoundFDStartForMyTargetAgg,currentRoundFDEndForMyTargetAgg); +#endif + + /* send the portion of my data that is within + * currentRoundFDStartForMyTargetAgg to + * currentRoundFDEndForMyTargetAgg */ + /* find the offset into the send buffer and the amount + * of data to send */ + int sendBufferOffset = 0; + int bufferAmountToSend = 0; + + if ((myOffsetStart >= currentRoundFDStartForMyTargetAgg) && (myOffsetStart <= currentRoundFDEndForMyTargetAgg)) { + if (myOffsetEnd > currentRoundFDEndForMyTargetAgg) + bufferAmountToSend = (currentRoundFDEndForMyTargetAgg - myOffsetStart) +1; + else + bufferAmountToSend = (myOffsetEnd - myOffsetStart) +1; + } + else if ((myOffsetEnd >= currentRoundFDStartForMyTargetAgg) && (myOffsetEnd <= currentRoundFDEndForMyTargetAgg)) { + sendBufferOffset = (int) (currentRoundFDStartForMyTargetAgg - myOffsetStart); + if (myOffsetEnd > currentRoundFDEndForMyTargetAgg) + bufferAmountToSend = (currentRoundFDEndForMyTargetAgg - currentRoundFDStartForMyTargetAgg) +1; + else + bufferAmountToSend = (myOffsetEnd - currentRoundFDStartForMyTargetAgg) +1; + } + else if ((myOffsetStart <= currentRoundFDStartForMyTargetAgg) && (myOffsetEnd >= currentRoundFDEndForMyTargetAgg)) { + sendBufferOffset = (int) (currentRoundFDStartForMyTargetAgg - myOffsetStart); + bufferAmountToSend = (currentRoundFDEndForMyTargetAgg - currentRoundFDStartForMyTargetAgg) +1; + } + + if (bufferAmountToSend > 0) { /* we have data to send this round */ + targetAggIndexesForMyDataThisRound[numTargetAggsThisRound] = i; + sendBufferOffsetsThisRound[numTargetAggsThisRound] = sendBufferOffset; + bufferAmountsToSendThisRound[numTargetAggsThisRound] = bufferAmountToSend; +#ifdef p2pcontigtrace + printf("bufferAmountToSend is %d sendBufferOffset is %d\n",bufferAmountToSend,sendBufferOffset); +#endif + /* only need to be pinged by the agg for rounds after the first one - for the first one just + * send the data without being pinged */ + if (roundIter > 0) + MPI_Irecv(&amountOfDataReqestedByTargetAgg[numTargetAggsThisRound],1, + MPI_INT,targetAggsForMyData[i],0, + fd->comm,&mpiSizeToSendRequest[numTargetAggsThisRound]); + numTargetAggsThisRound++; + + } + } + } + + /* determine what offsets define the portion of the file domain the agg is writing this round */ + if (iAmUsedAgg) { + if ((fd_end[myAggRank] - currentRoundFDStart) < coll_bufsize) { + currentRoundFDEnd = fd_end[myAggRank]; + } + else + currentRoundFDEnd = currentRoundFDStart + coll_bufsize - 1; +#ifdef p2pcontigtrace + printf("currentRoundFDStart is %ld currentRoundFDEnd is %ld within file domeain %ld to %ld\n",currentRoundFDStart,currentRoundFDEnd,fd_start[myAggRank],fd_end[myAggRank]); +#endif + } + + int irecv,isend; + int numSourceProcsSentData = 0; + + /* the aggs send the amount of data they need to their source procs */ + for (i=0;i= currentRoundFDStart) && (remainingDataOffsetToGetPerProc[i] <= currentRoundFDEnd)) { + if ((remainingDataOffsetToGetPerProc[i] + remainingDataAmountToGetPerProc[i]) <= currentRoundFDEnd) + dataSizeGottenThisRoundPerProc[i] = remainingDataAmountToGetPerProc[i]; + else + dataSizeGottenThisRoundPerProc[i] = (currentRoundFDEnd - remainingDataOffsetToGetPerProc[i]) +1; + } + else if (((remainingDataOffsetToGetPerProc[i]+remainingDataAmountToGetPerProc[i]) >= currentRoundFDStart) && ((remainingDataOffsetToGetPerProc[i]+remainingDataAmountToGetPerProc[i]) <= currentRoundFDEnd)) { + if ((remainingDataOffsetToGetPerProc[i]) >= currentRoundFDStart) + dataSizeGottenThisRoundPerProc[i] = remainingDataAmountToGetPerProc[i]; + else + dataSizeGottenThisRoundPerProc[i] = (remainingDataOffsetToGetPerProc[i]-currentRoundFDStart) +1; + } + else + dataSizeGottenThisRoundPerProc[i] = 0; + +#ifdef p2pcontigtrace + printf("dataSizeGottenThisRoundPerProc[%d] set to %d - remainingDataOffsetToGetPerProc is %d remainingDataAmountToGetPerProc is %d currentRoundFDStart is %d currentRoundFDEnd is %d\n",i,dataSizeGottenThisRoundPerProc[i],remainingDataOffsetToGetPerProc[i],remainingDataAmountToGetPerProc[i],currentRoundFDStart,currentRoundFDEnd); +#endif + if (dataSizeGottenThisRoundPerProc[i] > 0) { + if (roundIter > 0) { + MPI_Isend(&dataSizeGottenThisRoundPerProc[i],1,MPI_INT, + sourceProcsForMyData[i],0,fd->comm, + &mpiSendDataSizeRequest[numSourceProcsSentData]); + numSourceProcsSentData++; + } + } + } + + int numDataSendToWaitFor = 0; + /* the source procs send the requested data to the aggs */ + for (i = 0; i < numTargetAggsThisRound; i++) { + + /* the source procs aren't pinged by the target aggs on the first round */ + if (roundIter > 0) { + + MPI_Waitany(numTargetAggsThisRound,mpiSizeToSendRequest, + &irecv,&mpiWaitAnyStatusFromTargetAggs); + +#ifdef p2pcontigtrace + printf("irecv is %d amountOfDataReqestedByTargetAgg is %d bufferAmountsToSendThisRound is %d sendBufferOffsetsThisRound is %d targetAggsForMyData is %d\n",irecv,amountOfDataReqestedByTargetAgg[irecv], bufferAmountsToSendThisRound[irecv], sendBufferOffsetsThisRound[irecv],targetAggsForMyData[targetAggIndexesForMyDataThisRound[irecv]]); +#endif + ADIOI_Assert(amountOfDataReqestedByTargetAgg[irecv] == bufferAmountsToSendThisRound[irecv]); + MPI_Isend(&((char*)buf)[sendBufferOffsetsThisRound[irecv]], + bufferAmountsToSendThisRound[irecv],MPI_BYTE, + targetAggsForMyData[targetAggIndexesForMyDataThisRound[irecv]], + 0,fd->comm,&mpiSendDataToTargetAggRequest[irecv]); + + } + else { +#ifdef p2pcontigtrace + printf("i is %d bufferAmountsToSendThisRound is %d sendBufferOffsetsThisRound is %d targetAggsForMyData is %d\n",i, bufferAmountsToSendThisRound[i], sendBufferOffsetsThisRound[i],targetAggsForMyData[targetAggIndexesForMyDataThisRound[i]]); +#endif + MPI_Isend(&((char*)buf)[sendBufferOffsetsThisRound[i]],bufferAmountsToSendThisRound[i],MPI_BYTE, + targetAggsForMyData[targetAggIndexesForMyDataThisRound[i]],0,fd->comm,&mpiSendDataToTargetAggRequest[i]); + } + numDataSendToWaitFor++; + } + +#ifdef ROMIO_GPFS + gpfsmpio_prof_cw[GPFSMPIO_CIO_T_DEXCH_SETUP] += (endTimeBase-startTimeBase); + startTimeBase = MPI_Wtime(); +#endif + + /* the aggs receive the data from the source procs */ + int numDataRecvToWaitFor = 0; + for (i=0;i 0 count data */ + if (dataSizeGottenThisRoundPerProc[i] > 0) { +#ifdef p2pcontigtrace + printf("receiving data from rank %d dataSizeGottenThisRoundPerProc is %d currentWBOffset is %d\n",sourceProcsForMyData[i],dataSizeGottenThisRoundPerProc[i],currentWBOffset); +#endif + MPI_Irecv(&((char*)write_buf)[currentWBOffset],dataSizeGottenThisRoundPerProc[i], + MPI_BYTE,sourceProcsForMyData[i],0, + fd->comm,&mpiRecvDataRequest[numDataRecvToWaitFor]); + mpiRequestMapPerProc[numDataRecvToWaitFor] = i; + numDataRecvToWaitFor++; + } + +#ifdef p2pcontigtrace + printf("MPI_Irecv from rank %d\n",targetAggsForMyData[i]); +#endif + } + + int totalDataReceivedThisRound = 0; + for (i = 0; i < numDataRecvToWaitFor; i++) { + MPI_Waitany(numDataRecvToWaitFor,mpiRecvDataRequest, + &irecv,&mpiWaitAnyStatusFromSourceProcs); + totalDataReceivedThisRound += + dataSizeGottenThisRoundPerProc[mpiRequestMapPerProc[irecv]]; + totalAmountDataReceived += + dataSizeGottenThisRoundPerProc[mpiRequestMapPerProc[irecv]]; + +#ifdef p2pcontigtrace + printf("numDataRecvToWaitFor is %d was sent %d bytes data for %d remaining bytes from rank %d irecv index %d\n",numDataRecvToWaitFor,dataSizeGottenThisRoundPerProc[mpiRequestMapPerProc[irecv]],remainingDataAmountToGetPerProc[mpiRequestMapPerProc[irecv]],sourceProcsForMyData[mpiRequestMapPerProc[irecv]],irecv); +#endif + remainingDataAmountToGetPerProc[mpiRequestMapPerProc[irecv]] -= + dataSizeGottenThisRoundPerProc[mpiRequestMapPerProc[irecv]]; + remainingDataOffsetToGetPerProc[mpiRequestMapPerProc[irecv]] += + dataSizeGottenThisRoundPerProc[mpiRequestMapPerProc[irecv]]; + + } + + /* clean up the MPI_Request object for the MPI_Isend which told the + * source procs how much data to send */ + for (i=0;i 0) { + +#ifdef p2pcontigtrace + printf("totalDataReceivedThisRound is %d\n",totalDataReceivedThisRound); +#endif + if (!useIOBuffer) { + + ADIO_WriteContig(fd, write_buf, (int)totalDataReceivedThisRound, + MPI_BYTE, ADIO_EXPLICIT_OFFSET, + currentRoundFDStart, &status, error_code); + } else { /* use the thread writer */ + + if(!pthread_equal(io_thread, pthread_self())) { + pthread_join(io_thread, &thread_ret); + *error_code = *(int *)thread_ret; + if (*error_code != MPI_SUCCESS) return; + io_thread = pthread_self(); + + } + io_thread_args.fd = fd; + /* do a little pointer shuffling: background I/O works from one + * buffer while two-phase machinery fills up another */ + + if (currentWriteBuf == 0) { + io_thread_args.buf = write_buf0; + currentWriteBuf = 1; + write_buf = write_buf1; + } + else { + io_thread_args.buf = write_buf1; + currentWriteBuf = 0; + write_buf = write_buf0; + } + io_thread_args.io_kind = ADIOI_WRITE; + io_thread_args.size = totalDataReceivedThisRound; + io_thread_args.offset = currentRoundFDStart; + io_thread_args.status = status; + io_thread_args.error_code = *error_code; + if ( (pthread_create(&io_thread, NULL, + ADIOI_IO_Thread_Func, &(io_thread_args))) != 0) + io_thread = pthread_self(); + + } + + } /* numDataRecvToWaitFor > 0 */ + + if (iAmUsedAgg) + currentRoundFDStart += coll_bufsize; + for (i = 0; i < numDataSendToWaitFor; i++) { + MPI_Wait(&mpiSendDataToTargetAggRequest[i], + &mpiIsendStatusForData); + } + + } /* for-loop roundIter */ + +#ifdef ROMIO_GPFS + endTimeBase = MPI_Wtime(); + gpfsmpio_prof_cw[GPFSMPIO_CIO_T_DEXCH] += (endTimeBase-startTimeBase); +#endif + + if (useIOBuffer) { /* thread writer cleanup */ + + if ( !pthread_equal(io_thread, pthread_self()) ) { + pthread_join(io_thread, &thread_ret); + *error_code = *(int *)thread_ret; + } + + } + + + + if (iAmUsedAgg) { + ADIOI_Free(sourceProcsForMyData); + ADIOI_Free(remainingDataAmountToGetPerProc); + ADIOI_Free(remainingDataOffsetToGetPerProc); + } + + ADIOI_Free(targetAggsForMyData); + ADIOI_Free(targetAggsForMyDataFDStart); + ADIOI_Free(targetAggsForMyDataFDEnd); + ADIOI_Free(targetAggIndexesForMyDataThisRound); + ADIOI_Free(sendBufferOffsetsThisRound); + ADIOI_Free(bufferAmountsToSendThisRound); + ADIOI_Free(amountOfDataReqestedByTargetAgg); + ADIOI_Free(mpiSizeToSendRequest); + ADIOI_Free(mpiRecvDataRequest); + ADIOI_Free(mpiSendDataSizeRequest); + ADIOI_Free(mpiSendDataToTargetAggRequest); + ADIOI_Free(dataSizeGottenThisRoundPerProc); + ADIOI_Free(mpiRequestMapPerProc); + + /* TODO: still need a barrier here? */ + MPI_Barrier(fd->comm); + return; +} + +void ADIOI_P2PContigReadAggregation(ADIO_File fd, + const void *buf, + int *error_code, + ADIO_Offset *st_offsets, + ADIO_Offset *end_offsets, + ADIO_Offset *fd_start, + ADIO_Offset* fd_end) +{ + + *error_code = MPI_SUCCESS; /* initialize to success */ + +#ifdef ROMIO_GPFS + double startTimeBase,endTimeBase; +#endif + + MPI_Status status; + pthread_t io_thread; + void *thread_ret; + ADIOI_IO_ThreadFuncData io_thread_args; + +#ifdef ROMIO_GPFS + startTimeBase = MPI_Wtime(); +#endif + + int nprocs,myrank; + MPI_Comm_size(fd->comm, &nprocs); + MPI_Comm_rank(fd->comm, &myrank); + + ADIO_Offset myOffsetStart = st_offsets[myrank], myOffsetEnd = end_offsets[myrank]; + + int myAggRank = -1; /* if I am an aggregor this is my index into fd->hints->ranklist */ + int iAmUsedAgg = 0; + + int naggs = fd->hints->cb_nodes; + int coll_bufsize = fd->hints->cb_buffer_size; +#ifdef ROMIO_GPFS + if (gpfsmpio_pthreadio == 1) + /* share buffer between working threads */ + coll_bufsize = coll_bufsize/2; +#endif + + int j; + for (j=0;jhints->ranklist[j] == myrank) { + myAggRank = j; + if (fd_end[j] > fd_start[j]) { + iAmUsedAgg = 1; + } + } + } + + /* for my offset range determine how much data and from whom I need to get + * it. For source ag targets, also determine the source file domain + * offsets locally to reduce communication overhead */ + int *sourceAggsForMyData = (int *)ADIOI_Malloc(naggs * sizeof(int)); + ADIO_Offset *sourceAggsForMyDataFDStart = (ADIO_Offset *)ADIOI_Malloc(naggs * sizeof(ADIO_Offset)); + ADIO_Offset *sourceAggsForMyDataFDEnd = (ADIO_Offset *)ADIOI_Malloc(naggs * sizeof(ADIO_Offset)); + int numSourceAggs = 0; + int i; + for (i=0;i= fd_start[i]) && (myOffsetStart <= fd_end[i])) || + ((myOffsetEnd >= fd_start[i]) && (myOffsetEnd <= fd_end[i]))) { + sourceAggsForMyData[numSourceAggs] = fd->hints->ranklist[i]; + sourceAggsForMyDataFDStart[numSourceAggs] = fd_start[i]; + sourceAggsForMyDataFDEnd[numSourceAggs] = fd_end[i]; + numSourceAggs++; + } + } + + /* these 3 arrays track info on the procs that are fed from an aggregtor - + * to sacrifice some performance at setup to save on memory instead of + * using max size of nprocs for the arrays could determine exact size first + * and then allocate that size */ + int *targetProcsForMyData=NULL; + int *remainingDataAmountToSendPerProc=NULL; + ADIO_Offset *remainingDataOffsetToSendPerProc=NULL; + + int numTargetProcs = 0; + + if (iAmUsedAgg) { + /* for the used aggregators figure out how much data I need from what procs */ + + /* count numTargetProcs so we know how large to make the arrays */ + for (i=0;i= fd_start[myAggRank]) && + (st_offsets[i] <= fd_end[myAggRank])) || + ((end_offsets[i] >= fd_start[myAggRank]) && + (end_offsets[i] <= fd_end[myAggRank])) ) + numTargetProcs++; + + targetProcsForMyData = + (int *)ADIOI_Malloc(numTargetProcs * sizeof(int)); + remainingDataAmountToSendPerProc = + (int *)ADIOI_Malloc(numTargetProcs * sizeof(int)); + remainingDataOffsetToSendPerProc = + (ADIO_Offset *)ADIOI_Malloc(numTargetProcs * sizeof(ADIO_Offset)); + + /* everybody has the st_offsets and end_offsets for all ranks so if I am a + * used aggregator go thru them and figure out which ranks have data that + * falls into my file domain assigned to me */ + numTargetProcs = 0; + for (i=0;i= fd_start[myAggRank]) && (st_offsets[i] <= fd_end[myAggRank])) || ((end_offsets[i] >= fd_start[myAggRank]) && (end_offsets[i] <= fd_end[myAggRank]))) { + targetProcsForMyData[numTargetProcs] = i; + if ( ((st_offsets[i] >= fd_start[myAggRank]) && (st_offsets[i] <= fd_end[myAggRank])) && ((end_offsets[i] >= fd_start[myAggRank]) && (end_offsets[i] <= fd_end[myAggRank]))) { + remainingDataAmountToSendPerProc[numTargetProcs] = (end_offsets[i] - st_offsets[i])+1; + remainingDataOffsetToSendPerProc[numTargetProcs] = st_offsets[i]; + } + else if ((st_offsets[i] >= fd_start[myAggRank]) && (st_offsets[i] <= fd_end[myAggRank])) {/* starts in this fd and goes past it */ + remainingDataAmountToSendPerProc[numTargetProcs] = (fd_end[myAggRank] - st_offsets[i]) +1; + remainingDataOffsetToSendPerProc[numTargetProcs] = st_offsets[i]; + } + else { /* starts in fd before this and ends in it */ + remainingDataAmountToSendPerProc[numTargetProcs] = (end_offsets[i] - fd_start[myAggRank]) +1; + remainingDataOffsetToSendPerProc[numTargetProcs] = fd_start[myAggRank]; + } + numTargetProcs++; + } + } + } + + + MPI_Request *mpiRecvDataFromSourceAggsRequest = (MPI_Request *) ADIOI_Malloc(numSourceAggs * sizeof(MPI_Request)); + MPI_Request *mpiSendDataToTargetProcRequest = (MPI_Request *) ADIOI_Malloc(numTargetProcs * sizeof(MPI_Request)); + MPI_Status mpiWaitAnyStatusFromSourceProcs,mpiIsendStatusForData; + + /* use the two-phase buffer allocated in the file_open - no app should ever + * be both reading and writing at the same time */ + char *read_buf0 = fd->io_buf; + char *read_buf1 = fd->io_buf + coll_bufsize; + /* if threaded i/o selected, we'll do a kind of double buffering */ + char *read_buf = read_buf0; + + /* compute number of rounds */ + ADIO_Offset numberOfRounds = (ADIO_Offset)((((ADIO_Offset)(end_offsets[nprocs-1]-st_offsets[0]))/((ADIO_Offset)((ADIO_Offset)coll_bufsize*(ADIO_Offset)naggs)))) + 1; + + ADIO_Offset currentRoundFDStart = 0, nextRoundFDStart = 0; + ADIO_Offset currentRoundFDEnd = 0, nextRoundFDEnd = 0; + + if (iAmUsedAgg) { + currentRoundFDStart = fd_start[myAggRank]; + nextRoundFDStart = fd_start[myAggRank]; + } + + int *dataSizeSentThisRoundPerProc = (int *)ADIOI_Malloc(numTargetProcs * sizeof(int)); + int *sourceAggIndexesForMyDataThisRound = (int *)ADIOI_Malloc(numSourceAggs * sizeof(int)); + int *recvBufferOffsetsThisRound = (int *)ADIOI_Malloc(numSourceAggs * sizeof(int)); + int *bufferAmountsToGetThisRound = (int *)ADIOI_Malloc(numSourceAggs * sizeof(int)); + *error_code = MPI_SUCCESS; + + int currentReadBuf = 0; + int useIOBuffer = 0; +#ifdef ROMIO_GPFS + if (gpfsmpio_pthreadio && (numberOfRounds>1)) { + useIOBuffer = 1; + io_thread = pthread_self(); + } +#endif + +#ifdef ROMIO_GPFS + endTimeBase = MPI_Wtime(); + gpfsmpio_prof_cw[GPFSMPIO_CIO_T_MYREQ] += (endTimeBase-startTimeBase); +#endif + + + /* each iteration of this loop reads a coll_bufsize portion of the file domain */ + int roundIter; + for (roundIter=0;roundIter 0) + currentRoundFDEnd = nextRoundFDEnd; + + if (roundIter < (numberOfRounds-1)) { + nextRoundFDStart += coll_bufsize; + int amountDataToReadNextRound; + if ((fd_end[myAggRank] - nextRoundFDStart) < coll_bufsize) { + nextRoundFDEnd = fd_end[myAggRank]; + amountDataToReadNextRound = ((nextRoundFDEnd-nextRoundFDStart)+1); + } + else { + nextRoundFDEnd = nextRoundFDStart + coll_bufsize - 1; + amountDataToReadNextRound = coll_bufsize; + } + + if(!pthread_equal(io_thread, pthread_self())) { + pthread_join(io_thread, &thread_ret); + *error_code = *(int *)thread_ret; + if (*error_code != MPI_SUCCESS) return; + io_thread = pthread_self(); + + } + io_thread_args.fd = fd; + /* do a little pointer shuffling: background I/O works from one + * buffer while two-phase machinery fills up another */ + + if (currentReadBuf == 0) { + io_thread_args.buf = read_buf0; + currentReadBuf = 1; + read_buf = read_buf1; + } + else { + io_thread_args.buf = read_buf1; + currentReadBuf = 0; + read_buf = read_buf0; + } + io_thread_args.io_kind = ADIOI_READ; + io_thread_args.size = amountDataToReadNextRound; + io_thread_args.offset = nextRoundFDStart; + io_thread_args.status = status; + io_thread_args.error_code = *error_code; + if ( (pthread_create(&io_thread, NULL, + ADIOI_IO_Thread_Func, &(io_thread_args))) != 0) + io_thread = pthread_self(); + + } + else { /* last round */ + + if(!pthread_equal(io_thread, pthread_self())) { + pthread_join(io_thread, &thread_ret); + *error_code = *(int *)thread_ret; + if (*error_code != MPI_SUCCESS) return; + io_thread = pthread_self(); + + } + if (currentReadBuf == 0) { + read_buf = read_buf1; + } + else { + read_buf = read_buf0; + } + + } + } /* useIOBuffer */ + } /* IAmUsedAgg */ + + /* determine what source aggs I need to get data from this round and + * recv only from them */ + int numSourceAggsThisRound = 0; + for (i=0;i= sourceAggsForMyDataFDStart[i]) && (myOffsetStart <= sourceAggsForMyDataFDEnd[i])) + || ((myOffsetEnd >= sourceAggsForMyDataFDStart[i]) && (myOffsetEnd <= sourceAggsForMyDataFDEnd[i])) ) { + /* we know that we need to get data from this source agg at + * some point, now need to figure out how much this round */ + + /* here are the offsets currently being sent by the aggregator + * during this round */ + ADIO_Offset currentRoundFDStartForMySourceAgg = + (ADIO_Offset)((ADIO_Offset)sourceAggsForMyDataFDStart[i] + + (ADIO_Offset)((ADIO_Offset)roundIter*(ADIO_Offset)coll_bufsize)); + ADIO_Offset currentRoundFDEndForMySourceAgg = + (ADIO_Offset)((ADIO_Offset)sourceAggsForMyDataFDStart[i] + + (ADIO_Offset)((ADIO_Offset)(roundIter+1)*(ADIO_Offset)coll_bufsize) - (ADIO_Offset)1); + if (currentRoundFDEndForMySourceAgg > sourceAggsForMyDataFDEnd[i]) + currentRoundFDEndForMySourceAgg = sourceAggsForMyDataFDEnd[i]; + +#ifdef p2pcontigtrace + printf("roundIter %d source iter %d sourceAggsForMyData is %d myOffsetStart is %ld myOffsetEnd is %ld sourceAggsForMyDataFDStart is %ld sourceAggsForMyDataFDEnd is %ld currentRoundFDStartForMySourceAgg is %ld currentRoundFDEndForMySourceAgg is %ld\n",roundIter,i,sourceAggsForMyData[i],myOffsetStart,myOffsetEnd,sourceAggsForMyDataFDStart[i],sourceAggsForMyDataFDEnd[i],currentRoundFDStartForMySourceAgg,currentRoundFDEndForMySourceAgg); +#endif + + /* get the portion of my data that is within currentRoundFDStartForMySourceAgg to currentRoundFDEndForMySourceAgg */ + /* find the offset into the recv buffer and the amount of data to get */ + int recvBufferOffset = 0; + int bufferAmountToGet = 0; + + if ((myOffsetStart >= currentRoundFDStartForMySourceAgg) && (myOffsetStart <= currentRoundFDEndForMySourceAgg)) { + if (myOffsetEnd > currentRoundFDEndForMySourceAgg) + bufferAmountToGet = (currentRoundFDEndForMySourceAgg - myOffsetStart) +1; + else + bufferAmountToGet = (myOffsetEnd - myOffsetStart) +1; + } + else if ((myOffsetEnd >= currentRoundFDStartForMySourceAgg) && (myOffsetEnd <= currentRoundFDEndForMySourceAgg)) { + recvBufferOffset = (int) (currentRoundFDStartForMySourceAgg - myOffsetStart); + if (myOffsetEnd > currentRoundFDEndForMySourceAgg) + bufferAmountToGet = (currentRoundFDEndForMySourceAgg - currentRoundFDStartForMySourceAgg) +1; + else + bufferAmountToGet = (myOffsetEnd - currentRoundFDStartForMySourceAgg) +1; + } + else if ((myOffsetStart <= currentRoundFDStartForMySourceAgg) && (myOffsetEnd >= currentRoundFDEndForMySourceAgg)) { + recvBufferOffset = (int) (currentRoundFDStartForMySourceAgg - myOffsetStart); + bufferAmountToGet = (currentRoundFDEndForMySourceAgg - currentRoundFDStartForMySourceAgg) +1; + } + + + if (bufferAmountToGet > 0) { /* we have data to get this round */ + sourceAggIndexesForMyDataThisRound[numSourceAggsThisRound] = i; + recvBufferOffsetsThisRound[numSourceAggsThisRound] = recvBufferOffset; + bufferAmountsToGetThisRound[numSourceAggsThisRound] = bufferAmountToGet; +#ifdef p2pcontigtrace + printf("bufferAmountToGet is %d recvBufferOffset is %d\n",bufferAmountToGet,recvBufferOffset); +#endif + numSourceAggsThisRound++; + } + } + } + + /* the aggs determine the amount of data they will be sending to their + * source procs */ + for (i=0;i= currentRoundFDStart) && + (remainingDataOffsetToSendPerProc[i] <= currentRoundFDEnd)) { + if ((remainingDataOffsetToSendPerProc[i] + + remainingDataAmountToSendPerProc[i]) <= currentRoundFDEnd) + dataSizeSentThisRoundPerProc[i] = remainingDataAmountToSendPerProc[i]; + else + dataSizeSentThisRoundPerProc[i] = + (currentRoundFDEnd - remainingDataOffsetToSendPerProc[i]) +1; + } + else if (((remainingDataOffsetToSendPerProc[i]+ + remainingDataAmountToSendPerProc[i]) >= + currentRoundFDStart) && + ((remainingDataOffsetToSendPerProc[i]+ + remainingDataAmountToSendPerProc[i]) <= currentRoundFDEnd)) { + if ((remainingDataOffsetToSendPerProc[i]) >= currentRoundFDStart) + dataSizeSentThisRoundPerProc[i] = remainingDataAmountToSendPerProc[i]; + else + dataSizeSentThisRoundPerProc[i] = + (remainingDataOffsetToSendPerProc[i]-currentRoundFDStart) +1; + } + else + dataSizeSentThisRoundPerProc[i] = 0; + + } + + /* the target procs get the data from the source aggs */ + for (i = 0; i < numSourceAggsThisRound; i++) { + MPI_Irecv(&((char*)buf)[recvBufferOffsetsThisRound[i]], + bufferAmountsToGetThisRound[i],MPI_BYTE, + sourceAggsForMyData[sourceAggIndexesForMyDataThisRound[i]],0,fd->comm, + &mpiRecvDataFromSourceAggsRequest[i]); + } + + /* the source aggs send the data to the target procs */ + int numTargetProcsSentThisRound = 0; + for (i=0;i 0 count data */ + if (dataSizeSentThisRoundPerProc[i] > 0) { + MPI_Isend(&((char*)read_buf)[currentWBOffset], + dataSizeSentThisRoundPerProc[i], + MPI_BYTE,targetProcsForMyData[i],0, + fd->comm,&mpiSendDataToTargetProcRequest[numTargetProcsSentThisRound]); + numTargetProcsSentThisRound++; + remainingDataAmountToSendPerProc[i] -= dataSizeSentThisRoundPerProc[i]; + remainingDataOffsetToSendPerProc[i] += dataSizeSentThisRoundPerProc[i]; + } + } + + /* wait for the target procs to get their data */ + for (i = 0; i < numSourceAggsThisRound; i++) { + MPI_Waitany(numSourceAggsThisRound,mpiRecvDataFromSourceAggsRequest, + &irecv,&mpiWaitAnyStatusFromSourceProcs); + } + + nextRoundFDStart = currentRoundFDStart + coll_bufsize; + + /* clean up the MPI_Isend MPI_Requests */ + for (i=0;icomm); /* need to sync up the source aggs which did the isend with the target procs which did the irecvs to give the target procs time to get the data before overwriting with next round readcontig */ + + } /* for-loop roundIter */ + + if (useIOBuffer) { /* thread reader cleanup */ + + if ( !pthread_equal(io_thread, pthread_self()) ) { + pthread_join(io_thread, &thread_ret); + *error_code = *(int *)thread_ret; + } + } + + if (iAmUsedAgg) { + ADIOI_Free(targetProcsForMyData); + ADIOI_Free(remainingDataAmountToSendPerProc); + ADIOI_Free(remainingDataOffsetToSendPerProc); + } + + ADIOI_Free(sourceAggsForMyData); + ADIOI_Free(sourceAggsForMyDataFDStart); + ADIOI_Free(sourceAggsForMyDataFDEnd); + + ADIOI_Free(mpiRecvDataFromSourceAggsRequest); + ADIOI_Free(mpiSendDataToTargetProcRequest); + ADIOI_Free(dataSizeSentThisRoundPerProc); + ADIOI_Free(sourceAggIndexesForMyDataThisRound); + ADIOI_Free(recvBufferOffsetsThisRound); + ADIOI_Free(bufferAmountsToGetThisRound); + + /* TODO: is Barrier here needed? */ + MPI_Barrier(fd->comm); + + return; + +} diff --git a/ompi/mca/io/romio314/romio/adio/common/req_malloc.c b/ompi/mca/io/romio314/romio/adio/common/req_malloc.c new file mode 100644 index 0000000000..61018e1a68 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/req_malloc.c @@ -0,0 +1,83 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "adio_extern.h" + +struct ADIOI_RequestD *ADIOI_Malloc_request(void) +{ +/* returns a pointer to a new request object. + To reduce the number of system calls, mallocs NUM requests at a time + and maintains list of available requests. Supplies an object from this + list if available, else mallocs a new set of NUM and provides one + from that set. Is NUM=100 a good number? */ + +#define NUM 100 + + ADIOI_Req_node *curr, *ptr; + int i; + + if (!ADIOI_Req_avail_head) { + ADIOI_Req_avail_head = (ADIOI_Req_node *) + ADIOI_Malloc(NUM*sizeof(ADIOI_Req_node)); + if (ADIOI_Req_avail_head == NULL) + { + /* FIXME: Insert error here */ + return NULL; + } + curr = ADIOI_Req_avail_head; + for (i=1; inext = ADIOI_Req_avail_head+i; + curr = curr->next; + } + curr->next = NULL; + ADIOI_Req_avail_tail = curr; + + /* keep track of malloced area that needs to be freed later */ + if (!ADIOI_Malloc_req_tail) { + ADIOI_Malloc_req_tail = (ADIOI_Malloc_req *) + ADIOI_Malloc(sizeof(ADIOI_Malloc_req)); + ADIOI_Malloc_req_head = ADIOI_Malloc_req_tail; + ADIOI_Malloc_req_head->ptr = ADIOI_Req_avail_head; + ADIOI_Malloc_req_head->next = NULL; + } + else { + ADIOI_Malloc_req_tail->next = (ADIOI_Malloc_req *) + ADIOI_Malloc(sizeof(ADIOI_Malloc_req)); + ADIOI_Malloc_req_tail = ADIOI_Malloc_req_tail->next; + ADIOI_Malloc_req_tail->ptr = ADIOI_Req_avail_head; + ADIOI_Malloc_req_tail->next = NULL; + } + } + + ptr = ADIOI_Req_avail_head; + ADIOI_Req_avail_head = ADIOI_Req_avail_head->next; + if (!ADIOI_Req_avail_head) ADIOI_Req_avail_tail = NULL; + + (ptr->reqd).cookie = ADIOI_REQ_COOKIE; + return &(ptr->reqd); +} + + +void ADIOI_Free_request(ADIOI_Req_node *node) +{ +/* This function could be called as ADIOI_Free_request(ADIO_Request request), + because request would be a pointer to the first element of ADIOI_Req_node.*/ + +/* moves this node to available pool. does not actually free it. */ + + (node->reqd).cookie = 0; + + if (!ADIOI_Req_avail_tail) + ADIOI_Req_avail_head = ADIOI_Req_avail_tail = node; + else { + ADIOI_Req_avail_tail->next = node; + ADIOI_Req_avail_tail = node; + } + node->next = NULL; +} + diff --git a/ompi/mca/io/romio314/romio/adio/common/shfp_fname.c b/ompi/mca/io/romio314/romio/adio/common/shfp_fname.c new file mode 100644 index 0000000000..dfa5bafc2c --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/shfp_fname.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif +/* The following function selects the name of the file to be used to + store the shared file pointer. The shared-file-pointer file is a + hidden file in the same directory as the real file being accessed. + If the real file is /tmp/thakur/testfile, the shared-file-pointer + file will be /tmp/thakur/.testfile.shfp.yyy.xxxx, where yyy + is rank 0's process id and xxxx is a random number. If the + underlying file system supports shared file pointers + (PVFS does not, for example), the file name is always + constructed. This file is created only if the shared + file pointer functions are used and is deleted when the real + file is closed. */ + +void ADIOI_Shfp_fname(ADIO_File fd, int rank, int *error_code) +{ + int i; + int len; + char *slash, *ptr, tmp[128]; + int pid = 0; + + fd->shared_fp_fname = (char *) ADIOI_Malloc(PATH_MAX); + + if (!rank) { + srand(time(NULL)); + i = rand(); + pid = (int)getpid(); + + if (ADIOI_Strncpy(fd->shared_fp_fname, fd->filename, PATH_MAX)) { + *error_code = ADIOI_Err_create_code("ADIOI_Shfp_fname", + fd->filename, ENAMETOOLONG); + return; + } + +#ifdef ROMIO_NTFS + slash = strrchr(fd->filename, '\\'); +#else + slash = strrchr(fd->filename, '/'); +#endif + if (!slash) { + if (ADIOI_Strncpy(fd->shared_fp_fname, ".", 2)) { + *error_code = ADIOI_Err_create_code("ADIOI_Shfp_fname", + fd->filename, ENAMETOOLONG); + return; + } + if (ADIOI_Strncpy(fd->shared_fp_fname + 1, fd->filename, PATH_MAX-1)) { + *error_code = ADIOI_Err_create_code("ADIOI_Shfp_fname", + fd->filename, ENAMETOOLONG); + return; + } + } + else { + ptr = slash; +#ifdef ROMIO_NTFS + slash = strrchr(fd->shared_fp_fname, '\\'); +#else + slash = strrchr(fd->shared_fp_fname, '/'); +#endif + if (ADIOI_Strncpy(slash + 1, ".", 2)) { + *error_code = ADIOI_Err_create_code("ADIOI_Shfp_fname", + fd->filename, ENAMETOOLONG); + return; + } + /* ok to cast: file names bounded by PATH_MAX and NAME_MAX */ + len = (int) (PATH_MAX - (slash+2 - fd->shared_fp_fname)); + if (ADIOI_Strncpy(slash + 2, ptr + 1, len)) { + *error_code = ADIOI_Err_create_code("ADIOI_Shfp_fname", + ptr + 1, ENAMETOOLONG); + return; + } + } + + ADIOI_Snprintf(tmp, 128, ".shfp.%d.%d", pid, i); + /* ADIOI_Strnapp will return non-zero if truncated. That's ok */ + ADIOI_Strnapp(fd->shared_fp_fname, tmp, PATH_MAX); + + len = (int)strlen(fd->shared_fp_fname); + MPI_Bcast(&len, 1, MPI_INT, 0, fd->comm); + MPI_Bcast(fd->shared_fp_fname, len+1, MPI_CHAR, 0, fd->comm); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, fd->comm); + MPI_Bcast(fd->shared_fp_fname, len+1, MPI_CHAR, 0, fd->comm); + } +} diff --git a/ompi/mca/io/romio314/romio/adio/common/status_setb.c b/ompi/mca/io/romio314/romio/adio/common/status_setb.c new file mode 100644 index 0000000000..ec1e4ff7f6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/status_setb.c @@ -0,0 +1,37 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpi.h" + +#if defined(MPICH2) || (defined(MPICH) && (MPICH_NAME >= 3)) +/* Not quite correct, but much closer for MPI2 */ +/* TODO: still needs to handle partial datatypes and situations where the mpi + * implementation fills status with something other than bytes (globus2 might + * do this) */ +int MPIR_Status_set_bytes(MPI_Status *status, MPI_Datatype datatype, + MPI_Count nbytes) +{ + ADIOI_UNREFERENCED_ARG(datatype); + /* it's ok that ROMIO stores number-of-bytes in status, not + * count-of-copies, as long as MPI_GET_COUNT knows what to do */ + if (status != MPI_STATUS_IGNORE) + MPI_Status_set_elements_x(status, MPI_BYTE, nbytes); + return MPI_SUCCESS; +} +#elif defined(MPILAM) || defined(MPISGI) +int MPIR_Status_set_bytes(MPI_Status *status, MPI_Datatype datatype, + MPI_Count nbytes) +{ + /* Bogusness to silence compiler warnings */ + if (datatype == MPI_DATATYPE_NULL); + + if (status != MPI_STATUS_IGNORE) + status->st_length = nbytes; + return MPI_SUCCESS; +} +#endif diff --git a/ompi/mca/io/romio314/romio/adio/common/strfns.c b/ompi/mca/io/romio314/romio/adio/common/strfns.c new file mode 100644 index 0000000000..65e5ac24e7 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/strfns.c @@ -0,0 +1,315 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" + +/* style: allow:sprintf:3 sig:0 */ + +/* + * Below are the "safe" versions of the various string and printf + * operations. They are directly taken from MPICH, with MPIU replaced by ADIOI. + */ + +/* + * ADIOI_Strncpy - Copy at most n character. Stop once a null is reached. + * + * This is different from strncpy, which null pads so that exactly + * n characters are copied. The strncpy behavior is correct for many + * applications because it guarantees that the string has no uninitialized + * data. + * + * If n characters are copied without reaching a null, return an error. + * Otherwise, return 0. + * + */ +/*@ ADIOI_Strncpy - Copy a string with a maximum length + +Input Parameters: ++ instr - String to copy +- maxlen - Maximum total length of 'outstr' + +Output Parameters: +. outstr - String to copy into + + Notes: + This routine is the routine that you wish 'strncpy' was. In copying + 'instr' to 'outstr', it stops when either the end of 'outstr' (the + null character) is seen or the maximum length 'maxlen' is reached. + Unlike 'strncpy', it does not add enough nulls to 'outstr' after + copying 'instr' in order to move precisely 'maxlen' characters. + Thus, this routine may be used anywhere 'strcpy' is used, without any + performance cost related to large values of 'maxlen'. + + Module: + Utility + @*/ +int ADIOI_Strncpy( char *dest, const char *src, size_t n ) +{ + char * restrict d_ptr = dest; + const char * restrict s_ptr = src; + register int i; + + i = (int)n; + while (*s_ptr && i-- > 0) { + *d_ptr++ = *s_ptr++; + } + + if (i > 0) { + *d_ptr = 0; + return 0; + } + else + /* We may want to force an error message here, at least in the + debugging version */ + return 1; +} + +/* Append src to dest, but only allow dest to contain n characters (including + any null, which is always added to the end of the line */ +/*@ ADIOI_Strnapp - Append to a string with a maximum length + +Input Parameters: ++ instr - String to copy +- maxlen - Maximum total length of 'outstr' + +Output Parameters: +. outstr - String to copy into + + Notes: + This routine is similar to 'strncat' except that the 'maxlen' argument + is the maximum total length of 'outstr', rather than the maximum + number of characters to move from 'instr'. Thus, this routine is + easier to use when the declared size of 'instr' is known. + + Module: + Utility + @*/ +int ADIOI_Strnapp( char *dest, const char *src, size_t n ) +{ + char * restrict d_ptr = dest; + const char * restrict s_ptr = src; + register int i; + + /* Get to the end of dest */ + i = (int)n; + while (i-- > 0 && *d_ptr) d_ptr++; + if (i <= 0) return 1; + + /* Append. d_ptr points at first null and i is remaining space. */ + while (*s_ptr && i-- > 0) { + *d_ptr++ = *s_ptr++; + } + + /* We allow i >= (not just >) here because the first while decrements + i by one more than there are characters, leaving room for the null */ + if (i >= 0) { + *d_ptr = 0; + return 0; + } + else { + /* Force the null at the end */ + *--d_ptr = 0; + + /* We may want to force an error message here, at least in the + debugging version */ + return 1; + } +} + +/*@ + ADIOI_Strdup - Duplicate a string + + Synopsis: +.vb + char *ADIOI_Strdup( const char *str ) +.ve + +Input Parameters: +. str - null-terminated string to duplicate + + Return value: + A pointer to a copy of the string, including the terminating null. A + null pointer is returned on error, such as out-of-memory. + + Notes: + Like 'ADIOI_Malloc' and 'ADIOI_Free', this will often be implemented as a + macro but may use 'ADIOI_trstrdup' to provide a tracing version. + + Module: + Utility + @*/ +char *ADIOI_Strdup( const char *str ) +{ + char *p = ADIOI_Malloc( strlen(str) + 1 ); + char *in_p = (char *)str; + char *save_p; + + save_p = p; + if (p) { + while (*in_p) { + *p++ = *in_p++; + } + *p = '\0'; + } + return save_p; +} + + +/* + * We need an snprintf replacement for systems without one + */ +#ifndef HAVE_SNPRINTF +#include +/* FIXME: Really need a check for varargs.h vs stdarg.h */ +#include +/* + * This is an approximate form which is suitable for most uses within + * the MPICH code + */ +int ADIOI_Snprintf( char *str, size_t size, const char *format, ... ) +{ + int n; + const char *p; + char *out_str = str; + va_list list; + + va_start(list, format); + + p = format; + while (*p && size > 0) { + char *nf; + + nf = strchr(p, '%'); + if (!nf) { + /* No more format characters */ + while (size-- > 0 && *p) { + *out_str++ = *p++; + } + } + else { + int nc; + int width = -1; + + /* Copy until nf */ + while (p < nf && size-- > 0) { + *out_str++ = *p++; + } + /* p now points at nf */ + /* Handle the format character */ + nc = nf[1]; + if (isdigit(nc)) { + /* Get the field width */ + /* FIXME : Assumes ASCII */ + width = nc - '0'; + p = nf + 2; + while (*p && isdigit(*p)) { + width = 10 * width + (*p++ - '0'); + } + /* When there is no longer a digit, get the format + character */ + nc = *p++; + } + else { + /* Skip over the format string */ + p += 2; + } + + switch (nc) { + case '%': + *out_str++ = '%'; + size--; + break; + + case 'd': + { + int val; + char tmp[20]; + char *t = tmp; + /* Get the argument, of integer type */ + val = va_arg( list, int ); + sprintf( tmp, "%d", val ); + if (width > 0) { + int tmplen = strlen(tmp); + /* If a width was specified, pad with spaces on the + left (on the right if %-3d given; not implemented yet */ + while (size-- > 0 && width-- > tmplen) + *out_str++ = ' '; + } + while (size-- > 0 && *t) { + *out_str++ = *t++; + } + } + break; + + case 'x': + { + int val; + char tmp[20]; + char *t = tmp; + /* Get the argument, of integer type */ + val = va_arg( list, int ); + sprintf( tmp, "%x", val ); + if (width > 0) { + int tmplen = strlen(tmp); + /* If a width was specified, pad with spaces on the + left (on the right if %-3d given; not implemented yet */ + while (size-- > 0 && width-- > tmplen) + *out_str++ = ' '; + } + while (size-- > 0 && *t) { + *out_str++ = *t++; + } + } + break; + + case 'p': + { + void *val; + char tmp[20]; + char *t = tmp; + val = va_arg( list, void * ); + sprintf( tmp, "%p", val ); + if (width > 0) { + int tmplen = strlen(tmp); + /* If a width was specified, pad with spaces on the + left (on the right if %-3d given; not implemented yet */ + while (size-- > 0 && width-- > tmplen) + *out_str++ = ' '; + } + while (size-- > 0 && *t) { + *out_str++ = *t++; + } + } + break; + + case 's': + { + char *s_arg; + /* Get the argument, of pointer to char type */ + s_arg = va_arg( list, char * ); + while (size-- > 0 && s_arg && *s_arg) { + *out_str++ = *s_arg++; + } + } + break; + + default: + /* Error, unknown case */ + return -1; + break; + } + } + } + + va_end(list); + + if (size-- > 0) *out_str++ = '\0'; + + n = (int)(out_str - str); + return n; +} +#endif diff --git a/ompi/mca/io/romio314/romio/adio/common/system_hints.c b/ompi/mca/io/romio314/romio/adio/common/system_hints.c new file mode 100644 index 0000000000..fd6cba5cb5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/common/system_hints.c @@ -0,0 +1,195 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * Copyright (C) 2007 UChicago/Argonne LLC. + * See COPYRIGHT notice in top-level directory. + */ + +#include + +#include + +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_IO_H +#include +#endif + +/*#define SYSHINT_DEBUG 1 */ + +#define ROMIO_HINT_DEFAULT_CFG "/etc/romio-hints" +#define ROMIO_HINT_ENV_VAR "ROMIO_HINTS" + +/* debug function: a routine I want in the library to make my life easier when + * using a source debugger. Now optionally used in ADIO_Open. */ +void ADIOI_Info_print_keyvals(MPI_Info info) +{ + int i, nkeys, flag; + char key[MPI_MAX_INFO_KEY]; + char value[MPI_MAX_INFO_VAL]; + + if (info == MPI_INFO_NULL) + return; + + MPI_Info_get_nkeys(info, &nkeys); + + for (i=0; i \n". + * A # in collumn zero is a comment and the line will be ignored. Do our best + * to ignore badly formed lines too. + * + * The caller provides an 'info' object. Each key-value pair found by the + * parser will get added to the info object. any keys already set will be left + * alone on the assumption that the caller knows best. + * + * because MPI-IO hints are optional, we can get away with limited error + * reporting. + * + * for better scalability, the config file will be read on one processor and + * broadcast to all others */ +static int file_to_info_all(int fd, MPI_Info info, int rank, MPI_Comm comm) +{ + char *buffer, *token, *key, *val, *garbage; + char *pos1=NULL, *pos2=NULL; + int flag; + ssize_t ret; + char dummy; + + /* assumption: config files will be small */ +#define HINTFILE_MAX_SIZE 1024*4 + buffer = (char *)ADIOI_Calloc(HINTFILE_MAX_SIZE, sizeof (char)); + + if (rank == 0) { + ret = read(fd, buffer, HINTFILE_MAX_SIZE); + /* any error: bad/nonexistent fd, no perms, anything: set up a null + * buffer and the subsequent string parsing will quit immediately */ + if (ret == -1) + buffer[0] = '\0'; + } + MPI_Bcast(buffer, HINTFILE_MAX_SIZE, MPI_BYTE, 0, comm); + + token = strtok_r(buffer, "\n", &pos1); + if (token == NULL) + goto fn_exit; + do { + if ( (key = strtok_r(token, " \t", &pos2)) == NULL) + /* malformed line: found no items */ + continue; + if (token[0] == '#') + /* ignore '#'-delimited comments */ + continue; + if ( (val = strtok_r(NULL, " \t", &pos2)) == NULL) + /* malformed line: found key without value */ + continue; + if ( (garbage = strtok_r(NULL, " \t", &pos2)) != NULL) + /* malformed line: more than two items */ + continue; + +#ifdef SYSHINT_DEBUG + printf("found: key=%s val=%s\n", key, val); +#endif + /* don't actually care what the value is. only want to know if key + * exists: we leave it alone if so*/ + ADIOI_Info_get(info, key, 1, &dummy, &flag); + if (flag == 1) continue; + ADIOI_Info_set(info, key, val); + } while ((token = strtok_r(NULL, "\n", &pos1)) != NULL); + +fn_exit: + ADIOI_Free(buffer); + return 0; +} + +void ADIOI_process_system_hints(ADIO_File fd, MPI_Info info) +{ + int hintfd=-1, rank; + + MPI_Comm_rank(fd->comm, &rank); + if (rank == 0) { + hintfd = find_file(); + } + /* hintfd only significant on rank 0. -1 (on rank 0) means no hintfile found */ + file_to_info_all(hintfd, info, rank, fd->comm); + + if (hintfd != -1) + close(hintfd); +} + +/* given 'info', incorporate any hints in 'sysinfo' that are not already set + * into 'new_info'. Caller must free 'new_info' later. */ +void ADIOI_incorporate_system_hints(MPI_Info info, + MPI_Info sysinfo, + MPI_Info *new_info) +{ + int i, nkeys_sysinfo, flag=0; /* must initialize flag to 0 */ + + char val[MPI_MAX_INFO_VAL], key[MPI_MAX_INFO_KEY]; + + if (sysinfo == MPI_INFO_NULL) + nkeys_sysinfo = 0; + else + MPI_Info_get_nkeys(sysinfo, &nkeys_sysinfo); + + /* short-circuit: return immediately if no hints to process */ + if (info == MPI_INFO_NULL && nkeys_sysinfo == 0) { + *new_info = MPI_INFO_NULL; + return; + } + + if (info == MPI_INFO_NULL) + MPI_Info_create(new_info); + else + MPI_Info_dup(info, new_info); + + for (i=0; i +#include + + +/* utility function for creating large contiguous types: algorithim from BigMPI + * https://github.com/jeffhammond/BigMPI */ + +static int type_create_contiguous_x(MPI_Count count, + MPI_Datatype oldtype, MPI_Datatype *newtype) +{ + /* to make 'count' fit MPI-3 type processing routines (which take integer + * counts), we construct a type consisting of N INT_MAX chunks followed by + * a remainder. e.g for a count of 4000000000 bytes you would end up with + * one 2147483647-byte chunk followed immediately by a 1852516353-byte + * chunk */ + MPI_Datatype chunks, remainder; + MPI_Aint lb, extent, disps[2]; + int blocklens[2]; + MPI_Datatype types[2]; + + /* truly stupendously large counts will overflow an integer with this math, + * but that is a problem for a few decades from now. Sorry, few decades + * from now! */ + ADIOI_Assert(count/INT_MAX == (int)(count/INT_MAX)); + int c = (int)(count/INT_MAX); /* OK to cast until 'count' is 256 bits */ + int r = count%INT_MAX; + + MPI_Type_vector(c, INT_MAX, INT_MAX, oldtype, &chunks); + MPI_Type_contiguous(r, oldtype, &remainder); + + MPI_Type_get_extent(oldtype, &lb, &extent); + + blocklens[0] = 1; blocklens[1] = 1; + disps[0] = 0; disps[1] = c*extent*INT_MAX; + types[0] = chunks; types[1] = remainder; + + MPI_Type_create_struct(2, blocklens, disps, types, newtype); + + MPI_Type_free(&chunks); + MPI_Type_free(&remainder); + + return MPI_SUCCESS; +} +/* like MPI_Type_create_hindexed, except array_of_lengths can be a larger datatype. + * + * Hindexed provides 'count' pairs of (displacement, length), but what if + * length is longer than an integer? We will create 'count' types, using + * contig if length is small enough, or something more complex if not */ + +int ADIOI_Type_create_hindexed_x(int count, + const MPI_Count array_of_blocklengths[], + const MPI_Aint array_of_displacements[], + MPI_Datatype oldtype, + MPI_Datatype *newtype) +{ + int i, ret; + MPI_Datatype *types; + int *blocklens; + int is_big=0; + + types = ADIOI_Malloc(count*sizeof(MPI_Datatype)); + blocklens = ADIOI_Malloc(count*sizeof(int)); + + /* squashing two loops into one. + * - Look in the array_of_blocklengths for any large values + * - convert MPI_Count items (if they are not too big) into int-sized items + * after this loop we will know if we can use MPI_type_hindexed or if we + * need a more complicated BigMPI-style struct-of-chunks. + * + * Why not use the struct-of-chunks in all cases? HDF5 reported a bug, + * which I have not yet precicesly nailed down, but appears to have + * something to do with struct-of-chunks when the chunks are small */ + + for(i=0; i INT_MAX) { + blocklens[i] = 1; + is_big=1; + type_create_contiguous_x(array_of_blocklengths[i], oldtype, &(types[i])); + } else { + /* OK to cast: checked for "bigness" above */ + blocklens[i] = (int)array_of_blocklengths[i]; + MPI_Type_contiguous(blocklens[i], oldtype, &(types[i])); + } + } + + if (is_big) { + ret = MPI_Type_create_struct(count, blocklens, array_of_displacements, + types, newtype); + } else { + ret = MPI_Type_hindexed(count, blocklens, + array_of_displacements, oldtype, newtype); + } + for (i=0; i< count; i++) + MPI_Type_free(&(types[i])); + ADIOI_Free(types); + ADIOI_Free(blocklens); + + return ret; +} + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/adio/include/BaseIOErrMsgs.msg b/ompi/mca/io/romio314/romio/adio/include/BaseIOErrMsgs.msg new file mode 100644 index 0000000000..0ca0526619 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/BaseIOErrMsgs.msg @@ -0,0 +1,51 @@ +$set 12 MPI_ERR_ARG +12 65 "Invalid offset argument" +12 67 "Null datarep argument" +12 69 "Invalid count argument" +12 71 "Invalid size argument" +12 73 "Invalid whence argument" +12 75 "flag argument must be the same on all processes" +12 77 "Invalid displacement argument" +12 79 "Invalid etype argument" +12 81 "Invalid filetype argument" +12 83 "size argument must be the same on all processes" +12 85 "offset points to a negative location in the file" +12 87 "whence argument must be the same on all processes" +12 89 "offset argument must be the same on all processes" +$set 21 MPI_ERR_AMODE +21 1 "Invalid amode" +21 3 "Exactly one of MPI_MODE_RDONLY, MPI_MODE_WRONLY, or MPI_MODE_RDWR must be specified" +21 5 "Cannot use MPI_MODE_CREATE or MPI_MODE_EXCL with MPI_MODE_RDONLY" +21 7 "Cannot specify MPI_MODE_SEQUENTIAL with MPI_MODE_RDWR" +$set 27 MPI_ERR_FILE +27 1 "Invalid file handle" +27 3 "Null file handle" +27 5 "Corrupted file handle" +$set 32 MPI_ERR_IO +32 1 "I/O Error" +32 2 "%s" 1 +32 3 "Only an integral number of etypes can be accessed" +32 5 "Can't determine the file-system type. Check the filename/path you provided and try again. Otherwise, prefix the filename with a string to indicate the type of file system (piofs:, pfs:, nfs:, ufs:, hfs:, xfs:, sfs:, pvfs:, pvfs2:, ftp:, gsiftp:)" +32 7 "ROMIO has not been configured to use the PFS file system" +32 9 "ROMIO has not been configured to use the PIOFS file system" +32 11 "ROMIO has not been configured to use the UFS file system" +32 13 "ROMIO has not been configured to use the NFS file system" +32 15 "ROMIO has not been configured to use the HFS file system" +32 17 "ROMIO has not been configured to use the XFS file system" +32 19 "ROMIO has not been configured to use the SFS file system" +32 21 "ROMIO has not been configured to use the PVFS file system" +32 23 "Only one active split collective I/O operation allowed per file handle" +32 25 "No previous split collective begin" +32 27 "There are outstanding nonblocking I/O operations on this file" +32 29 "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." +32 31 "To preallocate disk space, ROMIO needs to read the file and write it back, but is unable to read the file. Please give the file read permission and open it with MPI_MODE_RDWR." +32 33 "Filetype must be constructed out of one or more etypes" +$set 43 MPI_ERR_UNSUPPORTED_DATAREP +43 1 "Unsupported data representation" +43 3 "Only native data representation currently supported" +$set 44 MPI_ERR_UNSUPPORTED_OPERATION +44 1 "Unsupported operation" +44 3 "Shared file pointer not supported on PIOFS and PVFS" +44 5 "Cannot use this function when file is opened with amode MPI_MODE_SEQUENTIAL" +44 7 "Cannot read from a file opened with amode MPI_MODE_WRONLY" +44 9 "MPI_MODE_SEQUENTIAL not supported on PIOFS and PVFS" diff --git a/ompi/mca/io/romio314/romio/adio/include/adio.h b/ompi/mca/io/romio314/romio/adio/include/adio.h new file mode 100644 index 0000000000..7ad3ced27b --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/adio.h @@ -0,0 +1,455 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* main include file for ADIO. + contains general definitions, declarations, and macros independent + of the underlying file system */ + +/* Functions and datataypes that are "internal" to the ADIO implementation + prefixed ADIOI_. Functions and datatypes that are part of the + "externally visible" (documented) ADIO interface are prefixed ADIO_. + + An implementation of MPI-IO, or any other high-level interface, should + not need to use any of the ADIOI_ functions/datatypes. + Only someone implementing ADIO on a new file system, or modifying + an existing ADIO implementation, would need to use the ADIOI_ + functions/datatypes. */ + +#ifndef ADIO_INCLUDE +#define ADIO_INCLUDE + +#ifdef SPPUX +#define _POSIX_SOURCE +#endif + +#ifdef USE_FORT_STDCALL +#define FORT_CALL __stdcall +#elif defined (USE_FORT_CDECL) +#define FORT_CALL __cdecl +#else +#define FORT_CALL +#endif + +#ifdef USE_FORT_MIXED_STR_LEN +#define FORT_MIXED_LEN_DECL , int +#define FORT_END_LEN_DECL +#define FORT_MIXED_LEN(a) , int a +#define FORT_END_LEN(a) +#else +#define FORT_MIXED_LEN_DECL +#define FORT_END_LEN_DECL , int +#define FORT_MIXED_LEN(a) +#define FORT_END_LEN(a) , int a +#endif + +#ifdef HAVE_FORTRAN_API +# ifdef FORTRAN_EXPORTS +# define FORTRAN_API __declspec(dllexport) +# else +# define FORTRAN_API __declspec(dllimport) +# endif +#else +# define FORTRAN_API +#endif + +/* Use this macro for each parameter to a function that is not referenced in the body of the function */ +#ifdef HAVE_WINDOWS_H +#define ADIOI_UNREFERENCED_ARG(a) a +#else +#define ADIOI_UNREFERENCED_ARG(a) +#endif + +/* Include romioconf.h if we haven't already (some include files may + need to include romioconf before some system includes) */ +#ifndef ROMIOCONF_H_INCLUDED +#include "romioconf.h" +#define ROMIOCONF_H_INCLUDED +#endif + +#include "mpi.h" +#include "mpio.h" +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include +#include +#include +#include +#include +#ifdef SPPUX +#include +#endif + +#ifdef ROMIO_NTFS +#include +#include +#define FDTYPE HANDLE +#else +#define FDTYPE int +#endif + +#ifdef MPI_OFFSET_IS_INT + typedef int ADIO_Offset; +# define ADIO_OFFSET MPI_INT +#elif defined(HAVE_LONG_LONG_64) + typedef long long ADIO_Offset; +# ifdef HAVE_MPI_LONG_LONG_INT +# define ADIO_OFFSET MPI_LONG_LONG_INT +# else +# define ADIO_OFFSET MPI_DOUBLE +# endif +#elif defined(HAVE_INT64) + typedef __int64 ADIO_Offset; +# define ADIO_OFFSET MPI_DOUBLE +#else + typedef long ADIO_Offset; +# define ADIO_OFFSET MPI_LONG +#endif + +#define ADIO_Status MPI_Status + +#ifndef MPIO_INCLUDE +# ifdef NEEDS_MPI_FINT + typedef int MPI_Fint; +# endif +#endif + +#if (!defined(HAVE_MPI_INFO) && !defined(MPIO_INCLUDE)) + typedef struct MPIR_Info *MPI_Info; +# define MPI_INFO_NULL 0 +# define MPI_MAX_INFO_VAL 1024 + +int MPI_Info_create(MPI_Info *info); +int MPI_Info_set(MPI_Info info, char *key, char *value); +int MPI_Info_delete(MPI_Info info, char *key); +int MPI_Info_get(MPI_Info info, char *key, int valuelen, + char *value, int *flag); +int MPI_Info_get_valuelen(MPI_Info info, char *key, int *valuelen, int *flag); +int MPI_Info_get_nkeys(MPI_Info info, int *nkeys); +int MPI_Info_get_nthkey(MPI_Info info, int n, char *key); +int MPI_Info_dup(MPI_Info info, MPI_Info *newinfo); +int MPI_Info_free(MPI_Info *info); + +#ifdef MPI_Info_f2c +#undef MPI_Info_f2c +#endif +#ifdef MPI_Info_c2f +#undef MPI_Info_c2f +#endif +/* above needed for some versions of mpi.h in MPICH!! */ +MPI_Fint MPI_Info_c2f(MPI_Info info); +MPI_Info MPI_Info_f2c(MPI_Fint info); + +int PMPI_Info_create(MPI_Info *info); +int PMPI_Info_set(MPI_Info info, char *key, char *value); +int PMPI_Info_delete(MPI_Info info, char *key); +int PMPI_Info_get(MPI_Info info, char *key, int valuelen, + char *value, int *flag); +int PMPI_Info_get_valuelen(MPI_Info info, char *key, int *valuelen, int *flag); +int PMPI_Info_get_nkeys(MPI_Info info, int *nkeys); +int PMPI_Info_get_nthkey(MPI_Info info, int n, char *key); +int PMPI_Info_dup(MPI_Info info, MPI_Info *newinfo); +int PMPI_Info_free(MPI_Info *info); + +MPI_Fint PMPI_Info_c2f(MPI_Info info); +MPI_Info PMPI_Info_f2c(MPI_Fint info); + +#endif + +/* style: allow:strdup:1 sig:0 */ + +#if defined(HAVE_STRDUP) && defined(NEEDS_STRDUP_DECL) && !defined(strdup) +char *strdup(const char *s); +# endif +#if defined(HAVE_READLINK) && defined(NEEDS_READLINK_DECL) && !defined(readlink) +ssize_t readlink(const char *path, char *buf, size_t bufsiz); +# endif +#if defined(HAVE_LSTAT) && defined(NEEDS_LSTAT_DECL) && !defined(lstat) +int lstat(const char *file_name, struct stat *buf); +# endif +#if defined(HAVE_FSYNC) && defined(NEEDS_FSYNC_DECL) && !defined(fsync) +int fsync(int fd); +# endif +#if defined(HAVE_FTRUNCATE) && defined(NEEDS_FTRUNCATE_DECL) && !defined(ftruncate) +int ftruncate(int fd, off_t length); +# endif + + +typedef struct ADIOI_Fns_struct ADIOI_Fns; +typedef struct ADIOI_Hints_struct ADIOI_Hints; + +typedef struct ADIOI_FileD { + int cookie; /* for error checking */ + FDTYPE fd_sys; /* system file descriptor */ + FDTYPE null_fd; /* the null-device file descriptor: debug only (obviously)*/ + int fd_direct; /* On XFS, this is used for direct I/O; + fd_sys is used for buffered I/O */ + int direct_read; /* flag; 1 means use direct read */ + int direct_write; /* flag; 1 means use direct write */ + /* direct I/O attributes */ + unsigned d_mem; /* data buffer memory alignment */ + unsigned d_miniosz; /* min xfer size, xfer size multiple, + and file seek offset alignment */ + long blksize; /* some optimizations benefit from knowing + underlying block size */ + ADIO_Offset fp_ind; /* individual file pointer in MPI-IO (in bytes)*/ + ADIO_Offset fp_sys_posn; /* current location of the system file-pointer + in bytes */ + ADIOI_Fns *fns; /* struct of I/O functions to use */ + MPI_Comm comm; /* communicator indicating who called open */ + int is_open; /* deferred open: 0: not open yet 1: is open */ + int is_agg; /* bool: if I am an aggregator */ + char *filename; + int file_system; /* type of file system */ + int access_mode; /* Access mode (sequential, append, etc.) */ + ADIO_Offset disp; /* reqd. for MPI-IO */ + MPI_Datatype etype; /* reqd. for MPI-IO */ + MPI_Datatype filetype; /* reqd. for MPI-IO */ + MPI_Count etype_size; /* in bytes */ + ADIOI_Hints *hints; /* structure containing fs-indep. info values */ + MPI_Info info; + + /* The following support the split collective operations */ + int split_coll_count; /* count of outstanding split coll. ops. */ + MPI_Status split_status; /* status used for split collectives */ + MPI_Datatype split_datatype; /* datatype used for split collectives */ + + /* The following support the shared file operations */ + char *shared_fp_fname; /* name of file containing shared file pointer */ + struct ADIOI_FileD *shared_fp_fd; /* file handle of file + containing shared fp */ + int async_count; /* count of outstanding nonblocking operations */ + int perm; + int atomicity; /* true=atomic, false=nonatomic */ + int fortran_handle; /* handle for Fortran interface if needed */ + MPI_Errhandler err_handler; + void *fs_ptr; /* file-system specific information */ + + /* Two phase collective I/O support */ + ADIO_Offset *file_realm_st_offs; /* file realm starting offsets */ + MPI_Datatype *file_realm_types; /* file realm datatypes */ + int my_cb_nodes_index; /* my index into cb_config_list. -1 if N/A */ + char *io_buf; /* two-phase buffer allocated out of i/o path */ + /* External32 */ + int is_external32; /* bool: 0 means native view */ + +} ADIOI_FileD; + +typedef struct ADIOI_FileD *ADIO_File; + +typedef MPI_Request ADIO_Request; + +/* fcntl structure */ +typedef struct { + ADIO_Offset disp; + MPI_Datatype etype; + MPI_Datatype filetype; + MPI_Info info; + int atomicity; + ADIO_Offset fsize; /* for get_fsize only */ + ADIO_Offset diskspace; /* for file preallocation */ +} ADIO_Fcntl_t; /* should contain more stuff */ + + +/* access modes */ +#define ADIO_CREATE 1 +#define ADIO_RDONLY 2 +#define ADIO_WRONLY 4 +#define ADIO_RDWR 8 +#define ADIO_DELETE_ON_CLOSE 16 +#define ADIO_UNIQUE_OPEN 32 +#define ADIO_EXCL 64 +#define ADIO_APPEND 128 +#define ADIO_SEQUENTIAL 256 + +#define ADIO_AMODE_NOMATCH ~(ADIO_CREATE|ADIO_RDONLY|ADIO_WRONLY|ADIO_RDWR|ADIO_DELETE_ON_CLOSE|ADIO_UNIQUE_OPEN|ADIO_EXCL|ADIO_APPEND|ADIO_SEQUENTIAL) + +/* file-pointer types */ +#define ADIO_EXPLICIT_OFFSET 100 +#define ADIO_INDIVIDUAL 101 +#define ADIO_SHARED 102 + +#define ADIO_REQUEST_NULL ((ADIO_Request) 0) +#define ADIO_FILE_NULL ((ADIO_File) 0) + +/* file systems */ +#define ADIO_NFS 150 +#define ADIO_PIOFS 151 /* IBM */ +#define ADIO_UFS 152 /* Unix file system */ +#define ADIO_PFS 153 /* Intel */ +#define ADIO_XFS 154 /* SGI */ +#define ADIO_HFS 155 /* HP/Convex */ +#define ADIO_SFS 156 /* NEC */ +#define ADIO_PVFS 157 /* PVFS for Linux Clusters from Clemson Univ. */ +#define ADIO_NTFS 158 /* NTFS for Windows NT */ +#define ADIO_TESTFS 159 /* fake file system for testing */ +#define ADIO_PVFS2 160 /* PVFS2: 2nd generation PVFS */ +#define ADIO_PANFS 161 /* Panasas FS */ +#define ADIO_GRIDFTP 162 /* Globus GridFTP */ +#define ADIO_LUSTRE 163 /* Lustre */ +/* #define ADIO_BGL 164 */ /* IBM BGL */ +/* #define ADIO_BGLOCKLESS 165 */ /* IBM BGL (lock-free) */ +#define ADIO_ZOIDFS 167 /* ZoidFS: the I/O forwarding fs */ +/* #define ADIO_BG 168 */ +#define ADIO_GPFS 168 + +#define ADIO_SEEK_SET SEEK_SET +#define ADIO_SEEK_CUR SEEK_CUR +#define ADIO_SEEK_END SEEK_END + +#define ADIO_FCNTL_SET_ATOMICITY 180 +#define ADIO_FCNTL_SET_DISKSPACE 188 +#define ADIO_FCNTL_GET_FSIZE 200 + +/* file system feature tests */ +#define ADIO_LOCKS 300 /* file system supports fcntl()-style locking */ +#define ADIO_SHARED_FP 301 /* file system supports shared file pointers */ +#define ADIO_ATOMIC_MODE 302 /* file system supports atomic mode */ +#define ADIO_DATA_SIEVING_WRITES 303 /* file system supports data sieving for writes */ +#define ADIO_SCALABLE_OPEN 304 /* one process can open the file and + broadcast result to all other + processors */ +#define ADIO_UNLINK_AFTER_CLOSE 305 /* supports posix semantic of keeping a + deleted file around until all + processors have closed it */ +#define ADIO_TWO_PHASE 306 /* file system implements some version of + two-phase collective buffering with + aggregation */ +#define ADIO_SCALABLE_RESIZE 307 /* file system supports resizing from one + processor (nfs, e.g. does not) */ + +/* for default file permissions */ +#define ADIO_PERM_NULL -1 + +#define ADIOI_FILE_COOKIE 2487376 +#define ADIOI_REQ_COOKIE 3493740 + +/* ADIO function prototypes */ +/* all these may not be necessary, as many of them are macro replaced to + function pointers that point to the appropriate functions for each + different file system (in adioi.h), but anyway... */ + +void ADIO_Init(int *argc, char ***argv, int *error_code); +void ADIO_End(int *error_code); +MPI_File ADIO_Open(MPI_Comm orig_comm, MPI_Comm comm, const char *filename, + int file_system, ADIOI_Fns *ops, + int access_mode, ADIO_Offset disp, MPI_Datatype etype, + MPI_Datatype filetype, + MPI_Info info, int perm, int *error_code); +void ADIOI_OpenColl(ADIO_File fd, int rank, int acces_mode, int *error_code); +void ADIO_ImmediateOpen(ADIO_File fd, int *error_code); +void ADIO_Close(ADIO_File fd, int *error_code); +void ADIO_ReadContig(ADIO_File fd, void *buf, int count, MPI_Datatype datatype, + int file_ptr_type, ADIO_Offset offset, + ADIO_Status *status, int *error_code); +void ADIO_WriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, int *bytes_written, int + *error_code); +void ADIO_IwriteContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIO_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +int ADIO_ReadDone(ADIO_Request *request, ADIO_Status *status, + int *error_code); +int ADIO_WriteDone(ADIO_Request *request, ADIO_Status *status, + int *error_code); +int ADIO_ReadIcomplete(ADIO_Request *request, ADIO_Status *status, int + *error_code); +int ADIO_WriteIcomplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIO_ReadComplete(ADIO_Request *request, ADIO_Status *status, int + *error_code); +void ADIO_WriteComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIO_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int + *error_code); +void ADIO_ReadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIO_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); +void ADIO_ReadStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIO_WriteStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIO_IreadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIO_IwriteStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +ADIO_Offset ADIO_SeekIndividual(ADIO_File fd, ADIO_Offset offset, + int whence, int *error_code); +void ADIO_Delete(char *filename, int *error_code); +void ADIO_Flush(ADIO_File fd, int *error_code); +void ADIO_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +void ADIO_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); +void ADIO_ResolveFileType(MPI_Comm comm, const char *filename, int *fstype, + ADIOI_Fns **ops, int *error_code); +void ADIO_Get_shared_fp(ADIO_File fd, ADIO_Offset size, ADIO_Offset *shared_fp, + int *error_code); +void ADIO_Set_shared_fp(ADIO_File fd, ADIO_Offset offset, int *error_code); +void ADIO_Set_view(ADIO_File fd, ADIO_Offset disp, MPI_Datatype etype, + MPI_Datatype filetype, MPI_Info info, int *error_code); +int ADIO_Feature(ADIO_File fd, int flag); + +/* functions to help deal with the array datatypes */ +int ADIO_Type_create_subarray(int ndims, + int *array_of_sizes, + int *array_of_subsizes, + int *array_of_starts, + int order, + MPI_Datatype oldtype, + MPI_Datatype *newtype); +int ADIO_Type_create_darray(int size, int rank, int ndims, + int *array_of_gsizes, int *array_of_distribs, + int *array_of_dargs, int *array_of_psizes, + int order, MPI_Datatype oldtype, + MPI_Datatype *newtype); + +/* MPI_File management functions (in mpio_file.c) */ +MPI_File MPIO_File_create(int size); +ADIO_File MPIO_File_resolve(MPI_File mpi_fh); +void MPIO_File_free(MPI_File *mpi_fh); +MPI_File MPIO_File_f2c(MPI_Fint fh); +MPI_Fint MPIO_File_c2f(MPI_File fh); +int MPIO_Err_create_code(int lastcode, int fatal, const char fcname[], + int line, int error_class, const char generic_msg[], + const char specific_msg[], ... ); +int MPIO_Err_return_file(MPI_File mpi_fh, int error_code); +int MPIO_Err_return_comm(MPI_Comm mpi_comm, int error_code); + +/* request managment helper functions */ +void MPIO_Completed_request_create(MPI_File *fh, MPI_Offset nbytes, + int * error_code, MPI_Request *request); + +#include "adioi.h" +#include "adioi_fs_proto.h" +#include "mpio_error.h" +#include "mpipr.h" + +/* these two defines don't appear to be in any other header file */ +#define MPIR_ERR_FATAL 1 +#define MPIR_ERR_RECOVERABLE 0 + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/include/adio_cb_config_list.h b/ompi/mca/io/romio314/romio/adio/include/adio_cb_config_list.h new file mode 100644 index 0000000000..ab2c5b501f --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/adio_cb_config_list.h @@ -0,0 +1,27 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2001 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* I have no idea what the "D" stands for; it's how things are done in adio.h + */ +struct ADIO_cb_name_arrayD { + int refct; + int namect; + char **names; +}; + +typedef struct ADIO_cb_name_arrayD *ADIO_cb_name_array; + +int ADIOI_cb_gather_name_array(MPI_Comm comm, MPI_Comm dupcomm, + ADIO_cb_name_array *arrayp); +int ADIOI_cb_copy_name_array(MPI_Comm comm, int keyval, void *extra, + void *attr_in, + void **attr_out, int *flag); +int ADIOI_cb_delete_name_array(MPI_Comm comm, int keyval, void *attr_val, + void *extra); +int ADIOI_cb_config_list_parse(char *config_list, ADIO_cb_name_array array, + int ranklist[], int cb_nodes); +int ADIOI_cb_bcast_rank_map(ADIO_File fd); diff --git a/ompi/mca/io/romio314/romio/adio/include/adio_extern.h b/ompi/mca/io/romio314/romio/adio/include/adio_extern.h new file mode 100644 index 0000000000..9a7f2e59b0 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/adio_extern.h @@ -0,0 +1,31 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +extern ADIOI_Flatlist_node *ADIOI_Flatlist; + +extern ADIOI_Datarep *ADIOI_Datarep_head; + +/* for f2c and c2f conversion */ +extern ADIO_File *ADIOI_Ftable; +extern int ADIOI_Ftable_ptr, ADIOI_Ftable_max; +extern ADIO_Request *ADIOI_Reqtable; +extern int ADIOI_Reqtable_ptr, ADIOI_Reqtable_max; +#ifndef HAVE_MPI_INFO +extern MPI_Info *MPIR_Infotable; +extern int MPIR_Infotable_ptr, MPIR_Infotable_max; +#endif +#if defined(ROMIO_XFS) || defined(ROMIO_LUSTRE) +extern int ADIOI_Direct_read, ADIOI_Direct_write; +#endif + +extern MPI_Errhandler ADIOI_DFLT_ERR_HANDLER; + +extern MPI_Info ADIOI_syshints; + +extern MPI_Op ADIO_same_amode; + +extern int ADIOI_cb_config_list_keyval; diff --git a/ompi/mca/io/romio314/romio/adio/include/adioi.h b/ompi/mca/io/romio314/romio/adio/include/adioi.h new file mode 100644 index 0000000000..3fddbdabf6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/adioi.h @@ -0,0 +1,918 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + + +/* contains general definitions, declarations, and macros internal to + the ADIO implementation, though independent of the underlying file + system. This file is included in adio.h */ + +/* Functions and datataypes that are "internal" to the ADIO implementation + prefixed ADIOI_. Functions and datatypes that are part of the + "externally visible" (documented) ADIO interface are prefixed ADIO_. + + An implementation of MPI-IO, or any other high-level interface, should + not need to use any of the ADIOI_ functions/datatypes. + Only someone implementing ADIO on a new file system, or modifying + an existing ADIO implementation, would need to use the ADIOI_ + functions/datatypes. */ + + +#ifndef ADIOI_INCLUDE +#define ADIOI_INCLUDE +/* used to keep track of hint/info values. + * Note that there are a lot of int-sized values in here...they are + * used as int-sized entities other places as well. This would be a + * problem on 32-bit systems using > 2GB files in some cases... + */ +struct ADIOI_Hints_struct { + int initialized; + int striping_factor; + int striping_unit; + int cb_read; + int cb_write; + int cb_nodes; + int cb_buffer_size; + int cb_pfr; + int cb_fr_type; + int cb_fr_alignment; + int cb_ds_threshold; + int cb_alltoall; + int ds_read; + int ds_write; + int no_indep_rw; + int ind_rd_buffer_size; + int ind_wr_buffer_size; + int deferred_open; + int min_fdomain_size; + char *cb_config_list; + int *ranklist; + union { + struct { + int listio_read; + int listio_write; + } pvfs; + struct { + int debugmask; + int posix_read; + int posix_write; + int listio_read; + int listio_write; + int dtype_read; + int dtype_write; + } pvfs2; + struct { + int start_iodevice; + int co_ratio; + int coll_threshold; + int ds_in_coll; + } lustre; + struct { + unsigned read_chunk_sz; /* chunk size for direct reads */ + unsigned write_chunk_sz; /* chunk size for direct writes */ + } xfs; + struct { + int *bridgelist; /* list of all bride ranks */ + int *bridgelistnum; /* each entry here is the number of aggregators + associated with the bridge rank of the same + index in bridgelist */ + int numbridges; /* total number of bridges */ + } bg; + } fs_hints; + +}; + +typedef struct ADIOI_Datarep { + char *name; + void *state; + MPI_Datarep_extent_function *extent_fn; + MPI_Datarep_conversion_function *read_conv_fn; + MPI_Datarep_conversion_function *write_conv_fn; + struct ADIOI_Datarep *next; /* pointer to next datarep */ +} ADIOI_Datarep; + +/* Values for use with cb_read, cb_write, ds_read, and ds_write + * and some fs-specific hints + (IBM xlc, Compaq Tru64 compilers object to a comma after the last item) + (that's just wrong) + */ +enum { + ADIOI_HINT_AUTO = 0, + ADIOI_HINT_ENABLE = 1, + ADIOI_HINT_DISABLE = 2 +}; + +/* flattened datatypes. Each datatype is stored as a node of a + globally accessible linked list. Once attribute caching on a + datatype is available (in MPI-2), that should be used instead. */ + +typedef struct ADIOI_Fl_node { + MPI_Datatype type; + MPI_Count count; /* no. of contiguous blocks */ + ADIO_Offset *blocklens; /* array of contiguous block lengths (bytes)*/ + ADIO_Offset *indices; /* array of byte offsets of each block */ + struct ADIOI_Fl_node *next; /* pointer to next node */ +} ADIOI_Flatlist_node; + +#ifdef ROMIO_PVFS2 +#include +#endif +typedef struct ADIOI_AIO_req_str { + /* very wierd: if this MPI_Request is a pointer, some C++ compilers + * will clobber it when the MPICH C++ bindings are used */ + MPI_Request req; + MPI_Offset nbytes; + /* should probably make this a union */ +#ifdef ROMIO_HAVE_WORKING_AIO + struct aiocb *aiocbp; +#endif +#ifdef ROMIO_PVFS2 + PVFS_sys_op_id op_id; + PVFS_sysresp_io resp_io; + PVFS_Request file_req; + PVFS_Request mem_req; +#endif +#ifdef ROMIO_NTFS + /* Ptr to Overlapped struct */ + LPOVERLAPPED lpOvl; + /* Ptr to file handle */ + HANDLE fd; +#endif +} ADIOI_AIO_Request; + +struct ADIOI_Fns_struct { + void (*ADIOI_xxx_Open) (ADIO_File fd, int *error_code); + void (*ADIOI_xxx_OpenColl) (ADIO_File fd, int rank, + int access_mode, int *error_code); + void (*ADIOI_xxx_ReadContig) (ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code); + void (*ADIOI_xxx_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); + void (*ADIOI_xxx_ReadStridedColl) (ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code); + void (*ADIOI_xxx_WriteStridedColl) (ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code); + ADIO_Offset (*ADIOI_xxx_SeekIndividual) (ADIO_File fd, ADIO_Offset offset, + int whence, int *error_code); + void (*ADIOI_xxx_Fcntl) (ADIO_File fd, int flag, + ADIO_Fcntl_t *fcntl_struct, int *error_code); + void (*ADIOI_xxx_SetInfo) (ADIO_File fd, MPI_Info users_info, + int *error_code); + void (*ADIOI_xxx_ReadStrided) (ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int *error_code); + void (*ADIOI_xxx_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); + void (*ADIOI_xxx_Close) (ADIO_File fd, int *error_code); + void (*ADIOI_xxx_IreadContig) (ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int *error_code); + void (*ADIOI_xxx_IwriteContig) (ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int *error_code); + int (*ADIOI_xxx_ReadDone) (ADIO_Request *request, ADIO_Status *status, + int *error_code); + int (*ADIOI_xxx_WriteDone) (ADIO_Request *request, ADIO_Status *status, + int *error_code); + void (*ADIOI_xxx_ReadComplete) (ADIO_Request *request, ADIO_Status *status, + int *error_code); + void (*ADIOI_xxx_WriteComplete) (ADIO_Request *request, ADIO_Status *status, + int *error_code); + void (*ADIOI_xxx_IreadStrided) (ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int *error_code); + void (*ADIOI_xxx_IwriteStrided) (ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int *error_code); + void (*ADIOI_xxx_Flush) (ADIO_File fd, int *error_code); + void (*ADIOI_xxx_Resize) (ADIO_File fd, ADIO_Offset size, int *error_code); + void (*ADIOI_xxx_Delete) (const char *filename, int *error_code); + int (*ADIOI_xxx_Feature) (ADIO_File fd, int flag); + const char *fsname; +}; + +/* optypes for ADIO_RequestD */ +#define ADIOI_READ 26 +#define ADIOI_WRITE 27 + +#define ADIOI_MIN(a, b) ((a) < (b) ? (a) : (b)) +#define ADIOI_MAX(a, b) ((a) > (b) ? (a) : (b)) +/* thanks stackoverflow: + * http://stackoverflow.com/questions/3982348/implement-generic-swap-macro-in-c */ +#define ADIOI_SWAP(x, y, T) do { T temp##x##y = x; x = y; y = temp##x##y; } while (0); + +#define ADIOI_PREALLOC_BUFSZ 16777216 /* buffer size used to + preallocate disk space */ + + +/* default values for some hints */ + /* buffer size for collective I/O = 16 MB */ +#define ADIOI_CB_BUFFER_SIZE_DFLT "16777216" + /* buffer size for data sieving in independent reads = 4MB */ +#define ADIOI_IND_RD_BUFFER_SIZE_DFLT "4194304" + /* buffer size for data sieving in independent writes = 512KB. default is + smaller than for reads, because write requires read-modify-write + with file locking. If buffer size is large there is more contention + for locks. */ +#define ADIOI_IND_WR_BUFFER_SIZE_DFLT "524288" + /* use one process per processor name by default */ +#define ADIOI_CB_CONFIG_LIST_DFLT "*:1" + + +/* some of the ADIO functions are macro-replaced */ + +#define ADIOI_OpenColl(fd, rank, access_mode, error_code) \ + (*(fd->fns->ADIOI_xxx_OpenColl))(fd, rank, access_mode, error_code) + +#define ADIO_ReadContig(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) \ + (*(fd->fns->ADIOI_xxx_ReadContig))(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) + +#define ADIO_WriteContig(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) \ + (*(fd->fns->ADIOI_xxx_WriteContig))(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) + +#define ADIO_SeekIndividual(fd,offset,whence,error_code) \ + (*(fd->fns->ADIOI_xxx_SeekIndividual))(fd,offset,whence,error_code) + +#define ADIO_Fcntl(fd,flag,fcntl_struct,error_code) \ + (*(fd->fns->ADIOI_xxx_Fcntl))(fd,flag,fcntl_struct,error_code) + +#define ADIO_IreadContig(fd,buf,count,datatype,file_ptr_type,offset,request,error_code) \ + (*(fd->fns->ADIOI_xxx_IreadContig))(fd,buf,count,datatype,file_ptr_type,offset,request,error_code) + +#define ADIO_IwriteContig(fd,buf,count,datatype,file_ptr_type,offset,request,error_code) \ + (*(fd->fns->ADIOI_xxx_IwriteContig))(fd,buf,count,datatype,file_ptr_type,offset,request,error_code) + +/* in these routines a pointer to request is passed */ +#define ADIO_ReadDone(request,status,error_code) \ + (*((*(request))->fd->fns->ADIOI_xxx_ReadDone))(request,status,error_code) + +#define ADIO_WriteDone(request,status,error_code) \ + (*((*(request))->fd->fns->ADIOI_xxx_WriteDone))(request,status,error_code) + +#define ADIO_ReadIcomplete(request,status,error_code) \ + (*((*(request))->fd->fns->ADIOI_xxx_ReadIcomplete))(request,status,error_code) + +#define ADIO_WriteIcomplete(request,status,error_code) \ + (*((*(request))->fd->fns->ADIOI_xxx_WriteIcomplete))(request,status,error_code) + +#define ADIO_ReadComplete(request,status,error_code) \ + (*((*(request))->fd->fns->ADIOI_xxx_ReadComplete))(request,status,error_code) + +#define ADIO_WriteComplete(request,status,error_code) \ + (*((*(request))->fd->fns->ADIOI_xxx_WriteComplete))(request,status,error_code) + +#define ADIO_ReadStrided(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) \ + (*(fd->fns->ADIOI_xxx_ReadStrided))(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) + +#define ADIO_WriteStrided(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) \ + (*(fd->fns->ADIOI_xxx_WriteStrided))(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) + +#define ADIO_ReadStridedColl(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) \ + (*(fd->fns->ADIOI_xxx_ReadStridedColl))(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) + +#define ADIO_WriteStridedColl(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) \ + (*(fd->fns->ADIOI_xxx_WriteStridedColl))(fd,buf,count,datatype,file_ptr_type,offset,status,error_code) + +#define ADIO_IreadStrided(fd,buf,count,datatype,file_ptr_type,offset,request,error_code) \ + (*(fd->fns->ADIOI_xxx_IreadStrided))(fd,buf,count,datatype,file_ptr_type,offset,request,error_code) + +#define ADIO_IwriteStrided(fd,buf,count,datatype,file_ptr_type,offset,request,error_code) \ + (*(fd->fns->ADIOI_xxx_IwriteStrided))(fd,buf,count,datatype,file_ptr_type,offset,request,error_code) + +#define ADIO_Flush(fd,error_code) (*(fd->fns->ADIOI_xxx_Flush))(fd,error_code) + +#define ADIO_Resize(fd,size,error_code) \ + (*(fd->fns->ADIOI_xxx_Resize))(fd,size,error_code) + +#define ADIO_Delete(filename,error_code) \ + (*(fd->fns->ADIOI_xxx_Delete))(filename,error_code) + +#define ADIO_SetInfo(fd, users_info, error_code) \ + (*(fd->fns->ADIOI_xxx_SetInfo))(fd, users_info, error_code) + +#define ADIO_Feature(fd, flag) \ + (*(fd->fns->ADIOI_xxx_Feature))(fd, flag) + + +/* structure for storing access info of this process's request + from the file domain of other processes, and vice-versa. used + as array of structures indexed by process number. */ +typedef struct { + ADIO_Offset *offsets; /* array of offsets */ + ADIO_Offset *lens; /* array of lengths */ + MPI_Aint *mem_ptrs; /* array of pointers. used in the read/write + phase to indicate where the data + is stored in memory */ + int count; /* size of above arrays */ +} ADIOI_Access; + +/* structure for storing generic offset/length pairs. used to describe + file realms among other things */ +typedef struct { + ADIO_Offset *offsets; /* array of offsets */ + ADIO_Offset *lens; /* array of lengths */ + int count; /* size of above arrays */ +} ADIOI_Offlen; + +/* prototypes for ADIO internal functions */ + +void ADIOI_SetFunctions(ADIO_File fd); +void ADIOI_Flatten_datatype(MPI_Datatype type); +void ADIOI_Flatten(MPI_Datatype type, ADIOI_Flatlist_node *flat, + ADIO_Offset st_offset, MPI_Count *curr_index); +void ADIOI_Delete_flattened(MPI_Datatype datatype); +MPI_Count ADIOI_Count_contiguous_blocks(MPI_Datatype type, MPI_Count *curr_index); +void ADIOI_Complete_async(int *error_code); +void *ADIOI_Malloc_fn(size_t size, int lineno, const char *fname); +void *ADIOI_Calloc_fn(size_t nelem, size_t elsize, int lineno, const char *fname); +void *ADIOI_Realloc_fn(void *ptr, size_t size, int lineno, const char *fname); +void ADIOI_Free_fn(void *ptr, int lineno, const char *fname); +void ADIOI_Datatype_iscontig(MPI_Datatype datatype, int *flag); +void ADIOI_Get_position(ADIO_File fd, ADIO_Offset *offset); +void ADIOI_Get_eof_offset(ADIO_File fd, ADIO_Offset *eof_offset); +void ADIOI_Get_byte_offset(ADIO_File fd, ADIO_Offset offset, + ADIO_Offset *disp); +void ADIOI_process_system_hints(ADIO_File fd, MPI_Info info); +void ADIOI_incorporate_system_hints(MPI_Info info, MPI_Info sysinfo, + MPI_Info *new_info); +void ADIOI_Info_print_keyvals(MPI_Info info); + + +void ADIOI_GEN_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, + int *error_code); +void ADIOI_GEN_Flush(ADIO_File fd, int *error_code); +void ADIOI_GEN_OpenColl(ADIO_File fd, int rank, + int access_mode, int *error_code); +void ADIOI_SCALEABLE_OpenColl(ADIO_File fd, int rank, + int access_mode, int *error_code); +void ADIOI_FAILSAFE_OpenColl(ADIO_File fd, int rank, + int access_mode, int *error_code); +void ADIOI_GEN_Delete(const char *filename, int *error_code); +void ADIOI_GEN_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 ADIOI_GEN_aio(ADIO_File fd, void *buf, int len, ADIO_Offset offset, + int wr, MPI_Request *request); +void ADIOI_GEN_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code); +void ADIOI_GEN_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); +void ADIOI_GEN_IwriteContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *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); +void ADIOI_GEN_IreadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +void ADIOI_GEN_IwriteStrided(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, int + *error_code); +int ADIOI_GEN_IODone(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIOI_GEN_IOComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); +int ADIOI_GEN_aio_poll_fn(void *extra_state, ADIO_Status *status); +int ADIOI_GEN_aio_wait_fn(int count, void **array_of_states, double timeout, + ADIO_Status *status); +int ADIOI_GEN_aio_query_fn(void *extra_state, ADIO_Status *status); +int ADIOI_GEN_aio_free_fn(void *extra_state); +int ADIOI_GEN_Feature(ADIO_File fd, int feature); + +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); +void ADIOI_GEN_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); +void ADIOI_GEN_WriteStrided_naive(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_NOLOCK_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); +void ADIOI_GEN_ReadStridedColl(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_GEN_WriteStridedColl(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_Calc_my_off_len(ADIO_File fd, int bufcount, MPI_Datatype + datatype, int file_ptr_type, ADIO_Offset + offset, ADIO_Offset **offset_list_ptr, ADIO_Offset + **len_list_ptr, ADIO_Offset *start_offset_ptr, + ADIO_Offset *end_offset_ptr, int + *contig_access_count_ptr); +void ADIOI_Calc_file_domains(ADIO_Offset *st_offsets, ADIO_Offset + *end_offsets, int nprocs, int nprocs_for_coll, + ADIO_Offset *min_st_offset_ptr, + ADIO_Offset **fd_start_ptr, ADIO_Offset + **fd_end_ptr, int min_fd_size, + ADIO_Offset *fd_size_ptr, + int striping_unit); +int ADIOI_Calc_aggregator(ADIO_File fd, + ADIO_Offset off, + ADIO_Offset min_off, + ADIO_Offset *len, + ADIO_Offset fd_size, + ADIO_Offset *fd_start, + ADIO_Offset *fd_end); +void ADIOI_Calc_my_req(ADIO_File fd, ADIO_Offset *offset_list, + ADIO_Offset *len_list, int + contig_access_count, ADIO_Offset + min_st_offset, ADIO_Offset *fd_start, + ADIO_Offset *fd_end, ADIO_Offset fd_size, + int nprocs, + int *count_my_req_procs_ptr, + int **count_my_req_per_proc_ptr, + ADIOI_Access **my_req_ptr, + int **buf_idx_ptr); +void ADIOI_Calc_others_req(ADIO_File fd, int count_my_req_procs, + int *count_my_req_per_proc, + ADIOI_Access *my_req, + int nprocs, int myrank, + int *count_others_req_procs_ptr, + ADIOI_Access **others_req_ptr); + +/* KC && AC - New Collective I/O internals*/ + +#define TEMP_OFF 0 +#define REAL_OFF 1 +#define MAX_OFF_TYPE 2 + +/* Communication Tags */ +#define DATA_TAG 30 +#define AMT_TAG 31 + +/* cb_fr_type user size is non-zero */ +#define ADIOI_FR_AAR 0 +#define ADIOI_FR_FSZ -1 +#define ADIOI_FR_USR_REALMS -2 + +typedef struct flatten_state +{ + ADIO_Offset abs_off; + ADIO_Offset cur_sz; + ADIO_Offset idx; + ADIO_Offset cur_reg_off; +} flatten_state; + +typedef struct view_state +{ + ADIO_Offset fp_ind; /* file view params*/ + ADIO_Offset disp; /* file view params*/ + ADIO_Offset byte_off; + ADIO_Offset sz; + ADIO_Offset ext; /* preserved extent from MPI_Type_extent */ + ADIO_Offset type_sz; + + /* Current state */ + flatten_state cur_state; + /* Scratch state for counting up ol pairs */ + flatten_state tmp_state; + + /* Preprocessed data amount and ol pairs */ + ADIO_Offset pre_sz; + int pre_ol_ct; + MPI_Aint *pre_disp_arr; + int *pre_blk_arr; + + ADIOI_Flatlist_node *flat_type_p; +} view_state; + +void ADIOI_Calc_bounds (ADIO_File fd, int count, MPI_Datatype buftype, + int file_ptr_type, ADIO_Offset offset, + ADIO_Offset *st_offset, ADIO_Offset *end_offset); +int ADIOI_Agg_idx (int rank, ADIO_File fd); +void ADIOI_Calc_file_realms (ADIO_File fd, ADIO_Offset min_st_offset, + ADIO_Offset max_end_offset); +void ADIOI_IOFiletype(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, MPI_Datatype custom_ftype, + int rdwr, ADIO_Status *status, int + *error_code); +void ADIOI_IOStridedColl(ADIO_File fd, void *buf, int count, int rdwr, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Status *status, int + *error_code); +void ADIOI_Print_flatlist_node(ADIOI_Flatlist_node *flatlist_node_p); +ADIOI_Flatlist_node * ADIOI_Add_contig_flattened(MPI_Datatype contig_type); +void ADIOI_Exch_file_views(int myrank, int nprocs, int file_ptr_type, + ADIO_File fd, int count, + MPI_Datatype datatype, ADIO_Offset off, + view_state *my_mem_view_state_arr, + view_state *agg_file_view_state_arr, + view_state *client_file_view_state_arr); +int ADIOI_init_view_state(int file_ptr_type, + int nprocs, + view_state *view_state_arr, + int op_type); +int ADIOI_Build_agg_reqs(ADIO_File fd, int rw_type, int nprocs, + view_state *client_file_view_state_arr, + MPI_Datatype *client_comm_dtype_arr, + ADIO_Offset *client_comm_sz_arr, + ADIO_Offset *agg_dtype_offset_p, + MPI_Datatype *agg_dtype_p); +int ADIOI_Build_client_reqs(ADIO_File fd, + int nprocs, + view_state *my_mem_view_state_arr, + view_state *agg_file_view_state_arr, + ADIO_Offset *agg_comm_sz_arr, + MPI_Datatype *agg_comm_dtype_arr); +int ADIOI_Build_client_pre_req(ADIO_File fd, + int agg_rank, + int agg_idx, + view_state *my_mem_view_state_p, + view_state *agg_file_view_state_p, + ADIO_Offset max_pre_req_sz, + int max_ol_ct); +int ADIOI_Build_client_req(ADIO_File fd, + int agg_rank, + int agg_idx, + view_state *my_mem_view_state_p, + view_state *agg_file_view_state_p, + ADIO_Offset agg_comm_sz, + MPI_Datatype *agg_comm_dtype_p); + +void ADIOI_P2PContigWriteAggregation(ADIO_File fd, + const void *buf, + int *error_code, + ADIO_Offset *st_offsets, + ADIO_Offset *end_offset, + ADIO_Offset *fd_start, + ADIO_Offset *fd_end); + +void ADIOI_P2PContigReadAggregation(ADIO_File fd, + const void *buf, + int *error_code, + ADIO_Offset *st_offsets, + ADIO_Offset *end_offset, + ADIO_Offset *fd_start, + ADIO_Offset *fd_end); + +ADIO_Offset ADIOI_GEN_SeekIndividual(ADIO_File fd, ADIO_Offset offset, + int whence, int *error_code); +void ADIOI_GEN_Resize(ADIO_File fd, ADIO_Offset size, int *error_code); +void ADIOI_GEN_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code); +void ADIOI_GEN_Close(ADIO_File fd, int *error_code); +void ADIOI_Shfp_fname(ADIO_File fd, int rank, int *error_code); +void ADIOI_GEN_Prealloc(ADIO_File fd, ADIO_Offset size, int *error_code); +int ADIOI_Error(ADIO_File fd, int error_code, char *string); +int MPIR_Err_setmsg( int, int, const char *, const char *, const char *, ... ); +int ADIOI_End_call(MPI_Comm comm, int keyval, void *attribute_val, void *extra_state); +int MPIR_Status_set_bytes(MPI_Status *status, MPI_Datatype datatype, MPI_Count nbytes); +int ADIOI_Uses_generic_read(ADIO_File fd); +int ADIOI_Uses_generic_write(ADIO_File fd); +int ADIOI_Err_create_code(const char *myname, const char *filename, int my_errno); +int ADIOI_Type_create_hindexed_x(int count, + const MPI_Count array_of_blocklengths[], + const MPI_Aint array_of_displacements[], + MPI_Datatype oldtype, + MPI_Datatype *newtype); + + +int ADIOI_FAKE_IODone(ADIO_Request *request, ADIO_Status *status, + int *error_code); +void ADIOI_FAKE_IreadContig(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code); +void ADIOI_FAKE_IreadStrided(ADIO_File fd, void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code); +void ADIOI_FAKE_IwriteContig(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code); +void ADIOI_FAKE_IwriteStrided(ADIO_File fd, const void *buf, int count, + MPI_Datatype datatype, int file_ptr_type, + ADIO_Offset offset, ADIO_Request *request, + int *error_code); +void ADIOI_FAKE_IOComplete(ADIO_Request *request, ADIO_Status *status, + int *error_code); + + +/* File I/O common functionality */ +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 MPIOI_File_write(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + const void *buf, + int count, + MPI_Datatype datatype, + char *myname, + MPI_Status *status); +int MPIOI_File_read_all(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + void *buf, + int count, + MPI_Datatype datatype, + char *myname, + MPI_Status *status); +int MPIOI_File_write_all(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + const void *buf, + int count, + MPI_Datatype datatype, + char *myname, + MPI_Status *status); +int MPIOI_File_read_all_begin(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + void *buf, + int count, + MPI_Datatype datatype, + char *myname); +int MPIOI_File_write_all_begin(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + const void *buf, + int count, + MPI_Datatype datatype, + char *myname); +int MPIOI_File_read_all_end(MPI_File fh, + void *buf, + char *myname, + MPI_Status *status); +int MPIOI_File_write_all_end(MPI_File fh, + const void *buf, + char *myname, + MPI_Status *status); +int MPIOI_File_iwrite(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + const void *buf, + int count, + MPI_Datatype datatype, + char *myname, + MPI_Request *request); +int MPIOI_File_iread(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + void *buf, + int count, + MPI_Datatype datatype, + char *myname, + MPI_Request *request); + + + +/* Unix-style file locking */ + +#if (defined(ROMIO_HFS) || defined(ROMIO_XFS)) + +# define ADIOI_WRITE_LOCK(fd, offset, whence, len) \ + do {if (((fd)->file_system == ADIO_XFS) || ((fd)->file_system == ADIO_HFS)) \ + ADIOI_Set_lock64((fd)->fd_sys, F_SETLKW64, F_WRLCK, offset, whence, len);\ + else ADIOI_Set_lock((fd)->fd_sys, F_SETLKW, F_WRLCK, offset, whence, len); } while (0) + +# define ADIOI_READ_LOCK(fd, offset, whence, len) \ + do {if (((fd)->file_system == ADIO_XFS) || ((fd)->file_system == ADIO_HFS)) \ + ADIOI_Set_lock64((fd)->fd_sys, F_SETLKW64, F_RDLCK, offset, whence, len);\ + else ADIOI_Set_lock((fd)->fd_sys, F_SETLKW, F_RDLCK, offset, whence, len); }while (0) + +# define ADIOI_UNLOCK(fd, offset, whence, len) \ + do {if (((fd)->file_system == ADIO_XFS) || ((fd)->file_system == ADIO_HFS)) \ + ADIOI_Set_lock64((fd)->fd_sys, F_SETLK64, F_UNLCK, offset, whence, len); \ + else ADIOI_Set_lock((fd)->fd_sys, F_SETLK, F_UNLCK, offset, whence, len); }while (0) + +#elif (defined(ROMIO_NTFS)) + +#define ADIOI_LOCK_CMD 0 +#define ADIOI_UNLOCK_CMD 1 + +# define ADIOI_WRITE_LOCK(fd, offset, whence, len) \ + ADIOI_Set_lock((fd)->fd_sys, ADIOI_LOCK_CMD, LOCKFILE_EXCLUSIVE_LOCK, offset, whence, len) +# define ADIOI_READ_LOCK(fd, offset, whence, len) \ + ADIOI_Set_lock((fd)->fd_sys, ADIOI_LOCK_CMD, 0, offset, whence, len) +# define ADIOI_UNLOCK(fd, offset, whence, len) \ + ADIOI_Set_lock((fd)->fd_sys, ADIOI_UNLOCK_CMD, LOCKFILE_FAIL_IMMEDIATELY, offset, whence, len) + +#else + +#ifdef ADIOI_MPE_LOGGING +# define ADIOI_WRITE_LOCK(fd, offset, whence, len) do { \ + MPE_Log_event( ADIOI_MPE_writelock_a, 0, NULL ); \ + ADIOI_Set_lock((fd)->fd_sys, F_SETLKW, F_WRLCK, offset, whence, len); \ + MPE_Log_event( ADIOI_MPE_writelock_b, 0, NULL ); } while( 0 ) +# define ADIOI_READ_LOCK(fd, offset, whence, len) \ + MPE_Log_event( ADIOI_MPE_readlock_a, 0, NULL ); do { \ + ADIOI_Set_lock((fd)->fd_sys, F_SETLKW, F_RDLCK, offset, whence, len); \ + MPE_Log_event( ADIOI_MPE_readlock_b, 0, NULL ); } while( 0 ) +# define ADIOI_UNLOCK(fd, offset, whence, len) do { \ + MPE_Log_event( ADIOI_MPE_unlock_a, 0, NULL ); \ + ADIOI_Set_lock((fd)->fd_sys, F_SETLK, F_UNLCK, offset, whence, len); \ + MPE_Log_event( ADIOI_MPE_unlock_b, 0, NULL ); } while( 0 ) +#else +# define ADIOI_WRITE_LOCK(fd, offset, whence, len) \ + ADIOI_Set_lock((fd)->fd_sys, F_SETLKW, F_WRLCK, offset, whence, len) +# define ADIOI_READ_LOCK(fd, offset, whence, len) \ + ADIOI_Set_lock((fd)->fd_sys, F_SETLKW, F_RDLCK, offset, whence, len) +# define ADIOI_UNLOCK(fd, offset, whence, len) \ + ADIOI_Set_lock((fd)->fd_sys, F_SETLK, F_UNLCK, offset, whence, len) +#endif + +#endif + +int ADIOI_Set_lock(FDTYPE fd_sys, int cmd, int type, ADIO_Offset offset, int whence, ADIO_Offset len); +int ADIOI_Set_lock64(FDTYPE fd_sys, int cmd, int type, ADIO_Offset offset, int whence, ADIO_Offset len); + +#define ADIOI_Malloc(a) ADIOI_Malloc_fn(a,__LINE__,__FILE__) +#define ADIOI_Calloc(a,b) ADIOI_Calloc_fn(a,b,__LINE__,__FILE__) +#define ADIOI_Realloc(a,b) ADIOI_Realloc_fn(a,b,__LINE__,__FILE__) +#define ADIOI_Free(a) ADIOI_Free_fn(a,__LINE__,__FILE__) + +int ADIOI_Strncpy( char *outstr, const char *instr, size_t maxlen ); +int ADIOI_Strnapp( char *, const char *, size_t ); +char *ADIOI_Strdup( const char * ); + +/* the current MPI standard is not const-correct, and modern compilers warn + * about the following sort of code: + * + * MPI_Info_set(info, "key", "val"); + * + * reminding us that "key" and "val" are const. We use the following macros to + * cast away the const and suppress the warning. */ +#define ADIOI_Info_set(info_,key_str_,val_) \ + MPI_Info_set((info_),((char*)key_str_),(char*)(val_)) +#define ADIOI_Info_get(info_,key_str_,val_len_,val_,flag_) \ + MPI_Info_get((info_),((char*)key_str_),(val_len_),(val_),(flag_)) +#define ADIOI_Info_get_valuelen(info_,key_str_,val_len_,flag_) \ + MPI_Info_get_valuelen((info_),((char*)key_str_),(val_len_),(flag_)) +#define ADIOI_Info_delete(info_,key_str_) \ + MPI_Info_delete((info_),((char*)key_str_)) + + +/* Provide a fallback snprintf for systems that do not have one */ +/* Define attribute as empty if it has no definition */ +#ifndef ATTRIBUTE +#ifdef HAVE_GCC_ATTRIBUTE +#define ATTRIBUTE(a) __attribute__(a) +#else +#define ATTRIBUTE(a) +#endif +#endif + +/* style: allow:snprintf:1 sig:0 */ + +#ifdef HAVE_SNPRINTF +#define ADIOI_Snprintf snprintf +/* Sometimes systems don't provide prototypes for snprintf */ +#ifdef NEEDS_SNPRINTF_DECL +extern int snprintf( char *, size_t, const char *, ... ) ATTRIBUTE((format(printf,3,4))); +#endif +#else +int ADIOI_Snprintf( char *str, size_t size, const char *format, ... ) + ATTRIBUTE((format(printf,3,4))); +#endif /* HAVE_SNPRINTF */ + +#define FPRINTF fprintf + +#ifndef HAVE_STRERROR +# ifdef HAVE_SYSERRLIST + extern char *sys_errlist[]; +# define strerror(n) sys_errlist[n] +# else +# define PRINT_ERR_MSG +# endif +#endif + +#include "adioi_error.h" + +/* MPE logging variables */ + +#ifdef ADIOI_MPE_LOGGING +#include "mpe.h" + +int ADIOI_MPE_open_a; +int ADIOI_MPE_open_b; +int ADIOI_MPE_read_a; +int ADIOI_MPE_read_b; +int ADIOI_MPE_write_a; +int ADIOI_MPE_write_b; +int ADIOI_MPE_lseek_a; +int ADIOI_MPE_lseek_b; +int ADIOI_MPE_close_a; +int ADIOI_MPE_close_b; +int ADIOI_MPE_writelock_a; +int ADIOI_MPE_writelock_b; +int ADIOI_MPE_readlock_a; +int ADIOI_MPE_readlock_b; +int ADIOI_MPE_unlock_a; +int ADIOI_MPE_unlock_b; +int ADIOI_MPE_postwrite_a; +int ADIOI_MPE_postwrite_b; +int ADIOI_MPE_openinternal_a; +int ADIOI_MPE_openinternal_b; +int ADIOI_MPE_stat_a; +int ADIOI_MPE_stat_b; +int ADIOI_MPE_iread_a; +int ADIOI_MPE_iread_b; +int ADIOI_MPE_iwrite_a; +int ADIOI_MPE_iwrite_b; +#endif + +#ifdef ROMIO_INSIDE_MPICH +/* Assert that this MPI_Aint value can be cast to a ptr value without problem.*/ +/* Basic idea is the value should be unchanged after casting + (no loss of (meaningful) high order bytes in 8 byte MPI_Aint + to (possible) 4 byte ptr cast) */ +/* Should work even on 64bit or old 32bit configs */ + /* Use MPID_Ensure_Aint_fits_in_pointer from mpiutil.h and + MPI_AINT_CAST_TO_VOID_PTR from configure (mpi.h) */ + #include "glue_romio.h" + + #define ADIOI_AINT_CAST_TO_VOID_PTR (void*)(MPIR_Pint) + /* The next two casts are only used when you don't want sign extension + when casting a (possible 4 byte) aint to a (8 byte) long long or offset */ + #define ADIOI_AINT_CAST_TO_LONG_LONG (long long) + #define ADIOI_AINT_CAST_TO_OFFSET ADIOI_AINT_CAST_TO_LONG_LONG + + #define ADIOI_ENSURE_AINT_FITS_IN_PTR(aint_value) MPIR_Ext_ensure_Aint_fits_in_pointer(aint_value) + #define ADIOI_Assert MPIR_Ext_assert +#else + #include + #define ADIOI_AINT_CAST_TO_VOID_PTR (void*) + #define ADIOI_AINT_CAST_TO_LONG_LONG (long long) + #define ADIOI_AINT_CAST_TO_OFFSET ADIOI_AINT_CAST_TO_LONG_LONG + #define ADIOI_ENSURE_AINT_FITS_IN_PTR(aint_value) + #define ADIOI_Assert assert + #define MPIR_Upint unsigned long + #define MPIU_THREADPRIV_DECL +#endif + +#ifdef USE_DBG_LOGGING /*todo fix dependency on mpich?*/ +/* DBGT_FPRINTF terse level printing */ +#define DBGT_FPRINTF if (MPIR_Ext_dbg_romio_verbose_enabled) fprintf(stderr,"%s:%d:",__FILE__,__LINE__); \ +if (MPIR_Ext_dbg_romio_terse_enabled) fprintf +/* DBG_FPRINTF default (typical level) printing */ +#define DBG_FPRINTF if (MPIR_Ext_dbg_romio_verbose_enabled) fprintf(stderr,"%s:%d:",__FILE__,__LINE__); \ +if (MPIR_Ext_dbg_romio_typical_enabled) fprintf +/* DBGV_FPRINTF verbose level printing */ +#define DBGV_FPRINTF if (MPIR_Ext_dbg_romio_verbose_enabled) fprintf(stderr,"%s:%d:",__FILE__,__LINE__); \ + if (MPIR_Ext_dbg_romio_verbose_enabled) fprintf +#else /* compile it out */ +#define DBGT_FPRINTF if (0) fprintf +#define DBG_FPRINTF if (0) fprintf +#define DBGV_FPRINTF if (0) fprintf +#endif + +/* declarations for threaded I/O */ +/* i/o thread data structure (bgmpio_pthreadwc) */ +typedef struct wcThreadFuncData { + ADIO_File fd; + int io_kind; + char *buf; + int size; + ADIO_Offset offset; + ADIO_Status status; + int error_code; +} ADIOI_IO_ThreadFuncData; + +void *ADIOI_IO_Thread_Func(void *vptr_args); + + +#ifdef HAVE_LIMITS_H +#include +#endif + +#ifndef PATH_MAX +#define PATH_MAX 65535 +#endif + +#endif + diff --git a/ompi/mca/io/romio314/romio/adio/include/adioi_errmsg.h b/ompi/mca/io/romio314/romio/adio/include/adioi_errmsg.h new file mode 100644 index 0000000000..b1cdb4577a --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/adioi_errmsg.h @@ -0,0 +1,73 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ + +MPI_ERR_FILE + MPIR_ERR_FILE_NULL "Null file handle" + MPIR_ERR_FILE_CORRUPT "Corrupted file handle" + +MPI_ERR_AMODE + 3 "Exactly one of MPI_MODE_RDONLY, MPI_MODE_WRONLY, or MPI_MODE_RDWR must be specified" + 5 "Cannot use MPI_MODE_CREATE or MPI_MODE_EXCL with MPI_MODE_RDONLY" + 7 "Cannot specify MPI_MODE_SEQUENTIAL with MPI_MODE_RDWR" + +MPI_ERR_ARG + MPIR_ERR_OFFSET_ARG "Invalid offset argument" + MPIR_ERR_DATAREP_ARG "Null datarep argument" + MPIR_ERR_COUNT_ARG "Invalid count argument" + MPIR_ERR_SIZE_ARG "Invalid size argument" + MPIR_ERR_WHENCE_ARG "Invalid whence argument" + MPIR_ERR_FLAG_ARG "flag argument must be the same on all processes" + MPIR_ERR_DISP_ARG "Invalid displacement argument" + MPIR_ERR_ETYPE_ARG "Invalid etype argument" + MPIR_ERR_FILETYPE_ARG "Invalid filetype argument" + MPIR_ERR_SIZE_ARG_NOT_SAME "size argument must be the same on all processes" + MPIR_ERR_OFFSET_ARG_NEG "offset points to a negative location in the file" + MPIR_ERR_WHENCE_ARG_NOT_SAME "whence argument must be the same on all processes" + MPIR_ERR_OFFSET_ARG_NOT_SAME "offset argument must be the same on all processes" + +MPI_ERR_TYPE + MPIR_ERR_TYPE_NULL (null datatype. from MPICH) + +MPI_ERR_UNSUPPORTED_OPERATION + MPIR_ERR_NO_SHARED_FP "Shared file pointer not supported on PIOFS and PVFS" + MPIR_ERR_AMODE_SEQ "Cannot use this function when file is opened with amode MPI_MODE_SEQUENTIAL" + MPIR_ERR_MODE_WRONLY "Cannot read from a file opened with amode MPI_MODE_WRONLY" + MPIR_ERR_NO_MODE_SEQ "MPI_MODE_SEQUENTIAL not supported on PIOFS and PVFS" + +MPI_ERR_REQUEST + MPIR_ERR_REQUEST_NULL (null request. from MPICH) + +MPI_ERR_IO + MPIR_ERR_ETYPE_FRACTIONAL "Only an integral number of etypes can be accessed" + MPIR_ERR_NO_FSTYPE "Can't determine the file-system type. Check the filename/path you provided and try again. Otherwise, prefix the filename with a string to indicate the type of file sytem (piofs:, pfs:, nfs:, ufs:, hfs:, xfs:, sfs:, pvfs:, panfs: ftp: gsiftp:)" + MPIR_ERR_NO_PFS "ROMIO has not been configured to use the PFS file system" + MPIR_ERR_NO_PIOFS "ROMIO has not been configured to use the PIOFS file system" + MPIR_ERR_NO_UFS "ROMIO has not been configured to use the UFS file system" + MPIR_ERR_NO_NFS "ROMIO has not been configured to use the NFS file system" + MPIR_ERR_NO_HFS "ROMIO has not been configured to use the HFS file system" + MPIR_ERR_NO_XFS "ROMIO has not been configured to use the XFS file system" + MPIR_ERR_NO_SFS "ROMIO has not been configured to use the SFS file system" + MPIR_ERR_NO_PVFS "ROMIO has not been configured to use the PVFS file system" + MPIR_ERR_NO_PANFS "ROMIO has not been configured to use the PANFS file system" + MPIR_ERR_MULTIPLE_SPLIT_COLL "Only one active split collective I/O operation allowed per file handle" + MPIR_ERR_NO_SPLIT_COLL "No previous split collective begin" + MPIR_ERR_ASYNC_OUTSTANDING "There are outstanding nonblocking I/O operations on this file" + MPIR_ADIO_ERROR "I/O Error" strerror(errno) + MPIR_READ_PERM "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." + MPIR_PREALLOC_PERM "To preallocate disk space, ROMIO needs to read the file and write it back, but is unable to read the file. Please give the file read permission and open it with MPI_MODE_RDWR." + MPIR_ERR_FILETYPE "Filetype must be constructed out of one or more etypes" + MPIR_ERR_NO_TESTFS "ROMIO has not been configured to use the TESTFS file system" + MPIR_ERR_DEFERRED "independent IO attempted even though no_indep_rw hint given" + MPIR_ERR_NO_BGL "ROMIO has not been configured to use the BGL file system" + +MPI_ERR_COMM + MPIR_ERR_COMM_NULL (null communicator. from MPICH) +MPIR_ERR_COMM_INTER (no intercommunicator. (from MPICH) + +MPI_ERR_UNSUPPORTED_DATAREP + MPIR_ERR_NOT_NATIVE_DATAREP "Only native data representation currently supported" + + diff --git a/ompi/mca/io/romio314/romio/adio/include/adioi_error.h b/ompi/mca/io/romio314/romio/adio/include/adioi_error.h new file mode 100644 index 0000000000..300a063861 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/adioi_error.h @@ -0,0 +1,183 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ + +#include /* for strerror() */ + +/* MPIO_CHECK_XXX macros are used to clean up error checking and + * handling in many of the romio/mpi-io/ source files. + */ +#define MPIO_CHECK_FILE_HANDLE(fh, myname, error_code) \ +if ((fh <= (ADIO_File) 0) || \ + ((fh)->cookie != ADIOI_FILE_COOKIE)) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_FILE, \ + "**iobadfh", 0); \ + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code);\ + goto fn_exit; \ +} + +/* TODO could add more glue code to help check for handle validity, or perhaps + * do some sort of always-safe attribute/info call to check for handle validity */ +#define MPIO_CHECK_COMM(comm_, myname_, error_code_) \ + do { \ + if ((comm_) == MPI_COMM_NULL) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + (myname_), __LINE__, \ + MPI_ERR_COMM, \ + "**commnull", 0); \ + error_code_ = MPIO_Err_return_file(MPI_FILE_NULL, (error_code_)); \ + goto fn_exit; \ + } \ + } while (0) + +#define MPIO_CHECK_COUNT(fh, count, myname, error_code) \ +if (count < 0) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_COUNT, \ + "**iobadcount", 0); \ + error_code = MPIO_Err_return_file(fh, error_code); \ + goto fn_exit; \ +} + +#define MPIO_CHECK_COUNT_SIZE(fh, count, datatype_size, myname, error_code) \ +if (count*datatype_size != (ADIO_Offset)(unsigned)count*(ADIO_Offset)datatype_size) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_ARG, \ + "**iobadcount", 0); \ + error_code = MPIO_Err_return_file(fh, error_code); \ + goto fn_exit; \ +} + +#define MPIO_CHECK_DATATYPE(fh, datatype, myname, error_code) \ + do { \ + if (datatype == MPI_DATATYPE_NULL) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_TYPE, \ + "**dtypenull", 0); \ + } \ + else { \ + MPIO_DATATYPE_ISCOMMITTED(datatype, error_code); \ + } \ + if (error_code != MPI_SUCCESS) { \ + error_code = MPIO_Err_return_file(fh, error_code); \ + goto fn_exit; \ + } \ + } while (0) + +#define MPIO_CHECK_READABLE(fh, myname, error_code) \ +if (fh->access_mode & ADIO_WRONLY) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_ACCESS, \ + "**iowronly", 0); \ + error_code = MPIO_Err_return_file(fh, error_code); \ + goto fn_exit; \ +} + +#define MPIO_CHECK_WRITABLE(fh, myname, error_code) \ +if (fh->access_mode & ADIO_RDONLY) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_READ_ONLY, \ + "**iordonly", \ + 0); \ + error_code = MPIO_Err_return_file(fh, error_code); \ + goto fn_exit; \ +} + +#define MPIO_CHECK_NOT_SEQUENTIAL_MODE(fh, myname, error_code) \ +if (fh->access_mode & ADIO_SEQUENTIAL) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_UNSUPPORTED_OPERATION, \ + "**ioamodeseq", 0); \ + error_code = MPIO_Err_return_file(fh, error_code); \ + goto fn_exit; \ +} + +#define MPIO_CHECK_INTEGRAL_ETYPE(fh, count, dtype_size, myname, error_code) \ +if ((count*dtype_size) % fh->etype_size != 0) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, MPI_ERR_IO, \ + "**ioetype", 0); \ + error_code = MPIO_Err_return_file(fh, error_code); \ + goto fn_exit; \ +} + +#define MPIO_CHECK_FS_SUPPORTS_SHARED(fh, myname, error_code) \ +if (!ADIO_Feature(fh, ADIO_SHARED_FP)) \ +{ \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_UNSUPPORTED_OPERATION, \ + "**iosharedunsupported", 0); \ + error_code = MPIO_Err_return_file(fh, error_code); \ + goto fn_exit; \ +} + +/* MPIO_ERR_CREATE_CODE_XXX macros are used to clean up creation of + * error codes for common cases in romio/adio/ + */ +#define MPIO_ERR_CREATE_CODE_ERRNO(myname, myerrno, error_code_p) \ +*(error_code_p) = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_IO, \ + "System call I/O error", \ + "Syscall error from %s: %s", \ + myname, \ + strerror(myerrno)); + +#define MPIO_ERR_CREATE_CODE_INFO_NOT_SAME(myname, key, error_code_p) \ +*(error_code_p) = MPIO_Err_create_code(MPI_SUCCESS, \ + MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, \ + MPI_ERR_NOT_SAME, \ + "Value for info key not same across processes", \ + "Value for info key %s not same across processes",\ + key); + + +/* TODO: handle the independent io case more gracefully */ +#define ADIOI_TEST_DEFERRED(fh, myname, error_code)\ + if(! (fh)->is_open ) {\ + ADIO_ImmediateOpen((fh), (error_code)); } + +/* Check MPI_Info object by calling MPI_Info_dup, if the info object is valid +then the dup operation will succeed */ +/* a collective check for error makes this macro collective */ +#define MPIO_CHECK_INFO_ALL(info, error_code, comm) { \ + MPI_Info dupinfo; \ + int tmp_err = MPI_SUCCESS; \ + if (info == MPI_INFO_NULL) { \ + dupinfo = MPI_INFO_NULL; \ + error_code = MPI_SUCCESS; \ + } else { \ + error_code = MPI_Info_dup(info, &dupinfo); \ + } \ + MPI_Allreduce(&error_code, &tmp_err, 1, MPI_INT, MPI_MAX, comm); \ + if(tmp_err != MPI_SUCCESS) { \ + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, \ + myname, __LINE__, MPI_ERR_OTHER, "**info", 0); \ + goto fn_fail; \ + } \ + if (dupinfo != MPI_INFO_NULL) { \ + MPI_Info_free(&dupinfo); \ + } \ +} diff --git a/ompi/mca/io/romio314/romio/adio/include/adioi_fs_proto.h b/ompi/mca/io/romio314/romio/adio/include/adioi_fs_proto.h new file mode 100644 index 0000000000..e3af917082 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/adioi_fs_proto.h @@ -0,0 +1,92 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + + +#ifndef ADIO_PROTO +#define ADIO_PROTO + +#ifdef ROMIO_NFS +extern struct ADIOI_Fns_struct ADIO_NFS_operations; +/* prototypes are in adio/ad_nfs/ad_nfs.h */ +#endif + +#ifdef ROMIO_PANFS +extern struct ADIOI_Fns_struct ADIO_PANFS_operations; +/* prototypes are in adio/ad_panfs/ad_panfs.h */ +#endif + +#ifdef ROMIO_PFS +extern struct ADIOI_Fns_struct ADIO_PFS_operations; +/* prototypes are in adio/ad_pfs/ad_pfs.h */ +#endif + +#ifdef ROMIO_PIOFS +extern struct ADIOI_Fns_struct ADIO_PIOFS_operations; +/* prototypes are in adio/ad_piofs/ad_piofs.h */ +#endif + +#ifdef ROMIO_UFS +extern struct ADIOI_Fns_struct ADIO_UFS_operations; +/* prototypes are in adio/ad_ufs/ad_ufs.h */ +#endif + +#ifdef ROMIO_HFS +extern struct ADIOI_Fns_struct ADIO_HFS_operations; +/* prototypes are in adio/ad_hfs/ad_hfs.h */ +#endif + +#ifdef ROMIO_XFS +extern struct ADIOI_Fns_struct ADIO_XFS_operations; +/* prototypes are in adio/ad_xfs/ad_xfs.h */ +#endif + +#ifdef ROMIO_SFS +extern struct ADIOI_Fns_struct ADIO_SFS_operations; +/* prototypes are in adio/ad_sfs/ad_sfs.h */ +#endif + +#ifdef ROMIO_LUSTRE +extern struct ADIOI_Fns_struct ADIO_LUSTRE_operations; +/* prototypes are in adio/ad_lustre/ad_lustre.h */ +#endif + +#ifdef ROMIO_NTFS +extern struct ADIOI_Fns_struct ADIO_NTFS_operations; +/* prototypes are in adio/ad_ntfs/ad_ntfs.h */ +#endif + +#ifdef ROMIO_PVFS +extern struct ADIOI_Fns_struct ADIO_PVFS_operations; +/* prototypes are in adio/ad_pvfs/ad_pvfs.h */ +#endif + +#ifdef ROMIO_PVFS2 +extern struct ADIOI_Fns_struct ADIO_PVFS2_operations; +/* prototypes are in adio/ad_pvfs2/ad_pvfs2.h */ +#endif + +#ifdef ROMIO_TESTFS +extern struct ADIOI_Fns_struct ADIO_TESTFS_operations; +/* prototypes are in adio/ad_testfs/ad_testfs.h */ +#endif + +#ifdef ROMIO_GPFS +extern struct ADIOI_Fns_struct ADIO_GPFS_operations; +/* prototypes are in adio/ad_gpfs/ad_gpfs.h */ +#endif + +#ifdef ROMIO_GRIDFTP +/* prototypes are in adio/ad_gridftp/ad_gridftp.h */ +extern struct ADIOI_Fns_struct ADIO_GRIDFTP_operations; +#endif + +#ifdef ROMIO_ZOIDFS +/* prototypes are in adio/ad_zoidfs/ad_zoidfs.h */ +extern struct ADIOI_Fns_struct ADIO_ZOIDFS_operations; +#endif + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/include/heap-sort.h b/ompi/mca/io/romio314/romio/adio/include/heap-sort.h new file mode 100644 index 0000000000..903a1e8060 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/heap-sort.h @@ -0,0 +1,22 @@ +#include "adio.h" + +typedef struct { + ADIO_Offset offset; + int proc; + ADIO_Offset reg_max_len; +} heap_node_t; + +typedef struct { + heap_node_t *nodes; + int size; +} heap_t; + +/*static inline int parent(heap_t *heap, int i); +static inline int left(heap_t *heap, int i); +static inline int right(heap_t *heap, int i); */ +void ADIOI_Heap_free(heap_t *heap); +int ADIOI_Heap_create(heap_t *heap, int size); +void ADIOI_Heap_insert(heap_t *heap, ADIO_Offset offset, int proc, + ADIO_Offset reg_max_len); +void ADIOI_Heap_extract_min(heap_t *heap, ADIO_Offset* key, int *proc, + ADIO_Offset *reg_max_len); diff --git a/ompi/mca/io/romio314/romio/adio/include/hint_fns.h b/ompi/mca/io/romio314/romio/adio/include/hint_fns.h new file mode 100644 index 0000000000..7c20177deb --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/hint_fns.h @@ -0,0 +1,23 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2013 UChicago/Argonne LLC + * See COPYRIGHT in top-level directory. + */ + +#ifndef _HINT_FNS_H +#define _HINT_FNS_H + +int ADIOI_Info_check_and_install_int(ADIO_File fd, MPI_Info info, const char *key, + int *local_cache, char *funcname, int *error_code); + +int ADIOI_Info_check_and_install_enabled(ADIO_File fd, MPI_Info info, const char *key, + int *local_cache, char *funcname, int *error_code); + +int ADIOI_Info_check_and_install_true(ADIO_File fd, MPI_Info info, const char *key, + int *local_cache, char *funcname, int *error_code); + +int ADIOI_Info_check_and_install_str(ADIO_File fd, MPI_Info info, const char *key, + char **local_cache, char *funcname, int *error_code); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/include/mpio_error.h b/ompi/mca/io/romio314/romio/adio/include/mpio_error.h new file mode 100644 index 0000000000..f9d22b1721 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/mpio_error.h @@ -0,0 +1,76 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +/* MPI_ERR_FILE */ +#define MPIR_ERR_FILE_NULL 3 +#define MPIR_ERR_FILE_CORRUPT 5 + +/* MPI_ERR_AMODE */ +/* kind values set directly to 3,5,7 in mpi-io/open.c */ + +/* MPI_ERR_ARG */ +#define MPIR_ERR_OFFSET_ARG 65 +#define MPIR_ERR_DATAREP_ARG 67 +#define MPIR_ERR_COUNT_ARG 69 +#define MPIR_ERR_SIZE_ARG 71 +#define MPIR_ERR_WHENCE_ARG 73 +#define MPIR_ERR_FLAG_ARG 75 +#define MPIR_ERR_DISP_ARG 77 +#define MPIR_ERR_ETYPE_ARG 79 +#define MPIR_ERR_FILETYPE_ARG 81 +#define MPIR_ERR_SIZE_ARG_NOT_SAME 83 +#define MPIR_ERR_OFFSET_ARG_NEG 85 +#define MPIR_ERR_WHENCE_ARG_NOT_SAME 87 +#define MPIR_ERR_OFFSET_ARG_NOT_SAME 89 + +/* MPI_ERR_TYPE */ +#ifndef MPIR_ERR_TYPE_NULL +#define MPIR_ERR_TYPE_NULL 5 +#endif + +/* MPI_ERR_UNSUPPORTED_OPERATION */ +#define MPIR_ERR_NO_SHARED_FP 3 +#define MPIR_ERR_AMODE_SEQ 5 +#define MPIR_ERR_MODE_WRONLY 7 +#define MPIR_ERR_NO_MODE_SEQ 9 + +/* MPI_ERR_REQUEST */ +#ifndef MPIR_ERR_REQUEST_NULL +#define MPIR_ERR_REQUEST_NULL 3 +#endif + +/* MPI_ERR_IO */ +#define MPIR_ADIO_ERROR 1 /* used for strerror(errno) */ +#define MPIR_ERR_ETYPE_FRACTIONAL 3 +#define MPIR_ERR_NO_FSTYPE 5 +#define MPIR_ERR_NO_PFS 7 +#define MPIR_ERR_NO_PIOFS 9 +#define MPIR_ERR_NO_UFS 11 +#define MPIR_ERR_NO_NFS 13 +#define MPIR_ERR_NO_HFS 15 +#define MPIR_ERR_NO_XFS 17 +#define MPIR_ERR_NO_SFS 19 +#define MPIR_ERR_NO_PVFS 21 +#define MPIR_ERR_NO_PANFS 22 +#define MPIR_ERR_MULTIPLE_SPLIT_COLL 23 +#define MPIR_ERR_NO_SPLIT_COLL 25 +#define MPIR_ERR_ASYNC_OUTSTANDING 27 +#define MPIR_READ_PERM 29 +#define MPIR_PREALLOC_PERM 31 +#define MPIR_ERR_FILETYPE 33 +#define MPIR_ERR_NO_NTFS 35 +#define MPIR_ERR_NO_TESTFS 36 +#define MPIR_ERR_NO_LUSTRE 37 +#define MPIR_ERR_NO_BGL 38 + +/* MPI_ERR_COMM */ +#ifndef MPIR_ERR_COMM_NULL +#define MPIR_ERR_COMM_NULL 3 +#define MPIR_ERR_COMM_INTER 5 +#endif + +/* MPI_ERR_UNSUPPORTED_DATAREP */ +#define MPIR_ERR_NOT_NATIVE_DATAREP 3 + diff --git a/ompi/mca/io/romio314/romio/adio/include/mpipr.h b/ompi/mca/io/romio314/romio/adio/include/mpipr.h new file mode 100644 index 0000000000..b1dcd9fb44 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/mpipr.h @@ -0,0 +1,385 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +/* This file replaces all MPI function names with their PMPI equivalents. + PMPI versions are used by default so that the user can profile + application code without interference from MPI functions used by + MPI-IO. */ + +#ifndef USE_MPI_VERSIONS + +#undef MPI_Abort +#define MPI_Abort PMPI_Abort +#undef MPI_Address +#define MPI_Address PMPI_Address +#undef MPI_Allgather +#define MPI_Allgather PMPI_Allgather +#undef MPI_Allgatherv +#define MPI_Allgatherv PMPI_Allgatherv +#undef MPI_Allreduce +#define MPI_Allreduce PMPI_Allreduce +#undef MPI_Alltoall +#define MPI_Alltoall PMPI_Alltoall +#undef MPI_Alltoallv +#define MPI_Alltoallv PMPI_Alltoallv +#undef MPI_Alltoallw +#define MPI_Alltoallw PMPI_Alltoallw +#undef MPI_Attr_delete +#define MPI_Attr_delete PMPI_Attr_delete +#undef MPI_Attr_get +#define MPI_Attr_get PMPI_Attr_get +#undef MPI_Attr_put +#define MPI_Attr_put PMPI_Attr_put +#undef MPI_Barrier +#define MPI_Barrier PMPI_Barrier +#undef MPI_Bcast +#define MPI_Bcast PMPI_Bcast +#undef MPI_Bsend +#define MPI_Bsend PMPI_Bsend +#undef MPI_Bsend_init +#define MPI_Bsend_init PMPI_Bsend_init +#undef MPI_Buffer_attach +#define MPI_Buffer_attach PMPI_Buffer_attach +#undef MPI_Buffer_detach +#define MPI_Buffer_detach PMPI_Buffer_detach +#undef MPI_Cancel +#define MPI_Cancel PMPI_Cancel +#undef MPI_Cart_coords +#define MPI_Cart_coords PMPI_Cart_coords +#undef MPI_Cart_create +#define MPI_Cart_create PMPI_Cart_create +#undef MPI_Cart_get +#define MPI_Cart_get PMPI_Cart_get +#undef MPI_Cart_map +#define MPI_Cart_map PMPI_Cart_map +#undef MPI_Cart_rank +#define MPI_Cart_rank PMPI_Cart_rank +#undef MPI_Cart_shift +#define MPI_Cart_shift PMPI_Cart_shift +#undef MPI_Cart_sub +#define MPI_Cart_sub PMPI_Cart_sub +#undef MPI_Cartdim_get +#define MPI_Cartdim_get PMPI_Cartdim_get +#undef MPI_Comm_call_errhandler +#define MPI_Comm_call_errhandler PMPI_Comm_call_errhandler +#undef MPI_Comm_compare +#define MPI_Comm_compare PMPI_Comm_compare +#undef MPI_Comm_create +#define MPI_Comm_create PMPI_Comm_create +#undef MPI_Comm_dup +#define MPI_Comm_dup PMPI_Comm_dup +#undef MPI_Comm_free +#define MPI_Comm_free PMPI_Comm_free +#undef MPI_Comm_group +#define MPI_Comm_group PMPI_Comm_group +#undef MPI_Comm_rank +#define MPI_Comm_rank PMPI_Comm_rank +#undef MPI_Comm_remote_group +#define MPI_Comm_remote_group PMPI_Comm_remote_group +#undef MPI_Comm_remote_size +#define MPI_Comm_remote_size PMPI_Comm_remote_size +#undef MPI_Comm_size +#define MPI_Comm_size PMPI_Comm_size +#undef MPI_Comm_split +#define MPI_Comm_split PMPI_Comm_split +#undef MPI_Comm_test_inter +#define MPI_Comm_test_inter PMPI_Comm_test_inter +#undef MPI_Dims_create +#define MPI_Dims_create PMPI_Dims_create +#undef MPI_Errhandler_create +#define MPI_Errhandler_create PMPI_Errhandler_create +#undef MPI_Errhandler_free +#define MPI_Errhandler_free PMPI_Errhandler_free +#undef MPI_Errhandler_get +#define MPI_Errhandler_get PMPI_Errhandler_get +#undef MPI_Errhandler_set +#define MPI_Errhandler_set PMPI_Errhandler_set +#undef MPI_Error_class +#define MPI_Error_class PMPI_Error_class +#undef MPI_Error_string +#define MPI_Error_string PMPI_Error_string +#undef MPI_Finalize +#define MPI_Finalize PMPI_Finalize +#undef MPI_Gather +#define MPI_Gather PMPI_Gather +#undef MPI_Gatherv +#define MPI_Gatherv PMPI_Gatherv +#undef MPI_Get_count +#define MPI_Get_count PMPI_Get_count +#undef MPI_Get_elements +#define MPI_Get_elements PMPI_Get_elements +#undef MPI_Get_processor_name +#define MPI_Get_processor_name PMPI_Get_processor_name +#undef MPI_Get_version +#define MPI_Get_version PMPI_Get_version +#undef MPI_Graph_create +#define MPI_Graph_create PMPI_Graph_create +#undef MPI_Graph_get +#define MPI_Graph_get PMPI_Graph_get +#undef MPI_Graph_map +#define MPI_Graph_map PMPI_Graph_map +#undef MPI_Graph_neighbors +#define MPI_Graph_neighbors PMPI_Graph_neighbors +#undef MPI_Graph_neighbors_count +#define MPI_Graph_neighbors_count PMPI_Graph_neighbors_count +#undef MPI_Graphdims_get +#define MPI_Graphdims_get PMPI_Graphdims_get +#undef MPI_Group_compare +#define MPI_Group_compare PMPI_Group_compare +#undef MPI_Group_difference +#define MPI_Group_difference PMPI_Group_difference +#undef MPI_Group_excl +#define MPI_Group_excl PMPI_Group_excl +#undef MPI_Group_free +#define MPI_Group_free PMPI_Group_free +#undef MPI_Group_incl +#define MPI_Group_incl PMPI_Group_incl +#undef MPI_Group_intersection +#define MPI_Group_intersection PMPI_Group_intersection +#undef MPI_Group_range_excl +#define MPI_Group_range_excl PMPI_Group_range_excl +#undef MPI_Group_range_incl +#define MPI_Group_range_incl PMPI_Group_range_incl +#undef MPI_Group_rank +#define MPI_Group_rank PMPI_Group_rank +#undef MPI_Group_size +#define MPI_Group_size PMPI_Group_size +#undef MPI_Group_translate_ranks +#define MPI_Group_translate_ranks PMPI_Group_translate_ranks +#undef MPI_Group_union +#define MPI_Group_union PMPI_Group_union +#undef MPI_Ibsend +#define MPI_Ibsend PMPI_Ibsend +#undef MPI_Init +#define MPI_Init PMPI_Init +#undef MPI_Initialized +#define MPI_Initialized PMPI_Initialized +#undef MPI_Intercomm_create +#define MPI_Intercomm_create PMPI_Intercomm_create +#undef MPI_Intercomm_merge +#define MPI_Intercomm_merge PMPI_Intercomm_merge +#undef MPI_Iprobe +#define MPI_Iprobe PMPI_Iprobe +#undef MPI_Irecv +#define MPI_Irecv PMPI_Irecv +#undef MPI_Irsend +#define MPI_Irsend PMPI_Irsend +#undef MPI_Isend +#define MPI_Isend PMPI_Isend +#undef MPI_Issend +#define MPI_Issend PMPI_Issend +#undef MPI_Keyval_create +#define MPI_Keyval_create PMPI_Keyval_create +#undef MPI_Keyval_free +#define MPI_Keyval_free PMPI_Keyval_free +#undef MPI_Name_get +#define MPI_Name_get PMPI_Name_get +#undef MPI_Name_put +#define MPI_Name_put PMPI_Name_put +#undef MPI_Op_create +#define MPI_Op_create PMPI_Op_create +#undef MPI_Op_free +#define MPI_Op_free PMPI_Op_free +#undef MPI_Pack +#define MPI_Pack PMPI_Pack +#undef MPI_Pack_size +#define MPI_Pack_size PMPI_Pack_size +#undef MPI_Pcontrol +#define MPI_Pcontrol PMPI_Pcontrol +#undef MPI_Probe +#define MPI_Probe PMPI_Probe +#undef MPI_Recv +#define MPI_Recv PMPI_Recv +#undef MPI_Recv_init +#define MPI_Recv_init PMPI_Recv_init +#undef MPI_Reduce +#define MPI_Reduce PMPI_Reduce +#undef MPI_Reduce_scatter +#define MPI_Reduce_scatter PMPI_Reduce_scatter +#undef MPI_Request_c2f +#define MPI_Request_c2f PMPI_Request_c2f +#undef MPI_Request_free +#define MPI_Request_free PMPI_Request_free +#undef MPI_Rsend +#define MPI_Rsend PMPI_Rsend +#undef MPI_Rsend_init +#define MPI_Rsend_init PMPI_Rsend_init +#undef MPI_Scan +#define MPI_Scan PMPI_Scan +#undef MPI_Scatter +#define MPI_Scatter PMPI_Scatter +#undef MPI_Scatterv +#define MPI_Scatterv PMPI_Scatterv +#undef MPI_Send +#define MPI_Send PMPI_Send +#undef MPI_Send_init +#define MPI_Send_init PMPI_Send_init +#undef MPI_Sendrecv +#define MPI_Sendrecv PMPI_Sendrecv +#undef MPI_Sendrecv_replace +#define MPI_Sendrecv_replace PMPI_Sendrecv_replace +#undef MPI_Ssend +#define MPI_Ssend PMPI_Ssend +#undef MPI_Ssend_init +#define MPI_Ssend_init PMPI_Ssend_init +#undef MPI_Start +#define MPI_Start PMPI_Start +#undef MPI_Startall +#define MPI_Startall PMPI_Startall +#undef MPI_Test +#define MPI_Test PMPI_Test +#undef MPI_Test_cancelled +#define MPI_Test_cancelled PMPI_Test_cancelled +#undef MPI_Testall +#define MPI_Testall PMPI_Testall +#undef MPI_Testany +#define MPI_Testany PMPI_Testany +#undef MPI_Testsome +#define MPI_Testsome PMPI_Testsome +#undef MPI_Topo_status +#define MPI_Topo_status PMPI_Topo_status +#undef MPI_Topo_test +#define MPI_Topo_test PMPI_Topo_test +#undef MPI_Type_commit +#define MPI_Type_commit PMPI_Type_commit +#undef MPI_Type_contiguous +#define MPI_Type_contiguous PMPI_Type_contiguous +#undef MPI_Type_count +#define MPI_Type_count PMPI_Type_count +/* #define MPI_Type_create_darray PMPI_Type_create_darray */ +#undef MPI_Type_create_indexed_block +#define MPI_Type_create_indexed_block PMPI_Type_create_indexed_block +#undef MPI_Type_create_hindexed_block +#define MPI_Type_create_hindexed_block PMPI_Type_create_hindexed_block +/* #define MPI_Type_create_subarray PMPI_Type_create_subarray */ +#undef MPI_Type_extent +#define MPI_Type_extent PMPI_Type_extent +#undef MPI_Type_free +#define MPI_Type_free PMPI_Type_free +#undef MPI_Type_get_contents +#define MPI_Type_get_contents PMPI_Type_get_contents +#undef MPI_Type_get_envelope +#define MPI_Type_get_envelope PMPI_Type_get_envelope +#undef MPI_Type_get_true_extent +#define MPI_Type_get_true_extent PMPI_Type_get_true_extent +#undef MPI_Type_hindexed +#define MPI_Type_hindexed PMPI_Type_hindexed +#undef MPI_Type_hvector +#define MPI_Type_hvector PMPI_Type_hvector +#undef MPI_Type_indexed +#define MPI_Type_indexed PMPI_Type_indexed +#undef MPI_Type_lb +#define MPI_Type_lb PMPI_Type_lb +#undef MPI_Type_size +#define MPI_Type_size PMPI_Type_size +#undef MPI_Type_struct +#define MPI_Type_struct PMPI_Type_struct +#undef MPI_Type_ub +#define MPI_Type_ub PMPI_Type_ub +#undef MPI_Type_vector +#define MPI_Type_vector PMPI_Type_vector +#undef MPI_Unpack +#define MPI_Unpack PMPI_Unpack +#undef MPI_Wait +#define MPI_Wait PMPI_Wait +#undef MPI_Waitall +#define MPI_Waitall PMPI_Waitall +#undef MPI_Waitany +#define MPI_Waitany PMPI_Waitany +#undef MPI_Waitsome +#define MPI_Waitsome PMPI_Waitsome +#undef MPI_Wtick +#define MPI_Wtick PMPI_Wtick +#undef MPI_Wtime +#define MPI_Wtime PMPI_Wtime + +/* commented out because these could be macros themselves, as in MPICH +#undef MPI_Type_c2f +#define MPI_Type_c2f PMPI_Type_c2f +#undef MPI_Type_f2c +#define MPI_Type_f2c PMPI_Type_f2c +#undef MPI_Comm_c2f +#define MPI_Comm_c2f PMPI_Comm_c2f +#undef MPI_Comm_f2c +#define MPI_Comm_f2c PMPI_Comm_f2c +#undef MPI_Group_c2f +#define MPI_Group_c2f PMPI_Group_c2f +#undef MPI_Group_f2c +#define MPI_Group_f2c PMPI_Group_f2c +#undef MPI_Op_c2f +#define MPI_Op_c2f PMPI_Op_c2f +#undef MPI_Op_f2c +#define MPI_Op_f2c PMPI_Op_f2c +#undef MPI_Request_c2f +#define MPI_Request_c2f PMPI_Request_c2f +#undef MPI_Request_f2c +#define MPI_Request_f2c PMPI_Request_f2c +#undef MPI_Win_c2f +#define MPI_Win_c2f PMPI_Win_c2f +#undef MPI_Win_f2c +#define MPI_Win_f2c PMPI_Win_f2c +*/ +#undef MPI_Status_c2f +#define MPI_Status_c2f PMPI_Status_c2f +#undef MPI_Status_f2c +#define MPI_Status_f2c PMPI_Status_f2c + +#undef MPI_Status_set_elements +#define MPI_Status_set_elements PMPI_Status_set_elements + +#ifndef HAVE_MPI_INFO_SRC /* everywhere except in info source directory */ +#undef MPI_Info_create +#define MPI_Info_create PMPI_Info_create +#undef MPI_Info_set +#define MPI_Info_set PMPI_Info_set +#undef MPI_Info_delete +#define MPI_Info_delete PMPI_Info_delete +#undef MPI_Info_get +#define MPI_Info_get PMPI_Info_get +#undef MPI_Info_get_valuelen +#define MPI_Info_get_valuelen PMPI_Info_get_valuelen +#undef MPI_Info_get_nkeys +#define MPI_Info_get_nkeys PMPI_Info_get_nkeys +#undef MPI_Info_get_nthkey +#define MPI_Info_get_nthkey PMPI_Info_get_nthkey +#undef MPI_Info_dup +#define MPI_Info_dup PMPI_Info_dup +#undef MPI_Info_free +#define MPI_Info_free PMPI_Info_free +/* #undef MPI_Info_c2f +#define MPI_Info_c2f PMPI_Info_c2f +#undef MPI_Info_f2c +#define MPI_Info_f2c PMPI_Info_f2c +*/ +#endif +#undef MPI_Grequest_start +#define MPI_Grequest_start PMPI_Grequest_start +#undef MPI_Grequest_complete +#define MPI_Grequest_complete PMPI_Grequest_complete +#undef MPI_Status_set_cancelled +#define MPI_Status_set_cancelled PMPI_Status_set_cancelled + +#undef MPIX_Grequest_class_create +#define MPIX_Grequest_class_create PMPIX_Grequest_class_create +#undef MPIX_Grequest_class_allocate +#define MPIX_Grequest_class_allocate PMPIX_Grequest_class_allocate + +#ifdef MPIO_FORTRAN_SRC /* only in MPI-IO Fortran source directory */ +#undef MPI_File_c2f +#define MPI_File_c2f PMPI_File_c2f +#undef MPI_File_f2c +#define MPI_File_f2c PMPI_File_f2c +#endif + +#undef MPI_Type_get_attr +#define MPI_Type_get_attr PMPI_Type_get_attr +#undef MPI_Type_set_attr +#define MPI_Type_set_attr PMPI_Type_set_attr +#undef MPI_Comm_set_attr +#define MPI_Comm_set_attr PMPI_Comm_set_attr +#undef MPI_Type_create_keyval +#define MPI_Type_create_keyval PMPI_Type_create_keyval + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/include/mpiu_external32.h b/ompi/mca/io/romio314/romio/adio/include/mpiu_external32.h new file mode 100644 index 0000000000..4302373774 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/mpiu_external32.h @@ -0,0 +1,22 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2012 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ + +#ifndef _MPIU_EXTERNAL32_H_ +#define _MPIU_EXTERNAL32_H_ + +int MPIU_write_external32_conversion_fn (const void *userbuf, MPI_Datatype datatype, + int count, void *filebuf); +int MPIU_read_external32_conversion_fn(void *userbuf, MPI_Datatype datatype, + int count, void *filebuf); +int MPIU_datatype_full_size(MPI_Datatype datatype, MPI_Aint *size); + +/* given a buffer, count, and datatype, return an apropriately sized and + * * external32-formatted buffer, suitable for handing off to a subsequent write + * * routine */ +int MPIU_external32_buffer_setup(const void * buf, int count, MPI_Datatype type, void **newbuf); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/include/mpiu_greq.h b/ompi/mca/io/romio314/romio/adio/include/mpiu_greq.h new file mode 100644 index 0000000000..e3fce1c41d --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/mpiu_greq.h @@ -0,0 +1,15 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ + +#ifndef _MPIU_GREQUEST_H +#define _MPIU_GREQUEST_H + +int MPIU_Greq_query_fn(void *extra_state, MPI_Status *status); +int MPIU_Greq_free_fn(void *extra_state); +int MPIU_Greq_cancel_fn(void *extra_state, int complete); + +#endif diff --git a/ompi/mca/io/romio314/romio/adio/include/nopackage.h b/ompi/mca/io/romio314/romio/adio/include/nopackage.h new file mode 100644 index 0000000000..184e4b4ac8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/adio/include/nopackage.h @@ -0,0 +1,16 @@ +/* + * (C) 2011 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +/* See comments in MPICH's configure.ac for an explanation of what this file is + * and why it exists. */ + +/* intentionally omitting any #ifndef guard, repeated inclusion is intentional */ +#undef PACKAGE +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_URL +#undef PACKAGE_VERSION + diff --git a/ompi/mca/io/romio314/romio/autogen.sh b/ompi/mca/io/romio314/romio/autogen.sh new file mode 100755 index 0000000000..dcc84c738a --- /dev/null +++ b/ompi/mca/io/romio314/romio/autogen.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +${AUTORECONF:-autoreconf} ${autoreconf_args:-"-vif"} -I confdb diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_am.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_am.m4 new file mode 100644 index 0000000000..4d3b0de225 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_am.m4 @@ -0,0 +1,6 @@ +dnl AM_IGNORE is an extension that tells (a patched) automake not to +dnl include the specified AC_SUBST variable in the Makefile.in that +dnl automake generates. We don't use AC_DEFUN, since aclocal will +dnl then complain that AM_IGNORE is a duplicate (if you are using the +dnl patched automake/aclocal). +m4_ifdef([AM_IGNORE],[],[m4_define([AM_IGNORE],[])]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_atomic.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_atomic.m4 new file mode 100644 index 0000000000..4e96cfbf36 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_atomic.m4 @@ -0,0 +1,227 @@ +dnl /*D PAC_C_MEMATOMIC - Try and determine how to implement memory-atomic +dnl operations with the selected C compiler +dnl +dnl Synopsis: +dnl PAC_C_MEMATOMIC +dnl +dnl Notes: +dnl Defines names of the following form +dnl + HAVE_GCC_ASM_AND_X86_{MFENCE,LFENCE,SFENCE} - gcc __asm__ will issue +dnl mfence, lfence, or sfence +dnl . HAVE___ASM_AND_X86_{MFENCE,LFENCE,SFENCE} - __asm _emit will issue +dnl mfence, lfence, or sfence +dnl . HAVE_ASM_AND_X86_{MFENCE,LFENCE,SFENCE} - asm("...") will issue +dnl mfence, lfence, or sfence +dnl . HAVE__INTERLOCKEDEXCHANGE - _InterlockedExchange intrinsic is available +dnl (IA64) +dnl . HAVE_GCC_ASM_SPARC_MEMBAR - gcc __asm__ will issue SPARC architecture +dnl memory barrier instruction +dnl . HAVE_SOLARIS_ASM_SPARC_MEMBAR - Solaris asm() will issue SPARC +dnl architecture memory barrier instruction +dnl . HAVE_GCC_ASM_SPARC_STBAR - gcc __asm__ will issue stbar +dnl - HAVE_SOLARIS_ASM_SPARC_STBAR - Solaris __asm() will issue stbar +dnl +dnl D*/ +AC_DEFUN([PAC_C_MEMATOMIC],[ +AC_CACHE_CHECK([for x86 mfence instruction using __asm__], + pac_cv_have_gcc_asm_and_x86_mfence,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + __asm__ __volatile__ ( ".byte 0x0f, 0xae, 0xf0" ::: "memory" ); + exit(0); +} +], +pac_cv_have_gcc_asm_and_x86_mfence=yes,pac_cv_have_gcc_asm_and_x86_mfence=no)]) + +if test "$pac_cv_have_gcc_asm_and_x86_mfence" = "yes" ; then + AC_DEFINE(HAVE_GCC_ASM_AND_X86_MFENCE, 1, [Define if using gcc on a x86 system with the mfence instruction]) +fi + +AC_CACHE_CHECK([for x86 sfence instruction using __asm__], + pac_cv_have_gcc_asm_and_x86_sfence,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + __asm__ __volatile__ ( ".byte 0x0f, 0xae, 0xf8" ::: "memory" ); + exit(0); +} +], +pac_cv_have_gcc_asm_and_x86_sfence=yes,pac_cv_have_gcc_asm_and_x86_sfence=no)]) + +if test "$pac_cv_have_gcc_asm_and_x86_sfence" = "yes" ; then + AC_DEFINE(HAVE_GCC_ASM_AND_X86_SFENCE, 1, [Define if using gcc on a x86 system with the sfence instruction]) +fi + +AC_CACHE_CHECK([for x86 lfence instruction using __asm__], + pac_cv_have_gcc_asm_and_x86_lfence,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + __asm__ __volatile__ ( ".byte 0x0f, 0xae, 0xe8" ::: "memory" ); + exit(0); +} +], +pac_cv_have_gcc_asm_and_x86_lfence=yes,pac_cv_have_gcc_asm_and_x86_lfence=no)]) + +if test "$pac_cv_have_gcc_asm_and_x86_lfence" = "yes" ; then + AC_DEFINE(HAVE_GCC_ASM_AND_X86_LFENCE, 1, [Define if using gcc on a x86 system with the lfence instruction]) +fi + +dnl Some compilers, like icc, may want __asm _emit +AC_CACHE_CHECK([for x86 mfence instruction using __asm], + pac_cv_have___asm_and_x86_mfence,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + __asm _emit 0x0f __asm _emit 0xae __asm _emit 0xf0 ; + exit(0); +} +], +pac_cv_have___asm_and_x86_mfence=yes,pac_cv_have___asm_and_x86_mfence=no)]) + +if test "$pac_cv_have___asm_and_x86_mfence" = "yes" ; then + AC_DEFINE(HAVE___ASM_AND_X86_MFENCE, 1, [Define if using __asm on a x86 system with the mfence instruction]) +fi + +AC_CACHE_CHECK([for x86 sfence instruction using __asm], + pac_cv_have___asm_and_x86_sfence,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + __asm sfence ; + exit(0); +} +], +pac_cv_have___asm_and_x86_sfence=yes,pac_cv_have___asm_and_x86_sfence=no)]) + +if test "$pac_cv_have___asm_and_x86_sfence" = "yes" ; then + AC_DEFINE(HAVE___ASM_AND_X86_SFENCE, 1, [Define if using __asm on a x86 system with the sfence instruction]) +fi + +AC_CACHE_CHECK([for x86 lfence instruction using __asm], + pac_cv_have___asm_and_x86_lfence,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + __asm _emit 0x0f __asm _emit 0xae __asm _emit 0xe8 ; + exit(0); +} +], +pac_cv_have___asm_and_x86_lfence=yes,pac_cv_have___asm_and_x86_lfence=no)]) + +if test "$lac_cv_have___asm_and_x86_lfence" = "yes" ; then + AC_DEFINE(HAVE___ASM_AND_X86_LFENCE, 1, [Define if using __asm on a x86 system with the lfence instruction]) +fi + +dnl +dnl Some compilers, such as pgcc, may require additional arguments. +dnl pgcc may need -Masmkeyword flag. We may want to try this with and +dnl without adding -Masmkeyword to CFLAGS + +AC_CACHE_CHECK([for x86 mfence instruction using asm()], + pac_cv_have_asm_and_x86_mfence,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + asm("_emit 0x0f __asm _emit 0xae __asm _emit 0xf0"); + exit(0); +} +], +pac_cv_have_asm_and_x86_mfence=yes,pac_cv_have_asm_and_x86_mfence=no)]) + +if test "$pac_cv_have_asm_and_x86_mfence" = "yes" ; then + AC_DEFINE(HAVE_ASM_AND_X86_MFENCE, 1, [Define if using asm() on a x86 system with the mfence instruction]) +fi + +AC_CACHE_CHECK([for x86 sfence instruction using asm()], + pac_cv_have_asm_and_x86_sfence,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + asm("sfence"); + exit(0); +} +], +pac_cv_have_asm_and_x86_sfence=yes,pac_cv_have_asm_and_x86_sfence=no)]) + +if test "$pac_cv_have_asm_and_x86_sfence" = "yes" ; then + AC_DEFINE(HAVE_ASM_AND_X86_SFENCE, 1, [Define if using asm() on a x86 system with the sfence instruction]) +fi + +AC_CACHE_CHECK([for x86 lfence instruction using asm()], + pac_cv_have_asm_and_x86_lfence,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + asm("_emit 0x0f __asm _emit 0xae __asm _emit 0xe8"); + exit(0); +} +], +pac_cv_have_asm_and_x86_lfence=yes,pac_cv_have_asm_and_x86_lfence=no)]) + +if test "$pac_cv_have_asm_and_x86_lfence" = "yes" ; then + AC_DEFINE(HAVE_ASM_AND_X86_LFENCE, 1, [Define if using asm() on a x86 system with the lfence instruction]) +fi + +AC_CACHE_CHECK([for _InterlockedExchange intrinsic], + pac_cv_have__InterlockedExchange,[ +AC_TRY_RUN([ +int main(int argc, char **argv) +{ + unsigned long lock, *lock_ptr; + lock_ptr = &lock; + _InterlockedExchange(lock_ptr, 1); + exit(0); +} +], +pac_cv_have__InterlockedExchange=yes,pac_cv_have__InterlockedExchange=no)]) + +if test "$pac_cv_have__InterlockedExchange" = "yes" ; then + AC_DEFINE(HAVE__INTERLOCKEDEXCHANGE, 1, [Define if _InterlockedExchange intrinsic is available]) +fi + +AC_CACHE_CHECK([for SPARC membar instruction with gcc], + pac_cv_gcc_sparc_membar,[ +AC_TRY_RUN([ +int main(int argc, char **argv){ + __asm__ __volatile__ ( "membar #StoreLoad | #StoreStore" : : : "memory" ); + exit(0); +}],pac_cv_gcc_sparc_membar=yes,pac_cv_gcc_sparc_membar=no)]) +if test "$pac_cv_gcc_sparc_membar" = yes ; then + AC_DEFINE(HAVE_GCC_ASM_SPARC_MEMBAR,1,[Define if gcc asm membar supported]) +fi + +AC_CACHE_CHECK([for SPARC membar instruction with Solaris C], + pac_cv_solaris_sparc_membar,[ +AC_TRY_RUN([ +int main(int argc, char **argv){ + __asm ( "membar #StoreLoad | #StoreStore"); + exit(0); +}],pac_cv_solaris_sparc_membar=yes,pac_cv_solaris_sparc_membar=no)]) +if test "$pac_cv_solaris_sparc_membar" = yes ; then + AC_DEFINE(HAVE_SOLARIS_ASM_SPARC_MEMBAR,1,[Define if solaris asm membar supported]) +fi + +AC_CACHE_CHECK([for SPARC stbar instruction with gcc], + pac_cv_gcc_sparc_stbar,[ +AC_TRY_RUN([ +int main(int argc, char **argv){ + __asm__ __volatile__ ( "stbar" : : : "memory" ); + exit(0); +}],pac_cv_gcc_sparc_stbar=yes,pac_cv_gcc_sparc_stbar=no)]) +if test "$pac_cv_gcc_sparc_stbar" = yes ; then + AC_DEFINE(HAVE_GCC_ASM_SPARC_STBAR,1,[Define if gcc asm stbar supported]) +fi + +AC_CACHE_CHECK([for SPARC stbar instruction with Solaris C], + pac_cv_solaris_sparc_stbar,[ +AC_TRY_RUN([ +int main(int argc, char **argv){ + __asm ( "stbar" ); + exit(0); +}],pac_cv_solaris_sparc_stbar=yes,pac_cv_solaris_sparc_stbar=no)]) +if test "$pac_cv_solaris_sparc_stbar" = yes ; then + AC_DEFINE(HAVE_SOLARIS_ASM_SPARC_STBAR,1,[Define if solaris asm stbar supported]) +fi +]) \ No newline at end of file diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_attr_alias.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_attr_alias.m4 new file mode 100644 index 0000000000..32f016546d --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_attr_alias.m4 @@ -0,0 +1,504 @@ +dnl +dnl Check for BSD or POSIZ style global symbol lister, nm. +dnl If found, pac_path_NM_G contains the absolute athname of nm + options +dnl pac_path_NM_G_type will be either POSIX or BSD. NM_G will be +dnl pac_path_NM_G without the absolute path. Preference is BSD style. +dnl +dnl The test checks if nm accepts the known options and also if nm produces +dnl the expected BSD or POSIX output format. +dnl +AC_DEFUN([PAC_PATH_NM_G],[ +AC_MSG_CHECKING([for BSD/POSIX style global symbol lister]) +AC_LANG_PUSH(C) +AC_PATH_PROGS_FEATURE_CHECK(NM_G, nm, [ + # Check if nm accepts -g and BSD or POSIX compatible flag. + # Use the `sed 1q' to avoid HP-UX's unknown option message: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # + # AIX's sed does not accept \+, 1) instead of doing 's|a\+||', do 's|aa*||' + # or 2) instead of 's|A \+B|AB|g', do 's|A *B|AB|g' + + # Check if nm accepts -g + case `${ac_path_NM_G} -g /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + ac_path_NM_G="${ac_path_NM_G} -g" + # Check if nm accepts -B + case `${ac_path_NM_G} -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([int iglobal;]) + ],[ + changequote(,) + case `${ac_path_NM_G} -B conftest.$OBJEXT | sed -e 's|[0-9][0-9]* *[A-Z] *iglobal|XXXX|g'` in + *XXXX*) + pac_path_NM_G="${ac_path_NM_G} -B" + pac_path_NM_G_type="BSD" + ;; + esac + changequote([,]) + ]) + ;; + *) + # Check if nm accepts -P + case `${ac_path_NM_G} -P /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([int iglobal;]) + ],[ + changequote(,) + case `${ac_path_NM_G} -P conftest.$OBJEXT | sed -e 's|iglobal *[A-Z] *[0-9][0-9]*|XXXX|g'` in + *XXXX*) + pac_path_NM_G="${ac_path_NM_G} -P" + pac_path_NM_G_type="POSIX" + ;; + esac + changequote([,]) + ]) + ;; + esac # Endof case `${ac_path_NM_G} -P + ;; + esac # Endof case `${ac_path_NM_G} -B + ;; + esac # Endof case `${ac_path_NM_G} -g + if test "X$pac_path_NM_G" != "X" ; then + AC_MSG_RESULT([$pac_path_NM_G_type style,$pac_path_NM_G]) + NM_G="`echo $pac_path_NM_G | sed -e 's|^.*nm |nm |g'`" + else + AC_MSG_RESULT(no) + fi + ac_cv_path_NM_G=${ac_path_NM_G} + ac_path_NM_G_found=: +], [AC_MSG_RESULT(no)], +[$PATH$PATH_SEPARATOR/usr/ccs/bin/elf$PATH_SEPARATOR/usr/ccs/bin$PATH_SEPARATOR/usr/ucb$PATH_SEPARATOR/bin]) +AC_LANG_POP(C) +]) dnl Endof AC_DEFUN([PAC_PATH_NM_G] +dnl +dnl PAC_C_MULTI_ATTR_ALIAS() +dnl +dnl The checks if multiple __attribute__((alias)) is available +dnl If the multiple __attribute((alias)) support is found, +dnl pac_c_multi_attr_alias=yes is set. +dnl +dnl The default is to do a runtime test. When cross_compiling=yes, +dnl pac_path_NM_G will be used to determine the test result. +dnl If CFLAGS(or CPPFLAGS) contains ATTR_ALIAS_DEBUG, the runtime will print +dnl out addresses of struct(s) for debugging purpose. +dnl +dnl +AC_DEFUN([PAC_C_MULTI_ATTR_ALIAS],[ +AC_REQUIRE([PAC_PATH_NM_G]) +AC_LANG_PUSH(C) +AC_CHECK_HEADERS([stdio.h]) +AC_MSG_CHECKING([for multiple __attribute__((alias)) support]) + +#Compile the "other" __attribute__ object file. +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif + +struct mpif_cmblk_t_ { int imember; }; +typedef struct mpif_cmblk_t_ mpif_cmblk_t; + +/* NOT initialize these structure so it appears in BSS or as COMMON symbols */ +mpif_cmblk_t mpifcmb; +mpif_cmblk_t MPIFCMB; + +/* + Do the test in this file instead in the file + where __attribute__((alias)) is used. + This is needed for pgcc since pgcc seems to + define aliased symbols if they are in the same file. +*/ +/* + We can't do the following comparision in one test: + + ilogical = (( &mpifcmb == ptr && &MPIFCMB == ptr ) ? TRUE : FALSE) ; + + because some compiler, like gcc 4.4.2's -O* optimizes the code + such that the ilogical expression is FALSE. The likely reason is that + mpifcmb and MPIFCMB are defined in the same scope in which C optimizer + may have treated them as different objects (with different addresses), + &mpifcmb != &MPIFCMB, before actually running the test and hence the + illogical expression is assumed to be always FALSE. The solution taken + here is to prevent the optimizer the opportunity to equate &mpifcmb and + &MPIFCMB (in same scope), e.g. using 2 separate tests and combine the + test results in a different scope. +*/ +int same_addrs1( void *ptr ); +int same_addrs1( void *ptr ) +{ +#if defined(ATTR_ALIAS_DEBUG) + printf( "others: addr(mpifcmb)=%p, addr(input ptr)=%p\n", &mpifcmb, ptr ); +#endif + return ( &mpifcmb == ptr ? 1 : 0 ); +} + +int same_addrs2( void *ptr ); +int same_addrs2( void *ptr ) +{ +#if defined(ATTR_ALIAS_DEBUG) + printf( "others: addr(MPIFCMB)=%p, addr(input ptr)=%p\n", &MPIFCMB, ptr ); +#endif + return ( &MPIFCMB == ptr ? 1 : 0 ); +} + + ]) +],[ + rm -f pac_conftest_other.$OBJEXT + PAC_RUNLOG([cp conftest.$OBJEXT pac_conftest_other.$OBJEXT]) + test -s pac_conftest_other.$OBJEXT && pac_c_attr_alias_other=yes +dnl cp conftest.$ac_ext pac_conftest_other.$ac_ext +dnl echo +dnl echo "pac_conftest_other.$OBJEXT" +dnl nm -P -g pac_conftest_other.$OBJEXT | grep -i "mpifcmb" +],[ + pac_c_attr_alias_other=no +]) dnl Endof AC_COMPILE_IFELSE + +pac_c_attr_alias_main=no +if test "$pac_c_attr_alias_other" = "yes" ; then + +# Push LIBS for later restoration. + PAC_PUSH_FLAG([LIBS]) + LIBS="pac_conftest_other.$OBJEXT $LIBS" + +# Link the "other" __attribute__ object file. + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif + +struct mpif_cmblk_t_ { int imember; }; +typedef struct mpif_cmblk_t_ mpif_cmblk_t; + +mpif_cmblk_t mpifcmbr = {0}; +extern mpif_cmblk_t MPIFCMB __attribute__ ((alias("mpifcmbr"))); +extern mpif_cmblk_t mpifcmb __attribute__ ((alias("mpifcmbr"))); + +extern int same_addrs1( void *ptr ); +extern int same_addrs2( void *ptr ); + + ],[ + int iaddr = 0; +#if defined(ATTR_ALIAS_DEBUG) + printf( "main: addr(mpifcmbr) = %p\n", &mpifcmbr ); + printf( "main: addr(mpifcmb) = %p\n", &mpifcmb ); + printf( "main: addr(MPIFCMB) = %p\n", &MPIFCMB ); +#endif + iaddr = same_addrs1( &mpifcmbr ) && same_addrs2( &mpifcmbr ); + FILE *file = fopen( "pac_conftestval", "w" ); + if (!file) return 1; + fprintf( file, "%d\n", iaddr ); + ]) + ],[ + rm -f pac_conftest_main$EXEEXT + PAC_RUNLOG([cp conftest$EXEEXT pac_conftest_main$EXEEXT]) + test -x pac_conftest_main$EXEEXT && pac_c_attr_alias_main=yes +dnl cp conftest.$ac_ext pac_conftest_main.$ac_ext +dnl echo +dnl echo "pac_conftest_main$EXEEXT" +dnl nm -P -g pac_conftest_main$EXEEXT | grep -i "mpifcmb" + ],[ + pac_c_attr_alias_main=no +dnl cp conftest.$ac_ext pac_conftest_main.$ac_ext + ]) dnl Endof AC_LINK_IFELSE + +# Restore the previously pushed LIBS + PAC_POP_FLAG([LIBS]) + rm -f pac_conftest_other.$OBJEXT +fi dnl Endof if test "$pac_c_attr_alias_other" = "yes" + +if test "$pac_c_attr_alias_main" = "yes" ; then + if test "$cross_compiling" = "yes" ; then + changequote(,) + # echo "PAC CROSS-COMPILING" dnl + # POSIX NM = nm -P format dnl + if test "$pac_path_NM_G_type" = "POSIX" ; then + addrs=`${pac_path_NM_G} ./pac_conftest_main$EXEEXT | grep -i mpifcmb | sed -e 's% *[a-zA-Z][a-zA-Z]* *[a-zA-Z] *\([0-9abcdef][0-9abcdef]*\).*%\1%g'` + fi + + # BSD NM = nm -B format dnl + if test "$pac_path_NM_G_type" = "BSD" ; then + addrs=`${pac_path_NM_G} -g ./pac_conftest_main$EXEEXT | grep -i mpifcmb | sed -e "s% *\([0-9abcdef][0-9abcdef]*\) *[a-zA-Z] *[a-zA-Z][a-zA-A]*.*%\1%g"` + fi + changequote([,]) + + cmp_addr="" + diff_addrs=no + for addr in ${addrs} ; do + if test "X${cmp_addr}" != "X" ; then + if test "${cmp_addr}" != "${addr}" ; then + diff_addrs=yes + break + fi + else + cmp_addr=${addr} + fi + done + + if test "$diff_addrs" != "yes" ; then + dnl echo "Same addresses. Multiple aliases support" + AC_MSG_RESULT([${NM_G} says yes]) + pac_c_multi_attr_alias=yes + else + dnl echo "Different addresses. No multiple aliases support." + AC_MSG_RESULT([${NM_G} says no]) + pac_c_multi_attr_alias=no + fi + + else # if test "$cross_compiling" != "yes" + rm -f pac_conftestval + ac_try="./pac_conftest_main$EXEEXT" + if AC_TRY_EVAL(ac_try) ; then + pac_c_attr_alias_val=0 + if test -s pac_conftestval ; then + eval pac_c_attr_alias_val=`cat pac_conftestval` + fi + if test "$pac_c_attr_alias_val" -eq 1 ; then + AC_MSG_RESULT(yes) + pac_c_multi_attr_alias=yes + else + AC_MSG_RESULT(no) + pac_c_multi_attr_alias=no + fi + rm -f pac_conftestval + fi + fi + dnl Endof if test "$cross_compiling" = "yes" + rm -f pac_conftest_main$EXEEXT +else + AC_MSG_RESULT(no! link failure) + pac_c_multi_attr_alias=no +fi dnl Endof if test "$pac_c_attr_alias_main" = "yes" + +AC_LANG_POP(C) + +]) dnl Endof AC_DEFUN([PAC_C_MULTI_ATTR_ALIAS] +dnl +dnl PAC_C_ATTR_ALIGNED() +dnl +dnl Check if __attribute__((aligned)) support is there. +dnl If so, set pac_c_attr_aligned=yes. +dnl +dnl Do a link test instead of compile test to check if the linker +dnl would emit an error. +dnl +AC_DEFUN([PAC_C_ATTR_ALIGNED],[ +AC_LANG_PUSH(C) +AC_MSG_CHECKING([for __attribute__((aligned)) support]) +#Link the __attribute__ object file. +AC_LINK_IFELSE([ + AC_LANG_PROGRAM([ +struct mpif_cmblk_t_ { int imembers[5]; }; +typedef struct mpif_cmblk_t_ mpif_cmblk_t; +mpif_cmblk_t mpifcmbr __attribute__((aligned)) = {0}; + ],[]) +],[pac_c_attr_aligned=yes], [pac_c_attr_aligned=no]) +AC_MSG_RESULT([$pac_c_attr_aligned]) +AC_LANG_POP(C) +]) +dnl +dnl PAC_F2C_ATTR_ALIGNED_SIZE(ARRAY_SIZE, [OUTPUT_VAR], [MIN_ALIGNMENT]) +dnl +dnl ARRAY_SIZE : Size of the integer array within the fortran commmon block. +dnl OUTPUT_VAR : Optional variable to be set. +dnl if test succeeds, set OUTPUT_VAR=$pac_f2c_attr_aligned_str. +dnl if test fails, set OUTPUT_VAR="unknown". +dnl MIN_ALIGNMENT : Optional value. +dnl Minimum alignment size to be used in OUTPUT_VAR. +dnl pac_f2c_attr_aligned_str won't be modified. +dnl +dnl "pac_f2c_attr_aligned_str" will be set with +dnl 1) __attribute__((aligned(ALIGNMENT_SIZE))), +dnl 2) __attribute__((aligned)). +dnl 3) "", i.e. empty string. +dnl +dnl 2) means the test can't find a good alignment value, but both the Fortran +dnl and C compilers are OK with "aligned" which in principle means the C +dnl compiler will pick the maximum useful alignment supported by the +dnl architecture. +dnl 3) means that the test has failed to find the alignment. +dnl +AC_DEFUN([PAC_F2C_ATTR_ALIGNED_SIZE],[ +cmblksize=$1 +AC_MSG_CHECKING([the minimum alignment of Fortran common block of $cmblksize integers]) +dnl To find the minmium alignment of Fortran common block (of integer array) +dnl as seen by C object file, C object files of various (typical) alignments +dnl are linked to the Fortran code using the common block of integer array. +# +dnl Since the incorrect alignment results only a warning messages from the +dnl fortran compiler(or linker), so we use "diff" to compare the fortran +dnl compiler/linker output. We cannot use AC_LANG_WERROR, +dnl i.e. ac_fc_werror_flag=yes, because compiler like pgf77 at version 10.x) +dnl has non-zero stderr output if a fortran program is used in the linking. +dnl The stderr contains the name of fortran program even if the linking is +dnl successful. We could avoid the non-zero stderr output in pgf77 by +dnl compiling everthing into object files and linking all the object files +dnl with pgf77. Doing that would need us to use AC_TRY_EVAL instead of +dnl AC_LINK_IFELSE, so "diff" approach is used instead. +# +dnl Using diff of compiler(linker) output requires a reference output file +dnl as the base of diff. The process of creating this reference output file +dnl has to be exactly the same as the testing process, because pgf77 has +dnl the following weird behavour +dnl pgf77 -o ftest ftest.f => when $?=0 with zero stderr output +dnl pgf77 -o ftest ftest.f dummy.o => when $?=0 with non-zero stderr output. +dnl stderr has "ftest.f:". +dnl +# First create a fortran CONFTEST which will be used repeatedly. +AC_LANG_PUSH([Fortran]) dnl AC_LANG_PUSH([Fortran 77]) +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + program fconftest + integer isize + parameter (isize=$cmblksize) + integer status_array(isize) + common /mpifcmb/ status_array + save /mpifcmb/ + end + ]) +]) +AC_LANG_POP([Fortran]) dnl AC_LANG_POP([Fortran 77]) +dnl +dnl +dnl +# Compile a C dummy.$OBJEXT and link with Fortran test program to create +# a reference linker output file, pac_align0.log, as the base of "diff". +AC_LANG_PUSH([C]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],[ + cp conftest.$ac_ext pac_conftest.c + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + PAC_PUSH_FLAG([LIBS]) + LIBS="pac_conftest.$OBJEXT $LIBS" + AC_LANG_PUSH([Fortran]) dnl AC_LANG_PUSH([Fortran 77]) + PAC_PUSH_FLAG([ac_link]) + ac_link="`echo $ac_link | sed -e 's|>.*$|> $pac_logfile 2>\&1|g'`" + pac_logfile="pac_align0.log" + rm -f $pac_logfile + AC_LINK_IFELSE([],[ + pac_f2c_alignedn_diffbase=yes + ],[ + pac_f2c_alignedn_diffbase=no + ]) + # Be sure NOT to remove the conftest.f which is still needed for later use. + # rm -f conftest.$ac_ext + # Restore everything in autoconf that has been overwritten + PAC_POP_FLAG([ac_link]) + # restore previously pushed LIBS + PAC_POP_FLAG([LIBS]) + AC_LANG_POP([Fortran]) dnl AC_LANG_POP([Fortran 77]) +],[ + pac_f2c_alignedn_diffbase=no +]) +AC_LANG_POP([C]) +dnl +dnl +if test "$pac_f2c_alignedn_diffbase" = "yes" ; then + # Initialize pac_result_str to empty string since part of the test + # depends on pac_result_str is empty or non-empty string. + pac_result_str="" + # Initialize pac_f2c_attr_aligned_str to empty string and + # it will remain as empty string if the following test fails. + pac_f2c_attr_aligned_str="" + for asize in 4 8 16 32 64 128 max ; do + if test "$asize" != "max" ; then + pac_attr_aligned_str="__attribute__((aligned($asize)))" + else + pac_attr_aligned_str="__attribute__((aligned))" + fi + AC_LANG_PUSH([C]) + #Compile the __attribute__ object file. + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ +changequote(,) +struct mpif_cmblk_t_ { $MPI_FINT imembers[$cmblksize]; }; +changequote([,]) +typedef struct mpif_cmblk_t_ mpif_cmblk_t; +mpif_cmblk_t mpifcmbr $pac_attr_aligned_str = {0}; + +extern mpif_cmblk_t _CMPIFCMB __attribute__ ((alias("mpifcmbr"))); +extern mpif_cmblk_t MPIFCMB __attribute__ ((alias("mpifcmbr"))); +extern mpif_cmblk_t MPIFCMB_ __attribute__ ((alias("mpifcmbr"))); +extern mpif_cmblk_t _Cmpifcmb __attribute__ ((alias("mpifcmbr"))); +extern mpif_cmblk_t mpifcmb __attribute__ ((alias("mpifcmbr"))); +extern mpif_cmblk_t mpifcmb_ __attribute__ ((alias("mpifcmbr"))); + ]) + ],[ + cp conftest.$ac_ext pac_conftest.c + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + PAC_PUSH_FLAG([LIBS]) + LIBS="pac_conftest.$OBJEXT $LIBS" + AC_LANG_PUSH([Fortran]) dnl AC_LANG_PUSH([Fortran 77]) + PAC_PUSH_FLAG([ac_link]) + ac_link="`echo $ac_link | sed -e 's|>.*$|> $pac_logfile 2>\&1|g'`" + pac_logfile="pac_align1.log" + rm -f $pac_logfile + # Use conftest.f created in CONFTEST. + AC_LINK_IFELSE([],[ + PAC_RUNLOG_IFELSE([diff -b pac_align0.log pac_align1.log],[ + pac_attr_alignedn=yes + ],[ + pac_attr_alignedn=no + cat $pac_logfile >&AS_MESSAGE_LOG_FD + echo "failed C program was:" >&AS_MESSAGE_LOG_FD + cat pac_conftest.c >&AS_MESSAGE_LOG_FD + echo "failed Fortran program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&AS_MESSAGE_LOG_FD + ]) + ],[ + pac_attr_alignedn=no + ]) + # Restore everything in autoconf that has been overwritten + PAC_POP_FLAG([ac_link]) + # restore previously pushed LIBS + PAC_POP_FLAG([LIBS]) + AC_LANG_POP([Fortran]) dnl AC_LANG_POP([Fortran 77]) + # remove previously generated object file and C file. + rm -f pac_conftest.$OBJEXT pac_conftest.c + rm -f $pac_logfile + if test "$pac_attr_alignedn" = yes ; then + ifelse([$3],[],[ + pac_result_str="$asize" + pac_f2c_attr_aligned_str="$pac_attr_aligned_str" + break + ],[ + if test "$asize" != "max" -a "$asize" -lt "$3" ; then + if test "X$pac_result_str" = "X" ; then + pac_result_str="$asize" + pac_f2c_attr_aligned_str="$pac_attr_aligned_str" + fi + continue + else + pac_f2c_attr_aligned_str="$pac_attr_aligned_str" + if test "X$pac_result_str" != "X" ; then + pac_result_str="$pac_result_str, too small! reset to $asize" + else + pac_result_str="$asize" + fi + break + fi + ]) + fi + ], [ + pac_attr_alignedn=no + ]) + AC_LANG_POP([C]) + done + ifelse([$2],[],[],[$2="$pac_f2c_attr_aligned_str"]) +else + pac_result_str="" + # Since the test fails, set pac_f2c_attr_aligned_str to empty string. + pac_f2c_attr_aligned_str="" +fi +if test "X$pac_result_str" != "X" ; then + AC_MSG_RESULT([$pac_result_str]) +else + AC_MSG_RESULT([unknown]) +fi +rm -f pac_align0.log +]) +dnl diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_bugfix.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_bugfix.m4 new file mode 100644 index 0000000000..f580d3919a --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_bugfix.m4 @@ -0,0 +1,75 @@ +dnl This internal macro fails to work properly with OTHER internal macros. +dnl Basically, if the prologue is [], then no message should be generated. +dnl This macro is in autoconf 2.52 +m4_define([AC_LANG_PROGRAM(Fortran 77)], +[m4_if([$1],[[[]]],,[m4_ifval([$1], + [m4_warn([syntax], [$0: ignoring PROLOGUE: $1])])])dnl + program main +$2 + end]) + + +dnl/*D +dnl PAC_PROG_CHECK_INSTALL_WORKS - Check whether the install program in INSTALL +dnl works. +dnl +dnl Synopsis: +dnl PAC_PROG_CHECK_INSTALL_WORKS +dnl +dnl Output Effect: +dnl Sets the variable 'INSTALL' to the value of 'ac_sh_install' if +dnl a file cannot be installed into a local directory with the 'INSTALL' +dnl program +dnl +dnl Notes: +dnl The 'AC_PROG_INSTALL' scripts tries to avoid broken versions of +dnl install by avoiding directories such as '/usr/sbin' where some +dnl systems are known to have bad versions of 'install'. Unfortunately, +dnl this is exactly the sort of test-on-name instead of test-on-capability +dnl that 'autoconf' is meant to eliminate. The test in this script +dnl is very simple but has been adequate for working around problems +dnl on Solaris, where the '/usr/sbin/install' program (known by +dnl autoconf to be bad because it is in /usr/sbin) is also reached by a +dnl soft link through /bin, which autoconf believes is good. +dnl +dnl No variables are cached to ensure that we do not make a mistake in +dnl our choice of install program. +dnl +dnl The Solaris configure requires the directory name to immediately +dnl follow the '-c' argument, rather than the more common +dnl.vb +dnl args sourcefiles destination-dir +dnl.ve +dnl D*/ +AC_DEFUN([PAC_PROG_CHECK_INSTALL_WORKS],[ +if test -z "$INSTALL" ; then + AC_MSG_RESULT([No install program available]) +else + # first make any "confdb/install-sh -c" into an absolute path + # this is a hack, but it's still much cleaner than anything else I could + # come up with (see tt#1007) [goodell@] + AS_CASE(["$INSTALL"], + [/*],[:], + [*install-sh*],[INSTALL="$master_top_srcdir/$INSTALL"]) + + # Check that this install really works + rm -f conftest + echo "Test file" > conftest + if test ! -d .conftest ; then mkdir .conftest ; fi + AC_MSG_CHECKING([whether install works]) + if $INSTALL conftest .conftest >/dev/null 2>&1 ; then + installOk=yes + else + installOk=no + fi + rm -rf .conftest conftest + AC_MSG_RESULT($installOk) + if test "$installOk" = no ; then + if test -n "$ac_install_sh" ; then + INSTALL=$ac_install_sh + else + AC_MSG_ERROR([Unable to find working install]) + fi + fi +fi +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_cache.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_cache.m4 new file mode 100644 index 0000000000..9d02c41638 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_cache.m4 @@ -0,0 +1,372 @@ +dnl +dnl/*D +dnl AC_CACHE_LOAD - Replacement for autoconf cache load +dnl +dnl Notes: +dnl Caching in autoconf is broken (at least through version 2.13). +dnl The problem is that the cache is read +dnl without any check for whether it makes any sense to read it. +dnl A common problem is a build on a shared file system; connecting to +dnl a different computer and then building within the same directory will +dnl lead to at best error messages from configure and at worse a build that +dnl is wrong but fails only at run time (e.g., wrong datatype sizes used). +dnl Later versions of autoconf do include some checks for changes in the +dnl environment that impact the choices, but still misses problems with +dnl multiple different systems. +dnl +dnl This fixes that by requiring the user to explicitly enable caching +dnl before the cache file will be loaded. +dnl +dnl To use this version of 'AC_CACHE_LOAD', you need to include +dnl 'aclocal_cache.m4' in your 'aclocal.m4' file. The sowing 'aclocal.m4' +dnl file includes this file. +dnl +dnl If no --enable-cache or --disable-cache option is selected, the +dnl command causes configure to keep track of the system being configured +dnl in a config.system file; if the current system matches the value stored +dnl in that file (or there is neither a config.cache nor config.system file), +dnl configure will enable caching. In order to ensure that the configure +dnl tests make sense, the values of CC, F77, F90, and CXX are also included +dnl in the config.system file. In addition, the value of PATH is included +dnl to ensure that changes in the PATH that might select a different version +dnl of a program with the same name (such as a native make versus gnumake) +dnl are detected. +dnl +dnl Bugs: +dnl This does not work with the Cygnus configure because the enable arguments +dnl are processed *after* AC_CACHE_LOAD (!). To address this, we avoid +dnl changing the value of enable_cache, and use real_enable_cache, duplicating +dnl the "notgiven" value. +dnl +dnl The environment variable CONFIGURE_DEBUG_CACHE, if set to yes, +dnl will cause additional data to be written out during the configure process. +dnl This can be helpful in debugging the cache file process. +dnl +dnl See Also: +dnl PAC_ARG_CACHING +dnl D*/ +define([AC_CACHE_LOAD], +[if test "$CONFIGURE_DEBUG_CACHE" = yes ; then + oldopts="$-" + clearMinusX=no + set -x + if test "$oldopts" != "$-" ; then + clearMinusX=yes + fi +fi +if test "X$cache_system" = "X" ; then + # A default file name, just in case + cache_system="config.system" + if test "$cache_file" != "/dev/null" ; then + # Get the directory for the cache file, if any + changequote(,) + dnl Be careful to ensure that there is no doubled slash + cache_system=`echo $cache_file | sed -e 's%^\(.*/\)[^/]*%\1config.system%'` + changequote([,]) + test "x$cache_system" = "x$cache_file" && cache_system="config.system" +# else +# We must *not* set enable_cache to no because we need to know if +# enable_cache was not set. +# enable_cache=no + fi +fi +dnl +dnl The "action-if-not-given" part of AC_ARG_ENABLE is not executed until +dnl after the AC_CACHE_LOAD is executed (!). Thus, the value of +dnl enable_cache if neither --enable-cache or --disable-cache is selected +dnl is null. Just in case autoconf ever fixes this, we test both cases. +dnl +dnl Include PATH in the cache.system file since changing the path can +dnl change which versions of programs are found (such as vendor make +dnl or GNU make). +dnl +# +# Get a test value and flag whether we should remove/replace the +# cache_system file (do so unless cache_system_ok is yes) +# FC and F77 should be synonyms. Save both in case +# We include the xxxFLAGS in case the user is using the flags to change +# the language (either input or output) of the compiler. E.g., +# using -xarch=v9 on Solaris to select 64 bit output or using -D_BSD_SOURCE +# with gcc to get different header files on input. +cleanargs=`echo "$CC $F77 $FC $CXX $F90 $CFLAGS $FFLAGS $CXXFLAGS $F90FLAGS $PATH" | tr '"' ' '` +if uname -srm >/dev/null 2>&1 ; then + cache_system_text="`uname -srm` $cleanargs" +else + cache_system_text="-no-uname- $cleanargs" +fi +cache_system_ok=no +# +if test -z "$real_enable_cache" ; then + real_enable_cache=$enable_cache + if test -z "$real_enable_cache" ; then real_enable_cache="notgiven" ; fi +fi +if test "X$real_enable_cache" = "Xnotgiven" ; then + # check for valid cache file + if test -z "$cache_system" ; then cache_system="config.system" ; fi + if uname -srm >/dev/null 2>&1 ; then + if test -f "$cache_system" -a -n "$cache_system_text" ; then + if test "$cache_system_text" = "`cat $cache_system`" ; then + real_enable_cache="yes" + cache_system_ok=yes + fi + elif test ! -f "$cache_system" -a -n "$cache_system_text" ; then + # remove the cache file because it may not correspond to our + # system + if test "$cache_file" != "/dev/null" ; then + rm -f $cache_file + fi + real_enable_cache="yes" + fi + fi +fi +if test "X$real_enable_cache" = "Xyes" -a "$cache_file" = "/dev/null" ; then + real_enable_cache=no +fi +if test "X$real_enable_cache" = "Xyes" ; then + if test -r "$cache_file" ; then + echo "loading cache $cache_file" + if test -w "$cache_file" ; then + # Clean the cache file (ergh) + PAC_CACHE_CLEAN + fi + . $cache_file + else + echo "Configure in `pwd` creating cache $cache_file" + > $cache_file + rm -f $cache_system + fi +else + cache_file="/dev/null" +fi +# Remember our location and the name of the cachefile +pac_cv_my_conf_dir=`pwd` +dnl do not include the cachefile name, since this may contain the process +dnl number and cause comparisons looking for changes to the cache file +dnl to detect a change that isn't real. +dnl pac_cv_my_cachefile=$cachefile +# +# Update the cache_system file if necessary +if test "$cache_system_ok" != yes ; then + if test -n "$cache_system" ; then + rm -f $cache_system + echo $cache_system_text > $cache_system + fi +fi +if test "$clearMinusX" = yes ; then + set +x +fi +]) +dnl +dnl/*D +dnl PAC_ARG_CACHING - Enable caching of results from a configure execution +dnl +dnl Synopsis: +dnl PAC_ARG_CACHING +dnl +dnl Output Effects: +dnl Adds '--enable-cache' and '--disable-cache' to the command line arguments +dnl accepted by 'configure'. +dnl +dnl See Also: +dnl AC_CACHE_LOAD +dnl D*/ +dnl Add this call to the other ARG_ENABLE calls. Note that the values +dnl set here are redundant; the LOAD_CACHE call relies on the way autoconf +dnl initially processes ARG_ENABLE commands. +AC_DEFUN([PAC_ARG_CACHING],[ +AC_ARG_ENABLE(cache, + AC_HELP_STRING([--enable-cache], [Turn on configure caching]),, + [enable_cache="notgiven"]) +]) + +dnl Clean the cache of extraneous quotes that AC_CACHE_SAVE may add +dnl +AC_DEFUN([PAC_CACHE_CLEAN],[ + rm -f confcache + sed -e "s/'\\\\''//g" -e "s/'\\\\/'/" -e "s/\\\\'/'/" \ + -e "s/'\\\\''//g" $cache_file > confcache + if cmp -s $cache_file confcache ; then + : + else + if test -w $cache_file ; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi + fi + rm -f confcache + if test "$DEBUG_AUTOCONF_CACHE" = "yes" ; then + echo "Results of cleaned cache file:" + echo "--------------------------------------------------------" + cat $cache_file + echo "--------------------------------------------------------" + fi +]) + +dnl/*D +dnl PAC_SUBDIR_CACHE - Create a cache file before ac_output for subdirectory +dnl configures. +dnl +dnl Synopsis: +dnl PAC_SUBDIR_CACHE(when) +dnl +dnl Input Parameter: +dnl . when - Indicates when the cache should be created (optional) +dnl If 'always', create a new cache file. This option +dnl should be used if any of the cache parameters (such as +dnl CFLAGS or LDFLAGS) may have changed. +dnl +dnl Output Effects: +dnl +dnl Create a cache file before ac_output so that subdir configures don't +dnl make mistakes. +dnl We can't use OUTPUT_COMMANDS to remove the cache file, because those +dnl commands are executed *before* the subdir configures. +dnl +dnl D*/ +AC_DEFUN([PAC_SUBDIR_CACHE],[]) +AC_DEFUN([PAC_SUBDIR_CACHE_OLD],[ +if test "x$1" = "xalways" -o \( "$cache_file" = "/dev/null" -a "X$real_enable_cache" = "Xnotgiven" \) ; then + # Use an absolute directory to help keep the subdir configures from getting + # lost + cache_file=`pwd`/$$conf.cache + touch $cache_file + dnl + dnl For Autoconf 2.52+, we should ensure that the environment is set + dnl for the cache. Make sure that we get the values and set the + dnl xxx_set variables properly + ac_cv_env_CC_set=set + ac_cv_env_CC_value=$CC + ac_cv_env_CFLAGS_set=${CFLAGS+set} + ac_cv_env_CFLAGS_value=$CFLAGS + ac_cv_env_CPP_set=set + ac_cv_env_CPP_value=$CPP + ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} + ac_cv_env_CPPFLAGS_value=$CPPFLAGS + ac_cv_env_LDFLAGS_set=${LDFLAGS+set} + ac_cv_env_LDFLAGS_value=$LDFLAGS + ac_cv_env_LIBS_set=${LIBS+set} + ac_cv_env_LIBS_value=$LIBS + ac_cv_env_FC_set=${FC+set} + ac_cv_env_FC_value=$FC + ac_cv_env_F77_set=${F77+set} + ac_cv_env_F77_value=$F77 + ac_cv_env_F90_set=${F90+set} + ac_cv_env_F90_value=$F90 + ac_cv_env_FFLAGS_set=${FFLAGS+set} + ac_cv_env_FFLAGS_value=$FFLAGS + ac_cv_env_CXX_set=${CXX+set} + ac_cv_env_CXX_value=$CXX + + ac_env_CC_set=set + ac_env_CC_value=$CC + ac_env_CFLAGS_set=${CFLAGS+set} + ac_env_CFLAGS_value=$CFLAGS + ac_env_CPP_set=set + ac_env_CPP_value=$CPP + ac_env_CPPFLAGS_set=${CPPFLAGS+set} + ac_env_CPPFLAGS_value=$CPPFLAGS + ac_env_LDFLAGS_set=${LDFLAGS+set} + ac_env_LDFLAGS_value=$LDFLAGS + ac_env_LIBS_set=${LIBS+set} + ac_env_LIBS_value=$LIBS + ac_env_FC_set=${FC+set} + ac_env_FC_value=$FC + ac_env_F77_set=${F77+set} + ac_env_F77_value=$F77 + ac_env_F90_set=${F90+set} + ac_env_F90_value=$F90 + ac_env_FFLAGS_set=${FFLAGS+set} + ac_env_FFLAGS_value=$FFLAGS + ac_env_CXX_set=${CXX+set} + ac_env_CXX_value=$CXX + + dnl other parameters are + dnl build_alias, host_alias, target_alias + + # It turns out that A C CACHE_SAVE can't be invoked more than once + # with data that contains blanks. What happens is that the quotes + # that it adds get quoted and then added again. To avoid this, + # we strip off the outer quotes for all cached variables + dnl We add pac_cv_my_conf_dir to give the source of this cachefile, + dnl and pac_cv_my_cachefile to indicate how it chose the cachefile. + pac_cv_my_conf_dir=`pwd` + pac_cv_my_cachefile=$cachefile + AC_CACHE_SAVE + PAC_CACHE_CLEAN + ac_configure_args="$ac_configure_args -enable-cache" +fi +dnl Unconditionally export these values. Subdir configures break otherwise +export CC +export CFLAGS +export LDFLAGS +export LIBS +export CPPFLAGS +export CPP +export FC +export F77 +export F90 +export CXX +export FFLAGS +export CCFLAGS +]) +AC_DEFUN([PAC_SUBDIR_CACHE_CLEANUP],[]) +AC_DEFUN([PAC_SUBDIR_CACHE_CLEANUP_OLD],[ +if test "$cache_file" != "/dev/null" -a "X$real_enable_cache" = "Xnotgiven" ; then + rm -f $cache_file + cache_file=/dev/null +fi +]) +dnl +dnl The following three macros support the sharing of configure results +dnl by configure scripts, including ones that are not run with +dnl AC_CONFIG_SUBDIRS (the cachefiles managed by --enable-cache can +dnl only be used with AC_CONFIG_SUBDIRS; creating a autoconf-style +dnl cachefile before the the end of the autoconf process will often +dnl cause problems. +dnl +AC_DEFUN([PAC_CREATE_BASE_CACHE],[ +AC_ARG_ENABLE(base-cache, + AC_HELP_STRING([--enable-base-cache], + [Enable the use of a simple cache for the subsidiary + configure scripts]),,enable_base_cache=default) +# The default case is controlled by the environment variable CONF_USE_CACHEFILE +if test "$enable_base_cache" = "default" ; then + if test "$CONF_USE_CACHEFILE" = yes ; then + enable_base_cache=yes + else + enable_base_cache=no + fi +fi +if test "$enable_base_cache" != no ; then + if test "$enable_base_cache" = yes ; then + basecachefile=`pwd`/cache.base + else + basecachefile=`pwd`/$enable_base_cache + fi + set | grep ac_cv > $basecachefile + # Tell other configures to load this file + echo "Creating and exporting the base cache file $basecachefile" + CONF_BASE_CACHEFILE=$basecachefile + export CONF_BASE_CACHEFILE +fi +]) +AC_DEFUN([PAC_LOAD_BASE_CACHE],[ +if test -n "$CONF_BASE_CACHEFILE" -a -s "$CONF_BASE_CACHEFILE" ; then + echo "Loading base cachefile $CONF_BASE_CACHEFILE" + . $CONF_BASE_CACHEFILE + export CONF_BASE_CACHEFILE +fi +]) +AC_DEFUN([PAC_UPDATE_BASE_CACHE],[ +if test -n "$CONF_BASE_CACHEFILE" -a -s "$CONF_BASE_CACHEFILE" ; then + set | grep ac_cv > $CONF_BASE_CACHEFILE.new + if cmp -s $CONF_BASE_CACHEFILE.new $CONF_BASE_CACHEFILE ; then + : + else + echo "Replacing $CONF_BASE_CACHEFILE" + mv $CONF_BASE_CACHEFILE.new $CONF_BASE_CACHEFILE + fi +fi +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_cc.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_cc.m4 new file mode 100644 index 0000000000..92e7ee109b --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_cc.m4 @@ -0,0 +1,1692 @@ +dnl AC_PROG_CC_GNU +ifdef([AC_PROG_CC_GNU],,[AC_DEFUN([AC_PROG_CC_GNU],)]) + +dnl PAC_PROG_CC - reprioritize the C compiler search order +AC_DEFUN([PAC_PROG_CC],[ + dnl Many standard autoconf/automake/libtool macros, such as LT_INIT, + dnl perform an AC_REQUIRE([AC_PROG_CC]). If this macro (PAC_PROG_CC) + dnl comes after LT_INIT (or similar) then the default compiler search + dnl path will be used instead. This AC_BEFORE macro ensures that a + dnl warning will be emitted at autoconf-time (autogen.sh-time) to help + dnl developers notice this case. + AC_BEFORE([$0],[AC_PROG_CC]) + PAC_PUSH_FLAG([CFLAGS]) + AC_PROG_CC([icc pgcc xlc xlC pathcc gcc clang cc]) + PAC_POP_FLAG([CFLAGS]) +]) +dnl +dnl/*D +dnl PAC_C_CHECK_COMPILER_OPTION - Check that a compiler option is accepted +dnl without warning messages +dnl +dnl Synopsis: +dnl PAC_C_CHECK_COMPILER_OPTION(optionname,action-if-ok,action-if-fail) +dnl +dnl Output Effects: +dnl +dnl If no actions are specified, a working value is added to 'COPTIONS' +dnl +dnl Notes: +dnl This is now careful to check that the output is different, since +dnl some compilers are noisy. +dnl +dnl We are extra careful to prototype the functions in case compiler options +dnl that complain about poor code are in effect. +dnl +dnl Because this is a long script, we have ensured that you can pass a +dnl variable containing the option name as the first argument. +dnl +dnl D*/ +AC_DEFUN([PAC_C_CHECK_COMPILER_OPTION],[ +AC_MSG_CHECKING([whether C compiler accepts option $1]) +pac_opt="$1" +AC_LANG_PUSH([C]) +CFLAGS_orig="$CFLAGS" +CFLAGS_opt="$pac_opt $CFLAGS" +pac_result="unknown" + +AC_LANG_CONFTEST([ + AC_LANG_PROGRAM([[#include + const char hw[] = "Hello, World\n";]], + [[fputs (hw, stdout);]]) +]) +CFLAGS="$CFLAGS_orig" +rm -f pac_test1.log +PAC_LINK_IFELSE_LOG([pac_test1.log], [], [ + CFLAGS="$CFLAGS_opt" + rm -f pac_test2.log + PAC_LINK_IFELSE_LOG([pac_test2.log], [], [ + PAC_RUNLOG_IFELSE([diff -b pac_test1.log pac_test2.log], + [pac_result=yes],[pac_result=no]) + ],[ + pac_result=no + ]) +], [ + pac_result=no +]) +AC_MSG_RESULT([$pac_result]) +dnl Delete the conftest created by AC_LANG_CONFTEST. +rm -f conftest.$ac_ext + +# gcc 4.2.4 on 32-bit does not complain about the -Wno-type-limits option +# even though it doesn't support it. However, when another warning is +# triggered, it gives an error that the option is not recognized. So we +# need to test with a conftest file that will generate warnings. +# +# add an extra switch, pac_c_check_compiler_option_prototest, to +# disable this test just in case some new compiler does not like it. +# +# Linking with a program with an invalid prototype to ensure a compiler warning. + +if test "$pac_result" = "yes" \ + -a "$pac_c_check_compiler_option_prototest" != "no" ; then + AC_MSG_CHECKING([whether C compiler option $1 works with an invalid prototype program]) + AC_LINK_IFELSE([ + dnl We want a warning, but we don't want to inadvertently disable + dnl special warnings like -Werror-implicit-function-declaration (e.g., + dnl in PAC_CC_STRICT) by compiling something that might actually be + dnl treated as an error by the compiler. So we try to elicit an + dnl "unused variable" warning and/or an "uninitialized" warning with the + dnl test program below. + dnl + dnl The old sanity program was: + dnl void main() {return 0;} + dnl which clang (but not GCC) would treat as an *error*, invalidating + dnl the test for any given parameter. + AC_LANG_SOURCE([int main(int argc, char **argv){ int foo, bar = 0; foo += 1; return foo; }]) + ],[pac_result=yes],[pac_result=no]) + AC_MSG_RESULT([$pac_result]) +fi +# +if test "$pac_result" = "yes" ; then + AC_MSG_CHECKING([whether routines compiled with $pac_opt can be linked with ones compiled without $pac_opt]) + pac_result=unknown + CFLAGS="$CFLAGS_orig" + rm -f pac_test3.log + PAC_COMPILE_IFELSE_LOG([pac_test3.log], [ + AC_LANG_SOURCE([ + int foo(void); + int foo(void){return 0;} + ]) + ],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $LIBS" + + rm -f pac_test4.log + PAC_LINK_IFELSE_LOG([pac_test4.log], [AC_LANG_PROGRAM()], [ + CFLAGS="$CFLAGS_opt" + rm -f pac_test5.log + PAC_LINK_IFELSE_LOG([pac_test5.log], [AC_LANG_PROGRAM()], [ + PAC_RUNLOG_IFELSE([diff -b pac_test4.log pac_test5.log], + [pac_result=yes], [pac_result=no]) + ],[ + pac_result=no + ]) + ],[ + pac_result=no + ]) + LIBS="$saved_LIBS" + rm -f pac_conftest.$OBJEXT + ],[ + pac_result=no + ]) + AC_MSG_RESULT([$pac_result]) + rm -f pac_test3.log pac_test4.log pac_test5.log +fi +rm -f pac_test1.log pac_test2.log + +dnl Restore CFLAGS before 2nd/3rd argument commands are executed, +dnl as 2nd/3rd argument command could be modifying CFLAGS. +CFLAGS="$CFLAGS_orig" +if test "$pac_result" = "yes" ; then + ifelse([$2],[],[COPTIONS="$COPTIONS $1"],[$2]) +else + ifelse([$3],[],[:],[$3]) +fi +AC_LANG_POP([C]) +]) +dnl +dnl/*D +dnl PAC_C_OPTIMIZATION - Determine C options for producing optimized code +dnl +dnl Synopsis +dnl PAC_C_OPTIMIZATION([action if found]) +dnl +dnl Output Effect: +dnl Adds options to 'COPTIONS' if no other action is specified +dnl +dnl Notes: +dnl This is a temporary standin for compiler optimization. +dnl It should try to match known systems to known compilers (checking, of +dnl course), and then falling back to some common defaults. +dnl Note that many compilers will complain about -g and aggressive +dnl optimization. +dnl D*/ +AC_DEFUN([PAC_C_OPTIMIZATION],[ + for copt in "-O4 -Ofast" "-Ofast" "-fast" "-O3" "-xO3" "-O" ; do + PAC_C_CHECK_COMPILER_OPTION($copt,found_opt=yes,found_opt=no) + if test "$found_opt" = "yes" ; then + ifelse($1,,COPTIONS="$COPTIONS $copt",$1) + break + fi + done + if test "$ac_cv_prog_gcc" = "yes" ; then + for copt in "-fomit-frame-pointer" "-finline-functions" \ + "-funroll-loops" ; do + PAC_C_CHECK_COMPILER_OPTION($copt,found_opt=yes,found_opt=no) + if test "$found_opt" = "yes" ; then + ifelse($1,,COPTIONS="$COPTIONS $copt",$1) + # no break because we're trying to add them all + fi + done + # We could also look for architecture-specific gcc options + fi + +]) + +dnl/*D +dnl PAC_PROG_C_UNALIGNED_DOUBLES - Check that the C compiler allows unaligned +dnl doubles +dnl +dnl Synopsis: +dnl PAC_PROG_C_UNALIGNED_DOUBLES(action-if-true,action-if-false, +dnl action-if-unknown) +dnl +dnl Notes: +dnl 'action-if-unknown' is used in the case of cross-compilation. +dnl D*/ +AC_DEFUN([PAC_PROG_C_UNALIGNED_DOUBLES],[ +AC_CACHE_CHECK([whether C compiler allows unaligned doubles], +pac_cv_prog_c_unaligned_doubles,[ +AC_TRY_RUN([ +void fetch_double( v ) +double *v; +{ +*v = 1.0; +} +int main( argc, argv ) +int argc; +char **argv; +{ +int p[4]; +double *p_val; +fetch_double( (double *)&(p[0]) ); +p_val = (double *)&(p[0]); +if (*p_val != 1.0) return 1; +fetch_double( (double *)&(p[1]) ); +p_val = (double *)&(p[1]); +if (*p_val != 1.0) return 1; +return 0; +} +],pac_cv_prog_c_unaligned_doubles="yes",pac_cv_prog_c_unaligned_doubles="no", +pac_cv_prog_c_unaligned_doubles="unknown")]) +ifelse($1,,,if test "X$pac_cv_prog_c_unaligned_doubles" = "yes" ; then +$1 +fi) +ifelse($2,,,if test "X$pac_cv_prog_c_unaligned_doubles" = "no" ; then +$2 +fi) +ifelse($3,,,if test "X$pac_cv_prog_c_unaligned_doubles" = "unknown" ; then +$3 +fi) +]) + +dnl/*D +dnl PAC_PROG_C_WEAK_SYMBOLS - Test whether C supports weak alias symbols. +dnl +dnl Synopsis +dnl PAC_PROG_C_WEAK_SYMBOLS(action-if-true,action-if-false) +dnl +dnl Output Effect: +dnl Defines one of the following if a weak symbol pragma is found: +dnl.vb +dnl HAVE_PRAGMA_WEAK - #pragma weak +dnl HAVE_PRAGMA_HP_SEC_DEF - #pragma _HP_SECONDARY_DEF +dnl HAVE_PRAGMA_CRI_DUP - #pragma _CRI duplicate x as y +dnl.ve +dnl May also define +dnl.vb +dnl HAVE_WEAK_ATTRIBUTE +dnl.ve +dnl if functions can be declared as 'int foo(...) __attribute__ ((weak));' +dnl sets the shell variable pac_cv_attr_weak to yes. +dnl Also checks for __attribute__((weak_import)) which is supported by +dnl Apple in Mac OSX (at least in Darwin). Note that this provides only +dnl weak symbols, not weak aliases +dnl +dnl D*/ +AC_DEFUN([PAC_PROG_C_WEAK_SYMBOLS],[ +pragma_extra_message="" +AC_CACHE_CHECK([for type of weak symbol alias support], +pac_cv_prog_c_weak_symbols,[ +# Test for weak symbol support... +# We can't put # in the message because it causes autoconf to generate +# incorrect code +AC_TRY_LINK([ +extern int PFoo(int); +#pragma weak PFoo = Foo +int Foo(int a) { return a; } +],[return PFoo(1);],has_pragma_weak=yes) +# +# Some systems (Linux ia64 and ecc, for example), support weak symbols +# only within a single object file! This tests that case. +# Note that there is an extern int PFoo declaration before the +# pragma. Some compilers require this in order to make the weak symbol +# externally visible. +if test "$has_pragma_weak" = yes ; then + PAC_COMPLINK_IFELSE([ + AC_LANG_SOURCE([ +extern int PFoo(int); +#pragma weak PFoo = Foo +int Foo(int); +int Foo(int a) { return a; } + ]) + ],[ + AC_LANG_SOURCE([ +extern int PFoo(int); +int main(int argc, char **argv) { +return PFoo(0);} + ]) + ],[ + PAC_COMPLINK_IFELSE([ + AC_LANG_SOURCE([ +extern int PFoo(int); +#pragma weak PFoo = Foo +int Foo(int); +int Foo(int a) { return a; } + ]) + ],[ + AC_LANG_SOURCE([ +extern int Foo(int); +int PFoo(int a) { return a+1;} +int main(int argc, char **argv) { +return Foo(0);} + ]) + ],[ + pac_cv_prog_c_weak_symbols="pragma weak" + ],[ + has_pragma_weak=0 + pragma_extra_message="pragma weak accepted but does not work (probably creates two non-weak entries)" + ]) + ],[ + has_pragma_weak=0 + pragma_extra_message="pragma weak accepted but does not work (probably creates two non-weak entries)" + ]) +fi +dnl +if test -z "$pac_cv_prog_c_weak_symbols" ; then + AC_TRY_LINK([ +extern int PFoo(int); +#pragma _HP_SECONDARY_DEF Foo PFoo +int Foo(int a) { return a; } +],[return PFoo(1);],pac_cv_prog_c_weak_symbols="pragma _HP_SECONDARY_DEF") +fi +dnl +if test -z "$pac_cv_prog_c_weak_symbols" ; then + AC_TRY_LINK([ +extern int PFoo(int); +#pragma _CRI duplicate PFoo as Foo +int Foo(int a) { return a; } +],[return PFoo(1);],pac_cv_prog_c_weak_symbols="pragma _CRI duplicate x as y") +fi +dnl +if test -z "$pac_cv_prog_c_weak_symbols" ; then + pac_cv_prog_c_weak_symbols="no" +fi +dnl +dnl If there is an extra explanatory message, echo it now so that it +dnl doesn't interfere with the cache result value +if test -n "$pragma_extra_message" ; then + echo $pragma_extra_message +fi +dnl +]) +if test "$pac_cv_prog_c_weak_symbols" != "no" ; then + case "$pac_cv_prog_c_weak_symbols" in + "pragma weak") AC_DEFINE(HAVE_PRAGMA_WEAK,1,[Supports weak pragma]) + ;; + "pragma _HP") AC_DEFINE(HAVE_PRAGMA_HP_SEC_DEF,1,[HP style weak pragma]) + ;; + "pragma _CRI") AC_DEFINE(HAVE_PRAGMA_CRI_DUP,1,[Cray style weak pragma]) + ;; + esac +fi +AC_CACHE_CHECK([whether __attribute__ ((weak)) allowed], +pac_cv_attr_weak,[ +AC_TRY_COMPILE([int foo(int) __attribute__ ((weak));],[int a;], +pac_cv_attr_weak=yes,pac_cv_attr_weak=no)]) +# Note that being able to compile with weak_import doesn't mean that +# it works. +AC_CACHE_CHECK([whether __attribute__ ((weak_import)) allowed], +pac_cv_attr_weak_import,[ +AC_TRY_COMPILE([int foo(int) __attribute__ ((weak_import));],[int a;], +pac_cv_attr_weak_import=yes,pac_cv_attr_weak_import=no)]) +# Check if the alias option for weak attributes is allowed +AC_CACHE_CHECK([whether __attribute__((weak,alias(...))) allowed], +pac_cv_attr_weak_alias,[ +PAC_PUSH_FLAG([CFLAGS]) +# force an error exit if the weak attribute isn't understood +CFLAGS=-Werror +AC_TRY_COMPILE([int __foo(int a){return 0;} int foo(int) __attribute__((weak,alias("__foo")));],[int a;], +pac_cv_attr_weak_alias=yes,pac_cv_attr_weak_alias=no) +# Restore original CFLAGS +PAC_POP_FLAG([CFLAGS])]) +if test "$pac_cv_attr_weak_alias" = "yes" ; then + AC_DEFINE(HAVE_WEAK_ATTRIBUTE,1,[Attribute style weak pragma]) +fi +if test "$pac_cv_prog_c_weak_symbols" = "no" -a "$pac_cv_attr_weak_alias" = "no" ; then + ifelse([$2],,:,[$2]) +else + ifelse([$1],,:,[$1]) +fi +]) + +# +# This is a replacement that checks that FAILURES are signaled as well +# (later configure macros look for the .o file, not just success from the +# compiler, but they should not HAVE to +# +dnl --- insert 2.52 compatibility here --- +dnl 2.52 does not have AC_PROG_CC_WORKS +ifdef([AC_PROG_CC_WORKS],,[AC_DEFUN([AC_PROG_CC_WORKS],)]) +dnl +AC_DEFUN([PAC_PROG_CC_WORKS], +[AC_PROG_CC_WORKS +AC_MSG_CHECKING([whether the C compiler sets its return status correctly]) +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILE(,[int a = bzzzt;],notbroken=no,notbroken=yes) +AC_MSG_RESULT($notbroken) +if test "$notbroken" = "no" ; then + AC_MSG_ERROR([installation or configuration problem: C compiler does not +correctly set error code when a fatal error occurs]) +fi +]) + +dnl/*D +dnl PAC_PROG_C_MULTIPLE_WEAK_SYMBOLS - Test whether C and the +dnl linker allow multiple weak symbols. +dnl +dnl Synopsis +dnl PAC_PROG_C_MULTIPLE_WEAK_SYMBOLS(action-if-true,action-if-false) +dnl +dnl +dnl D*/ +AC_DEFUN([PAC_PROG_C_MULTIPLE_WEAK_SYMBOLS],[ +AC_CACHE_CHECK([for multiple weak symbol support], +pac_cv_prog_c_multiple_weak_symbols,[ +# Test for multiple weak symbol support... +PAC_COMPLINK_IFELSE([ + AC_LANG_SOURCE([ +extern int PFoo(int); +extern int PFoo_(int); +extern int pfoo_(int); +#pragma weak PFoo = Foo +#pragma weak PFoo_ = Foo +#pragma weak pfoo_ = Foo +int Foo(int); +int Foo(a) { return a; } + ]) +],[ + AC_LANG_SOURCE([ +extern int PFoo(int), PFoo_(int), pfoo_(int); +int main() { +return PFoo(0) + PFoo_(1) + pfoo_(2);} + ]) +],[ + pac_cv_prog_c_multiple_weak_symbols="yes" +]) +dnl +]) +if test "$pac_cv_prog_c_multiple_weak_symbols" = "yes" ; then + ifelse([$1],,:,[$1]) +else + ifelse([$2],,:,[$2]) +fi +]) + +dnl Use the value of enable-strict to update CFLAGS +dnl pac_cc_strict_flags contains the strict flags. +dnl +dnl -std=c89 is used to select the C89 version of the ANSI/ISO C standard. +dnl As of this writing, many C compilers still accepted only this version, +dnl not the later C99 version. When all compilers accept C99, this +dnl should be changed to the appropriate standard level. Note that we've +dnl had trouble with gcc 2.95.3 accepting -std=c89 but then trying to +dnl compile program with a invalid set of options +dnl (-D __STRICT_ANSI__-trigraphs) +AC_DEFUN([PAC_CC_STRICT],[ +export enable_strict_done +if test "$enable_strict_done" != "yes" ; then + + # Some comments on strict warning options. + # These were added to improve portability + # -Wstack-usage=262144 -- 32 bit FreeBSD did not like the mprobe test + # allocating a big variable on the stack. (See tt#2160). The "right" + # value requires further investigation; 1 MiB would have at least + # caught #2160 at compile-time, and only two other tests show a + # warning at 256k. + # + # These were added to reduce warnings: + # -Wno-missing-field-initializers -- We want to allow a struct to be + # initialized to zero using "struct x y = {0};" and not require + # each field to be initialized individually. + # -Wno-unused-parameter -- For portability, some parameters go unused + # when we have different implementations of functions for + # different platforms + # -Wno-unused-label -- We add fn_exit: and fn_fail: on all functions, + # but fn_fail may not be used if the function doesn't return an + # error. + # -Wno-sign-compare -- read() and write() return bytes read/written + # as a signed value, but we often compare this to size_t (or + # msg_sz_t) variables. + # -Wno-format-zero-length -- this warning is irritating and useless, since + # a zero-length format string is very well defined + # These were removed to reduce warnings: + # -Wcast-qual -- Sometimes we need to cast "volatile char*" to + # "char*", e.g., for memcpy. + # -Wpadded -- We catch struct padding with asserts when we need to + # -Wredundant-decls -- Having redundant declarations is benign and the + # code already has some. + # -Waggregate-return -- This seems to be a performance-related warning + # aggregate return values are legal in ANSI C, but they may be returned + # in memory rather than through a register. We do use aggregate return + # values, but they are structs of a single basic type (used to enforce + # type checking for relative vs. absolute ptrs), and with optimization + # the aggregate value is converted to a scalar. + # -Wdeclaration-after-statement -- This is a C89 + # requirement. When compiling with C99, this should be + # disabled. + # -Wfloat-equal -- There are places in hwloc that set a float var to 0, then + # compare it to 0 later to see if it was updated. Also when using strtod() + # one needs to compare the return value with 0 to see whether a conversion + # was performed. + # -Werror-implicit-function-declaration -- implicit function declarations + # should never be tolerated. This also ensures that we get quick + # compilation failures rather than later link failures that usually + # come from a function name typo. + # -Wcast-align -- Casting alignment warnings. This is an + # important check, but is temporarily disabled, since it is + # throwing too many (correct) warnings currently, causing us + # to miss other warnings. + # -Wshorten-64-to-32 -- Bad type-casting warnings. This is an + # important check, but is temporarily disabled, since it is + # throwing too many (correct) warnings currently, causing us + # to miss other warnings. + # + # This was removed because it masks important failures (see ticket #2094). + # However, since Intel compiler currently does not include -Wtype-limits + # in -Wextra, -Wtype-limits was added to handle warnings with the Intel + # compiler. + # -Wno-type-limits -- There are places where we compare an unsigned to + # a constant that happens to be zero e.g., if x is unsigned and + # MIN_VAL is zero, we'd like to do "MPIU_Assert(x >= MIN_VAL);". + # Note this option is not supported by gcc 4.2. This needs to be added + # after most other warning flags, so that we catch a gcc bug on 32-bit + # that doesn't give a warning that this is unsupported, unless another + # warning is triggered, and then if gives an error. + # the embedded newlines in this string are safe because we evaluate each + # argument in the for-loop below and append them to the CFLAGS with a space + # as the separator instead + pac_common_strict_flags=" + -Wall + -Wextra + -Wno-missing-field-initializers + -Wstrict-prototypes + -Wmissing-prototypes + -DGCC_WALL + -Wno-unused-parameter + -Wno-unused-label + -Wshadow + -Wmissing-declarations + -Wno-long-long + -Wundef + -Wno-endif-labels + -Wpointer-arith + -Wbad-function-cast + -Wwrite-strings + -Wno-sign-compare + -Wold-style-definition + -Wno-multichar + -Wno-deprecated-declarations + -Wpacked + -Wnested-externs + -Winvalid-pch + -Wno-pointer-sign + -Wvariadic-macros + -Wno-format-zero-length + -Wtype-limits + -Werror-implicit-function-declaration + -Wstack-usage=262144 + " + + enable_c89=no + enable_c99=yes + enable_posix=2001 + enable_opt=yes + flags="`echo $1 | sed -e 's/:/ /g' -e 's/,/ /g'`" + for flag in ${flags}; do + case "$flag" in + c89) + enable_strict_done="yes" + enable_c89=yes + enable_c99=no + ;; + c99) + enable_strict_done="yes" + enable_c89=no + enable_c99=yes + ;; + posix1995) + enable_strict_done="yes" + enable_posix=1995 + ;; + posix|posix2001) + enable_strict_done="yes" + enable_posix=2001 + ;; + posix2008) + enable_strict_done="yes" + enable_posix=2008 + ;; + noposix) + enable_strict_done="yes" + enable_posix=no + ;; + opt) + enable_strict_done="yes" + enable_opt=yes + ;; + noopt) + enable_strict_done="yes" + enable_opt=no + ;; + all|yes) + enable_strict_done="yes" + enable_c99=yes + enable_posix=2001 + enable_opt=yes + ;; + no) + # Accept and ignore this value + : + ;; + *) + if test -n "$flag" ; then + AC_MSG_WARN([Unrecognized value for enable-strict:$flag]) + fi + ;; + esac + done + + pac_cc_strict_flags="" + if test "${enable_strict_done}" = "yes" ; then + if test "${enable_opt}" = "yes" ; then + pac_cc_strict_flags="-O2" + fi + pac_cc_strict_flags="$pac_cc_strict_flags $pac_common_strict_flags" + case "$enable_posix" in + no) : ;; + 1995) PAC_APPEND_FLAG([-D_POSIX_C_SOURCE=199506L],[pac_cc_strict_flags]) ;; + 2001) PAC_APPEND_FLAG([-D_POSIX_C_SOURCE=200112L],[pac_cc_strict_flags]) ;; + 2008) PAC_APPEND_FLAG([-D_POSIX_C_SOURCE=200809L],[pac_cc_strict_flags]) ;; + *) AC_MSG_ERROR([internal error, unexpected POSIX version: '$enable_posix']) ;; + esac + # We only allow one of strict-C99 or strict-C89 to be + # enabled. If C99 is enabled, we automatically disable C89. + if test "${enable_c99}" = "yes" ; then + PAC_APPEND_FLAG([-std=c99],[pac_cc_strict_flags]) + # Use -D_STDC_C99= for Solaris compilers. See + # http://lists.gnu.org/archive/html/autoconf/2010-12/msg00059.html + # for discussion on why not to use -xc99 + PAC_APPEND_FLAG([-D_STDC_C99=],[pac_cc_strict_flags]) + elif test "${enable_c89}" = "yes" ; then + PAC_APPEND_FLAG([-std=c89],[pac_cc_strict_flags]) + PAC_APPEND_FLAG([-Wdeclaration-after-statement],[pac_cc_strict_flags]) + fi + fi + + # See if the above options work with the compiler + accepted_flags="" + for flag in $pac_cc_strict_flags ; do + PAC_PUSH_FLAG([CFLAGS]) + CFLAGS="$CFLAGS $accepted_flags" + PAC_C_CHECK_COMPILER_OPTION([$flag],[accepted_flags="$accepted_flags $flag"],) + PAC_POP_FLAG([CFLAGS]) + done + pac_cc_strict_flags=$accepted_flags +fi +]) + +dnl/*D +dnl PAC_ARG_STRICT - Add --enable-strict to configure. +dnl +dnl Synopsis: +dnl PAC_ARG_STRICT +dnl +dnl Output effects: +dnl Adds '--enable-strict' to the command line. +dnl +dnl D*/ +AC_DEFUN([PAC_ARG_STRICT],[ +AC_ARG_ENABLE(strict, + AC_HELP_STRING([--enable-strict], [Turn on strict compilation testing])) +PAC_CC_STRICT($enable_strict) +CFLAGS="$CFLAGS $pac_cc_strict_flags" +export CFLAGS +]) + +dnl Return the integer structure alignment in pac_cv_c_max_integer_align +dnl Possible values include +dnl packed +dnl two +dnl four +dnl eight +dnl +dnl In addition, a "Could not determine alignment" and a "error!" +dnl return is possible. +AC_DEFUN([PAC_C_MAX_INTEGER_ALIGN],[ +AC_CACHE_CHECK([for max C struct integer alignment], +pac_cv_c_max_integer_align,[ +AC_TRY_RUN([ +#include +#define DBG(a,b,c) +int main( int argc, char *argv[] ) +{ + FILE *cf; + int is_packed = 1; + int is_two = 1; + int is_four = 1; + int is_eight = 1; + struct { char a; int b; } char_int; + struct { char a; short b; } char_short; + struct { char a; long b; } char_long; + struct { char a; int b; char c; } char_int_char; + struct { char a; short b; char c; } char_short_char; +#ifdef HAVE_LONG_LONG_INT + struct { long long int a; char b; } lli_c; + struct { char a; long long int b; } c_lli; +#endif + int size, extent, extent2; + + /* assume max integer alignment isn't 8 if we don't have + * an eight-byte value :) + */ +#ifdef HAVE_LONG_LONG_INT + if (sizeof(int) < 8 && sizeof(long) < 8 && sizeof(long long int) < 8) + is_eight = 0; +#else + if (sizeof(int) < 8 && sizeof(long) < 8) is_eight = 0; +#endif + + size = sizeof(char) + sizeof(int); + extent = sizeof(char_int); + if (size != extent) is_packed = 0; + if ( (extent % 2) != 0) is_two = 0; + if ( (extent % 4) != 0) is_four = 0; + if (sizeof(int) == 8 && (extent % 8) != 0) is_eight = 0; + DBG("char_int",size,extent); + + size = sizeof(char) + sizeof(short); + extent = sizeof(char_short); + if (size != extent) is_packed = 0; + if ( (extent % 2) != 0) is_two = 0; + if (sizeof(short) == 4 && (extent % 4) != 0) is_four = 0; + if (sizeof(short) == 8 && (extent % 8) != 0) is_eight = 0; + DBG("char_short",size,extent); + + size = sizeof(char) + sizeof(long); + extent = sizeof(char_long); + if (size != extent) is_packed = 0; + if ( (extent % 2) != 0) is_two = 0; + if ( (extent % 4) != 0) is_four = 0; + if (sizeof(long) == 8 && (extent % 8) != 0) is_eight = 0; + DBG("char_long",size,extent); + +#ifdef HAVE_LONG_LONG_INT + size = sizeof(char) + sizeof(long long int); + extent = sizeof(lli_c); + extent2 = sizeof(c_lli); + if (size != extent) is_packed = 0; + if ( (extent % 2) != 0 && (extent2 % 2) != 0) is_two = 0; + if ( (extent % 4) != 0 && (extent2 % 4) != 0) is_four = 0; + if (sizeof(long long int) >= 8 && (extent % 8) != 0 && (extent2 % 8) != 0) + is_eight = 0; +#endif + + size = sizeof(char) + sizeof(int) + sizeof(char); + extent = sizeof(char_int_char); + if (size != extent) is_packed = 0; + if ( (extent % 2) != 0) is_two = 0; + if ( (extent % 4) != 0) is_four = 0; + if (sizeof(int) == 8 && (extent % 8) != 0) is_eight = 0; + DBG("char_int_char",size,extent); + + size = sizeof(char) + sizeof(short) + sizeof(char); + extent = sizeof(char_short_char); + if (size != extent) is_packed = 0; + if ( (extent % 2) != 0) is_two = 0; + if (sizeof(short) == 4 && (extent % 4) != 0) is_four = 0; + if (sizeof(short) == 8 && (extent % 8) != 0) is_eight = 0; + DBG("char_short_char",size,extent); + + /* If aligned mod 8, it will be aligned mod 4 */ + if (is_eight) { is_four = 0; is_two = 0; } + + if (is_four) is_two = 0; + + /* Tabulate the results */ + cf = fopen( "ctest.out", "w" ); + if (is_packed + is_two + is_four + is_eight == 0) { + fprintf( cf, "Could not determine alignment\n" ); + } + else { + if (is_packed + is_two + is_four + is_eight != 1) { + fprintf( cf, "error!\n" ); + } + else { + if (is_packed) fprintf( cf, "packed\n" ); + if (is_two) fprintf( cf, "two\n" ); + if (is_four) fprintf( cf, "four\n" ); + if (is_eight) fprintf( cf, "eight\n" ); + } + } + fclose( cf ); + return 0; +}], +pac_cv_c_max_integer_align=`cat ctest.out`, +pac_cv_c_max_integer_align="unknown", +pac_cv_c_max_integer_align="$CROSS_ALIGN_STRUCT_INT") +rm -f ctest.out +]) +if test -z "$pac_cv_c_max_integer_align" ; then + pac_cv_c_max_integer_align="unknown" +fi +]) + +dnl Return the floating point structure alignment in +dnl pac_cv_c_max_fp_align. +dnl +dnl Possible values include: +dnl packed +dnl two +dnl four +dnl eight +dnl sixteen +dnl +dnl In addition, a "Could not determine alignment" and a "error!" +dnl return is possible. +AC_DEFUN([PAC_C_MAX_FP_ALIGN],[ +AC_CACHE_CHECK([for max C struct floating point alignment], +pac_cv_c_max_fp_align,[ +AC_TRY_RUN([ +#include +#define DBG(a,b,c) +int main( int argc, char *argv[] ) +{ + FILE *cf; + int is_packed = 1; + int is_two = 1; + int is_four = 1; + int is_eight = 1; + int is_sixteen = 1; + struct { char a; float b; } char_float; + struct { float b; char a; } float_char; + struct { char a; double b; } char_double; + struct { double b; char a; } double_char; +#ifdef HAVE_LONG_DOUBLE + struct { char a; long double b; } char_long_double; + struct { long double b; char a; } long_double_char; + struct { long double a; int b; char c; } long_double_int_char; +#endif + int size, extent1, extent2; + + size = sizeof(char) + sizeof(float); + extent1 = sizeof(char_float); + extent2 = sizeof(float_char); + if (size != extent1) is_packed = 0; + if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; + if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; + if (sizeof(float) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) + is_eight = 0; + DBG("char_float",size,extent1); + + size = sizeof(char) + sizeof(double); + extent1 = sizeof(char_double); + extent2 = sizeof(double_char); + if (size != extent1) is_packed = 0; + if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; + if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; + if (sizeof(double) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) + is_eight = 0; + DBG("char_double",size,extent1); + +#ifdef HAVE_LONG_DOUBLE + size = sizeof(char) + sizeof(long double); + extent1 = sizeof(char_long_double); + extent2 = sizeof(long_double_char); + if (size != extent1) is_packed = 0; + if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; + if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; + if (sizeof(long double) >= 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) + is_eight = 0; + if (sizeof(long double) > 8 && (extent1 % 16) != 0 + && (extent2 % 16) != 0) is_sixteen = 0; + DBG("char_long-double",size,extent1); + + extent1 = sizeof(long_double_int_char); + if ( (extent1 % 2) != 0) is_two = 0; + if ( (extent1 % 4) != 0) is_four = 0; + if (sizeof(long double) >= 8 && (extent1 % 8) != 0) is_eight = 0; + if (sizeof(long double) > 8 && (extent1 % 16) != 0) is_sixteen = 0; +#else + is_sixteen = 0; +#endif + + if (is_sixteen) { is_eight = 0; is_four = 0; is_two = 0; } + + if (is_eight) { is_four = 0; is_two = 0; } + + if (is_four) is_two = 0; + + /* Tabulate the results */ + cf = fopen( "ctest.out", "w" ); + if (is_packed + is_two + is_four + is_eight + is_sixteen == 0) { + fprintf( cf, "Could not determine alignment\n" ); + } + else { + if (is_packed + is_two + is_four + is_eight + is_sixteen != 1) { + fprintf( cf, "error!\n" ); + } + else { + if (is_packed) fprintf( cf, "packed\n" ); + if (is_two) fprintf( cf, "two\n" ); + if (is_four) fprintf( cf, "four\n" ); + if (is_eight) fprintf( cf, "eight\n" ); + if (is_sixteen) fprintf( cf, "sixteen\n" ); + } + } + fclose( cf ); + return 0; +}], +pac_cv_c_max_fp_align=`cat ctest.out`, +pac_cv_c_max_fp_align="unknown", +pac_cv_c_max_fp_align="$CROSS_ALIGN_STRUCT_FP") +rm -f ctest.out +]) +if test -z "$pac_cv_c_max_fp_align" ; then + pac_cv_c_max_fp_align="unknown" +fi +]) + +dnl Return the floating point structure alignment in +dnl pac_cv_c_max_double_fp_align. +dnl +dnl Possible values include: +dnl packed +dnl two +dnl four +dnl eight +dnl +dnl In addition, a "Could not determine alignment" and a "error!" +dnl return is possible. +AC_DEFUN([PAC_C_MAX_DOUBLE_FP_ALIGN],[ +AC_CACHE_CHECK([for max C struct alignment of structs with doubles], +pac_cv_c_max_double_fp_align,[ +AC_TRY_RUN([ +#include +#define DBG(a,b,c) +int main( int argc, char *argv[] ) +{ + FILE *cf; + int is_packed = 1; + int is_two = 1; + int is_four = 1; + int is_eight = 1; + struct { char a; float b; } char_float; + struct { float b; char a; } float_char; + struct { char a; double b; } char_double; + struct { double b; char a; } double_char; + int size, extent1, extent2; + + size = sizeof(char) + sizeof(float); + extent1 = sizeof(char_float); + extent2 = sizeof(float_char); + if (size != extent1) is_packed = 0; + if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; + if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; + if (sizeof(float) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) + is_eight = 0; + DBG("char_float",size,extent1); + + size = sizeof(char) + sizeof(double); + extent1 = sizeof(char_double); + extent2 = sizeof(double_char); + if (size != extent1) is_packed = 0; + if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; + if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; + if (sizeof(double) == 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) + is_eight = 0; + DBG("char_double",size,extent1); + + if (is_eight) { is_four = 0; is_two = 0; } + + if (is_four) is_two = 0; + + /* Tabulate the results */ + cf = fopen( "ctest.out", "w" ); + if (is_packed + is_two + is_four + is_eight == 0) { + fprintf( cf, "Could not determine alignment\n" ); + } + else { + if (is_packed + is_two + is_four + is_eight != 1) { + fprintf( cf, "error!\n" ); + } + else { + if (is_packed) fprintf( cf, "packed\n" ); + if (is_two) fprintf( cf, "two\n" ); + if (is_four) fprintf( cf, "four\n" ); + if (is_eight) fprintf( cf, "eight\n" ); + } + } + fclose( cf ); + return 0; +}], +pac_cv_c_max_double_fp_align=`cat ctest.out`, +pac_cv_c_max_double_fp_align="unknown", +pac_cv_c_max_double_fp_align="$CROSS_ALIGN_STRUCT_DOUBLE_FP") +rm -f ctest.out +]) +if test -z "$pac_cv_c_max_double_fp_align" ; then + pac_cv_c_max_double_fp_align="unknown" +fi +]) +AC_DEFUN([PAC_C_MAX_LONGDOUBLE_FP_ALIGN],[ +AC_CACHE_CHECK([for max C struct floating point alignment with long doubles], +pac_cv_c_max_longdouble_fp_align,[ +AC_TRY_RUN([ +#include +#define DBG(a,b,c) +int main( int argc, char *argv[] ) +{ + FILE *cf; + int is_packed = 1; + int is_two = 1; + int is_four = 1; + int is_eight = 1; + int is_sixteen = 1; + struct { char a; long double b; } char_long_double; + struct { long double b; char a; } long_double_char; + struct { long double a; int b; char c; } long_double_int_char; + int size, extent1, extent2; + + size = sizeof(char) + sizeof(long double); + extent1 = sizeof(char_long_double); + extent2 = sizeof(long_double_char); + if (size != extent1) is_packed = 0; + if ( (extent1 % 2) != 0 && (extent2 % 2) != 0) is_two = 0; + if ( (extent1 % 4) != 0 && (extent2 % 4) != 0) is_four = 0; + if (sizeof(long double) >= 8 && (extent1 % 8) != 0 && (extent2 % 8) != 0) + is_eight = 0; + if (sizeof(long double) > 8 && (extent1 % 16) != 0 + && (extent2 % 16) != 0) is_sixteen = 0; + DBG("char_long-double",size,extent1); + + extent1 = sizeof(long_double_int_char); + if ( (extent1 % 2) != 0) is_two = 0; + if ( (extent1 % 4) != 0) is_four = 0; + if (sizeof(long double) >= 8 && (extent1 % 8) != 0) is_eight = 0; + if (sizeof(long double) > 8 && (extent1 % 16) != 0) is_sixteen = 0; + + if (is_sixteen) { is_eight = 0; is_four = 0; is_two = 0; } + + if (is_eight) { is_four = 0; is_two = 0; } + + if (is_four) is_two = 0; + + /* Tabulate the results */ + cf = fopen( "ctest.out", "w" ); + if (is_packed + is_two + is_four + is_eight + is_sixteen == 0) { + fprintf( cf, "Could not determine alignment\n" ); + } + else { + if (is_packed + is_two + is_four + is_eight + is_sixteen != 1) { + fprintf( cf, "error!\n" ); + } + else { + if (is_packed) fprintf( cf, "packed\n" ); + if (is_two) fprintf( cf, "two\n" ); + if (is_four) fprintf( cf, "four\n" ); + if (is_eight) fprintf( cf, "eight\n" ); + if (is_sixteen) fprintf( cf, "sixteen\n" ); + } + } + fclose( cf ); + return 0; +}], +pac_cv_c_max_longdouble_fp_align=`cat ctest.out`, +pac_cv_c_max_longdouble_fp_align="unknown", +pac_cv_c_max_longdouble_fp_align="$CROSS_ALIGN_STRUCT_LONGDOUBLE_FP") +rm -f ctest.out +]) +if test -z "$pac_cv_c_max_longdouble_fp_align" ; then + pac_cv_c_max_longdouble_fp_align="unknown" +fi +]) + +dnl Other tests assume that there is potentially a maximum alignment +dnl and that if there is no maximum alignment, or a type is smaller than +dnl that value, then we align on the size of the value, with the exception +dnl of the "position-based alignment" rules we test for separately. +dnl +dnl It turns out that these assumptions have fallen short in at least one +dnl case, on MacBook Pros, where doubles are aligned on 4-byte boundaries +dnl even when long doubles are aligned on 16-byte boundaries. So this test +dnl is here specifically to handle this case. +dnl +dnl Puts result in pac_cv_c_double_alignment_exception. +dnl +dnl Possible values currently include no and four. +dnl +AC_DEFUN([PAC_C_DOUBLE_ALIGNMENT_EXCEPTION],[ +AC_CACHE_CHECK([if double alignment breaks rules, find actual alignment], +pac_cv_c_double_alignment_exception,[ +AC_TRY_RUN([ +#include +#define DBG(a,b,c) +int main( int argc, char *argv[] ) +{ + FILE *cf; + struct { char a; double b; } char_double; + struct { double b; char a; } double_char; + int extent1, extent2, align_4 = 0; + + extent1 = sizeof(char_double); + extent2 = sizeof(double_char); + + /* we're interested in the largest value, will let separate test + * deal with position-based issues. + */ + if (extent1 < extent2) extent1 = extent2; + if ((sizeof(double) == 8) && (extent1 % 8) != 0) { + if (extent1 % 4 == 0) { +#ifdef HAVE_MAX_FP_ALIGNMENT + if (HAVE_MAX_FP_ALIGNMENT >= 8) align_4 = 1; +#else + align_4 = 1; +#endif + } + } + + cf = fopen( "ctest.out", "w" ); + + if (align_4) fprintf( cf, "four\n" ); + else fprintf( cf, "no\n" ); + + fclose( cf ); + return 0; +}], +pac_cv_c_double_alignment_exception=`cat ctest.out`, +pac_cv_c_double_alignment_exception="unknown", +pac_cv_c_double_alignment_exception="$CROSS_ALIGN_DOUBLE_EXCEPTION") +rm -f ctest.out +]) +if test -z "$pac_cv_c_double_alignment_exception" ; then + pac_cv_c_double_alignment_exception="unknown" +fi +]) + +dnl Test for odd struct alignment rule that only applies max. +dnl padding when double value is at front of type. +dnl Puts result in pac_cv_c_double_pos_align. +dnl +dnl Search for "Power alignment mode" for more details. +dnl +dnl Possible values include yes, no, and unknown. +dnl +AC_DEFUN([PAC_C_DOUBLE_POS_ALIGN],[ +AC_CACHE_CHECK([if alignment of structs with doubles is based on position], +pac_cv_c_double_pos_align,[ +AC_TRY_RUN([ +#include +#define DBG(a,b,c) +int main( int argc, char *argv[] ) +{ + FILE *cf; + int padding_varies_by_pos = 0; + struct { char a; double b; } char_double; + struct { double b; char a; } double_char; + int extent1, extent2; + + extent1 = sizeof(char_double); + extent2 = sizeof(double_char); + if (extent1 != extent2) padding_varies_by_pos = 1; + + cf = fopen( "ctest.out", "w" ); + if (padding_varies_by_pos) fprintf( cf, "yes\n" ); + else fprintf( cf, "no\n" ); + + fclose( cf ); + return 0; +}], +pac_cv_c_double_pos_align=`cat ctest.out`, +pac_cv_c_double_pos_align="unknown", +pac_cv_c_double_pos_align="$CROSS_ALIGN_DOUBLE_POS") +rm -f ctest.out +]) +if test -z "$pac_cv_c_double_pos_align" ; then + pac_cv_c_double_pos_align="unknown" +fi +]) + +dnl Test for odd struct alignment rule that only applies max. +dnl padding when long long int value is at front of type. +dnl Puts result in pac_cv_c_llint_pos_align. +dnl +dnl Search for "Power alignment mode" for more details. +dnl +dnl Possible values include yes, no, and unknown. +dnl +AC_DEFUN([PAC_C_LLINT_POS_ALIGN],[ +AC_CACHE_CHECK([if alignment of structs with long long ints is based on position], +pac_cv_c_llint_pos_align,[ +AC_TRY_RUN([ +#include +#define DBG(a,b,c) +int main( int argc, char *argv[] ) +{ + FILE *cf; + int padding_varies_by_pos = 0; +#ifdef HAVE_LONG_LONG_INT + struct { char a; long long int b; } char_llint; + struct { long long int b; char a; } llint_char; + int extent1, extent2; + + extent1 = sizeof(char_llint); + extent2 = sizeof(llint_char); + if (extent1 != extent2) padding_varies_by_pos = 1; +#endif + + cf = fopen( "ctest.out", "w" ); + if (padding_varies_by_pos) fprintf( cf, "yes\n" ); + else fprintf( cf, "no\n" ); + + fclose( cf ); + return 0; +}], +pac_cv_c_llint_pos_align=`cat ctest.out`, +pac_cv_c_llint_pos_align="unknown", +pac_cv_c_llint_pos_align="$CROSS_ALIGN_LLINT_POS") +rm -f ctest.out +]) +if test -z "$pac_cv_c_llint_pos_align" ; then + pac_cv_c_llint_pos_align="unknown" +fi +]) + +dnl/*D +dnl PAC_FUNC_NEEDS_DECL - Set NEEDS__DECL if a declaration is needed +dnl +dnl Synopsis: +dnl PAC_FUNC_NEEDS_DECL(headerfiles,funcname) +dnl +dnl Output Effect: +dnl Sets 'NEEDS__DECL' if 'funcname' is not declared by the +dnl headerfiles. +dnl +dnl Approach: +dnl Attempt to assign library function to function pointer. If the function +dnl is not declared in a header, this will fail. Use a non-static global so +dnl the compiler does not warn about an unused variable. +dnl +dnl Simply calling the function is not enough because C89 compilers allow +dnl calls to implicitly-defined functions. Re-declaring a library function +dnl with an incompatible prototype is also not sufficient because some +dnl compilers (notably clang-3.2) only produce a warning in this case. +dnl +dnl D*/ +AC_DEFUN([PAC_FUNC_NEEDS_DECL],[ +AC_CACHE_CHECK([whether $2 needs a declaration], +pac_cv_func_decl_$2,[ +AC_TRY_COMPILE([$1 +void (*fptr)(void) = (void(*)(void))$2;],[], +pac_cv_func_decl_$2=no,pac_cv_func_decl_$2=yes)]) +if test "$pac_cv_func_decl_$2" = "yes" ; then +changequote(<<,>>)dnl +define(<>, translit(NEEDS_$2_DECL, [a-z *], [A-Z__]))dnl +changequote([, ])dnl + AC_DEFINE_UNQUOTED(PAC_FUNC_NAME,1,[Define if $2 needs a declaration]) +undefine([PAC_FUNC_NAME]) +fi +]) + +dnl PAC_C_GNU_ATTRIBUTE - See if the GCC __attribute__ specifier is allow. +dnl Use the following +dnl #ifndef HAVE_GCC_ATTRIBUTE +dnl #define __attribute__(a) +dnl #endif +dnl If *not*, define __attribute__(a) as null +dnl +dnl We start by requiring Gcc. Some other compilers accept __attribute__ +dnl but generate warning messages, or have different interpretations +dnl (which seems to make __attribute__ just as bad as #pragma) +dnl For example, the Intel icc compiler accepts __attribute__ and +dnl __attribute__((pure)) but generates warnings for __attribute__((format...)) +dnl +AC_DEFUN([PAC_C_GNU_ATTRIBUTE],[ +AC_REQUIRE([AC_PROG_CC_GNU]) +if test "$ac_cv_prog_gcc" = "yes" ; then + AC_CACHE_CHECK([whether __attribute__ allowed], +pac_cv_gnu_attr_pure,[ +AC_TRY_COMPILE([int foo(int) __attribute__ ((pure));],[int a;], +pac_cv_gnu_attr_pure=yes,pac_cv_gnu_attr_pure=no)]) +AC_CACHE_CHECK([whether __attribute__((format)) allowed], +pac_cv_gnu_attr_format,[ +AC_TRY_COMPILE([int foo(char *,...) __attribute__ ((format(printf,1,2)));],[int a;], +pac_cv_gnu_attr_format=yes,pac_cv_gnu_attr_format=no)]) + if test "$pac_cv_gnu_attr_pure" = "yes" -a "$pac_cv_gnu_attr_format" = "yes" ; then + AC_DEFINE(HAVE_GCC_ATTRIBUTE,1,[Define if GNU __attribute__ is supported]) + fi +fi +]) +dnl +dnl Check for a broken install (fails to preserve file modification times, +dnl thus breaking libraries. +dnl +dnl Create a library, install it, and then try to link against it. +AC_DEFUN([PAC_PROG_INSTALL_BREAKS_LIBS],[ +AC_CACHE_CHECK([whether install breaks libraries], +ac_cv_prog_install_breaks_libs,[ +AC_REQUIRE([AC_PROG_RANLIB]) +AC_REQUIRE([AC_PROG_INSTALL]) +AC_REQUIRE([AC_PROG_CC]) +ac_cv_prog_install_breaks_libs=yes + +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ int foo(int); int foo(int a){return a;} ]) +],[ + if ${AR-ar} ${AR_FLAGS-cr} libconftest.a conftest.$OBJEXT >/dev/null 2>&1 ; then + if ${RANLIB-:} libconftest.a >/dev/null 2>&1 ; then + # Anything less than sleep 10, and Mac OS/X (Darwin) + # will claim that install works because ranlib won't complain + sleep 10 + libinstall="$INSTALL_DATA" + eval "libinstall=\"$libinstall\"" + if ${libinstall} libconftest.a libconftest1.a >/dev/null 2>&1 ; then + saved_LIBS="$LIBS" + LIBS="libconftest1.a" + AC_LINK_IFELSE([ + AC_LANG_SOURCE([ +extern int foo(int); +int main(int argc, char **argv){ return foo(0); } + ]) + ],[ + # Success! Install works + ac_cv_prog_install_breaks_libs=no + ],[ + # Failure! Does install -p work? + rm -f libconftest1.a + if ${libinstall} -p libconftest.a libconftest1.a >/dev/null 2>&1 ; then + AC_LINK_IFELSE([],[ + # Success! Install works + ac_cv_prog_install_breaks_libs="no, with -p" + ]) + fi + ]) + LIBS="$saved_LIBS" + fi + fi + fi +]) +rm -f libconftest*.a +]) dnl Endof ac_cache_check + +if test -z "$RANLIB_AFTER_INSTALL" ; then + RANLIB_AFTER_INSTALL=no +fi +case "$ac_cv_prog_install_breaks_libs" in + yes) + RANLIB_AFTER_INSTALL=yes + ;; + "no, with -p") + INSTALL_DATA="$INSTALL_DATA -p" + ;; + *) + # Do nothing + : + ;; +esac +AC_SUBST(RANLIB_AFTER_INSTALL) +]) + +# +# determine if the compiler defines a symbol containing the function name +# +# These tests check not only that the compiler defines some symbol, such +# as __FUNCTION__, but that the symbol correctly names the function. +# +# Defines +# HAVE__FUNC__ (if __func__ defined) +# HAVE_CAP__FUNC__ (if __FUNC__ defined) +# HAVE__FUNCTION__ (if __FUNCTION__ defined) +# +AC_DEFUN([PAC_CC_FUNCTION_NAME_SYMBOL],[ +AC_CACHE_CHECK([whether the compiler defines __func__], +pac_cv_have__func__,[ +tmp_am_cross=no +AC_RUN_IFELSE([ +AC_LANG_SOURCE([ +#include +int foo(void); +int foo(void) +{ + return (strcmp(__func__, "foo") == 0); +} +int main(int argc, char ** argv) +{ + return (foo() ? 0 : 1); +} +]) +], pac_cv_have__func__=yes, pac_cv_have__func__=no,tmp_am_cross=yes) +if test "$tmp_am_cross" = yes ; then + AC_LINK_IFELSE([ + AC_LANG_SOURCE([ +#include +int foo(void); +int foo(void) +{ + return (strcmp(__func__, "foo") == 0); +} +int main(int argc, char ** argv) +{ + return (foo() ? 0 : 1); +} + ]) +], pac_cv_have__func__=yes, pac_cv_have__func__=no) +fi +]) + +if test "$pac_cv_have__func__" = "yes" ; then + AC_DEFINE(HAVE__FUNC__,,[define if the compiler defines __func__]) +fi + +AC_CACHE_CHECK([whether the compiler defines __FUNC__], +pac_cv_have_cap__func__,[ +tmp_am_cross=no +AC_RUN_IFELSE([ +AC_LANG_SOURCE([ +#include +int foo(void); +int foo(void) +{ + return (strcmp(__FUNC__, "foo") == 0); +} +int main(int argc, char ** argv) +{ + return (foo() ? 0 : 1); +} +]) +], pac_cv_have_cap__func__=yes, pac_cv_have_cap__func__=no,tmp_am_cross=yes) +if test "$tmp_am_cross" = yes ; then + AC_LINK_IFELSE([ + AC_LANG_SOURCE([ +#include +int foo(void); +int foo(void) +{ + return (strcmp(__FUNC__, "foo") == 0); +} +int main(int argc, char ** argv) +{ + return (foo() ? 0 : 1); +} + ]) +], pac_cv_have__func__=yes, pac_cv_have__func__=no) +fi +]) + +if test "$pac_cv_have_cap__func__" = "yes" ; then + AC_DEFINE(HAVE_CAP__FUNC__,,[define if the compiler defines __FUNC__]) +fi + +AC_CACHE_CHECK([whether the compiler sets __FUNCTION__], +pac_cv_have__function__,[ +tmp_am_cross=no +AC_RUN_IFELSE([ +AC_LANG_SOURCE([ +#include +int foo(void); +int foo(void) +{ + return (strcmp(__FUNCTION__, "foo") == 0); +} +int main(int argc, char ** argv) +{ + return (foo() ? 0 : 1); +} +]) +], pac_cv_have__function__=yes, pac_cv_have__function__=no,tmp_am_cross=yes) +if test "$tmp_am_cross" = yes ; then + AC_LINK_IFELSE([ + AC_LANG_SOURCE([ +#include +int foo(void); +int foo(void) +{ + return (strcmp(__FUNCTION__, "foo") == 0); +} +int main(int argc, char ** argv) +{ + return (foo() ? 0 : 1); +} + ]) +], pac_cv_have__func__=yes, pac_cv_have__func__=no) +fi +]) + +if test "$pac_cv_have__function__" = "yes" ; then + AC_DEFINE(HAVE__FUNCTION__,,[define if the compiler defines __FUNCTION__]) +fi + +]) + + +dnl Check structure alignment +AC_DEFUN([PAC_STRUCT_ALIGNMENT],[ + # Initialize alignment checks + is_packed=1 + is_two=1 + is_four=1 + is_eight=1 + is_largest=1 + + # See if long double exists + AC_TRY_COMPILE(,[long double a;],have_long_double=yes,have_long_double=no) + + # Get sizes of regular types + AC_CHECK_SIZEOF(char) + AC_CHECK_SIZEOF(int) + AC_CHECK_SIZEOF(short) + AC_CHECK_SIZEOF(long) + AC_CHECK_SIZEOF(float) + AC_CHECK_SIZEOF(double) + AC_CHECK_SIZEOF(long double) + + # char_int comparison + AC_CHECK_SIZEOF(char_int, 0, [typedef struct { char a; int b; } char_int; ]) + size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_int` + extent=$ac_cv_sizeof_char_int + if test "$size" != "$extent" ; then is_packed=0 ; fi + if test "`expr $extent % $ac_cv_sizeof_int`" != "0" ; then is_largest=0 ; fi + if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi + if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi + if test "$ac_cv_sizeof_int" = "8" -a "`expr $extent % 8`" != "0" ; then + is_eight=0 + fi + + # char_short comparison + AC_CHECK_SIZEOF(char_short, 0, [typedef struct { char a; short b; } char_short; ]) + size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_short` + extent=$ac_cv_sizeof_char_short + if test "$size" != "$extent" ; then is_packed=0 ; fi + if test "`expr $extent % $ac_cv_sizeof_short`" != "0" ; then is_largest=0 ; fi + if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi + if test "$ac_cv_sizeof_short" = "4" -a "`expr $extent % 4`" != "0" ; then + is_four=0 + fi + if test "$ac_cv_sizeof_short" = "8" -a "`expr $extent % 8`" != "0" ; then + is_eight=0 + fi + + # char_long comparison + AC_CHECK_SIZEOF(char_long, 0, [typedef struct { char a; long b; } char_long; ]) + size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_long` + extent=$ac_cv_sizeof_char_long + if test "$size" != "$extent" ; then is_packed=0 ; fi + if test "`expr $extent % $ac_cv_sizeof_long`" != "0" ; then is_largest=0 ; fi + if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi + if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi + if test "$ac_cv_sizeof_long" = "8" -a "`expr $extent % 8`" != "0" ; then + is_eight=0 + fi + + # char_float comparison + AC_CHECK_SIZEOF(char_float, 0, [typedef struct { char a; float b; } char_float; ]) + size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_float` + extent=$ac_cv_sizeof_char_float + if test "$size" != "$extent" ; then is_packed=0 ; fi + if test "`expr $extent % $ac_cv_sizeof_float`" != "0" ; then is_largest=0 ; fi + if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi + if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi + if test "$ac_cv_sizeof_float" = "8" -a "`expr $extent % 8`" != "0" ; then + is_eight=0 + fi + + # char_double comparison + AC_CHECK_SIZEOF(char_double, 0, [typedef struct { char a; double b; } char_double; ]) + size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_double` + extent=$ac_cv_sizeof_char_double + if test "$size" != "$extent" ; then is_packed=0 ; fi + if test "`expr $extent % $ac_cv_sizeof_double`" != "0" ; then is_largest=0 ; fi + if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi + if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi + if test "$ac_cv_sizeof_double" = "8" -a "`expr $extent % 8`" != "0" ; then + is_eight=0 + fi + + # char_long_double comparison + if test "$have_long_double" = "yes"; then + AC_CHECK_SIZEOF(char_long_double, 0, [ + typedef struct { + char a; + long double b; + } char_long_double; + ]) + size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_long_double` + extent=$ac_cv_sizeof_char_long_double + if test "$size" != "$extent" ; then is_packed=0 ; fi + if test "`expr $extent % $ac_cv_sizeof_long_double`" != "0" ; then is_largest=0 ; fi + if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi + if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi + if test "$ac_cv_sizeof_long_double" = "8" -a "`expr $extent % 8`" != "0" ; then + is_eight=0 + fi + fi + + # char_int_char comparison + AC_CHECK_SIZEOF(char_int_char, 0, [ + typedef struct { + char a; + int b; + char c; + } char_int_char; + ]) + size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_int + $ac_cv_sizeof_char` + extent=$ac_cv_sizeof_char_int_char + if test "$size" != "$extent" ; then is_packed=0 ; fi + if test "`expr $extent % $ac_cv_sizeof_int`" != "0" ; then is_largest=0 ; fi + if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi + if test "`expr $extent % 4`" != "0" ; then is_four=0 ; fi + if test "$ac_cv_sizeof_int" = "8" -a "`expr $extent % 8`" != "0" ; then + is_eight=0 + fi + + # char_short_char comparison + AC_CHECK_SIZEOF(char_short_char, 0, [ + typedef struct { + char a; + short b; + char c; + } char_short_char; + ]) + size=`expr $ac_cv_sizeof_char + $ac_cv_sizeof_short + $ac_cv_sizeof_char` + extent=$ac_cv_sizeof_char_short_char + if test "$size" != "$extent" ; then is_packed=0 ; fi + if test "`expr $extent % $ac_cv_sizeof_short`" != "0" ; then is_largest=0 ; fi + if test "`expr $extent % 2`" != "0" ; then is_two=0 ; fi + if test "$ac_cv_sizeof_short" = "4" -a "`expr $extent % 4`" != "0" ; then + is_four=0 + fi + if test "$ac_cv_sizeof_short" = "8" -a "`expr $extent % 8`" != "0" ; then + is_eight=0 + fi + + # If aligned mod 8, it will be aligned mod 4 + if test $is_eight = 1 ; then is_four=0 ; is_two=0 ; fi + if test $is_four = 1 ; then is_two=0 ; fi + + # Largest supersedes 8 + if test $is_largest = 1 ; then is_eight=0 ; fi + + # Find the alignment + if test "`expr $is_packed + $is_largest + $is_two + $is_four + $is_eight`" = "0" ; then + pac_cv_struct_alignment="unknown" + elif test "`expr $is_packed + $is_largest + $is_two + $is_four + $is_eight`" != "1" ; then + pac_cv_struct_alignment="unknown" + elif test $is_packed = 1 ; then + pac_cv_struct_alignment="packed" + elif test $is_largest = 1 ; then + pac_cv_struct_alignment="largest" + elif test $is_two = 1 ; then + pac_cv_struct_alignment="two" + elif test $is_four = 1 ; then + pac_cv_struct_alignment="four" + elif test $is_eight = 1 ; then + pac_cv_struct_alignment="eight" + fi +]) +dnl +dnl PAC_C_MACRO_VA_ARGS +dnl +dnl will AC_DEFINE([HAVE_MACRO_VA_ARGS]) if the compiler supports C99 variable +dnl length argument lists in macros (#define foo(...) bar(__VA_ARGS__)) +AC_DEFUN([PAC_C_MACRO_VA_ARGS],[ + AC_MSG_CHECKING([for variable argument list macro functionality]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #include + #define conftest_va_arg_macro(...) printf(__VA_ARGS__) + ], + [conftest_va_arg_macro("a test %d", 3);])], + [AC_DEFINE([HAVE_MACRO_VA_ARGS],[1],[Define if C99-style variable argument list macro functionality]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) +])dnl + +# Will AC_DEFINE([HAVE_BUILTIN_EXPECT]) if the compiler supports __builtin_expect. +AC_DEFUN([PAC_C_BUILTIN_EXPECT],[ +AC_MSG_CHECKING([if C compiler supports __builtin_expect]) + +AC_TRY_LINK(, [ + return __builtin_expect(1, 1) ? 1 : 0 +], [ + have_builtin_expect=yes + AC_MSG_RESULT([yes]) +], [ + have_builtin_expect=no + AC_MSG_RESULT([no]) +]) +if test x$have_builtin_expect = xyes ; then + AC_DEFINE([HAVE_BUILTIN_EXPECT], [1], [Define to 1 if the compiler supports __builtin_expect.]) +fi +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_coverage.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_coverage.m4 new file mode 100644 index 0000000000..ce949d40a6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_coverage.m4 @@ -0,0 +1,90 @@ + +dnl Macro to add --enable-coverage option (disabled by default) and add +dnl appropriate compiler flags to permit usage of gcov if that option is +dnl enabled. If WRAPPER_xFLAGS variables are set then the flags will also be +dnl added to those variables. +dnl +dnl Sets "pac_cv_use_coverage=yes" and AC_DEFINEs USE_COVERAGE if coverage was +dnl successfully enabled. Also creates an AM_CONDITIONAL with the name +dnl "BUILD_COVERAGE" that is true iff pac_cv_use_coverage=yes. +dnl +dnl Usage: PAC_CONFIG_SUBDIR_ARGS +dnl +dnl Assumes that all of the compiler macros have already been invoked +dnl (AC_PROG_CC and friends). +AC_DEFUN([PAC_ENABLE_COVERAGE],[ + +AC_ARG_VAR([GCOV],[name/path for the gcov utility]) +AC_CHECK_PROGS([GCOV],[gcov]) + +AC_ARG_ENABLE([coverage], + [AC_HELP_STRING([--enable-coverage], + [Turn on coverage analysis using gcc and gcov])], + [],[enable_coverage=no]) + +if test "$enable_coverage" = "yes" ; then + if test "$ac_cv_prog_gcc" = "yes" ; then + CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" + LIBS="$LIBS -lgcov" + if test ${WRAPPER_CFLAGS+set} = set ; then + WRAPPER_CFLAGS="$WRAPPER_CFLAGS -fprofile-arcs -ftest-coverage" + fi + else + AC_MSG_WARN([--enable-coverage only supported for GCC]) + fi + if test "$enable_cxx" = "yes" ; then + if test "$ac_cv_cxx_compiler_gnu" = "yes" ; then + CXXFLAGS="$CXXFLAGS -fprofile-arcs -ftest-coverage" + LIBS="$LIBS -lgcov" + if test ${WRAPPER_CXXFLAGS+set} = set ; then + WRAPPER_CXXFLAGS="$WRAPPER_CXXFLAGS -fprofile-arcs -ftest-coverage" + fi + else + AC_MSG_WARN([--enable-coverage only supported for GCC]) + fi + fi + # Add similar options for g77 so that the Fortran tests will also + # + if test "$enable_f77" = yes ; then + if test "$ac_cv_f77_compiler_gnu" = "yes" ; then + FFLAGS="$FFLAGS -fprofile-arcs -ftest-coverage" + LIBS="$LIBS -lgcov" + if test ${WRAPPER_FFLAGS+set} = set ; then + WRAPPER_FFLAGS="$WRAPPER_FFLAGS -fprofile-arcs -ftest-coverage" + fi + else + AC_MSG_WARN([--enable-coverage only supported for G77/GFORTRAN]) + fi + fi + if test "$enable_fc" = yes ; then + if test "$ac_cv_fc_compiler_gnu" = "yes" ; then + FCFLAGS="$FCFLAGS -fprofile-arcs -ftest-coverage" + LIBS="$LIBS -lgcov" + if test ${WRAPPER_FCFLAGS+set} = set ; then + WRAPPER_FCFLAGS="$WRAPPER_FCFLAGS -fprofile-arcs -ftest-coverage" + fi + else + AC_MSG_WARN([--enable-coverage only supported for GFORTRAN]) + fi + fi + # On some platforms (e.g., Mac Darwin), we must also *link* + # with the -fprofile-args -ftest-coverage option. + AC_MSG_CHECKING([whether compilation with coverage analysis enabled works]) + AC_LINK_IFELSE([AC_LANG_SOURCE([int main(int argc, char **argv){return 1;}])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([Unable to link programs when coverage analysis enabled])]) + + # Test for the routines that we need to use to ensure that the + # data files are (usually) written out + # FIXME: Some versions of Linux provide usleep, but it rounds times + # up to the next second (!) + AC_CHECK_FUNCS([usleep]) + + # NOTE: using a "pac_cv_" prefix but not caching because of xFLAGS "side effects" + pac_cv_use_coverage=yes + AC_DEFINE([USE_COVERAGE],[1],[Define if performing coverage tests]) +fi +AM_CONDITIONAL([BUILD_COVERAGE],[test "X$pac_cv_use_coverage" = "Xyes"]) +]) + diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_cxx.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_cxx.m4 new file mode 100644 index 0000000000..72febd8ab9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_cxx.m4 @@ -0,0 +1,187 @@ +dnl PAC_CXX_SEARCH_LIST - expands to a whitespace separated list of C++ +dnl compilers for use with AC_PROG_CXX that is more suitable for HPC software +dnl packages +AC_DEFUN([PAC_CXX_SEARCH_LIST],[$CCC icpc pgCC xlC pathCC g++ clang++ c++ cc++ cxx CC cl]) +dnl PAC_PROG_CXX - reprioritize the C++ compiler search order +dnl NOTE: this macro suffers from a basically intractable "expanded before it +dnl was required" problem when libtool is also used +AC_DEFUN([PAC_PROG_CXX],[ + PAC_PUSH_FLAG([CXXFLAGS]) + # This test uses the list from a recent PROG_CXX, but with the + # addition of the Portland group, IBM, and Intel C++ compilers + # (While the Intel icc compiler will compile C++ programs, it will + # not *link* C++ object files unless there is at least one C++ source + # file present on the command that performs the linking. icpc is the + # Intel C++ compiler that both compiles and links C++ programs) + AC_PROG_CXX([PAC_CXX_SEARCH_LIST]) + PAC_POP_FLAG([CXXFLAGS]) +]) + +dnl This is from crypt.to/autoconf-archive, slightly modified. +dnl It defines bool as int if it is not availalbe +dnl +AC_DEFUN([AX_CXX_BOOL], +[AC_CACHE_CHECK(whether the compiler recognizes bool as a built-in type, +ac_cv_cxx_bool, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ +int f(int x){return 1;} +int f(char x){return 1;} +int f(bool x){return 1;} +],[bool b = true; return f(b);], + ac_cv_cxx_bool=yes, ac_cv_cxx_bool=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_bool" != yes; then + AC_DEFINE(bool,int,[define if bool is a built-in type]) +fi +]) + +dnl This is from crypt.to/autoconf-archive, slightly modified (name defined) +dnl +AC_DEFUN([AX_CXX_EXCEPTIONS], +[AC_CACHE_CHECK(whether the compiler supports exceptions, +ac_cv_cxx_exceptions, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE(,[try { throw 1; } catch (int i) { return i; }], + ac_cv_cxx_exceptions=yes, ac_cv_cxx_exceptions=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_exceptions" = yes; then + AC_DEFINE(HAVE_CXX_EXCEPTIONS,,[define if the compiler supports exceptions]) +fi +]) + +dnl This is from crypt.to/autoconf-archive +dnl +AC_DEFUN([AX_CXX_NAMESPACES], +[AC_CACHE_CHECK(whether the compiler implements namespaces, +ac_cv_cxx_namespaces, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([namespace Outer { namespace Inner { int i = 0; }}], + [using namespace Outer::Inner; return i;], + ac_cv_cxx_namespaces=yes, ac_cv_cxx_namespaces=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_namespaces" = yes; then + AC_DEFINE(HAVE_NAMESPACES,,[define if the compiler implements namespaces]) +fi +]) + +dnl Some compilers support namespaces but don't know about std +dnl +AC_DEFUN([AX_CXX_NAMESPACE_STD], +[AC_REQUIRE([AX_CXX_NAMESPACES]) +AC_CACHE_CHECK(whether the compiler implements the namespace std, +ac_cv_cxx_namespace_std, +[ac_cv_cxx_namespace_std=no +if test "$ac_cv_cxx_namespaces" = yes ; then + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ +#include +using namespace std;], + [cout << "message\n";], + ac_cv_cxx_namespace_std=yes, ac_cv_cxx_namespace_std=no) + AC_LANG_RESTORE +fi +]) +if test "$ac_cv_cxx_namespace_std" = yes; then + AC_DEFINE(HAVE_NAMESPACE_STD,,[define if the compiler implements namespace std]) +fi +]) + +dnl/*D +dnl PAC_CXX_CHECK_COMPILER_OPTION - Check that a C++ compiler option is +dnl accepted without warning messages +dnl +dnl Synopsis: +dnl PAC_CXX_CHECK_COMPILER_OPTION(optionname,action-if-ok,action-if-fail) +dnl +dnl Output Effects: +dnl +dnl If no actions are specified, a working value is added to 'CXXOPTIONS' +dnl +dnl Notes: +dnl This is now careful to check that the output is different, since +dnl some compilers are noisy. +dnl +dnl We are extra careful to prototype the functions in case compiler options +dnl that complain about poor code are in effect. +dnl +dnl Because this is a long script, we have ensured that you can pass a +dnl variable containing the option name as the first argument. +dnl D*/ +AC_DEFUN([PAC_CXX_CHECK_COMPILER_OPTION],[ +AC_MSG_CHECKING([whether C++ compiler accepts option $1]) +pac_opt="$1" +AC_LANG_PUSH([C++]) +CXXFLAGS_orig="$CXXFLAGS" +CXXFLAGS_opt="$pac_opt $CXXFLAGS" +pac_result="unknown" + +AC_LANG_CONFTEST([AC_LANG_PROGRAM()]) +CXXFLAGS="$CXXFLAGS_orig" +rm -f pac_test1.log +PAC_LINK_IFELSE_LOG([pac_test1.log], [], [ + CXXFLAGS="$CXXFLAGS_opt" + rm -f pac_test2.log + PAC_LINK_IFELSE_LOG([pac_test2.log], [], [ + PAC_RUNLOG_IFELSE([diff -b pac_test1.log pac_test2.log], + [pac_result=yes],[pac_result=no]) + ],[ + pac_result=no + ]) +], [ + pac_result=no +]) +AC_MSG_RESULT([$pac_result]) +dnl Delete the conftest created by AC_LANG_CONFTEST. +rm -f conftest.$ac_ext + +if test "$pac_result" = "yes" ; then + AC_MSG_CHECKING([whether routines compiled with $pac_opt can be linked with ones compiled without $pac_opt]) + pac_result=unknown + CXXFLAGS="$CXXFLAGS_orig" + rm -f pac_test3.log + PAC_COMPILE_IFELSE_LOG([pac_test3.log], [ + AC_LANG_SOURCE([ + int foo(void); + int foo(void){return 0;} + ]) + ],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $LIBS" + + CXXFLAGS="$CXXFLAGS_opt" + rm -f pac_test4.log + PAC_LINK_IFELSE_LOG([pac_test4.log], [AC_LANG_PROGRAM()], [ + PAC_RUNLOG_IFELSE([diff -b pac_test2.log pac_test4.log], + [pac_result=yes], [pac_result=no]) + ],[ + pac_result=no + ]) + LIBS="$saved_LIBS" + rm -f pac_conftest.$OBJEXT + ],[ + pac_result=no + ]) + AC_MSG_RESULT([$pac_result]) + rm -f pac_test3.log pac_test4.log +fi +rm -f pac_test1.log pac_test2.log + +dnl Restore CXXFLAGS before 2nd/3rd argument commands are executed, +dnl as 2nd/3rd argument command could be modifying CXXFLAGS. +CXXFLAGS="$CXXFLAGS_orig" +if test "$pac_result" = "yes" ; then + ifelse([$2],[],[CXXOPTIONS="$CXXOPTIONS $1"],[$2]) +else + ifelse([$3],[],[:],[$3]) +fi +AC_LANG_POP([C++]) +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_f77.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_f77.m4 new file mode 100644 index 0000000000..92d310b0f2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_f77.m4 @@ -0,0 +1,1487 @@ +dnl PAC_F77_SEARCH_LIST - expands to a whitespace separated list of fortran 77 +dnl compilers for use with AC_PROG_F77 that is more suitable for HPC software +dnl packages +AC_DEFUN([PAC_F77_SEARCH_LIST],[ifort pgf77 af77 xlf frt cf77 fort77 fl32 fort ifc efc ftn gfortran f77 g77]) +dnl PAC_PROG_F77 - reprioritize the F77 compiler search order +dnl NOTE: this macro suffers from a basically intractable "expanded before it +dnl was required" problem when libtool is also used +AC_DEFUN([PAC_PROG_F77],[ +PAC_PUSH_FLAG([FFLAGS]) +AC_PROG_F77([PAC_F77_SEARCH_LIST]) +PAC_POP_FLAG([FFLAGS]) +]) +dnl +dnl/*D +dnl PAC_PROG_F77_NAME_MANGLE - Determine how the Fortran compiler mangles +dnl names +dnl +dnl Synopsis: +dnl PAC_PROG_F77_NAME_MANGLE([action]) +dnl +dnl Output Effect: +dnl If no action is specified, one of the following names is defined: +dnl.vb +dnl If fortran names are mapped: +dnl lower -> lower F77_NAME_LOWER +dnl lower -> lower_ F77_NAME_LOWER_USCORE +dnl lower -> UPPER F77_NAME_UPPER +dnl lower_lower -> lower__ F77_NAME_LOWER_2USCORE +dnl mixed -> mixed F77_NAME_MIXED +dnl mixed -> mixed_ F77_NAME_MIXED_USCORE +dnl mixed -> UPPER@STACK_SIZE F77_NAME_UPPER_STDCALL +dnl.ve +dnl If an action is specified, it is executed instead. +dnl +dnl Notes: +dnl We assume that if lower -> lower (any underscore), upper -> upper with the +dnl same underscore behavior. Previous versions did this by +dnl compiling a Fortran program and running strings -a over it. Depending on +dnl strings is a bad idea, so instead we try compiling and linking with a +dnl C program, since that is why we are doing this anyway. A similar approach +dnl is used by FFTW, though without some of the cases we check (specifically, +dnl mixed name mangling). STD_CALL not only specifies a particular name +dnl mangling convention (adding the size of the calling stack into the function +dnl name, but also the stack management convention (callee cleans the stack, +dnl and arguments are pushed onto the stack from right to left) +dnl +dnl One additional problem is that some Fortran implementations include +dnl references to the runtime (like pgf90_compiled for the pgf90 compiler +dnl used as the "Fortran 77" compiler). This is not yet solved. +dnl +dnl D*/ +dnl +AC_DEFUN([PAC_PROG_F77_NAME_MANGLE],[ +AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS]) +AC_CACHE_CHECK([for Fortran 77 name mangling], +pac_cv_prog_f77_name_mangle,[ +# Initialize pac_found to indicate if name mangling scheme has been found +pac_found=no +AC_LANG_PUSH([Fortran 77]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + subroutine MY_name( ii ) + return + end + ]) +],[ + PAC_RUNLOG([mv conftest.$OBJEXT f77conftest.$OBJEXT]) + saved_LIBS="$LIBS" + dnl FLIBS is set by AC_F77_LIBRARY_LDFLAGS + LIBS="f77conftest.$OBJEXT $FLIBS $LIBS" + AC_LANG_PUSH([C]) + for call in "" __stdcall ; do + for sym in my_name_ my_name__ my_name MY_NAME MY_name MY_name_ NONE ; do + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([extern void ${call} ${sym}(int);],[${sym}(0);]) + ],[ + pac_found=yes + break + ]) + done + test "$pac_found" = "yes" && break + done + AC_LANG_POP([C]) + LIBS="$saved_LIBS" + rm -f f77conftest.$OBJEXT +]) +AC_LANG_POP([Fortran 77]) +dnl +# If we got to here and pac_cv_prog_f77_name_mangle is still NOT definable, +# it may be that the programs have to be linked with the Fortran compiler, +# not the C compiler. Try reversing the language used for the test +if test "$pac_found" != "yes" ; then + AC_LANG_PUSH([C]) + for call in "" __stdcall ; do + for sym in my_name_ my_name__ my_name MY_NAME MY_name MY_name_ NONE ; do + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([void ${call} ${sym}(int a) {}]) + ],[ + PAC_RUNLOG([mv conftest.$OBJEXT cconftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="cconftest.$OBJEXT $LIBS" + AC_LANG_PUSH([Fortran 77]) + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([],[ call my_name(0)]) + ],[ + pac_found=yes + ]) + AC_LANG_POP([Fortran 77]) + LIBS="$saved_LIBS" + rm -f cconftest.$OBJEXT + test "$pac_found" = "yes" && break + ]) + done + test "$pac_found" = "yes" && break + done + AC_LANG_POP([C]) +fi +if test "$pac_found" = "yes" ; then + case ${sym} in + my_name_) + pac_cv_prog_f77_name_mangle="lower uscore" ;; + my_name__) + pac_cv_prog_f77_name_mangle="lower 2uscore" ;; + my_name) + pac_cv_prog_f77_name_mangle="lower" ;; + MY_NAME) + pac_cv_prog_f77_name_mangle="upper" ;; + MY_name) + pac_cv_prog_f77_name_mangle="mixed" ;; + MY_name_) + pac_cv_prog_f77_name_mangle="mixed uscore" ;; + *) + pac_cv_prog_f77_name_mangle="" + pac_found=no; + ;; + esac + if test "X$pac_cv_prog_f77_name_mangle" != "X" ; then + if test "$call" = "__stdcall" ; then + pac_cv_prog_f77_name_mangle="$pac_cv_prog_f77_name_mangle stdcall" + fi + fi +fi +]) +dnl Endof ac_cache_check +case $pac_cv_prog_f77_name_mangle in + *stdcall) + F77_STDCALL="__stdcall" ;; + *) + F77_STDCALL="" ;; +esac +# Get the standard call definition +# FIXME: This should use F77_STDCALL, not STDCALL (non-conforming name) +F77_STDCALL="$call" +AC_DEFINE_UNQUOTED(STDCALL,[$F77_STDCALL],[Define calling convention]) + +# new_name="`echo $name | tr ' ' '_' | tr [a-z] [A-Z]`" +# We could have done the character conversion with 'tr' +# which may not be portable, e.g. solaris's /usr/ucb/bin/tr. +# So use a conservative approach. + +# Replace blank with underscore +name_scheme="`echo $pac_cv_prog_f77_name_mangle | sed 's% %_%g'`" +# Turn lowercase into uppercase. +name_scheme="`echo $name_scheme | sed -e 'y%abcdefghijklmnopqrstuvwxyz%ABCDEFGHIJKLMNOPQRSTUVWXYZ%'`" +F77_NAME_MANGLE="F77_NAME_${name_scheme}" +AC_DEFINE_UNQUOTED([$F77_NAME_MANGLE]) +AC_SUBST(F77_NAME_MANGLE) +if test "X$pac_cv_prog_f77_name_mangle" = "X" ; then + AC_MSG_WARN([Unknown Fortran naming scheme]) +fi +dnl +dnl Define the macros that is needed by AC_DEFINE_UNQUOTED([$F77_NAME_MANGLE]) +AH_TEMPLATE([F77_NAME_LOWER], + [Fortran names are lowercase with no trailing underscore]) +AH_TEMPLATE([F77_NAME_LOWER_USCORE], + [Fortran names are lowercase with one trailing underscore]) +AH_TEMPLATE([F77_NAME_LOWER_2USCORE], + [Fortran names are lowercase with two trailing underscores]) +AH_TEMPLATE([F77_NAME_MIXED], + [Fortran names preserve the original case]) +AH_TEMPLATE([F77_NAME_MIXED_USCORE], + [Fortran names preserve the original case with one trailing underscore]) +AH_TEMPLATE([F77_NAME_UPPER], + [Fortran names are uppercase]) +AH_TEMPLATE([F77_NAME_LOWER_STDCALL], + [Fortran names are lowercase with no trailing underscore in stdcall]) +AH_TEMPLATE([F77_NAME_LOWER_USCORE_STDCALL], + [Fortran names are lowercase with one trailing underscore in stdcall]) +AH_TEMPLATE([F77_NAME_LOWER_2USCORE_STDCALL], + [Fortran names are lowercase with two trailing underscores in stdcall]) +AH_TEMPLATE([F77_NAME_MIXED_STDCALL], + [Fortran names preserve the original case in stdcall]) +AH_TEMPLATE([F77_NAME_MIXED_USCORE_STDCALL], + [Fortran names preserve the original case with one trailing underscore in stdcall]) +AH_TEMPLATE([F77_NAME_UPPER_STDCALL], + [Fortran names are uppercase in stdcall]) +]) +dnl +dnl/*D +dnl PAC_PROG_F77_CHECK_SIZEOF - Determine the size in bytes of a Fortran +dnl type +dnl +dnl Synopsis: +dnl PAC_PROG_F77_CHECK_SIZEOF(type,[cross-size]) +dnl +dnl Output Effect: +dnl Sets SIZEOF_F77_uctype to the size if bytes of type. +dnl If type is unknown, the size is set to 0. +dnl If cross-compiling, the value cross-size is used (it may be a variable) +dnl For example 'PAC_PROG_F77_CHECK_SIZEOF(real)' defines +dnl 'SIZEOF_F77_REAL' to 4 on most systems. The variable +dnl 'pac_cv_sizeof_f77_' (e.g., 'pac_cv_sizeof_f77_real') is also set to +dnl the size of the type. +dnl If the corresponding variable is already set, that value is used. +dnl If the name has an '*' in it (e.g., 'integer*4'), the defined name +dnl replaces that with an underscore (e.g., 'SIZEOF_F77_INTEGER_4'). +dnl +dnl Notes: +dnl If the 'cross-size' argument is not given, 'autoconf' will issue an error +dnl message. You can use '0' to specify undetermined. +dnl +dnl D*/ +AC_DEFUN([PAC_PROG_F77_CHECK_SIZEOF],[ +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS]) +changequote(<<, >>)dnl +dnl The name to #define. +dnl dnl If the arg value contains a variable, we need to update that +define(<>, translit(sizeof_f77_$1, [a-z *], [A-Z__]))dnl +dnl The cache variable name. +define(<>, translit(pac_cv_f77_sizeof_$1, [ *], [__]))dnl +changequote([, ])dnl +AC_CACHE_CHECK([for size of Fortran type $1],PAC_CV_NAME,[ +AC_REQUIRE([PAC_PROG_F77_NAME_MANGLE]) +AC_LANG_PUSH([Fortran 77]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + subroutine isize() + $1 i(2) + call cisize( i(1), i(2) ) + end + ]) +],[ + # pac_f77compile_ok=yes + PAC_RUNLOG([mv conftest.$OBJEXT pac_f77conftest.$OBJEXT]) + # Save original LIBS, prepend previously generated object file to LIBS + saved_LIBS="$LIBS" + LIBS="pac_f77conftest.$OBJEXT $FLIBS $LIBS" + AC_LANG_PUSH([C]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif +#ifdef F77_NAME_UPPER +#define cisize_ CISIZE +#define isize_ ISIZE +#elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) +#define cisize_ cisize +#define isize_ isize +#endif +static int isize_val=0; +void cisize_(char *,char*); +void isize_(void); +void cisize_(char *i1p, char *i2p) +{ + isize_val = (int)(i2p - i1p); +} + ],[ + FILE *f = fopen("conftestval", "w"); + if (!f) return 1; + isize_(); + fprintf(f,"%d\n", isize_val); + ]) + dnl Endof ac_lang_program + ],[ + eval PAC_CV_NAME=`cat conftestval` + ],[ + eval PAC_CV_NAME=0 + ],[ + # Use -9999 as value to emit a warning message after the cache_check. + ifelse([$2],[],[eval PAC_CV_NAME=-9999],[eval PAC_CV_NAME=$2]) + ]) + dnl Endof ac_run_ifelse + AC_LANG_POP([C]) + LIBS="$saved_LIBS" + # remove previously generated object file. + rm -f pac_f77conftest.$OBJEXT +],[ + # pac_f77compile_ok=no + ifelse([$2],,eval PAC_CV_NAME=0,eval PAC_CV_NAME=$2) +]) Endof ac_compile_ifelse +AC_LANG_POP([Fortran 77]) +]) +dnl Endof ac_cache_check +if test "$PAC_CV_NAME" = "-9999" ; then + AC_MSG_WARN([No value provided for size of $1 when cross-compiling]) +fi +AC_DEFINE_UNQUOTED(PAC_TYPE_NAME,$PAC_CV_NAME,[Define size of PAC_TYPE_NAME]) +undefine([PAC_TYPE_NAME]) +undefine([PAC_CV_NAME]) +]) +dnl +dnl This version uses a Fortran program to link programs. +dnl This is necessary because some compilers provide shared libraries +dnl that are not within the default linker paths (e.g., our installation +dnl of the Portland Group compilers) +dnl +AC_DEFUN([PAC_PROG_F77_CHECK_SIZEOF_EXT],[ +changequote(<<,>>)dnl +dnl The name to #define. +dnl If the arg value contains a variable, we need to update that +define(<>, translit(sizeof_f77_$1, [a-z *], [A-Z__]))dnl +dnl The cache variable name. +define(<>, translit(pac_cv_f77_sizeof_$1, [ *], [__]))dnl +changequote([,])dnl +AC_CACHE_CHECK([for size of Fortran type $1],PAC_CV_NAME,[ +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([PAC_PROG_F77_NAME_MANGLE]) +dnl if test "$cross_compiling" = yes ; then +dnl ifelse([$2],[], +dnl [AC_MSG_WARN([No value provided for size of $1 when cross-compiling])], +dnl [eval PAC_CV_NAME=$2]) +dnl fi +AC_LANG_PUSH([C]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif +#ifdef F77_NAME_UPPER +#define cisize_ CISIZE +#define isize_ ISIZE +#elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) +#define cisize_ cisize +#define isize_ isize +#endif +int cisize_(char *,char*); +int cisize_(char *i1p, char *i2p) { + int isize_val=0; + FILE *f = fopen("conftestval", "w"); + if (!f) return 1; + isize_val = (int)(i2p - i1p); + fprintf(f,"%d\n", isize_val); + fclose(f); + return 0; +} + ]) + dnl Endof ac_lang_source +],[ + # pac_compile_ok=yes + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + # Save LIBS and prepend object file to LIBS + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $LIBS" + AC_LANG_PUSH([Fortran 77]) + AC_RUN_IFELSE([ + AC_LANG_SOURCE([ + program main + $1 a(2) + integer irc, cisize + irc = cisize(a(1),a(2)) + end + ]) + ],[ + eval PAC_CV_NAME=`cat conftestval` + ],[ + eval PAC_CV_NAME=0 + ],[ + # Use -9999 as value to emit a warning message after the cache_check. + ifelse([$2],[],[eval PAC_CV_NAME=-9999],[eval PAC_CV_NAME=$2]) + ]) + AC_LANG_POP([Fortran 77]) + LIBS="$saved_LIBS" + # remove previously generated object file. + rm -f pac_conftest.$OBJEXT +],[ + AC_MSG_WARN([Unable to compile the C routine for finding the size of a $1]) +]) +AC_LANG_POP([C]) +]) +dnl Endof ac_cache_check +if test "$PAC_CV_NAME" = "-9999" ; then + AC_MSG_WARN([No value provided for size of $1 when cross-compiling]) +fi +AC_DEFINE_UNQUOTED(PAC_TYPE_NAME,$PAC_CV_NAME,[Define size of PAC_TYPE_NAME]) +undefine([PAC_TYPE_NAME]) +undefine([PAC_CV_NAME]) +]) +dnl +dnl/*D +dnl PAC_PROG_F77_EXCLAIM_COMMENTS +dnl +dnl Synopsis: +dnl PAC_PROG_F77_EXCLAIM_COMMENTS([action-if-true],[action-if-false]) +dnl +dnl Notes: +dnl Check whether '!' may be used to begin comments in Fortran. +dnl +dnl This macro requires a version of autoconf `after` 2.13; the 'acgeneral.m4' +dnl file contains an error in the handling of Fortran programs in +dnl 'AC_TRY_COMPILE' (fixed in our local version). +dnl +dnl D*/ +AC_DEFUN([PAC_PROG_F77_EXCLAIM_COMMENTS],[ +AC_CACHE_CHECK([whether Fortran 77 accepts ! for comments], +pac_cv_prog_f77_exclaim_comments,[ +AC_LANG_PUSH([Fortran 77]) +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([],[! This is a comment]) +],[ + pac_cv_prog_f77_exclaim_comments="yes" +],[ + pac_cv_prog_f77_exclaim_comments="no" +]) +AC_LANG_POP([Fortran 77]) +]) +if test "$pac_cv_prog_f77_exclaim_comments" = "yes" ; then + ifelse([$1],[],[:],[$1]) +else + ifelse([$2],[],[:],[$2]) +fi +])dnl +dnl +dnl/*D +dnl PAC_F77_CHECK_COMPILER_OPTION - Check that a F77 compiler option is +dnl accepted without warning messages +dnl +dnl Synopsis: +dnl PAC_F77_CHECK_COMPILER_OPTION(optionname,action-if-ok,action-if-fail) +dnl +dnl Output Effects: +dnl +dnl If no actions are specified, a working value is added to 'FOPTIONS' +dnl +dnl Notes: +dnl This is now careful to check that the output is different, since +dnl some compilers are noisy. +dnl +dnl We are extra careful to prototype the functions in case compiler options +dnl that complain about poor code are in effect. +dnl +dnl Because this is a long script, we have ensured that you can pass a +dnl variable containing the option name as the first argument. +dnl D*/ +AC_DEFUN([PAC_F77_CHECK_COMPILER_OPTION],[ +AC_MSG_CHECKING([whether Fortran 77 compiler accepts option $1]) +pac_opt="$1" +AC_LANG_PUSH([Fortran 77]) +FFLAGS_orig="$FFLAGS" +FFLAGS_opt="$pac_opt $FFLAGS" +pac_result="unknown" + +AC_LANG_CONFTEST([AC_LANG_PROGRAM()]) +FFLAGS="$FFLAGS_orig" +rm -f pac_test1.log +PAC_LINK_IFELSE_LOG([pac_test1.log], [], [ + FFLAGS="$FFLAGS_opt" + rm -f pac_test2.log + PAC_LINK_IFELSE_LOG([pac_test2.log], [], [ + PAC_RUNLOG_IFELSE([diff -b pac_test1.log pac_test2.log], + [pac_result=yes], [pac_result=no]) + ],[ + pac_result=no + ]) +], [ + pac_result=no +]) +AC_MSG_RESULT([$pac_result]) +dnl Delete the conftest created by AC_LANG_CONFTEST. +rm -f conftest.$ac_ext +# +if test "$pac_result" = "yes" ; then + AC_MSG_CHECKING([whether routines compiled with $pac_opt can be linked with ones compiled without $pac_opt]) + pac_result=unknown + FFLAGS="$FFLAGS_orig" + rm -f pac_test3.log + PAC_COMPILE_IFELSE_LOG([pac_test3.log], [ + AC_LANG_SOURCE([ + subroutine try() + end + ]) + ],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $LIBS" + + FFLAGS="$FFLAGS_opt" + rm -f pac_test4.log + PAC_LINK_IFELSE_LOG([pac_test4.log], [AC_LANG_PROGRAM()], [ + PAC_RUNLOG_IFELSE([diff -b pac_test2.log pac_test4.log], + [pac_result=yes], [pac_result=no]) + ],[ + pac_result=no + ]) + LIBS="$saved_LIBS" + rm -f pac_conftest.$OBJEXT + ],[ + pac_result=no + ]) + AC_MSG_RESULT([$pac_result]) + rm -f pac_test3.log pac_test4.log +fi +rm -f pac_test1.log pac_test2.log + +dnl Restore FFLAGS before 2nd/3rd argument commands are executed, +dnl as 2nd/3rd argument command could be modifying FFLAGS. +FFLAGS="$FFLAGS_orig" +if test "$pac_result" = "yes" ; then + ifelse([$2],[],[FOPTIONS="$FOPTIONS $1"],[$2]) +else + ifelse([$3],[],[:],[$3]) +fi +AC_LANG_POP([Fortran 77]) +]) +dnl +dnl/*D +dnl PAC_PROG_F77_LIBRARY_DIR_FLAG - Determine the flag used to indicate +dnl the directories to find libraries in +dnl +dnl Notes: +dnl Many compilers accept '-Ldir' just like most C compilers. +dnl Unfortunately, some (such as some HPUX Fortran compilers) do not, +dnl and require instead either '-Wl,-L,dir' or something else. This +dnl command attempts to determine what is accepted. The flag is +dnl placed into 'F77_LIBDIR_LEADER'. +dnl +dnl D*/ +dnl +dnl An earlier version of this only tried the arguments without using +dnl a library. This failed when the HP compiler complained about the +dnl arguments, but produced an executable anyway. +AC_DEFUN([PAC_PROG_F77_LIBRARY_DIR_FLAG],[ +AC_CACHE_CHECK([for Fortran 77 flag for library directories], +pac_cv_prog_f77_library_dir_flag,[ +AC_LANG_PUSH([Fortran 77]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + subroutine f1conf + end + ]) +],[ + # pac_f77compile_ok=yes + PAC_RUNLOG([mv conftest.$OBJEXT pac_f77conftest.$OBJEXT]) + PAC_RUNLOG([test -d conftestdir || mkdir conftestdir]) + PAC_RUNLOG([${AR-ar} ${AR_FLAGS-cr} conftestdir/libf77conftest.a pac_f77conftest.$OBJEXT]) + PAC_RUNLOG([${RANLIB-ranlib} conftestdir/libf77conftest.a]) + # Save original LIBS, prepend previously generated object file to LIBS + saved_LIBS="$LIBS" + LIBS="-lf77conftest $LIBS" + saved_LDFLAGS="$LDFLAGS" + pac_cv_prog_f77_library_dir_flag="none" + for ldir in "-L" "-Wl,-L," ; do + LDFLAGS="${ldir}conftestdir $saved_LDFLAGS" + AC_LINK_IFELSE([ + AC_LANG_SOURCE([ + program main + call f1conf + end + ]) + ],[pac_cv_prog_f77_library_dir_flag="$ldir";break]) + done + LDFLAGS="$saved_LDFLAGS" + LIBS="$saved_LIBS" + rm -rf conftestdir + rm -f pac_f77conftest.$OBJEXT +],[]) +AC_LANG_POP([Fortran 77]) +]) +dnl Endof ac_cache_check +if test "X$pac_cv_prog_f77_library_dir_flag" != "Xnone" ; then + F77_LIBDIR_LEADER="$pac_cv_prog_f77_library_dir_flag" + AC_SUBST(F77_LIBDIR_LEADER) +fi +]) +dnl +dnl/*D +dnl PAC_PROG_F77_HAS_INCDIR - Check whether Fortran accepts -Idir flag +dnl +dnl Syntax: +dnl PAC_PROG_F77_HAS_INCDIR(directory,action-if-true,action-if-false) +dnl +dnl Output Effect: +dnl Sets 'F77_INCDIR' to the flag used to choose the directory. +dnl +dnl Notes: +dnl This refers to the handling of the common Fortran include extension, +dnl not to the use of '#include' with the C preprocessor. +dnl If directory does not exist, it will be created. In that case, the +dnl directory should be a direct descendant of the current directory. +dnl +dnl D*/ +AC_DEFUN([PAC_PROG_F77_HAS_INCDIR],[ +ifelse([$1],[],[checkdir=f77tmpdir],[checkdir=$1;checkdir_is_given=yes]) +AC_CACHE_CHECK([for include directory flag for Fortran], +pac_cv_prog_f77_has_incdir,[ +test -d $checkdir || mkdir $checkdir +dnl PAC_RUNLOG([echo ' call sub()' > $checkdir/conftestf.h]) +echo ' call sub()' > $checkdir/conftestf.h +AC_LANG_PUSH([Fortran 77]) +saved_FFLAGS="$FFLAGS" +pac_cv_prog_f77_has_incdir="none" +# SGI wants -Wf,-I +for idir in "-I" "-Wf,-I" ; do + FFLAGS="${idir} $checkdir $saved_FFLAGS" + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + program main + include 'conftestf.h' + end + ]) + ],[pac_cv_prog_f77_has_incdir="$idir"; break]) +done +FFLAGS="$saved_FFLAGS" +AC_LANG_POP([Fortran 77]) +if test "$checkdir_is_given" = "yes" ; then + rm -f $checkdir/conftestf.h +else + rm -rf $checkdir +fi +]) +dnl Endof ac_cache_check +if test "X$pac_cv_prog_f77_has_incdir" != "Xnone" ; then + F77_INCDIR="$pac_cv_prog_f77_has_incdir" + AC_SUBST(F77_INCDIR) +fi +]) +dnl +dnl/*D +dnl PAC_PROG_F77_ALLOWS_UNUSED_EXTERNALS - Check whether the Fortran compiler +dnl allows unused and undefined functions to be listed in an external +dnl statement +dnl +dnl Syntax: +dnl PAC_PROG_F77_ALLOWS_UNUSED_EXTERNALS(action-if-true,action-if-false) +dnl +dnl D*/ +AC_DEFUN([PAC_PROG_F77_ALLOWS_UNUSED_EXTERNALS],[ +AC_CACHE_CHECK([whether Fortran allows unused externals], +pac_cv_prog_f77_allows_unused_externals,[ +AC_LANG_PUSH([Fortran 77]) +AC_LINK_IFELSE([ + AC_LANG_SOURCE([ + program main + external bar + end + ]) +],[ + pac_cv_prog_f77_allows_unused_externals="yes" +],[ + pac_cv_prog_f77_allows_unused_externals="no" +]) +AC_LANG_POP([Fortran 77]) +]) +dnl Endof ac_cache_check +if test "X$pac_cv_prog_f77_allows_unused_externals" = "Xyes" ; then + ifelse([$1],[],[:],[$1]) +else + ifelse([$2],[],[:],[$2]) +fi +]) +dnl PAC_PROG_F77_RUN_PROC_FROM_C( c main program, fortran routine, +dnl [action-if-works], [action-if-fails], +dnl [cross-action] ) +dnl Fortran routine MUST be named ftest unless you include code +dnl to select the appropriate Fortran name. +dnl +AC_DEFUN([PAC_PROG_F77_RUN_PROC_FROM_C],[ +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS]) +AC_LANG_PUSH([Fortran 77]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([$2]) +],[ + # pac_f77compile_ok=yes + PAC_RUNLOG([mv conftest.$OBJEXT pac_f77conftest.$OBJEXT]) + # Save original LIBS, prepend previously generated object file to LIBS + saved_LIBS="$LIBS" + LIBS="pac_f77conftest.$OBJEXT $FLIBS $LIBS" + AC_LANG_PUSH([C]) + AC_RUN_IFELSE([ + AC_LANG_SOURCE([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif +#ifdef F77_NAME_UPPER +#define ftest_ FTEST +#elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) +#define ftest_ ftest +#endif +$1 + ]) + ],[ + ifelse([$3],[],[:],[$3]) + ],[ + ifelse([$4],[],[:],[$4]) + ],[ + ifelse([$5],[],[:],[$5]) + ]) + AC_LANG_POP([C]) + LIBS="$saved_LIBS" + rm -f pac_f77conftest.$OBJEXT +],[ +]) +AC_LANG_POP([Fortran 77]) +]) +dnl PAC_PROG_F77_IN_C_LIBS +dnl +dnl Find the essential libraries that are needed to use the C linker to +dnl create a program that includes a trival Fortran code. +dnl +dnl For example, all pgf90 compiled objects include a reference to the +dnl symbol pgf90_compiled, found in libpgf90 . +dnl +dnl There is an additional problem. To *run* programs, we may need +dnl additional arguments; e.g., if shared libraries are used. Even +dnl with autoconf 2.52, the autoconf macro to find the library arguments +dnl doesn't handle this, either by detecting the use of -rpath or +dnl by trying to *run* a trivial program. It only checks for *linking*. +dnl +dnl +AC_DEFUN([PAC_PROG_F77_IN_C_LIBS],[ +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS]) +AC_MSG_CHECKING([for which Fortran libraries are needed to link C with Fortran]) +F77_IN_C_LIBS="invalid" +AC_LANG_PUSH([Fortran 77]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + subroutine ftest + end + ]) +],[ + # pac_f77compile_ok=yes + PAC_RUNLOG([mv conftest.$OBJEXT pac_f77conftest.$OBJEXT]) + # Save original LIBS, prepend previously generated object file to LIBS + saved_LIBS="$LIBS" + LIBS="pac_f77conftest.$OBJEXT $FLIBS $saved_LIBS" + AC_LANG_PUSH([C]) + + # Create conftest for all link tests. + AC_LANG_CONFTEST([ + AC_LANG_PROGRAM([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif + ],[ +#ifdef F77_NAME_UPPER +#define ftest_ FTEST +#elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) +#define ftest_ ftest +#endif +extern void ftest_(void); +ftest_(); + ]) + ]) + + F77_IN_C_LIBS="" + AC_LINK_IFELSE([],[:],[ + flibdirs=`echo $FLIBS | tr ' ' '\012' | grep '\-L' | tr '\012' ' '` + fliblibs=`echo $FLIBS | tr ' ' '\012' | grep -v '\-L' | tr '\012' ' '` + for flibs in $fliblibs ; do + LIBS="pac_f77conftest.$OBJEXT $flibdirs $flibs $saved_LIBS" + AC_LINK_IFELSE([],[F77_IN_C_LIBS="$flibdirs $flibs"; break]) + done + if test "X$F77_IN_C_LIBS" = "X" ; then + flibscat="" + for flibs in $fliblibs ; do + flibscat="$flibscat $flibs" + LIBS="pac_f77conftest.$OBJEXT $flibdirs $flibscat $saved_LIBS" + AC_LINK_IFELSE([],[F77_IN_C_LIBS="$flibdirs $flibscat";break]) + done + fi + ]) + + # remove conftest created by ac_lang_conftest + rm -f conftest.$ac_ext + AC_LANG_POP([C]) + LIBS="$saved_LIBS" + rm -f pac_f77conftest.$OBJEXT +]) +AC_LANG_POP([Fortran 77]) +if test "X$F77_IN_C_LIBS" = "X" ; then + AC_MSG_RESULT(none) +else + AC_MSG_RESULT($F77_IN_C_LIBS) +fi +]) +dnl +dnl Test to see if we should use C or Fortran to link programs whose +dnl main program is in Fortran. We may find that neither work because +dnl we need special libraries in each case. +dnl +AC_DEFUN([PAC_PROG_F77_LINKER_WITH_C],[ +AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS]) +AC_MSG_CHECKING([for linker for Fortran main program]) +dnl Create a C program that uses multiplication and division +dnl in case that requires special libraries +AC_LANG_PUSH([C]) +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([],[long long a;]) +],[ + AC_DEFINE(HAVE_LONG_LONG,1,[Define if long long allowed]) +]) +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ +#ifdef HAVE_LONG_LONG +int f(int a, long long b) { int c; c = a * ( b / 3 ) / (b-1); return c ; } +#else +int f(int a, long b) { int c; c = a * b / (b-1); return c ; } +#endif + ]) +]) +AC_LANG_POP([C]) + +dnl Create a Fortran program for test +AC_LANG_PUSH([Fortran 77]) +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + program main + double precision d + print *, "hi" + end + ]) +]) +AC_LANG_POP([Fortran 77]) + +dnl Initialize flags +pac_linkwithf77=no +pac_linkwithC=no + +dnl Use F77 as a linker to compile a Fortran main and C subprogram. +if test "$pac_linkwithC" != "yes" ; then + AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $saved_LIBS" + AC_LANG_PUSH([Fortran 77]) + AC_LINK_IFELSE([],[ + AC_MSG_RESULT([Use Fortran to link programs]) + pac_linkwithf77=yes + ]) + AC_LANG_POP([Fortran 77]) + LIBS="$saved_LIBS" + rm -f pac_conftest.$OBJEXT + ]) + AC_LANG_POP([C]) +fi + +dnl Use C as a linker and FLIBS to compile a Fortran main and C subprogram. +if test "$pac_linkwithf77" != "yes" ; then + AC_LANG_PUSH([Fortran 77]) + AC_COMPILE_IFELSE([],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_f77conftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="pac_f77conftest.$OBJEXT $FLIBS $saved_LIBS" + AC_LANG_PUSH([C]) + AC_LINK_IFELSE([],[ + pac_linkwithC=yes + AC_MSG_RESULT([Use C with FLIBS to link programs]) + F77LINKER="$CC" + F77_LDFLAGS="$F77_LDFLAGS $FLIBS" + ]) + AC_LANG_POP([C]) + LIBS="$saved_LIBS" + rm -f pac_f77conftest.$OBJEXT + ]) + AC_LANG_POP([Fortran 77]) +fi + +AC_LANG_PUSH([Fortran 77]) +rm -f conftest.$ac_ext +AC_LANG_POP([Fortran 77]) + +AC_LANG_PUSH([C]) +rm -f conftest.$ac_ext +AC_LANG_POP([C]) + +if test "$pac_linkwithf77" != "yes" -a "$pac_linkwithC" != "yes" ; then + AC_MSG_ERROR([Could not determine a way to link a Fortran test program!]) +fi +]) +dnl +dnl Check to see if a C program can be linked when using the libraries +dnl needed by C programs +dnl +AC_DEFUN([PAC_PROG_F77_CHECK_FLIBS],[ +AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS]) +AC_MSG_CHECKING([whether $CC links with FLIBS found by autoconf]) +AC_LANG_PUSH([C]) +# Create a simple C program for the tests. +AC_LANG_CONFTEST([ + AC_LANG_PROGRAM([],[int a;]) +]) +# Try to link a C program with all of these libraries +saved_LIBS="$LIBS" +LIBS="$FLIBS $saved_LIBS" +AC_LINK_IFELSE([],[ + AC_MSG_RESULT([yes]) +],[ + AC_MSG_RESULT([no]) + AC_MSG_CHECKING([for which libraries can be used]) + pac_ldirs="" + pac_libs="" + pac_other="" + for name in $FLIBS ; do + case $name in + -l*) pac_libs="$pac_libs $name" ;; + -L*) pac_ldirs="$pac_ldirs $name" ;; + *) pac_other="$pac_other $name" ;; + esac + done + keep_libs="" + for name in $pac_libs ; do + LIBS="$saved_LIBS $pac_ldirs $pac_other $name" + AC_LINK_IFELSE([],[ + keep_libs="$keep_libs $name" + ]) + done + AC_MSG_RESULT($keep_libs) + FLIBS="$pac_ldirs $pac_other $keep_libs" +]) +LIBS="$saved_LIBS" +rm -f conftest.$ac_ext +AC_LANG_PUSH([C]) +]) +dnl +dnl Test for extra libraries needed when linking C routines that use +dnl stdio with Fortran. This test was created for OSX, which +dnl sometimes requires -lSystemStubs. If another library is needed, +dnl add it to F77_OTHER_LIBS +dnl +AC_DEFUN([PAC_PROG_F77_AND_C_STDIO_LIBS],[ +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([PAC_PROG_F77_NAME_MANGLE]) +# To simply the code in the cache_check macro, chose the routine name +# first, in case we need it +confname=conf1_ +case "$pac_cv_prog_f77_name_mangle" in + "lower underscore") confname=conf1_ ;; + "upper stdcall") confname=CONF1 ;; + "upper") confname=CONF1 ;; + "lower doubleunderscore") confname=conf1_ ;; + "lower") confname=conf1 ;; + "mixed underscore") confname=conf1_ ;; + "mixed") confname=conf1 ;; +esac + +AC_CACHE_CHECK([for libraries to link Fortran main with C stdio routines], +pac_cv_prog_f77_and_c_stdio_libs,[ +pac_cv_prog_f77_and_c_stdio_libs=unknown +AC_LANG_PUSH([C]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif +int $confname(int a) { + printf( "The answer is %d\n", a ); fflush(stdout); return 0; +} + ]) +],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + saved_LIBS="$LIBS" + AC_LANG_PUSH([Fortran 77]) + AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + program main + call conf1(0) + end + ]) + ]) + for extralib in "" "-lSystemStubs" ; do + LIBS="pac_conftest.$OBJEXT $saved_LIBS $extralib" + AC_LINK_IFELSE([],[ + pac_cv_prog_f77_and_c_stdio_libs="$extralib"; break + ]) + done + if test "X$pac_cv_prog_f77_and_c_stdio_libs" = "X" ; then + pac_cv_prog_f77_and_c_stdio_libs=none + fi + rm -f conftest.$ac_ext + AC_LANG_POP([Fortran 77]) + LIBS="$saved_LIBS" + rm -f pac_conftest.$OBJEXT +]) +AC_LANG_POP([C]) +]) +dnl Endof ac_cache_check +if test "$pac_cv_prog_f77_and_c_stdio_libs" != "none" \ + -a "$pac_cv_prog_f77_and_c_stdio_libs" != "unknown" ; then + F77_OTHER_LIBS="$F77_OTHER_LIBS $pac_cv_prog_f77_and_c_stdio_libs" +fi +]) +dnl +dnl Check that the FLIBS determined by AC_F77_LIBRARY_LDFLAGS is valid. +dnl That macro (at least as of autoconf 2.59) attempted to parse the output +dnl of the compiler when asked to be verbose; in the case of the Fujitsu +dnl frt Fortran compiler, it included files that frt looked for and then +dnl discarded because they did not exist. +dnl +AC_DEFUN([PAC_PROG_F77_FLIBS_VALID],[ +AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS]) +AC_MSG_CHECKING([whether $F77 accepts the FLIBS found by autoconf]) +pac_cv_f77_flibs_valid=unknown +AC_LANG_PUSH([Fortran 77]) +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + program main + end + ]) +]) +AC_LINK_IFELSE([],[ + AC_MSG_RESULT([yes]) +],[ + AC_MSG_RESULT([no]) + AC_MSG_CHECKING([for valid entries in FLIBS]) + goodFLIBS="" + saveFLIBS=$FLIBS + FLIBS="" + for arg in $saveFLIBS ; do + FLIBS="$goodFLIBS $arg" + AC_LINK_IFELSE([],[goodFLIBS=$FLIBS]) + done + FLIBS=$goodFLIBS + AC_MSG_RESULT($FLIBS) +]) +rm -f conftest.$ac_ext +AC_LANG_POP([Fortran 77]) +]) +dnl +dnl Check if the Fortran 77 and C objects are compatible in linking. +dnl e.g. On some intel x86_64 Mac, Fortran compiler's default binary format +dnl is different from C, so either -m64 or -m32 is needed in either CFLAGS +dnl or FFLAGS. +dnl +AC_DEFUN([PAC_PROG_F77_OBJ_LINKS_WITH_C],[ +AC_REQUIRE([AC_F77_LIBRARY_LDFLAGS]) +AC_MSG_CHECKING([whether Fortran 77 and C objects are compatible]) +AC_LANG_PUSH([C]) +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ +/* lower */ +void c_subpgm( int *rc ); +void c_subpgm( int *rc ) { *rc = 1; } + +/* lower underscore */ +void c_subpgm_( int *rc ); +void c_subpgm_( int *rc ) { *rc = 2; } + +/* upper */ +void C_SUBPGM( int *rc ); +void C_SUBPGM( int *rc ) { *rc = 3; } + +/* lower doubleunderscore */ +void c_subpgm__( int *rc ); +void c_subpgm__( int *rc ) { *rc = 4; } + +/* mixed */ +void C_subpgm( int *rc ); +void C_subpgm( int *rc ) { *rc = 5; } + +/* mixed underscore */ +void C_subpgm_( int *rc ); +void C_subpgm_( int *rc ) { *rc = 6; } + ]) +]) +AC_LANG_POP([C]) + +AC_LANG_PUSH([Fortran 77]) +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + program test + integer rc + rc = -1 + call c_subpgm( rc ) + write(6,*) "rc=", rc + end + ]) +]) +AC_LANG_POP([Fortran 77]) + +dnl Initialize flags +pac_linkwithf77=no +pac_linkwithC=no + +dnl Use F77 as a linker to compile a Fortran main and C subprogram. +if test "$pac_linkwithC" != "yes" ; then + AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $saved_LIBS" + AC_LANG_PUSH([Fortran 77]) + AC_LINK_IFELSE([],[ + pac_linkwithf77=yes + AC_MSG_RESULT([yes]) + ]) + AC_LANG_POP([Fortran 77]) + LIBS="$saved_LIBS" + if test "$pac_linkwithf77" = "yes" ; then + rm -f pac_conftest.$OBJEXT + fi + ]) + AC_LANG_POP([C]) +fi + +dnl Use C as a linker and FLIBS to compile a Fortran main and C subprogram. +if test "$pac_linkwithf77" != "yes" ; then + AC_LANG_PUSH([Fortran 77]) + AC_COMPILE_IFELSE([],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_f77conftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="pac_f77conftest.$OBJEXT $FLIBS $saved_LIBS" + AC_LANG_PUSH([C]) + AC_LINK_IFELSE([],[ + pac_linkwithC=yes + AC_MSG_RESULT([yes]) + ]) + AC_LANG_POP([C]) + LIBS="$saved_LIBS" + if test "$pac_linkwithC" = "yes" ; then + rm -f pac_f77conftest.$OBJEXT + fi + ]) + AC_LANG_POP([Fortran 77]) +fi + +AC_LANG_PUSH([Fortran 77]) +rm -f conftest.$ac_ext +AC_LANG_POP([Fortran 77]) + +AC_LANG_PUSH([C]) +rm -f conftest.$ac_ext +AC_LANG_POP([C]) + +if test "$pac_linkwithf77" != "yes" -a "$pac_linkwithC" != "yes" ; then + AC_MSG_RESULT(no) + AC_CHECK_PROG(FILE, file, file, []) + if test "X$FILE" != "X" ; then + fobjtype="`${FILE} pac_f77conftest.$OBJEXT | sed -e \"s|pac_f77conftest\.$OBJEXT||g\"`" + cobjtype="`${FILE} pac_conftest.$OBJEXT | sed -e \"s|pac_conftest\.$OBJEXT||g\"`" + if test "$fobjtype" != "$cobjtype" ; then + AC_MSG_ERROR([**** Incompatible Fortran and C Object File Types! **** +F77 Object File Type produced by \"${F77} ${FFLAGS}\" is : ${fobjtype}. + C Object File Type produced by \"${CC} ${CFLAGS}\" is : ${cobjtype}.]) + fi + fi +fi +]) +dnl +dnl /*D +dnl PAC_F77_WORKS_WITH_CPP +dnl +dnl Checks if Fortran 77 compiler works with C preprocessor +dnl +dnl Most systems allow the Fortran compiler to process .F and .F90 files +dnl using the C preprocessor. However, some systems either do not +dnl allow this or have serious bugs (OSF Fortran compilers have a bug +dnl that generates an error message from cpp). The following test +dnl checks to see if .F works, and if not, whether "cpp -P -C" can be used +dnl D*/ +AC_DEFUN([PAC_F77_WORKS_WITH_CPP],[ +AC_REQUIRE([AC_PROG_CPP]) +AC_MSG_CHECKING([whether Fortran 77 compiler processes .F files with C preprocessor]) +AC_LANG_PUSH([Fortran 77]) +saved_f77_ext=${ac_ext} +ac_ext="F" +saved_FFLAGS="$FFLAGS" +FFLAGS="$FFLAGS $CPPFLAGS" +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + program main +#define ASIZE 10 + integer a(ASIZE) + end + ]) +]) +AC_COMPILE_IFELSE([],[ + pac_cv_f77_accepts_F=yes + ifelse([$1],[],[],[$1=""]) +],[ + pac_cv_f77_accepts_F=no + ifelse([$1],[],[:],[$1="false"]) +]) +# Restore Fortran 77's ac_ext but not FFLAGS +ac_ext="$saved_f77_ext" + +if test "$pac_cv_f77_accepts_F" != "yes" ; then + pac_cpp_f77="$ac_cpp -C -P conftest.F > conftest.$ac_ext" + PAC_RUNLOG_IFELSE([$pac_cpp_f77],[ + if test -s conftest.${ac_ext} ; then + AC_COMPILE_IFELSE([],[ + pac_cv_f77_accepts_F="no, use cpp" + ifelse([$1],[],[],[$1="$CPP -C -P"]) + ],[]) + rm -f conftest.${ac_ext} + fi + ],[]) +fi +FFLAGS="$saved_FFLAGS" +rm -f conftest.F +AC_LANG_POP([Fortran 77]) +AC_MSG_RESULT([$pac_cv_f77_accepts_F]) +]) +dnl +dnl /*D +dnl PAC_PROG_F77_CRAY_POINTER - Check if Fortran 77 supports Cray-style pointer. +dnl If so, set pac_cv_prog_f77_has_pointer to yes +dnl and find out if any extra compiler flag is +dnl needed and set it as CRAYPTR_FFLAGS. +dnl i.e. CRAYPTR_FFLAGS is meaningful only if +dnl pac_cv_prog_f77_has_pointer = yes. +dnl +dnl Synopsis: +dnl PAC_PROG_F77_CRAY_POINTER([action-if-true],[action-if-false]) +dnl D*/ +AC_DEFUN([PAC_PROG_F77_CRAY_POINTER],[ +AC_CACHE_CHECK([whether Fortran 77 supports Cray-style pointer], +pac_cv_prog_f77_has_pointer,[ +AC_LANG_PUSH([Fortran 77]) +AC_LANG_CONFTEST([ + AC_LANG_PROGRAM([],[ + integer M + pointer (MPTR,M) + data MPTR/0/ + ]) +]) +saved_FFLAGS="$FFLAGS" +pac_cv_prog_f77_has_pointer=no +CRAYPTR_FFLAGS="" +for ptrflag in '' '-fcray-pointer' ; do + FFLAGS="$saved_FFLAGS $ptrflag" + AC_COMPILE_IFELSE([], [ + pac_cv_prog_f77_has_pointer=yes + CRAYPTR_FFLAGS="$ptrflag" + break + ]) +done +dnl Restore FFLAGS first, since user may not want to modify FFLAGS +FFLAGS="$saved_FFLAGS" +dnl remove conftest after ac_lang_conftest +rm -f conftest.$ac_ext +AC_LANG_POP([Fortran 77]) +]) +if test "$pac_cv_prog_f77_has_pointer" = "yes" ; then + AC_MSG_CHECKING([for Fortran 77 compiler flag for Cray-style pointer]) + if test "X$CRAYPTR_FFLAGS" != "X" ; then + AC_MSG_RESULT([$CRAYPTR_FFLAGS]) + else + AC_MSG_RESULT([none]) + fi + ifelse([$1],[],[:],[$1]) +else + ifelse([$2],[],[:],[$2]) +fi +]) +dnl +dnl +dnl PAC_F77_INIT_WORKS_WITH_C +dnl +AC_DEFUN([PAC_F77_INIT_WORKS_WITH_C],[ +AC_REQUIRE([AC_HEADER_STDC]) +AC_MSG_CHECKING([whether Fortran init will work with C]) +pac_f_init_works_with_c=unknown +AC_LANG_PUSH([Fortran 77]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + subroutine minit() + common /m1/ vc, vc2 + character*1 vc(1,1), vc2(1) + common /m2/ vd + integer vd + save /m1/, /m2/ + call minitc( vc, vc2, vd ) + end + ]) +],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_f77conftest.$OBJEXT]) + saved_LIBS="$LIBS" + # This test checks if Fortran init can be done in pure C environment, + # i.e. no FLIBS in linking, so don't put FLIBS in LIBS below + dnl LIBS="pac_f77conftest.$OBJEXT $FLIBS $LIBS" + LIBS="pac_f77conftest.$OBJEXT $LIBS" + AC_LANG_PUSH([C]) + AC_LINK_IFELSE([ + AC_LANG_SOURCE([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif +#ifdef F77_NAME_UPPER +#define minit_ MINIT +#elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) +#define minit_ minit +#endif +extern void minit_(void); +int main( int argc, char **argv ) +{ + minit_(); + return 0; +} +char *v1 = 0; +char *vc2 = 0; +int v2 = 0; +void minitc_( char *dv1, int d, char *dv2, int d2, int dv3 ); +void minitc_( char *dv1, int d, char *dv2, int d2, int dv3 ) +{ +v1 = dv1; +v2 = dv3; +vc2 = dv2; +*vc2 = ' '; +} + ]) + ],[pac_f_init_works_with_c=yes],[pac_f_init_works_with_c=no]) + AC_LANG_POP([C]) + LIBS="$saved_LIBS" + rm -f pac_f77conftest.$OBJEXT +]) +AC_LANG_POP([Fortran 77]) +AC_MSG_RESULT([$pac_f_init_works_with_c]) +]) +dnl +dnl PAC_F77_LOGICALS_IN_C(MPI_FINT) +dnl +dnl where MPI_FINT is the C type for Fortran integer. +dnl +dnl Use a Fortran main program. This simplifies some steps, +dnl since getting all of the Fortran libraries (including shared +dnl libraries that are not in the default library search path) can +dnl be tricky. Specifically, The PROG_F77_RUN_PROC_FROM_C failed with +dnl some installations of the Portland group compiler. +dnl +dnl We'd also like to check other values for .TRUE. and .FALSE. to see +dnl if the compiler allows (or uses) more than one value (some DEC compilers, +dnl for example, used the high (sign) bit to indicate true and false; the +dnl rest of the bits were ignored. For now, we'll assume that there are +dnl unique true and false values. +dnl +AC_DEFUN([PAC_F77_LOGICALS_IN_C],[ +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([PAC_PROG_F77_NAME_MANGLE]) +pac_mpi_fint="$1" +AC_MSG_CHECKING([for values of Fortran logicals]) +AC_CACHE_VAL(pac_cv_prog_f77_true_false_value,[ +pac_cv_prog_f77_true_false_value="" +AC_LANG_PUSH([C]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif +#if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS) +#include +#endif +#ifdef F77_NAME_UPPER +#define ftest_ FTEST +#elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) +#define ftest_ ftest +#endif +void ftest_( $pac_mpi_fint *, $pac_mpi_fint *); +void ftest_( $pac_mpi_fint *itrue, $pac_mpi_fint *ifalse ) +{ + FILE *f = fopen("conftestval","w"); + if (!f) exit(1); + fprintf( f, "%d %d\n", *itrue, *ifalse ); + fclose(f); +} + ]) +],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $saved_LIBS" + AC_LANG_PUSH([Fortran 77]) + AC_RUN_IFELSE([ + AC_LANG_SOURCE([ + program main + logical itrue, ifalse + itrue = .TRUE. + ifalse = .FALSE. + call ftest( itrue, ifalse ) + end + ]) + ],[ + pac_cv_prog_f77_true_false_value="`cat conftestval`" + ],[ + AC_MSG_WARN([Failed to build/run program to determine Fortran logical values.]) + ],[ + # Cross-Compiling. Allow the user to set the values + if test -n "$CROSS_F77_TRUE_VALUE" -a -n "$CROSS_F77_FALSE_VALUE" ; then + pac_cv_prog_f77_true_false_value="$CROSS_F77_TRUE_VALUE $CROSS_F77_FALSE_VALUE" + else + AC_MSG_WARN([Either CROSS_F77_TRUE_VALUE="$CROSS_F77_TRUE_VALUE" or CROSS_F77_FALSE_VALUE="$CROSS_F77_FALSE_VALUE" is not set.]) + fi + ]) + AC_LANG_POP([Fortran 77]) + LIBS="$saved_LIBS" + rm -f pac_conftest.$OBJEXT +]) +AC_LANG_POP([C]) +]) +dnl Endof ac_cache_val +if test "X$pac_cv_prog_f77_true_false_value" != "X" ; then + true_val="`echo $pac_cv_prog_f77_true_false_value | sed -e 's/ .*//g'`" + false_val="`echo $pac_cv_prog_f77_true_false_value | sed -e 's/.* *//g'`" + if test -n "$true_val" -a -n "$false_val" ; then + AC_MSG_RESULT([True is $true_val and False is $false_val]) + else + AC_MSG_RESULT([could not determine]) + fi +fi +if test -n "$true_val" -a -n "$false_val" ; then + AC_DEFINE(F77_TRUE_VALUE_SET,1,[Define if we know the value of Fortran true and false]) + AC_DEFINE_UNQUOTED(F77_TRUE_VALUE,$true_val,[The value of true in Fortran]) + AC_DEFINE_UNQUOTED(F77_FALSE_VALUE,$false_val,[The value of false in Fortran]) +fi +]) +dnl/*D +dnl PAC_PROG_F77_MISMATCHED_ARGS([option],[AllOnly]) - Determine whether the +dnl Fortran compiler allows routines to be called with different +dnl argument types. If not, attempts to determine a command-line argument +dnl that permits such use +dnl (The Fortran standard prohibits this usage) +dnl +dnl option is set to the compiler option to use. +dnl if AllOnly is yes (literal, not variable with value), then only consider +dnl options that turn off checking +dnl for all routines +dnl +dnl The NAG Fortran compiler, nagfor, is known to enforce this part of the +dnl Fortran standard. +dnl D*/ +AC_DEFUN([PAC_PROG_F77_MISMATCHED_ARGS],[ +AC_MSG_CHECKING([whether $F77 allows mismatched arguments]) +if test "X$pac_cv_prog_f77_mismatched_args" = X ; then + pac_cv_prog_f77_mismatched_args_parm="" + pac_cv_prog_f77_mismatched_args=no + AC_LANG_PUSH([Fortran 77]) + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + program main + integer a + real b + character c + call foo1(a) + call foo1(b) + call foo1(c) + end +])],[pac_cv_prog_f77_mismatched_args=yes]) + if test "$pac_cv_prog_f77_mismatched_args" != "yes" ; then + # try again with -wmismatch=foo1 + save_FFLAGS="$FFLAGS" + # The best solution is to turn off errors on particular routines + # if that isn't possible (e.g., too many of them), then + # just try arguments that turn off all checking + for flags in ifelse($2,yes,,"-wmismatch=foo1") "-mismatch" ; do + testok=no + FFLAGS="$FFLAGS $flags" + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + program main + integer a + real b + character c + call foo1(a) + call foo1(b) + call foo1(c) + end +])],[testok=yes]) + FFLAGS="$save_FFLAGS" + if test "$testok" = yes ; then break ; fi + done + if test "$testok" = yes ; then + pac_cv_prog_f77_mismatched_args_parm="$flags" + pac_cv_prog_f77_mismatched_args="yes, with $pac_cv_prog_f77_mismatched_args_parm" + fi + fi + AC_LANG_POP([Fortran 77]) +fi +AC_MSG_RESULT($pac_cv_prog_f77_mismatched_args) +if test "$pac_cv_prog_f77_mismatched_args" = no ; then + AC_MSG_ERROR([The Fortran compiler $F77 will not compile files that call +the same routine with arguments of different types.]) +fi + +ifelse($1,,,[$1=$pac_cv_prog_f77_mismatched_args_parm]) +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_f77old.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_f77old.m4 new file mode 100644 index 0000000000..5d6e2d9e70 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_f77old.m4 @@ -0,0 +1,389 @@ +dnl/*D +dnl PAC_PROG_F77_CMDARGS - Determine how to access the command line from +dnl Fortran 77 +dnl +dnl Output Effects: +dnl The following variables are set: +dnl.vb +dnl F77_GETARG - Statement to get an argument i into string s +dnl F77_IARGC - Routine to return the number of arguments +dnl FXX_MODULE - Module command when using Fortran 90 compiler +dnl F77_GETARGDECL - Declaration of routine used for F77_GETARG +dnl F77_GETARG_FFLAGS - Flags needed when compiling/linking +dnl F77_GETARG_LDFLAGS - Flags needed when linking +dnl.ve +dnl If 'F77_GETARG' has a value, then that value and the values for these +dnl other symbols will be used instead. If no approach is found, all of these +dnl variables will have empty values. +dnl If no other approach works and a file 'f77argdef' is in the directory, +dnl that file will be sourced for the values of the above four variables. +dnl +dnl In most cases, you should add F77_GETARG_FFLAGS to the FFLAGS variable +dnl and F77_GETARG_LDFLAGS to the LDFLAGS variable, to ensure that tests are +dnl performed on the compiler version that will be used. +dnl +dnl 'AC_SUBST' is called for all six variables. +dnl +dnl One complication is that on systems with multiple Fortran compilers, +dnl some libraries used by one Fortran compiler may have been (mis)placed +dnl in a common location. We have had trouble with libg2c in particular. +dnl To work around this, we test whether iargc etc. work first. This +dnl will catch most systems and will speed up the tests. +dnl +dnl Next, the libraries are only added if they are needed to complete a +dnl link; they aren''t added just because they exist. +dnl +dnl f77argdef +dnl D*/ +dnl +dnl Random notes +dnl You can export the command line arguments from C to the g77 compiler +dnl using +dnl extern char **__libc_argv; +dnl extern int __libc_argc; +dnl f_setarg( __libc_argc, __libc_argv ); +dnl +AC_DEFUN([PAC_PROG_F77_CMDARGS],[ +found_cached="yes" +AC_MSG_CHECKING([for routines to access the command line from Fortran 77]) +AC_CACHE_VAL(pac_cv_prog_f77_cmdarg, +[ + AC_MSG_RESULT([searching...]) + found_cached="no" + # First, we perform a quick check. Does iargc and getarg work? + fxx_module="${FXX_MODULE:-}" + f77_getargdecl="${F77_GETARGDECL:-external getarg}" + f77_getarg="${F77_GETARG:-call GETARG(i,s)}" + f77_iargc="${F77_IARGC:-IARGC()}" + # + # Grumble. The Absoft Fortran compiler computes i - i as 0 and then + # 1.0 / 0 at compile time, even though the code may never be executed. + # What we need is a way to generate an error, so the second usage of i + # was replaced with f77_iargc. + cat > conftest.f </dev/null 2>&1 ; then + found_answer="yes" + FXX_MODULE="$fxx_module" + F77_GETARGDECL="$f77_getargdecl" + F77_GETARG="$f77_getarg" + F77_IARGC="$f77_iargc" + AC_MSG_RESULT(yes) + fi + fi + fi + if test $found_answer = "no" ; then + AC_MSG_RESULT(no) + # Grumph. Here are a bunch of different approaches + # We have several axes the check: + # Library to link with (none, -lU77 (HPUX), -lg2c (LINUX f77)) + # PEPCF90 (Intel ifc) + # The first line is a dummy + # (we experimented with using a , but this caused other + # problems because we need in the IFS) + trial_LIBS="0 -lU77 -lPEPCF90" + if test "$NOG2C" != "1" ; then + trial_LIBS="$trial_LIBS -lg2c" + fi + # Discard libs that are not availble: + save_IFS="$IFS" + # Make sure that IFS includes a space, or the tests that run programs + # may fail + IFS=" "" +" + save_trial_LIBS="$trial_LIBS" + trial_LIBS="" + cat > conftest.f <, the space is important + # To make the Absoft f77 and f90 work together, we need to prefer the + # upper case versions of the arguments. They also require libU77. + # -YCFRL=1 causes Absoft f90 to work with g77 and similar (f2c-based) + # Fortran compilers + # + # Problem: The Intel efc compiler hangs when presented with -N109 . + # The only real fix for this is to detect this compiler and exclude + # the test. We may want to reorganize these tests so that if we + # can compile code without special options, we never look for them. + # + using_intel_efc="no" + pac_test_msg=`$F77 -V 2>&1 | grep 'Intel(R) Fortran Itanium'` + if test "$pac_test_msg" != "" ; then + using_intel_efc="yes" + fi + if test "$using_intel_efc" = "yes" ; then + trial_FLAGS="000" + else + trial_FLAGS="000 +-N109 +-f +-YEXT_NAMES=UCS +-YEXT_NAMES=LCS +-YCFRL=1 ++U77" + fi + # Discard options that are not available: + # (IFS already saved above) + IFS=" "" +" + save_trial_FLAGS="$trial_FLAGS" + trial_FLAGS="" + for flag in $save_trial_FLAGS ; do + if test "$flag" = " " -o "$flag" = "000" ; then + opt_ok="yes" + else + PAC_F77_CHECK_COMPILER_OPTION($flag,opt_ok=yes,opt_ok=no) + fi + if test "$opt_ok" = "yes" ; then + if test "$flag" = " " -o "$flag" = "000" ; then + fflag="" + else + fflag="$flag" + fi + # discard options that don't allow mixed-case name matching + cat > conftest.f < conftest.f </dev/null 2>&1 ; then + found_answer="yes" + fi + else + found_answer="yes" + fi + fi + IFS=" "" +" + if test "$found_answer" = "yes" ; then + AC_MSG_RESULT([yes]) + pac_cv_prog_f77_cmdarg="$MSG" + pac_cv_prog_f77_cmdarg_fflags="$flags" + pac_cv_prog_f77_cmdarg_ldflags="$libs" + break + else + AC_MSG_RESULT([no]) + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.f >&AC_FD_CC + fi + done + done + IFS="$save_IFS" + rm -f conftest.* + trial=`expr $trial + 1` + done +fi +pac_cv_F77_GETARGDECL="$F77_GETARGDECL" +pac_cv_F77_IARGC="$F77_IARGC" +pac_cv_F77_GETARG="$F77_GETARG" +pac_cv_FXX_MODULE="$FXX_MODULE" +]) +if test "$found_cached" = "yes" ; then + AC_MSG_RESULT([$pac_cv_prog_f77_cmdarg]) +elif test -z "$pac_cv_F77_IARGC" ; then + AC_MSG_WARN([Could not find a way to access the command line from Fortran 77]) +fi +# Set the variable values based on pac_cv_prog_xxx +F77_GETARGDECL="$pac_cv_F77_GETARGDECL" +F77_IARGC="$pac_cv_F77_IARGC" +F77_GETARG="$pac_cv_F77_GETARG" +FXX_MODULE="$pac_cv_FXX_MODULE" +F77_GETARG_FFLAGS="$pac_cv_prog_f77_cmdarg_fflags" +F77_GETARG_LDFLAGS="$pac_cv_prog_f77_cmdarg_ldflags" +AC_SUBST(F77_GETARGDECL) +AC_SUBST(F77_IARGC) +AC_SUBST(F77_GETARG) +AC_SUBST(FXX_MODULE) +AC_SUBST(F77_GETARG_FFLAGS) +AC_SUBST(F77_GETARG_LDFLAGS) +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_fc.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_fc.m4 new file mode 100644 index 0000000000..870a5bea10 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_fc.m4 @@ -0,0 +1,1225 @@ +dnl PAC_FC_SEARCH_LIST - expands to a whitespace separated list of modern +dnl fortran compilers for use with AC_PROG_FC that is more suitable for HPC +dnl software packages +AC_DEFUN([PAC_FC_SEARCH_LIST], + [ifort pgf90 pathf90 pathf95 xlf90 xlf95 xlf2003 gfortran f90 epcf90 f95 fort lf95 g95 ifc efc gfc]) +dnl /*D +dnl PAC_PROG_FC([COMPILERS]) +dnl +dnl COMPILERS is a space separated list of Fortran 77 compilers to search +dnl for. Fortran 95 isn't strictly backwards-compatible with Fortran 77, +dnl but `f95' is worth trying. +dnl +dnl Compilers are ordered by +dnl 1. F77, F90, F95 +dnl 2. Good/tested native compilers, bad/untested native compilers +dnl 3. Wrappers around f2c go last. +dnl +dnl `fort77' is a wrapper around `f2c'. +dnl It is believed that under HP-UX `fort77' is the name of the native +dnl compiler. On some Cray systems, fort77 is a native compiler. +dnl frt is the Fujitsu F77 compiler. +dnl pgf77 and pgf90 are the Portland Group F77 and F90 compilers. +dnl xlf/xlf90/xlf95/xlf2003 are IBM (AIX) F77/F90/F95/F2003 compilers. +dnl lf95 is the Lahey-Fujitsu compiler. +dnl fl32 is the Microsoft Fortran "PowerStation" compiler. +dnl af77 is the Apogee F77 compiler for Intergraph hardware running CLIX. +dnl epcf90 is the "Edinburgh Portable Compiler" F90. +dnl fort is the Compaq Fortran 90 (now 95) compiler for Tru64 and Linux/Alpha. +dnl pathf90 is the Pathscale Fortran 90 compiler +dnl ifort is another name for the Intel f90 compiler +dnl efc - An older Intel compiler (?) +dnl ifc - An older Intel compiler +dnl fc - A compiler on some unknown system. This has been removed because +dnl it may also be the name of a command for something other than +dnl the Fortran compiler (e.g., fc=file system check!) +dnl gfortran - The GNU Fortran compiler (not the same as g95) +dnl gfc - An alias for gfortran recommended in cygwin installations +dnl NOTE: this macro suffers from a basically intractable "expanded before it +dnl was required" problem when libtool is also used +dnl D*/ +AC_DEFUN([PAC_PROG_FC],[ +PAC_PUSH_FLAG([FCFLAGS]) +AC_PROG_FC([m4_default([$1],[PAC_FC_SEARCH_LIST])]) +PAC_POP_FLAG([FCFLAGS]) +]) +dnl +dnl PAC_FC_EXT checks for the default Fortran 90 program extension, f90 then f. +dnl This could be replaced by AC_FC_SRCEXT but since AC_FC_SRCEXT +dnl adds FCFLAGS_ext, which is used to modify FCFLAGS or Makefile.in. +dnl So will do this later. +dnl +AC_DEFUN([PAC_FC_EXT],[ +AC_MSG_CHECKING([for extension for Fortran 90 programs]) +ac_fc_srcext="f90" +AC_LANG_PUSH(Fortran) +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM() +],[ + AC_MSG_RESULT([f90]) +],[ + ac_fc_srcext="f" + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM() + ],[ + AC_MSG_RESULT([f]) + ],[ + AC_MSG_RESULT([unknown!]) + ]) +]) +AC_LANG_POP(Fortran) +]) +dnl +dnl Internal routine for testing F90 +dnl PAC_PROG_FC_WORKS() +dnl +AC_DEFUN([PAC_PROG_FC_WORKS],[ +AC_REQUIRE([PAC_FC_EXT]) +AC_LANG_PUSH(Fortran) +AC_MSG_CHECKING([whether the Fortran 90 compiler ($FC $FCFLAGS $LDFLAGS) works]) +AC_LINK_IFELSE([ + AC_LANG_SOURCE([ + program conftest + integer, dimension(10) :: n + end + ]) +],[ + pac_cv_prog_fc_works="yes" + AC_MSG_RESULT([$pac_cv_prog_fc_works]) + AC_MSG_CHECKING([whether the Fortran 90 compiler ($FC $FCFLAGS $LDFLAGS) is a cross-compiler]) + AC_RUN_IFELSE([], + [pac_cv_prog_fc_cross="no"], + [pac_cv_prog_fc_cross="yes"], + [pac_cv_prog_fc_cross="$cross_compiling"] + ) + AC_MSG_RESULT($pac_cv_prog_fc_cross) +],[ + pac_cv_prog_fc_works="no" + AC_MSG_WARN([installation or configuration problem: Fortran 90 compiler cannot create executables.]) +]) +# The intel compiler sometimes generates these work.pc and .pcl files +rm -f work.pc work.pcl +AC_LANG_POP(Fortran) +dnl cross_compiling no longer maintained by autoconf as part of the +dnl AC_LANG changes. If we set it here, a later AC_LANG may not +dnl restore it (in the case where one compiler claims to be a cross compiler +dnl and another does not) +dnl cross_compiling=$pac_cv_prog_f90_cross +]) +dnl/*D +dnl PAC_PROG_FC_INT_KIND - Determine kind parameter for an integer with +dnl the specified number of bytes. +dnl +dnl Synopsis: +dnl PAC_PROG_FC_INT_KIND(variable-to-set,number-of-bytes,[cross-size]) +dnl +dnl D*/ +AC_DEFUN([PAC_PROG_FC_INT_KIND],[ +# Set the default +$1=-1 +if test "$pac_cv_prog_fc_cross" = "yes" ; then + AS_IF([test -z "$3"],[AC_MSG_ERROR(['$3' is empty])]) + $1="$3" +else + AC_LANG_PUSH(Fortran) + AC_MSG_CHECKING([for Fortran 90 integer kind for $2-byte integers]) + # Convert bytes to digits + case $2 in + 1) sellen=2 ;; + 2) sellen=4 ;; + 4) sellen=8 ;; + 8) sellen=16 ;; + 16) sellen=30 ;; + *) sellen=8 ;; + esac + # Check for cached value + eval testval=\$"pac_cv_prog_fc_int_kind_$sellen" + if test -n "$testval" ; then + AC_MSG_RESULT([$testval (cached)]) + $1=$testval + else + KINDVAL="unavailable" + eval "pac_cv_prog_fc_int_kind_$sellen"=-1 + AC_RUN_IFELSE([ + AC_LANG_SOURCE([ + program main + integer ii + ii = selected_int_kind($sellen) + open(8, file="conftest1.out", form="formatted") + write (8,*) ii + close(8) + stop + end + ]) + ],[pac_run_ok=yes],[pac_run_ok=no]) + if test "$pac_run_ok" = "yes" ; then + if test -s conftest1.out ; then + # Because of write, there may be a leading blank. + KINDVAL=`cat conftest1.out | sed 's/ //g'` + eval "pac_cv_prog_fc_int_kind_$sellen"=$KINDVAL + $1=$KINDVAL + fi + fi + AC_MSG_RESULT([$KINDVAL]) + fi # not cached + AC_LANG_POP(Fortran) +fi # is not cross compiling +])dnl +dnl +dnl ------------------------------------------------------------------------ +dnl Special characteristics that have no autoconf counterpart but that +dnl we need as part of the Fortran 90 support. To distinquish these, they +dnl have a [PAC] prefix. +dnl +dnl At least one version of the Cray compiler needs the option -em to +dnl generate a separate module file, rather than including the module +dnl information in the object (.o) file. +dnl +dnl +dnl PAC_FC_MODULE_EXT(action if found,action if not found) +dnl +AC_DEFUN([PAC_FC_MODULE_EXT], +[AC_CACHE_CHECK([for Fortran 90 module extension], +pac_cv_fc_module_ext,[ +pac_cv_fc_module_case="unknown" +AC_LANG_PUSH(Fortran) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + module conftest + integer n + parameter (n=1) + end module conftest + ]) +],[ + # Look for module name + # First, try to find known names. This avoids confusion caused by + # additional files (like .stb created by some versions of pgf90) + # Early versions of the Intel compiler used d as the module extension; + # we include that just to finish the test as early as possible. + for name in conftest CONFTEST ; do + for ext in mod MOD d ; do + if test -s $name.$ext ; then + if test $name = conftest ; then + pac_cv_fc_module_case=lower + else + pac_cv_fc_module_case=upper + fi + pac_cv_fc_module_ext=$ext + pac_MOD=$ext + break + fi + done + if test -n "$pac_cv_fc_module_ext" ; then break ; fi + done + if test -z "$pac_MOD" ; then + # The test on .err is needed for Cray Fortran. + pac_MOD=`ls conftest.* 2>&1 | grep -v conftest.${ac_fc_srcext} | grep -v conftest.o | grep -v conftest.err` + pac_MOD=`echo $pac_MOD | sed -e 's/conftest\.//g'` + pac_cv_fc_module_case="lower" + if test "X$pac_MOD" = "X" ; then + pac_MOD=`ls CONFTEST* 2>&1 | grep -v CONFTEST.${ac_fc_srcext} | grep -v CONFTEST.o | grep -v CONFTEST.err` + pac_MOD=`echo $pac_MOD | sed -e 's/CONFTEST\.//g'` + if test -n "$pac_MOD" -a -s "CONFTEST.$pac_MOD" ; then + pac_cv_fc_module_case="upper" + else + # Clear because we must have gotten an error message + pac_MOD="" + fi + fi + if test -z "$pac_MOD" ; then + pac_cv_fc_module_ext="unknown" + else + pac_cv_fc_module_ext=$pac_MOD + fi + fi +],[ + pac_cv_fc_module_ext="unknown" +]) + +if test "$pac_cv_fc_module_ext" = "unknown" ; then + # Try again, but with an -em option. Abbreviated, because we're + # just looking for the Cray option + saveFCFLAGS=$FCFLAGS + FCFLAGS="$FCFLAGS -em" + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + module conftest + integer n + parameter (n=1) + end module conftest + ]) +],[ + if test -s conftest.mod ; then + pac_cv_fc_module_ext="mod" + pac_cv_fc_module_case="lower" + elif test -s CONFTEST.mod ; then + pac_cv_fc_module_ext="mod" + pac_cv_fc_module_case="upper" + fi +],[ + : + # do nothing - already have the unknown default value +]) + if test "$pac_cv_fc_module_ext" = "unknown" ; then + # The additional command line option did not help - restore + # the original flags. + FCFLAGS=$saveFCFLAGS + fi +fi +AC_LANG_POP(Fortran) +]) +# +AC_SUBST(FCMODEXT) +if test "$pac_cv_fc_module_ext" = "unknown" ; then + ifelse($2,,:,[$2]) +else + ifelse($1,,FCMODEXT=$pac_MOD,[$1]) +fi +]) +dnl +dnl +dnl PAC_FC_MODULE_INCFLAG +AC_DEFUN([PAC_FC_MODULE_INCFLAG],[ +AC_REQUIRE([PAC_FC_MODULE_EXT]) +AC_CACHE_CHECK([for Fortran 90 module include flag], +pac_cv_fc_module_incflag,[ +AC_LANG_PUSH(Fortran) +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + module conf + integer n + parameter (n=1) + end module conf + ]) +]) +pac_madedir="no" +if test ! -d conf ; then mkdir conftestdir ; pac_madedir="yes"; fi +if test "$pac_cv_fc_module_case" = "upper" ; then + pac_module="CONF.$pac_cv_fc_module_ext" +else + pac_module="conf.$pac_cv_fc_module_ext" +fi +AC_COMPILE_IFELSE([],[ + if test -s "$pac_module" ; then + mv $pac_module conftestdir + # Remove any temporary files, and hide the work.pc file + # (if the compiler generates them) + if test -f work.pc ; then + mv -f work.pc conftest.pc + fi + rm -f work.pcl + else + AC_MSG_WARN([Unable to build a simple Fortran 90 module]) + # echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD + # cat conftest.$ac_ext >&AS_MESSAGE_LOG_FD + _AC_MSG_LOG_CONFTEST + fi +],[]) +# Remove the conftest* after AC_LANG_CONFTEST +rm -rf conftest.dSYM +rm -f conftest.$ac_ext + +dnl Create the conftest here so the test isn't created everytime inside loop. +AC_LANG_CONFTEST([AC_LANG_PROGRAM([],[use conf])]) + +# Save the original FCFLAGS +saved_FCFLAGS="$FCFLAGS" +pac_cv_fc_module_incflag="" +for inchdr in '-I' '-M' '-p' ; do + FCFLAGS="$saved_FCFLAGS ${inchdr}conftestdir" + AC_COMPILE_IFELSE([],[pac_cv_fc_module_incflag="$inchdr" ; break]) +done +if test "X$pac_cv_fc_module_incflag" = "X" ; then + if test -s conftest.pc ; then + mv conftest.pc conftestdir/mpimod.pc + echo "mpimod.pc" > conftestdir/mpimod.pcl + echo "`pwd`/conftestdir/mpimod.pc" >> conftestdir/mpimod.pcl + inchdr='-cl,' + FCFLAGS="$save_FCFLAGS ${inchdr}conftestdir" + AC_COMPILE_IFELSE([], [pac_fcompile_ok=yes], [pac_fcompile_ok=no]) + if test "$pac_fcompile_ok" = "yes" ; then + pac_cv_fc_module_incflag="$inchdr" + # Not quite right; see the comments that follow + AC_MSG_RESULT([-cl,filename where filename contains a list of files and directories]) + FC_WORK_FILES_ARG="-cl,mpimod.pcl" + FCMODINCSPEC="-cl,/mod.pcl" + else + # The version of the Intel compiler that I have refuses to let + # you put the "work catalog" list anywhere but the current directory. + pac_cv_fc_module_incflag="Unavailable!" + fi + else + # Early versions of the Intel ifc compiler required a *file* + # containing the names of files that contained the names of the + # + # -cl,filename.pcl + # filename.pcl contains + # fullpathname.pc + # The "fullpathname.pc" is generated, I believe, when a module is + # compiled. + # Intel compilers use a wierd system: -cl,filename.pcl . If no file is + # specified, work.pcl and work.pc are created. However, if you specify + # a file, it must contain the name of a file ending in .pc . Ugh! + pac_cv_fc_module_incflag="unknown" + fi +fi +# Restore the original FCFLAGS +FCFLAGS="$saved_FCFLAGS" +if test "$pac_madedir" = "yes" ; then rm -rf conftestdir ; fi +# Remove the conftest* after AC_LANG_CONFTEST +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest* +AC_LANG_POP(Fortran) +]) +AC_SUBST(FC_WORK_FILES_ARG) +AC_SUBST(FCMODINCFLAG) +FCMODINCFLAG=$pac_cv_fc_module_incflag +]) +dnl +dnl +dnl +AC_DEFUN([PAC_FC_MODULE],[ +PAC_FC_MODULE_EXT +PAC_FC_MODULE_INCFLAG +PAC_FC_MODULE_OUTFLAG +]) +dnl +dnl PAC_FC_MODULE_OUTFLAG +AC_DEFUN([PAC_FC_MODULE_OUTFLAG],[ +AC_REQUIRE([PAC_FC_MODULE_EXT]) +AC_CACHE_CHECK([for Fortran 90 module output directory flag], + [pac_cv_fc_module_outflag], +[ +AC_LANG_PUSH([Fortran]) +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + module conf + integer n + parameter (n=1) + end module conf + ]) +]) +pac_madedir="no" +if test ! -d conf ; then mkdir conftestdir ; pac_madedir="yes"; fi +if test "$pac_cv_fc_module_case" = "upper" ; then + pac_module="CONF.$pac_cv_fc_module_ext" +else + pac_module="conf.$pac_cv_fc_module_ext" +fi + +# check base case that the compiler can create modules and that they endup in +# the current directory +AC_COMPILE_IFELSE([],[ + if test -s "$pac_module" ; then + rm -f "$pac_module" + # Remove any temporary files, and hide the work.pc file + # (if the compiler generates them) + if test -f work.pc ; then + mv -f work.pc conftest.pc + fi + rm -f work.pcl + else + AC_MSG_WARN([Unable to build a simple Fortran 90 module]) + # echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD + # cat conftest.$ac_ext >&AS_MESSAGE_LOG_FD + _AC_MSG_LOG_CONFTEST + fi +],[]) + +# known flags for reasonably recent versions of various f90 compilers: +# gfortran -J${dir} +# xlf -qmoddir=${dir} +# pgf90 -module ${dir} +# ifort -module ${dir} +# nagfor -mdir ${dir} +# ftn -J ${dir} ## the Cray fortran compiler +# ftn -em -J${dir} ## the Cray fortran compiler (crayftn, in 2013) +# For this above case, we must have added -em to FCFLAGS, since other +# module tests do not always use the module output flag. See +# FC_MODULE_EXT , where this is determined. +# f95 -YMOD_OUT_DIR=${dir} ## the Absoft fortran compiler +# lf95 -Am -mod ${dir} ## the Lahey/Fujitsu fortran compiler +# f90 -moddir=${dir} ## the Sun f90 compiler +# g95 -fmod=${dir} +# +# If there are any compilers still out there that are totally brain-dead and +# don't support an output directory flag, we can write a wrapper script to tell +# users to use. Alternatively they can use an older version of MPICH. + +pac_cv_fc_module_outflag= +for mod_flag in '-J' '-J ' '-qmoddir=' '-module ' '-YMOD_OUT_DIR=' '-mdir ' '-moddir=' '-fmod=' ; do + rm -f conftestdir/NONEXISTENT conftestdir/* + PAC_PUSH_FLAG([FCFLAGS]) + FCFLAGS="$FCFLAGS ${mod_flag}conftestdir" + AC_COMPILE_IFELSE([],[pac_build_success=yes],[pac_build_success=no]) + AS_IF([test "X$pac_build_success" = Xyes], + [AS_IF([test -s "conftestdir/${pac_module}"], + [pac_cv_fc_module_outflag="$mod_flag"])]) + PAC_POP_FLAG([FCFLAGS]) + AS_IF([test "X$pac_cv_fc_module_outflag" = X],[:],[break]) +done + +# Remove the conftest* after AC_LANG_CONFTEST +rm -rf conftest.dSYM +rm -f conftest.$ac_ext + +if test "$pac_madedir" = "yes" ; then rm -rf conftestdir ; fi +AS_UNSET([pac_madedir]) +# Remove the conftest* after AC_LANG_CONFTEST +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest* +AC_LANG_POP(Fortran) +])dnl end AC_CACHE_CHECK + +AC_SUBST([FCMODOUTFLAG],[$pac_cv_fc_module_outflag]) +])dnl end AC_DEFUN([PAC_FC_MODULE_OUTFLAG]) +dnl +dnl PAC_FC_AND_F77_COMPATIBLE([action-if-true],[action-if-false]) +dnl +dnl Determine whether object files compiled with Fortran 77 can be +dnl linked to Fortran 90 main programs. +dnl +dnl The test uses a name that includes an underscore unless the 3rd +dnl argument provides another routine name. +dnl +AC_DEFUN([PAC_FC_AND_F77_COMPATIBLE],[ +AC_REQUIRE([PAC_PROG_FC_WORKS]) +AC_CACHE_CHECK([whether Fortran 90 compiler works with Fortran 77 compiler], +pac_cv_fc_and_f77,[ +pacTestRoutine=foo_abc +ifelse([$3],,,[eval pacTestRoutine=$3]) +pac_cv_fc_and_f77="unknown" +# compile the f77 program and link with the f90 program +# The reverse may not work because the Fortran 90 environment may +# expect to be in control (and to provide library files unknown to any other +# environment, even Fortran 77!) +AC_LANG_PUSH(Fortran 77) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ + subroutine ${pacTestRoutine}(b) + integer b + b = b + 1 + end + ]) +],[ + # pac_f77compile_ok=yes + PAC_RUNLOG([mv conftest.$OBJEXT pac_f77conftest.$OBJEXT]) + # Save original LIBS, prepend previously generated object file to LIBS + saved_LIBS="$LIBS" + LIBS="pac_f77conftest.$OBJEXT $LIBS" + AC_LANG_PUSH(Fortran) + AC_LINK_IFELSE([ + AC_LANG_SOURCE([ + program main + integer a + a = 1 + call ${pacTestRoutine}(a) + end + ]) + ],[pac_cv_fc_and_f77=yes],[pac_cv_fc_and_f77=no]) + # Some versions of the Intel compiler produce these two files + rm -f work.pc work.pcl + # Restore LIBS + LIBS="$saved_LIBS" + AC_LANG_POP(Fortran) + # remove previously generated object file. + rm -f pac_f77conftest.$OBJEXT +], [ + # pac_f77compile_ok=no + pac_cv_fc_and_f77=no +]) +AC_LANG_POP(Fortran 77) +# Perform the requested action based on whether the test succeeded +if test "$pac_cv_fc_and_f77" = yes ; then + ifelse($1,,:,[$1]) +else + ifelse($2,,:,[$2]) + AC_MSG_WARN([See config.log for the failed test program and its output.]) +fi +]) +dnl +]) +dnl +dnl +dnl /*D +dnl PAC_PROG_FC_CRAY_POINTER - Check if Fortran supports Cray-style pointer. +dnl If so, set pac_cv_prog_fc_has_pointer to yes +dnl and find out if any extra compiler flag is +dnl needed and set it as CRAYPTR_FCFLAGS. +dnl i.e. CRAYPTR_FCFLAGS is meaningful only if +dnl pac_cv_prog_fc_has_pointer = yes. +dnl +dnl Synopsis: +dnl PAC_PROG_FC_CRAY_POINTER([action-if-true],[action-if-false]) +dnl D*/ +AC_DEFUN([PAC_PROG_FC_CRAY_POINTER],[ +AC_CACHE_CHECK([whether Fortran 90 supports Cray-style pointer], +pac_cv_prog_fc_has_pointer,[ +AC_LANG_PUSH([Fortran]) +AC_LANG_CONFTEST([ + AC_LANG_PROGRAM([],[ + integer M + pointer (MPTR,M) + data MPTR/0/ + ]) +]) +saved_FCFLAGS="$FCFLAGS" +pac_cv_prog_fc_has_pointer=no +CRAYPTR_FCFLAGS="" +for ptrflag in '' '-fcray-pointer' ; do + FCFLAGS="$saved_FCFLAGS $ptrflag" + AC_COMPILE_IFELSE([],[ + pac_cv_prog_fc_has_pointer=yes + CRAYPTR_FCFLAGS="$ptrflag" + break + ]) +done +dnl Restore FCFLAGS first, since user may not want to modify FCFLAGS +FCFLAGS="$saved_FCFLAGS" +dnl remove conftest after ac_lang_conftest +rm -f conftest.$ac_ext +AC_LANG_POP([Fortran]) +]) +if test "$pac_cv_prog_fc_has_pointer" = "yes" ; then + AC_MSG_CHECKING([for Fortran 90 compiler flag for Cray-style pointer]) + if test "X$CRAYPTR_FCFLAGS" != "X" ; then + AC_MSG_RESULT([$CRAYPTR_FCFLAGS]) + else + AC_MSG_RESULT([none]) + fi + ifelse([$1],[],[:],[$1]) +else + ifelse([$2],[],[:],[$2]) +fi +]) +dnl +dnl +dnl +AC_DEFUN([PAC_PROG_FC_AND_C_STDIO_LIBS],[ +AC_REQUIRE([AC_HEADER_STDC]) +# To simply the code in the cache_check macro, chose the routine name +# first, in case we need it +confname=conf1_ +case "$pac_cv_prog_f77_name_mangle" in + "lower underscore") confname=conf1_ ;; + "upper stdcall") confname=CONF1 ;; + upper) confname=CONF1 ;; + "lower doubleunderscore") confname=conf1_ ;; + lower) confname=conf1 ;; + "mixed underscore") confname=conf1_ ;; + mixed) confname=conf1 ;; +esac + +AC_CACHE_CHECK([what libraries are needed to link Fortran90 programs with C routines that use stdio],pac_cv_prog_fc_and_c_stdio_libs,[ +pac_cv_prog_fc_and_c_stdio_libs=unknown + +AC_LANG_PUSH(C) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ +#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS) +#include +#endif +int $confname( int a ) +{ printf( "The answer is %d\n", a ); fflush(stdout); return 0; } + ]) +],[ + pac_compile_ok=yes + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + # Save LIBS and prepend object file to LIBS + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $LIBS" + AC_LANG_PUSH(Fortran) + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([],[call conf1(0)]) + ],[ + pac_cv_prog_fc_and_c_stdio_libs=none + ],[ + # Try again with -lSystemStubs + LIBS="$LIBS -lSystemStubs" + AC_LINK_IFELSE([],[ + pac_cv_prog_fc_and_c_stdio_libs="-lSystemStubs" + ],[]) + ]) + LIBS="$saved_LIBS" + AC_LANG_POP(Fortran) + rm -f pac_conftest.$OBJEXT +]) +AC_LANG_POP(C) +dnl +if test "$pac_cv_prog_fc_and_c_stdio_libs" != none -a \ + "$pac_cv_prog_fc_and_c_stdio_libs" != unknown ; then + FC_OTHER_LIBS="$FC_OTHER_LIBS $pac_cv_prog_fc_and_c_stdio_libs" +fi +]) +dnl +]) +dnl +dnl/*D +dnl PAC_FC_CHECK_COMPILER_OPTION - Check that a FC compiler option is +dnl accepted without warning messages +dnl +dnl Synopsis: +dnl PAC_FC_CHECK_COMPILER_OPTION(optionname,action-if-ok,action-if-fail) +dnl +dnl Output Effects: +dnl +dnl If no actions are specified, a working value is added to 'FCOPTIONS' +dnl +dnl Notes: +dnl This is now careful to check that the output is different, since +dnl some compilers are noisy. +dnl +dnl We are extra careful to prototype the functions in case compiler options +dnl that complain about poor code are in effect. +dnl +dnl Because this is a long script, we have ensured that you can pass a +dnl variable containing the option name as the first argument. +dnl D*/ +AC_DEFUN([PAC_FC_CHECK_COMPILER_OPTION],[ +AC_MSG_CHECKING([whether Fortran 90 compiler accepts option $1]) +pac_opt="$1" +AC_LANG_PUSH(Fortran) +FCFLAGS_orig="$FCFLAGS" +FCFLAGS_opt="$pac_opt $FCFLAGS" +pac_result="unknown" + +AC_LANG_CONFTEST([AC_LANG_PROGRAM()]) +FCFLAGS="$FCFLAGS_orig" +rm -f pac_test1.log +PAC_LINK_IFELSE_LOG([pac_test1.log], [], [ + FCFLAGS="$FCFLAGS_opt" + rm -f pac_test2.log + PAC_LINK_IFELSE_LOG([pac_test2.log], [], [ + PAC_RUNLOG_IFELSE([diff -b pac_test1.log pac_test2.log], + [pac_result=yes], [pac_result=no]) + ],[ + pac_result=no + ]) +], [ + pac_result=no +]) +AC_MSG_RESULT([$pac_result]) +dnl Delete the conftest created by AC_LANG_CONFTEST. +rm -f conftest.$ac_ext +# +if test "$pac_result" = "yes" ; then + AC_MSG_CHECKING([whether routines compiled with $pac_opt can be linked with ones compiled without $pac_opt]) + pac_result=unknown + FCFLAGS="$FCFLAGS_orig" + rm -f pac_test3.log + PAC_COMPILE_IFELSE_LOG([pac_test3.log], [ + AC_LANG_SOURCE([ + subroutine try() + end + ]) + ],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $LIBS" + + FCFLAGS="$FCFLAGS_opt" + rm -f pac_test4.log + PAC_LINK_IFELSE_LOG([pac_test4.log], [AC_LANG_PROGRAM()], [ + PAC_RUNLOG_IFELSE([diff -b pac_test2.log pac_test4.log], + [pac_result=yes], [pac_result=no]) + ],[ + pac_result=no + ]) + LIBS="$saved_LIBS" + rm -f pac_conftest.$OBJEXT + ],[ + pac_result=no + ]) + AC_MSG_RESULT([$pac_result]) + rm -f pac_test3.log pac_test4.log +fi +rm -f pac_test1.log pac_test2.log + +dnl Restore FCFLAGS before 2nd/3rd argument commands are executed, +dnl as 2nd/3rd argument command could be modifying FCFLAGS. +FCFLAGS="$FCFLAGS_orig" +if test "$pac_result" = "yes" ; then + ifelse([$2],[],[FCOPTIONS="$FCOPTIONS $1"],[$2]) +else + ifelse([$3],[],[:],[$3]) +fi +AC_LANG_POP(Fortran) +]) +dnl /*D +dnl PAC_FC_WORKS_WITH_CPP +dnl +dnl Checks if Fortran 90 compiler works with C preprocessor +dnl +dnl Most systems allow the Fortran compiler to process .F and .F90 files +dnl using the C preprocessor. However, some systems either do not +dnl allow this or have serious bugs (OSF Fortran compilers have a bug +dnl that generates an error message from cpp). The following test +dnl checks to see if .F works, and if not, whether "cpp -P -C" can be used +dnl D*/ +AC_DEFUN([PAC_FC_WORKS_WITH_CPP],[ +AC_REQUIRE([AC_PROG_CPP]) +AC_MSG_CHECKING([whether Fortran 90 compiler processes .F90 files with C preprocessor]) +AC_LANG_PUSH([Fortran]) +saved_fc_ext=${ac_ext} +ac_ext="F90" +saved_FCFLAGS="$FCFLAGS" +FCFLAGS="$FCFLAGS $CPPFLAGS" +AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + program main +#define ASIZE 10 + integer a(ASIZE) + end + ]) +]) +AC_COMPILE_IFELSE([],[ + pac_cv_fc_accepts_F90=yes + ifelse([$1],[],[],[$1=""]) +],[ + pac_cv_fc_accepts_F90=no + ifelse([$1],[],[:],[$1="false"]) +]) +# Restore Fortran's ac_ext but not FCFLAGS +ac_ext="$saved_fc_ext" + +if test "$pac_cv_fc_accepts_F90" != "yes" ; then + pac_cpp_fc="$ac_cpp -C -P conftest.F90 > conftest.$ac_ext" + PAC_RUNLOG_IFELSE([$pac_cpp_fc],[ + if test -s conftest.${ac_ext} ; then + AC_COMPILE_IFELSE([],[ + pac_cv_fc_accepts_F90="no, use cpp" + ifelse([$1],[],[],[$1="$CPP -C -P"]) + ],[]) + rm -f conftest.${ac_ext} + fi + ],[]) +fi +FCFLAGS="$saved_FCFLAGS" +rm -f conftest.F90 +AC_LANG_POP([Fortran]) +AC_MSG_RESULT([$pac_cv_fc_accepts_F90]) +]) +dnl +dnl PAC_FC_VENDOR: +dnl Try to get a version string for the F90 compiler. We may +dnl need this to find likely command-line arguments for accessing +dnl shared libraries +dnl +AC_DEFUN([PAC_FC_VENDOR],[ +AC_MSG_CHECKING([for Fortran 90 compiler vendor]) +# This is complicated by some compilers (such as the Intel 8.1 ifort) +# that return a non-zero status even when they accept the -V option +# (a zero status is returned only if there is a file). +pac_cv_fc_vendor="unknown" +for arg in --version -V -v ; do + rm -f conftest.txt + PAC_RUNLOG([$FC $arg conftest.txt 2>&1]) + # Ignore the return code, because some compilers set the + # return code to zero on invalid arguments and some to + # non-zero on success (with no files to compile) + if test -f conftest.txt ; then + if grep 'Portland Group' conftest.txt >/dev/null 2>&1 ; then + pac_cv_fc_vendor=pgi + elif grep 'Sun Workshop' conftest.txt >/dev/null 2>&1 ; then + pac_cv_fc_vendor=sun + elif grep 'Sun Fortran 9' conftest.txt >/dev/null 2>&1 ; then + pac_cv_fc_vendor=sun + elif grep 'Absoft' conftest.txt >/dev/null 2>&1 ; then + pac_cv_fc_vendor=absoft + elif grep 'G95' conftest.txt >/dev/null 2>&1 ; then + pac_cv_fc_vendor=gnu + elif grep 'GNU Fortran' conftest.txt >/dev/null 2>&1 ; then + # This is gfortran + pac_cv_fc_vendor=gnu + elif grep Intel conftest.txt >/dev/null 2>&1 ; then + pac_cv_fc_vendor=intel + fi + fi + if test "$pac_cv_fc_vendor" != "unknown" ; then break ; fi +done +if test "$pac_cv_fc_vendor" = "unknown" ; then + # Try to use the compiler name + if test "$FC" = "ifort" -o "$FC" = "ifc" ; then + pac_cv_fc_vendor=intel + elif test "$FC" = "pgf90" ; then + pac_cv_fc_vendor=pgi + elif test "$FC" = "xlf90" -o "$FC" = "xlf90_r" ; then + pac_cv_fc_vendor=ibm + elif test "$FC" = "xlf95" -o "$FC" = "xlf95_r" ; then + pac_cv_fc_vendor=ibm + fi +fi +AC_MSG_RESULT([$pac_cv_fc_vendor]) +rm -f conftest.txt +# End of checking for F90 compiler vendor +]) +dnl +dnl PAC_F77_IS_FC([ACTION_IF_TRUE],[ACTION_IF_FALSE]) +dnl Check if F77 is a Fortran 90 compiler. +dnl +AC_DEFUN([PAC_F77_IS_FC],[ +AC_MSG_CHECKING([whether $F77 is a Fortran 90 compiler]) +AC_LANG_PUSH([Fortran 77]) +saved_ac_ext=$ac_ext +ac_ext="f90" +AC_LINK_IFELSE([ + AC_LANG_SOURCE([ + program main + integer, dimension(10) :: n + integer k + print *, range(k) + end + ]) +],[ + pac_cv_prog_f77_is_fc=yes + ifelse([$1],[],[],[$1]) +],[ + pac_cv_prog_f77_is_fc=no + ifelse([$2],[],[],[$2]) +]) +AC_MSG_RESULT([$pac_cv_prog_f77_is_fc]) +AC_LANG_POP([Fortran 77]) +]) +dnl +dnl PAC_FC_FLOAT_MODEL(float_type, [variable-set-if-successful-test]) +dnl variable-set-if-successful-test is optional variable. +dnl +dnl This is a runtime test. +dnl +AC_DEFUN([PAC_FC_FLOAT_MODEL],[ +type="$1" +AC_MSG_CHECKING([for precision and range of $type]) +AC_LANG_PUSH([Fortran]) +rm -f pac_fconftest.out +AC_RUN_IFELSE([ + AC_LANG_SOURCE([ + program main + $type aa + open(8, file="pac_fconftest.out", form="formatted") + write(8,*) precision(aa), ",", range(aa) + close(8) + end + ]) +],[ + if test -s pac_fconftest.out ; then + pac_fc_num_model="`sed -e 's/ */ /g' pac_fconftest.out`" + AC_MSG_RESULT([$pac_fc_num_model]) + ifelse([$2],[],[],[$2=$pac_fc_num_model]) + else + AC_MSG_RESULT([Error]) + AC_MSG_WARN([No output from test program!]) + fi + rm -f pac_fconftest.out +],[ + AC_MSG_RESULT([Error]) + AC_MSG_WARN([Failed to run program to determine the precision and range of $type]) +]) +AC_LANG_POP([Fortran]) +]) +dnl +dnl PAC_FC_SIMPLE_NUMBER_MODEL(message, Fortran-type, Fortran-write, +dnl [variable-set-if-successful-test], +dnl [cross-value]) +dnl +dnl message : message of what test-fc-code is checking +dnl Fortran-type : Fortran90 type's data model to be examined. +dnl Fortran-write : Fortran90 type's write statement used with write(N,*). +dnl variable-set-if-successful-test : +dnl The optional variable to be set if the codelet: +dnl "Fortran-type" + "write(N,*) Fortran-write" +dnl is successful in returning the simple data model. +dnl cross-value : value to be used for above variable when +dnl cross_compiling=yes +dnl +dnl This is a runtime test. +dnl +AC_DEFUN([PAC_FC_SIMPLE_NUMBER_MODEL],[ +pac_msg="$1" +AC_MSG_CHECKING([for $pac_msg]) +AC_LANG_PUSH([Fortran]) +rm -f pac_fconftest.out +AC_RUN_IFELSE([ + AC_LANG_SOURCE([ + program main + $2 + open(8, file="pac_fconftest.out", form="formatted") + write(8,*) $3 + close(8) + end + ]) +],[ + if test -s pac_fconftest.out ; then + pac_fc_num_model="`sed -e 's/ */ /g' pac_fconftest.out`" + AC_MSG_RESULT([$pac_fc_num_model]) + ifelse([$4],[],[],[$4=$pac_fc_num_model]) + else + AC_MSG_RESULT([Error]) + AC_MSG_WARN([No output from test program!]) + fi + rm -f pac_fconftest.out +],[ + AC_MSG_RESULT([Error]) + AC_MSG_WARN([Failed to run program to determine $pac_msg]) +],[ + AC_MSG_RESULT([$5]) + ifelse([$4],[],[],[$4=$5]) +]) +AC_LANG_POP([Fortran]) +]) +dnl +dnl PAC_FC_AVAIL_INTEGER_MODELS([INTEGER-MODELS-FLAG],[CROSS-VARIABLE]) +dnl +dnl INTEGER-MODELS-FLAG : an optional variable to be set if provided. +dnl If it isn't provided, PAC_FC_ALL_INTEGER_MODELS +dnl will be set. +dnl CROSS-VALUE : value will be used to set INTEGER-MODELS-FLAG +dnl or PAC_FC_ALL_INTEGER_MODELS if cross_compiling=yes. +dnl +dnl This is a runtime test. +dnl +AC_DEFUN([PAC_FC_AVAIL_INTEGER_MODELS],[ +AC_MSG_CHECKING([for available integer kinds]) +AC_LANG_PUSH([Fortran]) +rm -f pac_fconftest.out +AC_RUN_IFELSE([ + AC_LANG_SOURCE([ + program main + integer r, lastkind + lastkind=selected_int_kind(1) + open(8, file="pac_fconftest.out", form="formatted") + do r=2,30 + k = selected_int_kind(r) + if (k .ne. lastkind) then + write(8,*) r-1, ",", lastkind + lastkind = k + endif + if (k .le. 0) then + exit + endif + enddo + if (k.ne.lastkind) then + write(8,*) 31, ",", k + endif + close(8) + end + ]) +],[ + if test -s pac_fconftest.out ; then + pac_flag="`sed -e 's/ */ /g' pac_fconftest.out | tr '\012' ','`" + AC_MSG_RESULT([$pac_flag]) + pac_validKinds="`sed -e 's/ */ /g' pac_fconftest.out | tr '\012' ':'`" + ifelse([$1],[],[PAC_FC_ALL_INTEGER_MODELS=$pac_flag],[$1=$pac_flag]) + else + AC_MSG_RESULT([Error]) + AC_MSG_WARN([No output from test program!]) + fi + rm -f pac_fconftest.out +],[ + AC_MSG_RESULT([Error]) + AC_MSG_WARN([Failed to run program to determine available integer models]) +],[ + dnl Even when cross_compiling=yes, + dnl pac_validKinds needs to be set for PAC_FC_INTEGER_MODEL_MAP() + pac_validKinds="`echo \"$2\" | tr ',' ':'`" + AC_MSG_RESULT([$2]) + ifelse([$1],[],[PAC_FC_ALL_INTEGER_MODELS=$2],[$1=$2]) +]) +AC_LANG_POP([Fortran]) +]) +dnl +dnl PAC_FC_INTEGER_MODEL_MAP([INTEGER-MODEL-MAP-FLAG],[CROSS-VALUE])) +dnl +dnl INTEGER-MODEL-MAP-FLAG : an optional variable to be set if provided. +dnl If it isn't provided, PAC_FC_INTEGER_MODEL_MAP +dnl will be set. +dnl CROSS-VALUE : value will be used to set INTEGER-MODEL-MAP-FLAG +dnl or PAC_FC_INTEGER_MODEL_MAP if cross_compiling=yes. +dnl +dnl This test requires $pac_validKinds set by PAC_FC_ALL_INTEGER_MODELS(). +dnl +dnl This is a runtime test. +dnl +dnl Compile the C subroutine as pac_conftest.o and Link it with a Fortran main. +AC_DEFUN([PAC_FC_INTEGER_MODEL_MAP],[ +AC_REQUIRE([PAC_FC_AVAIL_INTEGER_MODELS]) +AC_MSG_CHECKING([for available integer ranges]) +AC_LANG_PUSH([C]) +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ +#ifdef F77_NAME_UPPER +#define cisize_ CISIZE +#define isize_ ISIZE +#elif defined(F77_NAME_LOWER) || defined(F77_NAME_MIXED) +#define cisize_ cisize +#define isize_ isize +#endif +int cisize_(char *,char*); +int cisize_(char *i1p, char *i2p) +{ + int isize_val=0; + isize_val = (int)(i2p - i1p); + return isize_val; +} + ]) +],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + pac_ccompile_ok=yes +],[ + pac_ccompile_ok=no +]) +AC_LANG_POP([C]) +dnl +if test "$pac_ccompile_ok" = "yes" ; then + saved_LIBS="$LIBS" + LIBS="pac_conftest.$OBJEXT $LIBS" + saved_IFS=$IFS + IFS=: + AC_LANG_PUSH([Fortran]) + pac_flag="" + for rangekind in $pac_validKinds ; do + kind="`echo $rangekind | sed -e 's/.*,//'`" + range="`echo $rangekind | sed -e 's/,.*//'`" + AC_LANG_CONFTEST([ + AC_LANG_SOURCE([ + program main + integer (kind=$kind) a(2) + integer cisize + open(8, file="pac_fconftest.out", form="formatted") + write(8,*) $range, ",", $kind, ",", cisize( a(1), a(2) ) + close(8) + end + ]) + ]) + IFS=$saved_IFS + rm -f pac_fconftest.out + AC_RUN_IFELSE([],[ + if test -s pac_fconftest.out ; then + sizes="`sed -e 's/ */ /g' pac_fconftest.out`" + pac_flag="$pac_flag { $sizes }," + else + AC_MSG_WARN([No output from test program!]) + fi + rm -f pac_fconftest.out + ],[ + AC_MSG_WARN([Fortran program fails to build or run!]) + ],[ + pac_flag="$2" + ]) + IFS=: + done + IFS=$saved_IFS + AC_MSG_RESULT([$pac_flag]) + ifelse([$1],[],[PAC_FC_INTEGER_MODEL_MAP=$pac_flag],[$1=$pac_flag]) + AC_LANG_POP([Fortran]) + LIBS="$saved_LIBS" + rm -f pac_conftest.$OBJEXT +fi +]) + + +AC_DEFUN([PAC_FC_2008_SUPPORT],[ +AC_MSG_CHECKING([for Fortran 2008 support]) + +AC_LANG_PUSH([C]) +f08_works=yes +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE( +[[ +#include + +int foo_c(CFI_cdesc_t * a_desc, CFI_cdesc_t * b_desc) +{ + char * a_row = (char*) a_desc->base_addr; + if (a_desc->type != CFI_type_int) { return 1; } + if (a_desc->rank != 2) { return 2; } + if (a_desc->dim[1].extent != b_desc->dim[0].extent) { return 3; } + return 0; +} +]])],[mv conftest.$OBJEXT conftest1.$OBJEXT],[f08_works=no]) +AC_LANG_POP([C]) + +AC_LANG_PUSH([Fortran]) +PAC_PUSH_FLAG([LIBS]) +LIBS="conftest1.$OBJEXT $LIBS" +AC_LINK_IFELSE([ + AC_LANG_SOURCE([ +MODULE F08TS_MODULE +IMPLICIT NONE + +! Test public, private, protected +REAL, PUBLIC :: x +REAL, PRIVATE :: y +LOGICAL, PROTECTED :: z + +! Test abstract +ABSTRACT INTERFACE + SUBROUTINE user_func(x, y) + INTEGER :: x(*) + REAL :: y + END SUBROUTINE +END INTERFACE + +! Test TS 29113 assumed type , assumed rank and bind(C) +INTERFACE + FUNCTION FOO(A, B, C) & + BIND(C,name="foo_c") RESULT(err) + USE, intrinsic :: iso_c_binding, ONLY : c_int + TYPE(*), DIMENSION(..) :: A, B, C + INTEGER(c_int) :: err + END FUNCTION FOO +END INTERFACE + +CONTAINS + +! Test TS 29113 asychronous attribute and optional +SUBROUTINE test1(buf, count, ierr) + INTEGER, ASYNCHRONOUS :: buf(*) + INTEGER :: count + INTEGER, OPTIONAL :: ierr +END SUBROUTINE + +! Test procedure type and non-bind(c) x in C_FUNCLOC(x) +SUBROUTINE test2(func) + USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_FUNLOC, C_FUNPTR + PROCEDURE(user_func) :: func + TYPE(C_FUNPTR) :: errhandler_fn + errhandler_fn = C_FUNLOC(func) +END SUBROUTINE + +! Test intrinsic storage_size +SUBROUTINE test3(x, size) + CHARACTER, DIMENSION(..) :: x + INTEGER, INTENT(OUT) :: size + size = storage_size(x)/8 +END SUBROUTINE test3 + +END MODULE + +!============================================== +PROGRAM MAIN +USE :: F08TS_MODULE, ONLY : FOO +IMPLICIT NONE + +INTEGER, DIMENSION(4,4) :: A, B +INTEGER, DIMENSION(2,2) :: C +INTEGER :: ERRCODE + +! Test contiguous and non-contiguous array section passing +! and linkage with C code +ERRCODE = FOO(A(1:4:2, :), B(:, 2:4:2), C) + +END PROGRAM + ])],[],[f08_works=no]) +PAC_POP_FLAG([LIBS]) +AC_LANG_POP([Fortran]) + +if test "$f08_works" = "yes" ; then + $1 +else + $2 +fi +rm -f conftest1.$OBJEXT +AC_MSG_RESULT([$f08_works]) +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_libs.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_libs.m4 new file mode 100644 index 0000000000..9dff74248b --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_libs.m4 @@ -0,0 +1,104 @@ + +dnl PAC_SET_HEADER_LIB_PATH(with_option,[default_path]) +dnl This macro looks for the --with-xxx=, --with-xxx-include and --with-xxx-lib= +dnl options and sets the library and include paths. +dnl +dnl TODO as written, this macro cannot handle a "with_option" arg that has "-" +dnl characters in it. Use AS_TR_SH (and possibly AS_VAR_* macros) to handle +dnl this case if it ever arises. +AC_DEFUN([PAC_SET_HEADER_LIB_PATH],[ + AC_ARG_WITH([$1], + [AC_HELP_STRING([--with-$1=PATH], + [specify path where $1 include directory and lib directory can be found])], + + [AS_CASE(["$withval"], + [yes|no|''], + [AC_MSG_WARN([--with[out]-$1=PATH expects a valid PATH]) + with_$1=""])], + [with_$1=$2]) + AC_ARG_WITH([$1-include], + [AC_HELP_STRING([--with-$1-include=PATH], + [specify path where $1 include directory can be found])], + [AS_CASE(["$withval"], + [yes|no|''], + [AC_MSG_WARN([--with[out]-$1-include=PATH expects a valid PATH]) + with_$1_include=""])], + []) + AC_ARG_WITH([$1-lib], + [AC_HELP_STRING([--with-$1-lib=PATH], + [specify path where $1 lib directory can be found])], + [AS_CASE(["$withval"], + [yes|no|''], + [AC_MSG_WARN([--with[out]-$1-lib=PATH expects a valid PATH]) + with_$1_lib=""])], + []) + + # The args have been sanitized into empty/non-empty values above. + # Now append -I/-L args to CPPFLAGS/LDFLAGS, with more specific options + # taking priority + + AS_IF([test -n "${with_$1_include}"], + [PAC_APPEND_FLAG([-I${with_$1_include}],[CPPFLAGS])], + [AS_IF([test -n "${with_$1}"], + [PAC_APPEND_FLAG([-I${with_$1}/include],[CPPFLAGS])])]) + + AS_IF([test -n "${with_$1_lib}"], + [PAC_APPEND_FLAG([-L${with_$1_lib}],[LDFLAGS])], + [AS_IF([test -n "${with_$1}"], + dnl is adding lib64 by default really the right thing to do? What if + dnl we are on a 32-bit host that happens to have both lib dirs available? + [PAC_APPEND_FLAG([-L${with_$1}/lib64],[LDFLAGS]) + PAC_APPEND_FLAG([-L${with_$1}/lib],[LDFLAGS])])]) +]) + + +dnl PAC_CHECK_HEADER_LIB(header.h, libname, function, action-if-yes, action-if-no) +dnl This macro checks for a header and lib. It is assumed that the +dnl user can specify a path to the includes and libs using --with-xxx=. +dnl The xxx is specified in the "with_option" parameter. +dnl +dnl NOTE: This macro expects a corresponding PAC_SET_HEADER_LIB_PATH +dnl macro (or equivalent logic) to be used before this macro is used. +AC_DEFUN([PAC_CHECK_HEADER_LIB],[ + failure=no + AC_CHECK_HEADER([$1],,failure=yes) + AC_CHECK_LIB($2,$3,,failure=yes) + if test "$failure" = "no" ; then + $4 + else + $5 + fi +]) + +dnl PAC_CHECK_HEADER_LIB_FATAL(with_option, header.h, libname, function) +dnl Similar to PAC_CHECK_HEADER_LIB, but errors out on failure +AC_DEFUN([PAC_CHECK_HEADER_LIB_FATAL],[ + PAC_CHECK_HEADER_LIB($2,$3,$4,success=yes,success=no) + if test "$success" = "no" ; then + AC_MSG_ERROR(['$2 or lib$3 library not found. Did you specify --with-$1= or --with-$1-include= or --with-$1-lib=?']) + fi +]) + +dnl PAC_CHECK_PREFIX(with_option,prefixvar) +AC_DEFUN([PAC_CHECK_PREFIX],[ + AC_ARG_WITH([$1-prefix], + [AS_HELP_STRING([[--with-$1-prefix[=DIR]]], [use the $1 + library installed in DIR, rather than the + one included in the distribution. Pass + "embedded" to force usage of the included + $1 source.])], + [if test "$withval" = "system" ; then + : + elif test "$withval" = "embedded" ; then + : + else + PAC_APPEND_FLAG([-I${with_$1_prefix}/include],[CPPFLAGS]) + if test -d "${with_$1_prefix}/lib64" ; then + PAC_APPEND_FLAG([-L${with_$1_prefix}/lib64],[LDFLAGS]) + fi + PAC_APPEND_FLAG([-L${with_$1_prefix}/lib],[LDFLAGS]) + fi + ], + [with_$1_prefix="embedded"]) + ] +) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_make.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_make.m4 new file mode 100644 index 0000000000..147e92e9c2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_make.m4 @@ -0,0 +1,315 @@ +dnl +dnl We need routines to check that make works. Possible problems with +dnl make include +dnl +dnl It is really gnumake, and contrary to the documentation on gnumake, +dnl it insists on screaming everytime a directory is changed. The fix +dnl is to add the argument --no-print-directory to the make +dnl +dnl It is really BSD 4.4 make, and can't handle 'include'. For some +dnl systems, this can be fatal; there is no fix (other than removing this +dnl alleged make). +dnl +dnl It is the OSF V3 make, and can't handle a comment in a block of target +dnl code. There is no acceptable fix. +dnl +dnl +dnl +dnl +dnl Find a make program if none is defined. +AC_DEFUN([PAC_PROG_MAKE_PROGRAM],[true +if test "X$MAKE" = "X" ; then + AC_CHECK_PROGS(MAKE,make gnumake nmake pmake smake) +fi +])dnl + +dnl/*D +dnl PAC_PROG_MAKE_INCLUDE - Check whether make supports include +dnl +dnl Synopsis: +dnl PAC_PROG_MAKE_INCLUDE([action if true],[action if false]) +dnl +dnl Output Effect: +dnl None +dnl +dnl Notes: +dnl This checks for makes that do not support 'include filename'. Some +dnl versions of BSD 4.4 make required '#include' instead; some versions of +dnl 'pmake' have the same syntax. +dnl +dnl See Also: +dnl PAC_PROG_MAKE +dnl +dnl D*/ +AC_DEFUN([PAC_PROG_MAKE_INCLUDE],[ +AC_CACHE_CHECK([whether make supports include],pac_cv_prog_make_include,[ +AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest +cat > conftest <<. +ALL: + @echo "success" +. +cat > conftest1 <<. +include conftest +. +pac_str=`$MAKE -f conftest1 2>&1` +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest conftest1 +if test "$pac_str" != "success" ; then + pac_cv_prog_make_include="no" +else + pac_cv_prog_make_include="yes" +fi +]) +if test "$pac_cv_prog_make_include" = "no" ; then + ifelse([$2],,:,[$2]) +else + ifelse([$1],,:,[$1]) +fi +])dnl + +dnl/*D +dnl PAC_PROG_MAKE_ALLOWS_COMMENTS - Check whether comments are allowed in +dnl shell commands in a makefile +dnl +dnl Synopsis: +dnl PAC_PROG_MAKE_ALLOWS_COMMENTS([false text]) +dnl +dnl Output Effect: +dnl Issues a warning message if comments are not allowed in a makefile. +dnl Executes the argument if one is given. +dnl +dnl Notes: +dnl Some versions of OSF V3 make do not all comments in action commands. +dnl +dnl See Also: +dnl PAC_PROG_MAKE +dnl D*/ +dnl +AC_DEFUN([PAC_PROG_MAKE_ALLOWS_COMMENTS],[ +AC_CACHE_CHECK([whether make allows comments in actions], +pac_cv_prog_make_allows_comments,[ +AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest +cat > conftest <<. +SHELL=/bin/sh +ALL: + @# This is a valid comment! + @echo "success" +. +pac_str=`$MAKE -f conftest 2>&1` +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest +if test "$pac_str" != "success" ; then + pac_cv_prog_make_allows_comments="no" +else + pac_cv_prog_make_allows_comments="yes" +fi +]) +if test "$pac_cv_prog_make_allows_comments" = "no" ; then + AC_MSG_WARN([Your make does not allow comments in target code. +Using this make may cause problems when building programs. +You should consider using gnumake instead.]) + ifelse([$1],,[$1]) +fi +])dnl + +dnl/*D +dnl PAC_PROG_MAKE_VPATH - Check whether make supports source-code paths. +dnl +dnl Synopsis: +dnl PAC_PROG_MAKE_VPATH +dnl +dnl Output Effect: +dnl Sets the variable 'VPATH' to either +dnl.vb +dnl VPATH = .:${srcdir} +dnl.ve +dnl or +dnl.vb +dnl .PATH: . ${srcdir} +dnl.ve +dnl +dnl Notes: +dnl The test checks that the path works with implicit targets (some makes +dnl support only explicit targets with 'VPATH' or 'PATH'). +dnl +dnl NEED TO DO: Check that $< works on explicit targets. +dnl +dnl See Also: +dnl PAC_PROG_MAKE +dnl +dnl D*/ +AC_DEFUN([PAC_PROG_MAKE_VPATH],[ +AC_SUBST(VPATH) +dnl AM_IGNORE(VPATH) +AC_CACHE_CHECK([for virtual path format], +pac_cv_prog_make_vpath,[ +AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -rf conftest* +mkdir conftestdir +cat >conftestdir/a.c < conftest <&1 | grep 'conftestdir/a.c'` +if test -n "$ac_out" ; then + pac_cv_prog_make_vpath="VPATH" +else + rm -f conftest + cat > conftest <&1 | grep 'conftestdir/a.c'` + if test -n "$ac_out" ; then + pac_cv_prog_make_vpath=".PATH" + else + pac_cv_prog_make_vpath="neither VPATH nor .PATH works" + fi +fi +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -rf conftest* +]) +if test "$pac_cv_prog_make_vpath" = "VPATH" ; then + VPATH='VPATH=.:${srcdir}' +elif test "$pac_cv_prog_make_vpath" = ".PATH" ; then + VPATH='.PATH: . ${srcdir}' +fi +])dnl + +dnl/*D +dnl PAC_PROG_MAKE_SET_CFLAGS - Check whether make sets CFLAGS +dnl +dnl Synopsis: +dnl PAC_PROG_MAKE_SET_CFLAGS([action if true],[action if false]) +dnl +dnl Output Effects: +dnl Executes the first argument if 'CFLAGS' is set by 'make'; executes +dnl the second argument if 'CFLAGS' is not set by 'make'. +dnl +dnl Notes: +dnl If 'CFLAGS' is set by make, you may wish to override that choice in your +dnl makefile. +dnl +dnl See Also: +dnl PAC_PROG_MAKE +dnl D*/ +AC_DEFUN([PAC_PROG_MAKE_SET_CFLAGS],[ +AC_CACHE_CHECK([whether make sets CFLAGS], +pac_cv_prog_make_set_cflags,[ +AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest +cat > conftest <&1` +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest +if test "$pac_str" = "XX" ; then + pac_cv_prog_make_set_cflags="no" +else + pac_cv_prog_make_set_cflags="yes" +fi +]) +if test "$pac_cv_prog_make_set_cflags" = "no" ; then + ifelse([$2],,:,[$2]) +else + ifelse([$1],,:,[$1]) +fi +])dnl + +dnl/*D +dnl PAC_PROG_MAKE_CLOCK_SKEW - Check whether there is a problem with +dnl clock skew in suing make. +dnl +dnl Effect: +dnl Sets the cache variable 'pac_cv_prog_make_found_clock_skew' to yes or no +dnl D*/ +AC_DEFUN([PAC_PROG_MAKE_CLOCK_SKEW],[ +AC_CACHE_CHECK([whether clock skew breaks make], +pac_cv_prog_make_found_clock_skew,[ +AC_REQUIRE([PAC_PROG_MAKE_PROGRAM]) +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest* +cat > conftest < conftest.out 2>&1 +if grep -i skew conftest >/dev/null 2>&1 ; then + pac_cv_prog_make_found_clock_skew=yes +else + pac_cv_prog_make_found_clock_skew=no +fi +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest* +]) +dnl We should really do something if we detect clock skew. The question is, +dnl what? +if test "$pac_cv_prog_make_found_clock_skew" = "yes" ; then + AC_MSG_WARN([Clock skew found by make. The configure and build may fail. +Consider building in a local instead of NFS filesystem.]) +fi +]) + +dnl/*D +dnl PAC_PROG_MAKE - Checks for the varieties of MAKE, including support for +dnl VPATH +dnl +dnl Synopsis: +dnl PAC_PROG_MAKE +dnl +dnl Output Effect: +dnl Sets 'MAKE' to the make program to use if 'MAKE' is not already set. +dnl Sets the variable 'SET_CFLAGS' to 'CFLAGS =' if make sets 'CFLAGS'. +dnl +dnl Notes: +dnl This macro uses 'PAC_PROG_MAKE_INCLUDE', +dnl 'PAC_PROG_MAKE_ALLOWS_COMMENTS', 'PAC_PROG_MAKE_VPATH', and +dnl 'PAC_PROG_MAKE_SET_CFLAGS'. See those commands for details about their +dnl actions. +dnl +dnl It may call 'AC_PROG_MAKE_SET', which sets 'SET_MAKE' to 'MAKE = @MAKE@' +dnl if the make program does not set the value of make, otherwise 'SET_MAKE' +dnl is set to empty; if the make program echos the directory name, then +dnl 'SET_MAKE' is set to 'MAKE = $MAKE'. +dnl D*/ +AC_DEFUN([PAC_PROG_MAKE],[ +PAC_PROG_MAKE_PROGRAM +PAC_PROG_MAKE_CLOCK_SKEW +PAC_PROG_MAKE_INCLUDE +PAC_PROG_MAKE_ALLOWS_COMMENTS +PAC_PROG_MAKE_VPATH +AC_SUBST(SET_CFLAGS) +dnl AM_IGNORE(SET_CFLAGS) +PAC_PROG_MAKE_SET_CFLAGS([SET_CFLAGS='CFLAGS=']) +if test "$pac_cv_prog_make_echos_dir" = "no" ; then + AC_PROG_MAKE_SET +else + SET_MAKE="MAKE=${MAKE-make}" +fi +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_mpi.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_mpi.m4 new file mode 100644 index 0000000000..f0013a9bd1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_mpi.m4 @@ -0,0 +1,519 @@ +dnl +dnl/*D +dnl PAC_LIB_MPI - Check for MPI library +dnl +dnl Synopsis: +dnl PAC_LIB_MPI([action if found],[action if not found]) +dnl +dnl Output Effect: +dnl +dnl Notes: +dnl Currently, only checks for lib mpi and mpi.h. Later, we will add +dnl MPI_Pcontrol prototype (const int or not?). +dnl +dnl Prerequisites: +dnl autoconf version 2.13 (for AC_SEARCH_LIBS) +dnl D*/ +dnl Other tests to add: +dnl Version of MPI +dnl MPI-2 I/O? +dnl MPI-2 Spawn? +dnl MPI-2 RMA? +dnl PAC_LIB_MPI([found text],[not found text]) +AC_DEFUN([PAC_LIB_MPI],[ +dnl Set the prereq to 2.50 to avoid having +AC_PREREQ(2.50) +if test "X$pac_lib_mpi_is_building" != "Xyes" ; then + # Use CC if TESTCC is defined + if test "X$pac_save_level" != "X" ; then + pac_save_TESTCC="${TESTCC}" + pac_save_TESTCPP="${TESTCPP}" + CC="$pac_save_CC" + if test "X$pac_save_CPP" != "X" ; then + CPP="$pac_save_CPP" + fi + fi + # Look for MPILIB first if it is defined + AC_SEARCH_LIBS(MPI_Init,$MPILIB mpi mpich) + if test "$ac_cv_search_MPI_Init" = "no" ; then + ifelse($2,, + AC_MSG_ERROR([Could not find MPI library]),[$2]) + fi + AC_CHECK_HEADER(mpi.h,pac_have_mpi_h="yes",pac_have_mpi_h="no") + if test $pac_have_mpi_h = "no" ; then + ifelse($2,, + AC_MSG_ERROR([Could not find mpi.h include file]),[$2]) + fi + if test "X$pac_save_level" != "X" ; then + CC="$pac_save_TESTCC" + CPP="$pac_save_TESTCPP" + fi +fi +ifelse($1,,,[$1]) +]) + +dnl This should also set MPIRUN. +dnl +dnl/*D +dnl PAC_ARG_MPI_TYPES - Add command-line switches for different MPI +dnl environments +dnl +dnl Synopsis: +dnl PAC_ARG_MPI_TYPES([default]) +dnl +dnl Output Effects: +dnl Adds the following command line options to configure +dnl+ \-\-with\-mpich[=path] - MPICH. 'path' is the location of MPICH commands +dnl. \-\-with\-ibmmpi - IBM MPI +dnl. \-\-with\-lammpi[=path] - LAM/MPI +dnl. \-\-with\-mpichnt - MPICH NT +dnl- \-\-with\-sgimpi - SGI MPI +dnl If no type is selected, and a default ("mpich", "ibmmpi", or "sgimpi") +dnl is given, that type is used as if '--with-' was given. +dnl +dnl Sets 'CC', 'F77', 'TESTCC', 'TESTF77', and 'MPILIBNAME'. Does `not` +dnl perform an AC_SUBST for these values. +dnl Also sets 'MPIBOOT' and 'MPIUNBOOT'. These are used to specify +dnl programs that may need to be run before and after running MPI programs. +dnl For example, 'MPIBOOT' may start demons necessary to run MPI programs and +dnl 'MPIUNBOOT' will stop those demons. +dnl +dnl The two forms of the compilers are to allow for tests of the compiler +dnl when the MPI version of the compiler creates executables that cannot +dnl be run on the local system (for example, the IBM SP, where executables +dnl created with mpcc will not run locally, but executables created +dnl with xlc may be used to discover properties of the compiler, such as +dnl the size of data types). +dnl +dnl Historical note: +dnl Some common autoconf tests, such as AC_CHECK_SIZEOF, used to require +dnl running a program. But some MPI compilers (often really compilation +dnl scripts) produced programs that could only be run with special commands, +dnl such as a batch submission system. To allow these test programs to be +dnl run, a separate set of compiler variables, TESTCC, TESTF77, etc., +dnl were defined. However, in later versions of autoconf, it both became +dnl unnecessary to run programs for tests such as AC_CHECK_SIZEOF and +dnl it became necessary to define CC etc. before invoking AC_PROG_CC (and +dnl the othe language compilers), because those commands now do much, much +dnl more than just determining the compiler. +dnl +dnl To address the change, we still define the TESTCC etc. compilers where +dnl possible to allow the use of AC_TRY_RUN when required, but we define +dnl the CC etc variables and do not define ac_cv_prog_CC etc., as these +dnl cause autoconf to skip all of the other initialization code that +dnl AC_PROG_CC etc. runs. Note also that this command must occur before +dnl AC_PROG_CC (or anything that might cause AC_PROG_CC to be invoked). +dnl +dnl See also: +dnl PAC_LANG_PUSH_COMPILERS, PAC_LIB_MPI +dnl D*/ +AC_DEFUN([PAC_ARG_MPI_TYPES],[ +# known types +PAC_ARG_MPI_KNOWN_TYPES +# find compilers +PAC_MPI_FIND_COMPILER_SCRIPTS +PAC_MPI_FIND_COMPILERS +# check for MPI library +PAC_MPI_CHECK_MPI_LIB +]) +dnl +dnl To keep autoconf from prematurely invoking the compiler check scripts, +dnl we need a command that first sets the compilers and a separate one +dnl that makes any necessary checks for libraries +dnl +AC_DEFUN([PAC_ARG_MPI_KNOWN_TYPES],[ +AC_ARG_WITH(mpich, +[--with-mpich=path - Assume that we are building with MPICH], +ac_mpi_type=mpich) +# Allow MPICH as well as MPICH +AC_ARG_WITH(mpich, +[--with-mpich=path - Assume that we are building with MPICH], +ac_mpi_type=mpich) +AC_ARG_WITH(lammpi, +[--with-lammpi=path - Assume that we are building with LAM/MPI], +ac_mpi_type=lammpi) +AC_ARG_WITH(ibmmpi, +[--with-ibmmpi - Use the IBM SP implementation of MPI], +ac_mpi_type=ibmmpi) +AC_ARG_WITH(sgimpi, +[--with-sgimpi - Use the SGI implementation of MPI], +ac_mpi_type=sgimpi) +AC_ARG_WITH(mpichnt, +[--with-mpichnt - Use MPICH for Windows NT ], +ac_mpi_type=mpichnt) +AC_ARG_WITH(mpi, +[--with-mpi=path - Use an MPI implementation with compile scripts mpicc + and mpif77 in path/bin],ac_mpi_type=generic) + +if test "X$ac_mpi_type" = "X" ; then + if test "X$1" != "X" ; then + ac_mpi_type=$1 + else + ac_mpi_type=unknown + fi +fi +if test "$ac_mpi_type" = "unknown" -a "$pac_lib_mpi_is_building" = "yes" ; then + ac_mpi_type="mpich" +fi +]) +dnl +dnl Because autoconf insists on moving code to the beginning of +dnl certain definitions, it is *not possible* to define a single command +dnl that selects compilation scripts and also check for other options. +dnl Thus, this needs to be divided into +dnl MPI_FIND_COMPILER_SCRIPTS +dnl which can fail (i.e., not find a script), and +dnl MPI_FIND_COMPILERS +dnl which runs the various PROC_xx for the compilers. +dnl WARNING: this function ignores --program-suffix and --program-prefix. +dnl However, this function is not currently used at all. +AC_DEFUN([PAC_MPI_FIND_COMPILER_SCRIPTS],[ +# Set defaults +MPIRUN_NP="-np " +MPIEXEC_N="-n " +AC_SUBST(MPIRUN_NP) +AC_SUBST(MPIEXEC_N) +dnl +AC_ARG_VAR([MPIEXEC],[Name and path of mpiexec program]) +AC_ARG_VAR([MPIRUN],[Name and path of mpirun program]) +AC_ARG_VAR([MPIBOOT],[Name and path of program to run before mpirun]) +AC_ARG_VAR([MPIUNBOOT],[Name and path of program to run after all mpirun]) +AC_ARG_VAR([MPICC],[Name and absolute path of program used to compile MPI programs in C]) +AC_ARG_VAR([MPIF77],[Name and absolute path of program used to compile MPI programs in F77]) +AC_ARG_VAR([MPICXX],[Name and absolute path of program used to compile MPI programs in C++]) +AC_ARG_VAR([MPIF90],[Name and absolute path of program used to compile MPI programs in F90]) +# +# Check for things that will cause trouble. For example, +# if MPICC is defined but does not contain a / or \, then PATH_PROG will +# ignore the value +if test -n "$MPICC" ; then + case $MPICC in +changequote(<<,>>) + [\\/]* | ?:[\\/]*) +changequote([,]) + # Ok, PATH_PROG will figure it out + ;; + *) + AC_MSG_ERROR([MPICC must be set to an absolute path if it is set]) + esac +fi +if test -n "$MPICXX" ; then + case $MPICXX in +changequote(<<,>>) + [\\/]* | ?:[\\/]*) +changequote([,]) + # Ok, PATH_PROG will figure it out + ;; + *) + AC_MSG_ERROR([MPICXX must be set to an absolute path if it is set]) + esac +fi +if test -n "$MPIF77" ; then + case $MPIF77 in +changequote(<<,>>) + [\\/]* | ?:[\\/]*) +changequote([,]) + # Ok, PATH_PROG will figure it out + ;; + *) + AC_MSG_ERROR([MPIF77 must be set to an absolute path if it is set]) + esac +fi +if test -n "$MPIF90" ; then + case $MPIF90 in +changequote(<<,>>) + [\\/]* | ?:[\\/]*) +changequote([,]) + # Ok, PATH_PROG will figure it out + ;; + *) + AC_MSG_ERROR([MPIF90 must be set to an absolute path if it is set]) + esac +fi + +case $ac_mpi_type in + mpich) + dnl + dnl This isn't correct. It should try to get the underlying compiler + dnl from the mpicc and mpif77 scripts or mpireconfig + if test "X$pac_lib_mpi_is_building" != "Xyes" ; then + PAC_PUSH_FLAG([PATH]) + if test "$with_mpich" != "yes" -a "$with_mpich" != "no" ; then + # Look for commands; if not found, try adding bin to the + # path + if test ! -x $with_mpich/mpicc -a -x $with_mpich/bin/mpicc ; then + with_mpich="$with_mpich/bin" + fi + PATH=$with_mpich:${PATH} + fi + AC_PATH_PROG(MPICC,mpicc) + if test -z "$TESTCC" ; then TESTCC=${CC-cc} ; fi + CC="$MPICC" + # Note that autoconf may unconditionally change the value of + # CC (!) in some other command. Thus, we define CCMASTER + CCMASTER=$CC + # Force autoconf to respect this choice + ac_ct_CC=$CC + # to permit configure codes to recover the correct CC. This + # is an ugly not-quite-correct workaround for the fact that + # does not want you to change the C compiler once you have set it + # (But since it does so unconditionally, it silently creates + # bogus output files.) + AC_PATH_PROG(MPIF77,mpif77) + if test -z "$TESTF77" ; then TESTF77=${F77-f77} ; fi + F77="$MPIF77" + AC_PATH_PROG(MPIFC,mpif90) + if test -z "$TESTFC" ; then TESTFC=${FC-f90} ; fi + FC="$MPIFC" + AC_PATH_PROG(MPICXX,mpiCC) + if test -z "$TESTCXX" ; then TESTCXX=${CXX-CC} ; fi + CXX="$MPICXX" + # We may want to restrict this to the path containing mpirun + AC_PATH_PROG(MPIEXEC,mpiexec) + AC_PATH_PROG(MPIRUN,mpirun) + AC_PATH_PROG(MPIBOOT,mpichboot) + AC_PATH_PROG(MPIUNBOOT,mpichstop) + PAC_POP_FLAG([PATH]) + MPILIBNAME="mpich" + else + # All of the above should have been passed in the environment! + : + fi + ;; + + mpichnt) + ;; + + lammpi) + dnl + dnl This isn't correct. It should try to get the underlying compiler + dnl from the mpicc and mpif77 scripts or mpireconfig + PAC_PUSH_FLAG([PATH]) + if test "$with_mpich" != "yes" -a "$with_mpich" != "no" ; then + # Look for commands; if not found, try adding bin to the path + if test ! -x $with_lammpi/mpicc -a -x $with_lammpi/bin/mpicc ; then + with_lammpi="$with_lammpi/bin" + fi + PATH=$with_lammpi:${PATH} + fi + AC_PATH_PROG(MPICC,mpicc) + if test -z "$TESTCC" ; then TESTCC=${CC-cc} ; fi + CC="$MPICC" + AC_PATH_PROG(MPIF77,mpif77) + if test -z "$TESTCC" ; then TESTF77=${F77-f77} ; fi + F77="$MPIF77" + AC_PATH_PROG(MPIFC,mpif90) + TESTFC=${FC-f90} + if test -z "$TESTFC" ; then TESTFC=${FC-f90} ; fi + FC="$MPIFC" + AC_PATH_PROG(MPICXX,mpiCC) + if test -z "$TESTCXX" ; then TESTCXX=${CXX-CC} ; fi + CXX="$MPICXX" + PAC_POP_FLAG([PATH]) + MPILIBNAME="lammpi" + MPIBOOT="lamboot" + MPIUNBOOT="wipe" + MPIRUN="mpirun" + ;; + + ibmmpi) + AC_CHECK_PROGS(MPCC,mpcc) + AC_CHECK_PROGS(MPXLF,mpxlf mpfort) + if test -z "$MPCC" -o -z "$MPXLF" ; then + AC_MSG_ERROR([Could not find IBM MPI compilation scripts. Either mpcc or mpxlf/mpfort is missing]) + fi + if test -z "$TESTCC" ; then TESTCC=${CC-xlC} ; fi + if test -z "$TESTF77" ; then TESTF77=${F77-xlf}; fi + CC=mpcc; F77=$MPXLF + # There is no mpxlf90, but the options langlvl and free can + # select the Fortran 90 version of xlf + if test "$enable_f90" != no ; then + AC_CHECK_PROGS(MPIXLF90,mpxlf90 mpfort) + if test -z "$TESTFC" ; then TESTFC=${FC-xlf90}; fi + if test "X$MPIXLF90" != "X" ; then + FC="$MPIXLF90" + else + FC="$MPXLF -qlanglvl=90ext -qfree=f90" + fi + fi + MPILIBNAME="" + cross_compiling=yes + # Turn off the autoconf version 3 warning message + ac_tool_warned=yes + ;; + + sgimpi) + if test -z "$TESTCC" ; then TESTCC=${CC:=cc} ; fi + if test -z "$TESTF77" ; then TESTF77=${F77:=f77} ; fi + if test -z "$TESTCXX" ; then TESTCXX=${CXX:=CC} ; fi + if test -z "$TESTFC" ; then TESTFC=${FC:=f90} ; fi + # Must check for the MPI library in a separate macro - adding + # a test here will cause autoconf to prematurely define the + # C compiler + MPIRUN=mpirun + MPIBOOT="" + MPIUNBOOT="" + ;; + + generic) + # in $with_mpi/bin or $with_mpi + if test "X$MPICC" = "X" ; then + if test -x "$with_mpi/bin/mpicc" ; then + MPICC=$with_mpi/bin/mpicc + elif test -x "$with_mpi/mpicc" ; then + MPICC=$with_mpi/mpicc + fi + fi + if test "X$MPICXX" = "X" ; then + if test -x "$with_mpi/bin/mpicxx" ; then + MPICXX=$with_mpi/bin/mpicxx + elif test -x "$with_mpi/mpicxx" ; then + MPICXX=$with_mpi/mpicxx + fi + fi + if test "X$MPIF77" = "X" ; then + if test -x "$with_mpi/bin/mpif77" ; then + MPIF77=$with_mpi/bin/mpif77 + elif test -x "$with_mpi/mpif77" ; then + MPIF77=$with_mpi/mpif77 + fi + fi + if test "X$MPIF90" = "X" ; then + if test -x "$with_mpi/bin/mpif90" ; then + MPIF90=$with_mpi/bin/mpif90 + elif test -x "$with_mpi/mpif90" ; then + MPIF90=$with_mpi/mpif90 + fi + fi + if test "X$MPIEXEC" = "X" ; then + if test -x "$with_mpi/bin/mpiexec" ; then + MPIEXEC=$with_mpi/bin/mpiexec + elif test -x "$with_mpi/mpiexec" ; then + MPIEXEC=$with_mpi/mpiexec + fi + fi + CC=$MPICC + F77=$MPIF77 + if test "X$MPICXX" != "X" ; then CXX=$MPICXX ; fi + if test "X$MPIF90" != "X" ; then F90=$MPIF90 ; fi + ;; + + *) + # Use the default choices for the compilers + ;; +esac +]) + +AC_DEFUN([PAC_MPI_FIND_COMPILERS],[ +# Tell autoconf to determine properties of the compilers (these are the +# compilers for MPI programs) +PAC_PROG_CC +if test "$enable_f77" != no -a "$enable_fortran" != no ; then + AC_PROG_F77 +fi +if test "$enable_cxx" != no ; then + AC_PROG_CXX +fi +if test "$enable_f90" != no ; then + PAC_PROG_FC +fi +]) + +dnl +dnl This uses the selected CC etc to check for include paths and libraries +AC_DEFUN([PAC_MPI_CHECK_MPI_LIB],[ +AC_REQUIRE([AC_PROG_CC]) +case $ac_mpi_type in + mpich) + ;; + + mpichnt) + dnl + dnl This isn't adequate, but it helps with using MPICH-NT/SDK.gcc + PAC_PUSH_FLAG([CFLAGS]) + CFLAGS="$CFLAGS -I$with_mpichnt/include" + PAC_PUSH_FLAG([CPPFLAGS]) + CPPFLAGS="$CPPFLAGS -I$with_mpichnt/include" + PAC_PUSH_FLAG([LDFLAGS]) + LDFLAGS="$LDFLAGS -L$with_mpichnt/lib" + AC_CHECK_LIB(mpich,MPI_Init,found="yes",found="no") + if test "$found" = "no" ; then + AC_CHECK_LIB(mpich,MPI_Init,found="yes",found="no") + fi + if test "$enable_cxx" != no ; then + AC_PROG_CXX + fi + if test "$enable_f90" != no ; then + PAC_PROG_FC + fi + # Set defaults for the TEST versions if not already set + if test -z "$TESTCC" ; then TESTCC=${CC:=cc} ; fi + if test -z "$TESTF77" ; then TESTF77=${F77:=f77} ; fi + if test -z "$TESTCXX" ; then TESTCXX=${CXX:=CC} ; fi + if test -z "$TESTFC" ; then TESTFC=${FC:=f90} ; fi + if test "$found" = "no" ; then + PAC_POP_FLAG([CFLAGS]) + PAC_POP_FLAG([CPPFLAGS]) + PAC_POP_FLAG([LDFLAGS]) + fi + ;; + + lammpi) + ;; + + ibmmpi) + ;; + + sgimpi) + AC_CHECK_LIB(mpi,MPI_Init) + if test "$ac_cv_lib_mpi_MPI_Init" = "yes" ; then + MPILIBNAME="mpi" + fi + ;; + + generic) + AC_SEARCH_LIBS(MPI_Init,mpi mpich mpich) + if test "$ac_cv_lib_mpi_MPI_Init" = "yes" ; then + MPILIBNAME="mpi" + fi + ;; + + *) + ;; +esac +]) + +dnl +dnl/*D +dnl PAC_MPI_F2C - Determine if MPI has the MPI-2 functions MPI_xxx_f2c and +dnl MPI_xxx_c2f +dnl +dnl Output Effect: +dnl Define 'HAVE_MPI_F2C' if the routines are found. +dnl +dnl Notes: +dnl Looks only for 'MPI_Request_c2f'. +dnl D*/ +AC_DEFUN([PAC_MPI_F2C],[ +AC_CACHE_CHECK([for MPI F2C and C2F routines], +pac_cv_mpi_f2c, +[ +AC_TRY_LINK([#include "mpi.h"], +[MPI_Request request;MPI_Fint a;a = MPI_Request_c2f(request);], +pac_cv_mpi_f2c="yes",pac_cv_mpi_f2c="no") +]) +if test "$pac_cv_mpi_f2c" = "yes" ; then + AC_DEFINE(HAVE_MPI_F2C,1,[Define if MPI has F2C]) +fi +]) +dnl +dnl/*D +dnl PAC_HAVE_ROMIO - make mpi.h include mpio.h if romio enabled +dnl +dnl Output Effect: +dnl expands @HAVE_ROMIO@ in mpi.h into #include "mpio.h" +dnl D*/ +AC_DEFUN([PAC_HAVE_ROMIO],[ +if test "$enable_romio" = "yes" ; then HAVE_ROMIO='#include "mpio.h"'; fi +AC_SUBST(HAVE_ROMIO) +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_romio.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_romio.m4 new file mode 100644 index 0000000000..39dd76dab2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_romio.m4 @@ -0,0 +1,858 @@ +dnl +dnl This files contains additional macros for using autoconf to +dnl build configure scripts. +dnl +dnl Almost all of this file is taken from the aclocal.m4 of MPICH +dnl +dnl Get the format of Fortran names. Uses F77, FFLAGS, and sets WDEF. +dnl If the test fails, sets NOF77 to 1, HAVE_FORTRAN to 0. +dnl +dnl +AC_DEFUN([PAC_GET_FORTNAMES],[ + rm -f confftest.f confftest.$OBJEXT + cat > confftest.f < /dev/null 2>&1 + if test ! -s confftest.$OBJEXT ; then + AC_MSG_WARN([Unable to test Fortran compiler. Compiling a test +program failed to produce an object file]) + NOF77=1 + elif test -z "$FORTRANNAMES" ; then + # MAC OS X (and probably FreeBSD need strings - (not strings -a) + # Cray doesn't accept -a ... + allstrings="-a" + if test $arch_CRAY ; then + allstrings="" + elif strings - confftest.$OBJEXT < /dev/null >/dev/null 2>&1 ; then + allstrings="-" + elif strings -a confftest.$OBJEXT < /dev/null >/dev/null 2>&1 ; then + allstrings="-a" + fi + + nameform1=`strings $allstrings confftest.$OBJEXT | grep mpir_init_fop_ | head -1` + nameform2=`strings $allstrings confftest.$OBJEXT | grep MPIR_INIT_FOP | head -1` + nameform3=`strings $allstrings confftest.$OBJEXT | grep mpir_init_fop | head -1` + nameform4=`strings $allstrings confftest.$OBJEXT | grep mpir_init_fop__ | head -1` + rm -f confftest.f confftest.$OBJEXT + if test -n "$nameform4" ; then + echo "Fortran externals are lower case and have two trailing underscores" + FORTRANNAMES="FORTRANDOUBLEUNDERSCORE" + elif test -n "$nameform1" ; then + # We don't set this in CFLAGS; it is a default case + echo "Fortran externals have a trailing underscore and are lowercase" + FORTRANNAMES="FORTRANUNDERSCORE" + elif test -n "$nameform2" ; then + echo "Fortran externals are uppercase" + FORTRANNAMES="FORTRANCAPS" + elif test -n "$nameform3" ; then + echo "Fortran externals are lower case" + FORTRANNAMES="FORTRANNOUNDERSCORE" + else + AC_MSG_WARN([Unable to determine the form of Fortran external names. +Make sure that the compiler $F77 can be run on this system. +Turning off Fortran (-nof77 being assumed)]) + NOF77=1 + fi + fi + if test -n "$FORTRANNAMES" ; then + WDEF="-D$FORTRANNAMES" + fi + # Delete confftest files with any extension. This catches the case + # where auxillary files, such as coverage files, are removed. + rm -f confftest.* + ])dnl +dnl +define(PAC_GET_SPECIAL_SYSTEM_INFO,[ +# +if test -n "$arch_IRIX"; then + AC_MSG_CHECKING(for IRIX OS version) + dnl This block of code replaces a generic "IRIX" arch value with + dnl IRIX__ + dnl For example + dnl IRIX_5_4400 (IRIX 5.x, using MIPS 4400) + osversion=`uname -r | sed 's/\..*//'` + dnl Note that we need to allow brackets here, so we briefly turn off + dnl the macro quotes + changequote(,)dnl + dnl Get the second field (looking for 6.1) + osvminor=`uname -r | sed 's/[0-9]\.\([0-9]*\)\..*/\1/'` + changequote([,])dnl + AC_MSG_RESULT($osversion) + dnl Get SGI processor count by quick hack + AC_MSG_CHECKING(for IRIX cpucount) + changequote(,)dnl + cpucount=`hinv | grep '[0-9]* [0-9]* MHZ IP[0-9]* Proc' | cut -f 1 -d' '` + if test "$cpucount" = "" ; then + cpucount=`hinv | grep 'Processor [0-9]*:' | wc -l | sed -e 's/ //g'` + fi + changequote([,])dnl + if test "$cpucount" = "" ; then + AC_MSG_RESULT([Could not determine cpucount. Please send]) + hinv + AC_MSG_ERROR([to romio-maint@mcs.anl.gov]) + fi + AC_MSG_RESULT($cpucount) + dnl + AC_MSG_CHECKING(for IRIX cpumodel) + dnl The tail -1 is necessary for multiple processor SGI boxes + dnl We might use this to detect SGI multiprocessors and recommend + dnl -comm=shared + cputype=`hinv -t cpu | tail -1 | cut -f 3 -d' '` + if test -z "$cputype" ; then + AC_MSG_RESULT([Could not get cputype from hinv -t cpu command. Please send]) + hinv -t cpu 2>&1 + hinv -t cpu | cut -f 3 -d' ' 2>&1 + AC_MSG_ERROR([to romio-maint@mcs.anl.gov]) + fi + AC_MSG_RESULT($cputype) + dnl echo "checking for osversion and cputype" + dnl cputype may contain R4400, R2000A/R3000, or something else. + dnl We may eventually need to look at it. + if test -z "$osversion" ; then + AC_MSG_RESULT([Could not determine OS version. Please send]) + uname -a + AC_MSG_ERROR([to romio-maint@mcs.anl.gov]) + elif test $osversion = 4 ; then + true + elif test $osversion = 5 ; then + true + elif test $osversion = 6 ; then + true + else + AC_MSG_RESULT([Could not recognize the version of IRIX (got $osversion). +ROMIO knows about versions 4, 5 and 6; the version being returned from +uname -r is $osversion. Please send]) + uname -a 2>&1 + hinv 2>&1 + AC_MSG_ERROR([to romio-maint@mcs.anl.gov]) + fi + AC_MSG_CHECKING(for cputype) + OLD_ARCH=IRIX + IRIXARCH="$ARCH_$osversion" + dnl Now, handle the chip set + changequote(,)dnl + cputype=`echo $cputype | sed -e 's%.*/%%' -e 's/R//' | tr -d "[A-Z]"` + changequote([,])dnl + case $cputype in + 3000) ;; + 4000) ;; + 4400) ;; + 4600) ;; + 5000) ;; + 8000) ;; + 10000);; + 12000);; + *) + AC_MSG_WARN([Unexpected IRIX/MIPS chipset $cputype. Please send the output]) + uname -a 2>&1 + hinv 2>&1 + AC_MSG_WARN([to romio-maint@mcs.anl.gov +ROMIO will continue and assume that the cputype is +compatible with a MIPS 4400 processor.]) + cputype=4400 + ;; + esac + AC_MSG_RESULT($cputype) + IRIXARCH="$IRIXARCH_$cputype" + echo "IRIX-specific architecture is $IRIXARCH" +fi +])dnl +dnl +dnl +define(PAC_TEST_MPI,[ + AC_MSG_CHECKING(if a simple MPI program compiles and links) + rm -f mpitest.c + cat > mpitest.c <&5 + $cmd >&5 2>&5 + if test ! -x conftest$EXEEXT ; then + echo "$as_me:$LINENO: failed program was:" >&5 + sed 's/^/| /' mpitest.c >&5 + rm -f conftest$EXEEXT mpitest.c + AC_MSG_ERROR([Unable to compile a simple MPI program. +Use environment variables to provide the location of MPI libraries and +include directories]) + else + rm -f conftest$EXEEXT mpitest.c + fi +AC_MSG_RESULT(yes) +])dnl +dnl +dnl +dnl +define(PAC_NEEDS_FINT,[ + AC_MSG_CHECKING(if MPI_Fint is defined in the MPI implementation) + cat > mpitest1.c < /dev/null 2>&1 + if test ! -s mpitest1.$OBJEXT ; then + NEEDS_MPI_FINT="#define NEEDS_MPI_FINT" + CFLAGS="$CFLAGS -DNEEDS_MPI_FINT" + AC_MSG_RESULT(no) + rm -f mpitest1.$OBJEXT mpitest1.c + else + NEEDS_MPI_FINT="" + AC_MSG_RESULT(yes) + rm -f mpitest1.$OBJEXT mpitest1.c + fi +])dnl +dnl +define(PAC_MPI_LONG_LONG_INT,[ + AC_MSG_CHECKING(if MPI_LONG_LONG_INT is defined in mpi.h) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MPI_LONG_LONG_INT,,[Define if mpi has long long it]) + else + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT mpitest.c +])dnl +dnl +dnl PAC_LONG_LONG_64: check if there is a 64-bit long long +dnl +define(PAC_LONG_LONG_64,[ +if test -n "$longlongsize" ; then + if test "$longlongsize" = 8 ; then + echo "defining MPI_Offset as long long in C and integer*8 in Fortran" + AC_DEFINE(HAVE_LONG_LONG_64,,[Define if long long is 64 bits]) + DEFINE_MPI_OFFSET="typedef long long MPI_Offset;" + FORTRAN_MPI_OFFSET="integer*8" + LL="\%lld" + elif test "$longlongsize" = "int" ; then # a hack to set MPI_Offset as int + echo "defining MPI_Offset as int in C and integer in Fortran" + DEFINE_MPI_OFFSET="typedef int MPI_Offset;" + FORTRAN_MPI_OFFSET="integer" + AC_DEFINE(MPI_OFFSET_IS_INT,,[Define if MPI_Offset is int]) + LL="\%d" + MPI_OFFSET_KIND1="!" + MPI_OFFSET_KIND2="!" + else + echo "defining MPI_Offset as long in C and integer in Fortran" + DEFINE_MPI_OFFSET="typedef long MPI_Offset;" + FORTRAN_MPI_OFFSET="integer" + LL="\%ld" + MPI_OFFSET_KIND1="!" + MPI_OFFSET_KIND2="!" + fi +else + PAC_GET_TYPE_SIZE(long long, longlongsize) + if test -n "$longlongsize" ; then + if test "$longlongsize" = 8 ; then + PAC_TEST_LONG_LONG() + else + echo "defining MPI_Offset as long in C and integer in Fortran" + DEFINE_MPI_OFFSET="typedef long MPI_Offset;" + FORTRAN_MPI_OFFSET="integer" + LL="\%ld" + MPI_OFFSET_KIND1="!" + MPI_OFFSET_KIND2="!" + fi + else +dnl check if longlong is not supported or only its size cannot be determined +dnl because the program cannot be run. + rm -f ltest.c + cat > ltest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + echo "assuming size of long long is 8bytes; use '-longlongsize' to indicate otherwise" + rm -f conftest$EXEEXT ltest.c + echo "defining MPI_Offset as long long in C and integer*8 in Fortran" + AC_DEFINE(HAVE_LONG_LONG_64,,[Define if long long is 64 bits]) + DEFINE_MPI_OFFSET="typedef long long MPI_Offset;" + FORTRAN_MPI_OFFSET="integer*8" + LL="\%lld" + else + echo "assuming long long is not available; use '-longlongsize' to indicate otherwise" + echo "defining MPI_Offset as long in C and integer in Fortran" + DEFINE_MPI_OFFSET="typedef long MPI_Offset;" + FORTRAN_MPI_OFFSET="integer" + LL="\%ld" + MPI_OFFSET_KIND1="!" + MPI_OFFSET_KIND2="!" + fi + fi +fi +])dnl +dnl +dnl +define(PAC_MPI_INFO,[ + AC_MSG_CHECKING(if MPI_Info functions are defined in the MPI implementation) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MPI_INFO,1,[Define if MPI_Info available]) + HAVE_MPI_INFO="#define HAVE_MPI_INFO" + MPI_FINFO1="!" + MPI_FINFO2="!" + MPI_FINFO3="!" + MPI_FINFO4="!" + else + AC_MSG_RESULT(no) + BUILD_MPI_INFO=1 + MPI_FINFO1=" INTEGER MPI_MAX_INFO_KEY, MPI_MAX_INFO_VAL" + MPI_FINFO2=" PARAMETER (MPI_MAX_INFO_KEY=255, MPI_MAX_INFO_VAL=1024)" + MPI_FINFO3=" INTEGER MPI_INFO_NULL" + MPI_FINFO4=" PARAMETER (MPI_INFO_NULL=0)" + fi + rm -f conftest$EXEEXT mpitest.c +])dnl +dnl +dnl +define(PAC_MPI_DARRAY_SUBARRAY,[ + AC_MSG_CHECKING(if darray and subarray constructors are defined in the MPI implementation) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MPI_DARRAY_SUBARRAY,,[Define if MPI Darray available]) + HAVE_MPI_DARRAY_SUBARRAY="#define HAVE_MPI_DARRAY_SUBARRAY" + MPI_FARRAY1="!" + MPI_FARRAY2="!" + MPI_FARRAY3="!" + MPI_FARRAY4="!" + MPI_FARRAY5="!" + MPI_FARRAY6="!" + MPI_FARRAY7="!" + else + AC_MSG_RESULT(no) + BUILD_MPI_ARRAY=1 + MPI_FARRAY1=" INTEGER MPI_ORDER_C, MPI_ORDER_FORTRAN" + MPI_FARRAY2=" PARAMETER (MPI_ORDER_C=56, MPI_ORDER_FORTRAN=57)" + MPI_FARRAY3=" INTEGER MPI_DISTRIBUTE_BLOCK, MPI_DISTRIBUTE_CYCLIC" + MPI_FARRAY4=" INTEGER MPI_DISTRIBUTE_NONE, MPI_DISTRIBUTE_DFLT_DARG" + MPI_FARRAY5=" PARAMETER (MPI_DISTRIBUTE_BLOCK=121, MPI_DISTRIBUTE_CYCLIC=122)" + MPI_FARRAY6=" PARAMETER (MPI_DISTRIBUTE_NONE=123)" + MPI_FARRAY7=" PARAMETER (MPI_DISTRIBUTE_DFLT_DARG=-49767)" + fi + rm -f conftest$EXEEXT mpitest.c +])dnl +dnl +dnl +define(PAC_CHECK_MPI_SGI_INFO_NULL,[ + AC_MSG_CHECKING([if MPI_INFO_NULL is defined in mpi.h]) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + cp adio/sgi/mpi3.1/*.h include + else + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT mpitest.c +])dnl +dnl +dnl +dnl +define(PAC_CHECK_MPIOF_H,[ + AC_MSG_CHECKING(if mpiof.h is included in mpif.h) + rm -f mpitest.f + cat > mpitest.f < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + MPIOF_H_INCLUDED=1 + else + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT mpitest.f +])dnl +dnl +dnl +dnl check if pread64 is defined in IRIX. needed on IRIX 6.5 +dnl +define(PAC_HAVE_PREAD64,[ + AC_MSG_CHECKING(if pread64 is defined) + rm -f conftest.c + cat > conftest.c < + main() + { + int fd=0, buf=0, i=0; + off64_t off=0; + pread64(fd, &buf, i, off); + } +EOF + rm -f conftest$EXEEXT + $CC $USER_CFLAGS -o conftest$EXEEXT conftest.c > /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PREAD64,,[Define if pread64 available]) + else + AC_MSG_RESULT(no) + fi +rm -f conftest$EXEEXT conftest.c +])dnl +dnl +dnl +define(PAC_TEST_MPI_SGI_type_is_contig,[ + AC_MSG_CHECKING(if MPI_SGI_type_is_contig is defined) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + AC_DEFINE(NO_MPI_SGI_type_is_contig,,[Define if no MPI type is contig]) + fi + rm -f conftest$EXEEXT mpitest.c +])dnl +dnl +dnl +dnl +define(PAC_TEST_MPI_COMBINERS,[ + AC_MSG_CHECKING(if MPI-2 combiners are defined in mpi.h) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MPI_COMBINERS,,[Define if MPI combiners available]) + else + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT mpitest.c +])dnl +dnl +dnl +dnl PAC_MPI_OFFSET_KIND() +dnl +dnl tries to determine the Fortran 90 kind parameter for 8-byte integers +dnl +define(PAC_MPI_OFFSET_KIND, +[ +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest* +# Determine the extension for Fortran 90 files (not all compilers accept +# .f and not all accept .f90) +if test -z "$ac_f90ext" ; then + if test -z "$FC" ; then + # This list should correspond to the list in aclocal_fc.m4 + AC_CHECK_PROGS(FC,ifort pgf90 pathf90 pathf95 xlf90 xlf95 f90 epcf90 \ + f95 fort lf95 gfortran g95 ifc efc) + fi + AC_MSG_CHECKING([for extension for Fortran 90 programs]) + ac_f90ext="f90" + ac_f90compile='${FC-f90} -c $FCFLAGS conftest.$ac_f90ext 1>&AC_FD_CC' + cat > conftest.$ac_f90ext < conftest.$ac_f90ext < conftest.$ac_f90ext + program main + integer i + i = selected_int_kind(16) + open(8, file="conftest.out", form="formatted") + write (8,*) i + close(8) + stop + end +EOF +if test -z "$FC" ; then + FC=f90 +fi +KINDVAL="" +if $FC -o conftest$EXEEXT conftest.$ac_f90ext >/dev/null 2>&1 ; then + ./conftest$EXEEXT >/dev/null 2>&1 + if test -s conftest.out ; then + KINDVAL=`cat conftest.out` + fi +fi +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest* +if test -n "$KINDVAL" -a "$KINDVAL" != "-1" ; then + AC_MSG_RESULT($KINDVAL) + MPI_OFFSET_KIND1=" INTEGER MPI_OFFSET_KIND" + MPI_OFFSET_KIND2=" PARAMETER (MPI_OFFSET_KIND=$KINDVAL)" +else + AC_MSG_RESULT(unavailable) +fi +])dnl +dnl +dnl +define(PAC_TEST_MPI_HAVE_OFFSET_KIND,[ + AC_MSG_CHECKING(if MPI_OFFSET_KIND is defined in mpif.h) + rm -f mpitest.f + cat > mpitest.f < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + MPI_OFFSET_KIND1="!" + MPI_OFFSET_KIND2="!" + else + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT mpitest.f +])dnl +dnl +dnl +dnl PAC_GET_XFS_MEMALIGN +dnl +dnl +define(PAC_GET_XFS_MEMALIGN, +[AC_MSG_CHECKING([for memory alignment needed for direct I/O]) +rm -f memalignval +rm -f /tmp/romio_tmp.bin +AC_TEST_PROGRAM([#include +#include +#include +#include +main() { + struct dioattr st; + int fd = open("/tmp/romio_tmp.bin", O_RDWR | O_CREAT, 0644); + FILE *f=fopen("memalignval","w"); + if (fd == -1) exit(1); + if (!f) exit(1); + fcntl(fd, F_DIOINFO, &st); + fprintf( f, "%u\n", st.d_mem); + exit(0); +}],Pac_CV_NAME=`cat memalignval`,Pac_CV_NAME="") +rm -f memalignval +rm -f /tmp/romio_tmp.bin +if test -n "$Pac_CV_NAME" -a "$Pac_CV_NAME" != 0 ; then + AC_MSG_RESULT($Pac_CV_NAME) + CFLAGS="$CFLAGS -DXFS_MEMALIGN=$Pac_CV_NAME" +else + AC_MSG_RESULT(unavailable, assuming 128) + CFLAGS="$CFLAGS -DXFS_MEMALIGN=128" +fi +])dnl +dnl + +define(PAC_HAVE_MOUNT_NFS,[ + AC_MSG_CHECKING([if MOUNT_NFS is defined in the include files]) + rm -f conftest.c + cat > conftest.c < +#include + main() + { + int i=MOUNT_NFS; + } +EOF + rm -f conftest$EXEEXT + $CC $USER_CFLAGS -o conftest$EXEEXT conftest.c > /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + ROMIO_HAVE_MOUNT_NFS=1 + AC_DEFINE(HAVE_MOUNT_NFS,,[Define if MOUNT_NFS defined]) + else + ROMIO_HAVE_MOUNT_NFS=0 + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT conftest.c +])dnl +dnl +dnl +dnl PAC_MPI_OFFSET_KIND_4BYTE() +dnl +dnl tries to determine the Fortran 90 kind parameter for 4-byte integers +dnl +define(PAC_MPI_OFFSET_KIND_4BYTE, +[AC_MSG_CHECKING([for Fortran 90 KIND parameter for 4-byte integers]) +rm -f kind.f kind.$OBJEXT kind$EXEEXT +cat < kind.f + program main + integer i + i = selected_int_kind(8) + open(8, file="k.out", form="formatted") + write (8,*) i + close(8) + stop + end +EOF +if test -z "$FC" ; then + FC=f90 +fi +KINDVAL="" +if $FC -o kind$EXEEXT kind.f >/dev/null 2>&1 ; then + ./kind >/dev/null 2>&1 + if test -s k.out ; then + KINDVAL=`cat k.out` + fi +fi +rm -f kind$EXEEXT k.out kind.f kind.$OBJEXT +if test -n "$KINDVAL" -a "$KINDVAL" != "-1" ; then + AC_MSG_RESULT($KINDVAL) + MPI_OFFSET_KIND1=" INTEGER MPI_OFFSET_KIND" + MPI_OFFSET_KIND2=" PARAMETER (MPI_OFFSET_KIND=$KINDVAL)" +else + AC_MSG_RESULT(unavailable) +fi +])dnl +dnl +dnl +define(PAC_FUNC_STRERROR,[ + AC_MSG_CHECKING([for strerror()]) + rm -f conftest.c + cat > conftest.c < + main() + { + char *s = strerror(5); + } +EOF + rm -f conftest$EXEEXT + $CC $USER_CFLAGS -o conftest$EXEXT conftest.c >> config.log 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_STRERROR,,[Define if strerror available]) + else + AC_MSG_RESULT(no) + AC_MSG_CHECKING([for sys_errlist]) + rm -f conftest.c +changequote(,) + cat > conftest.c < + main() + { + extern char *sys_errlist[]; + printf("%s\n", sys_errlist[34]); + } +EOF +changequote([,]) + rm -f conftest$EXEEXT + $CC $USER_CFLAGS -o conftest$EXEEXT conftest.c > config.log 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SYSERRLIST,,[Define if syserrlist available]) + else + AC_MSG_RESULT(no) + fi + fi + rm -f conftest$EXEEXT conftest.c +])dnl +dnl +define(PAC_TEST_MPIR_STATUS_SET_BYTES,[ + AC_MSG_CHECKING(if MPIR_Status_set_bytes is defined) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_STATUS_SET_BYTES,,[Define if status set bytes available]) + else + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT mpitest.c +])dnl +define(PAC_TEST_MPIU_FUNCS,[ + AC_MSG_CHECKING(support for MPICH memory macros) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MPIU_FUNCS,1,[Define if MPICH memory tracing macros defined]) + else + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT mpitest.c +])dnl +dnl +define(PAC_TEST_MPI_GREQUEST,[ + AC_MSG_CHECKING(support for generalized requests) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MPI_GREQUEST,1,[Define if generalized requests avaliable]) + DEFINE_HAVE_MPI_GREQUEST="#define HAVE_MPI_GREQUEST 1" + else + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT mpitest.c +])dnl + +define(PAC_TEST_MPI_GREQUEST_EXTENSIONS,[ + AC_MSG_CHECKING(support for non-standard extended generalized requests) + rm -f mpitest.c + cat > mpitest.c < /dev/null 2>&1 + if test -x conftest$EXEEXT ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MPI_GREQUEST_EXTENTIONS,1,[Define if non-standard generalized requests extensions avaliable]) + DEFINE_HAVE_MPI_GREQUEST_EXTENSIONS="#define HAVE_MPI_GREQUEST_EXTENSIONS 1" + else + AC_MSG_RESULT(no) + fi + rm -f conftest$EXEEXT mpitest.c +])dnl diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_runlog.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_runlog.m4 new file mode 100644 index 0000000000..f22e6ddbc3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_runlog.m4 @@ -0,0 +1,218 @@ +dnl +dnl PAC_RUN_LOG mimics _AC_RUN_LOG which is autoconf internal routine. +dnl We also make sure PAC_RUN_LOG can be used in AS_IF, so the last +dnl test command should have terminating ]), i.e. without newline before ]). +dnl +AC_DEFUN([PAC_RUNLOG],[ +{ AS_ECHO(["$as_me:$LINENO: $1"]) >&AS_MESSAGE_LOG_FD + (eval $1) 2>&AS_MESSAGE_LOG_FD + ac_status=$? + AS_ECHO(["$as_me:$LINENO: \$? = $ac_status"]) >&AS_MESSAGE_LOG_FD + test $ac_status = 0; }]) + +dnl +dnl PAC_COMMAND_IFELSE is written to replace AC_TRY_EVAL with added logging +dnl to config.log, i.e. AC_TRY_EVAL does not log anything to config.log. +dnl If autoconf provides AC_COMMAND_IFELSE or AC_EVAL_IFELSE, +dnl AC_COMMAND_IFELSE dnl should be replaced by the official autoconf macros. +dnl +dnl PAC_COMMAND_IFELSE(COMMMAND,[ACTION-IF-RUN-OK],[ACTION-IF-RUN-FAIL]) +dnl +AC_DEFUN([PAC_COMMAND_IFELSE],[ +AS_IF([PAC_RUNLOG([$1])],[ + $2 +],[ + AS_ECHO(["$as_me: program exited with status $ac_status"]) >&AS_MESSAGE_LOG_FD + m4_ifvaln([$3],[ + (exit $ac_status) + $3 + ]) +]) +]) + +AC_DEFUN([PAC_RUNLOG_IFELSE],[ +dnl pac_TESTLOG is the internal temporary logfile for this macro. +pac_TESTLOG="pac_test.log" +rm -f $pac_TESTLOG +PAC_COMMAND_IFELSE([$1 > $pac_TESTLOG],[ + ifelse([$2],[],[],[$2]) +],[ + AS_ECHO(["*** $1 :"]) >&AS_MESSAGE_LOG_FD + cat $pac_TESTLOG >&AS_MESSAGE_LOG_FD + ifelse([$3],[],[],[$3]) +]) +rm -f $pac_TESTLOG +]) + + +dnl PAC_VAR_PUSHVAL(VARNAME, [LastSavedValue])) +dnl +dnl Save the content of the shell variable, VARNAME, onto a stack. +dnl The saved value of VARNAME is restorable with respect to the nesting +dnl of the macro. +dnl +dnl The Last saved value of VARNAME on the stack is stored in shell variable +dnl pac_LastSavedValueOf_$VARNAME if the 2nd argument is NOT supplied. +dnl If the 2nd argument is present, the last saved value will be stored +dnl in the 2nd argument instead. +dnl +dnl The First saved value of VARNAME on the stack is stored in shell variable +dnl dnl pac_FirstSavedValueOf_$VARNAME. +dnl +AC_DEFUN([PAC_VAR_PUSHVAL],[ +# START of PUSHVAL +dnl define local m4-name pac_stk_level. +AS_VAR_PUSHDEF([pac_stk_level], [pac_stk_$1_level]) +AS_VAR_SET_IF([pac_stk_level],[ + AS_VAR_ARITH([pac_stk_level], [$pac_stk_level + 1]) +],[ + AS_VAR_SET([pac_stk_level], [0]) +]) +dnl AS_ECHO_N(["PUSHVAL: pac_stk_level = $pac_stk_level, "]) +dnl Save the content of VARNAME, i.e. $VARNAME, onto the stack. +AS_VAR_SET([pac_stk_$1_$pac_stk_level],[$$1]) +AS_VAR_IF([pac_stk_level], [0], [ + dnl Save the 1st pushed value of VARNAME as pac_FirstSavedValueOf_$VARNAME + AS_VAR_COPY([pac_FirstSavedValueOf_$1],[pac_stk_$1_$pac_stk_level]) +]) +ifelse([$2],[],[ + dnl Save the last pushed value of VARNAME as pac_LastSavedValueOf_$VARNAME + AS_VAR_COPY([pac_LastSavedValueOf_$1],[pac_stk_$1_$pac_stk_level]) + dnl AS_ECHO(["pac_LastSavedValueOf_$1 = $pac_LastSavedValueOf_$1"]) +],[ + dnl Save the last pushed value of VARNAME as $2 + AS_VAR_COPY([$2],[pac_stk_$1_$pac_stk_level]) + dnl AS_ECHO(["$2 = $$2"]) +]) +AS_VAR_POPDEF([pac_stk_level]) +# END of PUSHVAL +]) +dnl +dnl +dnl +dnl PAC_VAR_POPVAL(VARNAME) +dnl +dnl Restore variable, VARNAME, from the stack. +dnl This macro is safe with respect to the nesting. +dnl Some minimal checking of nesting balance of PAC_VAR_PUSH[POP]VAL() +dnl is done here. +dnl +AC_DEFUN([PAC_VAR_POPVAL],[ +# START of POPVAL +dnl define local m4-name pac_stk_level. +AS_VAR_PUSHDEF([pac_stk_level], [pac_stk_$1_level]) +AS_VAR_SET_IF([pac_stk_level],[ + AS_VAR_IF([pac_stk_level],[-1],[ + AC_MSG_WARN(["Imbalance of PUSHVAL/POPVAL of $1"]) + ],[ + dnl AS_ECHO_N(["POPVAL: pac_stk_level = $pac_stk_level, "]) + AS_VAR_COPY([$1],[pac_stk_$1_$pac_stk_level]) + dnl AS_ECHO(["popped_val = $$1"]) + AS_VAR_ARITH([pac_stk_level], [ $pac_stk_level - 1 ]) + ]) +],[ + AC_MSG_WARN(["Uninitialized PUSHVAL/POPVAL of $1"]) +]) +AS_VAR_POPDEF([pac_stk_level]) +# END of POPVAL +]) +dnl +dnl +dnl +dnl PAC_COMPILE_IFELSE_LOG is a wrapper around AC_COMPILE_IFELSE with the +dnl output of ac_compile to a specified logfile instead of AS_MESSAGE_LOG_FD +dnl +dnl PAC_COMPILE_IFELSE_LOG(logfilename, input, +dnl [action-if-true], [action-if-false]) +dnl +dnl where input, [action-if-true] and [action-if-false] are used +dnl in AC_COMPILE_IFELSE(input, [action-if-true], [action-if-false]). +dnl This macro is nesting safe. +dnl +AC_DEFUN([PAC_COMPILE_IFELSE_LOG],[ +dnl +dnl Instead of defining our own ac_compile and do AC_TRY_EVAL +dnl on these variables. We modify ac_compile used by AC_*_IFELSE +dnl by piping the output of the command to a logfile. The reason is that +dnl 1) AC_TRY_EVAL is discouraged by Autoconf. 2) defining our ac_compile +dnl could mess up the usage and order of *CFLAGS, LDFLAGS and LIBS in +dnl these commands, i.e. deviate from how GNU standard uses these variables. +dnl +dnl Replace ">&AS_MESSAGE_LOG_FD" by "> FILE 2>&1" in ac_compile. +dnl Save a copy of ac_compile on a stack +dnl which is safe through nested invocations of this macro. +PAC_VAR_PUSHVAL([ac_compile]) +dnl Modify ac_compile based on the unmodified ac_compile. +ac_compile="`echo $pac_FirstSavedValueOf_ac_compile | sed -e 's|>.*$|> $1 2>\&1|g'`" +AC_COMPILE_IFELSE([$2],[ + ifelse([$3],[],[:],[$3]) +],[ + ifelse([$4],[],[:],[$4]) +]) +dnl Restore the original ac_compile from the stack. +PAC_VAR_POPVAL([ac_compile]) +]) +dnl +dnl +dnl +dnl PAC_LINK_IFELSE_LOG is a wrapper around AC_LINK_IFELSE with the +dnl output of ac_link to a specified logfile instead of AS_MESSAGE_LOG_FD +dnl +dnl PAC_LINK_IFELSE_LOG(logfilename, input, +dnl [action-if-true], [action-if-false]) +dnl +dnl where input, [action-if-true] and [action-if-false] are used +dnl in AC_LINK_IFELSE(input, [action-if-true], [action-if-false]). +dnl This macro is nesting safe. +dnl +AC_DEFUN([PAC_LINK_IFELSE_LOG],[ +dnl +dnl Instead of defining our own ac_link and do AC_TRY_EVAL +dnl on these variables. We modify ac_link used by AC_*_IFELSE +dnl by piping the output of the command to a logfile. The reason is that +dnl 1) AC_TRY_EVAL is discouraged by Autoconf. 2) defining our ac_link +dnl could mess up the usage and order of *CFLAGS, LDFLAGS and LIBS in +dnl these commands, i.e. deviate from how GNU standard uses these variables. +dnl +dnl Replace ">&AS_MESSAGE_LOG_FD" by "> FILE 2>&1" in ac_link. +dnl Save a copy of ac_link on a stack +dnl which is safe through nested invocations of this macro. +PAC_VAR_PUSHVAL([ac_link]) +dnl Modify ac_link based on the unmodified ac_link. +ac_link="`echo $pac_FirstSavedValueOf_ac_link | sed -e 's|>.*$|> $1 2>\&1|g'`" +dnl +AC_LINK_IFELSE([$2],[ + ifelse([$3],[],[:],[$3]) +],[ + ifelse([$4],[],[:],[$4]) +]) +dnl Restore the original ac_link from the stack. +PAC_VAR_POPVAL([ac_link]) +]) +dnl +dnl +dnl +dnl PAC_COMPLINK_IFELSE (input1, input2, [action-if-true], [action-if-false]) +dnl +dnl where input1 and input2 are either AC_LANG_SOURCE or AC_LANG_PROGRAM +dnl enclosed input programs. +dnl +dnl The macro first compiles input1 and uses the object file created +dnl as part of LIBS during linking. This macro is nesting safe. +dnl +AC_DEFUN([PAC_COMPLINK_IFELSE],[ +AC_COMPILE_IFELSE([$1],[ + PAC_RUNLOG([mv conftest.$OBJEXT pac_conftest.$OBJEXT]) + PAC_VAR_PUSHVAL([LIBS]) + LIBS="pac_conftest.$OBJEXT $pac_FirstSavedValueOf_LIBS" + AC_LINK_IFELSE([$2],[ + ifelse([$3],[],[:],[$3]) + ],[ + ifelse([$4],[],[:],[$4]) + ]) + PAC_VAR_POPVAL([LIBS]) + rm -f pac_conftest.$OBJEXT +],[ + ifelse([$4],[],[:],[$4]) +]) +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_shl.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_shl.m4 new file mode 100644 index 0000000000..f974bfa226 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_shl.m4 @@ -0,0 +1,500 @@ +dnl +dnl Definitions for creating shared libraries +dnl +dnl The purpose of these definitions is to provide common support for +dnl shared libraries, with *or without* the use of the GNU Libtool package. +dnl For many of our important platforms, the Libtool approach is overkill, +dnl and can be particularly painful for developers. +dnl +dnl To use libtool, you need macros that are defined by libtool for libtool +dnl Don't even think about the consequences of this for updating and for +dnl using user-versions of libtool :( +dnl +dnl !!!!!!!!!!!!!!!!!!!!! +dnl libtool requires ac 2.50 !!!!!!!!!!!!!!!!! +dnl +dnl builtin(include,libtool.m4) +dnl +dnl/*D +dnl PAC_ARG_SHAREDLIBS - Add --enable-sharedlibs=kind to configure. +dnl +dnl Synopsis: +dnl PAC_ARG_SHAREDLIBS +dnl +dnl Output effects: +dnl Adds '--enable-sharedlibs=kind' to the command line. If this is enabled, +dnl then based on the value of 'kind', programs are selected for the +dnl names 'CC_SHL' and 'CC_LINK_SHL' that configure will substitute for in +dnl 'Makefile.in's. These symbols are generated by 'simplemake' when +dnl shared library support is selected. +dnl The variable 'C_LINKPATH_SHL' is set to the option to specify the +dnl path to search at runtime for libraries (-rpath in gcc/GNU ld). +dnl This can be turned off with --disable-rpath , which is appropriate +dnl for libraries and for executables that may be installed in different +dnl locations. +dnl The variable 'SHLIB_EXT' is set to the extension used by shared +dnl libraries; under most forms of Unix, this is 'so'; under Mac OS/X, this +dnl is 'dylib', and under Windows (including cygwin), this is 'dll'. +dnl +dnl Supported values of 'kind' include \: +dnl+ gcc - Use gcc to create both shared objects and libraries +dnl. osx-gcc - Use gcc on Mac OS/X to create both shared objects and +dnl libraries +dnl. solaris-cc - Use native Solaris cc to create shared objects and +dnl libraries +dnl. cygwin-gcc - Use gcc on Cygwin to create shared objects and libraries +dnl- none - The same as '--disable-sharedlibs' +dnl +dnl Others will be added as experience dictates. Likely names are +dnl + libtool - For general GNU libtool +dnl - linux-pgcc - For Portland group under Linux +dnl +dnl Notes: +dnl Shared libraries are only partially implemented. Additional symbols +dnl will probably be defined, including symbols to specify how shared library +dnl search paths are specified and how shared library names are set. +dnl D*/ +AC_DEFUN([PAC_ARG_SHAREDLIBS],[ + +AC_ARG_ENABLE(shared, + AC_HELP_STRING([--enable-shared], [Enable shared library builds]),, + enable_shared=no) + +AC_ARG_ENABLE(rpath, + AC_HELP_STRING([--enable-rpath], + [Determine whether the rpath is set when programs are + compiled and linked when shared libraries are built. + The default is yes; use --disable-rpath to turn this + feature off; in that case, shared libraries will be + found according to the rules for your system (e.g., in + LD_LIBRARY_PATH)]),,enable_rpath=yes) + +AC_ARG_ENABLE(sharedlibs, +[ --enable-sharedlibs=kind - Enable shared libraries. kind may be + gcc - Standard gcc and GNU ld options for creating shared libraries + osx-gcc - Special options for gcc needed only on OS/X + solaris-cc - Solaris native (SPARC) compilers for 32 bit systems + cygwin-gcc - Special options for gcc needed only for cygwin + none - same as --disable-sharedlibs + Only gcc, osx-gcc, and solaris-cc are currently supported +],,enable_sharedlibs=default) + +if test "$enable_sharedlibs" = "default" ; then + if test "$enable_shared" = "yes" ; then + AS_CASE([$host], + [*-*-darwin*], [enable_sharedlibs=gcc-osx], + [*-*-cygwin*|*-*-mingw*|*-*-pw32*|*-*-cegcc*], [enable_sharedlibs=cygwin-gcc], + [*-*-sunos*], [enable_sharedlibs=solaris-gcc], + [enable_sharedlibs=gcc]) + else + enable_sharedlibs=none + fi +fi + +# If --enable-sharedlibs is given, but --enable-shared is not, throw +# an error +if test "$enable_sharedlibs" != "no" -a "$enable_sharedlibs" != "none" ; then + if test "$enable_shared" = "no" ; then + AC_MSG_ERROR([--enable-sharedlibs cannot be used without --enable-shared]) + fi +fi + +CC_SHL=true +C_LINK_SHL=true +C_LINKPATH_SHL="" +SHLIB_EXT=unknown +SHLIB_FROM_LO=no +SHLIB_INSTALL='$(INSTALL_PROGRAM)' +case "$enable_sharedlibs" in + no|none) + ;; + gcc-osx|osx-gcc) + AC_MSG_RESULT([Creating shared libraries using GNU for Mac OSX]) + C_LINK_SHL='${CC} -dynamiclib -undefined suppress -single_module -flat_namespace' + CC_SHL='${CC} -fPIC' + # No way in osx to specify the location of the shared libraries at link + # time (see the code in createshlib in mpich/src/util) + # As of 10.5, -Wl,-rpath,dirname should work . The dirname + # must be a single directory, not a colon-separated list (use multiple + # -Wl,-rpath,path for each of the paths in the list). However, os x + # apparently records the library full path, so rpath isn't as useful + # as it is on other systems + C_LINKPATH_SHL="" + SHLIB_EXT="dylib" + enable_sharedlibs="osx-gcc" + ;; + gcc) + AC_MSG_RESULT([Creating shared libraries using GNU]) + # Not quite right yet. See mpich/util/makesharedlib + # Use syntax that works in both Make and the shell + #C_LINK_SHL='${CC} -shared -Wl,-r' + C_LINK_SHL='${CC} -shared' + # For example, include the libname as ${LIBNAME_SHL} + #C_LINK_SHL='${CC} -shared -Wl,-h,' + # May need -fPIC . Test to see which one works. + for sh_arg in "-fPIC" "-fpic" "-KPIC" ; do + PAC_C_CHECK_COMPILER_OPTION($sh_arg,works=yes,works=no) + if test "$works" = "yes" ; then + CC_SHL="${CC} ${sh_arg}" + break + fi + done + if test "$works" != "yes"; then + AC_MSG_ERROR([Cannot build shared libraries with this compiler]) + fi + # This used to have -Wl,-rpath earlier, but that causes problems + # on many systems. + if test $enable_rpath = "yes" ; then + C_LINKPATH_SHL="-Wl,-rpath," + fi + SHLIB_EXT=so + # We need to test that this isn't osx. The following is a + # simple hack + osname=`uname -s` + case $osname in + *Darwin*|*darwin*) + AC_MSG_ERROR([You must specify --enable-sharedlibs=osx-gcc for Mac OS/X]) + ;; + *CYGWIN*|*cygwin*) + AC_MSG_ERROR([You must specify --enable-sharedlibs=cygwin-gcc for Cygwin]) + ;; + *SunOS*) + AC_MSG_ERROR([You must specify --enable-sharedlibs=solaris-gcc for Solaris with gcc]) + ;; + esac + ;; + + cygwin|cygwin-gcc|gcc-cygwin) + AC_MSG_RESULT([Creating shared libraries using GNU under CYGWIN]) + C_LINK_SHL='${CC} -shared' + CC_SHL='${CC}' + # DLL Libraries need to be in the user's path (!) + C_LINKPATH_SHL="" + SHLIB_EXT="dll" + enable_sharedlibs="cygwin-gcc" + ;; + + libtool) + # set TRY_LIBTOOL to yes to experiment with libtool. You are on your + # own - only send fixes, not bug reports. + if test "$TRY_LIBTOOL" != yes ; then + AC_MSG_ERROR([Creating shared libraries using libtool not yet supported]) + else + # Using libtool requires a heavy-weight process to test for + # various stuff that libtool needs. Without this, you'll get a + # bizarre error message about libtool being unable to find + # configure.in or configure.ac (!) + # Libtool expects to see at least enable-shared. + if test "X$enable_shared" = "X" ; then enable_shared=yes ; fi + # Initialize libtool + # This works, but libtool version 2 places the object files + # in a different place, making it harder to integrate with + # our base approach. Disabling for now + dnl LT_PREREQ([2.2.6]) + dnl LT_INIT([disable-shared]) + AC_MSG_ERROR([To use this test verison, edit aclocal_shl.m4]) + # Likely to be + # either CC or CC_SHL is libtool $cc + CC_SHL='${LIBTOOL} --mode=compile ${CC}' + # CC_LINK_SHL includes the final installation path + # For many systems, the link may need to include *all* libraries + # (since many systems don't allow any unsatisfied dependencies) + # We need to give libtool the .lo file, not the .o files + SHLIB_FROM_LO=yes + # We also need to add -no-undefined when the compiler is gcc and + # we are building under cygwin + sysname=`uname -s | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` + isCygwin=no + case "$sysname" in + *CYGWIN*) isCygwin=yes ;; + esac + if test "$isCygwin" = yes ; then + C_LINK_SHL='${LIBTOOL} --mode=link ${CC} -no-undefined -rpath ${libdir}' + else + C_LINK_SHL='${LIBTOOL} --mode=link ${CC} -rpath ${libdir}' + fi + if test $enable_rpath = "yes" ; then + C_LINKPATH_SHL="-rpath " + fi + # We also need a special install process with libtool. Note that this + # will also install the static libraries + SHLIB_INSTALL='$(LIBTOOL) --mode=install $(INSTALL_PROGRAM)' + # Note we may still need to add + #'$(LIBTOOL) --mode=finish $(libdir)' + fi + ;; +dnl +dnl Other, such as solaris-cc + solaris|solaris-cc) + AC_MSG_RESULT([Creating shared libraries using Solaris]) + # pic32 is appropriate for both 32 and 64 bit Solaris + C_LINK_SHL='${CC} -G -xcode=pic32' + CC_SHL='${CC} -xcode=pic32' + if test $enable_rpath = "yes" ; then + C_LINKPATH_SHL="-R" + fi + SHLIB_EXT=so + enable_sharedlibs="solaris-cc" + ;; + + solaris-gcc) + # This is the same as gcc, except for the C_LINKPATH_SHL + AC_MSG_RESULT([Creating shared libraries using Solaris with gcc]) + C_LINK_SHL='${CC} -shared' + CC_SHL='${CC} -fPIC' + if test $enable_rpath = "yes" ; then + C_LINKPATH_SHL="-R" + fi + SHLIB_EXT=so + enable_sharedlibs="solaris-gcc" + ;; + + linuxppc-xlc) + # This is only the beginning of xlc support, thanks to andy@vpac.org + CC_SHL='${CC} -qmkshrobj' + # More recent versions allow multiple args, separated by commas + if test $enable_rpath = "yes" ; then + C_LINKPATH_SHL="-Wl,-rpath," + fi + #C_LINKPATH_SHL="-Wl,-rpath -Wl," + C_LINK_SHL='${CC} -shared -qmkshrobj' + SHLIB_EXT=so + # Note that the full line should be more like + # $CLINKER -shared -qmkshrobj -Wl,-h,$libbase.$slsuffix -o ../shared/$libbase.$slsuffix *.o $OtherLibs + # for the appropriate values of $libbase and $slsuffix + # The -h name sets the name of the object; this is necessary to + # ensure that the dynamic linker can find the proper shared library. + ;; + + *) + AC_MSG_ERROR([Unknown value $enable_sharedlibs for enable-sharedlibs. Values should be gcc or osx-gcc]) + enable_sharedlibs=no + ;; +esac +# Check for the shared-library extension +PAC_CC_SHLIB_EXT +dnl +AC_SUBST(CC_SHL) +AC_SUBST(C_LINK_SHL) +AC_SUBST(C_LINKPATH_SHL) +AC_SUBST(SHLIB_EXT) +AC_SUBST(SHLIB_FROM_LO) +AC_SUBST(SHLIB_INSTALL) +]) + +dnl /*D +dnl PAC_xx_SHAREDLIBS - Get compiler and linker for shared libraries +dnl These routines may be used to determine the compiler and the +dnl linker to be used in creating shared libraries +dnl Rather than set predefined variable names, they set an argument +dnl (if provided) +dnl +dnl Synopsis +dnl PAC_CC_SHAREDLIBS(type,CCvar,CLINKvar) +dnl D*/ +AC_DEFUN([PAC_CC_SHAREDLIBS], +[ +pac_kinds=$1 +ifelse($1,,[ + pac_prog="" + AC_CHECK_PROG(pac_prog,gcc,yes,no) + # If we are gcc but OS X, set the special type + # We need a similar setting for cygwin + if test "$pac_prog" = yes ; then + osname=`uname -s` + case $osname in + *Darwin*|*darwin*) pac_kinds=gcc-osx + ;; + *) pac_kinds=gcc + ;; + esac + fi + pac_prog="" + AC_CHECK_PROG(pac_prog,libtool,yes,no) + if test "$pac_prog" = yes ; then pac_kinds="$pac_kinds libtool" ; fi +]) +for pac_arg in $pac_kinds ; do + case $pac_arg in + gcc) + # For example, include the libname as ${LIBNAME_SHL} + #C_LINK_SHL='${CC} -shared -Wl,-h,' + pac_cc_sharedlibs='gcc -shared' + # Make sure we select the correct fpic option + PAC_C_CHECK_COMPILER_OPTION(-fPIC,fPIC_OK=yes,fPIC_OK=no) + if test "$fPIC_OK" != yes ; then + PAC_C_CHECK_COMPILER_OPTION(-fpic,fpic_ok=yes,fpic_ok=no) + if test "$fpic_ok" != yes ; then + AC_MSG_ERROR([Neither -fpic nor -fPIC accepted by $CC]) + else + pac_cc_sharedlibs="$pac_cc_sharedlibs -fpic" + fi + else + pac_cc_sharedlibs="$pac_cc_sharedlibs -fPIC" + fi + pac_clink_sharedlibs='gcc -shared' + pac_type_sharedlibs=gcc + ;; + gcc-osx|osx-gcc) + pac_clink_sharedlibs='${CC} -dynamiclib -undefined suppress -single_module -flat_namespace' + pac_cc_sharedlibs='${CC} -fPIC' + pac_type_sharedlibs=gcc-osx + ;; + libtool) + AC_CHECK_PROGS(LIBTOOL,libtool,false) + if test "$LIBTOOL" = "false" ; then + AC_MSG_WARN([Could not find libtool]) + else + # Likely to be + # either CC or CC_SHL is libtool $cc + pac_cc_sharedlibs'${LIBTOOL} -mode=compile ${CC}' + pac_clink_sharedlibs='${LIBTOOL} -mode=link ${CC} -rpath ${libdir}' + pac_type_sharedlibs=libtool + fi + ;; + *) + ;; + esac + if test -n "$pac_cc_sharedlibs" ; then break ; fi +done +if test -z "$pac_cc_sharedlibs" ; then pac_cc_sharedlibs=true ; fi +if test -z "$pac_clink_sharedlibs" ; then pac_clink_sharedlibs=true ; fi +ifelse($2,,CC_SHL=$pac_cc_sharedlibs,$2=$pac_cc_sharedlibs) +ifelse($3,,C_LINK_SHL=$pac_clink_sharedlibs,$3=$pac_clink_sharedlibs) +ifelse($4,,SHAREDLIB_TYPE=$pac_type_sharedlibs,$4=$pac_type_sharedlibs) +]) + +dnl This macro ensures that all of the necessary substitutions are +dnl made by any subdirectory configure (which may simply SUBST the +dnl necessary values rather than trying to determine them from scratch) +dnl This is a more robust (and, in the case of libtool, only +dnl managable) method. +AC_DEFUN([PAC_CC_SUBDIR_SHLIBS],[ + AC_SUBST(CC_SHL) + AC_SUBST(C_LINK_SHL) + AC_SUBST(LIBTOOL) + AC_SUBST(ENABLE_SHLIB) + AC_SUBST(SHLIB_EXT) + if test "$ENABLE_SHLIB" = "libtool" ; then + if test -z "$LIBTOOL" ; then + AC_MSG_WARN([libtool selected for shared library support but LIBTOOL is not defined]) + fi + # Libtool needs master_top_builddir + if test "X$master_top_builddir" = "X" ; then + AC_MSG_ERROR([Libtool requires master_top_builddir - check configure.ac sources]) + fi + AC_SUBST(master_top_builddir) + fi +]) + +dnl PAC_CC_SHLIB_EXT - get the extension for shared libraries +dnl Set the variable SHLIB_EXT if it is other than unknown. +AC_DEFUN([PAC_CC_SHLIB_EXT],[ +# Not all systems use .so as the extension for shared libraries (cygwin +# and OSX are two important examples). If we did not set the SHLIB_EXT, +# then try and determine it. We need this to properly implement +# clean steps that look for libfoo.$SHLIB_EXT . +if test "$SHLIB_EXT" = "unknown" ; then + osname=`uname -s` + case $osname in + *Darwin*|*darwin*) SHLIB_EXT=dylib + ;; + *CYGWIN*|*cygwin*) SHLIB_EXT=dll + ;; + *Linux*|*LINUX*|*SunOS*) SHLIB_EXT=so + ;; + esac +fi +]) + +dnl PAC_COMPILER_SHLIB_FLAGS(compiler-var,output-file) +dnl +dnl Uses confdb/config.rpath to determine important linking flags and +dnl information. This is mainly intended to support the compiler wrapper +dnl scripts in MPICH ("mpicc" and friends) which cannot directly use libtool to +dnl handle linking. MPICH's compiler wrappers attempt to link executables with +dnl an rpath by default. The resulting variable assignment statements will be +dnl placed into "output-file", which is then suitable for AC_SUBST_FILE or +dnl sourcing in a shell script (including configure itself). +dnl +dnl This macro assumes that the basic tests associated with "compiler-var" have +dnl been run already, but does not AC_REQUIRE them in order to prevent problems +dnl with "expanded before required" when requiring the AC_PROG_{CC,F77,FC,CXX} +dnl macros. +dnl +dnl Example usage: +dnl +dnl ----8<---- +dnl # compute flags for linking executables against shared libraries when using +dnl # the modern Fortran compiler ($FC). +dnl PAC_COMPILER_SHLIB_FLAGS([FC],[src/env/fc_shlib.conf]) +dnl ----8<---- +AC_DEFUN([PAC_COMPILER_SHLIB_FLAGS],[ +AC_REQUIRE_AUX_FILE([config.rpath]) +AC_REQUIRE([AC_CANONICAL_HOST]) + +# It appears that the libtool dynamic linking strategy on Darwin is this: +# 1. Link all shared libs with "-install_name /full/path/to/libfoo.dylib" +# 2. Don't do anything special when linking programs, since it seems that the +# darwin dynamic linker will always use the "install_name" field from the lib +# that was found at program link-time. (CONFIRMED) This is in opposition to +# the way that Linux does it, where specifying a "-rpath" argument at program +# link-time is important. +# +# There is an alternative darwin strategy for versions +# >= 10.5, see this: http://www.cmake.org/pipermail/cmake/2010-August/038970.html +# (goodell@ 2011-06-17) + +AC_MSG_CHECKING([for shared library (esp. rpath) characteristics of $1]) + +# unfortunately, config.rpath expects the compiler in question is always CC and +# uses several other environment variables as input +PAC_PUSH_FLAG([CC]) +PAC_PUSH_FLAG([GCC]) +PAC_PUSH_FLAG([LD]) +# these two don't currently get overridden, but we push/pop them for safety in +# case they do in the future +PAC_PUSH_FLAG([LDFLAGS]) +PAC_PUSH_FLAG([with_gnu_ld]) + +# set the temporary override values (if any) +m4_case([$1], +[CC], + [:], dnl do nothing special for CC, values are already correct +[F77], + [CC="$$1" + GCC="$G77" + LD="$LD_F77"], +[FC], + [CC="$$1" + GCC="$GCC_FC" + LD="$LD_FC"], +[CXX], + [CC="$$1" + GCC="$GXX" + LD="$LD_CXX"], +[m4_fatal([unknown compiler argument "$1"])]) + +# ensure the values are available to the script +export CC +export GCC +export LDFLAGS +export LD +export with_gnu_ld + +AS_IF([$ac_aux_dir/config.rpath "$host" > $2],[:],[AC_MSG_ERROR([unable to execute $ac_aux_dir/config.rpath])]) + +C_LINKPATH_SHL="" +AC_SUBST([C_LINKPATH_SHL]) + +rm -f conftest.out + +# restore the old values +PAC_POP_FLAG([with_gnu_ld]) +PAC_POP_FLAG([LD]) +PAC_POP_FLAG([LDFLAGS]) +PAC_POP_FLAG([GCC]) +PAC_POP_FLAG([CC]) + +AC_MSG_RESULT([done (results in $2)]) +]) + diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_shm.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_shm.m4 new file mode 100644 index 0000000000..d2cbaade43 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_shm.m4 @@ -0,0 +1,49 @@ +dnl +dnl Definitions for using shared memory +dnl + +dnl/*D +dnl PAC_ARG_SHARED_MEMORY - add --with-shared-memory=kind to configure +dnl +dnl Synopsis: +dnl PAC_ARG_SHARED_MEMORY +dnl +dnl Output effects: +dnl Adds '--with-shared-memory' to the command line. Checks for available +dnl shared memory functionality. +dnl +dnl Supported values of 'kind' include \: +dnl+ auto - default +dnl. mmap - use mmap and munmap +dnl- sysv - use sysv shared memory functions +dnl D*/ +AC_DEFUN([PAC_ARG_SHARED_MEMORY],[ + +# check how to allocate shared memory +AC_ARG_WITH(shared-memory, + AC_HELP_STRING([--with-shared-memory[=auto|sysv|mmap]], [create shared memory using sysv or mmap (default is auto)]),, + with_shared_memory=auto) + +if test "$with_shared_memory" = auto -o "$with_shared_memory" = mmap; then + found_mmap_funcs=yes + AC_CHECK_FUNCS(mmap munmap, , found_mmap_funcs=no) + if test "$found_mmap_funcs" = yes ; then + with_shared_memory=mmap + AC_DEFINE(USE_MMAP_SHM,1,[Define if we have sysv shared memory]) + AC_MSG_NOTICE([Using a memory-mapped file for shared memory]) + elif test "$with_shared_memory" = mmap ; then + AC_MSG_ERROR([cannot support shared memory: mmap() or munmap() not found]) + fi +fi +if test "$with_shared_memory" = auto -o "$with_shared_memory" = sysv; then + found_sysv_shm_funcs=yes + AC_CHECK_FUNCS(shmget shmat shmctl shmdt, , found_sysv_shm_funcs=no) + if test "$found_sysv_shm_funcs" = yes ; then + with_shared_memory=sysv + AC_DEFINE(USE_SYSV_SHM,1,[Define if we have sysv shared memory]) + AC_MSG_NOTICE([Using SYSV shared memory]) + elif test "$with_shared_memory" = sysv ; then + AC_MSG_ERROR([cannot support shared memory: sysv shared memory functions functions not found]) + fi +fi +]) diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_subcfg.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_subcfg.m4 new file mode 100644 index 0000000000..53fb78e3d9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_subcfg.m4 @@ -0,0 +1,261 @@ +dnl PAC_RESET_ALL_FLAGS - Reset precious flags to those set by the user +AC_DEFUN([PAC_RESET_ALL_FLAGS],[ + if test "$FROM_MPICH" = "yes" ; then + CFLAGS="$USER_CFLAGS" + CPPFLAGS="$USER_CPPFLAGS" + CXXFLAGS="$USER_CXXFLAGS" + FFLAGS="$USER_FFLAGS" + FCFLAGS="$USER_FCFLAGS" + LDFLAGS="$USER_LDFLAGS" + LIBS="$USER_LIBS" + fi +]) + +dnl PAC_RESET_LINK_FLAGS - Reset precious link flags to those set by the user +AC_DEFUN([PAC_RESET_LINK_FLAGS],[ + if test "$FROM_MPICH" = "yes" ; then + LDFLAGS="$USER_LDFLAGS" + LIBS="$USER_LIBS" + fi +]) + +dnl Sandbox configure with additional arguments +dnl Usage: PAC_CONFIG_SUBDIR_ARGS(subdir,configure-args,action-if-success,action-if-failure) +dnl +dnl The subconfigure argument list is created based on "ac_precious_vars" +dnl instead of explicitly use of well-known Makefile variables, like +dnl CC/CFLAGS/CPPFLAGS..., this generalization is effective as long as +dnl calling configure.ac declares the needed variables to be passed down +dnl to subconfigure as "precious" appropriately. The precious variable +dnl can be created in the following ways: +dnl 1) implicit declaration through use of autoconf macros, like +dnl AC_PROG_CC (declares CC/CFLAGS/CPPFLAGS/LIBS/LDFLAGS), or +dnl AC_PROG_F77 (declares F77/FFLAGS/FLIBS) ... +dnl which are in turns invoked by other subconfigure. +dnl When in doubt, check "ac_precious_var" in the calling configure. +dnl 2) explicit "precious" declaration through AC_ARG_VAR. +dnl Without correct "precious" declaration in the calling configure.ac, +dnl there would be variables not being included in the subconfigure +dnl argument list. +dnl +dnl Note: I suspect this DEFUN body is underquoted in places, but it does not +dnl seem to cause problems in practice yet. [goodell@ 2010-05-18] +AC_DEFUN([PAC_CONFIG_SUBDIR_ARGS],[ + pac_dir="$1" + AC_MSG_NOTICE([===== configuring $1 =====]) + + pac_abs_srcdir=`(cd $srcdir && pwd)` + + if test -f $pac_abs_srcdir/$1/setup ; then + AC_MSG_NOTICE([sourcing $pac_abs_srcdir/$1/setup]) + . $pac_abs_srcdir/$1/setup + fi + + # Adapted for MPICH from the autoconf-2.67 implementation of + # AC_CONFIG_SUBDIRS. Search for "MPICH note:" for relevant commentary and + # local modifications. + + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. Otherwise relative paths (like --srcdir=.. from + # make distcheck) will be incorrect. + pac_sub_configure_args="$2" + pac_prev= + eval "set x $ac_configure_args" + shift + for pac_arg + do + if test -n "$pac_prev"; then + pac_prev= + continue + fi + case $pac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + pac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + pac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + pac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + --disable-option-checking) + ;; + *) + # MPICH note: this is a more robust version of the "precious + # variable" propagation code that was present in the previous + # incarnation of this macro + for pac_pvar in $ac_precious_vars ; do + # check if configure argument token contains the + # precious variable, i.e. "name_of_prec_var=". + if ( echo $pac_arg | grep "^$pac_pvar=" >/dev/null 2>&1 ) ; then + # check if current precious variable is set in env + eval pvar_set=\${$pac_pvar+set} + if test "$pvar_set" = "set" ; then + # Append 'name_of_prec_var=value_of_prec_var' + # to the subconfigure arguments list, where + # value_of_prec_var is fetched from the env. + # this also overrides any value set on the command line + eval pac_pval=\${$pac_pvar} + pac_arg="$pac_pvar=$pac_pval" + break + fi + fi + done + case $pac_arg in + *\'*) pac_arg=`AS_ECHO(["$pac_arg"]) | sed "s/'/'\\\\\\\\''/g"` ;; + esac + AS_VAR_APPEND([pac_sub_configure_args], [" '$pac_arg'"]) ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + # MPICH note: see tt#983 for an example of why this is necessary + pac_arg="--prefix=$prefix" + case $pac_arg in + *\'*) pac_arg=`AS_ECHO(["$pac_arg"]) | sed "s/'/'\\\\\\\\''/g"` ;; + esac + pac_sub_configure_args="'$pac_arg' $pac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + pac_sub_configure_args="--silent $pac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + pac_sub_configure_args="--disable-option-checking $pac_sub_configure_args" + + pac_popdir=`pwd` + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$pac_dir" || continue + + # MPICH note: modified to remove the internal "_AS_*" macro usage, also + # msg is already printed at top +dnl _AS_ECHO_LOG([$pac_msg]) +dnl _AS_ECHO([$pac_msg]) + AS_MKDIR_P(["$pac_dir"]) + # MPICH note: we leave this internal macro reference for now. We can clone + # the macro locally if this turns out to be non-portable across several autoconf + # versions. It sets the following variables: ac_builddir, + # ac_top_builddir_sub, ac_top_build_prefix, ac_srcdir, ac_top_srcdir, + # ac_abs_top_builddir, ac_abs_builddir, ac_abs_top_srcdir, ac_abs_srcdir + _AC_SRCDIRS(["$pac_dir"]) + + cd "$pac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + pac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + pac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.ac"; then + # This should be Cygnus configure. + pac_sub_configure=$ac_aux_dir/configure + else + AC_MSG_WARN([no configuration information is in $pac_dir]) + pac_sub_configure= + fi + + # The recursion is here. + if test -n "$pac_sub_configure"; then + # MPICH note: overriding the cache file on purpose to prevent strange + # issues resulting from inter-dir caching +dnl # Make the cache file name correct relative to the subdirectory. +dnl case $cache_file in +dnl [[\\/]]* | ?:[[\\/]]* ) pac_sub_cache_file=$cache_file ;; +dnl *) # Relative name. +dnl pac_sub_cache_file=$ac_top_build_prefix$cache_file ;; +dnl esac + pac_sub_cache_file="/dev/null" + + AC_MSG_NOTICE([running $SHELL $pac_sub_configure $pac_sub_configure_args --cache-file=$pac_sub_cache_file --srcdir=$ac_srcdir]) + # The eval makes quoting arguments work. + # MPICH note: we want to execute the provided actions, not be silent + # or error out if the subconfigure succeeded/failed +dnl eval "\$SHELL \"\$pac_sub_configure\" $pac_sub_configure_args \ +dnl --cache-file=\"\$pac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || +dnl AC_MSG_ERROR([$pac_sub_configure failed for $pac_dir]) + if eval "\$SHELL \"\$pac_sub_configure\" $pac_sub_configure_args \ + --cache-file=\"\$pac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" + then + # restore the current dir for the provided actions + cd "$pac_popdir" + $3 + else + # restore the current dir for the provided actions + cd "$pac_popdir" + $4 + fi + fi + + cd "$pac_popdir" + + AC_MSG_NOTICE([===== done with $1 configure =====]) + + # Check for any localdefs files. These may be created, so we + # look in the local directory first. + if test -f $1/localdefs ; then + AC_MSG_NOTICE([sourcing $1/localdefs]) + . $1/localdefs + elif test -f $pac_abs_srcdir/$1/localdefs ; then + AC_MSG_NOTICE([sourcing $pac_abs_srcdir/$1/localdefs]) + . $pac_abs_srcdir/$1/localdefs + fi +]) + +dnl Sandbox configure +dnl Usage: PAC_CONFIG_SUBDIR(subdir,action-if-success,action-if-failure) +AC_DEFUN([PAC_CONFIG_SUBDIR],[PAC_CONFIG_SUBDIR_ARGS([$1],[],[$2],[$3])]) + +dnl PAC_SUBCFG_EXPAND_SUFFIX_MACRO(MACRO_PREFIX,MACRO_PATH_SUFFIX) +dnl converts the path given by MACRO_PATH_SUFFIX (with '/' chars in it) to one +dnl with '_' chars in it and then appends that to MACRO_PREFIX with '_' in +dnl between. The resulting macro name is then expanded, but with informative +dnl "##" comments before and after the expansion. +dnl +dnl This is intended to be an internal helper macro for the PAC_SUBCFG +dnl implementation. +dnl +dnl XXX DJG FIXME: need to be able to deal with PREREQ macros that potentially +dnl aren't present while having safety for BODY macros when there are +dnl misspellings +AC_DEFUN([PAC_SUBCFG_EXPAND_PATH_SUFFIX_MACRO],[ +dnl convert path separators into '_', the m4_translit is intentionally unquoted +m4_pushdef([subsys_uscore_name],[$1_]m4_translit([$2],[\/],[__]))dnl +m4_ifdef(m4_defn([subsys_uscore_name]),[],[m4_fatal([macro ]m4_defn([subsys_uscore_name])[ is undefined])])dnl +[##] begin expansion of m4_defn([subsys_uscore_name]) +dnl call the computed routine name with the remaining args +m4_indir(m4_defn([subsys_uscore_name]),m4_shift($@)) +dnl there is intentionally no "dnl" on the previous line to reduce the chance of +dnl a "fi## end expansion" bug when the BODY macro doesn't end in a newline +[##] end expansion of m4_defn([subsys_uscore_name]) +]) + +dnl invokes the PAC_SUBCFG_BODY_foo macro for the "foo" subsys, when "foo" is +dnl passed as the only argument to this macro. The first arg may be the '/' +dnl path version instead of having underscores. +AC_DEFUN([PAC_SUBCFG_CONFIGURE_SUBSYS],[PAC_SUBCFG_EXPAND_PATH_SUFFIX_MACRO([PAC_SUBCFG_BODY],[$1])]) + +dnl invokes the PAC_SUBCFG_PREREQ_foo macro for the "foo" subsys, when "foo" is +dnl passed as the only argument to this macro. The first arg may be the '/' +dnl path version instead of having underscores. +AC_DEFUN([PAC_SUBCFG_DO_PREREQ],[PAC_SUBCFG_EXPAND_PATH_SUFFIX_MACRO([PAC_SUBCFG_PREREQ],[$1])]) + +dnl takes no arguments, expands to "foo_bar_baz" when invoked in a file named +dnl "foo/bar/baz/subconfigure.m4" +dnl +dnl This is useful for reducing copy-paste errors when defining PREREQ and BODY +dnl macros. If you tinker with this macro, watch the quoting carefully. +AC_DEFUN([PAC_SUBCFG_AUTO_SUFFIX],[m4_translit(m4_bpatsubst(m4_dquote(__file__),[/[^/]+.m4],[]),[/],[_])]) + diff --git a/ompi/mca/io/romio314/romio/confdb/aclocal_util.m4 b/ompi/mca/io/romio314/romio/confdb/aclocal_util.m4 new file mode 100644 index 0000000000..575a144463 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/aclocal_util.m4 @@ -0,0 +1,216 @@ +dnl Nesting safe macros for saving variables +dnl Usage: PAC_PUSH_FLAG(CFLAGS) +AC_DEFUN([PAC_PUSH_FLAG],[ + if test -z "${pac_save_$1_nesting}" ; then + pac_save_$1_nesting=0 + fi + eval pac_save_$1_${pac_save_$1_nesting}='"$$1"' + pac_save_$1_nesting=`expr ${pac_save_$1_nesting} + 1` +]) + +dnl Usage: PAC_POP_FLAG(CFLAGS) +AC_DEFUN([PAC_POP_FLAG],[ + pac_save_$1_nesting=`expr ${pac_save_$1_nesting} - 1` + eval $1="\$pac_save_$1_${pac_save_$1_nesting}" + eval pac_save_$1_${pac_save_$1_nesting}="" +]) + +dnl Usage: PAC_PUSH_ALL_FLAGS +AC_DEFUN([PAC_PUSH_ALL_FLAGS],[ + PAC_PUSH_FLAG(CFLAGS) + PAC_PUSH_FLAG(CPPFLAGS) + PAC_PUSH_FLAG(CXXFLAGS) + PAC_PUSH_FLAG(FFLAGS) + PAC_PUSH_FLAG(FCFLAGS) + PAC_PUSH_FLAG(LDFLAGS) + PAC_PUSH_FLAG(LIBS) +]) + +dnl Usage: PAC_POP_ALL_FLAGS +AC_DEFUN([PAC_POP_ALL_FLAGS],[ + PAC_POP_FLAG(CFLAGS) + PAC_POP_FLAG(CPPFLAGS) + PAC_POP_FLAG(CXXFLAGS) + PAC_POP_FLAG(FFLAGS) + PAC_POP_FLAG(FCFLAGS) + PAC_POP_FLAG(LDFLAGS) + PAC_POP_FLAG(LIBS) +]) + +dnl PAC_PREFIX_FLAG - Save flag with a prefix +dnl Usage: PAC_PREFIX_FLAG(PREFIX, FLAG) +AC_DEFUN([PAC_PREFIX_FLAG],[ + $1_$2=$$2 + export $1_$2 + AC_SUBST($1_$2) +]) + +dnl PAC_PREFIX_ALL_FLAGS - Save flags with a prefix +dnl Usage: PAC_PREFIX_ALL_FLAGS(PREFIX) +AC_DEFUN([PAC_PREFIX_ALL_FLAGS],[ + PAC_PREFIX_FLAG($1, CFLAGS) + PAC_PREFIX_FLAG($1, CPPFLAGS) + PAC_PREFIX_FLAG($1, CXXFLAGS) + PAC_PREFIX_FLAG($1, FFLAGS) + PAC_PREFIX_FLAG($1, FCFLAGS) + PAC_PREFIX_FLAG($1, LDFLAGS) + PAC_PREFIX_FLAG($1, LIBS) + PAC_PREFIX_FLAG($1, EXTRA_LIBS) +]) + +dnl Usage: PAC_APPEND_FLAG([-02], [CFLAGS]) +dnl appends the given argument to the specified shell variable unless the +dnl argument is already present in the variable +AC_DEFUN([PAC_APPEND_FLAG],[ + AC_REQUIRE([AC_PROG_FGREP]) + AS_IF( + [echo "$$2" | $FGREP -e '$1' >/dev/null 2>&1], + [echo "$2(='$$2') contains '$1', not appending" >&AS_MESSAGE_LOG_FD], + [echo "$2(='$$2') does not contain '$1', appending" >&AS_MESSAGE_LOG_FD + $2="$$2 $1"] + ) +]) + +dnl Usage: PAC_PREPEND_FLAG([-lpthread], [LIBS]) +dnl Prepends the given argument to the specified shell variable unless the +dnl argument is already present in the variable. +dnl +dnl This is typically used for LIBS and similar variables because libraries +dnl should be added in reverse order. +AC_DEFUN([PAC_PREPEND_FLAG],[ + AC_REQUIRE([AC_PROG_FGREP]) + AS_IF( + [echo "$$2" | $FGREP -e '$1' >/dev/null 2>&1], + [echo "$2(='$$2') contains '$1', not prepending" >&AS_MESSAGE_LOG_FD], + [echo "$2(='$$2') does not contain '$1', prepending" >&AS_MESSAGE_LOG_FD + $2="$1 $$2"] + ) +]) + + +dnl PAC_MKDIRS(path) +dnl Create any missing directories in the path +AC_DEFUN([PAC_MKDIRS],[ +# Build any intermediate directories +for dir in $1 ; do + PAC_PUSH_FLAG([IFS]) + IFS="/" + tmp_curdir="" + for tmp_subdir in $dir ; do + tmp_curdir="${tmp_curdir}$tmp_subdir" + if test ! -d "$tmp_curdir" ; then mkdir "$tmp_curdir" ; fi + tmp_curdir="${tmp_curdir}/" + done + PAC_POP_FLAG([IFS]) +done +]) + +# Find something to use for mkdir -p. Eventually, this will have a +# script for backup. As of autoconf-2.63, AC_PROG_MKDIR_P was broken; +# it was checking to see if it recognized the "version" of mkdir and +# was deciding based on that. This should always be a feature test. +AC_DEFUN([PAC_PROG_MKDIR_P],[ +AC_CACHE_CHECK([whether mkdir -p works], +pac_cv_mkdir_p,[ +pac_cv_mkdir_p=no +rm -rf .tmp +if mkdir -p .tmp/.foo 1>/dev/null 2>&1 ; then + if test -d .tmp/.foo ; then + pac_cv_mkdir_p=yes + fi +fi +rm -rf .tmp +]) +if test "$pac_cv_mkdir_p" = "yes" ; then + MKDIR_P="mkdir -p" + export MKDIR_P +else + AC_MSG_WARN([mkdir -p does not work; the install step may fail]) +fi +AC_SUBST(MKDIR_P) +]) + +dnl Test for a clean VPATH directory. Provide this command with the names +dnl of all of the generated files that might cause problems +dnl (Makefiles won't cause problems because there's no VPATH usage for them) +dnl +dnl Synopsis +dnl PAC_VPATH_CHECK([file-names],[directory-names]) +dnl file-names should be files other than config.status and any header (e.g., +dnl fooconf.h) file that should be removed. It is optional +AC_DEFUN([PAC_VPATH_CHECK],[ +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest* +date >conftest$$ +# If creating a file in the current directory does not show up in the srcdir +# then we're doing a VPATH build (or something is very wrong) +if test ! -s $srcdir/conftest$$ ; then + pac_dirtyfiles="" + pac_dirtydirs="" + pac_header="" + ifdef([AC_LIST_HEADER],[pac_header=AC_LIST_HEADER]) + for file in config.status $pac_header $1 ; do + if test -f $srcdir/$file ; then + pac_dirtyfiles="$pac_dirtyfiles $file" + fi + done + ifelse($2,,,[ + for dir in $2 ; do + if test -d $srcdir/$dir ; then + pac_dirtydirs="$pac_dirtydirs $dir" + fi + done + ]) + + if test -n "$pac_dirtyfiles" -o -n "$pac_dirtydirs" ; then + # Create a nice message about what to remove + rmmsg="" + if test -n "$pac_dirtyfiles" ; then + rmmsg="files $pac_dirtyfiles" + fi + if test -n "$pac_dirtydirs" ; then + if test -n "$rmmsg" ; then + rmmsg="$rmmsg and directories $pac_dirtydirs" + else + rmmsg="directories $pac_dirtydirs" + fi + fi + if test -f $srcdir/Makefile ; then + AC_MSG_ERROR([You cannot do a VPATH build if the source directory has been + configured. Run "make distclean" in $srcdir first and make sure that the + $rmmsg have been removed.]) + else + AC_MSG_ERROR([You cannot do a VPATH build if the source directory has been + configured. Remove the $rmmsg in $srcdir.]) + fi + fi +fi +# This is needed for Mac OSX 10.5 +rm -rf conftest.dSYM +rm -f conftest* +]) + +dnl PAC_CONF_HEX_TO_DEC(value,out_var) +dnl +dnl Converts the given hexadecimal integer constant to an integer constant and +dnl stores the result in the shell variable given by 'out_var'. +dnl +dnl I think that printf like this will be sufficiently portable, but I don't +dnl have any guarantee of it. If not, we can fall back to AS_VAR_ARITH +dnl and/or AC_COMPUTE_INT (the latter will probably be slow) +AC_DEFUN([PAC_CONV_HEX_TO_DEC],[AS_VAR_SET([$2],[`printf "%d" $1`])]) + +dnl PAC_GET_EXENAME(exe_name, out_exe_name) +dnl +dnl Prepends and appends program prefix and suffix as supplied by --program_prefix +dnl and --program-sufix +AC_DEFUN([PAC_GET_EXENAME],[ +$2=$1 +if test "$program_prefix" != "NONE" ; then + $2="${program_prefix}$$2" +fi +if test "$program_suffix" != "NONE" ; then + $2="$$2$program_suffix" +fi +]) diff --git a/ompi/mca/io/romio314/romio/confdb/ax_prefix_config_h.m4 b/ompi/mca/io/romio314/romio/confdb/ax_prefix_config_h.m4 new file mode 100644 index 0000000000..83f8df6f4b --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/ax_prefix_config_h.m4 @@ -0,0 +1,219 @@ +# =========================================================================== +# http://autoconf-archive.cryp.to/ax_prefix_config_h.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PREFIX_CONFIG_H [(OUTPUT-HEADER [,PREFIX [,ORIG-HEADER]])] +# +# DESCRIPTION +# +# This is a new variant from ac_prefix_config_ this one will use a +# lowercase-prefix if the config-define was starting with a +# lowercase-char, e.g. "#define const", "#define restrict", or "#define +# off_t", (and this one can live in another directory, e.g. +# testpkg/config.h therefore I decided to move the output-header to be the +# first arg) +# +# takes the usual config.h generated header file; looks for each of the +# generated "#define SOMEDEF" lines, and prefixes the defined name (ie. +# makes it "#define PREFIX_SOMEDEF". The result is written to the output +# config.header file. The PREFIX is converted to uppercase for the +# conversions. +# +# Defaults: +# +# OUTPUT-HEADER = $PACKAGE-config.h +# PREFIX = $PACKAGE +# ORIG-HEADER, from AM_CONFIG_HEADER(config.h) +# +# Your configure.ac script should contain both macros in this order, and +# unlike the earlier variations of this prefix-macro it is okay to place +# the AX_PREFIX_CONFIG_H call before the AC_OUTPUT invokation. +# +# Example: +# +# AC_INIT(config.h.in) # config.h.in as created by "autoheader" +# AM_INIT_AUTOMAKE(testpkg, 0.1.1) # makes #undef VERSION and PACKAGE +# AM_CONFIG_HEADER(config.h) # prep config.h from config.h.in +# AX_PREFIX_CONFIG_H(mylib/_config.h) # prep mylib/_config.h from it.. +# AC_MEMORY_H # makes "#undef NEED_MEMORY_H" +# AC_C_CONST_H # makes "#undef const" +# AC_OUTPUT(Makefile) # creates the "config.h" now +# # and also mylib/_config.h +# +# if the argument to AX_PREFIX_CONFIG_H would have been omitted then the +# default outputfile would have been called simply "testpkg-config.h", but +# even under the name "mylib/_config.h" it contains prefix-defines like +# +# #ifndef TESTPKG_VERSION +# #define TESTPKG_VERSION "0.1.1" +# #endif +# #ifndef TESTPKG_NEED_MEMORY_H +# #define TESTPKG_NEED_MEMORY_H 1 +# #endif +# #ifndef _testpkg_const +# #define _testpkg_const _const +# #endif +# +# and this "mylib/_config.h" can be installed along with other +# header-files, which is most convenient when creating a shared library +# (that has some headers) where some functionality is dependent on the +# OS-features detected at compile-time. No need to invent some +# "mylib-confdefs.h.in" manually. :-) +# +# Note that some AC_DEFINEs that end up in the config.h file are actually +# self-referential - e.g. AC_C_INLINE, AC_C_CONST, and the AC_TYPE_OFF_T +# say that they "will define inline|const|off_t if the system does not do +# it by itself". You might want to clean up about these - consider an +# extra mylib/conf.h that reads something like: +# +# #include +# #ifndef _testpkg_const +# #define _testpkg_const const +# #endif +# +# and then start using _testpkg_const in the header files. That is also a +# good thing to differentiate whether some library-user has starting to +# take up with a different compiler, so perhaps it could read something +# like this: +# +# #ifdef _MSC_VER +# #include +# #else +# #include +# #endif +# #ifndef _testpkg_const +# #define _testpkg_const const +# #endif +# +# LAST MODIFICATION +# +# 2008-04-12 +# +# COPYLEFT +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2008 Marten Svantesson +# Copyright (c) 2008 Gerald Point +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Macro Archive. When you make and +# distribute a modified version of the Autoconf Macro, you may extend this +# special exception to the GPL to apply to your modified version as well. + +AC_DEFUN([AX_PREFIX_CONFIG_H],[dnl +AC_BEFORE([AC_CONFIG_HEADERS],[$0])dnl +AC_CONFIG_COMMANDS([ifelse($1,,$PACKAGE-config.h,$1)],[dnl +AS_VAR_PUSHDEF([_OUT],[ac_prefix_conf_OUT])dnl +AS_VAR_PUSHDEF([_DEF],[ac_prefix_conf_DEF])dnl +AS_VAR_PUSHDEF([_PKG],[ac_prefix_conf_PKG])dnl +AS_VAR_PUSHDEF([_LOW],[ac_prefix_conf_LOW])dnl +AS_VAR_PUSHDEF([_UPP],[ac_prefix_conf_UPP])dnl +AS_VAR_PUSHDEF([_INP],[ac_prefix_conf_INP])dnl +m4_pushdef([_script],[conftest.prefix])dnl +m4_pushdef([_symbol],[m4_cr_Letters[]m4_cr_digits[]_])dnl +_OUT=`echo ifelse($1, , $PACKAGE-config.h, $1)` +_DEF=`echo _$_OUT | sed -e "y:m4_cr_letters:m4_cr_LETTERS[]:" -e "s/@<:@^m4_cr_Letters@:>@/_/g"` +_PKG=`echo ifelse($2, , $PACKAGE, $2)` +_LOW=`echo _$_PKG | sed -e "y:m4_cr_LETTERS-:m4_cr_letters[]_:"` +_UPP=`echo $_PKG | sed -e "y:m4_cr_letters-:m4_cr_LETTERS[]_:" -e "/^@<:@m4_cr_digits@:>@/s/^/_/"` +_INP=`echo "ifelse($3,,,$3)" | sed -e 's/ *//'` +if test ".$_INP" = "."; then + for ac_file in : $CONFIG_HEADERS; do test "_$ac_file" = _: && continue + case "$ac_file" in + *.h) _INP=$ac_file ;; + *) + esac + test ".$_INP" != "." && break + done +fi +if test ".$_INP" = "."; then + case "$_OUT" in + */*) _INP=`basename "$_OUT"` + ;; + *-*) _INP=`echo "$_OUT" | sed -e "s/@<:@_symbol@:>@*-//"` + ;; + *) _INP=config.h + ;; + esac +fi +if test -z "$_PKG" ; then + AC_MSG_ERROR([no prefix for _PREFIX_PKG_CONFIG_H]) +else + if test ! -f "$_INP" ; then if test -f "$srcdir/$_INP" ; then + _INP="$srcdir/$_INP" + fi fi + AC_MSG_NOTICE(creating $_OUT - prefix $_UPP for $_INP defines) + if test -f $_INP ; then + echo "s/^@%:@undef *\\(@<:@m4_cr_LETTERS[]_@:>@\\)/@%:@undef $_UPP""_\\1/" > _script + echo "s/^@%:@undef *\\(@<:@m4_cr_letters@:>@\\)/@%:@undef $_LOW""_\\1/" >> _script + echo "s/^@%:@def[]ine *\\(@<:@m4_cr_LETTERS[]_@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_UPP""_\\1 \\" >> _script + echo "@%:@def[]ine $_UPP""_\\1 \\2 \\" >> _script + echo "@%:@endif/" >>_script + echo "s/^@%:@def[]ine *\\(@<:@m4_cr_letters@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_LOW""_\\1 \\" >> _script + echo "@%:@define $_LOW""_\\1 \\2 \\" >> _script + echo "@%:@endif/" >> _script + # now executing _script on _DEF input to create _OUT output file + echo "@%:@ifndef $_DEF" >$tmp/pconfig.h + echo "@%:@def[]ine $_DEF 1" >>$tmp/pconfig.h + echo ' ' >>$tmp/pconfig.h + echo /'*' $_OUT. Generated automatically at end of configure. '*'/ >>$tmp/pconfig.h + + sed -f _script $_INP >>$tmp/pconfig.h + echo ' ' >>$tmp/pconfig.h + echo '/* once:' $_DEF '*/' >>$tmp/pconfig.h + echo "@%:@endif" >>$tmp/pconfig.h + if cmp -s $_OUT $tmp/pconfig.h 2>/dev/null; then + AC_MSG_NOTICE([$_OUT is unchanged]) + else + ac_dir=`AS_DIRNAME(["$_OUT"])` + AS_MKDIR_P(["$ac_dir"]) + rm -f "$_OUT" + mv $tmp/pconfig.h "$_OUT" + fi + cp _script _configs.sed + else + AC_MSG_ERROR([input file $_INP does not exist - skip generating $_OUT]) + fi + rm -f conftest.* +fi +m4_popdef([_symbol])dnl +m4_popdef([_script])dnl +AS_VAR_POPDEF([_INP])dnl +AS_VAR_POPDEF([_UPP])dnl +AS_VAR_POPDEF([_LOW])dnl +AS_VAR_POPDEF([_PKG])dnl +AS_VAR_POPDEF([_DEF])dnl +AS_VAR_POPDEF([_OUT])dnl +],[PACKAGE="$PACKAGE"])]) + +dnl implementation note: a bug report (31.5.2005) from Marten Svantesson points +dnl out a problem where `echo "\1"` results in a Control-A. The unix standard +dnl http://www.opengroup.org/onlinepubs/000095399/utilities/echo.html +dnl defines all backslash-sequences to be inherently non-portable asking +dnl for replacement mit printf. Some old systems had problems with that +dnl one either. However, the latest libtool (!) release does export an $ECHO +dnl (and $echo) that does the right thing - just one question is left: what +dnl was the first version to have it? Is it greater 2.58 ? diff --git a/ompi/mca/io/romio314/romio/confdb/ax_tls.m4 b/ompi/mca/io/romio314/romio/confdb/ax_tls.m4 new file mode 100644 index 0000000000..2704438226 --- /dev/null +++ b/ompi/mca/io/romio314/romio/confdb/ax_tls.m4 @@ -0,0 +1,74 @@ +# =========================================================================== +# http://www.nongnu.org/autoconf-archive/ax_tls.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_TLS +# +# DESCRIPTION +# +# Provides a test for the compiler support of thread local storage (TLS) +# extensions. Defines TLS if it is found. Currently only knows about GCC +# and MSVC. I think SunPro uses the same as GCC, and Borland apparently +# supports either. +# +# LICENSE +# +# Copyright (c) 2008 Alan Woodland +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +AC_DEFUN([AX_TLS], [ + AC_MSG_CHECKING(for thread local storage specifier) + AC_CACHE_VAL(ac_cv_tls, [ + ax_tls_keywords="__thread __declspec(thread) none" + for ax_tls_keyword in $ax_tls_keywords; do + case $ax_tls_keyword in + none) ac_cv_tls=none ; break ;; + *) + # MPICH modification: This was an AC_TRY_COMPILE before, but + # Darwin with non-standard compilers will accept __thread at + # compile time but fail to link due to an undefined + # "__emutls_get_address" symbol unless -lgcc_eh is added to the + # link line. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([$ax_tls_keyword int bar = 5;],[++bar;])], + [ac_cv_tls=$ax_tls_keyword ; break], + [ac_cv_tls=none]) + esac + done +]) + + if test "$ac_cv_tls" != "none"; then + # MPICH modification: this was "TLS" before instead of + # "MPIU_TLS_SPECIFIER", but TLS had a reasonably high chance of conflicting + # with a system library. + AC_DEFINE_UNQUOTED([MPIU_TLS_SPECIFIER], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here]) + fi + AC_MSG_RESULT($ac_cv_tls) +]) diff --git a/ompi/mca/io/romio314/romio/configure.ac b/ompi/mca/io/romio314/romio/configure.ac new file mode 100644 index 0000000000..68801adb45 --- /dev/null +++ b/ompi/mca/io/romio314/romio/configure.ac @@ -0,0 +1,1865 @@ +# -*- Mode: shell-script -*- +# build with +# autoconf --localdir=../confdb configure.ac +# (or wherever the confdb is) +# +AC_PREREQ([2.63]) + +m4_include([version.m4]) +dnl 2nd arg is intentionally underquoted +AC_INIT([ROMIO], + MPICH_VERSION_m4, + [discuss@mpich.org], + [romio], + [http://www.mpich.org/]) + +dnl AC_CONFIG_AUX_DIR(../../../confdb) +dnl Set the directory that contains the required install-sh, config.sub, +dnl and config.guess . Make sure that these are updated (in MPICH, use +dnl the top-level confdb files). This separate directory is used for +dnl the moment to allow ROMIO to be separatedly distributed. +dnl scripts. +AC_CONFIG_AUX_DIR([confdb]) +AC_CONFIG_MACRO_DIR([confdb]) + +AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability-recursive foreign 1.12.3 silent-rules subdir-objects]) +AM_MAINTAINER_MODE([enable]) + +dnl must come before LT_INIT, which AC_REQUIREs AC_PROG_CC +PAC_PROG_CC +AM_PROG_CC_C_O + +AM_PROG_AR + +LT_INIT([]) +# Non-verbose make by default +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# VERSION=1.2.6 +# AC_MSG_RESULT([Configuring ROMIO Version $VERSION]) +CONFIGURE_ARGS="$*" +if test -n "$CONFIGURE_ARGS" ; then + echo "Configuring with args $CONFIGURE_ARGS" +fi + +AC_CONFIG_HEADER(adio/include/romioconf.h) +AH_TOP([/* + * (C) 2011 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#ifndef ROMIOCONF_H_INCLUDED +#define ROMIOCONF_H_INCLUDED +]) +AH_BOTTOM([ +/* quash PACKAGE and PACKAGE_* vars, see MPICH top-level configure.ac for + * more info */ +#include "nopackage.h" + +#endif /* !defined(ROMIOCONF_H_INCLUDED) */ +]) + +dnl +NOF77=0 +NOF90=0 +ARCH="" +arch_IRIX="" +MPI_IMPL="" +MPI_INCLUDE_DIR="" +ROMIO_INCLUDE="" + +# Used by the new build system, should contain zero or more "-Iblah" args for +# inclusion in AM_CPPFLAGS. Should not contain relative paths. This probably +# overlaps with ROMIO_INCLUDE some, but adding a new var is easier than teasing +# apart all of the current usages of that variable and re-testing all of the +# non-MPICH and exotic platform cases. +MPI_H_INCLUDE="" +AC_SUBST([MPI_H_INCLUDE]) + +TEST_LIBNAME="" +FILE_SYSTEM="" + +# Do not set variables to empty that may be communicated from the +# outside environment (e.g., MPI_LIB, MPI_BIN_DIR, LIBNAME) +DEBUG=no +MIPS=0 +BITS=0 + +AC_ARG_VAR([FROM_MPICH],[set to "yes" if building ROMIO inside of MPICH]) +FROM_MPICH=${FROM_MPICH:-no} + +AC_ARG_VAR([FROM_LAM],[set to "yes" if building ROMIO inside of LAM]) +FROM_LAM=${FROM_LAM:-no} +if test "$FROM_LAM" = 1 ; then FROM_LAM=yes ; fi + +AC_ARG_VAR([FROM_OMPI],[set to "yes" if building ROMIO inside of Open MPI]) +FROM_OMPI=${FROM_OMPI:-no} +if test "$FROM_OMPI" = 1 ; then FROM_OMPI=yes ; fi + +CFLAGS=${CFLAGS:-""} +LL="lld" +AR_LOCAL="" +DEFINE_HAVE_MPI_GREQUEST="#undef HAVE_MPI_GREQUEST" +HAVE_MPI_INFO="" +BUILD_MPI_INFO="" +MPI_FINFO1="" +MPI_FINFO2="" +MPI_FINFO3="" +MPI_FINFO4="" +MPI_FARRAY1="" +MPI_FARRAY2="" +MPI_FARRAY3="" +MPI_FARRAY4="" +MPI_FARRAY5="" +MPI_FARRAY6="" +MPI_FARRAY7="" +DEFS="" +ROMIO_LFLAGS="" +ROMIO_TCFLAGS="" +ROMIO_TCPPFLAGS="" +ROMIO_TFFLAGS="" +NOPROFILE=0 +MPIRUN="" +FORTRAN_TEST="" +MAKE=${MAKE:-"make"} +# foll. needed for f77 test programs +F77GETARG="call getarg(i,str)" +F77IARGC="iargc()" +F77MPIOINC="" +FTESTDEFINE="" +FORTRAN_MPI_OFFSET="" +MPIOF_H_INCLUDED=0 +MPI_OFFSET_KIND1="!" +MPI_OFFSET_KIND2="!" +TEST_CC="" +TEST_F77="" +# +have_aio=no +# +known_mpi_impls="mpich_mpi mpich_mpi sgi_mpi hp_mpi cray_mpi lam_mpi open_mpi_mpi" + +dnl An m4 macro for use with m4_foreach_w and friends. You should modify this +dnl list if you want to add a known file system. The list is just whitespace +dnl separated, so you can use newlines and tabs as well. +m4_define([known_filesystems_m4_w], + [nfs ufs pfs pvfs pvfs2 testfs xfs panfs gridftp lustre gpfs zoidfs hfs piofs sfs])dnl +dnl +dnl An m4 macro for use with m4_foreach and friends. Expands to a quoted list of +dnl quoted elements. A bit easier to use without unintended expansion than the +dnl whitespace version. +m4_define([known_filesystems_m4], m4_dquote(m4_map_args_w(m4_defn([known_filesystems_m4_w]),[],[],[,])))dnl +dnl +# a shell var for checking arguments given via --with-file-system=... +known_filesystems="m4_join([ ],known_filesystems_m4)" + +##################################################################### + +# +# Defaults +AC_ARG_ENABLE(aio,[ +--enable-aio - Request use of asynchronous I/O routines (default)], +[ + if test "x$enableval" = "xno" ; then + disable_aio=yes + else + disable_aio=no + fi +], disable_aio=no) +AC_ARG_ENABLE(echo, +[--enable-echo - Turn on strong echoing. The default is enable=no.] ,set -x) +AC_ARG_ENABLE(f77, +[--enable-f77 - Turn on support for Fortran 77 (default)],,enable_f77=yes) +AC_ARG_ENABLE(f90, +[--enable-f90 - Turn on support for Fortran 90 (default)],,enable_f90=yes) +AC_ARG_ENABLE(weak-symbols, +[--enable-weak-symbols - Turn on support for weak symbols],,enable_weak_symbols=yes) +AC_ARG_ENABLE(debug, +[--enable-debug - Build a debugging version],,) +AC_ARG_WITH(file-system,[ +--with-file-system=name - Build with support for the named file systems],,) +AC_ARG_WITH(pvfs2,[ +--with-pvfs2=path - Path to installation of PVFS (version 2)],,) +AC_ARG_WITH(mpi-impl,[ +--with-mpi-impl=name - Specify MPI implementation to build ROMIO for],,) +dnl +AC_ARG_WITH(mpi, [ +--with-mpi=path - Path to instalation of MPI (headers, libs, etc)],,) +dnl +if test "$enable_f77" != "yes" ; then + NOF77=1 +fi +if test "$enable_f90" != "yes" ; then + NOF90=1 +fi +if test "$enable_debug" = "yes" ; then + DEBUG=yes +fi +MPI=$with_mpi +if test -n "$with_mpi"; then + CC=$MPI/bin/mpicc +fi + +# start with the set of file systems that the user asked for +# FILE_SYSTEM=$with_file_system +FILE_SYSTEM=`echo $with_file_system | sed -e 's/:.*$//'` + +# Check if Make is working +PAC_PROG_MAKE +# +# Check that an arch was set +# If it wasn't set, try to guess using "util/tarch" +# +# Sometimes tarch looses its execute bit (!) +if test -s $srcdir/util/tarch -a ! -x $srcdir/util/tarch ; then + chmod a+x $srcdir/util/tarch +fi +if test -z "$ARCH" -a -x $srcdir/util/tarch ; then + AC_MSG_CHECKING([for architecture]) + ARCH=`$srcdir/util/tarch | sed s/-/_/g` + if test -z "$ARCH" ; then + AC_MSG_RESULT([Unknown!]) + AC_MSG_ERROR([Error: Could not guess target architecture, you must +set an architecture type with the environment variable ARCH]) + fi + eval "arch_$ARCH=1" + AC_MSG_RESULT($ARCH) +fi +# +# check for valid architecture. Use __ so that _ALPHA_ does not match +# LINUX_ALPHA_ +#### WE SHOULD REMOVE THIS SOON +grep __"$ARCH"_ $srcdir/.config_params > /dev/null 2>&1 +if test $? != 0 ; then + AC_MSG_WARN([Unknown architecture $ARCH... proceeding anyway]) +fi +# +# +# Find the home directory if not specified +if test "X$srcdir" != "X." -a -s $srcdir/mpi-io/Makefile.in ; then + ROMIO_HOME_TRIAL=$srcdir +else + # Take advantage of autoconf2 features + if test -n "$ac_confdir" ; then + ROMIO_HOME_TRIAL=$ac_confdir + else + if test -s configure ; then + ROMIO_HOME_TRIAL=`pwd` + else + ac_confdir=`dirname "$0" 2>/dev/null` + if test -n "$ac_confdir" ; then + ROMIO_HOME_TRIAL=$ac_confdir + fi + fi + fi +fi +AC_MSG_RESULT([ROMIO home directory is $ROMIO_HOME_TRIAL]) +ROMIO_HOME=$ROMIO_HOME_TRIAL + +# get a fully qualified pathname for our build directory +top_build_dir=`pwd` +# used in romioinstall +AC_SUBST(top_build_dir) + +# +# Create the "autoconf" style directory names... +# Most of these are done for us; add the documentation directories +# +# mandir is the root for the man pages +if test -z "$mandir" ; then mandir='${prefix}/man' ; fi +AC_SUBST(mandir) +if test -z "$docdir" ; then docdir='${prefix}/doc' ; fi +AC_SUBST(docdir) +if test -z "$htmldir" ; then htmldir='${prefix}/www' ; fi +AC_SUBST(htmldir) + + +# If we are building within a known MPI implementation, we must avoid the +# tests about an existing implementation +if test "$FROM_MPICH" != no -o "$FROM_LAM" != no -o "$FROM_OMPI" != no ; then + WITHIN_KNOWN_MPI_IMPL=yes +else + WITHIN_KNOWN_MPI_IMPL=no +fi + +# Open MPI: Set the MPI implementation +if test "$FROM_OMPI" = "yes" ; then + MPI_IMPL=open_mpi +fi + +# check for valid MPI implementation +if test -n "$MPI_IMPL" ; then + found=no + for mpi in $known_mpi_impls ; do + if test "${MPI_IMPL}_mpi" = "$mpi" ; then + found=yes + break + fi + done + if test $found = no ; then + AC_MSG_WARN([Unknown MPI implementation $MPI... proceeding anyway]) + fi +fi +# + +if test -n "${with_mpi}" ; then + MPI_INCLUDE_DIR="${with_mpi}"/include + MPI_LIB_DIR="${with_mpi}"/lib +fi + +# check for valid MPI include directory if specified +if test $WITHIN_KNOWN_MPI_IMPL = no ; then + if test -n "$MPI_INCLUDE_DIR"; then + if test ! -f "$MPI_INCLUDE_DIR/mpi.h" ; then + AC_MSG_ERROR([Include file $MPI_INCLUDE_DIR/mpi.h not found]) + fi + else +# assume that mpi.h is in the default path +# set MPI_INCLUDE_DIR to ".", so that it translates to -I. in the +# compile command. Some compilers complain if it's only -I + MPI_INCLUDE_DIR=. + fi +else + MPI_INCLUDE_DIR=. +fi +# +# check for valid MPI library if specified +if test $WITHIN_KNOWN_MPI_IMPL = no ; then + if test -n "$MPI_LIB" ; then + if test ! -f "$MPI_LIB" ; then + AC_MSG_ERROR([MPI library $MPI_LIB not found]) + fi + fi +fi + +# USER_CFLAGS and USER_FFLAGS are used only in test/Makefile.in +if test $DEBUG = "yes"; then + USER_CFLAGS="$CFLAGS -g" + USER_FFLAGS="$FFLAGS -g" +else + USER_CFLAGS="$CFLAGS -O" + USER_FFLAGS="$FFLAGS -O" +fi +# +# Here begin the architecture-specific tests. +# -------------------------------------------------------------------------- +# We must first select the C and Fortran compilers. Because of the +# way that the PROG_CC autoconf macro works (and all of the macros that +# require it, including CHECK_HEADERS), that macro must occur exactly +# once in the configure.ac file, at least as of autoconf 2.57 . +# Unfortunately, this requirement is not enforced. To handle this, +# we first case on the architecture; then use PROG_CC, then case on the +# architecture again for any arch-specific features. We also set the +# C_DEBUG_FLAG and F77_DEBUG_FLAG in case debugging is selected. +# +# For the MPICH and MPICH configures, the compilers will already be +# selected, so most of the compiler-selection code will be bypassed. +# -------------------------------------------------------------------------- +# For historical reasons +if test -z "$FC" ; then + FC=$F77 +fi +# +C_DEBUG_FLAG="-g" +F77_DEBUG_FLAG="-g" + +dnl AC_PROG_{CXX,F77,FC} must come early in configure.ac in order to control +dnl compiler search order and avoid some esoteric autoconf macro expansion +dnl errors +if test "$enable_f77" = "yes" ; then + # suppress default "-g -O2" from AC_PROG_F77 + : ${FFLAGS=""} + AC_PROG_F77([PAC_F77_SEARCH_LIST]) +fi +if test "$enable_f90" = "yes" ; then + # suppress default "-g -O2" from AC_PROG_FC + : ${FCFLAGS=""} + AC_PROG_FC([PAC_FC_SEARCH_LIST]) +fi + +if test "$CC" = "gcc" -a -z "$C_DEBUG_FLAG" ; then + C_DEBUG_FLAG="-g -O -Wall -Wstrict-prototypes -Wmissing-prototypes" +fi +if test $DEBUG = "yes" ; then + CFLAGS="$CFLAGS $C_DEBUG_FLAG" +else + CFLAGS="$CFLAGS $C_OPT_FLAG" +fi +# --------------------------------------------------------------------------- +# Here go the rest of the tests +# --------------------------------------------------------------------------- + +AC_CHECK_TYPE(long long) +AC_CHECK_SIZEOF(long long) +if test -z "$MPI_IMPL" ; then + MPI_IMPL=mpich + mpi_mpich=1 +fi +if test $MPI_IMPL = "mpich" ; then + TEST_CC=mpicc + TEST_F77=mpifort +else + TEST_CC="$CC" + TEST_F77="$F77" +fi +# there used to be a ton of arch-specific stuff in here. If some random +# platform really truly needs it, restore it, but that defeats the whole + +PAC_GET_SPECIAL_SYSTEM_INFO + +AC_HAVE_FUNCS(memalign) + +# +# Question: Should ROMIO under MPICH ignore the Fortran tests, since +# MPICH provides all of the Fortran interface routines? +# +if test $NOF77 = 0 ; then + echo "checking Fortran external names" + PAC_GET_FORTNAMES + if test -n "$WDEF" ; then + CFLAGS="$CFLAGS $WDEF" + fi + dnl PAC_PROG_F77_NAME_MANGLE + dnl (need to set the new name format) + rm -f test/mpif.h + if test "$MPI_INCLUDE_DIR" != "." && test $WITHIN_KNOWN_MPI_IMPL = no ; then + if test ! -d test ; then mkdir test ; fi + ln -s $MPI_INCLUDE_DIR/mpif.h test + fi +else + F77=":" +fi +# +AC_C_INLINE + +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T +AC_TYPE_OFF_T + +# Header files +# Find the CPP before the header check +AC_PROG_CPP +AC_CHECK_HEADERS([unistd.h fcntl.h malloc.h stddef.h sys/types.h limits.h time.h]) +AC_CHECK_HEADERS(mpix.h,,,[#include ]) +# + +# When compiling ROMIO on Darwin with _POSIX_C_SOURCE defined (such as when +# using --enable-strict in MPICH), sys/types.h does not define u_short and +# friends unless _DARWIN_C_SOURCE is also defined (see compat(5) on a Darwin +# box). This would normally be fine, except sys/stat.h defines struct stat to +# use u_long, so strict compiles fail. One option is to also compile with +# _DARWIN_C_SOURCE, but this disables much of the strictness that is intended +# by _POSIX_C_SOURCE. Instead we just define our own types if they are not +# provided by the system. This isn't quite as safe as typedef'ing the +# replacement types, but it will apply to later configure tests, which is +# important. +AC_CHECK_TYPE([u_char],[],[AC_DEFINE_UNQUOTED([u_char],[unsigned char],[Define to "unsigned char" if sys/types.h does not define.])]) +AC_CHECK_TYPE([u_short],[],[AC_DEFINE_UNQUOTED([u_short],[unsigned short],[Define to "unsigned short" if sys/types.h does not define.])]) +AC_CHECK_TYPE([u_int],[],[AC_DEFINE_UNQUOTED([u_int],[unsigned int],[Define to "unsigned int" if sys/types.h does not define.])]) +AC_CHECK_TYPE([u_long],[],[AC_DEFINE_UNQUOTED([u_long],[unsigned long],[Define to "unsigned long" if sys/types.h does not define.])]) + +# must come _after_ the above checks for u_char/u_short/u_int/u_long +AC_CHECK_HEADERS([sys/attr.h]) + +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(void *) +AC_CACHE_CHECK([for int large enough for pointers], +pac_cv_int_hold_pointer,[ +if test "$ac_cv_sizeof_int" = "0" -o \ + "$ac_cv_sizeof_void_p" = "0" ; then + pac_cv_int_hold_pointer=unknown +elif test "$ac_cv_sizeof_int" -lt "$ac_cv_sizeof_void_p" ; then + pac_cv_int_hold_pointer=no +else + pac_cv_int_hold_pointer=yes +fi +]) +if test "$pac_cv_int_hold_pointer" != yes ; then + AC_DEFINE(INT_LT_POINTER,1,[Define if int smaller than pointer]) + dnl Switch to a conforming name (start with HAVE or USE) + AC_DEFINE(HAVE_INT_LT_POINTER,1,[Define if int smaller than pointer]) +fi + +# LL is the printf-style format name for output of a MPI_Offset. +# We have to match this to the type that we use for MPI_Offset. +AC_CHECK_SIZEOF(long long) +if test "$ac_cv_sizeof_long_long" != 0 ; then + if test "$ac_cv_sizeof_long_long" = "8" ; then + AC_DEFINE(HAVE_LONG_LONG_64,1,[Define if long long is 64 bits]) + MPI_OFFSET_TYPE="long long" + DEFINE_MPI_OFFSET="typedef long long MPI_Offset;" + FORTRAN_MPI_OFFSET="integer*8" + LL="lld" + elif test "$ac_cv_sizeof_long_long" = "$ac_cv_sizeof_int" ; then + MPI_OFFSET_TYPE="int" + DEFINE_MPI_OFFSET="typedef int MPI_Offset;" + FORTRAN_MPI_OFFSET="integer" + AC_DEFINE(MPI_OFFSET_IS_INT,1,[Define if MPI_Offset is int]) + LL="d" + MPI_OFFSET_KIND1="!" + MPI_OFFSET_KIND2="!" + else + echo "defining MPI_Offset as long in C and integer in Fortran" + MPI_OFFSET_TYPE="long" + DEFINE_MPI_OFFSET="typedef long MPI_Offset;" + FORTRAN_MPI_OFFSET="integer" + LL="ld" + MPI_OFFSET_KIND1="!" + MPI_OFFSET_KIND2="!" + fi +else + echo "defining MPI_Offset as long in C and integer in Fortran" + MPI_OFFSET_TYPE="long" + DEFINE_MPI_OFFSET="typedef long MPI_Offset;" + FORTRAN_MPI_OFFSET="integer" + LL="ld" + MPI_OFFSET_KIND1="!" + MPI_OFFSET_KIND2="!" +fi + + +# +if test -n "$ac_cv_sizeof_long_long"; then + if test $WITHIN_KNOWN_MPI_IMPL = no ; then + PAC_MPI_LONG_LONG_INT + else + AC_DEFINE(HAVE_MPI_LONG_LONG_INT,1,[Define if supports long long int]) + fi +fi +# +if test -n "$OFFSET_KIND" -a "A$MPI_OFFSET_KIND1" = "A!" ; then + MPI_OFFSET_KIND1=" INTEGER MPI_OFFSET_KIND" + MPI_OFFSET_KIND2=" PARAMETER (MPI_OFFSET_KIND=$OFFSET_KIND)" + MPI_OFFSET_KIND_VAL=$OFFSET_KIND +else + if test "$FORTRAN_MPI_OFFSET" = "integer*8" && test "A$MPI_OFFSET_KIND2" = "A!" && test $NOF77 = 0 && test $NOF90 = 0 ; then + PAC_MPI_OFFSET_KIND + fi + # + if test "$FORTRAN_MPI_OFFSET" = "integer" && test "A$MPI_OFFSET_KIND2" = "A!" && test $NOF77 = 0 && test $NOF90 = 0 ; then + PAC_MPI_OFFSET_KIND_4BYTE + fi +fi +# +# Test that we can use the FORTRAN_MPI_OFFSET type. If the environment +# is a strict Fortran 90/95 or later compiler, the "integer*8" format +# may not work. +if test "$NOF77" = 0 ; then + rm -f conftest* + ac_cv_f77_offset_type_works=no + AC_MSG_CHECKING([that we can use $FORTRAN_MPI_OFFSET to declare MPI_DISPLACMENT_CURRENT]) + cat >conftest.f <>config.log 2>&1 && test -x conftest$EXEEXT ; then + ac_cv_f77_offset_type_works=yes + fi + rm -f conftest* + AC_MSG_RESULT($ac_cv_f77_offset_type_works) + + if test "$ac_cv_f77_offset_type_works" != "yes" -a -n "$MPI_OFFSET_KIND_VAL"; then + AC_MSG_CHECKING([whether we can use KIND with the selected F77 compiler $F77]) + ac_cv_f77_allows_offset_kind=no + rm -f conftest* + cat >conftest.f <>config.log 2>&1 && test -x conftest$EXEEXT ; then + ac_cv_f77_allows_offset_kind=yes + fi + rm -f conftest* + AC_MSG_RESULT($ac_cv_f77_allows_offset_kind) + if test "$ac_cv_f77_allows_offset_kind" ; then + FORTRAN_MPI_OFFSET="integer (kind=$MPI_OFFSET_KIND_VAL)" + else + AC_MSG_WARN([Could not find a way to declare an integer type corresponding to MPI_Offset in Fortran.]) + fi + fi +fi + +# +# check if MPI_Info functions are defined in the MPI implementation +if test $WITHIN_KNOWN_MPI_IMPL = no ; then + PAC_MPI_INFO +else + AC_DEFINE(HAVE_MPI_INFO,1,[Define if MPI Info is available]) + HAVE_MPI_INFO="#define HAVE_MPI_INFO" + MPI_FINFO1="!" + MPI_FINFO2="!" + MPI_FINFO3="!" + MPI_FINFO4="!" +fi +# +if test -n "$mpi_sgi"; then +dnl if test -z "$HAVE_MPI_INFO" ; then +dnl PAC_CHECK_MPI_SGI_INFO_NULL # is MPI_INFO_NULL defined in mpi.h? +dnl fi + PAC_TEST_MPI_SGI_type_is_contig + PAC_TEST_MPI_COMBINERS + PAC_TEST_MPI_HAVE_OFFSET_KIND +fi +# +# check if darray and subarray constructors are defined in the MPI +# implementation +if test $WITHIN_KNOWN_MPI_IMPL = no ; then + PAC_MPI_DARRAY_SUBARRAY +fi +if test $FROM_MPICH = yes ; then + dnl Made this a message instead of a warning because the warning is + dnl likely to confuse users. + AC_MSG_RESULT([Overriding Array test for MPICH]) + unset BUILD_MPI_ARRAY + AC_DEFINE(HAVE_MPI_DARRAY_SUBARRAY,1,[Define if Darray is available]) + HAVE_MPI_DARRAY_SUBARRAY="#define HAVE_MPI_DARRAY_SUBARRAY" + MPI_FARRAY1="!" + MPI_FARRAY2="!" + MPI_FARRAY3="!" + MPI_FARRAY4="!" + MPI_FARRAY5="!" + MPI_FARRAY6="!" + MPI_FARRAY7="!" +fi + +# Check to see if weak symbols work correctly +if test "$enable_weak_symbols" = "yes" ; then + # Turn off weak symbols if they aren't available + PAC_PROG_C_WEAK_SYMBOLS(,enable_weak_symbols=no) +fi +if test "$enable_weak_symbols" = "yes" ; then + AC_DEFINE(USE_WEAK_SYMBOLS,1,[Define if weak symbols should be used]) + # Check for the ability to support multiple weak symbols + if test "$pac_cv_prog_c_weak_symbols" = "pragma weak" ; then + PAC_PROG_C_MULTIPLE_WEAK_SYMBOLS(AC_DEFINE(HAVE_MULTIPLE_PRAGMA_WEAK,1,[Define if multiple weak symbols may be defined])) + fi +fi + +if test "$enable_weak_symbols" = "yes" ; then + AC_DEFINE(HAVE_WEAK_SYMBOLS,1,[Define if weak symbols available]) + HAVE_WEAK_SYMBOLS=1 +else + HAVE_WEAK_SYMBOLS=0 +fi +AC_SUBST(HAVE_WEAK_SYMBOLS) + +AM_CONDITIONAL([BUILD_ROMIO_EMBEDDED],[test "$WITHIN_KNOWN_MPI_IMPL" = "yes" ]) +# FIXME need to get this right for non-MPICH builds +AM_CONDITIONAL([BUILD_MPIO_REQUEST],[false]) +# FIXME need to get this right for non-MPICH builds +AM_CONDITIONAL([BUILD_MPIO_ERRHAN],[false]) + +# if we don't have weak symbol support, we must build a separate convenience +# library in order to provide the "PMPI_" symbols +AM_CONDITIONAL([BUILD_PROFILING_LIB],[test "x$HAVE_WEAK_SYMBOLS" = "x0"]) + +# weird: we have conflated "buid ROMIO's versions of the fortran bindings" and +# "build ROMIO"s fortran I/O tests". Of course the common situaiton is that we +# are building as part of MPICH, which builds its own fortran bindings, but we +# still want tests built +AM_CONDITIONAL([BUILD_F77_BINDINGS],[test "x$NOF77" != "x1" && test "x$FROM_MPICH" != "xyes"]) + +AM_CONDITIONAL([BUILD_F77_TESTS],[test "x$NOF77" != "x1"]) + +# +# Check whether the MPI Offset type is compatible with struct flock +AC_MSG_CHECKING([whether struct flock compatible with MPI_Offset]) +AC_TRY_COMPILE([#include ], +[struct flock l; + $MPI_OFFSET_TYPE a=1; + l.l_start = a; + l.l_len = a; +],pac_cv_struct_flock_and_mpi_offset=yes,pac_cv_struct_flock_and_mpi_offset=no) +AC_MSG_RESULT($pac_cv_struct_flock_and_mpi_offset) +# FIXME: We should look for struct flock64 and the F_SETLK64/F_GETLK64 +# ADIOI_Set_lock could use these instead. +if test "$pac_cv_struct_flock_and_mpi_offset" = no ; then + AC_MSG_CHECKING([whether struct flock compatible with int]) + AC_TRY_COMPILE([#include ], +[struct flock l; + int a=1; + l.l_start = a; + l.l_len = a; +],pac_cv_struct_flock_and_int=yes,pac_cv_struct_flock_and_int=no) + AC_MSG_RESULT($pac_cv_struct_flock_and_int) + if test "$pac_cv_struct_flock_and_int" = yes ; then + AC_DEFINE(NEEDS_INT_CAST_WITH_FLOCK,1,[Define if l_start and l_len data should be cast as int]) + fi + # FIXME. Solaris header files define off_t as a UNION if 64bit file + # sizes are selected. Gah! +fi + +# +# if FILE_SYSTEM is not set above, use ufs and nfs as default +# +if test -z "$FILE_SYSTEM" ; then + FILE_SYSTEM="ufs nfs" +fi + +# no matter what, always build testfs +FILE_SYSTEM="testfs $FILE_SYSTEM" + +# check for valid file system +if test -n "$FILE_SYSTEM" ; then + # if multiple filesystems are passed in, they are '+'-delimited + # we could set the IFS to tokenize FILE_SYSTEM, but the FILE_SYSTEM env var + # is used in multiple places in the build system: get rid of the '+'s so we + # can use the 'for x in $FILE_SYSTEM ...' idiom + FILE_SYSTEM=`echo $FILE_SYSTEM|sed -e 's/\+/ /g'` + for x in $FILE_SYSTEM + do + found=no + # We could also do test -d "ad_$y" to test for known file systems + # based on having access to the adio code. Then adding a file + # system would not require changing configure to change known_filesystems + for y in $known_filesystems ; do + if test $x = $y ; then + found=yes + eval "file_system_`echo $x`=1" + break + fi + done + if test "$found" = "no" ; then + AC_MSG_WARN([Unknown file system $x... proceeding anyway]) + fi + done +fi + +############################################# +# This PVFS2 logic is special because it's hard to get it right if it comes +# before the known_filesystems check loop above. So we handle it down here, +# after the loop but before the AM_CONDITIONAL m4 loop. +############################################# +# +# An attempt to "do the right thing" with as little help from the end-user as +# possible: +# - if 'with-pvfs2' given, use that to find pvfs2-config. complain if we +# cannot find it, as this is probably what the user would expect +# - if we can find 'pvfs2-config' in our path, we can use it to set CFLAGS, +# LIBS, and LDFLAGS accordingly +# - as a fallback, use CFLAGS, LIBS, and LDFLAGS passed in by the user +# - don't do any of this if --with-file-system was given and did not include +# 'pvfs2': i.e. don't surprise the user with pvfs support. + +AC_PATH_PROG(PVFS2_CONFIG, pvfs2-config, notfound, [${with_pvfs2}/bin:$PATH]) +if test $PVFS2_CONFIG != "notfound" ; then + if test -n "${with_pvfs2}" -o -n "${file_system_pvfs2}" ; then + # the user either told us where pvfs is or asked for it in + # --with-file-system (or both) + CFLAGS="$CFLAGS $( $PVFS2_CONFIG --cflags)" + LIBS="$LIBS $( $PVFS2_CONFIG --libs)" + FILE_SYSTEM="pvfs2 $FILE_SYSTEM" + file_system_pvfs2=1 + fi +fi + +if test "$PVFS2_CONFIG" = "notfound" -a -n "$with_pvfs2" ; then + AC_MSG_ERROR([pvfs2-config not found in $with_pvfs2]) +fi +############################################# + + +# Setup an AM_CONDITIONAL named BUILD_AD_FOO for use in each adio's Makefile.mk. +# This must come *after* the condition becomes valid, in this case after all +# $file_system_foo variables have been set. +# +# If you fiddle with this, please watch the m4 quoting carefully. m4_foreach +# expands any macros in the "list" argument exactly once. The defn bits ensure +# that any macro names in "fs"'s value will not be expanded, such as if someone +# is daft enough to "m4_define([ufs],[some crazy value])". +m4_foreach([fs],[known_filesystems_m4],[ +AM_CONDITIONAL([BUILD_AD_]m4_toupper(defn([fs])),[test x$file_system_]defn([fs])[ = x1]) +]) + + +# +# Print list of configured file systems +# +# TODO: REMOVE BAD ONES FROM THE LIST SOMEHOW? +# +AC_MSG_CHECKING([configured file systems]) +AC_MSG_RESULT([$FILE_SYSTEM]) + + +if test -n "$file_system_nfs" ; then + AC_DEFINE(ROMIO_NFS,1,[Define for ROMIO with NFS]) + AC_MSG_WARN([File locks may not work with NFS. See the Installation and +users manual for instructions on testing and if necessary fixing this]) +fi + +if test -n "$file_system_panfs"; then + # TODO: are there ever any installations with the panfs SDK somewhere else? + CPPFLAGS="${CPPFLAGS} -I/opt/panfs/include" + AC_CHECK_HEADER(pan_fs_client_cw_mode.h, + AC_DEFINE(ROMIO_PANFS,1,[Define for ROMIO with PANFS]), + AC_MSG_ERROR([PANFS support requested but cannot find pan_fs_client_cw_mode.h header file]) + ) +fi + +if test -n "$file_system_ufs"; then + AC_DEFINE(ROMIO_UFS,1,[Define for ROMIO with UFS]) +fi + +changequote(<<,>>) +file_system_args=`echo $with_file_system | sed -e 's/^[^:]*//' -e 's/^://'` +changequote([,]) + +if test -n "$file_system_gpfs"; then + AC_DEFINE(ROMIO_GPFS,1,[Define for ROMIO with GPFS]) +fi + +AM_CONDITIONAL([BUILD_AD_BG],[false]) +AM_CONDITIONAL([BUILD_AD_PE],[false]) +if test "$file_system_args" = "BGQ" -a -n "$file_system_gpfs"; then + AC_DEFINE(BGQPLATFORM,1,BGQ platform) + AM_CONDITIONAL([BUILD_AD_BG],[true]) + dnl what if anything can make Blue Gene support aio? + disable_aio=yes +fi +if test "$file_system_args" = "PE" -a -n "$file_system_gpfs"; then + AC_DEFINE(PEPLATFORM,1,PE platform) + AM_CONDITIONAL([BUILD_AD_PE],[true]) +fi + +# echo "with_file_system is :"$with_file_system": file_system_args is :"$file_system_args": FILE_SYSTEM is :"$FILE_SYSTEM":" + +if test -n "$file_system_hfs"; then + AC_DEFINE(ROMIO_HFS,1,[Define for ROMIO with HFS]) +fi +if test -n "$file_system_sfs"; then + AC_DEFINE(ROMIO_SFS,1,[Define for ROMIO with SFS]) +fi + +if test -n "$file_system_pfs"; then + AC_DEFINE(ROMIO_PFS,1,[Define for ROMIO with PFS]) +fi + +if test -n "$file_system_testfs"; then + AC_DEFINE(ROMIO_TESTFS,1,[Define for ROMIO with TESTFS]) +fi +# +# Verify presence of lustre/lustre_user.h +# +if test -n "$file_system_lustre"; then + AC_CHECK_HEADERS(lustre/lustre_user.h, + AC_DEFINE(ROMIO_LUSTRE,1,[Define for ROMIO with LUSTRE]), + AC_MSG_ERROR([LUSTRE support requested but cannot find lustre/lustre_user.h header file]) + ) +fi + +if test -n "$file_system_xfs"; then + AC_DEFINE(ROMIO_XFS,1,[Define for ROMIO with XFS]) + # Check for memalign value + AC_CACHE_CHECK([for memory alignment needed for direct I/O], + pac_cv_memalignval, + [ + rm -f confmemalignval + rm -f /tmp/romio_tmp.bin + AC_TRY_RUN([ +#include +#include +#include +#include +int main(int argc, char **argv) { + struct dioattr st; + int fd = open("/tmp/romio_tmp.bin", O_RDWR | O_CREAT, 0644); + FILE *f=fopen("confmemalignval","w"); + if (fd == -1) exit(1); + if (!f) exit(1); + fcntl(fd, F_DIOINFO, &st); + fprintf( f, "%u\n", st.d_mem); + exit(0); + } + ], + pac_cv_memalignval=`cat confmemalignval`, + pac_cv_memalignval="unknown",pac_cv_memalignval="unknown" + ) + rm -f confmemalignval + rm -f /tmp/romio_tmp.bin + ]) + if test -n "$pac_cv_memalignval" -a "$pac_cv_memalignval" != 0 -a \ + "$pac_cv_memalignval" != "unknown" ; then + CFLAGS="$CFLAGS -DXFS_MEMALIGN=$pac_cv_memalignval" + else + AC_MSG_RESULT(assuming 128 for memory alignment) + CFLAGS="$CFLAGS -DXFS_MEMALIGN=128" + fi +fi + +# +# Verify presence of pvfs.h, issue with int64 +# +if test -n "$file_system_pvfs"; then + CPPFLAGS="$CPPFLAGS $CFLAGS" + AC_CHECK_HEADERS(pvfs.h, + AC_DEFINE(ROMIO_PVFS,1,[Define for ROMIO with PVFS]), + AC_MSG_ERROR([PVFS support requested but cannot find pvfs.h header file]) + ) + # Check for missing int64_t (intel version 8 compiler and -no-gcc + # selected) + AC_MSG_CHECKING([that pvfs.h can be compiled]) + AC_TRY_COMPILE([ +#include + ],[ + ],pvfs_header_ok=yes,pvfs_header_ok=no + ) + AC_MSG_RESULT($pvfs_header_ok) + if test "$pvfs_header_ok" = no -a "$ac_cv_sizeof_long_long" = 8 ; then + AC_MSG_CHECKING([if pvfs.h can be compiled if we define int64_t]) + # Try again, but with int64_t + AC_TRY_COMPILE([ + typedef long long int int64_t; +#include + ],[ + ], + pvfs_header_ok="yes with int64 definition" + ) + AC_MSG_RESULT($pvfs_header_ok) + fi + if test "$pvfs_header_ok" = "yes with int64 definition" ; then + AC_DEFINE(ROMIO_PVFS_NEEDS_INT64_DEFINITION,1,[Define if int64_t must be defined for PVFS]) + fi + if test "$pvfs_header_ok" != "no" ; then + AC_DEFINE(ROMIO_PVFS,1,[Define for ROMIO with PVFS]) + AC_DEFINE(HAVE_PVFS_SUPER_MAGIC, 1, [Define if PVFS_SUPER_MAGIC defined.]) + else + AC_MSG_WARN(missing or broken pvfs.h header file; disabling ROMIO PVFS support) + fi +fi + + + +if test -n "$file_system_zoidfs"; then + AC_CHECK_HEADERS(zoidfs.h, + AC_DEFINE(ROMIO_ZOIDFS,1,[Define for ROMIO with ZoidFD]), + AC_MSG_ERROR([ZoidFS support requested but cannot find zoidfs.h header file]) + ) +fi + +# +# Verify presence of pvfs2.h +# +if test -n "$file_system_pvfs2"; then + CPPFLAGS="$CPPFLAGS $CFLAGS" + AC_CHECK_HEADERS(pvfs2.h, + AC_DEFINE(ROMIO_PVFS2,1,[Define for ROMIO with PVFS2]) + AC_DEFINE(HAVE_PVFS2_SUPER_MAGIC, 1, [Define if PVFS2_SUPER_MAGIC defined.]), + AC_MSG_ERROR([PVFS2 support requested but cannot find pvfs2.h header file]) + ) +fi + +# layout change after pvfs-2.6.3: +if test -n "$file_system_pvfs2"; then + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([ +#include +#include "pvfs2.h" + int main(int argc, char **argv) { + PVFS_object_ref ref; + PVFS_sys_attr attr; + PVFS_sys_create(NULL, ref, attr, NULL, NULL, NULL, NULL); + return 0; } + ])], + , AC_DEFINE(HAVE_PVFS2_CREATE_WITHOUT_LAYOUT, 1, + [Define if PVFS_sys_create does not have layout parameter]) + ) +fi + + +if test -n "$file_system_gridftp"; then + AC_DEFINE(ROMIO_GRIDFTP, 1, [Define for ROMIO with gridftp]) +fi + +AS_IF([test -n "$file_system_gpfs"], + [SYSDEP_INC=-I${prefix}/include], [SYSDEP_INC=]) + +AC_CHECK_HEADERS([gpfs.h gpfs_fcntl.h]) +AS_IF([test "$ac_cv_header_gpfs_h" = "yes" -o "$ac_cv_header_gpfs_fcntl_h" = "yes"], [ + AC_SEARCH_LIBS([gpfs_fcntl], [gpfs], [], + [AC_MSG_ERROR([Library containing gpfs_fcntl symbols not found])]) +]) +# Check for presence and characteristics of async. I/O calls if +# not disabled. + +# Some systems need pthreads to get AIO to work. However, we don't want +# to add pthreads just because it is there, as that can cause problems +# with some implementations of pthreads and compilers (e.g., gcc version 3 +# would fail if there was an int a[100000] on the stack if the application +# was *linked* with pthreads, but would succeed if the application was +# *not linked* with pthreads. +# +if test "x$disable_aio" = "xno" ; then + AC_SEARCH_LIBS(aio_write,aio rt,aio_write_found=yes,aio_write_found=no) + if test "$aio_write_found" = no ; then + # If not found, try finding pthread_create first, and if + # found, try the test again. + AC_SEARCH_LIBS(pthread_create,pthread,foundPTHREAD=yes,foundPTHREAD=no) + if test "$foundPTHREAD" = yes ; then + AC_SEARCH_LIBS(aio_write,aio rt,aio_write_found=yes,aio_write_found=no) + fi + fi +fi + +if test "x$disable_aio" = "xno" -a -n "$aio_write_found" ; then + AC_CHECK_HEADERS(signal.h) + # Just because aio.h is found by CPP doesn't mean that we can use it + # We try to compile it, not just read it. + AC_MSG_CHECKING([if aio.h exists and can be compiled]) + AC_TRY_COMPILE([ +#include +#include ], +[],have_aio_h=yes,have_aio_h=no) + AC_MSG_RESULT($have_aio_h) + if test "$have_aio_h" = yes ; then + AC_DEFINE(HAVE_AIO_H,1,[Define if aio.h exists and can be compiled]) + fi + + AC_MSG_CHECKING([if sys/aio.h exists and can be compiled]) + AC_TRY_COMPILE([ +#include +#include ], +[],have_sys_aio_h=yes,have_sys_aio_h=no) + AC_MSG_RESULT($have_sys_aio_h) + if test "$have_sys_aio_h" = yes ; then + AC_DEFINE(HAVE_SYS_AIO_H,1,[Define if sys/aio.h exists and can be compiled]) + fi + if test "$have_aio_h" = "no" -a "$have_sys_aio_h" = "no" ; then + disable_aio=yes + fi +fi + +if test "$have_aio_h" = "yes" -o "$have_sys_aio_h" = "yes" -o "x$disable_aio" = "xno"; then + + # Check that aio is available (many systems appear to have aio + # either installed improperly or turned off). + # The test is the following: if not cross compiling, try to run a + # program that includes a *reference* to aio_write but does not call it + # If the libraries are not set up correctly, then this will fail. + + AC_MSG_CHECKING([whether aio routines can be used]) + # Include aio.h and the aiocb struct (since we'll need these to + # actually use the aio_write interface). Note that this will + # fail for some pre-POSIX implementations of the aio interface + # (an old IBM interface needs an fd argument as well) + AC_TRY_RUN([ +#include +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + int main(int argc, char **argv) + { + struct aiocb *aiocbp; + if (argc > 10) aio_write(aiocbp); + return 0; + } + ], + aio_runs=yes + AC_MSG_RESULT(yes), + aio_runs=no + AC_MSG_RESULT(no), + aio_runs=no + AC_MSG_RESULT(no: aio routines disabled when cross compiling) + ) + if test "$aio_runs" != "no" ; then + AC_DEFINE(ROMIO_HAVE_WORKING_AIO, 1, Define if AIO calls seem to work) + fi + + # now about that old IBM interface... + # modern AIO interfaces have the file descriptor in the aiocb structure, + # and will set ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_FILDES. Old IBM + # implementations pass the file descriptor as an argument to aio_write and + # aio_read. AIO still works on these platforms, but we have to test with + # two-argument aio_write to avoid a false negative. no need to worry about + # the two-argument vs. one-argument aio_write and aio_read: ROMIO already + # uses ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_FILDES to call aio_write and + # aio_read correctly + + AC_MSG_CHECKING([for obsolete two-argument aio_write]) + AC_TRY_RUN([ +#include +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + int main(int argc, char **argv) + { + int fd; + struct aiocb *aiocbp; + if (argc > 10) aio_write(fd, aiocbp); + return 0; + } + ], + aio_two_arg_write=yes + AC_MSG_RESULT(yes), + aio_two_arg_write=no + AC_MSG_RESULT(no), + aio_two_arg_write=no + AC_MSG_RESULT(no: cannot test when cross-compiling) + ) + + if test "$aio_two_arg_write" != "no" -a "$aio_runs" != "yes" ; then + AC_DEFINE(ROMIO_HAVE_WORKING_AIO, 1, Define if AIO calls seem to work) + AC_DEFINE(ROMIO_HAVE_AIO_CALLS_NEED_FILEDES, 1, Define if AIO calls need file descriptor) + fi + + AC_MSG_CHECKING([for obsolete two-argument aio_suspend]) + AC_TRY_RUN([ +#include +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + int main(int argc, char **argv) + { + struct aiocb *aiocbp; + if (argc > 10) aio_suspend(1, &aiocbp); + return 0; + } + ], + aio_two_arg_suspend=yes + AC_MSG_RESULT(yes), + aio_two_arg_suspend=no + AC_MSG_RESULT(no), + aio_two_arg_suspend=no + AC_MSG_RESULT(no: cannot test when cross compiling) + ) + + if test "$aio_two_arg_suspend" != "no" -a "$aio_runs" != "yes" ; then + AC_DEFINE(ROMIO_HAVE_AIO_SUSPEND_TWO_ARGS, 1, Define if aio_suspend needs two arguments) + fi + + AC_MSG_CHECKING([for aio_fildes member of aiocb structure]) + AC_TRY_COMPILE([ +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + ],[ + struct aiocb a; + a.aio_fildes = 0; + ], + AC_MSG_RESULT(yes) + AC_DEFINE(ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_FILDES, 1, [Define if aiocb has aio_fildes member]), + AC_MSG_RESULT(no) + ) + AC_MSG_CHECKING(for aio_whence member of aiocb structure) + AC_TRY_COMPILE([ +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif +#include +#include + ],[ + struct aiocb a; + a.aio_whence = SEEK_SET; + ], + AC_MSG_RESULT(yes) + AC_DEFINE(ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_WHENCE, 1, [Define if aiocb has aio_whence member]), + AC_MSG_RESULT(no) + ) + AC_MSG_CHECKING(for aio_handle member of aiocb structure) + AC_TRY_COMPILE([ +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + ],[ + struct aiocb a; + aio_handle_t h; + + a.aio_handle = h; + ], + AC_MSG_RESULT(yes) + AC_DEFINE(ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_HANDLE, 1, [Define if aiocb has aio_handle member]), + AC_MSG_RESULT(no) + ) + AC_MSG_CHECKING(for aio_reqprio member of aiocb structure) + AC_TRY_COMPILE([ +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + ],[ + struct aiocb a; + + a.aio_reqprio = 0; + ], + AC_MSG_RESULT(yes) + AC_DEFINE(ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_REQPRIO, 1, [Define if aiocb has aio_reqprio member]), + AC_MSG_RESULT(no) + ) + AC_MSG_CHECKING(for aio_sigevent member of aiocb structure) + AC_TRY_COMPILE([ +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_AIO_H +#include +#endif +#ifdef HAVE_SYS_AIO_H +#include +#endif + ],[ + struct aiocb a; + + a.aio_sigevent.sigev_signo = 0; + ], + AC_MSG_RESULT(yes) + AC_DEFINE(ROMIO_HAVE_STRUCT_AIOCB_WITH_AIO_SIGEVENT, 1, [Define if aiocb has aio_sigevent member]), + AC_MSG_RESULT(no) + ) + +fi + +# End of aio-related tests + +# +# Check for statfs (many) and specifically f_fstypename field (BSD) +# +AC_CHECK_HEADERS(sys/vfs.h sys/param.h sys/mount.h sys/statvfs.h) +AC_CHECK_FUNCS([statfs]) +AC_MSG_CHECKING([whether struct statfs properly defined]) +AC_TRY_COMPILE([ +#ifdef HAVE_SYS_VFS_H +#include +#endif +#ifdef HAVE_SYS_STATVFS_H +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif + ],[ + struct statfs f; + ], + pac_cv_have_statfs=yes,pac_cv_have_statfs=no +) +AC_MSG_RESULT($pac_cv_have_statfs) +# At this point, we could check for whether defining +# __SWORD_TYPE as sizet_t or int/long (size of pointer) +# would help. FIXME + +if test "$pac_cv_have_statfs" = yes ; then + AC_DEFINE(HAVE_STRUCT_STATFS,1,[Define if struct statfs can be compiled]) +fi + +AC_MSG_CHECKING([for f_fstypename member of statfs structure]) +AC_TRY_COMPILE([ +#include +#include +#include + ],[ + struct statfs f; + memset(&f, 0, sizeof(f)); + strncmp("nfs", f.f_fstypename, 3); + ], + pac_cv_have_statfs_f_fstypename=yes, + pac_cv_have_statfs_f_fstypename=no +) +AC_MSG_RESULT($pac_cv_have_statfs_f_fstypename) +if test $pac_cv_have_statfs_f_fstypename = yes ; then + AC_DEFINE(ROMIO_HAVE_STRUCT_STATFS_WITH_F_FSTYPENAME, 1,[Define if statfs has f_fstypename]) +fi + +# +# Check for stat and st_fstype field (NEC SX4) +# +AC_CHECK_HEADERS(sys/stat.h sys/types.h unistd.h) +AC_CHECK_FUNCS(stat, + AC_DEFINE(HAVE_STAT, 1, Define if stat function is present) + AC_MSG_CHECKING([for st_fstype member of stat structure]) + AC_TRY_COMPILE([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + ],[ + struct stat s; + + s.st_fstype = NULL; + ], + AC_MSG_RESULT(yes) + AC_DEFINE(ROMIO_HAVE_STRUCT_STAT_WITH_ST_FSTYPE, 1, Define if struct stat has a st_fstype member), + AC_MSG_RESULT(no) + ) +) + +# +# Check for statvfs and f_basetype field (Solaris, Irix, AIX, etc.) +# +AC_CHECK_HEADERS(sys/types.h sys/statvfs.h sys/vfs.h) +AC_CHECK_FUNCS(statvfs, + AC_DEFINE(HAVE_STATVFS, 1, Define if statvfs function is present) + AC_MSG_CHECKING([for f_basetype member of statvfs structure]) + AC_TRY_COMPILE([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_VFS_H +#include +#endif +#ifdef HAVE_SYS_STATVFS_H +#include +#endif + ], [[ + struct statvfs foo; + + foo.f_basetype[0] = 'a'; + ]], + AC_MSG_RESULT(yes) + AC_DEFINE(ROMIO_HAVE_STRUCT_STATVFS_WITH_F_BASETYPE, 1, defined if struct statvfs has a f_basetype member), + AC_MSG_RESULT(no) + ) +) + +AC_CHECK_TYPE([blksize_t],[],[AC_DEFINE_UNQUOTED([blksize_t],[__blksize_t],[Provide blksize_t if not available]) ], [[ + #ifdef HAVE_SYS_TYPES_H + #include + #endif + #ifdef HAVE_SYS_STAT_H + #include + #endif + #ifdef HAVE_UNISTD_H + #include + #endif]] ) + +# +# Check for large file support. Make sure that we can use the off64_t +# type (in some cases, it is an array, and the ROMIO code isn't prepared for +# that). +# +AC_CHECK_HEADERS(unistd.h) +if test "$ac_cv_header_unistd_h" = "yes" ; then + AC_CACHE_CHECK([for large file defines],ac_cv_has_large_file_defines,[ + AC_TRY_COMPILE([ +#include + ], [ +#ifndef _LFS64_LARGEFILE +#error no largefile defines +#endif + ],ac_cv_has_large_file_defines=yes,ac_cv_has_large_file_defines=no)]) + if test "$ac_cv_has_large_file_defines" = "yes" ; then + # See if we can use them + AC_CACHE_CHECK([whether off64_t is an scalar type],ac_cv_off64_t_scalar,[ + AC_TRY_COMPILE([ +#define _LARGEFILE64_SOURCE +#define _FILE_OFFSET_BITS 64 +#include +#include +],[off64_t a = 3;],ac_cv_off64_t_scalar=yes,ac_cv_off64_t_scalar=no)]) + + if test "$ac_cv_off64_t_scalar" = "yes" ; then + CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64" + fi + fi +fi + + +#################################################################### +# We're about to mess with CC etc. No more feature tests past here, +# because we may set CC to something that does not yet exist! +#################################################################### + +if test -n "$mpi_mpich"; then + if test -z "$arch_SX4" ; then + MPIOF_H_INCLUDED=1 + fi + if test "$FROM_MPICH" = no; then + AC_DEFINE(NEEDS_MPI_TEST,1,[Define if mpi_test needed]) + AC_DEFINE(MPICH,1,[Define if using MPICH]) + fi +fi + +if test -n "$mpi_sgi"; then + AC_DEFINE(MPISGI,1,[Define if SGI MPI]) +fi + +if test -n "$mpi_lam"; then + AC_DEFINE(MPILAM,1,[Define if using LAM/MPI]) +fi + +if test -n "$mpi_hp"; then + AC_DEFINE(MPIHP,1,[Define if using HP MPI]) + if test "$NOF77" = 0; then + PAC_CHECK_MPIOF_H + fi +fi +# +AC_CHECK_FUNCS(strerror) +if test -z "$srcdir" -o "$srcdir" = "." ; then srcdir="$ROMIO_HOME" ; fi +AC_SUBST(srcdir) + +# preserve these values across a config.status --recheck +AC_ARG_VAR([master_top_srcdir],[set by the MPICH configure to indicate the MPICH source root]) +AC_ARG_VAR([master_top_builddir],[set by the MPICH configure to indicate the MPICH build root]) + +# The master_top_srcdir is the location of the source for the building +# package. This is used only as part of the MPICH build, including +# the documentation targets mandoc, htmldoc, and latexdoc +if test -z "$master_top_srcdir" ; then + if test "$FROM_MPICH" = yes ; then + AC_MSG_WARN([Could not determine master_top_srcdir]) + fi +fi +# +# Get the master builddir (which may be imported from above) +if test -z "$master_top_builddir" ; then + if test "$FROM_MPICH" = yes ; then + # this variable is essential to proper build operation + AC_MSG_ERROR([Could not determine master_top_srcdir]) + fi + master_top_builddir=`pwd` +fi +# Make sure the alternate spelling is used until we clean up all of the code +master_topbuild_dir=$master_top_builddir +export master_topbuild_dir +AC_SUBST(master_topbuild_dir) + +# The following definitions are needed within adio/common/status_setb.c +if test "$FROM_MPICH" = yes ; then + AC_DEFINE(ROMIO_INSIDE_MPICH,1,[Define if compiling within MPICH]) +elif test "$FROM_MPILAM" = yes ; then + AC_DEFINE(MPILAM,1,[Define if compiling within LAM/MPI]) +fi + +if test "$FROM_MPICH" = no ; then + if test -z "$LIBNAME"; then + LIBNAME="$top_build_dir/lib/libmpio.a" + fi + # + if test ! -d $top_build_dir/lib ; then + mkdir $top_build_dir/lib + fi +else + MPILIBNAME=${MPILIBNAME:-mpich} + if test -z "$LIBNAME" ; then + if test -d "$master_top_builddir/lib" ; then + LIBNAME=$master_top_builddir/lib/lib${MPILIBNAME}.a + else + LIBNAME="$ROMIO_HOME/lib${MPILIBNAME}.a" + fi + fi +fi +if test "$FROM_MPICH" != no ; then + # use the error handlers from MPICH + MPIO_EXTRA_OBJECTS= + MPIO_EXTRA_TMP_POBJECTS= + MPIO_EXTRA_REAL_POBJECTS= + # Use generalized request to get the multiple-completion routines + MPIO_REQOBJECTS= +fi +AC_SUBST(MPIO_EXTRA_OBJECTS) +AC_SUBST(MPIO_EXTRA_TMP_POBJECTS) +AC_SUBST(MPIO_EXTRA_REAL_POBJECTS) +# +# Use DOCTEXT instead of doctext +AC_CHECK_PROGS(DOCTEXT,doctext,true) +AC_SUBST(DOCTEXT) +# +if test $NOF77 = 1 ; then + F77=":" +else + FORTRAN_TEST="fperf fcoll_test fmisc pfcoll_test" +fi +# +if test $WITHIN_KNOWN_MPI_IMPL = no ; then + PAC_TEST_MPI + PAC_NEEDS_FINT +else + NEEDS_MPI_FINT="" +fi +# +if test "$MPI_INCLUDE_DIR" = "." ; then + ROMIO_INCLUDE="-I../include" +else + ROMIO_INCLUDE="-I../include -I$MPI_INCLUDE_DIR" +fi +# +TEST_LIBNAME=$LIBNAME +MPIRUN=mpirun +if test $FROM_OMPI = yes ; then + # Open MPI does have the status set bytes functionality + + AC_DEFINE(HAVE_STATUS_SET_BYTES,1,[Define if have MPIR_Status_set_bytes]) + + # Used in the tests/ subdirectory for after ROMIO is built + + TEST_CC=mpicc + TEST_F77=mpifort + MPIRUN=mpirun + MPI_LIB= + NOPROFILE=1 + ROMIO_INCLUDE= + USER_CFLAGS= + USER_FFLAGS= + TEST_LIBNAME= + AC_DEFINE(HAVE_MPI_DARRAY_SUBARRAY,1,[Define if Darray is available]) + HAVE_MPI_DARRAY_SUBARRAY="#define HAVE_MPI_DARRAY_SUBARRAY" + # Open MPI: see comments in mpi-io/mpioprof.h + AC_DEFINE(MPIO_BUILD_PROFILING, 1, [hack to make ROMIO build without profiling]) + DEFINE_HAVE_MPI_GREQUEST="#define HAVE_MPI_GREQUEST" + AC_DEFINE(HAVE_DECL_MPI_COMBINER_HINDEXED_BLOCK, 1, [Define if MPI library provides HINDEXED_BLOCK datatype]) +elif test $FROM_LAM = yes ; then + # LAM does have the status set bytes functionality + AC_DEFINE(HAVE_STATUS_SET_BYTES,1,[Define if have MPIR_Status_set_bytes]) + + # Used in the tests/ subdirectory for after ROMIO is built + TEST_CC=mpicc + TEST_F77=mpifort + MPIRUN=mpirun + MPI_LIB= + ROMIO_INCLUDE= + USER_CFLAGS= + USER_FFLAGS= + TEST_LIBNAME= + EXTRA_DIRS="mpi-io/fortran mpi2-other/info mpi2-other/info/fortran mpi2-other/array mpi2-other/array/fortran" +elif test $FROM_MPICH = yes ; then + # For now, separate the mpich from mpich cases + MPICH_HOME=`dirname $ROMIO_HOME` + MPICH_HOME=`dirname $MPICH_HOME` + MPICH_HOME=`dirname $MPICH_HOME` + if test -z "$MPI_BIN_DIR" ; then MPI_BIN_DIR=$MPICH_HOME/bin ; fi + # No special compiler script. + # BUT we need the include paths + # CC="$CC -I${use_top_srcdir}/src/include -I${top_build_dir}/src/include" + # TEST_CC="$CC" + # MPI_LIB="$LIBNAME" + # To allow ROMIO to work with the LIBTOOL scripts, we want to + # work directly with the CC, not the mpicc, compiler. + # Note that in the "FROM_MPICH" case, the CPPFLAGS and INCLUDES are already + # properly set + #CC=${top_build_dir}/bin/mpicc + # + # set the compilers to the ones in MPICH bin directory (master_top_builddir/bin) + TEST_CC='$(bindir)/mpicc' + TEST_F77='$(bindir)/mpifort' + MPI_H_INCLUDE="-I${master_top_builddir}/src/include" + ROMIO_INCLUDE="" + USER_CFLAGS="" + USER_FFLAGS="" + TEST_LIBNAME="" + MPIRUN='${bindir}/mpiexec' + # + # Turn off the building of the Fortran interface and the Info routines + EXTRA_DIRS="" + AC_DEFINE(HAVE_STATUS_SET_BYTES,1,[Define if status_set_bytes available]) + DEFINE_HAVE_MPI_GREQUEST="#define HAVE_MPI_GREQUEST 1" + DEFINE_HAVE_MPI_GREQUEST_EXTENSIONS="#define HAVE_MPI_GREQUEST_EXTENSIONS 1" + AC_DEFINE(HAVE_MPIU_FUNCS,1,[Define if MPICH memory tracing macros defined]) + AC_DEFINE(HAVE_MPIX_H, 1, []) + AC_DEFINE(HAVE_MPIIO_CONST, const, Set if MPI-IO prototypes use const qualifier) + AC_DEFINE(HAVE_MPI_TYPE_SIZE_X, 1, [Define if MPI library provides MPI_TYPE_SIZE_X]) + AC_DEFINE(HAVE_MPI_STATUS_SET_ELEMENTS_X, 1, [Define if MPI library provides MPI_STATUS_SET_ELEMENTS_X]) + AC_DEFINE(HAVE_DECL_MPI_COMBINER_HINDEXED_BLOCK, 1, [Define if MPI library provides HINDEXED_BLOCK datatype]) +fi +# +# +# feature tests: we can't test features if building as part of MPICH because +# we don't yet have an implementation against which we can test +# +if test $WITHIN_KNOWN_MPI_IMPL = no ; then + PAC_TEST_MPIR_STATUS_SET_BYTES + PAC_TEST_MPI_GREQUEST + PAC_TEST_MPIU_FUNCS + AC_DEFINE(PRINT_ERR_MSG,1,[Define for printing error messages]) + AC_CHECK_TYPE(MPI_Count,[],[AC_DEFINE_UNQUOTED([MPI_Count],[MPI_Aint],[Define to "MPI_Aint" if MPI does not provide MPI_Count]) ]) + PAC_TEST_NEEDS_CONST + AC_CHECK_DECLS([MPI_COMBINER_HINDEXED_BLOCK], [], [], [[#include ]]) + AC_CHECK_FUNCS(MPI_Type_size_x MPI_Status_set_elements_x) +fi +# +if test -z "$TEST_CC" ; then + TEST_CC="$CC" +fi +if test -z "$TEST_F77" ; then + TEST_F77="$F77" +fi +# +AC_CHECK_FUNCS(strdup) +if test "$ac_cv_func_strdup" = "yes" ; then + # Do we need to declare strdup? + PAC_FUNC_NEEDS_DECL([#include ],strdup) +fi +AC_CHECK_FUNCS(snprintf) +if test "$ac_cv_func_snprintf" = "yes" ; then + # Do we need to declare snprintf? + PAC_FUNC_NEEDS_DECL([#include ],snprintf) +fi +AC_CHECK_FUNCS(lstat) +if test "$ac_cv_func_lstat" = "yes" ; then + # Do we need to declare lstat? + PAC_FUNC_NEEDS_DECL([#include ],lstat) +fi +AC_CHECK_FUNCS(readlink) +if test "$ac_cv_func_readlink" = "yes" ; then + # Do we need to declare readlink? + PAC_FUNC_NEEDS_DECL([#include ],readlink) +fi +AC_CHECK_FUNCS(fsync) +if test "$ac_cv_func_fsync" = "yes" ; then + # Do we need to declare fsync? + PAC_FUNC_NEEDS_DECL([#include ],fsync) +fi +AC_CHECK_FUNCS(ftruncate) +if test "$ac_cv_func_ftruncate" = "yes" ; then + # Do we need to declare ftruncate? + PAC_FUNC_NEEDS_DECL([#include ],ftruncate) +fi + +AC_CHECK_FUNCS(lseek64) +if test "$ac_cv_func_lseek64" = "yes" ; then + PAC_FUNC_NEEDS_DECL([#include ],lseek64) +fi + +AC_CHECK_FUNCS(usleep) +if test "$ac_cv_func_usleep" = "yes" ; then + PAC_FUNC_NEEDS_DECL([#include ],usleep) +fi + +# +# Create the directory lists for the Makefile +FILE_SYS_DIRS="" +for dir in $FILE_SYSTEM ; do + FILE_SYS_DIRS="$FILE_SYS_DIRS adio/ad_$dir" +done +# FIXME eliminate FILE_SYS_DIRS and EXTRA_SRC_DIRS +EXTRA_SRC_DIRS="" + +mpio_glue="" +if test "$FROM_MPICH" = yes -o "${MPI_IMPL}_mpi" = "mpich_mpi"; then + mpio_glue=mpich +elif test "$FROM_OMPI" = yes -o "${MPI_IMPL}_mpi" = "open_mpi_mpi" ; then + mpio_glue=openmpi +else + mpio_glue=default +fi + +AM_CONDITIONAL([MPIO_GLUE_MPICH],[test "X$mpio_glue" = "Xmpich"]) +AM_CONDITIONAL([MPIO_GLUE_OPENMPI],[test "X$mpio_glue" = "Xopenmpi"]) +AM_CONDITIONAL([MPIO_GLUE_DEFAULT],[test "X$mpio_glue" = "Xdefault"]) + +if test "$BUILD_MPI_INFO" = 1 ; then + EXTRA_SRC_DIRS="$EXTRA_SRC_DIRS mpi2-other/info" + if test "$NOF77" = 0 -a "$FROM_MPICH" != yes ; then + EXTRA_SRC_DIRS="$EXTRA_SRC_DIRS mpi2-other/info/fortran" + fi +fi +if test "$BUILD_MPI_ARRAY" = 1 ; then + EXTRA_SRC_DIRS="$EXTRA_SRC_DIRS mpi2-other/array" + if test "$NOF77" = 0 -a "$FROM_MPICH" != yes ; then + EXTRA_SRC_DIRS="$EXTRA_SRC_DIRS mpi2-other/array/fortran" + fi +fi +if test "$NOF77" = 0 -a "$FROM_MPICH" != yes ; then + EXTRA_SRC_DIRS="$EXTRA_SRC_DIRS mpi-io/fortran" +fi +AC_SUBST(EXTRA_SRC_DIRS) +AC_SUBST(FILE_SYS_DIRS) + +# +CFLAGS="$CFLAGS -DHAVE_ROMIOCONF_H" +# + +if test -n "$MPIOF_H_INCLUDED"; then + F77MPIOINC="" +else + F77MPIOINC="include 'mpiof.h'" +fi + +AC_CHECK_HEADERS(unistd.h, + AC_MSG_CHECKING([for large file defines]) + AC_TRY_COMPILE([ + #include + ], [ + #ifndef _LFS64_LARGEFILE + #error no largefile defines + #endif + ], + CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64" + AC_MSG_RESULT(yes), + AC_MSG_RESULT(none) ) + ) + +echo "setting SYSDEP_INC to $SYSDEP_INC" +AC_SUBST(SYSDEP_INC) + +AC_C_RESTRICT +PAC_C_GNU_ATTRIBUTE + +# support gcov test coverage information +PAC_ENABLE_COVERAGE + +echo "setting CC to $CC" +echo "setting F77 to $F77" +echo "setting TEST_CC to $TEST_CC" +echo "setting TEST_F77 to $TEST_F77" +echo "setting CFLAGS to $CFLAGS" +echo "setting USER_CFLAGS to $USER_CFLAGS" +echo "setting USER_FFLAGS to $USER_FFLAGS" + +AC_SUBST(ARCH) +AC_SUBST(FILE_SYSTEM) +AC_SUBST(CC) +AC_SUBST(CPPFLAGS) +AC_SUBST(CFLAGS) +AC_SUBST(USER_CFLAGS) +AC_SUBST(USER_FFLAGS) +AC_SUBST(MIPS) +AC_SUBST(BITS) +AC_SUBST(AR) +AC_SUBST(AR_FLAGS) +AC_SUBST(MPI_INCLUDE_DIR) +AC_SUBST(MPI_LIB) +AC_SUBST(F77) +AC_SUBST(NOF77) +AC_SUBST(NOPROFILE) +AC_SUBST(MAKE) +AC_SUBST(arch_IRIX) +AC_SUBST(ROMIO_HOME) +AC_SUBST(LIBNAME) +AC_SUBST(TEST_LIBNAME) +AC_SUBST(LL) +AC_SUBST(F77GETARG) +AC_SUBST(F77IARGC) +AC_SUBST(F77MPIOINC) +AC_SUBST(FTESTDEFINE) +AC_SUBST(FORTRAN_MPI_OFFSET) +AC_SUBST(FROM_MPICH) +AC_SUBST(FROM_LAM) +AC_SUBST(WITHIN_KNOWN_MPI_IMPL) +AC_SUBST(NEEDS_MPI_FINT) +AC_SUBST(HAVE_MPI_INFO) +AC_SUBST(BUILD_MPI_INFO) +AC_SUBST(HAVE_MPI_DARRAY_SUBARRAY) +AC_SUBST(BUILD_MPI_ARRAY) +AC_SUBST(DEFINE_MPI_OFFSET) +AC_SUBST(DEFINE_HAVE_MPI_GREQUEST) +AC_SUBST(MPI_OFFSET_TYPE) +AC_SUBST(MPI_FINFO1) +AC_SUBST(MPI_FINFO2) +AC_SUBST(MPI_FINFO3) +AC_SUBST(MPI_FINFO4) +AC_SUBST(MPI_FARRAY1) +AC_SUBST(MPI_FARRAY2) +AC_SUBST(MPI_FARRAY3) +AC_SUBST(MPI_FARRAY4) +AC_SUBST(MPI_FARRAY5) +AC_SUBST(MPI_FARRAY6) +AC_SUBST(MPI_FARRAY7) +AC_SUBST(MPI_OFFSET_KIND1) +AC_SUBST(MPI_OFFSET_KIND2) +AC_SUBST(TEST_CC) +AC_SUBST(TEST_F77) +AC_SUBST(ROMIO_INCLUDE) +AC_SUBST(ROMIO_LFLAGS) +AC_SUBST(ROMIO_TCFLAGS) +AC_SUBST(ROMIO_TCPPFLAGS) +AC_SUBST(ROMIO_TFFLAGS) +AC_SUBST(MPIRUN) +AC_SUBST(FORTRAN_TEST) +dnl +dnl Support shared libraries +if test -z "$ENABLE_SHLIB" ; then + ENABLE_SHLIB=none +fi +AC_SUBST(ENABLE_SHLIB) +AC_SUBST(CC_SHL) +AC_SUBST(LIBTOOL) +# Remove the .a from the library file name (so that we can use .so or +# other appropriate suffix) +SHLIBNAME=`echo $LIBNAME | sed 's/\.a$//'` +AC_SUBST(SHLIBNAME) +dnl +if test ! -d adio ; then mkdir adio ; fi +if test ! -d adio/include ; then mkdir adio/include ; fi +if test ! -d mpi2-other ; then mkdir mpi2-other ; fi +if test ! -d mpi-io ; then mkdir mpi-io ; fi +if test ! -d mpi-io/glue ; then mkdir mpi-io/glue ; fi + +# Create makefiles for all of the adio devices. Only the ones that +# are active will be called by the top level ROMIO make +AC_OUTPUT_COMMANDS([chmod 755 util/romioinstall test/runtests]) +AC_CONFIG_FILES([ + Makefile + localdefs + mpi2-other/info/Makefile + mpi2-other/array/Makefile + test/Makefile + test/misc.c + test/large_file.c + test/runtests + test-internal/Makefile + util/romioinstall + include/mpio.h + include/mpiof.h + mpi2-other/info/fortran/Makefile + mpi2-other/array/fortran/Makefile + test/fmisc.f + test/fcoll_test.f + test/pfcoll_test.f + test/fperf.f +]) +AC_OUTPUT + +dnl PAC_SUBDIR_CACHE_CLEANUP +exit 0 diff --git a/ompi/mca/io/romio314/romio/doc/README b/ompi/mca/io/romio314/romio/doc/README new file mode 100644 index 0000000000..b61e73ee20 --- /dev/null +++ b/ompi/mca/io/romio314/romio/doc/README @@ -0,0 +1,35 @@ +The ROMIO Users Guide is in the file users-guide.ps.gz. + +The book ``Using MPI-2: Advanced Features of the Message-Passing +Interface,'' by William Gropp, Ewing Lusk, and Rajeev Thakur, +MIT Press, 1999, provides a tutorial introduction to all aspects of +MPI-2, including I/O. It has lots of example programs. + +The following papers related to ROMIO are available online: + +* Rajeev Thakur, William Gropp, and Ewing Lusk, ``Optimizing +Noncontiguous Accesses in MPI-IO,'' Parallel Computing, (28)1:83--105, +January 2002. +http://www.mcs.anl.gov/~thakur/papers/mpi-io-noncontig.ps + +* R. Thakur, W. Gropp, and E. Lusk, ``On Implementing MPI-IO Portably +and with High Performance,'' in Proc. of the Sixth Workshop on I/O in +Parallel and Distributed Systems, May 1999. +http://www.mcs.anl.gov/~thakur/papers/mpio-impl.ps + +* R. Thakur, W. Gropp, and E. Lusk, ``Data Sieving and Collective I/O +in ROMIO,'' in Proc. of the 7th Symposium on the Frontiers of +Massively Parallel Computation, February 1999, pp. 182--189. +http://www.mcs.anl.gov/~thakur/papers/romio-coll.ps + +* R. Thakur, W. Gropp, and E. Lusk, ``A Case for Using MPI's Derived +Datatypes to Improve I/O Performance,'' in Proc. of SC98: High +Performance Networking and Computing, November 1998. +http://www.mcs.anl.gov/~thakur/dtype + +* R. Thakur, W. Gropp, and E. Lusk, ``An Abstract-Device Interface for +Implementing Portable Parallel-I/O Interfaces,'' in Proc. of the 6th +Symposium on the Frontiers of Massively Parallel Computation, +October 1996, pp. 180-187. +http://www.mcs.anl.gov/~thakur/papers/adio.ps + diff --git a/ompi/mca/io/romio314/romio/doc/makepubpage.sh b/ompi/mca/io/romio314/romio/doc/makepubpage.sh new file mode 100755 index 0000000000..390519e580 --- /dev/null +++ b/ompi/mca/io/romio314/romio/doc/makepubpage.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# if you have bibtext2html installed (http://www.lri.fr/~filliatr/bibtex2html/ +# but I know there are other packages by that name), then you can re-generate +# the "ROMIO publication page" +# (http://www.mcs.anl.gov/research/projects/romio/pubs.html) + +# If you update the command below, please be sure to retain the link to the +# older papers + +WEB_HOST=login3.mcs.anl.gov +WEB_DIR=/mcs/web/research/projects/romio + +bibtex2html -t "Papers using ROMIO" \ + --header "Please help us keep this list up to date. Contact mpich-discuss@mcs.anl.gov for any corrections or additions.

Last updated at $(date).

Recent publications

" \ + --footer "

Other publications

+

    +
  • Northwestern University CUCIS group +
  • Weikuan Yu +
  • Phillip Dickens +
  • Older ROMIO papers" \ + -r -d -both pubs.bib + +if [ $? -eq 0 ] ; then + scp pubs* ${WEB_HOST}:${WEB_DIR} +else + echo "error running bibtex2html. website not updated" +fi diff --git a/ompi/mca/io/romio314/romio/doc/pubs.bib b/ompi/mca/io/romio314/romio/doc/pubs.bib new file mode 100644 index 0000000000..5799bc305c --- /dev/null +++ b/ompi/mca/io/romio314/romio/doc/pubs.bib @@ -0,0 +1,465 @@ +@InProceedings{gropp:selfconsist-io, + author={William Gropp and Dries Kimpe and Robert B. Ross and Rajeev Thakur and Jesper Larsson Tr\"aff}, + title={Self-Consistent {MPI-IO} Performance Requirements and Expectations}, + booktitle={Proc. of the 15th European PVM/MPI Users' Group Meeting (Euro + PVM/MPI 2008)}, + month={September}, + year={2008} +} + +@InProceedings{kimpe:log-based, + author={D. Kimpe and R. Ross and S. Vandewalle and S. Poedts}, + title={Transparent Log-Based Data Storage in {MPI-IO} Applications}, + booktitle={Proc. of the 14th European PVM/MPI Users' Group Meeting (Euro PVM/MPI 2007)}, + month={September}, + year={2007} +} + +@InProceedings{latham:gen-req, + author={Robert Latham and William Gropp and Robert B. Ross and Rajeev Thakur}, + title={Extending the {MPI-2} Generalized Request Interface}, + booktitle={Proc. of the 14th European PVM/MPI Users' Group Meeting (Euro PVM/MPI 2007)}, + month={September}, + year={2007}, + pages={223--232} +} + +@InProceedings{lee:mpiio-l, + author={Jonghyun Lee and Robert B. Ross and Scott Atchley and Micah Beck and + and Rajeev Thakur}, + title={{MPI-IO/L}: Efficient Remote {I/O} for {MPI-IO} via Logistical Networking}, + booktitle={Proceedings of the 20th IEEE International Parallel and Distributed + Processing Symposium (IPDPS 2006)}, + address={Rhodes Island, Greece}, + month={April}, + year={2006} +} + +@InProceedings{ross:atomic, + author = {Robert Ross and Robert Latham and William Gropp and Rajeev Thakur + and Brian Toonen}, + title = {Implementing {MPI-IO} Atomic Mode Without File System Support}, + booktitle = {Proceedings of CCGrid 2005}, + month = {May}, + year = {2005}, +} + +@InProceedings{latham:sharedfp, + author = {Robert Latham and Robert Ross and Rajeev Thakur}, + title = {Implementing {MPI-IO} Shared File Pointers Without File + System Support}, + booktitle = {Proceedings of EuroPVM/MPI 2005}, + month={September}, + year = {2005}, +} + +@article{latham:rma-ops, + author = {Latham, Robert and Ross, Robert and Thakur, Rajeev}, + title = {{Implementing MPI-IO Atomic Mode and Shared File Pointers Using MPI + One-Sided Communication}}, + journal = {International Journal of High Performance Computing Applications}, + volume = {21}, + number = {2}, + pages = {132-143}, + doi = {10.1177/1094342007077859}, + year = {2007}, + abstract = {The ROMIO implementation of the MPI-IO standard provides a + portable infrastructure for use on top of a variety of underlying storage + targets. These targets vary widely in their capabilities, and in some cases + additional effort is needed within ROMIO to support all MPI-IO semantics. Two + aspects of the interface that can be problematic to implement are MPI-IO + atomic mode and the shared file pointer access routines. Atomic mode requires + enforcing strict consistency semantics, and shared file pointer routines + require communication and coordination in order to atomically update a shared + resource. For some file systems, native locks may be used to implement these + features, but not all file systems have lock support. In this work, we + describe algorithms for implementing efficient mutex locks using MPI-1 and + the one-sided capabilities from MPI-2. We then show how these algorithms may + be used to implement both MPI-IO atomic mode and shared file pointer + methods for ROMIO without requiring any features from the underlying file + system. We show that these algorithms can outperform traditional file system + lock approaches. Because of the portable nature of these algorithms, they are + likely useful in a variety of situations where distributed locking or + coordination is needed in the MPI-2 environment. }, + URL = {http://hpc.sagepub.com/cgi/content/abstract/21/2/132}, + pdf = {papers/latham_rmaops.pdf}, + eprint = {http://hpc.sagepub.com/cgi/reprint/21/2/132.pdf} +} + +@Article{latham:mpi-io-scalability, + author = {Rob Latham and Rob Ross and Rajeev Thakur}, + title = {The impact of file systems on {MPI-IO} scalability}, + journal = {Lecture Notes in Computer Science}, + booktitle = {11th European Parallel Virtual Machine and Message Passing + Interface Users Group Meeting; September 19-22, 2004; Budapest, HUNGARY}, + editor = {Kranzlmuller, D; Kacsuk, P; Dongarra, J}, + year = {2004}, + month = {September}, + volume = {3241}, + pages = {87--96}, + institution = {Argonne Natl Lab, 9700 S Cass Ave, Argonne, IL 60439 USA; + Argonne Natl Lab, Argonne, IL 60439 USA}, + publisher = {Springer-Verlag Heidelberg}, + copyright = {(c)2004 Institute for Scientific Information, Inc.}, + URL = {http://www.springerlink.com/link.asp?id=m31px2lt90296b62}, + pdf = {papers/latham:scalable_ops.pdf}, + keywords = {scalability analysis, MPI-IO, pario-bib}, + abstract = {As the number of nodes in cluster systems continues to grow, + leveraging scalable algorithms in all aspects of such systems becomes key to + maintaining performance. While scalable algorithms have been applied + successfully in some areas of parallel I/O, many operations are still + performed in an uncoordinated manner. In this work we consider, in three file + system scenarios, the possibilities for applying scalable algorithms to the + many operations that make up the MPI-IO interface. From this evaluation we + extract a set of file system characteristics that aid in developing scalable + MPI-IO implementations.} +} + + + +@InProceedings{thakur:byte-range, + author = {Rajeev Thakur and Robert Ross and Robert Latham}, + title = {Implementing Byte-Range Locks Using {MPI} One-Sided Communication}, + booktitle = {Proceedings of the 12th European PVM/MPI Users' Group Meeting (Euro PVM/MPI 2005), Recent Advances in Parallel Virtual Machine and Message Passing Interface, Lecture Notes in Computer Science, LNCS 3666, Springer}, + month = {September}, + year = {2005}, + pages = {119-128}, +} + +@InProceedings{gropp:io-redundancy, + author={William Gropp and Robert B. Ross and Neill Miller}, + title={Providing Efficient {I/O} Redundancy in {MPI} Environments}, + booktitle={Proceedings of EuroPVM/MPI 2004}, + month={September}, + year={2004} +} + +@InProceedings{lee:rfs, + author = {Jonghyun Lee and Xiaosong Ma and Robert B. Ross and Rajeev Thakur + and Marianne Winslett}, + title={{RFS}: Implementing Efficient and Flexible Remote File Access for + {MPI-IO}}, + booktitle={Proceedings of Cluster 2004}, + month={September}, + year={2004} +} + +@InProceedings{yu:bgl-io, + author = {Hao Yu and R. K. Sahoo and C. Howson and George. Almasi and + J. G. Castanos and M. Gupta and Jose. E. Moreira and J. J. Parker and + T. E. Engelsiepen and Robert Ross and Rajeev Thakur and Robert Latham + and W. D. Gropp}, + title = {High Performance File {I/O} for the {BlueGene/L} Supercomputer}, + booktitle = {Proceedings of the 12th International Symposium on High-Performance Computer Architecture (HPCA-12)}, + month = {February}, + year = {2006}, + url = {http://www.mcs.anl.gov/~thakur/papers/bgl-io.pdf}, +} + +@Article{Hastings:pio-shmem, + author = {Andrew B. Hastings and Alok Choudhary}, + title = {Exploiting Shared Memory to Improve Parallel {I/O} Performance}, + journal = {Lecture Notes in Computer Science}, + booktitle = {13th European PVM/MPI User's Group Meeting; September 17-20, 2006; Bonn, Germany}, + editor = {Mohr, B; Worringen, J; Dongarra, J}, + year = {2006}, + month = {September}, + volume = {4192}, + pages = {212-221}, + publisher = {Springer-Verlag Heidelberg}, +} + +@Article{seidel:memfs, + author = {Jan Seidel and Rudolf Berrendorf and Marcel Birkner and Marc-Andre Hermanns}, + title = {High-Bandwidth Remote Parallel {I/O} with the Distributed Memory Filesystem {MEMFS}}, + journal = {Lecture Notes in Computer Science}, + booktitle = {13th European PVM/MPI User's Group Meeting; September 17-20, 2006; Bonn, Germany}, + editor = {Mohr, B; Worringen, J; Dongarra, J}, + year = {2006}, + month = {September}, + volume = {4192}, + pages = {222-229}, + publisher = {Springer-Verlag Heidelberg}, +} + +@InProceedings{calderon:ft-mpiio, + author={A. Calderon and F. Garcia-Carballeira and Florin Isaila and Rainer Keller and Alexander Schulz}, + title={Faul Tolerant File Models for {MPI-IO} Parallel File Systems}, + booktitle={Proc. of the 14th European PVM/MPI Users' Group Meeting (Euro PVM/MPI 2007)}, + month={September}, + year={2007}, + pages={153-160} +} +@InProceedings{Blas:romio-gpfs, + author={Francisco Javier Garc{\'i}a Blas and Florin Isaila and Jes{\'u}s Carretero + and Thomas Grossmann}, + title={Implementation and Evaluation of an {MPI-IO} Interface for + {GPFS} in {ROMIO}}, + booktitle={Proc. of the 15th European PVM/MPI Users' Group Meeting (Euro + PVM/MPI 2008)}, + month={September}, + year={2008} +} + +@InProceedings{dickens:y-lib, + author = {Dickens, Phillip M. and Logan, Jeremy}, + title = {Y-lib: a user level library to increase the performance of {MPI-IO} in a lustre file system environment}, + booktitle = {HPDC '09: Proceedings of the 18th ACM international symposium on High performance distributed computing}, + year = {2009}, + isbn = {978-1-60558-587-1}, + pages = {31--38}, + location = {Garching, Germany}, + doi = {http://doi.acm.org/10.1145/1551609.1551617}, + publisher = {ACM}, + address = {New York, NY, USA}, + } + + +% these ROMIO-related papers won't be published until EuroPVM/MPI 2009 + +@InProceedings{buettner:nonblocking-io, + author = {David Buettner and Julian Kunkel and Thomas Ludwig}, + title = {Using Non-Blocking {I/O} Operations in High Performance Computing to Reduce Execution Times}, + booktitle = {To be Published in Proc. of the 16th European PVM/MPI User's Group Meeting (Euro PVM/MPI 2009)}, + month={September}, + year={2009} + } + +@InProceedings{sehrish:conflicts, + author = {Saba Sehrish and Jun Wang and Rajeev Thakur}, + title = {Conflict Detection Algorithm to Minimize Locking for {MPI-IO} Atomicity}, + booktitle = {To be Published in Proc. of the 16th European PVM/MPI User's Group Meeting (Euro PVM/MPI 2009)}, + month={September}, + year={2009} +} + +@InProceedings{blas:bg-writeback, + author = {Javier Garc{\'i}a Blas and Florin Isaila and Jes{\'u}s Carretero and Robert Latham and Robert Ross}, + title = {Multiple-level {MPI} file write-back and prefetching for {Blue Gene} systems}, + booktitle = {To be Published in Proc. of the 16th European PVM/MPI User's Group Meeting (Euro PVM/MPI 2009)}, + month={September}, + year={2009} +} + +@InProceedings{isaila:ahpios, + author = {Florin Isaila and Javier Garc{\'i}a Blas and Jes{\'u}s Carretero and Wei-keng Liao and Alok Choudhary}, + title = {{AHPIOS}: An {MPI-based} ad-hoc parallel {I/O} system}, + booktitle = {14th Intl Conference on Parallel and Distributed Systems. Melbourne, Victoria, Austraila}, + year={2008} +} + +@InProceedings{blas:viewio, + author = {Javier Garc{\'i}a Blas and Florin Isaila and David E. Singh and Jes{\'u}s Carretero}, + title ={View-based collective {I/O} for {MPI-IO}}, + booktitle={8th IEEE International Symposium on Cluster Computing and the Grid}, + year={2008} +} + +@InProceedings{yu:lustre-joining, + author = {Weikuan Yu and Jeffrey Vetter and R. Shane Canon and Song Jiang}, + title = {Exploiting {Lustre} File Joining for Effective Collective {IO}}, + booktitle = {Seventh IEEE International Symposium on Cluster Computing and the Grid (CCGrid 2007)}, + month = {May}, + year = {2007}, +} + +@InProceedings{yu:opal, + author = {Weikuan Yu and Jeffrey Vetter and Shane Canon}, + title = {{OPAL}: An Open-Source {MPI-IO} Library over {Cray XT}}, + booktitle = {International Workshop on Storage Network Architecture and Parallel I/O (SNAPI'07)}, + month={September}, + year = {2007} +} + +@InProceedings{dickens:lustre-mpi, + title = {Towards a High Performance Implementation of {MPI-IO} on the {Lustre} File System}, + author = { Phillip M. Dickens and Jeremy Logan}, + booktitle = {Proceedings of GADA'08: Grid computing, high-performAnce and Distributed Applications. Monterrey, Mexico}, + month = {November}, + year = {2008} +} + +@article{dickens:lustre-mpi-journal, + author = {Phillip Dickens and J. Logan}, + title = {A High Performance Implementation of {MPI-IO} for a {Lustre} File System Environment}, + journal = {To appear: Concurrency and Computation: Practice and Experience}, + year = {2009} +} + +@InProceedings{logan:objectio, + author = {J. Logan and Phillip Dickens}, + title = {Using Object Based Files for High Performance Parallel {I/O}}, + booktitle = {Proceedings of the IEEE 4th International Workshop on Intelligent Data acquisition and Advanced Computing Systems: Technology and Applications. Dortmund, Germany}, + month = {September}, + year = {2007} + } + +@InProceedings{logan:dynamic-object-io, + author = {J. Logan and Phillip Dickens}, + title = {Dynamic Object Based {I/O}. (Invited Paper)}, + booktitle = {To appear: IEEE 5th International Workshop on Intelligent Data + acquisition and Advanced Computing Systems: Technology and Applications}, + year = {2009}, + month = {August} +} + + +@InProceedings{liao:partitioning, + author = {Wei-keng Liao and Alok Choudhary}, + title = {Dynamically Adapting File Domain Partitioning Methods for Collective {I/O} Based on Underlying Parallel File System Locking Protocols}, + booktitle = {Proceedings of International Conference for High Performance Computing, Networking, Storage and Analysis (SC08), Austin, Texas}, + month={November}, + year = {2008} +} + +@InProceedings{nisar:io-delegation, + author = {Arifa Nisar and Wei-keng Liao and Alok Choudhary}, + title = {Scaling Parallel {I/O} Performance through {I/O} Delegate and Caching System}, + booktitle = {Proceedings of International Conference for High Performance Computing, Networking, Storage and Analysis (SC08), Austin, Texas}, + month={November}, + year ={2008} +} + +@InProceedings{liao:caching-large-scale, + author = { Wei-keng Liao and Avery Ching and Kenin Coloma and Arifa Nisar and Alok Choudhary and Jackie Chen and Ramanan Sankaran and Scott Klasky}, + title = {Using {MPI} File Caching to Improve Parallel Write Performance for Large-Scale Scientiï¬c Applications}, + booktitle = {Proceedings of the International Conference for High Performance Computing, Networking, Storage and Analysis (SC 2007), Reno, Nevada}, + month = {November}, + year = {2007} +} + +@article{liao:cooperative_caching_mpi_journal, + author = {Wei-keng Liao and Kenin Coloma and Alok Choudhary and Lee Ward}, + title = {Cooperative Client-side File Caching for {MPI} Applications}, + journal = {International Journal of High Performance Computing Applications}, + volume = {21}, + number = {2}, + pages = {144-154}, + month = {May}, + year = {2007} +} + +@InProceedings{liao:client_cache_eval, + author = {Wei-keng Liao and Avery Ching and Kenin Coloma and Alok Choudhary and Lee Ward}, + title = {An Implementation and Evaluation of Client-side File Caching for {MPI-IO}}, + booktitle = {Proceedings of the 21st International Parallel and Distributed +Processing Symposium (IPDPS), Long Beach, California}, + month = {March}, + year = {2007} +} + +@article{liao:overlapping_io, + author = {Wei-keng Liao and Kenin Coloma and Alok Choudhary and Lee Ward and Eric Russell and Neil Pundit}, + title = {Scalable Design and Implementations for MPI Parallel Overlapping {I/O}}, + journal = {{IEEE} Transactions on Parallel and Distributed System}, + volume = {17}, + number = {11}, + pages = {1264-1276}, + month = {November}, + year = {2006} +} + + +@InProceedings{coloma:new_collective_io, + author = {Kenin Coloma and Avery Ching and Alok Choudhary and Wei-keng Liao and Robert Ross and Rajeev Thakur and Lee Ward}, + title = {A New Flexible {MPI} Collective {I/O} Implementation}, + booktitle = {Proceedings of the IEEE Conference on Cluster Computing (Cluster 2006), Barcelona, Spain}, + month = {September}, + year = {2006} +} + +@article{memik:multicollective_io, + author = {Gokhan Memik and Mahmut T. Kandemir and Wei-Keng Liao and Alok Choudhary}, + title = {Multicollective {I/O}: A Technique for Exploiting Inter-ï¬le Access Patterns}, + journal = {{ACM} Transactions on Storage (TOS)}, + volume = {2}, + number = {3}, + pages = {349-360}, + month = {August}, + year = {2006} +} + +@Inbook{liao:atomicity_overlap, + author = {Wei-keng Liao and Alok Choudhary and Kenin Coloma and Lee Ward and Eric Russell and Neil Pundit}, + title = {{MPI} Atomicity and Concurrent Overlapping {I/O}}, + booktitle = {High Performance Computing: Paradigm and Infrastructure}, + pages = {203-218}, + chapter = {10}, + month = {November}, + year = {2005}, + publisher = {John Wiley & Sons Inc}, + note = {ISBN: 978-0-471-65471-1} +} + +@InProceedings{liao:cooperative_write-behind, + author = {Wei-keng Liao and Kenin Coloma and Alok Choudhary and Lee Ward}, + title = {{Cooperative Write-Behind Data Buffering for MPI I/O}}, + booktitle = {Proceedings of the 12th European Parallel Virtual Machine and Message Passing Interface Conference (EURO PVM/MPI), Sorrento (Naples), Italy}, + month = {September}, + year = {2005} + } + +@InProceedings{liao:app_aware_caching, + author = {Wei-keng Liao and Kenin Coloma and Alok Choudhary and Lee Ward and Eric Russell and Sonja Tideman}, + title = {{Collective Caching: Application-aware Client-side File Caching}}, + booktitle = {Proceedings of the 14th IEEE International Symposium on High Performance Distributed Computing (HPDC-14), Research Triangle Park, NC}, + month = {July}, + year = {2005} + } + +@InProceedings{coloma:dache, + author = {Kenin Coloma and Alok Choudhary and Wei-keng Liao and Lee Ward and Sonja Tideman}, + title = {{DAChe: Direct Access Cache System for Parallel I/O}}, + booktitle = {Proceedings of the International Supercomputer Conference, Heidelberg, Germany}, + month = {June}, + year = {2005} + } + +@InProceedings{coloma:scalable_caching, + author = {Kenin Coloma and Alok Choudhary and Wei-keng Liao and Lee Ward and Eric Russell and Neil Pundit}, + title = {{Scalable High-level Caching for Parallel I/O}}, + booktitle = {Proceedings of the International Parallel and Distributed Parallel Processing Symposium (IPDPS), New Mexico}, + month = {April}, + year = {2004} +} + +@InProceedings{Liao:scalable_atomicity, + author = {Wei-keng Liao and Alok Choudhary and Kenin Coloma and George K. Thiruvathukal and Lee Ward and Eric Russell and Neil Pundit}, + title = {{Scalable Implementations of MPI Atomicity for Concurrent Overlapping I/O}}, + booktitle = {Proceedings of the International Conference on Parallel Processing (ICPP), Kaohsiung, Taiwan}, + month = {October}, + year = {2003} + } + +@InProceedings{ching:noncontig, + author = {Avery Ching and Alok Choudhary and Kenin Coloma and Wei-keng Liao and Robert Ross and William Gropp}, + title = {{Noncontiguous I/O Accesses Through MPI-IO}}, + booktitle = {Proceedings of the International Symposium on Cluster Computing and the Grid (CCGrid), Tokyo, Japan}, + month = {May}, + year = {2003} +} + +@Article{chaarawi:collective_writes, + author = {Mohamad Chaarawi and Suneet Chandok and Edgar Gabriel}, + title = {{Performance Evaluation of Collective Write Algorithms in MPI I/O}}, + journal = {Lecture Notes in Computer Science}, + booktitle = {International Conference on Computer Science (ICCS) 2009}, + month = {May}, + year = {2009}, + volume = {5544}, + pages = {185-194}, + publisher = {Springer Berlin / Heidelberg}, + doi = {10.1007/978-3-642-01970-8_19} +} +@Article{kulkarni::shared_file_pointers, + author = {Ketan Kulkarni and Edgar Gabriel}, + title = {{Evaluating Algorithms for Shared File Pointer Operations in MPI I/O}}, + journal = {Lecture Notes in Computer Science}, + booktitle = {International Conference on Computer Science (ICCS) 2009}, + month = {May}, + year = {2009}, + volume = {5544}, + pages = {280-289}, + publisher = {Springer Berlin / Heidelberg}, + doi = {10.1007/978-3-642-01970-8_28} +} diff --git a/ompi/mca/io/romio314/romio/doc/romio.bib b/ompi/mca/io/romio314/romio/doc/romio.bib new file mode 100644 index 0000000000..bb94a2d2ea --- /dev/null +++ b/ompi/mca/io/romio314/romio/doc/romio.bib @@ -0,0 +1,92 @@ +@Book{grop99a, + author = {William Gropp and Ewing Lusk and Rajeev Thakur}, + title = {{Using MPI-2: Advanced Features of the Message-Passing Interface}}, + publisher = {MIT Press}, + year = 1999, + address = {Cambridge, MA} +} + +@Misc{mpi97a, + author = "{Message Passing Interface Forum}", + title = "{{MPI-2}: Extensions to the Message-Passing Interface}", + note = "{\tt http://www.mpi-forum.org/docs/docs.html}", + year = {July 1997} +} + +@InProceedings{thak96e, + author = {Rajeev Thakur and William Gropp and Ewing Lusk}, + title = {An Abstract-Device Interface for Implementing Portable + Parallel-{I/O} Interfaces}, + booktitle = {Proceedings of the 6th Symposium on the Frontiers of + Massively Parallel Computation}, + publisher = {IEEE Computer Society Press}, + pages = {180--187}, + month = {October}, + year = {1996} +} + +@InProceedings{thak99b, + author = {Rajeev Thakur and William Gropp and Ewing Lusk}, + title = {On Implementing {MPI-IO} Portably and with High Performance}, + booktitle = {Proceedings of the 6th Workshop on I/O in Parallel and + Distributed Systems}, + pages = {23--32}, + year = {1999}, + month = {May}, + publisher = {ACM Press} +} + +@InProceedings{bordawekar:primitives, + author = {Rajesh Bordawekar and Juan Miguel {del Rosario} and Alok + Choudhary}, + title = {Design and Evaluation of Primitives for Parallel {I/O}}, + booktitle = {Proceedings of Supercomputing '93}, + year = {1993}, + pages = {452--461}, + publisher = {IEEE Computer Society Press}, + address = {Portland, OR}, + URL = {ftp://erc.cat.syr.edu/ece/choudhary/PASSION/sc93.ps.Z}, + keywords = {parallel I/O, pario-bib}, + abstract = {In this paper, we show that the performance of parallel file + systems can vary greatly as a function of the selected data distributions, + and that some data distributions can not be supported. Also, we describe how + the parallel language extensions, though simplifying the programming, do not + address the performance problems found in parallel file systems. \par We have + devised an alternative scheme for conducting parallel I/O - the Two-Phase + Access Strategy - which guarantees higher and more consistent performance + over a wider spectrum of data distributions. We have designed and implemented + runtime primitives that make use of the two-phase access strategy to conduct + parallel I/O, and facilitate the programming of parallel I/O operations. We + describe these primitives in detail and provide performance results which + show that I/O access rates are improved by up to several orders of magnitude. + Further, we show that the variation in performance over various data + distributions is restricted to within a factor of 2 of the best access + rate.}, + comment = {Much of this is the same as delrosario:two-phase, except for + section~4 where they describe their actual run-time library of primitives, + with a little bit about how it works. It's not clear, for example, how their + meta-data structures are distributed across the machine. They also do not + describe their methods for the data redistribution.} +} + +@TechReport{choudhary:passion, + author = {Alok Choudhary and Rajesh Bordawekar and Michael Harry and Rakesh + Krishnaiyer and Ravi Ponnusamy and Tarvinder Singh and Rajeev Thakur}, + title = {{PASSION:} Parallel And Scalable Software for Input-Output}, + year = {1994}, + month = {September}, + number = {SCCS-636}, + institution = {ECE Dept., NPAC and CASE Center, Syracuse University}, + later = {thakur:jpassion}, + URL = {ftp://erc.cat.syr.edu/ece/choudhary/PASSION/passion_report.ps.Z}, + keywords = {parallel I/O, out-of-core, pario-bib}, + comment = {This TR overviews the PASSION project, and all its components: + two-phase access, out-of-core support for structured and unstructured + problems, data sieving, prefetching, caching, compiler and language support, + file system support, virtual parallel file system, and parallel pipes. They + reference many of their related papers in an extensive bibliography. See also + singh:adopt, jadav:ioschedule, thakur:passion, thakur:runtime, + bordawekar:efficient, thakur:out-of-core, delrosario:prospects, + delrosario:two-phase, bordawekar:primitives, bordawekar:delta-fs.} +} + diff --git a/ompi/mca/io/romio314/romio/doc/source-guide.tex b/ompi/mca/io/romio314/romio/doc/source-guide.tex new file mode 100644 index 0000000000..96fa7ca58d --- /dev/null +++ b/ompi/mca/io/romio314/romio/doc/source-guide.tex @@ -0,0 +1,494 @@ +% \documentstyle[11pt,psfig]{article} +\documentclass[11pt]{article} +\hoffset=-.7in +\voffset=-.6in +\textwidth=6.5in +\textheight=8.5in + +\begin{document} +\vspace*{-1in} +\thispagestyle{empty} +\begin{center} +ARGONNE NATIONAL LABORATORY \\ +9700 South Cass Avenue \\ +Argonne, IL 60439 +\end{center} +\vskip .5 in + +\begin{center} +\rule{1.75in}{.01in} \\ +\vspace{.1in} + +ANL/MCS-TM-XXX \\ + +\rule{1.75in}{.01in} \\ + +\vskip 1.3 in +{\Large\bf A Guide to the ROMIO MPI-IO Implementation } \\ +by \\ [2ex] +{\large\it Robert Ross, Robert Latham, and Rajeev Thakur} +\vspace{1in} + +Mathematics and Computer Science Division + +\bigskip + +Technical Memorandum No.\ XXX + + +% \vspace{1.4in} +% Revised May 2004 + +\end{center} + +\vfill + +{\small +\noindent +This work was supported by the Mathematical, Information, and +Computational Sciences Division subprogram of the Office of Advanced +Scientific Computing Research, U.S. Department of Energy, under +Contract W-31-109-Eng-38; and by the Scalable I/O Initiative, a +multiagency project funded by the Defense Advanced Research Projects +Agency (Contract DABT63-94-C-0049), the Department of Energy, the +National Aeronautics and Space Administration, and the National +Science Foundation.} + +\newpage + + +%% Line Spacing (e.g., \ls{1} for single, \ls{2} for double, even \ls{1.5}) +%% + +\newcommand{\ls}[1] + {\dimen0=\fontdimen6\the\font + \lineskip=#1\dimen0 + \advance\lineskip.5\fontdimen5\the\font + \advance\lineskip-\dimen0 + \lineskiplimit=.9\lineskip + \baselineskip=\lineskip + \advance\baselineskip\dimen0 + \normallineskip\lineskip + \normallineskiplimit\lineskiplimit + \normalbaselineskip\baselineskip + \ignorespaces + } +\renewcommand{\baselinestretch}{1} +\newcommand {\ix} {\hspace*{2em}} +\newcommand {\mc} {\multicolumn} + + +\tableofcontents +\thispagestyle{empty} +\newpage + +\pagenumbering{arabic} +\setcounter{page}{1} +\begin{center} +{\bf Users Guide for ROMIO: A High-Performance,\\[1ex] +Portable MPI-IO Implementation} \\ [2ex] +by \\ [2ex] +{\it Rajeev Thakur, Robert Ross, Ewing Lusk, and William Gropp} + +\end{center} +\addcontentsline{toc}{section}{Abstract} +\begin{abstract} +\noindent +ROMIO is a high-performance, portable implementation of MPI-IO (the +I/O chapter in the \mbox{MPI Standard}). +This document describes the internals of the ROMIO implementation. +\end{abstract} + +\section{Introduction} + +The ROMIO MPI-IO implementation, originally written by Rajeev Thakur, has been +in existence since XXX. + +... Discussion of the evolution of ROMIO ... + +Architecturally, ROMIO is broken up into three layers: a layer implementing +the MPI I/O routines in terms of an abstract device for I/O (ADIO), a layer of +common code implementing a subset of the ADIO interface, and a set of storage +system specific functions that complete the ADIO implementation in terms of +that storage type. These three layers work together to provide I/O support +for MPI applications. + +In this document we will discuss the details of the ROMIO implementation, +including the major components, how those components are implemented, and +where those components are located in the ROMIO source tree. + +\section{The Directory Structure} + +The ROMIO directory structure consists of two main branches, the MPI-IO branch +(mpi-io) and the ADIO branch (adio). The MPI-IO branch contains code that +implements the functions defined in the MPI specification for I/O, such as +MPI\_File\_open. These functions are then written in terms of other functions +that provide an abstract interface to I/O resources, the ADIO functions. +There is an additional glue subdirectory in the MPI-IO branch that defines +functions related to the MPI implementation as a whole, such as how to +allocate MPI\_File structures and how to report errors. + +Code for the ADIO functions is located under the ADIO branch. This code is +responsible for performing I/O operations on whatever underlying storage is +available. There are two categories of directories in this branch. The first +is the common directory. This directory contains two distinct types of +source: source that is used by all ADIO implementations and source that is +common across many ADIO implementations. This distinction will become more +apparent when we discuss file system implementations. + +The second category of directory in the ADIO branch is the file system +specific directory (e.g. ad\_ufs, ad\_pvfs2). These directories provide code +that is specific to a particular file system type and is only built if that +file system type is selected at configure time. + +\section{The Configure Process} + +... What can be specified, AIO stuff, where romioconf exists, how to add +another Makefile.in into the list. + +\section{File System Implementations} + +Each file system implementation exists in its own subdirectory under the adio +directory in the source tree. Each of these subdirectories must contain at +least two files, a Makefile.in (describing how to build the code in the +directory) and a C source file describing the mapping of ADIO operations to C +functions. + +The common practice is to name this file based on the name of the ADIO +implementation. In the ad\_ufs implementation this file is called ad\_ufs.c, +and contains the following: + +\begin{verbatim} +struct ADIOI_Fns_struct ADIO_UFS_operations = { + ADIOI_UFS_Open, /* Open */ + ADIOI_GEN_ReadContig, /* ReadContig */ + ADIOI_GEN_WriteContig, /* WriteContig */ + ADIOI_GEN_ReadStridedColl, /* ReadStridedColl */ + ADIOI_GEN_WriteStridedColl, /* WriteStridedColl */ + ADIOI_GEN_SeekIndividual, /* SeekIndividual */ + ADIOI_GEN_Fcntl, /* Fcntl */ + ADIOI_GEN_SetInfo, /* SetInfo */ + ADIOI_GEN_ReadStrided, /* ReadStrided */ + ADIOI_GEN_WriteStrided, /* WriteStrided */ + ADIOI_GEN_Close, /* Close */ + ADIOI_GEN_IreadContig, /* IreadContig */ + ADIOI_GEN_IwriteContig, /* IwriteContig */ + ADIOI_GEN_IODone, /* ReadDone */ + ADIOI_GEN_IODone, /* WriteDone */ + ADIOI_GEN_IOComplete, /* ReadComplete */ + ADIOI_GEN_IOComplete, /* WriteComplete */ + ADIOI_GEN_IreadStrided, /* IreadStrided */ + ADIOI_GEN_IwriteStrided, /* IwriteStrided */ + ADIOI_GEN_Flush, /* Flush */ + ADIOI_GEN_Resize, /* Resize */ + ADIOI_GEN_Delete, /* Delete */ +}; +\end{verbatim} + +The ADIOI\_Fns\_struct structure is defined in adio/include/adioi.h. This +structure holds pointers to appropriate functions for a given file system +type. "Generic" functions, defined in adio/common, are denoted by the +"ADIOI\_GEN" prefix, while file system specific functions use a file system +related prefix. In this example, the only file system specific function is +ADIOI\_UFS\_Open. All other operations use the generic versions. + +Typically a third file, a header with file system specific defines and +includes, is also provided and named based on the name of the ADIO +implementation (e.g. ad\_ufs.h). + +Because the UFS implementation provides its own open function, that code must be provided in the ad\_ufs subdirectory. That function is implemented in adio/ad\_ufs/ad\_ufs\_open.c. + +\section{Generic Functions} + +As we saw in the discussion above, generic ADIO function implementations are +used to minimize the amount of code in the ROMIO tree by sharing common +functionality between ADIO implementations. As the ROMIO implementation has +grown, a few categories of generic implementations have developed. At this +time, these are all lumped into the adio/common subdirectory together, which +can be confusing. + +The easiest category of generic functions to understand is the ones that +implement functionality in terms of some other ADIO function. +ADIOI\_GEN\_ReadStridedColl is a good example of this type of function and is +implemented in adio/common/ad\_read\_coll.c. This function implements +collective read operations (e.g. MPI\_File\_read\_at\_all). We will discuss how +it works later in this document, but for the time being it is sufficient to +note that it is written in terms of ADIO ReadStrided or ReadContig calls. + +A second category of generic functions are ones that implement functionality +in terms of POSIX I/O calls. ADIOI\_GEN\_ReadContig (adio/common/ad\_read.c) is +a good example of this type of function. These "generic" functions are the +result of a large number of ADIO implementations that are largely POSIX I/O +based, such as the UFS, XFS, and PANFS implementations. We have discussed +moving these functions into a separate common/posix subdirectory and renaming +them with ADIOI\_POSIX prefixes, but this has not been done as of the writing +of this document. + +The next category of generic functions holds functions that do not actually +require I/O at all. ADIOI\_GEN\_SeekIndividual (adio/common/ad\_seek.c) is a +good example of this. Since we don't need to actually perform I/O at seek +time, we can just update local variables at each process. In fact, one could +argue that we no longer need the ADIO SeekIndividual function at all - all the +ADIO implementations simply use this generic version (with the exception of +TESTFS, which prints the value as well). + +The next category of generic functions are the "FAKE" functions (e.g. +ADIOI\_FAKE\_IODone implemented in adio/common/ad\_done\_fake.c). These functions +are all related to asynchronous I/O (AIO) operations. These implement the AIO +operations in terms of blocking operations - in other words, they follow the +standard but do not allow for overlap of I/O and computation or communication. +These are used in cases where AIO support is otherwise unavailable or +unimplemented. + +The final category of generic functions are the "naïve" functions (e.g. +ADIOI\_GEN\_WriteStrided\_naive in adio/common/ad\_write\_str\_naive.c). These +functions avoid the use of certain optimizations, such as data sieving. + +Other Things in adio/common + +... what else is in there? + +\subsection{Calling ADIO Functions} + +Throughout the code you will see calls to functions such as ADIO\_ReadContig. +There is no such function - this is actually a macro defined in +adio/include/adioi.h that calls the particular function out of the correct +ADIOI\_Fns\_struct for the file being accessed. This is done for convenience. + +Exceptions!!! ADIO\_Open, ADIO\_Close... + +\section{ROMIO Implementation Details} + +The ROMIO Implementation relies on some basic concepts in order to operate and +to optimize I/O access. In this section we will discuss these concepts and +how they are implemented within ROMIO. Before we do that though, we will +discuss the core data structure of ROMIO, the ADIO\_File structure. + +\subsection{ADIO\_File} + +... discussion ... + +\subsection{I/O Aggregation and Aggregators} + +When performing collective I/O operations, it is often to our advantage to +combine operations or eliminate redundant operations altogether. We call this +combining process "aggregation", and processes that perform these combined +operations aggregators. + +Aggregators are defined at the time the file is opened. A collection of MPI +hints can be used to tune what processes become aggregators for a given file +(see ROMIO User's Guide). The aggregators will then interact with the file +system during collective operations. + +Note that it is possible to implement a system where ALL I/O operations pass +exclusively through aggregators, including independent I/O operations from +non-aggregators. However, this would require a guarantee of progress from the +aggregators that for portability would mean adding a thread to manage I/O. We +have chosen not to pursue this path at this time, so independent operations +continue to be serviced by the process making the call. + +... how implemented ... + +Rank 0 in the communicator opening a file \emph{always} processes the +cb\_config\_list hint using ADIOI\_cb\_config\_list\_parse. A previous call to +ADIOI\_cb\_gather\_name\_array had collected the processor names from all hosts +into an array that is cached on the communicator (so we don't have to gather +it more than once). This creates an ordered array of ranks (relative to the +communicator used to open the file) that will be aggregators. This array is +distributed to all processes using ADIOI\_cb\_bcast\_rank\_map. Aggregators are +referenced by their rank in the communicator used to open the file. These +ranks are stored in fd->hints->ranklist[]. + +Note that this could be a big list for very large runs. If we were to +restrict aggregators to a rank order subset, we could use a bitfield instead. + +If the user specified hints and met conditions for deferred open, then a +separate communicator is also set up (fd->agg\_comm) that contains all the +aggregators, in order of their original ranks (not their order in the rank +list). Otherwise this communicator is set to MPI\_COMM\_NULL, and in any case +it is set to this for non-aggregators. This communicator is currently only +used at ADIO\_Close (adio/common/ad\_close.c), but could be useful in two-phase +I/O as well (discussed later). + + +\subsection{Deferred Open} + +We do not always want all processes to attempt to actually open a file when +MPI\_File\_open is called. We might want to avoid this open because in fact +some processes (non-aggregators) cannot access the file at all and would get +an error, or we might want to avoid this open to avoid a storm of system calls +hitting the file system all at once. In either case, ROMIO implements a +"deferred open" mode that allows some processes to avoid opening the file +until such time as they perform an independent I/O operation on the file (see +ROMIO User's Guide). + +Deferred open has a broad impact on the ROMIO implementation, because with its +addition there are now many places where we must first check to see if we have +called the file system specific ADIO Open call before performing I/O. This +impact is limited to the MPI-IO layer by semantically guaranteeing the FS ADIO +Open call has been made by the process prior to calling a read or write +function. + +... how implemented ... + +\subsection{Two-Phase I/O} + +Two-Phase I/O is a technique for increasing the efficiency of I/O operations +by reordering data between processes, either before writes, or after reads. + +ROMIO implements two-phase I/O as part of the generic implementations of +ADIO\_WriteStridedColl and ADIO\_ReadStridedColl. These implementations in turn +rely heavily on the aggregation code to determine what processes will actually +perform I/O on behalf of the application as a whole. + + + +\subsection{Data Sieving} + +Data sieving is a single-process technique for reducing the number of I/O +operations used to service a MPI read or write operation by accessing a +contiguous region of the file that contains more than one desired region at +once. Because often I/O operations require data movement across the network, +this is usually a more efficient way to access data. + +Data sieving is implemented in the common strided I/O routines +(adio/common/ad\_write\_str.c and adio/common/ad\_read\_str.c). These functions +use the contig read and write routines to perform actual I/O. In the case of +a write operation, a read/modify/write sequence is used. In that case, as +well as in the atomic mode case, locking is required on the region. Some of +the ADIO implementations do not currently support locking, and in those cases +it would be erroneous to use the generic strided I/O routines. + +\subsection{Shared File Pointers} + +Because no file systems supported by ROMIO currently support a shared file +pointer mode, ROMIO must implement shared file pointers under the covers on +its own. + +Currently ROMIO implements shared file pointers by storing the file pointer +value in a separate file... + +Note that the ROMIO team has devised a portable method for implementing shared +file pointers using only MPI functions. However, this method has +not yet been implemented in ROMIO. + +file name is selected at end of mpi-io/open.c. + +\subsection{Error Handling} + +\subsection{MPI and MPIO Requests} + +\section*{Appendix A: ADIO Functions and Semantics} + +ADIOI\_Open(ADIO\_File fd, int *error\_code) + +Open is used in a strange way in ROMIO, as described previously. + +The Open function is used to perform whatever operations are necessary prior +to actually accessing a file using read or write. The file name for the file +is stored in fd->filename prior to Open being called. + +Note that when deferred open is in effect, all processes may not immediately +call Open at MPI\_File\_open time, but instead call open if they perform +independent I/O. This can result in somewhat unusual error returns to +processes (e.g. learning that a file is not accessible at write time). + +ADIOI\_ReadContig(ADIO\_File fd, void *buf, int count, MPI\_Datatype datatype, +int file\_ptr\_type, ADIO\_Offset offset, ADIO\_Status *status, int *error\_code) + +ReadContig is used to read a contiguous region from a file into a contiguous +buffer. The datatype (which refers to the buffer) can be assumed to be +contiguous. The offset is in bytes and is an absolute offset if +ADIO\_EXPLICIT\_OFFSET was passed as the file\_ptr\_type or relative to the +current individual file pointer if ADIO\_INDIVIDUAL was passed as +file\_ptr\_type. Open has been called by this process prior to the call to +ReadContig. There is no guarantee that any other processes will call this +function at the same time. + +ADIOI\_WriteContig(ADIO\_File fd, void *buf, int count, MPI\_Datatype datatype, +int file\_ptr\_type, ADIO\_Offset offset, ADIO\_Status *status, int *error\_code) + +WriteContig is used to write a contiguous region to a file from a contiguous +buffer. The datatype (which refers to the buffer) can be assumed to be +contiguous. The offset is in bytes and is an absolute offset if +ADIO\_EXPLICIT\_OFFSET was passed as the file\_ptr\_type or relative to the +current individual file pointer if ADIO\_INDIVIDUAL was passed as +file\_ptr\_type. Open has been called by this process prior to the call to +WriteContig. There is no guarantee that any other processes will call this +function at the same time. + +ADIOI\_ReadStridedColl + +ADIOI\_WriteStridedColl + +ADIOI\_SeekIndividual + +ADIOI\_Fcntl + +ADIOI\_SetInfo + +ADIOI\_ReadStrided + +ADIOI\_WriteStrided + +ADIOI\_Close(ADIO\_File fd, int *error\_code) + +Close is responsible for releasing any resources associated with an open file. +It is called on all processes that called the corresponding ADIOI Open, which +might not be all the processes that opened the file (due to deferred open). +Thus it is not safe to perform collective communication among all processes in +the communicator during Close, although collective communication between +aggregators would be safe (if desired). + +For performance reasons ROMIO does not guarantee that all file data is written +to "storage" at MPI\_File\_close, instead only performing synchronization +operations at MPI\_File\_sync time. As a result, our Close implementations do +not typically call a sync. However, any locally cached data, if any, should +be passed on to the underlying storage system at this time. + +Note that ADIOI\_GEN\_Close is implemented in adio/common/adi\_close.c; +ad\_close.c implements ADIO\_Close, which is called by all processes that opened +the file. + +ADIOI\_IreadContig + +ADIOI\_IwriteContig + +ADIOI\_ReadDone + +ADIOI\_WriteDone + +ADIOI\_ReadComplete + +ADIOI\_WriteComplete + +ADIOI\_IreadStrided + +ADIOI\_IwriteStrided + +ADIOI\_Flush + +ADIOI\_Resize(ADIO\_File fd, ADIO\_Offset size, int *error\_code) + +Resize is called collectively by all processes that opened the file referenced +by fd. It is not required that the Resize implementation block until all +processes have completed resize operations, but each process should be able to +see the correct size with a corresponding MPI\_File\_get\_size operation (an +independent operation that results in an ADIO Fcntl to obtain the file size). + +ADIOI\_Delete(char *filename, int *error\_code) + +Delete is called independently, and because only a filename is passed, there +is no opportunity to coordinate deletion if an application were to choose to +have all processes call MPI\_File\_delete. That's not likely to be an issue +though. + +\section*{Appendix B: Status of ADIO Implementations} + +... who wrote what, status, etc. + +Appendix C: Adding a New ADIO Implementation + +References + +\end{document} diff --git a/ompi/mca/io/romio314/romio/doc/users-guide.pdf b/ompi/mca/io/romio314/romio/doc/users-guide.pdf new file mode 100644 index 0000000000..be9359f04d Binary files /dev/null and b/ompi/mca/io/romio314/romio/doc/users-guide.pdf differ diff --git a/ompi/mca/io/romio314/romio/doc/users-guide.tex b/ompi/mca/io/romio314/romio/doc/users-guide.tex new file mode 100644 index 0000000000..b33d483079 --- /dev/null +++ b/ompi/mca/io/romio314/romio/doc/users-guide.tex @@ -0,0 +1,1136 @@ +% \documentstyle[11pt,psfig]{article} +\documentstyle[11pt]{article} +\hoffset=-.7in +\voffset=-.6in +\textwidth=6.5in +\textheight=8.5in +\begin{document} +\vspace*{-1in} +\thispagestyle{empty} +\begin{center} +ARGONNE NATIONAL LABORATORY \\ +9700 South Cass Avenue \\ +Argonne, IL 60439 +\end{center} +\vskip .5 in +\begin{center} +\rule{1.75in}{.01in} \\ +\vspace{.1in} + +ANL/MCS-TM-234 \\ + +\rule{1.75in}{.01in} \\ + +\vskip 1.3in +{\Large\bf Users Guide for ROMIO: A High-Performance, \\ [1ex] +Portable MPI-IO Implementation} \\ [4ex] +by \\ [2ex] +{\large\it Rajeev Thakur, Robert Ross, Ewing Lusk, William Gropp, Robert Latham} +\vspace{1in} + +Mathematics and Computer Science Division + +\bigskip + +Technical Memorandum No.\ 234 + + +\vspace{1.4in} +Revised May 2004, November 2007, April 2010 + +\end{center} + +\vfill + +{\small +\noindent +This work was supported by the Mathematical, Information, and +Computational Sciences Division subprogram of the Office of Advanced +Scientific Computing Research, U.S. Department of Energy, under +Contract W-31-109-Eng-38; and by the Scalable I/O Initiative, a +multiagency project funded by the Defense Advanced Research Projects +Agency (Contract DABT63-94-C-0049), the Department of Energy, the +National Aeronautics and Space Administration, and the National +Science Foundation.} + +\newpage + + +%% Line Spacing (e.g., \ls{1} for single, \ls{2} for double, even \ls{1.5}) +%% + +\newcommand{\ls}[1] + {\dimen0=\fontdimen6\the\font + \lineskip=#1\dimen0 + \advance\lineskip.5\fontdimen5\the\font + \advance\lineskip-\dimen0 + \lineskiplimit=.9\lineskip + \baselineskip=\lineskip + \advance\baselineskip\dimen0 + \normallineskip\lineskip + \normallineskiplimit\lineskiplimit + \normalbaselineskip\baselineskip + \ignorespaces + } +\renewcommand{\baselinestretch}{1} +\newcommand {\ix} {\hspace*{2em}} +\newcommand {\mc} {\multicolumn} + + +\tableofcontents +\thispagestyle{empty} +\newpage + +\pagenumbering{arabic} +\setcounter{page}{1} +\begin{center} +{\bf Users Guide for ROMIO: A High-Performance,\\[1ex] +Portable MPI-IO Implementation} \\ [2ex] +by \\ [2ex] +{\it Rajeev Thakur, Robert Ross, Ewing Lusk, and William Gropp} + +\end{center} +\addcontentsline{toc}{section}{Abstract} +\begin{abstract} +\noindent +ROMIO is a high-performance, portable implementation of MPI-IO (the +I/O chapter in the \mbox{MPI Standard}). This document describes how to install and use +ROMIO version~1.2.4 on various machines. +\end{abstract} + +\section{Introduction} + +ROMIO\footnote{\tt http://www.mcs.anl.gov/romio} is a +high-performance, portable implementation of MPI-IO (the I/O chapter in +MPI~\cite{mpi97a}). This document describes how to install and use +ROMIO version~1.2.4 on various machines. + + +% +% MAJOR CHANGES IN THIS VERSION +% +\section{Major Changes in This Version} +\begin{itemize} +\item Added section describing ROMIO \texttt{MPI\_FILE\_SYNC} and + \texttt{MPI\_FILE\_CLOSE} behavior to User's Guide +\item Bug removed from PVFS ADIO implementation regarding resize operations +\item Added support for PVFS listio operations (see Section \ref{sec:hints}) +\item Added the following working hints: + \texttt{romio\_pvfs\_listio\_read}, \texttt{romio\_pvfs\_listio\_write} +\end{itemize} + +% +% GENERAL INFORMATION +% +\section{General Information} + +This version of ROMIO includes everything defined in the MPI I/O +chapter except support for file interoperability and +user-defined error handlers for files (\S~4.13.3). The subarray and +distributed array datatype constructor functions from Chapter 4 +(\S~4.14.4 \& \S~4.14.5) have been implemented. They are useful for +accessing arrays stored in files. The functions {\tt MPI\_File\_f2c} +and {\tt MPI\_File\_c2f} (\S~4.12.4) are also implemented. C, +Fortran, and profiling interfaces are provided for all functions that +have been implemented. + +This version of ROMIO runs on at least the following machines: IBM SP; Intel +Paragon; HP Exemplar; SGI Origin2000; Cray T3E; NEC SX-4; other +symmetric multiprocessors from HP, SGI, DEC, Sun, and IBM; and networks of +workstations (Sun, SGI, HP, IBM, DEC, Linux, and FreeBSD). +Supported file systems are IBM PIOFS, Intel PFS, HP/Convex +HFS, SGI XFS, NEC SFS, PVFS, NFS, NTFS, and any Unix file system (UFS). + +This version of ROMIO is included in MPICH 1.2.4; an earlier version +is included in at least the following MPI implementations: LAM, HP +MPI, SGI MPI, and NEC MPI. + +Note that proper I/O error codes and classes are returned and the status +variable is filled only when used with MPICH revision 1.2.1 or later. + +You can open files on multiple file systems in the same program. The +only restriction is that the directory where the file is to be opened +must be accessible from the process opening the file. For example, a +process running on one workstation may not be able to access a +directory on the local disk of another workstation, and therefore +ROMIO will not be able to open a file in such a directory. NFS-mounted +files can be accessed. + +An MPI-IO file created by ROMIO is no different from any other file +created by the underlying file system. Therefore, you may use any of +the commands provided by the file system to access the file, for example, +{\tt ls}, {\tt mv}, {\tt cp}, {\tt rm}, {\tt ftp}. + +Please read the limitations of this version of ROMIO that are listed +in Section~\ref{sec:limit} of this document (e.g., restriction to homogeneous +environments). + +\subsection{ROMIO Optimizations} +\label{sec:opt} + +ROMIO implements two I/O optimization techniques that in general +result in improved performance for applications. The first of these +is \emph{data sieving}~\cite{choudhary:passion}. Data sieving is a +technique for efficiently accessing noncontiguous regions of data in files +when noncontiguous accesses are not provided as a file system primitive. +The naive approach to accessing noncontiguous regions is to use a separate +I/O call for each contiguous region in the file. This results in a large +number of I/O operations, each of which is often for a very small amount +of data. The added network cost of performing an I/O operation across the +network, as in parallel I/O systems, is often high because of latency. +Thus, this naive approach typically performs very poorly because of +the overhead of multiple operations. +% +In the data sieving technique, a number of noncontiguous regions are +accessed by reading a block of data containing all of the regions, +including the unwanted data between them (called ``holes''). The regions +of interest are then extracted from this large block by the client. +This technique has the advantage of a single I/O call, but additional +data is read from the disk and passed across the network. + +There are four hints that can be used to control the application of +data sieving in ROMIO: \texttt{ind\_rd\_buffer\_size}, +\texttt{ind\_wr\_buffer\_size}, \texttt{romio\_ds\_read}, +and \texttt{romio\_ds\_write}. These are discussed in +Section~\ref{sec:hints}. + +The second optimization is \emph{two-phase +I/O}~\cite{bordawekar:primitives}. Two-phase I/O, also called collective +buffering, is an optimization that only applies to collective I/O +operations. In two-phase I/O, the collection of independent I/O operations +that make up the collective operation are analyzed to determine what +data regions must be transferred (read or written). These regions are +then split up amongst a set of aggregator processes that will actually +interact with the file system. In the case of a read, these aggregators +first read their regions from disk and redistribute the data to the +final locations, while in the case of a write, data is first collected +from the processes before being written to disk by the aggregators. + +There are five hints that can be used to control the application +of two-phase I/O: \texttt{cb\_config\_list}, \texttt{cb\_nodes}, +\texttt{cb\_buffer\_size}, \texttt{romio\_cb\_read}, +and \texttt{romio\_cb\_write}. These are discussed in +Subsection~\ref{sec:hints}. + +\subsection{Hints} +\label{sec:hints} + +If ROMIO doesn't understand a hint, or if the value is invalid, the hint +will be ignored. The values of hints being used by ROMIO for a file +can be obtained at any time via {\tt MPI\_File\_get\_info}. + +The following hints control the data sieving optimization and are +applicable to all file system types: + +\begin{itemize} +\item \texttt{ind\_rd\_buffer\_size} -- Controls the size (in bytes) of the +intermediate buffer used by ROMIO when performing data sieving during +read operations. Default is \texttt{4194304} (4~Mbytes). +\item \texttt{ind\_wr\_buffer\_size} -- Controls the size (in bytes) of the +intermediate buffer used by ROMIO when performing data sieving during +write operations. Default is \texttt{524288} (512~Kbytes). +\item \texttt{romio\_ds\_read} -- +Determines when ROMIO will choose to perform data sieving. +Valid values are \texttt{enable}, \texttt{disable}, or \texttt{automatic}. +Default value is \texttt{automatic}. In \texttt{automatic} mode ROMIO +may choose to enable or disable data sieving based on heuristics. +\item \texttt{romio\_ds\_write} -- Same as above, only for writes. +\end{itemize} + +The following hints control the two-phase (collective buffering) +optimization and are applicable to all file system types: +\begin{itemize} +\item \texttt{cb\_buffer\_size} -- Controls the size (in bytes) of the +intermediate buffer used in two-phase collective I/O. If the amount +of data that an aggregator will transfer is larger than this value, +then multiple operations are used. The default is \texttt{4194304} (4~Mbytes). +\item \texttt{cb\_nodes} -- Controls the maximum number of aggregators +to be used. By default this is set to the number of unique hosts in the +communicator used when opening the file. +\item \texttt{romio\_cb\_read} -- Controls when collective buffering is +applied to collective read operations. Valid values are +\texttt{enable}, \texttt{disable}, and \texttt{automatic}. Default is +\texttt{automatic}. When enabled, all collective reads will use +collective buffering. When disabled, all collective reads will be +serviced with individual operations by each process. When set to +\texttt{automatic}, ROMIO will use heuristics to determine when to +enable the optimization. +\item \texttt{romio\_cb\_write} -- Controls when collective buffering is +applied to collective write operations. Valid values are +\texttt{enable}, \texttt{disable}, and \texttt{automatic}. Default is +\texttt{automatic}. See the description of \texttt{romio\_cb\_read} for +an explanation of the values. +\item \texttt{romio\_no\_indep\_rw} -- This hint controls when ``deferred +open'' is used. When set to \texttt{true}, ROMIO will make an effort to avoid +performing any file operation on non-aggregator nodes. The application is +expected to use only collective operations. This is discussed in further +detail below. +\item \texttt{cb\_config\_list} -- Provides explicit control over +aggregators. This is discussed in further detail below. +\end{itemize} + +For some systems configurations, more control is needed to specify which +hardware resources (processors or nodes in an SMP) are preferred for +collective I/O, either for performance reasons or because only certain +resources have access to storage. The additional MPI\_Info key name +\texttt{cb\_config\_list} specifies a comma-separated list of strings, +each string specifying a particular node and an optional limit on the +number of processes to be used for collective buffering on this node. + +This refers to the same processes that \texttt{cb\_nodes} refers to, +but specifies the available nodes more precisely. + +The format of the value of \texttt{cb\_config\_list} is given by the +following BNF: +\begin{verbatim} +cb_config_list => hostspec [ ',' cb_config_list ] +hostspec => hostname [ ':' maxprocesses ] +hostname => + | '*' +maxprocesses => + | '*' +\end{verbatim} + +The value \texttt{hostname} identifies a processor. This name must match +the name returned by \texttt{MPI\_Get\_processor\_name}~\footnote{The +MPI standard requires that the output from this routine identify a +particular piece of hardware; some MPI implementations may not conform +to this requirement. MPICH does conform to the MPI standard.} +% +for the specified hardware. The value \texttt{*} as a hostname matches all +processors. The value of maxprocesses may be any nonnegative integer +(zero is allowed). + +The value \texttt{maxprocesses} specifies the maximum number of +processes that may be used for collective buffering on the specified +host. If no value is specified, the value one is assumed. If \texttt{*} +is specified for the number of processes, then all MPI processes with +this same hostname will be used.. + +Leftmost components of the info value take precedence. + +Note: Matching of processor names to \texttt{cb\_config\_list} entries +is performed with string matching functions and is independent of the +listing of machines that the user provides to mpirun/mpiexec. In other +words, listing the same machine multiple times in the list of hosts to +run on will not cause a \texttt{*:1} to assign the same host four +aggregators, because the matching code will see that the processor name +is the same for all four and will assign exactly one aggregator to the +processor. + +The value of this info key must be the same for all processes (i.e., the +call is collective and each process must receive the same hint value for +these collective buffering hints). Further, in the ROMIO implementation +the hint is only recognized at \texttt{MPI\_File\_open} time. + +The set of hints used with a file is available through the routine +\texttt{MPI\_File\_get\_info}, as documented in the MPI standard. +As an additional feature in the ROMIO implementation, wildcards will +be expanded to indicate the precise configuration used with the file, +with the hostnames in the rank order used for the collective buffering +algorithm (\emph{this is not implemented at this time}). + +Here are some examples of how this hint might be used: +\begin{itemize} +\item \texttt{*:1} One process per hostname (i.e., one process per node) +\item \texttt{box12:30,*:0} Thirty processes on one machine, namely + \texttt{box12}, and none anywhere else. +\item \texttt{n01,n11,n21,n31,n41} One process on each of these specific + nodes only. +\end{itemize} + +When the values specified by \texttt{cb\_config\_list} conflict with +other hints (e.g., the number of collective buffering nodes specified by +\texttt{cb\_nodes}), the implementation is encouraged to take the minimum +of the two values. In other words, if \texttt{cb\_config\_list} specifies +ten processors on which I/O should be performed, but \texttt{cb\_nodes} +specifies a smaller number, then an implementation is encouraged to use +only \texttt{cb\_nodes} total aggregators. If \texttt{cb\_config\_list} +specifies fewer processes than \texttt{cb\_nodes}, no more than the +number in \texttt{cb\_config\_list} should be used. + +The implementation is also encouraged to assign processes in the order +that they are listed in \texttt{cb\_config\_list}. + +The following hint controls the deferred open feature of romio and are also +applicable to all file system types: +\begin{itemize} +\item \texttt{romio\_no\_indep\_rw} -- If the application plans on performing only + collecitve operations and this hint is set to ``true'', then ROMIO can + have just the aggregators open a file. The \texttt{cb\_config\_list} and + \texttt{cb\_nodes} hints can be given to further control which nodes are + aggregators. +\end{itemize} + +For PVFS, PIOFS, and PFS: +\begin{itemize} +\item \texttt{striping\_factor} -- Controls the number of I/O devices to +stripe across. The default is file system dependent, but for PVFS it is +\texttt{-1}, indicating that the file should be striped across all I/O +devices. +\item \texttt{striping\_unit} -- Controls the striping unit (in bytes). +For PVFS the default will be the PVFS file system default strip size. +\item \texttt{start\_iodevice} -- Determines what I/O device data will +first be written to. This is a number in the range of 0 ... +striping\_factor - 1. +\end{itemize} + +\subsubsection{Hints for PFS} +\label{sec:hints_pfs} +\begin{itemize} +\item \texttt{pfs\_svr\_buf} -- Turns on PFS server buffering. Valid +values are \texttt{true} and \texttt{false}. Default is \texttt{false}. +\end{itemize} + +\subsubsection{Hints for XFS} +\label{sec:hints_xfs} +For XFS control is provided for the direct I/O optimization: +\begin{itemize} +\item \texttt{direct\_read} -- Controls direct I/O for reads. Valid +values are \texttt{true} and \texttt{false}. Default is \texttt{false}. +\item \texttt{direct\_write} -- Controls direct I/O for writes. Valid +values are \texttt{true} and \texttt{false}. Default is \texttt{false}. +\end{itemize} + +\subsubsection{Hints for PVFS (v1)} +\label{sec:hints_oldpvfs} + +For PVFS control is provided for the use of the listio interface. This +interface to PVFS allows for a collection of noncontiguous regions to be +requested (for reading or writing) with a single operation. This can result +in substantially higher performance when accessing noncontiguous regions. +Support for these operations in PVFS exists after version 1.5.4, but has not +been heavily tested, so use of the interface is disabled in ROMIO by default +at this time. The hints to control listio use are: +\begin{itemize} +\item \texttt{romio\_pvfs\_listio\_read} -- Controls use of listio for reads. +Valid values are \texttt{enable}, \texttt{disable}, and \texttt{automatic}. +Default is \texttt{disable}. +\item \texttt{romio\_pvfs\_listio\_write} -- Controls use of listio for writes. +Valid values are \texttt{enable}, \texttt{disable}, and \texttt{automatic}. +Default is \texttt{disable}. +\end{itemize} + +\subsubsection{Hints for PVFS (v2)} +\label{sec:hints_pvfs} + +The PVFS v2 file system has many tuning parameters. +\begin{itemize} +\item dtype i/o +\end{itemize} + +\subsubsection{Hints for Lustre} + +\begin{itemize} +\item romio\_lustre\_co\_ratio + +In stripe-contiguous IO pattern, each OST will be accessed by a group of +IO clients. CO means *C*lient/*O*ST ratio, or the max. number of IO clients +for each OST. +CO=1 by default. + +\item \texttt{romio\_lustre\_coll\_threshold} + +We won't do collective I/O if this hint is set and the IO request size is +bigger than this value. That's because when the request size is big, the +collective communication overhead increases and the benefits from collective +I/O becomes limited. A value of 0 means always perform collective I/O + +\item \texttt{romio\_lustre\_cb\_ds\_threshold} + +ROMIO can optimize collective I/O with a version of data sieving. If the I/O +request is smaller than this hint's value, though, ROMIO will not try to apply +the data sieving optimization. + +\item \texttt{romio\_lustre\_ds\_in\_coll} + +Collective IO will apply read-modify-write to deal with non-contiguous +data by default. However, it will introduce some overhead(IO operation and +locking). The Lustre developers have run tests where data sieving showed bad +collective write performance for some kinds of workloads. So, to avoid this, +we define the \texttt{romio\_lustre\_ds\_in\_coll} hint to disable the read-modify-write +step in collective I/O. This optimization is distinct from the one in +independent I/O (controlled by \texttt{romio\_ds\_read} and +\texttt{romio\_ds\_write}). + +\end{itemize} + +\subsubsection{Hints for PANFS (Panasas)} + +PanFS allows users to specify the layout of a file at file-creation time. +Layout information includes the number of StorageBlades (SB) across which the +data is stored, the number of SBs across which a parity stripe is written, and +the number of consecutive stripes that are placed on the same set of SBs. The +\texttt{panfs\_layout\_*} hints are only used if supplied at file-creation +time. +\begin{itemize} + +\item \texttt{panfs\_layout\_type} Specifies the layout of a file: 2 = RAID0 +3 = RAID5 Parity Stripes + +\item \texttt{panfs\_layout\_stripe\_unit} The size of the stripe unit +in bytes + +\item \texttt{panfs\_layout\_total\_num\_comps} The total number of +StorageBlades a file is striped across. + +\item \texttt{ panfs\_layout\_parity\_stripe\_width} If the layout type is +RAID5 Parity Stripes, this hint specifies the number of StorageBlades in a +parity stripe. + +\item \texttt{panfs\_layout\_parity\_stripe\_depth} If the layout type is RAID5 +Parity Stripes, this hint specifies the number of contiguous parity stripes +written across the same set of SBs. + +\item \texttt{panfs\_layout\_visit\_policy} If the layout type is RAID5 Parity +Stripes, the policy used to determine the parity stripe a given file offset is +written to: 1 = Round Robin +\end{itemize} + +PanFS supports the ``concurrent write'' (CW) mode, where groups of +cooperating clients can disable the PanFS consistency mechanisms and use +their own consistency protocol. Clients participating in concurrent +write mode use application specific information to improve performance +while maintaining file consistency. All clients accessing the file(s) +must enable concurrent write mode. If any client does not enable +concurrent write mode, then the PanFS consistency protocol will be +invoked. Once a file is opened in CW mode on a machine, attempts to +open a file in non-CW mode will fail with EACCES. If a file is already +opened in non-CW mode, attempts to open the file in CW mode will fail +with EACCES. The following hint is used to enable concurrent write +mode. + +\begin{itemize} +\item \texttt{panfs\_concurrent\_write} If set to 1 at file open time, +the file is opened using the PanFS concurrent write mode flag. +Concurrent write mode is not a persistent attribute of the file. +\end{itemize} + +Below is an example PanFS layout using the following parameters: +\begin{verbatim} + + - panfs_layout_type = 3 + - panfs_layout_total_num_comps = 100 + - panfs_layout_parity_stripe_width = 10 + - panfs_layout_parity_stripe_depth = 8 + - panfs_layout_visit_policy = 1 + + Parity Stripe Group 1 Parity Stripe Group 2 . . . Parity Stripe Group 10 + ---------------------- ---------------------- -------------------- + SB1 SB2 ... SB10 SB11 SB12 ... SB20 ... SB91 SB92 ... SB100 + ----------------------- ----------------------- --------------------- + D1 D2 ... D10 D91 D92 ... D100 D181 D182 ... D190 + D11 D12 D20 D101 D102 D110 D191 D192 D193 + D21 D22 D30 . . . . . . + D31 D32 D40 + D41 D42 D50 + D51 D52 D60 + D61 D62 D70 + D71 D72 D80 + D81 D82 D90 D171 D172 D180 D261 D262 D270 + D271 D272 D273 . . . . . . + ... +\end{verbatim} + +\subsubsection{Systemwide Hints} +\label{sec:system_hints} + +A site administrator with knowledge of the storage and networking capabilities +of a machine might be able to come up with a set of hint values that work +better for that machine than the ROMIO default values. As an extention to the +standard, ROMIO will consult a ``hints file''. This file provides an +additional mechanism for setting MPI-IO hints, albeit in a ROMIO-specific +manner. The hints file contains a list of hints and their values. ROMIO will +use these initial hint settings, though programs are free to override any of +them. + +The format of the hints file is a list of hints and their values, one per line. +A \# character in the first column indicates a comment, and ROMIO will ignore +the entire line. Here's an example: + +\begin{verbatim} +# this is a comment describing the following setting +cb_nodes 32 +# these nodes happen to have the best connection to storage +cb_config_list n01,n11,n21,n31,n41 +\end{verbatim} + +ROMIO will look for these hints in the file \texttt{/etc/romio-hints}. A user +can set the environment variable \texttt{ROMIO\_HINTS} to the name of a file +which ROMIO will use instead. + +\subsection{Using ROMIO on NFS} + +It is worth first mentioning that in no way do we encourage the use +of ROMIO on NFS volumes. NFS is not a high-performance protocol, nor +are NFS servers typically very good at handling the types of concurrent +access seen from MPI-IO applications. Nevertheless, NFS is a very popular +mechanism for providing access to a shared space, and ROMIO does support +MPI-IO to NFS volumes, provided that they are configured properly. + +To use ROMIO on NFS, file locking with {\tt fcntl} must work correctly +on the NFS installation. On some installations, fcntl locks don't +work. To get them to work, you need to use Version~3 of NFS, ensure +that the lockd daemon is running on all the machines, and have the system +administrator mount the NFS file system with the ``{\tt noac}'' option +(no attribute caching). Turning off attribute caching may reduce +performance, but it is necessary for correct behavior. + +The following are some instructions we received from Ian Wells of HP +for setting the {\tt noac} option on NFS. We have not tried them +ourselves. We are including them here because you may find +them useful. Note that some of the steps may be specific to HP +systems, and you may need root permission to execute some of the +commands. + +\begin{verbatim} + >1. first confirm you are running nfs version 3 + > + >rpcnfo -p `hostname` | grep nfs + > + >ie + > goedel >rpcinfo -p goedel | grep nfs + > 100003 2 udp 2049 nfs + > 100003 3 udp 2049 nfs + > + > + >2. then edit /etc/fstab for each nfs directory read/written by MPIO + > on each machine used for multihost MPIO. + > + > Here is an example of a correct fstab entry for /epm1: + > + > ie grep epm1 /etc/fstab + > + > ROOOOT 11>grep epm1 /etc/fstab + > gershwin:/epm1 /rmt/gershwin/epm1 nfs bg,intr,noac 0 0 + > + > if the noac option is not present, add it + > and then remount this directory + > on each of the machines that will be used to share MPIO files + > + >ie + > + >ROOOOT >umount /rmt/gershwin/epm1 + >ROOOOT >mount /rmt/gershwin/epm1 + > + >3. Confirm that the directory is mounted noac: + > + >ROOOOT >grep gershwin /etc/mnttab + >gershwin:/epm1 /rmt/gershwin/epm1 nfs + >noac,acregmin=0,acregmax=0,acdirmin=0,acdirmax=0 0 0 899911504 +\end{verbatim} + +\subsubsection{ROMIO, NFS, and Synchronization} + +NFS has a ``sync'' option that specifies that the server should put data on +the disk before replying that an operation is complete. This means that +the actual I/O cost on the server side cannot be hidden with caching, +etc. when this option is selected. + +In the ``async'' mode the server can get the data into a buffer (and +perhaps put it in the write queue; this depends on the implementation) +and reply right away. Obviously if the server were to go down after the +reply was sent but before the data was written, the system would be in +a strange state, which is why so many articles suggest the "sync" option. + +Some systems default to ``sync'', while others default to ``async'', +and the default can change from version to version of the NFS software. If +you find that access to an NFS volume through MPI-IO is particularly slow, +this is one thing to check out. + + +\subsection{Using testfs} +The testfs ADIO implementation provides a harness for testing components +of ROMIO or discovering the underlying I/O access patterns of an +application. When testfs is specified as the file system type, no +actual files will be opened. Instead debugging information will be +displayed on the processes opening the file. Subsequent I/O operations +on this testfs file will provide additional debugging information. + +The intention of the testfs implementation is that it serve as a +starting point for further instrumentation when debugging new features +or applications. As such it is expected that users will want to modify +the ADIO implementation in order to get the specific output they desire. + +\subsection{ROMIO and {\tt MPI\_FILE\_SYNC}} + +The MPI specification notes that a call to {\tt MPI\_FILE\_SYNC} ``causes +all previous writes to {\tt fh} by the calling process to be transferred to +the storage device.'' Likewise, calls to {\tt MPI\_FILE\_CLOSE} have this +same semantic. Further, ``if all processes have made updates to the storage +device, then all such updates become visible to subsequent reads of {\tt fh} +by the calling process.'' + +The intended use of {\tt MPI\_FILE\_SYNC} is to allow all processes in the +communicator used to open the file to see changes made to the file by each +other (the second part of the specification). The definition of ``storage +device'' in the specification is vague, and it isn't necessarily the case that +calling {\tt MPI\_FILE\_SYNC} will force data out to permanent storage. + +Since users often use {\tt MPI\_FILE\_SYNC} to attempt to force data out to +permanent storage (i.e. disk), the ROMIO implementation of this call enforces +stronger semantics for most underlying file systems by calling the appropriate +file sync operation when {\tt MPI\_FILE\_SYNC} is called (e.g. {\tt fsync}). +However, it is still unwise to assume that the data has all made it to disk +because some file systems (e.g. NFS) may not force data to disk when a client +system makes a sync call. + +For performance reasons we do \emph{not} make this same file system call at +{\tt MPI\_FILE\_CLOSE} time. At close time ROMIO ensures any data has been +written out to the ``storage device'' (file system) as defined in the +standard, but does not try to push the data beyond this and into physical +storage. Users should call {\tt MPI\_FILE\_SYNC} before the close if they wish +to encourage the underlying file system to push data to permanent storage. + +\subsection{ROMIO and {\tt MPI\_FILE\_SET\_SIZE}} + +{\tt MPI\_FILE\_SET\_SIZE} is a collective routine used to resize a file. It +is important to remember that a MPI-IO routine being collective does not imply +that the routine synchronizes the calling processes in any way (unless this is +specified explicitly). + +As of 1.2.4, ROMIO implements {\tt MPI\_FILE\_SET\_SIZE} by calling {\tt +ftruncate} from all processes. Since different processes may call the +function at different times, it means that unless external synchronization is +used, a resize operation mixed in with writes or reads could have unexpected +results. + +In short, if synchronization after a set size is needed, the user should add a +barrier or similar operation to ensure the set size has completed. + + +% +% INSTALLATION INSTRUCTIONS +% +\section{Installation Instructions} +Since ROMIO is included in MPICH, LAM, HP MPI, SGI MPI, and NEC MPI, you don't +need to install it separately if you are using any of these MPI +implementations. If you are using some other MPI, you +can configure and build ROMIO as follows: + +Untar the tar file as +\begin{verbatim} + gunzip -c romio.tar.gz | tar xvf - +\end{verbatim} +{\noindent or} +\begin{verbatim} + zcat romio.tar.Z | tar xvf - +\end{verbatim} + +{\noindent then} + +\begin{verbatim} + cd romio + ./configure + make +\end{verbatim} + +Some example programs and a Makefile are provided in the {\tt romio/test} +directory. Run the examples as you would run any MPI program. Each +program takes the filename as a command-line argument ``{\tt -fname +filename}''. + +The {\tt configure} script by default configures ROMIO for the file +systems most likely +to be used on the given machine. If you wish, you can explicitly specify the file +systems by using the ``{\tt -file\_system}'' option to configure. Multiple file +systems can be specified by using `+' as a separator, e.g., \\ +\hspace*{.4in} {\tt ./configure -file\_system=xfs+nfs} \\ +For the entire list of options to configure, do\\ +\hspace*{.4in} {\tt ./configure -h | more} \\ +After building a specific version, you can install it in a +particular directory with \\ +\hspace*{.4in} {\tt make install PREFIX=/usr/local/romio (or whatever directory you like)} \\ +or just\\ +\hspace*{.4in} {\tt make install (if you used -prefix at configure time)} + +If you intend to leave ROMIO where you built it, you should {\it not} +install it; {\tt make install} is used only to move the necessary +parts of a built ROMIO to another location. The installed copy will +have the include files, libraries, man pages, and a few other odds and +ends, but not the whole source tree. It will have a {\tt test} +directory for testing the installation and a location-independent +Makefile built during installation, which users can copy and modify to +compile and link against the installed copy. + +To rebuild ROMIO with a different set of configure options, do\\ +\hspace*{.4in} {\tt make distclean}\\ +to clean everything, including the Makefiles created by {\tt +configure}. Then run {\tt configure} again with the new options, +followed by {\tt make}. + +\subsection{Configuring for Linux and Large Files } + +32-bit systems running linux kernel version 2.4.0 or newer and glibc +version 2.2.0 or newer can support files greater than 2 GBytes in size. +This support is currently automaticly detected and enabled. We document the +manual steps should the automatic detection not work for some reason. + +The two macros {\tt\_FILE\_OFFSET\_BITS=64} and +{\tt\_LARGEFILE64\_SOURCE} tell gnu libc it's ok to support large files +on 32 bit platforms. The former changes the size of {\tt off\_t} (no +need to change source. might affect interoperability with libraries +compiled with a different size of {\tt off\_t}). The latter exposes +the gnu libc functions open64(), write64(), read64(), etc. ROMIO does +not make use of the 64 bit system calls directly at this time, but we +add this flag for good measure. + +If your linux system is relatively new, there is an excellent chance it +is running kernel 2.4.0 or newer and glibc-2.2.0 or newer. Add the +string +\begin{verbatim} +"-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE" +\end{verbatim} +to your CFLAGS environment variable before runnint {\tt./configure} + +% +% TESTING ROMIO +% +\section{Testing ROMIO} +To test if the installation works, do\\ +\hspace*{.4in} {\tt make testing}\\ +in the {\tt romio/test} directory. This calls a script that runs the test +programs and compares the results with what they should be. By +default, {\tt make testing} causes the test programs to create files in +the current directory and use whatever file system that corresponds +to. To test with other file systems, you need to specify a filename in +a directory corresponding to that file system as follows:\\ +\hspace*{.4in} {\tt make testing TESTARGS="-fname=/foo/piofs/test"} + + +% +% COMPILING AND RUNNING MPI-IO PROGRAMS +% +\section{Compiling and Running MPI-IO Programs} +If ROMIO is not already included in the MPI implementation, you need +to include the file {\tt mpio.h} for C or {\tt mpiof.h} for Fortran in +your MPI-IO program. + +Note that on HP machines running HPUX and on NEC SX-4, you need to +compile Fortran programs with {\tt mpifort}. + +With MPICH, HP MPI, or NEC MPI, you can compile MPI-IO programs as \\ +\hspace*{.4in} {\tt mpicc foo.c}\\ +or \\ +\hspace*{.4in} {\tt mpifort foo.f}\\ + +With SGI MPI, you can compile MPI-IO programs as \\ +\hspace*{.4in} {\tt cc foo.c -lmpi}\\ +or \\ +\hspace*{.4in} {\tt f77 foo.f -lmpi}\\ +or \\ +\hspace*{.4in} {\tt f90 foo.f -lmpi}\\ + +With LAM, you can compile MPI-IO programs as \\ +\hspace*{.4in} {\tt hcc foo.c -lmpi}\\ +or \\ +\hspace*{.4in} {\tt hf77 foo.f -lmpi}\\ + +If you have built ROMIO with some other MPI implementation, you can +compile MPI-IO programs by explicitly giving the path to the include +file mpio.h or mpiof.h and explicitly specifying the path to the +library libmpio.a, which is located in {\tt \$(ROMIO\_HOME)/lib/\$(ARCH)/libmpio.a}. + +Run the program as you would run any MPI program on the machine. +If you use {\tt mpirun}, make sure you use the correct {\tt mpirun} +for the MPI implementation you are using. For example, if you +are using MPICH on an SGI machine, make sure that you use MPICH's +{\tt mpirun} and not SGI's {\tt mpirun}. + + +% +% LIMITATIONS +% +\section{Limitations of This Version of ROMIO \label{sec:limit}} + +\begin{itemize} +\item When used with any MPI implementation other than MPICH revision +1.2.1 or later, the {\tt status} argument is not filled in any MPI-IO +function. Consequently, {\tt MPI\_Get\_count} and\linebreak {\tt +MPI\_Get\_elements} will not work when passed the {\tt status} object +from an MPI-IO operation. + +\item Additionally, when used with any MPI implementation other than MPICH +revision 1.2.1 or later, all MPI-IO functions return only two possible +error codes---{\tt MPI\_SUCCESS} on success and {\tt MPI\_ERR\_UNKNOWN} +on failure. + +\item This version works only on a homogeneous cluster of machines, +and only the ``native'' file data representation is supported. + +\item Shared file pointers are not supported on PVFS and IBM PIOFS +file systems because they don't support {\tt fcntl} file locks, +and ROMIO uses that feature to implement shared file pointers. + +\item On HP machines running HPUX and on NEC SX-4, you need to compile +Fortran programs with {\tt mpifort}. + +\item The file-open mode {\tt MPI\_MODE\_EXCL} does not work on Intel +PFS file system, due to a bug in PFS. + +\end{itemize} + + +% +% USAGE TIPS +% +\section{Usage Tips} +\begin{itemize} +\item When using ROMIO with SGI MPI, you may +sometimes get an error message from SGI MPI: ``MPI has run out of +internal datatype entries. Please set the environment variable +{\tt MPI\_TYPE\_MAX} for additional space.'' If you get this error message, +add the following line to your {\tt .cshrc} file:\\ +\hspace*{.4in} {\tt setenv MPI\_TYPE\_MAX 65536}\\ +Use a larger number if you still get the error message. +\item If a Fortran program uses a file handle created using ROMIO's C +interface, or vice versa, you must use the functions {\tt MPI\_File\_c2f} +or {\tt MPI\_File\_f2c} (see \S~4.12.4 in~\cite{mpi97a}). Such a +situation occurs, for example, if a Fortran program uses an I/O +library written in C +with MPI-IO calls. Similar functions {\tt MPIO\_Request\_f2c} and +{\tt MPIO\_Request\_c2f} are also provided. +\item For Fortran programs on the Intel Paragon, you may need +to provide the complete path to {\tt mpif.h} in the {\tt include} +statement, e.g., \\ +\hspace*{.4in} {\tt include '/usr/local/mpich/include/mpif.h'}\\ +instead of \\ +\hspace*{.4in} {\tt include 'mpif.h'}\\ +This is because the {\tt -I} +option to the Paragon Fortran compiler {\tt if77} doesn't work +correctly. It always looks in the default directories first and, +therefore, picks up Intel's {\tt mpif.h}, which is actually the {\tt +mpif.h} of an older version of MPICH. + +\end{itemize} + +% +% MAILING LIST +% +% this mailing list has been dead for a while +% +% REPORTING BUGS +% +\section{Reporting Bugs} +If you have trouble, first check the users guide. Then check if there +is a list of known bugs and patches on the ROMIO web page at {\tt +http://www.mcs.anl.gov/romio}. Finally, if you still have problems, send a +detailed message containing:\\ +\hspace*{.2in}$\bullet$ the type of system (often {\tt uname -a}),\\ +\hspace*{.2in}$\bullet$ the output of {\tt configure},\\ +\hspace*{.2in}$\bullet$ the output of {\tt make}, and \\ +\hspace*{.2in}$\bullet$ any programs or tests\\ +to {\tt romio-maint@mcs.anl.gov}. + + +% +% ROMIO INTERNALS +% +\section{ROMIO Internals} +A key component of ROMIO that enables such a portable MPI-IO +implementation is an internal abstract I/O device layer called +ADIO~\cite{thak96e}. Most users of ROMIO will not need to deal with +the ADIO layer at all. However, ADIO is useful to those who want to +port ROMIO to some other file system. The ROMIO source code and the +ADIO paper~\cite{thak96e} will help you get started. + +MPI-IO implementation issues are discussed in~\cite{thak99b}. All +ROMIO-related papers are available online at {\tt +http://www.mcs.anl.gov/romio}. + + +\section{Learning MPI-IO} +The book {\em Using MPI-2: Advanced Features of the Message-Passing +Interface}~\cite{grop99a}, published by MIT Press, provides a tutorial +introduction to all aspects of MPI-2, including parallel I/O. It has +lots of example programs. See {\tt +http://www.mcs.anl.gov/mpi/usingmpi2} for further information about +the book. + +% +% MAJOR CHANGES IN PREVIOUS RELEASES +% +\section{Major Changes in Previous Releases} + +\subsection{Major Changes in Version 1.2.3} +\begin{itemize} +\item Added explicit control over aggregators for collective operations + (see description of \texttt{cb\_config\_list}). +\item Added the following working hints: \texttt{cb\_config\_list}, + \texttt{romio\_cb\_read}, \texttt{romio\_cb\_write},\newline + \texttt{romio\_ds\_read}. These additional hints have + been added but are currently ignored by the implementation: + \texttt{romio\_ds\_write}, \texttt{romio\_no\_indep\_rw}. +\item Added NTFS ADIO implementation. +\item Added testfs ADIO implementation for use in debugging. +\item Added delete function to ADIO interface so that file systems that + need to use their own delete function may do so (e.g. PVFS). +\item Changed version numbering to match version number of MPICH release. +\end{itemize} + +\subsection{Major Changes in Version 1.0.3} +\begin{itemize} +\item When used with MPICH 1.2.1, the MPI-IO functions return proper +error codes and classes, and the status object is filled in. + +\item On SGI's XFS file system, ROMIO can use direct I/O even if the +user's request does not meet the various restrictions needed to use +direct I/O. ROMIO does this by doing part of the request with buffered +I/O (until all the restrictions are met) and doing the rest with +direct I/O. (This feature hasn't been tested rigorously. Please check +for errors.) + +By default, ROMIO will use only buffered I/O. Direct I/O can be +enabled either by setting the environment variables {\tt +MPIO\_DIRECT\_READ} and/or {\tt MPIO\_DIRECT\_WRITE} to {\tt TRUE}, or +on a per-file basis by using the info keys {\tt direct\_read} and {\tt +direct\_write}. + +Direct I/O will result in higher performance only if you are accessing +a high-bandwidth disk system. Otherwise, buffered I/O is better and is +therefore used as the default. + +\item Miscellaneous bug fixes. +\end{itemize} + +\subsection{Major Changes in Version 1.0.2} +\begin{itemize} +\item Implemented the shared file pointer functions and + split collective I/O functions. Therefore, the main + components of the MPI I/O chapter not yet implemented are + file interoperability and error handling. + +\item Added support for using ``direct I/O'' on SGI's XFS file system. + Direct I/O is an optional feature of XFS in which data is moved + directly between the user's buffer and the storage devices, bypassing + the file-system cache. This can improve performance significantly on + systems with high disk bandwidth. Without high disk bandwidth, + regular I/O (that uses the file-system cache) perfoms better. + ROMIO, therefore, does not use direct I/O by default. The user can + turn on direct I/O (separately for reading and writing) either by + using environment variables or by using MPI's hints mechanism (info). + To use the environment-variables method, do +\begin{verbatim} + setenv MPIO_DIRECT_READ TRUE + setenv MPIO_DIRECT_WRITE TRUE +\end{verbatim} + To use the hints method, the two keys are {\tt direct\_read} and {\tt + direct\_write}. By default their values are {\tt false}. To turn on + direct I/O, set the values to {\tt true}. The environment variables + have priority over the info keys. In other words, if the environment + variables are set to {\tt TRUE}, direct I/O will be used even if the + info keys say {\tt false}, and vice versa. Note that direct I/O must be + turned on separately for reading and writing. The environment-variables + method assumes that the environment variables can be read by each + process in the MPI job. This is not guaranteed by the MPI Standard, + but it works with SGI's MPI and the {\tt ch\_shmem} device of MPICH. + +\item Added support (new ADIO device, {\tt ad\_pvfs}) for the PVFS parallel + file system for Linux clusters, developed at Clemson University + (see {\tt http://www.parl.clemson.edu/pvfs}). To use it, you + must first install PVFS and then when configuring ROMIO, specify + {\tt -file\_system=pvfs} in addition to any other options to {\tt + configure}. (As usual, you can configure for multiple file systems by + using ``{\tt +}''; for example, {\tt -file\_system=pvfs+ufs+nfs}.) You + will need to specify the path to the PVFS include files via the {\tt + -cflags} option to {\tt configure}, for example, \newline {\tt configure + -cflags=-I/usr/pvfs/include}. You will also need to specify the full + path name of the PVFS library. The best way to do this is via the {\tt + -lib} option to MPICH's {\tt configure} script (assuming you are using + ROMIO from within MPICH). + +\item Uses weak symbols (where available) for building the profiling version, + i.e., the PMPI routines. As a result, the size of the library is reduced + considerably. + +\item The Makefiles use {\em virtual paths} if supported by the make + utility. GNU {\tt make} + supports it, for example. This feature allows you to untar the + distribution in some directory, say a slow NFS directory, + and compile the library (create the .o files) in another + directory, say on a faster local disk. For example, if the tar file + has been untarred in an NFS directory called {\tt /home/thakur/romio}, + one can compile it in a different directory, say {\tt /tmp/thakur}, as + follows: +\begin{verbatim} + cd /tmp/thakur + /home/thakur/romio/configure + make +\end{verbatim} + The .o files will be created in {\tt /tmp/thakur}; the library will be created in\newline + {\tt /home/thakur/romio/lib/\$ARCH/libmpio.a}. + This method works only if the {\tt make} utility supports {\em + virtual paths}. + If the default {\tt make} utility does not, you can install GNU {\tt + make} which does, and specify it to {\tt configure} as +\begin{verbatim} + /home/thakur/romio/configure -make=/usr/gnu/bin/gmake (or whatever) +\end{verbatim} + +\item Lots of miscellaneous bug fixes and other enhancements. + +\item This version is included in MPICH 1.2.0. If you are using MPICH, you + need not download ROMIO separately; it gets built as part of MPICH. + The previous version of ROMIO is included in LAM, HP MPI, SGI MPI, and + NEC MPI. NEC has also implemented the MPI-IO functions missing + in ROMIO, and therefore NEC MPI has a complete implementation of MPI-IO. +\end{itemize} + + +\subsection{Major Changes in Version 1.0.1} + +\begin{itemize} +\item This version is included in MPICH 1.1.1 and HP MPI 1.4. + +\item Added support for NEC SX-4 and created a new device {\tt ad\_sfs} for +NEC SFS file system. + +\item New devices {\tt ad\_hfs} for HP HFS file system and {\tt +ad\_xfs} for SGI XFS file system. + +\item Users no longer need to prefix the filename with the type of +file system; ROMIO determines the file-system type on its own. + +\item Added support for 64-bit file sizes on IBM PIOFS, SGI XFS, +HP HFS, and NEC SFS file systems. + +\item {\tt MPI\_Offset} is an 8-byte integer on machines that support +8-byte integers. It is of type {\tt long long} in C and {\tt +integer*8} in Fortran. With a Fortran 90 compiler, you can use either +{\tt integer*8} or {\tt integer(kind=MPI\_OFFSET\_KIND)}. +If you {\tt printf} an {\tt MPI\_Offset} in C, remember to use {\tt \%lld} +or {\tt \%ld} as required by your compiler. (See what is used in the test +program {\tt romio/test/misc.c}). +On some machines, ROMIO detects at configure time that {\tt long long} is +either not supported by the C compiler or it doesn't work properly. +In such cases, configure sets {\tt MPI\_Offset} to {\tt long} in C and {\tt +integer} in Fortran. This happens on Intel Paragon, Sun4, and FreeBSD. + +\item Added support for passing hints to the implementation via the +{\tt MPI\_Info} parameter. ROMIO understands the following hints (keys +in {\tt MPI\_Info} object): +\texttt{cb\_buffer\_size}, +\texttt{cb\_nodes},\newline +\texttt{ind\_rd\_buffer\_size}, +\texttt{ind\_wr\_buffer\_size} (on all but IBM PIOFS), +\texttt{striping\_factor} (on PFS and PIOFS), +\texttt{striping\_unit} (on PFS and PIOFS), +\texttt{start\_iodevice} (on PFS and PIOFS), +and \texttt{pfs\_svr\_buf} (on PFS only). + +\end{itemize} +\newpage + +\addcontentsline{toc}{section}{References} +\bibliographystyle{plain} +%% these are the "full" bibliography databases +%\bibliography{/homes/thakur/tex/bib/papers,/homes/robl/projects/papers/pario} +% this is the pared-down one containing only those references used in +% users-guide.tex +% to regenerate, uncomment the full databases above, then run +% ~gropp/bin/citetags users-guide.tex | sort | uniq | \ +% ~gropp/bin/citefind - /homes/thakur/tex/bib/papers.bib \ +% /homes/robl/projects/papers/pario +\bibliography{romio} + +\end{document} diff --git a/ompi/mca/io/romio314/romio/include/mpio.h.in b/ompi/mca/io/romio314/romio/include/mpio.h.in new file mode 100644 index 0000000000..d4c7ed769d --- /dev/null +++ b/ompi/mca/io/romio314/romio/include/mpio.h.in @@ -0,0 +1,507 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* user include file for MPI-IO programs */ + +#ifndef MPIO_INCLUDE +#define MPIO_INCLUDE + +#include "mpi.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define ROMIO_VERSION 126 /* version 1.2.6 */ + +/* define MPI-IO datatypes and constants */ + +#ifndef MPI_FILE_DEFINED +typedef struct ADIOI_FileD *MPI_File; +#endif + +@DEFINE_HAVE_MPI_GREQUEST@ +#ifndef HAVE_MPI_GREQUEST +typedef struct ADIOI_RequestD *MPIO_Request; +#else +#define MPIO_Request MPI_Request +#define MPIO_USES_MPI_REQUEST +/* Also rename the MPIO routines to get the MPI versions */ +#define MPIO_Wait MPI_Wait +#define MPIO_Test MPI_Test +#define PMPIO_Wait PMPI_Wait +#define PMPIO_Test PMPI_Test +#endif +#define MPIO_REQUEST_DEFINED + +#ifndef HAVE_MPI_OFFSET +@DEFINE_MPI_OFFSET@ +/* If we needed to define MPI_Offset, then we also need to make + this definition. */ +#ifndef HAVE_MPI_DATAREP_FUNCTIONS +#define HAVE_MPI_DATAREP_FUNCTIONS +typedef int (MPI_Datarep_conversion_function)(void *, MPI_Datatype, int, + void *, MPI_Offset, void *); +typedef int (MPI_Datarep_extent_function)(MPI_Datatype datatype, MPI_Aint *, + void *); +#endif +#endif + +#ifndef NEEDS_MPI_FINT +@NEEDS_MPI_FINT@ +#endif +#ifdef NEEDS_MPI_FINT +typedef int MPI_Fint; +#endif + +#ifndef HAVE_MPI_INFO +@HAVE_MPI_INFO@ +#endif +#ifndef HAVE_MPI_INFO + typedef struct MPIR_Info *MPI_Info; +# define MPI_INFO_NULL ((MPI_Info) 0) +# define MPI_MAX_INFO_KEY 255 +# define MPI_MAX_INFO_VAL 1024 +#endif + +#define MPI_MODE_RDONLY 2 /* ADIO_RDONLY */ +#define MPI_MODE_RDWR 8 /* ADIO_RDWR */ +#define MPI_MODE_WRONLY 4 /* ADIO_WRONLY */ +#define MPI_MODE_CREATE 1 /* ADIO_CREATE */ +#define MPI_MODE_EXCL 64 /* ADIO_EXCL */ +#define MPI_MODE_DELETE_ON_CLOSE 16 /* ADIO_DELETE_ON_CLOSE */ +#define MPI_MODE_UNIQUE_OPEN 32 /* ADIO_UNIQUE_OPEN */ +#define MPI_MODE_APPEND 128 /* ADIO_APPEND */ +#define MPI_MODE_SEQUENTIAL 256 /* ADIO_SEQUENTIAL */ + +#define MPI_DISPLACEMENT_CURRENT -54278278 + +#ifndef MPICH +/* FIXME: Make sure that we get a consistent definition of MPI_FILE_NULL + in MPICH */ +/* MPICH defines null object handles differently */ +#define MPI_FILE_NULL ((MPI_File) 0) +#endif +#define MPIO_REQUEST_NULL ((MPIO_Request) 0) + +#define MPI_SEEK_SET 600 +#define MPI_SEEK_CUR 602 +#define MPI_SEEK_END 604 + +/* Open MPI: don't define MPI_MAX_DATAREP_STRING here; it's defined in + OMPI's mpi.h. */ +#ifndef OPEN_MPI +#define MPI_MAX_DATAREP_STRING 128 +#endif + +#ifndef HAVE_MPI_DARRAY_SUBARRAY +@HAVE_MPI_DARRAY_SUBARRAY@ +#endif +#ifndef HAVE_MPI_DARRAY_SUBARRAY +# define MPI_ORDER_C 56 +# define MPI_ORDER_FORTRAN 57 +# define MPI_DISTRIBUTE_BLOCK 121 +# define MPI_DISTRIBUTE_CYCLIC 122 +# define MPI_DISTRIBUTE_NONE 123 +# define MPI_DISTRIBUTE_DFLT_DARG -49767 +#endif + + +/* MPI-IO function prototypes */ + +/* The compiler must support ANSI C style prototypes, otherwise + long long constants (e.g. 0) may get passed as ints. */ + +#ifndef HAVE_PRAGMA_HP_SEC_DEF + +/* Section 9.2 */ +/* Begin Prototypes */ +int MPI_File_open(MPI_Comm comm, const char *filename, int amode, MPI_Info info, MPI_File *fh); +int MPI_File_close(MPI_File *fh); +int MPI_File_delete(const char *filename, MPI_Info info); +int MPI_File_set_size(MPI_File fh, MPI_Offset size); +int MPI_File_preallocate(MPI_File fh, MPI_Offset size); +int MPI_File_get_size(MPI_File fh, MPI_Offset *size); +int MPI_File_get_group(MPI_File fh, MPI_Group *group); +int MPI_File_get_amode(MPI_File fh, int *amode); +int MPI_File_set_info(MPI_File fh, MPI_Info info); +int MPI_File_get_info(MPI_File fh, MPI_Info *info_used); + +/* Section 9.3 */ +int MPI_File_set_view(MPI_File fh, MPI_Offset disp, MPI_Datatype etype, MPI_Datatype filetype, + const char *datarep, MPI_Info info); +int MPI_File_get_view(MPI_File fh, MPI_Offset *disp, MPI_Datatype *etype, MPI_Datatype *filetype, + char *datarep); + +/* Section 9.4.2 */ +int MPI_File_read_at(MPI_File fh, MPI_Offset offset, void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int MPI_File_read_at_all(MPI_File fh, MPI_Offset offset, void * buf, int count, + MPI_Datatype datatype, MPI_Status *status) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int MPI_File_write_at(MPI_File fh, MPI_Offset offset, const void * buf, int count, + MPI_Datatype datatype, MPI_Status *status) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int MPI_File_write_at_all(MPI_File fh, MPI_Offset offset, const void *buf, int count, + MPI_Datatype datatype, MPI_Status *status) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); + +/* nonblocking calls currently use MPIO_Request, because generalized + requests not yet implemented. For the same reason, MPIO_Test and + MPIO_Wait are used to test and wait on nonblocking I/O requests */ +int MPI_File_iread_at(MPI_File fh, MPI_Offset offset, void *buf, int count, MPI_Datatype datatype, + MPIO_Request *request) MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int MPI_File_iwrite_at(MPI_File fh, MPI_Offset offset, const void *buf, int count, + MPI_Datatype datatype, MPIO_Request *request) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); + +/* Section 9.4.3 */ +int MPI_File_read(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_read_all(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_write(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_write_all(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); + +/* nonblocking calls currently use MPIO_Request, because generalized + requests not yet implemented. For the same reason, MPIO_Test and + MPIO_Wait are used to test and wait on nonblocking I/O requests */ + +int MPI_File_iread(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPIO_Request *request) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_iwrite(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPIO_Request *request) MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); + +int MPI_File_seek(MPI_File fh, MPI_Offset offset, int whence); +int MPI_File_get_position(MPI_File fh, MPI_Offset *offset); +int MPI_File_get_byte_offset(MPI_File fh, MPI_Offset offset, MPI_Offset *disp); + +/* Section 9.4.4 */ +int MPI_File_read_shared(MPI_File fh, void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_write_shared(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_iread_shared(MPI_File fh, void *buf, int count, MPI_Datatype datatype, + MPIO_Request *request) MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_iwrite_shared(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPIO_Request *request) MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_read_ordered(MPI_File fh, void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_write_ordered(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_seek_shared(MPI_File fh, MPI_Offset offset, int whence); +int MPI_File_get_position_shared(MPI_File fh, MPI_Offset *offset); + +/* Section 9.4.5 */ +int MPI_File_read_at_all_begin(MPI_File fh, MPI_Offset offset, void *buf, int count, + MPI_Datatype datatype) MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int MPI_File_read_at_all_end(MPI_File fh, void *buf, MPI_Status *status); +int MPI_File_write_at_all_begin(MPI_File fh, MPI_Offset offset, const void *buf, int count, + MPI_Datatype datatype) MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int MPI_File_write_at_all_end(MPI_File fh, const void *buf, MPI_Status *status); +int MPI_File_read_all_begin(MPI_File fh, void *buf, int count, MPI_Datatype datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_read_all_end(MPI_File fh, void *buf, MPI_Status *status); +int MPI_File_write_all_begin(MPI_File fh, const void *buf, int count, MPI_Datatype datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_write_all_end(MPI_File fh, const void *buf, MPI_Status *status); +int MPI_File_read_ordered_begin(MPI_File fh, void *buf, int count, MPI_Datatype datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_read_ordered_end(MPI_File fh, void *buf, MPI_Status *status); +int MPI_File_write_ordered_begin(MPI_File fh, const void *buf, int count, MPI_Datatype datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int MPI_File_write_ordered_end(MPI_File fh, const void *buf, MPI_Status *status); + +/* Section 9.5.1 */ +int MPI_File_get_type_extent(MPI_File fh, MPI_Datatype datatype, MPI_Aint *extent); + +/* Section 9.5.3 */ +int MPI_Register_datarep(const char *datarep, MPI_Datarep_conversion_function *read_conversion_fn, + MPI_Datarep_conversion_function *write_conversion_fn, + MPI_Datarep_extent_function *dtype_file_extent_fn, void *extra_state); + +/* Section 9.6.1 */ +int MPI_File_set_atomicity(MPI_File fh, int flag); +int MPI_File_get_atomicity(MPI_File fh, int *flag); +int MPI_File_sync(MPI_File fh); + +/* Section 4.13.3 */ +#ifndef MPICH +/* MPICH provides these definitions */ +int MPI_File_set_errhandler(MPI_File file, MPI_Errhandler errhandler); +int MPI_File_get_errhandler(MPI_File file, MPI_Errhandler *errhandler); +#endif +/* End Prototypes */ + +#ifndef HAVE_MPI_DARRAY_SUBARRAY +/* Section 4.14.4 */ +int MPI_Type_create_subarray(int ndims, const int array_of_sizes[], const int array_of_subsizes[], + const int array_of_starts[], int order, MPI_Datatype oldtype, + MPI_Datatype *newtype); + +/* Section 4.14.5 */ +int MPI_Type_create_darray(int size, int rank, int ndims, const int array_of_gsizes[], + const int array_of_distribs[], const int array_of_dargs[], + const int array_of_psizes, int order, MPI_Datatype oldtype, + MPI_Datatype *newtype); +#endif + +/* The globus2 device has to rename MPI_ symbols in order to use the vendor + MPI as one of its transport mechanisms. Therefore, the following undefines + should only happen if MPICH_RENAMING_MPI_FUNCS is not defined. */ +/* Section 4.12.4 */ +#if !defined(MPICH_RENAMING_MPI_FUNCS) +#ifdef MPI_File_f2c +#undef MPI_File_f2c +#endif +#ifdef MPI_File_c2f +#undef MPI_File_c2f +#endif +#endif +/* above needed for some versions of mpi.h in MPICH!! */ +MPI_File MPI_File_f2c(MPI_Fint file); +MPI_Fint MPI_File_c2f(MPI_File file); + + +#ifndef HAVE_MPI_GREQUEST +/* The following functions are required if generalized requests are not + available, because in that case, an MPIO_Request object + is currently used for nonblocking I/O. */ +int MPIO_Test(MPIO_Request *request, int *flag, MPI_Status *status); +int MPIO_Wait(MPIO_Request *request, MPI_Status *status); +int MPIO_Testall(int count, MPIO_Request array_of_requests[], int *flag, + MPI_Status array_of_statuses[]); +int MPIO_Waitall(int count, MPIO_Request array_of_requests[], MPI_Status array_of_statuses[]); +int MPIO_Testany(int count, MPIO_Request array_of_requests[], int *indx, int *flag, + MPI_Status *status); +int MPIO_Waitany(int count, MPIO_Request array_of_requests[], int *indx, MPI_Status *status); +int MPIO_Waitsome(int incount, MPIO_Request array_of_requests[], int *outcount, + int array_of_indices[], MPI_Status array_of_statuses[]); +int MPIO_Testsome(int incount, MPIO_Request array_of_requests[], int *outcount, + int array_of_indices[], MPI_Status array_of_statuses[]); + +MPI_Fint MPIO_Request_c2f(MPIO_Request request); +MPIO_Request MPIO_Request_f2c(MPI_Fint request); +#endif /* HAVE_MPI_GREQUEST */ + +/* info functions if not defined in the MPI implementation */ +#ifndef HAVE_MPI_INFO + +int MPI_Info_create(MPI_Info *info); +int MPI_Info_set(MPI_Info info, const char *key, const char *value); +int MPI_Info_delete(MPI_Info info, const char *key); +int MPI_Info_get(MPI_Info info, const char *key, int valuelen, char *value, int *flag); +int MPI_Info_get_valuelen(MPI_Info info, const char *key, int *valuelen, int *flag); +int MPI_Info_get_nkeys(MPI_Info info, int *nkeys); +int MPI_Info_get_nthkey(MPI_Info info, int n, char *key); +int MPI_Info_dup(MPI_Info info, MPI_Info *newinfo); +int MPI_Info_free(MPI_Info *info); + +/* The globus2 device has to rename MPI_ symbols in order to use the vendor + MPI as one of its transport mechanisms. Therefore, the following undefines + should only happen if MPICH_RENAMING_MPI_FUNCS is not defined. */ +#if !defined(MPICH_RENAMING_MPI_FUNCS) +#ifdef MPI_Info_f2c +#undef MPI_Info_f2c +#endif +#ifdef MPI_Info_c2f +#undef MPI_Info_c2f +#endif +#endif +/* above needed for some versions of mpi.h in MPICH!! */ +MPI_Fint MPI_Info_c2f(MPI_Info info); +MPI_Info MPI_Info_f2c(MPI_Fint info); +#endif + +#endif /* HAVE_PRAGMA_HP_SEC_DEF */ + + +/**************** BINDINGS FOR THE PROFILING INTERFACE ***************/ + + +/* Section 9.2 */ +int PMPI_File_open(MPI_Comm, const char *, int, MPI_Info, MPI_File *); +int PMPI_File_close(MPI_File *); +int PMPI_File_delete(const char *, MPI_Info); +int PMPI_File_set_size(MPI_File, MPI_Offset); +int PMPI_File_preallocate(MPI_File, MPI_Offset); +int PMPI_File_get_size(MPI_File, MPI_Offset *); +int PMPI_File_get_group(MPI_File, MPI_Group *); +int PMPI_File_get_amode(MPI_File, int *); +int PMPI_File_set_info(MPI_File, MPI_Info); +int PMPI_File_get_info(MPI_File, MPI_Info *); + +/* Section 9.3 */ +int PMPI_File_set_view(MPI_File, MPI_Offset, + MPI_Datatype, MPI_Datatype, const char *, MPI_Info); +int PMPI_File_get_view(MPI_File, MPI_Offset *, + MPI_Datatype *, MPI_Datatype *, char *); + +/* Section 9.4.2 */ +int PMPI_File_read_at(MPI_File, MPI_Offset, void *, + int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int PMPI_File_read_at_all(MPI_File, MPI_Offset, void *, + int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int PMPI_File_write_at(MPI_File, MPI_Offset, const void *, + int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int PMPI_File_write_at_all(MPI_File, MPI_Offset, const void *, + int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); + +/* nonblocking calls currently use MPIO_Request, because generalized + requests not yet implemented. For the same reason, MPIO_Test and + MPIO_Wait are used to test and wait on nonblocking I/O requests */ + +int PMPI_File_iread_at(MPI_File, MPI_Offset, void *, + int, MPI_Datatype, MPIO_Request *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int PMPI_File_iwrite_at(MPI_File, MPI_Offset, const void *, + int, MPI_Datatype, MPIO_Request *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); + +/* Section 9.4.3 */ +int PMPI_File_read(MPI_File, void *, int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_read_all(MPI_File, void *, int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_write(MPI_File, const void *, int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_write_all(MPI_File, const void *, int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); + +/* nonblocking calls currently use MPIO_Request, because generalized + requests not yet implemented. For the same reason, MPIO_Test and + MPIO_Wait are used to test and wait on nonblocking I/O requests */ + +int PMPI_File_iread(MPI_File, void *, int, MPI_Datatype, MPIO_Request *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_iwrite(MPI_File, const void *, int, MPI_Datatype, MPIO_Request *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); + +int PMPI_File_seek(MPI_File, MPI_Offset, int); +int PMPI_File_get_position(MPI_File, MPI_Offset *); +int PMPI_File_get_byte_offset(MPI_File, MPI_Offset, MPI_Offset *); + +/* Section 9.4.4 */ +int PMPI_File_read_shared(MPI_File, void *, int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_write_shared(MPI_File, const void *, int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_iread_shared(MPI_File, void *, int, + MPI_Datatype, MPIO_Request *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_iwrite_shared(MPI_File, const void *, int, + MPI_Datatype, MPIO_Request *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_read_ordered(MPI_File, void *, int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_write_ordered(MPI_File, const void *, int, MPI_Datatype, MPI_Status *) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_seek_shared(MPI_File, MPI_Offset, int); +int PMPI_File_get_position_shared(MPI_File, MPI_Offset *); + +/* Section 9.4.5 */ +int PMPI_File_read_at_all_begin(MPI_File, MPI_Offset, void *, + int, MPI_Datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int PMPI_File_read_at_all_end(MPI_File, void *, MPI_Status *); +int PMPI_File_write_at_all_begin(MPI_File, MPI_Offset, const void *, + int, MPI_Datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(3,5); +int PMPI_File_write_at_all_end(MPI_File, const void *, MPI_Status *); +int PMPI_File_read_all_begin(MPI_File, void *, int, MPI_Datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_read_all_end(MPI_File, void *, MPI_Status *); +int PMPI_File_write_all_begin(MPI_File, const void *, int, MPI_Datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_write_all_end(MPI_File, const void *, MPI_Status *); +int PMPI_File_read_ordered_begin(MPI_File, void *, int, MPI_Datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_read_ordered_end(MPI_File, void *, MPI_Status *); +int PMPI_File_write_ordered_begin(MPI_File, const void *, int, MPI_Datatype) + MPICH_ATTR_POINTER_WITH_TYPE_TAG(2,4); +int PMPI_File_write_ordered_end(MPI_File, const void *, MPI_Status *); + +/* Section 9.5.1 */ +int PMPI_File_get_type_extent(MPI_File, MPI_Datatype, MPI_Aint *); + +/* Section 9.5.3 */ +int PMPI_Register_datarep(const char *, + MPI_Datarep_conversion_function *, + MPI_Datarep_conversion_function *, + MPI_Datarep_extent_function *, + void *); + +/* Section 9.6.1 */ +int PMPI_File_set_atomicity(MPI_File, int); +int PMPI_File_get_atomicity(MPI_File, int *); +int PMPI_File_sync(MPI_File); + +/* Section 4.13.3 */ +#ifndef MPICH +/* MPICH provides these definitions */ +int PMPI_File_set_errhandler( MPI_File, MPI_Errhandler ); +int PMPI_File_get_errhandler( MPI_File, MPI_Errhandler * ); +#endif + +#ifndef HAVE_MPI_DARRAY_SUBARRAY +/* Section 4.14.4 */ +int PMPI_Type_create_subarray(int, int *, int *, int *, int, + MPI_Datatype, MPI_Datatype *); + +/* Section 4.14.5 */ +int PMPI_Type_create_darray(int, int, int, int *, int *, + int *, int *, int, MPI_Datatype, MPI_Datatype *); +#endif + +/* Section 4.12.4 */ +MPI_File PMPI_File_f2c(MPI_Fint); +MPI_Fint PMPI_File_c2f(MPI_File); + +#ifndef HAVE_MPI_GREQUEST +/* The following functions are required if generalized requests are not + available, because in that case, an MPIO_Request object + is currently used for nonblocking I/O. */ +int PMPIO_Test(MPIO_Request *, int *, MPI_Status *); +int PMPIO_Wait(MPIO_Request *, MPI_Status *); +int PMPIO_Testall(int, MPIO_Request *, int *, MPI_Status *); +int PMPIO_Waitall(int, MPIO_Request *, MPI_Status *); +int PMPIO_Testany(int, MPIO_Request *, int *, int *, MPI_Status *); +int PMPIO_Waitany(int, MPIO_Request *, int *, MPI_Status *); +int PMPIO_Waitsome(int, MPIO_Request *, int *, int *, MPI_Status *); +int PMPIO_Testsome(int, MPIO_Request *, int *, int *, MPI_Status *); +MPI_Fint PMPIO_Request_c2f(MPIO_Request); +MPIO_Request PMPIO_Request_f2c(MPI_Fint); +#endif /* HAVE_MPI_GREQUEST */ + +/* info functions if not defined in the MPI implementation */ +#ifndef HAVE_MPI_INFO + +int PMPI_Info_create(MPI_Info *); +int PMPI_Info_set(MPI_Info, char *, char *); +int PMPI_Info_delete(MPI_Info, char *); +int PMPI_Info_get(MPI_Info, char *, int, char *, int *); +int PMPI_Info_get_valuelen(MPI_Info, char *, int *, int *); +int PMPI_Info_get_nkeys(MPI_Info, int *); +int PMPI_Info_get_nthkey(MPI_Info, int, char *); +int PMPI_Info_dup(MPI_Info, MPI_Info *); +int PMPI_Info_free(MPI_Info *); + +MPI_Fint PMPI_Info_c2f(MPI_Info); +MPI_Info PMPI_Info_f2c(MPI_Fint); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/ompi/mca/io/romio314/romio/include/mpiof.h.in b/ompi/mca/io/romio314/romio/include/mpiof.h.in new file mode 100644 index 0000000000..fa945807bd --- /dev/null +++ b/ompi/mca/io/romio314/romio/include/mpiof.h.in @@ -0,0 +1,46 @@ +! +! Copyright (C) 1997 University of Chicago. +! See COPYRIGHT notice in top-level directory. +! +! +! user include file for Fortran MPI-IO programs +! + INTEGER MPI_MODE_RDONLY, MPI_MODE_RDWR, MPI_MODE_WRONLY + INTEGER MPI_MODE_DELETE_ON_CLOSE, MPI_MODE_UNIQUE_OPEN + INTEGER MPI_MODE_CREATE, MPI_MODE_EXCL + INTEGER MPI_MODE_APPEND, MPI_MODE_SEQUENTIAL + PARAMETER (MPI_MODE_RDONLY=2, MPI_MODE_RDWR=8, MPI_MODE_WRONLY=4) + PARAMETER (MPI_MODE_CREATE=1, MPI_MODE_DELETE_ON_CLOSE=16) + PARAMETER (MPI_MODE_UNIQUE_OPEN=32, MPI_MODE_EXCL=64) + PARAMETER (MPI_MODE_APPEND=128, MPI_MODE_SEQUENTIAL=256) +! + INTEGER MPI_FILE_NULL + PARAMETER (MPI_FILE_NULL=0) +! + INTEGER MPI_MAX_DATAREP_STRING + PARAMETER (MPI_MAX_DATAREP_STRING=128) +! + INTEGER MPI_SEEK_SET, MPI_SEEK_CUR, MPI_SEEK_END + PARAMETER (MPI_SEEK_SET=600, MPI_SEEK_CUR=602, MPI_SEEK_END=604) +! + INTEGER MPIO_REQUEST_NULL + PARAMETER (MPIO_REQUEST_NULL=0) +! + @FORTRAN_MPI_OFFSET@ MPI_DISPLACEMENT_CURRENT + PARAMETER (MPI_DISPLACEMENT_CURRENT=-54278278) +! +@MPI_OFFSET_KIND1@ +@MPI_OFFSET_KIND2@ +! +@MPI_FARRAY1@ +@MPI_FARRAY2@ +@MPI_FARRAY3@ +@MPI_FARRAY4@ +@MPI_FARRAY5@ +@MPI_FARRAY6@ +@MPI_FARRAY7@ +! +@MPI_FINFO1@ +@MPI_FINFO2@ +@MPI_FINFO3@ +@MPI_FINFO4@ diff --git a/ompi/mca/io/romio314/romio/localdefs.in b/ompi/mca/io/romio314/romio/localdefs.in new file mode 100644 index 0000000000..bf057d198a --- /dev/null +++ b/ompi/mca/io/romio314/romio/localdefs.in @@ -0,0 +1,7 @@ +#! /bin/sh + +# Append ROMIO library dependencies to the global list +EXTERNAL_LIBS="$EXTERNAL_LIBS @LIBS@" + +MPI_OFFSET_TYPE="@MPI_OFFSET_TYPE@" +FORTRAN_MPI_OFFSET="@FORTRAN_MPI_OFFSET@" diff --git a/ompi/mca/io/romio314/romio/mpi-io/Makefile.mk b/ompi/mca/io/romio314/romio/mpi-io/Makefile.mk new file mode 100644 index 0000000000..b917fadc09 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/Makefile.mk @@ -0,0 +1,104 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +include $(top_srcdir)/mpi-io/glue/Makefile.mk +include $(top_srcdir)/mpi-io/fortran/Makefile.mk + +AM_CPPFLAGS += -I$(top_builddir)/mpi-io -I$(top_srcdir)/mpi-io +noinst_HEADERS += mpi-io/mpioimpl.h mpi-io/mpioprof.h + +romio_mpi_sources += \ + mpi-io/close.c \ + mpi-io/delete.c \ + mpi-io/file_c2f.c \ + mpi-io/file_f2c.c \ + mpi-io/fsync.c \ + mpi-io/get_amode.c \ + mpi-io/get_atom.c \ + mpi-io/get_bytoff.c \ + mpi-io/get_extent.c \ + mpi-io/get_group.c \ + mpi-io/get_info.c \ + mpi-io/get_posn.c \ + mpi-io/get_posn_sh.c \ + mpi-io/get_size.c \ + mpi-io/get_view.c \ + mpi-io/iread.c \ + mpi-io/iread_at.c \ + mpi-io/iread_sh.c \ + mpi-io/iwrite.c \ + mpi-io/iwrite_at.c \ + mpi-io/iwrite_sh.c \ + mpi-io/open.c \ + mpi-io/prealloc.c \ + mpi-io/rd_atallb.c \ + mpi-io/rd_atalle.c \ + mpi-io/read.c \ + mpi-io/read_all.c \ + mpi-io/read_allb.c \ + mpi-io/read_alle.c \ + mpi-io/read_at.c \ + mpi-io/read_atall.c \ + mpi-io/read_ord.c \ + mpi-io/read_ordb.c \ + mpi-io/read_orde.c \ + mpi-io/read_sh.c \ + mpi-io/register_datarep.c \ + mpi-io/seek.c \ + mpi-io/seek_sh.c \ + mpi-io/set_atom.c \ + mpi-io/set_info.c \ + mpi-io/set_size.c \ + mpi-io/set_view.c \ + mpi-io/wr_atallb.c \ + mpi-io/wr_atalle.c \ + mpi-io/write.c \ + mpi-io/write_all.c \ + mpi-io/write_allb.c \ + mpi-io/write_alle.c \ + mpi-io/write_at.c \ + mpi-io/write_atall.c \ + mpi-io/write_ord.c \ + mpi-io/write_ordb.c \ + mpi-io/write_orde.c \ + mpi-io/write_sh.c + + +# non-MPI/PMPI sources that will be included in libromio +romio_other_sources += \ + mpi-io/mpich_fileutil.c \ + mpi-io/mpir-mpioinit.c \ + mpi-io/mpiu_greq.c \ + mpi-io/mpiu_external32.c + +# helper variables for conditionally compiled sources +mpio_request_sources= \ + mpi-io/ioreq_c2f.c \ + mpi-io/ioreq_f2c.c \ + mpi-io/iotest.c \ + mpi-io/iotestall.c \ + mpi-io/iotestany.c \ + mpi-io/iotestsome.c \ + mpi-io/iowait.c \ + mpi-io/iowaitall.c \ + mpi-io/iowaitany.c \ + mpi-io/iowaitsome.c + +mpio_extra_sources = \ + mpi-io/get_errh.c \ + mpi-io/set_errh.c + +# not used in MPICH, we use generalized requests instead +if BUILD_MPIO_REQUEST +romio_other_sources += $(mpio_request_sources) +endif BUILD_MPIO_REQUEST + +# not used in MPICH +if BUILD_MPIO_ERRHAN +romio_other_sources += $(mpio_request_sources) +endif BUILD_MPIO_ERRHAN + diff --git a/ompi/mca/io/romio314/romio/mpi-io/close.c b/ompi/mca/io/romio314/romio/mpi-io/close.c new file mode 100644 index 0000000000..520f206cd0 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/close.c @@ -0,0 +1,100 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_close = PMPI_File_close +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_close MPI_File_close +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_close as PMPI_File_close +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_close(MPI_File *fh) __attribute__((weak,alias("PMPI_File_close"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_close - Closes a file + +Input Parameters: +. fh - file handle (handle) + +.N fortran +@*/ +int MPI_File_close(MPI_File *fh) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_CLOSE"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_WSTART(fl_xmpi, BLKMPIFILECLOSE, TRDTBLOCK, *adio_fh); +#endif /* MPI_hpux */ + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(*fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + if (ADIO_Feature(adio_fh, ADIO_SHARED_FP)) + { + ADIOI_Free((adio_fh)->shared_fp_fname); + /* POSIX semantics say a deleted file remains available until all + * processes close the file. But since when was NFS posix-compliant? + */ + /* this used to be gated by the lack of the UNLINK_AFTER_CLOSE feature, + * but a race condition in GPFS necessated this. See ticket #2214 */ + MPI_Barrier((adio_fh)->comm); + if ((adio_fh)->shared_fp_fd != ADIO_FILE_NULL) { + MPI_File *fh_shared = &(adio_fh->shared_fp_fd); + ADIO_Close((adio_fh)->shared_fp_fd, &error_code); + MPIO_File_free(fh_shared); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) goto fn_fail; + /* --END ERROR HANDLING-- */ + } + } + + /* Because ROMIO expects the MPI library to provide error handler management + * routines but it doesn't ever participate in MPI_File_close, we have to + * somehow inform the MPI library that we no longer hold a reference to any + * user defined error handler. We do this by setting the errhandler at this + * point to MPI_ERRORS_RETURN. */ + error_code = PMPI_File_set_errhandler(*fh, MPI_ERRORS_RETURN); + if (error_code != MPI_SUCCESS) goto fn_fail; + + ADIO_Close(adio_fh, &error_code); + MPIO_File_free(fh); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) goto fn_fail; + /* --END ERROR HANDLING-- */ + +#ifdef MPI_hpux + HPMP_IO_WEND(fl_xmpi); +#endif /* MPI_hpux */ + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +fn_fail: + /* --BEGIN ERROR HANDLING-- */ + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + /* --END ERROR HANDLING-- */ +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/delete.c b/ompi/mca/io/romio314/romio/mpi-io/delete.c new file mode 100644 index 0000000000..7335136d83 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/delete.c @@ -0,0 +1,95 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_delete = PMPI_File_delete +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_delete MPI_File_delete +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_delete as PMPI_File_delete +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_delete(const char *filename, MPI_Info info) __attribute__((weak,alias("PMPI_File_delete"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_delete - Deletes a file + +Input Parameters: +. filename - name of file to delete (string) +. info - info object (handle) + +.N fortran +@*/ +int MPI_File_delete(ROMIO_CONST char *filename, MPI_Info info) +{ + int error_code, file_system; + char *tmp; + ADIOI_Fns *fsops; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEDELETE, TRDTBLOCK, + MPI_FILE_NULL, MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + + MPIU_UNREFERENCED_ARG(info); + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + MPIR_MPIOInit(&error_code); + if (error_code != MPI_SUCCESS) goto fn_exit; + + /* resolve file system type from file name; this is a collective call */ + ADIO_ResolveFileType(MPI_COMM_SELF, filename, &file_system, &fsops, + &error_code); + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + { + /* ADIO_ResolveFileType() will print as informative a message as it + * possibly can or call MPIR_Err_setmsg. We just need to propagate + * the error up. In the PRINT_ERR_MSG case MPI_Abort has already + * been called as well, so we probably didn't even make it this far. + */ + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + /* skip prefixes on file names if they have more than one character; + * single-character prefixes are assumed to be windows drive + * specifications (e.g. c:\foo) and are left alone. + */ + tmp = strchr(filename, ':'); + if (tmp > filename + 1) + filename = tmp + 1; + + /* call the fs-specific delete function */ + (fsops->ADIOI_xxx_Delete)(filename, &error_code); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + /* --END ERROR HANDLING-- */ + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, MPI_FILE_NULL, MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/file_c2f.c b/ompi/mca/io/romio314/romio/mpi-io/file_c2f.c new file mode 100644 index 0000000000..4eaae9fafa --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/file_c2f.c @@ -0,0 +1,41 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_c2f = PMPI_File_c2f +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_c2f MPI_File_c2f +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_c2f as PMPI_File_c2f +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +MPI_Fint MPI_File_c2f(MPI_File fh) __attribute__((weak,alias("PMPI_File_c2f"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif +#include "adio_extern.h" + +/*@ + MPI_File_c2f - Translates a C file handle to a Fortran file handle + +Input Parameters: +. fh - C file handle (handle) + +Return Value: + Fortran file handle (integer) +@*/ +MPI_Fint MPI_File_c2f(MPI_File fh) +{ + return MPIO_File_c2f(fh); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/file_f2c.c b/ompi/mca/io/romio314/romio/mpi-io/file_f2c.c new file mode 100644 index 0000000000..b6b4896b38 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/file_f2c.c @@ -0,0 +1,41 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_f2c = PMPI_File_f2c +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_f2c MPI_File_f2c +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_f2c as PMPI_File_f2c +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +MPI_File MPI_File_f2c(MPI_Fint fh) __attribute__((weak,alias("PMPI_File_f2c"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif +#include "adio_extern.h" + +/*@ + MPI_File_f2c - Translates a Fortran file handle to a C file handle + +Input Parameters: +. fh - Fortran file handle (integer) + +Return Value: + C file handle (handle) +@*/ +MPI_File MPI_File_f2c(MPI_Fint fh) +{ + return MPIO_File_f2c(fh); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/Makefile.mk b/ompi/mca/io/romio314/romio/mpi-io/fortran/Makefile.mk new file mode 100644 index 0000000000..f7ed72b69b --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/Makefile.mk @@ -0,0 +1,68 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if BUILD_F77_BINDINGS + +romio_mpi_sources += \ + mpi-io/fortran/closef.c \ + mpi-io/fortran/deletef.c \ + mpi-io/fortran/fsyncf.c \ + mpi-io/fortran/get_amodef.c \ + mpi-io/fortran/get_atomf.c \ + mpi-io/fortran/get_bytofff.c \ + mpi-io/fortran/get_errhf.c \ + mpi-io/fortran/get_extentf.c \ + mpi-io/fortran/get_groupf.c \ + mpi-io/fortran/get_infof.c \ + mpi-io/fortran/get_posn_shf.c \ + mpi-io/fortran/get_posnf.c \ + mpi-io/fortran/get_sizef.c \ + mpi-io/fortran/get_viewf.c \ + mpi-io/fortran/iotestf.c \ + mpi-io/fortran/iowaitf.c \ + mpi-io/fortran/iread_atf.c \ + mpi-io/fortran/iread_shf.c \ + mpi-io/fortran/ireadf.c \ + mpi-io/fortran/iwrite_atf.c \ + mpi-io/fortran/iwrite_shf.c \ + mpi-io/fortran/iwritef.c \ + mpi-io/fortran/openf.c \ + mpi-io/fortran/preallocf.c \ + mpi-io/fortran/rd_atallbf.c \ + mpi-io/fortran/rd_atallef.c \ + mpi-io/fortran/read_allbf.c \ + mpi-io/fortran/read_allef.c \ + mpi-io/fortran/read_allf.c \ + mpi-io/fortran/read_atallf.c \ + mpi-io/fortran/read_atf.c \ + mpi-io/fortran/read_ordbf.c \ + mpi-io/fortran/read_ordef.c \ + mpi-io/fortran/read_ordf.c \ + mpi-io/fortran/read_shf.c \ + mpi-io/fortran/readf.c \ + mpi-io/fortran/seek_shf.c \ + mpi-io/fortran/seekf.c \ + mpi-io/fortran/set_atomf.c \ + mpi-io/fortran/set_errhf.c \ + mpi-io/fortran/set_infof.c \ + mpi-io/fortran/set_sizef.c \ + mpi-io/fortran/set_viewf.c \ + mpi-io/fortran/wr_atallbf.c \ + mpi-io/fortran/wr_atallef.c \ + mpi-io/fortran/write_allbf.c \ + mpi-io/fortran/write_allef.c \ + mpi-io/fortran/write_allf.c \ + mpi-io/fortran/write_atallf.c \ + mpi-io/fortran/write_atf.c \ + mpi-io/fortran/write_ordbf.c \ + mpi-io/fortran/write_ordef.c \ + mpi-io/fortran/write_ordf.c \ + mpi-io/fortran/write_shf.c \ + mpi-io/fortran/writef.c + +endif BUILD_F77_BINDINGS + diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/closef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/closef.c new file mode 100644 index 0000000000..aebdf56a61 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/closef.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_CLOSE( MPI_File*, MPI_Fint * ); +#pragma weak MPI_FILE_CLOSE = PMPI_FILE_CLOSE +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_close__( MPI_File*, MPI_Fint * ); +#pragma weak mpi_file_close__ = pmpi_file_close__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_close( MPI_File*, MPI_Fint * ); +#pragma weak mpi_file_close = pmpi_file_close +#else +extern FORTRAN_API void FORT_CALL mpi_file_close_( MPI_File*, MPI_Fint * ); +#pragma weak mpi_file_close_ = pmpi_file_close_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_CLOSE MPI_FILE_CLOSE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_close__ mpi_file_close__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_close mpi_file_close +#else +#pragma _HP_SECONDARY_DEF pmpi_file_close_ mpi_file_close_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_CLOSE as PMPI_FILE_CLOSE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_close__ as pmpi_file_close__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_close as pmpi_file_close +#else +#pragma _CRI duplicate mpi_file_close_ as pmpi_file_close_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_close_ PMPI_FILE_CLOSE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_close_ pmpi_file_close__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_close pmpi_file_close_ +#endif +#define mpi_file_close_ pmpi_file_close +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_close_ pmpi_file_close +#endif +#define mpi_file_close_ pmpi_file_close_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_close_ MPI_FILE_CLOSE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_close_ mpi_file_close__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_close mpi_file_close_ +#endif +#define mpi_file_close_ mpi_file_close +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_close_ mpi_file_close +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_close_(MPI_Fint *fh, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_close_(MPI_Fint *fh, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_close(&fh_c); + *fh = MPI_File_c2f(fh_c); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/deletef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/deletef.c new file mode 100644 index 0000000000..660129f760 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/deletef.c @@ -0,0 +1,144 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifdef _UNICOS +#include +#endif +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_DELETE( char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak MPI_FILE_DELETE = PMPI_FILE_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_delete__( char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_delete__ = pmpi_file_delete__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_delete( char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_delete = pmpi_file_delete +#else +extern FORTRAN_API void FORT_CALL mpi_file_delete_( char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_delete_ = pmpi_file_delete_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_DELETE MPI_FILE_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_delete__ mpi_file_delete__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_delete mpi_file_delete +#else +#pragma _HP_SECONDARY_DEF pmpi_file_delete_ mpi_file_delete_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_DELETE as PMPI_FILE_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_delete__ as pmpi_file_delete__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_delete as pmpi_file_delete +#else +#pragma _CRI duplicate mpi_file_delete_ as pmpi_file_delete_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_delete_ PMPI_FILE_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_delete_ pmpi_file_delete__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_delete pmpi_file_delete_ +#endif +#define mpi_file_delete_ pmpi_file_delete +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_delete_ pmpi_file_delete +#endif +#define mpi_file_delete_ pmpi_file_delete_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_delete_ MPI_FILE_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_delete_ mpi_file_delete__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_delete mpi_file_delete_ +#endif +#define mpi_file_delete_ mpi_file_delete +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_delete_ mpi_file_delete +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +/* +FORTRAN_API void FORT_CALL mpi_file_delete_(char *filename, MPI_Fint *info, MPI_Fint *ierr, int str_len); + +#ifdef _UNICOS +void mpi_file_delete_(_fcd filename_fcd, MPI_Fint *info, MPI_Fint *ierr) +{ + char *filename = _fcdtocp(filename_fcd); + int str_len = _fcdlen(filename_fcd); +#else +FORTRAN_API void FORT_CALL mpi_file_delete_(char *filename, MPI_Fint *info, MPI_Fint *ierr, int str_len) +*/ +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_delete_(char *filename FORT_MIXED_LEN_DECL, MPI_Fint *info, MPI_Fint *ierr FORT_END_LEN_DECL); + +#ifdef _UNICOS +void mpi_file_delete_(_fcd filename_fcd, MPI_Fint *info, MPI_Fint *ierr) +{ + char *filename = _fcdtocp(filename_fcd); + int str_len = _fcdlen(filename_fcd); +#else +FORTRAN_API void FORT_CALL mpi_file_delete_(char *filename FORT_MIXED_LEN(str_len), MPI_Fint *info, MPI_Fint *ierr FORT_END_LEN(str_len)) +{ +#endif + char *newfname; + int real_len, i; + MPI_Info info_c; + + info_c = MPI_Info_f2c(*info); + + /* strip trailing blanks */ + if (filename <= (char *) 0) { + FPRINTF(stderr, "MPI_File_delete: filename is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + for (i=str_len-1; i>=0; i--) if (filename[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_File_delete: filename is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + real_len = i + 1; + + newfname = (char *) ADIOI_Malloc((real_len+1)*sizeof(char)); + ADIOI_Strncpy(newfname, filename, real_len); + newfname[real_len] = '\0'; + + *ierr = MPI_File_delete(newfname, info_c); + + ADIOI_Free(newfname); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/fsyncf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/fsyncf.c new file mode 100644 index 0000000000..b52245256b --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/fsyncf.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_SYNC( MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_SYNC = PMPI_FILE_SYNC +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_sync__( MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_sync__ = pmpi_file_sync__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_sync( MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_sync = pmpi_file_sync +#else +extern FORTRAN_API void FORT_CALL mpi_file_sync_( MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_sync_ = pmpi_file_sync_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_SYNC MPI_FILE_SYNC +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_sync__ mpi_file_sync__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_sync mpi_file_sync +#else +#pragma _HP_SECONDARY_DEF pmpi_file_sync_ mpi_file_sync_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_SYNC as PMPI_FILE_SYNC +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_sync__ as pmpi_file_sync__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_sync as pmpi_file_sync +#else +#pragma _CRI duplicate mpi_file_sync_ as pmpi_file_sync_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_sync_ PMPI_FILE_SYNC +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_sync_ pmpi_file_sync__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_sync pmpi_file_sync_ +#endif +#define mpi_file_sync_ pmpi_file_sync +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_sync_ pmpi_file_sync +#endif +#define mpi_file_sync_ pmpi_file_sync_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_sync_ MPI_FILE_SYNC +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_sync_ mpi_file_sync__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_sync mpi_file_sync_ +#endif +#define mpi_file_sync_ mpi_file_sync +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_sync_ mpi_file_sync +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_sync_(MPI_Fint *fh, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_sync_(MPI_Fint *fh, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_sync(fh_c); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_amodef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_amodef.c new file mode 100644 index 0000000000..2427f06831 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_amodef.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_AMODE( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_GET_AMODE = PMPI_FILE_GET_AMODE +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_amode__( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_amode__ = pmpi_file_get_amode__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_amode( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_amode = pmpi_file_get_amode +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_amode_( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_amode_ = pmpi_file_get_amode_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_AMODE MPI_FILE_GET_AMODE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_amode__ mpi_file_get_amode__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_amode mpi_file_get_amode +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_amode_ mpi_file_get_amode_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_AMODE as PMPI_FILE_GET_AMODE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_amode__ as pmpi_file_get_amode__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_amode as pmpi_file_get_amode +#else +#pragma _CRI duplicate mpi_file_get_amode_ as pmpi_file_get_amode_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_amode_ PMPI_FILE_GET_AMODE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_amode_ pmpi_file_get_amode__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_amode pmpi_file_get_amode_ +#endif +#define mpi_file_get_amode_ pmpi_file_get_amode +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_amode_ pmpi_file_get_amode +#endif +#define mpi_file_get_amode_ pmpi_file_get_amode_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_amode_ MPI_FILE_GET_AMODE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_amode_ mpi_file_get_amode__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_amode mpi_file_get_amode_ +#endif +#define mpi_file_get_amode_ mpi_file_get_amode +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_amode_ mpi_file_get_amode +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_amode_(MPI_Fint *fh, MPI_Fint *amode, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_get_amode_(MPI_Fint *fh, MPI_Fint *amode, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_amode(fh_c, amode); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_atomf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_atomf.c new file mode 100644 index 0000000000..98bf557e34 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_atomf.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_ATOMICITY( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_GET_ATOMICITY = PMPI_FILE_GET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_atomicity__( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_atomicity__ = pmpi_file_get_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_atomicity( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_atomicity = pmpi_file_get_atomicity +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_atomicity_( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_atomicity_ = pmpi_file_get_atomicity_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_ATOMICITY MPI_FILE_GET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_atomicity__ mpi_file_get_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_atomicity mpi_file_get_atomicity +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_atomicity_ mpi_file_get_atomicity_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_ATOMICITY as PMPI_FILE_GET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_atomicity__ as pmpi_file_get_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_atomicity as pmpi_file_get_atomicity +#else +#pragma _CRI duplicate mpi_file_get_atomicity_ as pmpi_file_get_atomicity_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_atomicity_ PMPI_FILE_GET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_atomicity_ pmpi_file_get_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_atomicity pmpi_file_get_atomicity_ +#endif +#define mpi_file_get_atomicity_ pmpi_file_get_atomicity +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_atomicity_ pmpi_file_get_atomicity +#endif +#define mpi_file_get_atomicity_ pmpi_file_get_atomicity_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_atomicity_ MPI_FILE_GET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_atomicity_ mpi_file_get_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_atomicity mpi_file_get_atomicity_ +#endif +#define mpi_file_get_atomicity_ mpi_file_get_atomicity +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_atomicity_ mpi_file_get_atomicity +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_atomicity_(MPI_Fint *fh, MPI_Fint *flag, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_get_atomicity_(MPI_Fint *fh, MPI_Fint *flag, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_atomicity(fh_c, flag); +} + diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_bytofff.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_bytofff.c new file mode 100644 index 0000000000..fb38b7be4c --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_bytofff.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_BYTE_OFFSET( MPI_Fint *, MPI_Offset *, MPI_Offset*, MPI_Fint * ); +#pragma weak MPI_FILE_GET_BYTE_OFFSET = PMPI_FILE_GET_BYTE_OFFSET +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_byte_offset__( MPI_Fint *, MPI_Offset *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_byte_offset__ = pmpi_file_get_byte_offset__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_byte_offset( MPI_Fint *, MPI_Offset *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_byte_offset = pmpi_file_get_byte_offset +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_byte_offset_( MPI_Fint *, MPI_Offset *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_byte_offset_ = pmpi_file_get_byte_offset_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_BYTE_OFFSET MPI_FILE_GET_BYTE_OFFSET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_byte_offset__ mpi_file_get_byte_offset__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_byte_offset mpi_file_get_byte_offset +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_byte_offset_ mpi_file_get_byte_offset_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_BYTE_OFFSET as PMPI_FILE_GET_BYTE_OFFSET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_byte_offset__ as pmpi_file_get_byte_offset__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_byte_offset as pmpi_file_get_byte_offset +#else +#pragma _CRI duplicate mpi_file_get_byte_offset_ as pmpi_file_get_byte_offset_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_byte_offset_ PMPI_FILE_GET_BYTE_OFFSET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_byte_offset_ pmpi_file_get_byte_offset__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_byte_offset pmpi_file_get_byte_offset_ +#endif +#define mpi_file_get_byte_offset_ pmpi_file_get_byte_offset +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_byte_offset_ pmpi_file_get_byte_offset +#endif +#define mpi_file_get_byte_offset_ pmpi_file_get_byte_offset_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_byte_offset_ MPI_FILE_GET_BYTE_OFFSET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_byte_offset_ mpi_file_get_byte_offset__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_byte_offset mpi_file_get_byte_offset_ +#endif +#define mpi_file_get_byte_offset_ mpi_file_get_byte_offset +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_byte_offset_ mpi_file_get_byte_offset +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_byte_offset_(MPI_Fint *fh, MPI_Offset *offset, MPI_Offset *disp, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_get_byte_offset_(MPI_Fint *fh,MPI_Offset *offset, MPI_Offset *disp, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_byte_offset(fh_c,*offset,disp); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_errhf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_errhf.c new file mode 100644 index 0000000000..96901ad776 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_errhf.c @@ -0,0 +1,103 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_ERRHANDLER( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_GET_ERRHANDLER = PMPI_FILE_GET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_errhandler__( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_errhandler__ = pmpi_file_get_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_errhandler( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_errhandler = pmpi_file_get_errhandler +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_errhandler_( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_errhandler_ = pmpi_file_get_errhandler_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_ERRHANDLER MPI_FILE_GET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_errhandler__ mpi_file_get_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_errhandler mpi_file_get_errhandler +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_errhandler_ mpi_file_get_errhandler_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_ERRHANDLER as PMPI_FILE_GET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_errhandler__ as pmpi_file_get_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_errhandler as pmpi_file_get_errhandler +#else +#pragma _CRI duplicate mpi_file_get_errhandler_ as pmpi_file_get_errhandler_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_errhandler_ PMPI_FILE_GET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_errhandler_ pmpi_file_get_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_errhandler pmpi_file_get_errhandler_ +#endif +#define mpi_file_get_errhandler_ pmpi_file_get_errhandler +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_errhandler_ pmpi_file_get_errhandler +#endif +#define mpi_file_get_errhandler_ pmpi_file_get_errhandler_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_errhandler_ MPI_FILE_GET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_errhandler_ mpi_file_get_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_errhandler mpi_file_get_errhandler_ +#endif +#define mpi_file_get_errhandler_ mpi_file_get_errhandler +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_errhandler_ mpi_file_get_errhandler +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_errhandler_(MPI_Fint *fh, MPI_Fint *err_handler, MPI_Fint *ierr); + +FORTRAN_API void FORT_CALL mpi_file_get_errhandler_(MPI_Fint *fh, MPI_Fint *err_handler, MPI_Fint *ierr) +{ + MPI_File fh_c; + MPI_Errhandler err_handler_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_errhandler(fh_c, &err_handler_c); + *err_handler = MPI_Errhandler_c2f(err_handler_c); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_extentf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_extentf.c new file mode 100644 index 0000000000..9a11d3c946 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_extentf.c @@ -0,0 +1,126 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_TYPE_EXTENT( MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak MPI_FILE_GET_TYPE_EXTENT = PMPI_FILE_GET_TYPE_EXTENT +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_type_extent__( MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_get_type_extent__ = pmpi_file_get_type_extent__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_type_extent( MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_get_type_extent = pmpi_file_get_type_extent +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_type_extent_( MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_get_type_extent_ = pmpi_file_get_type_extent_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_TYPE_EXTENT MPI_FILE_GET_TYPE_EXTENT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_type_extent__ mpi_file_get_type_extent__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_type_extent mpi_file_get_type_extent +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_type_extent_ mpi_file_get_type_extent_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_TYPE_EXTENT as PMPI_FILE_GET_TYPE_EXTENT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_type_extent__ as pmpi_file_get_type_extent__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_type_extent as pmpi_file_get_type_extent +#else +#pragma _CRI duplicate mpi_file_get_type_extent_ as pmpi_file_get_type_extent_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_type_extent_ PMPI_FILE_GET_TYPE_EXTENT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_type_extent_ pmpi_file_get_type_extent__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_type_extent pmpi_file_get_type_extent_ +#endif +#define mpi_file_get_type_extent_ pmpi_file_get_type_extent +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_type_extent_ pmpi_file_get_type_extent +#endif +#define mpi_file_get_type_extent_ pmpi_file_get_type_extent_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_type_extent_ MPI_FILE_GET_TYPE_EXTENT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_type_extent_ mpi_file_get_type_extent__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_type_extent mpi_file_get_type_extent_ +#endif +#define mpi_file_get_type_extent_ mpi_file_get_type_extent +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_type_extent_ mpi_file_get_type_extent +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_get_type_extent_(MPI_Fint *fh,MPI_Fint *datatype, + MPI_Fint *extent, MPI_Fint *ierr ); + +void mpi_file_get_type_extent_(MPI_Fint *fh,MPI_Fint *datatype, + MPI_Fint *extent, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + MPI_Aint extent_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_get_type_extent(fh_c,datatype_c, &extent_c); + *(MPI_Aint*)extent = extent_c; /* Have to assume it's really an MPI_Aint?*/ +} + +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_type_extent_(MPI_Fint *fh,MPI_Datatype *datatype, + MPI_Fint *extent, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_get_type_extent_(MPI_Fint *fh,MPI_Datatype *datatype, + MPI_Fint *extent, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Aint extent_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_type_extent(fh_c,*datatype, &extent_c); + *(MPI_Aint*)extent = extent_c; /* Have to assume it's really an MPI_Aint?*/ +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_groupf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_groupf.c new file mode 100644 index 0000000000..bb8c9a9cba --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_groupf.c @@ -0,0 +1,116 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_GROUP( MPI_Fint *, MPI_Group*, MPI_Fint * ); +#pragma weak MPI_FILE_GET_GROUP = PMPI_FILE_GET_GROUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_group__( MPI_Fint *, MPI_Group*, MPI_Fint * ); +#pragma weak mpi_file_get_group__ = pmpi_file_get_group__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_group( MPI_Fint *, MPI_Group*, MPI_Fint * ); +#pragma weak mpi_file_get_group = pmpi_file_get_group +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_group_( MPI_Fint *, MPI_Group*, MPI_Fint * ); +#pragma weak mpi_file_get_group_ = pmpi_file_get_group_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_GROUP MPI_FILE_GET_GROUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_group__ mpi_file_get_group__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_group mpi_file_get_group +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_group_ mpi_file_get_group_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_GROUP as PMPI_FILE_GET_GROUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_group__ as pmpi_file_get_group__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_group as pmpi_file_get_group +#else +#pragma _CRI duplicate mpi_file_get_group_ as pmpi_file_get_group_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_group_ PMPI_FILE_GET_GROUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_group_ pmpi_file_get_group__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_group pmpi_file_get_group_ +#endif +#define mpi_file_get_group_ pmpi_file_get_group +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_group_ pmpi_file_get_group +#endif +#define mpi_file_get_group_ pmpi_file_get_group_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_group_ MPI_FILE_GET_GROUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_group_ mpi_file_get_group__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_group mpi_file_get_group_ +#endif +#define mpi_file_get_group_ mpi_file_get_group +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_group_ mpi_file_get_group +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_get_group_(MPI_Fint *fh, MPI_Fint *group, MPI_Fint *ierr ); + +void mpi_file_get_group_(MPI_Fint *fh, MPI_Fint *group, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Group group_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_group(fh_c, &group_c); + *group = MPI_Group_c2f(group_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_group_(MPI_Fint *fh,MPI_Group *group, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_get_group_(MPI_Fint *fh,MPI_Group *group, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_group(fh_c, group); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_infof.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_infof.c new file mode 100644 index 0000000000..eb2ba551a4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_infof.c @@ -0,0 +1,104 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_INFO( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_GET_INFO = PMPI_FILE_GET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_info__( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_info__ = pmpi_file_get_info__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_info( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_info = pmpi_file_get_info +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_info_( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_get_info_ = pmpi_file_get_info_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_INFO MPI_FILE_GET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_info__ mpi_file_get_info__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_info mpi_file_get_info +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_info_ mpi_file_get_info_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_INFO as PMPI_FILE_GET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_info__ as pmpi_file_get_info__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_info as pmpi_file_get_info +#else +#pragma _CRI duplicate mpi_file_get_info_ as pmpi_file_get_info_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_info_ PMPI_FILE_GET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_info_ pmpi_file_get_info__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_info pmpi_file_get_info_ +#endif +#define mpi_file_get_info_ pmpi_file_get_info +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_info_ pmpi_file_get_info +#endif +#define mpi_file_get_info_ pmpi_file_get_info_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_info_ MPI_FILE_GET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_info_ mpi_file_get_info__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_info mpi_file_get_info_ +#endif +#define mpi_file_get_info_ mpi_file_get_info +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_info_ mpi_file_get_info +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_info_(MPI_Fint *fh, MPI_Fint *info_used, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_get_info_(MPI_Fint *fh, MPI_Fint *info_used, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Info info_used_c; + + fh_c = MPI_File_f2c(*fh); + + *ierr = MPI_File_get_info(fh_c, &info_used_c); + *info_used = MPI_Info_c2f(info_used_c); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_posn_shf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_posn_shf.c new file mode 100644 index 0000000000..8f5bff5c06 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_posn_shf.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_POSITION_SHARED( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak MPI_FILE_GET_POSITION_SHARED = PMPI_FILE_GET_POSITION_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_position_shared__( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_position_shared__ = pmpi_file_get_position_shared__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_position_shared( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_position_shared = pmpi_file_get_position_shared +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_position_shared_( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_position_shared_ = pmpi_file_get_position_shared_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_POSITION_SHARED MPI_FILE_GET_POSITION_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_position_shared__ mpi_file_get_position_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_position_shared mpi_file_get_position_shared +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_position_shared_ mpi_file_get_position_shared_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_POSITION_SHARED as PMPI_FILE_GET_POSITION_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_position_shared__ as pmpi_file_get_position_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_position_shared as pmpi_file_get_position_shared +#else +#pragma _CRI duplicate mpi_file_get_position_shared_ as pmpi_file_get_position_shared_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_position_shared_ PMPI_FILE_GET_POSITION_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_position_shared_ pmpi_file_get_position_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_position_shared pmpi_file_get_position_shared_ +#endif +#define mpi_file_get_position_shared_ pmpi_file_get_position_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_position_shared_ pmpi_file_get_position_shared +#endif +#define mpi_file_get_position_shared_ pmpi_file_get_position_shared_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_position_shared_ MPI_FILE_GET_POSITION_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_position_shared_ mpi_file_get_position_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_position_shared mpi_file_get_position_shared_ +#endif +#define mpi_file_get_position_shared_ mpi_file_get_position_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_position_shared_ mpi_file_get_position_shared +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_position_shared_(MPI_Fint *fh, MPI_Offset *offset, + MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_get_position_shared_(MPI_Fint *fh, MPI_Offset *offset, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_position_shared(fh_c, offset); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_posnf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_posnf.c new file mode 100644 index 0000000000..e21f37674a --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_posnf.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_POSITION( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak MPI_FILE_GET_POSITION = PMPI_FILE_GET_POSITION +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_position__( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_position__ = pmpi_file_get_position__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_position( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_position = pmpi_file_get_position +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_position_( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_position_ = pmpi_file_get_position_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_POSITION MPI_FILE_GET_POSITION +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_position__ mpi_file_get_position__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_position mpi_file_get_position +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_position_ mpi_file_get_position_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_POSITION as PMPI_FILE_GET_POSITION +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_position__ as pmpi_file_get_position__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_position as pmpi_file_get_position +#else +#pragma _CRI duplicate mpi_file_get_position_ as pmpi_file_get_position_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_position_ PMPI_FILE_GET_POSITION +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_position_ pmpi_file_get_position__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_position pmpi_file_get_position_ +#endif +#define mpi_file_get_position_ pmpi_file_get_position +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_position_ pmpi_file_get_position +#endif +#define mpi_file_get_position_ pmpi_file_get_position_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_position_ MPI_FILE_GET_POSITION +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_position_ mpi_file_get_position__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_position mpi_file_get_position_ +#endif +#define mpi_file_get_position_ mpi_file_get_position +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_position_ mpi_file_get_position +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_position_(MPI_Fint *fh, MPI_Offset *offset, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_get_position_(MPI_Fint *fh, MPI_Offset *offset, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_position(fh_c, offset); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_sizef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_sizef.c new file mode 100644 index 0000000000..71ff17bb56 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_sizef.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_SIZE( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak MPI_FILE_GET_SIZE = PMPI_FILE_GET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_size__( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_size__ = pmpi_file_get_size__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_size( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_size = pmpi_file_get_size +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_size_( MPI_Fint *, MPI_Offset*, MPI_Fint * ); +#pragma weak mpi_file_get_size_ = pmpi_file_get_size_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_SIZE MPI_FILE_GET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_size__ mpi_file_get_size__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_size mpi_file_get_size +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_size_ mpi_file_get_size_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_SIZE as PMPI_FILE_GET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_size__ as pmpi_file_get_size__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_size as pmpi_file_get_size +#else +#pragma _CRI duplicate mpi_file_get_size_ as pmpi_file_get_size_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_size_ PMPI_FILE_GET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_size_ pmpi_file_get_size__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_size pmpi_file_get_size_ +#endif +#define mpi_file_get_size_ pmpi_file_get_size +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_size_ pmpi_file_get_size +#endif +#define mpi_file_get_size_ pmpi_file_get_size_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_size_ MPI_FILE_GET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_size_ mpi_file_get_size__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_size mpi_file_get_size_ +#endif +#define mpi_file_get_size_ mpi_file_get_size +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_size_ mpi_file_get_size +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_get_size_(MPI_Fint *fh, MPI_Offset *size, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_get_size_(MPI_Fint *fh, MPI_Offset *size, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_size(fh_c, size); +} + diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/get_viewf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_viewf.c new file mode 100644 index 0000000000..8a4bc3d7fb --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/get_viewf.c @@ -0,0 +1,187 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifdef _UNICOS +#include +#endif +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_GET_VIEW( MPI_Fint *, MPI_Offset*, MPI_Fint*, MPI_Fint*, char * FORT_MIXED_LEN_DECL, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak MPI_FILE_GET_VIEW = PMPI_FILE_GET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_view__( MPI_Fint *, MPI_Offset*, MPI_Fint*, MPI_Fint*, char * FORT_MIXED_LEN_DECL, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_get_view__ = pmpi_file_get_view__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_get_view( MPI_Fint *, MPI_Offset*, MPI_Fint*, MPI_Fint*, char * FORT_MIXED_LEN_DECL, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_get_view = pmpi_file_get_view +#else +extern FORTRAN_API void FORT_CALL mpi_file_get_view_( MPI_Fint *, MPI_Offset*, MPI_Fint*, MPI_Fint*, char * FORT_MIXED_LEN_DECL, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_get_view_ = pmpi_file_get_view_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_GET_VIEW MPI_FILE_GET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_view__ mpi_file_get_view__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_get_view mpi_file_get_view +#else +#pragma _HP_SECONDARY_DEF pmpi_file_get_view_ mpi_file_get_view_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_GET_VIEW as PMPI_FILE_GET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_view__ as pmpi_file_get_view__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_get_view as pmpi_file_get_view +#else +#pragma _CRI duplicate mpi_file_get_view_ as pmpi_file_get_view_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_get_view_ PMPI_FILE_GET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_view_ pmpi_file_get_view__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_view pmpi_file_get_view_ +#endif +#define mpi_file_get_view_ pmpi_file_get_view +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_get_view_ pmpi_file_get_view +#endif +#define mpi_file_get_view_ pmpi_file_get_view_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_get_view_ MPI_FILE_GET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_get_view_ mpi_file_get_view__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_view mpi_file_get_view_ +#endif +#define mpi_file_get_view_ mpi_file_get_view +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_get_view_ mpi_file_get_view +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_get_view_(MPI_Fint *fh,MPI_Offset *disp,MPI_Fint *etype, + MPI_Fint *filetype,char *datarep, MPI_Fint *ierr, int str_len ); + +void mpi_file_get_view_(MPI_Fint *fh,MPI_Offset *disp,MPI_Fint *etype, + MPI_Fint *filetype,char *datarep, MPI_Fint *ierr, int str_len ) +{ + MPI_File fh_c; + MPI_Datatype etype_c, filetype_c; + int i, tmpreplen; + char *tmprep; + + if (datarep <= (char *) 0) { + FPRINTF(stderr, "MPI_File_get_view: datarep is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + tmprep = (char *) ADIOI_Malloc((MPI_MAX_DATAREP_STRING+1) * sizeof(char)); + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_get_view(fh_c, disp, &etype_c, &filetype_c, tmprep); + + tmpreplen = strlen(tmprep); + if (tmpreplen <= str_len) { + ADIOI_Strncpy(datarep, tmprep, tmpreplen); + + /* blank pad the remaining space */ + for (i=tmpreplen; iPMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpio_test_ PMPIO_TEST +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpio_test_ pmpio_test__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpio_test pmpio_test_ +#endif +#define mpio_test_ pmpio_test +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpio_test_ pmpio_test +#endif +#define mpio_test_ pmpio_test_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpio_test_ MPIO_TEST +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpio_test_ mpio_test__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpio_test mpio_test_ +#endif +#define mpio_test_ mpio_test +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpio_test_ mpio_test +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpio_test_(MPI_Fint *request,MPI_Fint *flag,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpio_test_(MPI_Fint *request,MPI_Fint *flag,MPI_Status *status, MPI_Fint *ierr ) +{ + MPIO_Request req_c; + + req_c = MPIO_Request_f2c(*request); + *ierr = MPIO_Test(&req_c,flag,status); + *request = MPIO_Request_c2f(req_c); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/iowaitf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/iowaitf.c new file mode 100644 index 0000000000..a87ca6a6d9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/iowaitf.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +FORTRAN_API void FORT_CALL MPIO_WAIT(MPI_Fint *request,MPI_Status *status, MPI_Fint *ierr ); +#pragma weak MPIO_WAIT = PMPIO_WAIT +#elif defined(FORTRANDOUBLEUNDERSCORE) +FORTRAN_API void FORT_CALL mpio_wait__(MPI_Fint *request,MPI_Status *status, MPI_Fint *ierr ); +#pragma weak mpio_wait__ = pmpio_wait__ +#elif !defined(FORTRANUNDERSCORE) +FORTRAN_API void FORT_CALL mpio_wait(MPI_Fint *request,MPI_Status *status, MPI_Fint *ierr ); +#pragma weak mpio_wait = pmpio_wait +#else +FORTRAN_API void FORT_CALL mpio_wait_(MPI_Fint *request,MPI_Status *status, MPI_Fint *ierr ); +#pragma weak mpio_wait_ = pmpio_wait_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPIO_WAIT MPIO_WAIT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpio_wait__ mpio_wait__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpio_wait mpio_wait +#else +#pragma _HP_SECONDARY_DEF pmpio_wait_ mpio_wait_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPIO_WAIT as PMPIO_WAIT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpio_wait__ as pmpio_wait__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpio_wait as pmpio_wait +#else +#pragma _CRI duplicate mpio_wait_ as pmpio_wait_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpio_wait_ PMPIO_WAIT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpio_wait_ pmpio_wait__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpio_wait pmpio_wait_ +#endif +#define mpio_wait_ pmpio_wait +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpio_wait_ pmpio_wait +#endif +#define mpio_wait_ pmpio_wait_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpio_wait_ MPIO_WAIT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpio_wait_ mpio_wait__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpio_wait mpio_wait_ +#endif +#define mpio_wait_ mpio_wait +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpio_wait_ mpio_wait +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpio_wait_(MPI_Fint *request,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpio_wait_(MPI_Fint *request,MPI_Status *status, MPI_Fint *ierr ) +{ + MPIO_Request req_c; + + req_c = MPIO_Request_f2c(*request); + *ierr = MPIO_Wait(&req_c, status); + *request = MPIO_Request_c2f(req_c); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/iread_atf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/iread_atf.c new file mode 100644 index 0000000000..c6a687dcee --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/iread_atf.c @@ -0,0 +1,130 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_IREAD_AT( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak MPI_FILE_IREAD_AT = PMPI_FILE_IREAD_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iread_at__( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iread_at__ = pmpi_file_iread_at__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iread_at( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iread_at = pmpi_file_iread_at +#else +extern FORTRAN_API void FORT_CALL mpi_file_iread_at_( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iread_at_ = pmpi_file_iread_at_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_IREAD_AT MPI_FILE_IREAD_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iread_at__ mpi_file_iread_at__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iread_at mpi_file_iread_at +#else +#pragma _HP_SECONDARY_DEF pmpi_file_iread_at_ mpi_file_iread_at_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_IREAD_AT as PMPI_FILE_IREAD_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_iread_at__ as pmpi_file_iread_at__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_iread_at as pmpi_file_iread_at +#else +#pragma _CRI duplicate mpi_file_iread_at_ as pmpi_file_iread_at_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_iread_at_ PMPI_FILE_IREAD_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iread_at_ pmpi_file_iread_at__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iread_at pmpi_file_iread_at_ +#endif +#define mpi_file_iread_at_ pmpi_file_iread_at +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iread_at_ pmpi_file_iread_at +#endif +#define mpi_file_iread_at_ pmpi_file_iread_at_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_iread_at_ MPI_FILE_IREAD_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iread_at_ mpi_file_iread_at__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iread_at mpi_file_iread_at_ +#endif +#define mpi_file_iread_at_ mpi_file_iread_at +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iread_at_ mpi_file_iread_at +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_iread_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Fint *request, MPI_Fint *ierr ); + +void mpi_file_iread_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_iread_at(fh_c,*offset,buf,*count,datatype_c,&req_c); + + *request = MPIO_Request_c2f(req_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_iread_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Datatype *datatype, + MPI_Fint *request, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_iread_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Datatype *datatype, + MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_iread_at(fh_c,*offset,buf,*count,*datatype,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/iread_shf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/iread_shf.c new file mode 100644 index 0000000000..84dc3753c4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/iread_shf.c @@ -0,0 +1,124 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_IREAD_SHARED( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak MPI_FILE_IREAD_SHARED = PMPI_FILE_IREAD_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iread_shared__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iread_shared__ = pmpi_file_iread_shared__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iread_shared( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iread_shared = pmpi_file_iread_shared +#else +extern FORTRAN_API void FORT_CALL mpi_file_iread_shared_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iread_shared_ = pmpi_file_iread_shared_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_IREAD_SHARED MPI_FILE_IREAD_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iread_shared__ mpi_file_iread_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iread_shared mpi_file_iread_shared +#else +#pragma _HP_SECONDARY_DEF pmpi_file_iread_shared_ mpi_file_iread_shared_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_IREAD_SHARED as PMPI_FILE_IREAD_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_iread_shared__ as pmpi_file_iread_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_iread_shared as pmpi_file_iread_shared +#else +#pragma _CRI duplicate mpi_file_iread_shared_ as pmpi_file_iread_shared_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_iread_shared_ PMPI_FILE_IREAD_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iread_shared_ pmpi_file_iread_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iread_shared pmpi_file_iread_shared_ +#endif +#define mpi_file_iread_shared_ pmpi_file_iread_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iread_shared_ pmpi_file_iread_shared +#endif +#define mpi_file_iread_shared_ pmpi_file_iread_shared_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_iread_shared_ MPI_FILE_IREAD_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iread_shared_ mpi_file_iread_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iread_shared mpi_file_iread_shared_ +#endif +#define mpi_file_iread_shared_ mpi_file_iread_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iread_shared_ mpi_file_iread_shared +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_iread_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *request, MPI_Fint *ierr ); + +void mpi_file_iread_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + MPI_Datatype datatype_c; + + datatype_c = MPI_Type_f2c(*datatype); + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_iread_shared(fh_c,buf,*count,datatype_c,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_iread_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Datatype *datatype,MPI_Fint *request, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_iread_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Datatype *datatype,MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_iread_shared(fh_c,buf,*count,*datatype,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/ireadf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/ireadf.c new file mode 100644 index 0000000000..ae9fbaf3bf --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/ireadf.c @@ -0,0 +1,124 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_IREAD( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak MPI_FILE_IREAD = PMPI_FILE_IREAD +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iread__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iread__ = pmpi_file_iread__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iread( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iread = pmpi_file_iread +#else +extern FORTRAN_API void FORT_CALL mpi_file_iread_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iread_ = pmpi_file_iread_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_IREAD MPI_FILE_IREAD +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iread__ mpi_file_iread__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iread mpi_file_iread +#else +#pragma _HP_SECONDARY_DEF pmpi_file_iread_ mpi_file_iread_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_IREAD as PMPI_FILE_IREAD +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_iread__ as pmpi_file_iread__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_iread as pmpi_file_iread +#else +#pragma _CRI duplicate mpi_file_iread_ as pmpi_file_iread_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_iread_ PMPI_FILE_IREAD +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iread_ pmpi_file_iread__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iread pmpi_file_iread_ +#endif +#define mpi_file_iread_ pmpi_file_iread +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iread_ pmpi_file_iread +#endif +#define mpi_file_iread_ pmpi_file_iread_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_iread_ MPI_FILE_IREAD +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iread_ mpi_file_iread__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iread mpi_file_iread_ +#endif +#define mpi_file_iread_ mpi_file_iread +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iread_ mpi_file_iread +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_iread_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *request, MPI_Fint *ierr ); + +void mpi_file_iread_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + MPI_Datatype datatype_c; + + datatype_c = MPI_Type_f2c(*datatype); + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_iread(fh_c,buf,*count,datatype_c,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_iread_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Datatype *datatype,MPI_Fint *request, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_iread_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Datatype *datatype,MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_iread(fh_c,buf,*count,*datatype,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/iwrite_atf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/iwrite_atf.c new file mode 100644 index 0000000000..b326fc3d1a --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/iwrite_atf.c @@ -0,0 +1,129 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_IWRITE_AT( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak MPI_FILE_IWRITE_AT = PMPI_FILE_IWRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iwrite_at__( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iwrite_at__ = pmpi_file_iwrite_at__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iwrite_at( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iwrite_at = pmpi_file_iwrite_at +#else +extern FORTRAN_API void FORT_CALL mpi_file_iwrite_at_( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iwrite_at_ = pmpi_file_iwrite_at_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_IWRITE_AT MPI_FILE_IWRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_at__ mpi_file_iwrite_at__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_at mpi_file_iwrite_at +#else +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_at_ mpi_file_iwrite_at_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_IWRITE_AT as PMPI_FILE_IWRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_iwrite_at__ as pmpi_file_iwrite_at__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_iwrite_at as pmpi_file_iwrite_at +#else +#pragma _CRI duplicate mpi_file_iwrite_at_ as pmpi_file_iwrite_at_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_iwrite_at_ PMPI_FILE_IWRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iwrite_at_ pmpi_file_iwrite_at__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_at pmpi_file_iwrite_at_ +#endif +#define mpi_file_iwrite_at_ pmpi_file_iwrite_at +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_at_ pmpi_file_iwrite_at +#endif +#define mpi_file_iwrite_at_ pmpi_file_iwrite_at_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_iwrite_at_ MPI_FILE_IWRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iwrite_at_ mpi_file_iwrite_at__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iwrite_at mpi_file_iwrite_at_ +#endif +#define mpi_file_iwrite_at_ mpi_file_iwrite_at +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iwrite_at_ mpi_file_iwrite_at +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_iwrite_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Fint *request, MPI_Fint *ierr ); + +void mpi_file_iwrite_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_iwrite_at(fh_c,*offset,buf,*count,datatype_c,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_iwrite_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Datatype *datatype, + MPI_Fint *request, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_iwrite_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Datatype *datatype, + MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_iwrite_at(fh_c,*offset,buf,*count,*datatype,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/iwrite_shf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/iwrite_shf.c new file mode 100644 index 0000000000..90ea68777b --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/iwrite_shf.c @@ -0,0 +1,124 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_IWRITE_SHARED( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak MPI_FILE_IWRITE_SHARED = PMPI_FILE_IWRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iwrite_shared__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iwrite_shared__ = pmpi_file_iwrite_shared__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iwrite_shared( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iwrite_shared = pmpi_file_iwrite_shared +#else +extern FORTRAN_API void FORT_CALL mpi_file_iwrite_shared_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iwrite_shared_ = pmpi_file_iwrite_shared_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_IWRITE_SHARED MPI_FILE_IWRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_shared__ mpi_file_iwrite_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_shared mpi_file_iwrite_shared +#else +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_shared_ mpi_file_iwrite_shared_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_IWRITE_SHARED as PMPI_FILE_IWRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_iwrite_shared__ as pmpi_file_iwrite_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_iwrite_shared as pmpi_file_iwrite_shared +#else +#pragma _CRI duplicate mpi_file_iwrite_shared_ as pmpi_file_iwrite_shared_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_iwrite_shared_ PMPI_FILE_IWRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iwrite_shared_ pmpi_file_iwrite_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_shared pmpi_file_iwrite_shared_ +#endif +#define mpi_file_iwrite_shared_ pmpi_file_iwrite_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_shared_ pmpi_file_iwrite_shared +#endif +#define mpi_file_iwrite_shared_ pmpi_file_iwrite_shared_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_iwrite_shared_ MPI_FILE_IWRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iwrite_shared_ mpi_file_iwrite_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iwrite_shared mpi_file_iwrite_shared_ +#endif +#define mpi_file_iwrite_shared_ mpi_file_iwrite_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iwrite_shared_ mpi_file_iwrite_shared +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_iwrite_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *request, MPI_Fint *ierr ); +void mpi_file_iwrite_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_iwrite_shared(fh_c,buf,*count,datatype_c,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_iwrite_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Datatype *datatype,MPI_Fint *request, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_iwrite_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Datatype *datatype,MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_iwrite_shared(fh_c,buf,*count,*datatype,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/iwritef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/iwritef.c new file mode 100644 index 0000000000..4410c011a1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/iwritef.c @@ -0,0 +1,125 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_IWRITE( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak MPI_FILE_IWRITE = PMPI_FILE_IWRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iwrite__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iwrite__ = pmpi_file_iwrite__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_iwrite( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iwrite = pmpi_file_iwrite +#else +extern FORTRAN_API void FORT_CALL mpi_file_iwrite_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint*, MPI_Fint * ); +#pragma weak mpi_file_iwrite_ = pmpi_file_iwrite_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_IWRITE MPI_FILE_IWRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite__ mpi_file_iwrite__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite mpi_file_iwrite +#else +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_ mpi_file_iwrite_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_IWRITE as PMPI_FILE_IWRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_iwrite__ as pmpi_file_iwrite__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_iwrite as pmpi_file_iwrite +#else +#pragma _CRI duplicate mpi_file_iwrite_ as pmpi_file_iwrite_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_iwrite_ PMPI_FILE_IWRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iwrite_ pmpi_file_iwrite__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite pmpi_file_iwrite_ +#endif +#define mpi_file_iwrite_ pmpi_file_iwrite +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_iwrite_ pmpi_file_iwrite +#endif +#define mpi_file_iwrite_ pmpi_file_iwrite_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_iwrite_ MPI_FILE_IWRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_iwrite_ mpi_file_iwrite__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iwrite mpi_file_iwrite_ +#endif +#define mpi_file_iwrite_ mpi_file_iwrite +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_iwrite_ mpi_file_iwrite +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_iwrite_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *request, MPI_Fint *ierr ); + +void mpi_file_iwrite_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_iwrite(fh_c,buf,*count,datatype_c,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_iwrite_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Datatype *datatype,MPI_Fint *request, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_iwrite_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Datatype *datatype,MPI_Fint *request, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPIO_Request req_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_iwrite(fh_c,buf,*count,*datatype,&req_c); + *request = MPIO_Request_c2f(req_c); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/openf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/openf.c new file mode 100644 index 0000000000..ea1a5d1c47 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/openf.c @@ -0,0 +1,187 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifdef _UNICOS +#include +#endif +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_OPEN( MPI_Fint *, char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint *, MPI_File*, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak MPI_FILE_OPEN = PMPI_FILE_OPEN +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_open__( MPI_Fint *, char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint *, MPI_File*, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_open__ = pmpi_file_open__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_open( MPI_Fint *, char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint *, MPI_File*, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_open = pmpi_file_open +#else +extern FORTRAN_API void FORT_CALL mpi_file_open_( MPI_Fint *, char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint *, MPI_File*, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_open_ = pmpi_file_open_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_OPEN MPI_FILE_OPEN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_open__ mpi_file_open__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_open mpi_file_open +#else +#pragma _HP_SECONDARY_DEF pmpi_file_open_ mpi_file_open_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_OPEN as PMPI_FILE_OPEN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_open__ as pmpi_file_open__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_open as pmpi_file_open +#else +#pragma _CRI duplicate mpi_file_open_ as pmpi_file_open_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_open_ PMPI_FILE_OPEN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_open_ pmpi_file_open__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_open pmpi_file_open_ +#endif +#define mpi_file_open_ pmpi_file_open +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_open_ pmpi_file_open +#endif +#define mpi_file_open_ pmpi_file_open_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_open_ MPI_FILE_OPEN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_open_ mpi_file_open__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_open mpi_file_open_ +#endif +#define mpi_file_open_ mpi_file_open +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_open_ mpi_file_open +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_open_(MPI_Fint *comm,char *filename,MPI_Fint *amode, + MPI_Fint *info, MPI_Fint *fh, MPI_Fint *ierr, int str_len ); + +void mpi_file_open_(MPI_Fint *comm,char *filename,MPI_Fint *amode, + MPI_Fint *info, MPI_Fint *fh, MPI_Fint *ierr, int str_len ) +{ + char *newfname; + MPI_File fh_c; + int real_len, i; + MPI_Comm comm_c; + MPI_Info info_c; + + comm_c = MPI_Comm_f2c(*comm); + info_c = MPI_Info_f2c(*info); + + /* strip trailing blanks */ + if (filename <= (char *) 0) { + FPRINTF(stderr, "MPI_File_open: filename is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + for (i=str_len-1; i>=0; i--) if (filename[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_File_open: filename is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + real_len = i + 1; + + newfname = (char *) ADIOI_Malloc((real_len+1)*sizeof(char)); + ADIOI_Strncpy(newfname, filename, real_len); + newfname[real_len] = '\0'; + + *ierr = MPI_File_open(comm_c, newfname, *amode, info_c, &fh_c); + + *fh = MPI_File_c2f(fh_c); + ADIOI_Free(newfname); +} + +#else + +#ifdef _UNICOS +void mpi_file_open_(MPI_Fint *comm,_fcd filename_fcd,MPI_Fint *amode, + MPI_Fint *info, MPI_Fint *fh, MPI_Fint *ierr) +{ + char *filename = _fcdtocp(filename_fcd); + int str_len = _fcdlen(filename_fcd); +#else +/* Prototype to keep compiler happy */ +/* +FORTRAN_API void FORT_CALL mpi_file_open_(MPI_Comm *comm,char *filename,MPI_Fint *amode, + MPI_Fint *info, MPI_Fint *fh, MPI_Fint *ierr, int str_len ); + +FORTRAN_API void FORT_CALL mpi_file_open_(MPI_Comm *comm,char *filename,MPI_Fint *amode, + MPI_Fint *info, MPI_Fint *fh, MPI_Fint *ierr, int str_len ) +*/ +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_open_(MPI_Fint *comm,char *filename FORT_MIXED_LEN_DECL,MPI_Fint *amode, + MPI_Fint *info, MPI_Fint *fh, MPI_Fint *ierr FORT_END_LEN_DECL); + +FORTRAN_API void FORT_CALL mpi_file_open_(MPI_Fint *comm,char *filename FORT_MIXED_LEN(str_len),MPI_Fint *amode, + MPI_Fint *info, MPI_Fint *fh, MPI_Fint *ierr FORT_END_LEN(str_len)) +{ +#endif + char *newfname; + MPI_File fh_c; + int real_len, i; + MPI_Info info_c; + + info_c = MPI_Info_f2c(*info); + + /* strip trailing blanks */ + if (filename <= (char *) 0) { + FPRINTF(stderr, "MPI_File_open: filename is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + for (i=str_len-1; i>=0; i--) if (filename[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_File_open: filename is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + real_len = i + 1; + + newfname = (char *) ADIOI_Malloc((real_len+1)*sizeof(char)); + ADIOI_Strncpy(newfname, filename, real_len); + newfname[real_len] = '\0'; + + *ierr = MPI_File_open((MPI_Comm)(*comm), newfname, *amode, info_c, &fh_c); + + *fh = MPI_File_c2f(fh_c); + ADIOI_Free(newfname); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/preallocf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/preallocf.c new file mode 100644 index 0000000000..515aa4a912 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/preallocf.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_PREALLOCATE( MPI_Fint *, MPI_Offset *, MPI_Fint * ); +#pragma weak MPI_FILE_PREALLOCATE = PMPI_FILE_PREALLOCATE +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_preallocate__( MPI_Fint *, MPI_Offset *, MPI_Fint * ); +#pragma weak mpi_file_preallocate__ = pmpi_file_preallocate__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_preallocate( MPI_Fint *, MPI_Offset *, MPI_Fint * ); +#pragma weak mpi_file_preallocate = pmpi_file_preallocate +#else +extern FORTRAN_API void FORT_CALL mpi_file_preallocate_( MPI_Fint *, MPI_Offset *, MPI_Fint * ); +#pragma weak mpi_file_preallocate_ = pmpi_file_preallocate_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_PREALLOCATE MPI_FILE_PREALLOCATE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_preallocate__ mpi_file_preallocate__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_preallocate mpi_file_preallocate +#else +#pragma _HP_SECONDARY_DEF pmpi_file_preallocate_ mpi_file_preallocate_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_PREALLOCATE as PMPI_FILE_PREALLOCATE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_preallocate__ as pmpi_file_preallocate__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_preallocate as pmpi_file_preallocate +#else +#pragma _CRI duplicate mpi_file_preallocate_ as pmpi_file_preallocate_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_preallocate_ PMPI_FILE_PREALLOCATE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_preallocate_ pmpi_file_preallocate__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_preallocate pmpi_file_preallocate_ +#endif +#define mpi_file_preallocate_ pmpi_file_preallocate +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_preallocate_ pmpi_file_preallocate +#endif +#define mpi_file_preallocate_ pmpi_file_preallocate_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_preallocate_ MPI_FILE_PREALLOCATE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_preallocate_ mpi_file_preallocate__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_preallocate mpi_file_preallocate_ +#endif +#define mpi_file_preallocate_ mpi_file_preallocate +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_preallocate_ mpi_file_preallocate +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_preallocate_(MPI_Fint *fh,MPI_Offset *size, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_preallocate_(MPI_Fint *fh,MPI_Offset *size, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_preallocate(fh_c,*size); +} + diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/rd_atallbf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/rd_atallbf.c new file mode 100644 index 0000000000..5fff4e9e7e --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/rd_atallbf.c @@ -0,0 +1,121 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_AT_ALL_BEGIN( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_READ_AT_ALL_BEGIN = PMPI_FILE_READ_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_at_all_begin__( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_read_at_all_begin__ = pmpi_file_read_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_at_all_begin( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_read_at_all_begin = pmpi_file_read_at_all_begin +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_at_all_begin_( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_read_at_all_begin_ = pmpi_file_read_at_all_begin_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_AT_ALL_BEGIN MPI_FILE_READ_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_begin__ mpi_file_read_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_begin mpi_file_read_at_all_begin +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_begin_ mpi_file_read_at_all_begin_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_AT_ALL_BEGIN as PMPI_FILE_READ_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_at_all_begin__ as pmpi_file_read_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_at_all_begin as pmpi_file_read_at_all_begin +#else +#pragma _CRI duplicate mpi_file_read_at_all_begin_ as pmpi_file_read_at_all_begin_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_at_all_begin_ PMPI_FILE_READ_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_at_all_begin_ pmpi_file_read_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_begin pmpi_file_read_at_all_begin_ +#endif +#define mpi_file_read_at_all_begin_ pmpi_file_read_at_all_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_begin_ pmpi_file_read_at_all_begin +#endif +#define mpi_file_read_at_all_begin_ pmpi_file_read_at_all_begin_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_at_all_begin_ MPI_FILE_READ_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_at_all_begin_ mpi_file_read_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_at_all_begin mpi_file_read_at_all_begin_ +#endif +#define mpi_file_read_at_all_begin_ mpi_file_read_at_all_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_at_all_begin_ mpi_file_read_at_all_begin +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_read_at_all_begin_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, MPI_Fint *ierr ); + +void mpi_file_read_at_all_begin_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_read_at_all_begin(fh_c,*offset,buf,*count,datatype_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_at_all_begin_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_at_all_begin_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read_at_all_begin(fh_c,*offset,buf,*count,(MPI_Datatype) *datatype); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/rd_atallef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/rd_atallef.c new file mode 100644 index 0000000000..8a3441126d --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/rd_atallef.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_AT_ALL_END( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_READ_AT_ALL_END = PMPI_FILE_READ_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_at_all_end__( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_at_all_end__ = pmpi_file_read_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_at_all_end( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_at_all_end = pmpi_file_read_at_all_end +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_at_all_end_( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_at_all_end_ = pmpi_file_read_at_all_end_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_AT_ALL_END MPI_FILE_READ_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_end__ mpi_file_read_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_end mpi_file_read_at_all_end +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_end_ mpi_file_read_at_all_end_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_AT_ALL_END as PMPI_FILE_READ_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_at_all_end__ as pmpi_file_read_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_at_all_end as pmpi_file_read_at_all_end +#else +#pragma _CRI duplicate mpi_file_read_at_all_end_ as pmpi_file_read_at_all_end_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_at_all_end_ PMPI_FILE_READ_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_at_all_end_ pmpi_file_read_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_end pmpi_file_read_at_all_end_ +#endif +#define mpi_file_read_at_all_end_ pmpi_file_read_at_all_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_end_ pmpi_file_read_at_all_end +#endif +#define mpi_file_read_at_all_end_ pmpi_file_read_at_all_end_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_at_all_end_ MPI_FILE_READ_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_at_all_end_ mpi_file_read_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_at_all_end mpi_file_read_at_all_end_ +#endif +#define mpi_file_read_at_all_end_ mpi_file_read_at_all_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_at_all_end_ mpi_file_read_at_all_end +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_at_all_end_(MPI_Fint *fh,void *buf,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_at_all_end_(MPI_Fint *fh,void *buf,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read_at_all_end(fh_c,buf,status); +} + diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/read_allbf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_allbf.c new file mode 100644 index 0000000000..5708a03c8d --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_allbf.c @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_ALL_BEGIN( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_READ_ALL_BEGIN = PMPI_FILE_READ_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_all_begin__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_read_all_begin__ = pmpi_file_read_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_all_begin( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_read_all_begin = pmpi_file_read_all_begin +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_all_begin_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_read_all_begin_ = pmpi_file_read_all_begin_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_ALL_BEGIN MPI_FILE_READ_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_begin__ mpi_file_read_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_begin mpi_file_read_all_begin +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_begin_ mpi_file_read_all_begin_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_ALL_BEGIN as PMPI_FILE_READ_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_all_begin__ as pmpi_file_read_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_all_begin as pmpi_file_read_all_begin +#else +#pragma _CRI duplicate mpi_file_read_all_begin_ as pmpi_file_read_all_begin_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_all_begin_ PMPI_FILE_READ_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_all_begin_ pmpi_file_read_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_begin pmpi_file_read_all_begin_ +#endif +#define mpi_file_read_all_begin_ pmpi_file_read_all_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_begin_ pmpi_file_read_all_begin +#endif +#define mpi_file_read_all_begin_ pmpi_file_read_all_begin_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_all_begin_ MPI_FILE_READ_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_all_begin_ mpi_file_read_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_all_begin mpi_file_read_all_begin_ +#endif +#define mpi_file_read_all_begin_ mpi_file_read_all_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_all_begin_ mpi_file_read_all_begin +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_read_all_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ); + +void mpi_file_read_all_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_read_all_begin(fh_c,buf,*count,datatype_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_all_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_all_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read_all_begin(fh_c,buf,*count,(MPI_Datatype) *datatype); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/read_allef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_allef.c new file mode 100644 index 0000000000..776b182d64 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_allef.c @@ -0,0 +1,103 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_ALL_END( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_READ_ALL_END = PMPI_FILE_READ_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_all_end__( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_all_end__ = pmpi_file_read_all_end__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_all_end( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_all_end = pmpi_file_read_all_end +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_all_end_( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_all_end_ = pmpi_file_read_all_end_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_ALL_END MPI_FILE_READ_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_end__ mpi_file_read_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_end mpi_file_read_all_end +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_end_ mpi_file_read_all_end_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_ALL_END as PMPI_FILE_READ_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_all_end__ as pmpi_file_read_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_all_end as pmpi_file_read_all_end +#else +#pragma _CRI duplicate mpi_file_read_all_end_ as pmpi_file_read_all_end_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_all_end_ PMPI_FILE_READ_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_all_end_ pmpi_file_read_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_end pmpi_file_read_all_end_ +#endif +#define mpi_file_read_all_end_ pmpi_file_read_all_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_end_ pmpi_file_read_all_end +#endif +#define mpi_file_read_all_end_ pmpi_file_read_all_end_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_all_end_ MPI_FILE_READ_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_all_end_ mpi_file_read_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_all_end mpi_file_read_all_end_ +#endif +#define mpi_file_read_all_end_ mpi_file_read_all_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_all_end_ mpi_file_read_all_end +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_all_end_(MPI_Fint *fh,void *buf,MPI_Status *status, + MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_all_end_(MPI_Fint *fh,void *buf,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + + *ierr = MPI_File_read_all_end(fh_c,buf,status); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/read_allf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_allf.c new file mode 100644 index 0000000000..99e1229b7f --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_allf.c @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_ALL( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_READ_ALL = PMPI_FILE_READ_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_all__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_all__ = pmpi_file_read_all__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_all( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_all = pmpi_file_read_all +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_all_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_all_ = pmpi_file_read_all_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_ALL MPI_FILE_READ_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all__ mpi_file_read_all__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all mpi_file_read_all +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_ mpi_file_read_all_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_ALL as PMPI_FILE_READ_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_all__ as pmpi_file_read_all__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_all as pmpi_file_read_all +#else +#pragma _CRI duplicate mpi_file_read_all_ as pmpi_file_read_all_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_all_ PMPI_FILE_READ_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_all_ pmpi_file_read_all__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all pmpi_file_read_all_ +#endif +#define mpi_file_read_all_ pmpi_file_read_all +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_all_ pmpi_file_read_all +#endif +#define mpi_file_read_all_ pmpi_file_read_all_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_all_ MPI_FILE_READ_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_all_ mpi_file_read_all__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_all mpi_file_read_all_ +#endif +#define mpi_file_read_all_ mpi_file_read_all +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_all_ mpi_file_read_all +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_read_all_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_read_all_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_read_all(fh_c,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_all_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_all_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read_all(fh_c,buf,*count,(MPI_Datatype)*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/read_atallf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_atallf.c new file mode 100644 index 0000000000..b9f30a0056 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_atallf.c @@ -0,0 +1,125 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_AT_ALL( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_READ_AT_ALL = PMPI_FILE_READ_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_at_all__( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_at_all__ = pmpi_file_read_at_all__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_at_all( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_at_all = pmpi_file_read_at_all +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_at_all_( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_at_all_ = pmpi_file_read_at_all_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_AT_ALL MPI_FILE_READ_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all__ mpi_file_read_at_all__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all mpi_file_read_at_all +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_ mpi_file_read_at_all_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_AT_ALL as PMPI_FILE_READ_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_at_all__ as pmpi_file_read_at_all__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_at_all as pmpi_file_read_at_all +#else +#pragma _CRI duplicate mpi_file_read_at_all_ as pmpi_file_read_at_all_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_at_all_ PMPI_FILE_READ_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_at_all_ pmpi_file_read_at_all__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all pmpi_file_read_at_all_ +#endif +#define mpi_file_read_at_all_ pmpi_file_read_at_all +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_all_ pmpi_file_read_at_all +#endif +#define mpi_file_read_at_all_ pmpi_file_read_at_all_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_at_all_ MPI_FILE_READ_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_at_all_ mpi_file_read_at_all__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_at_all mpi_file_read_at_all_ +#endif +#define mpi_file_read_at_all_ mpi_file_read_at_all +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_at_all_ mpi_file_read_at_all +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_read_at_all_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_read_at_all_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_read_at_all(fh_c,*offset,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_at_all_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_at_all_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read_at_all(fh_c,*offset,buf,*count,(MPI_Datatype)*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/read_atf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_atf.c new file mode 100644 index 0000000000..2602e399bf --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_atf.c @@ -0,0 +1,121 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_AT( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_READ_AT = PMPI_FILE_READ_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_at__( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_at__ = pmpi_file_read_at__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_at( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_at = pmpi_file_read_at +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_at_( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_at_ = pmpi_file_read_at_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_AT MPI_FILE_READ_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at__ mpi_file_read_at__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at mpi_file_read_at +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_ mpi_file_read_at_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_AT as PMPI_FILE_READ_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_at__ as pmpi_file_read_at__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_at as pmpi_file_read_at +#else +#pragma _CRI duplicate mpi_file_read_at_ as pmpi_file_read_at_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_at_ PMPI_FILE_READ_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_at_ pmpi_file_read_at__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at pmpi_file_read_at_ +#endif +#define mpi_file_read_at_ pmpi_file_read_at +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_at_ pmpi_file_read_at +#endif +#define mpi_file_read_at_ pmpi_file_read_at_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_at_ MPI_FILE_READ_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_at_ mpi_file_read_at__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_at mpi_file_read_at_ +#endif +#define mpi_file_read_at_ mpi_file_read_at +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_at_ mpi_file_read_at +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_read_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_read_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_read_at(fh_c,*offset,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read_at(fh_c,*offset,buf,*count,(MPI_Datatype)*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/read_ordbf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_ordbf.c new file mode 100644 index 0000000000..74389174f4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_ordbf.c @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_ORDERED_BEGIN( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_READ_ORDERED_BEGIN = PMPI_FILE_READ_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_ordered_begin__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_read_ordered_begin__ = pmpi_file_read_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_ordered_begin( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_read_ordered_begin = pmpi_file_read_ordered_begin +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_ordered_begin_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_read_ordered_begin_ = pmpi_file_read_ordered_begin_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_ORDERED_BEGIN MPI_FILE_READ_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_begin__ mpi_file_read_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_begin mpi_file_read_ordered_begin +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_begin_ mpi_file_read_ordered_begin_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_ORDERED_BEGIN as PMPI_FILE_READ_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_ordered_begin__ as pmpi_file_read_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_ordered_begin as pmpi_file_read_ordered_begin +#else +#pragma _CRI duplicate mpi_file_read_ordered_begin_ as pmpi_file_read_ordered_begin_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_ordered_begin_ PMPI_FILE_READ_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_ordered_begin_ pmpi_file_read_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_begin pmpi_file_read_ordered_begin_ +#endif +#define mpi_file_read_ordered_begin_ pmpi_file_read_ordered_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_begin_ pmpi_file_read_ordered_begin +#endif +#define mpi_file_read_ordered_begin_ pmpi_file_read_ordered_begin_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_ordered_begin_ MPI_FILE_READ_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_ordered_begin_ mpi_file_read_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_ordered_begin mpi_file_read_ordered_begin_ +#endif +#define mpi_file_read_ordered_begin_ mpi_file_read_ordered_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_ordered_begin_ mpi_file_read_ordered_begin +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_read_ordered_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *ierr ); + +void mpi_file_read_ordered_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_read_ordered_begin(fh_c,buf,*count,datatype_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_ordered_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_ordered_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read_ordered_begin(fh_c,buf,*count,(MPI_Datatype)*datatype); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/read_ordef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_ordef.c new file mode 100644 index 0000000000..63425c8ad3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_ordef.c @@ -0,0 +1,103 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_ORDERED_END( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_READ_ORDERED_END = PMPI_FILE_READ_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_ordered_end__( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_ordered_end__ = pmpi_file_read_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_ordered_end( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_ordered_end = pmpi_file_read_ordered_end +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_ordered_end_( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_ordered_end_ = pmpi_file_read_ordered_end_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_ORDERED_END MPI_FILE_READ_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_end__ mpi_file_read_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_end mpi_file_read_ordered_end +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_end_ mpi_file_read_ordered_end_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_ORDERED_END as PMPI_FILE_READ_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_ordered_end__ as pmpi_file_read_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_ordered_end as pmpi_file_read_ordered_end +#else +#pragma _CRI duplicate mpi_file_read_ordered_end_ as pmpi_file_read_ordered_end_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_ordered_end_ PMPI_FILE_READ_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_ordered_end_ pmpi_file_read_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_end pmpi_file_read_ordered_end_ +#endif +#define mpi_file_read_ordered_end_ pmpi_file_read_ordered_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_end_ pmpi_file_read_ordered_end +#endif +#define mpi_file_read_ordered_end_ pmpi_file_read_ordered_end_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_ordered_end_ MPI_FILE_READ_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_ordered_end_ mpi_file_read_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_ordered_end mpi_file_read_ordered_end_ +#endif +#define mpi_file_read_ordered_end_ mpi_file_read_ordered_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_ordered_end_ mpi_file_read_ordered_end +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_ordered_end_(MPI_Fint *fh,void *buf,MPI_Status *status, + MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_ordered_end_(MPI_Fint *fh,void *buf,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + + *ierr = MPI_File_read_ordered_end(fh_c,buf,status); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/read_ordf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_ordf.c new file mode 100644 index 0000000000..a45ae1282f --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_ordf.c @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_ORDERED( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_READ_ORDERED = PMPI_FILE_READ_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_ordered__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_ordered__ = pmpi_file_read_ordered__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_ordered( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_ordered = pmpi_file_read_ordered +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_ordered_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_ordered_ = pmpi_file_read_ordered_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_ORDERED MPI_FILE_READ_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered__ mpi_file_read_ordered__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered mpi_file_read_ordered +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_ mpi_file_read_ordered_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_ORDERED as PMPI_FILE_READ_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_ordered__ as pmpi_file_read_ordered__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_ordered as pmpi_file_read_ordered +#else +#pragma _CRI duplicate mpi_file_read_ordered_ as pmpi_file_read_ordered_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_ordered_ PMPI_FILE_READ_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_ordered_ pmpi_file_read_ordered__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered pmpi_file_read_ordered_ +#endif +#define mpi_file_read_ordered_ pmpi_file_read_ordered +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ordered_ pmpi_file_read_ordered +#endif +#define mpi_file_read_ordered_ pmpi_file_read_ordered_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_ordered_ MPI_FILE_READ_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_ordered_ mpi_file_read_ordered__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_ordered mpi_file_read_ordered_ +#endif +#define mpi_file_read_ordered_ mpi_file_read_ordered +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_ordered_ mpi_file_read_ordered +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_read_ordered_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_read_ordered_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_read_ordered(fh_c,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_ordered_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_ordered_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read_ordered(fh_c,buf,*count,(MPI_Datatype)*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/read_shf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_shf.c new file mode 100644 index 0000000000..937e54fb95 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/read_shf.c @@ -0,0 +1,119 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ_SHARED( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_READ_SHARED = PMPI_FILE_READ_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_shared__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_shared__ = pmpi_file_read_shared__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read_shared( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_shared = pmpi_file_read_shared +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_shared_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_shared_ = pmpi_file_read_shared_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ_SHARED MPI_FILE_READ_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_shared__ mpi_file_read_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read_shared mpi_file_read_shared +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_shared_ mpi_file_read_shared_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ_SHARED as PMPI_FILE_READ_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_shared__ as pmpi_file_read_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read_shared as pmpi_file_read_shared +#else +#pragma _CRI duplicate mpi_file_read_shared_ as pmpi_file_read_shared_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_shared_ PMPI_FILE_READ_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_shared_ pmpi_file_read_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_shared pmpi_file_read_shared_ +#endif +#define mpi_file_read_shared_ pmpi_file_read_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_shared_ pmpi_file_read_shared +#endif +#define mpi_file_read_shared_ pmpi_file_read_shared_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_shared_ MPI_FILE_READ_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_shared_ mpi_file_read_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_shared mpi_file_read_shared_ +#endif +#define mpi_file_read_shared_ mpi_file_read_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_shared_ mpi_file_read_shared +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_read_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); +void mpi_file_read_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_read_shared(fh_c,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); +FORTRAN_API void FORT_CALL mpi_file_read_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read_shared(fh_c,buf,*count,(MPI_Datatype)*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/readf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/readf.c new file mode 100644 index 0000000000..c802739139 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/readf.c @@ -0,0 +1,121 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_READ( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_READ = PMPI_FILE_READ +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read__ = pmpi_file_read__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_read( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read = pmpi_file_read +#else +extern FORTRAN_API void FORT_CALL mpi_file_read_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_read_ = pmpi_file_read_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_READ MPI_FILE_READ +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read__ mpi_file_read__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_read mpi_file_read +#else +#pragma _HP_SECONDARY_DEF pmpi_file_read_ mpi_file_read_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_READ as PMPI_FILE_READ +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_read__ as pmpi_file_read__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_read as pmpi_file_read +#else +#pragma _CRI duplicate mpi_file_read_ as pmpi_file_read_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_read_ PMPI_FILE_READ +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_ pmpi_file_read__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read pmpi_file_read_ +#endif +#define mpi_file_read_ pmpi_file_read +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_read_ pmpi_file_read +#endif +#define mpi_file_read_ pmpi_file_read_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_read_ MPI_FILE_READ +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_read_ mpi_file_read__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read mpi_file_read_ +#endif +#define mpi_file_read_ mpi_file_read +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_read_ mpi_file_read +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_read_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_read_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_read(fh_c,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_read_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_read_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_read(fh_c,buf,*count,(MPI_Datatype)*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/seek_shf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/seek_shf.c new file mode 100644 index 0000000000..158e626c0e --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/seek_shf.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_SEEK_SHARED( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_SEEK_SHARED = PMPI_FILE_SEEK_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_seek_shared__( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_seek_shared__ = pmpi_file_seek_shared__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_seek_shared( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_seek_shared = pmpi_file_seek_shared +#else +extern FORTRAN_API void FORT_CALL mpi_file_seek_shared_( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_seek_shared_ = pmpi_file_seek_shared_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_SEEK_SHARED MPI_FILE_SEEK_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_seek_shared__ mpi_file_seek_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_seek_shared mpi_file_seek_shared +#else +#pragma _HP_SECONDARY_DEF pmpi_file_seek_shared_ mpi_file_seek_shared_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_SEEK_SHARED as PMPI_FILE_SEEK_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_seek_shared__ as pmpi_file_seek_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_seek_shared as pmpi_file_seek_shared +#else +#pragma _CRI duplicate mpi_file_seek_shared_ as pmpi_file_seek_shared_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_seek_shared_ PMPI_FILE_SEEK_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_seek_shared_ pmpi_file_seek_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_seek_shared pmpi_file_seek_shared_ +#endif +#define mpi_file_seek_shared_ pmpi_file_seek_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_seek_shared_ pmpi_file_seek_shared +#endif +#define mpi_file_seek_shared_ pmpi_file_seek_shared_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_seek_shared_ MPI_FILE_SEEK_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_seek_shared_ mpi_file_seek_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_seek_shared mpi_file_seek_shared_ +#endif +#define mpi_file_seek_shared_ mpi_file_seek_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_seek_shared_ mpi_file_seek_shared +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_seek_shared_(MPI_Fint *fh,MPI_Offset *offset,MPI_Fint *whence, + MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_seek_shared_(MPI_Fint *fh,MPI_Offset *offset,MPI_Fint *whence, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_seek_shared(fh_c,*offset,*whence); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/seekf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/seekf.c new file mode 100644 index 0000000000..8e125d1849 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/seekf.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_SEEK( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_SEEK = PMPI_FILE_SEEK +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_seek__( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_seek__ = pmpi_file_seek__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_seek( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_seek = pmpi_file_seek +#else +extern FORTRAN_API void FORT_CALL mpi_file_seek_( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_seek_ = pmpi_file_seek_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_SEEK MPI_FILE_SEEK +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_seek__ mpi_file_seek__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_seek mpi_file_seek +#else +#pragma _HP_SECONDARY_DEF pmpi_file_seek_ mpi_file_seek_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_SEEK as PMPI_FILE_SEEK +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_seek__ as pmpi_file_seek__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_seek as pmpi_file_seek +#else +#pragma _CRI duplicate mpi_file_seek_ as pmpi_file_seek_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_seek_ PMPI_FILE_SEEK +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_seek_ pmpi_file_seek__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_seek pmpi_file_seek_ +#endif +#define mpi_file_seek_ pmpi_file_seek +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_seek_ pmpi_file_seek +#endif +#define mpi_file_seek_ pmpi_file_seek_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_seek_ MPI_FILE_SEEK +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_seek_ mpi_file_seek__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_seek mpi_file_seek_ +#endif +#define mpi_file_seek_ mpi_file_seek +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_seek_ mpi_file_seek +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_seek_(MPI_Fint *fh,MPI_Offset *offset,MPI_Fint *whence, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_seek_(MPI_Fint *fh,MPI_Offset *offset,MPI_Fint *whence, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_seek(fh_c,*offset,*whence); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/set_atomf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_atomf.c new file mode 100644 index 0000000000..c4388950da --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_atomf.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_SET_ATOMICITY( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_SET_ATOMICITY = PMPI_FILE_SET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_atomicity__( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_set_atomicity__ = pmpi_file_set_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_atomicity( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_set_atomicity = pmpi_file_set_atomicity +#else +extern FORTRAN_API void FORT_CALL mpi_file_set_atomicity_( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_set_atomicity_ = pmpi_file_set_atomicity_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_SET_ATOMICITY MPI_FILE_SET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_atomicity__ mpi_file_set_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_atomicity mpi_file_set_atomicity +#else +#pragma _HP_SECONDARY_DEF pmpi_file_set_atomicity_ mpi_file_set_atomicity_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_SET_ATOMICITY as PMPI_FILE_SET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_atomicity__ as pmpi_file_set_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_atomicity as pmpi_file_set_atomicity +#else +#pragma _CRI duplicate mpi_file_set_atomicity_ as pmpi_file_set_atomicity_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_set_atomicity_ PMPI_FILE_SET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_atomicity_ pmpi_file_set_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_atomicity pmpi_file_set_atomicity_ +#endif +#define mpi_file_set_atomicity_ pmpi_file_set_atomicity +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_atomicity_ pmpi_file_set_atomicity +#endif +#define mpi_file_set_atomicity_ pmpi_file_set_atomicity_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_set_atomicity_ MPI_FILE_SET_ATOMICITY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_atomicity_ mpi_file_set_atomicity__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_atomicity mpi_file_set_atomicity_ +#endif +#define mpi_file_set_atomicity_ mpi_file_set_atomicity +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_atomicity_ mpi_file_set_atomicity +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_set_atomicity_(MPI_Fint *fh,MPI_Fint *flag, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_set_atomicity_(MPI_Fint *fh,MPI_Fint *flag, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_set_atomicity(fh_c,*flag); +} + diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/set_errhf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_errhf.c new file mode 100644 index 0000000000..c622660898 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_errhf.c @@ -0,0 +1,105 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_SET_ERRHANDLER( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_SET_ERRHANDLER = PMPI_FILE_SET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_errhandler__( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_set_errhandler__ = pmpi_file_set_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_errhandler( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_set_errhandler = pmpi_file_set_errhandler +#else +extern FORTRAN_API void FORT_CALL mpi_file_set_errhandler_( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_set_errhandler_ = pmpi_file_set_errhandler_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_SET_ERRHANDLER MPI_FILE_SET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_errhandler__ mpi_file_set_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_errhandler mpi_file_set_errhandler +#else +#pragma _HP_SECONDARY_DEF pmpi_file_set_errhandler_ mpi_file_set_errhandler_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_SET_ERRHANDLER as PMPI_FILE_SET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_errhandler__ as pmpi_file_set_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_errhandler as pmpi_file_set_errhandler +#else +#pragma _CRI duplicate mpi_file_set_errhandler_ as pmpi_file_set_errhandler_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_set_errhandler_ PMPI_FILE_SET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_errhandler_ pmpi_file_set_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_errhandler pmpi_file_set_errhandler_ +#endif +#define mpi_file_set_errhandler_ pmpi_file_set_errhandler +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_errhandler_ pmpi_file_set_errhandler +#endif +#define mpi_file_set_errhandler_ pmpi_file_set_errhandler_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_set_errhandler_ MPI_FILE_SET_ERRHANDLER +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_errhandler_ mpi_file_set_errhandler__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_errhandler mpi_file_set_errhandler_ +#endif +#define mpi_file_set_errhandler_ mpi_file_set_errhandler +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_errhandler_ mpi_file_set_errhandler +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_set_errhandler_(MPI_Fint *fh, MPI_Fint *err_handler, MPI_Fint *ierr); + +FORTRAN_API void FORT_CALL mpi_file_set_errhandler_(MPI_Fint *fh, MPI_Fint *err_handler, MPI_Fint *ierr) +{ + MPI_File fh_c; + MPI_Errhandler err_handler_c; + + fh_c = MPI_File_f2c(*fh); + err_handler_c = MPI_Errhandler_f2c(*err_handler); + + *ierr = MPI_File_set_errhandler(fh_c,err_handler_c); +} + diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/set_infof.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_infof.c new file mode 100644 index 0000000000..85c05e8f1d --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_infof.c @@ -0,0 +1,104 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_SET_INFO( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_SET_INFO = PMPI_FILE_SET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_info__( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_set_info__ = pmpi_file_set_info__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_info( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_set_info = pmpi_file_set_info +#else +extern FORTRAN_API void FORT_CALL mpi_file_set_info_( MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_set_info_ = pmpi_file_set_info_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_SET_INFO MPI_FILE_SET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_info__ mpi_file_set_info__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_info mpi_file_set_info +#else +#pragma _HP_SECONDARY_DEF pmpi_file_set_info_ mpi_file_set_info_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_SET_INFO as PMPI_FILE_SET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_info__ as pmpi_file_set_info__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_info as pmpi_file_set_info +#else +#pragma _CRI duplicate mpi_file_set_info_ as pmpi_file_set_info_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_set_info_ PMPI_FILE_SET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_info_ pmpi_file_set_info__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_info pmpi_file_set_info_ +#endif +#define mpi_file_set_info_ pmpi_file_set_info +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_info_ pmpi_file_set_info +#endif +#define mpi_file_set_info_ pmpi_file_set_info_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_set_info_ MPI_FILE_SET_INFO +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_info_ mpi_file_set_info__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_info mpi_file_set_info_ +#endif +#define mpi_file_set_info_ mpi_file_set_info +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_info_ mpi_file_set_info +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_set_info_(MPI_Fint *fh, MPI_Fint *info, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_set_info_(MPI_Fint *fh, MPI_Fint *info, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Info info_c; + + fh_c = MPI_File_f2c(*fh); + info_c = MPI_Info_f2c(*info); + + *ierr = MPI_File_set_info(fh_c, info_c); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/set_sizef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_sizef.c new file mode 100644 index 0000000000..c595f2b855 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_sizef.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_SET_SIZE( MPI_Fint *, MPI_Offset *, MPI_Fint * ); +#pragma weak MPI_FILE_SET_SIZE = PMPI_FILE_SET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_size__( MPI_Fint *, MPI_Offset *, MPI_Fint * ); +#pragma weak mpi_file_set_size__ = pmpi_file_set_size__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_size( MPI_Fint *, MPI_Offset *, MPI_Fint * ); +#pragma weak mpi_file_set_size = pmpi_file_set_size +#else +extern FORTRAN_API void FORT_CALL mpi_file_set_size_( MPI_Fint *, MPI_Offset *, MPI_Fint * ); +#pragma weak mpi_file_set_size_ = pmpi_file_set_size_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_SET_SIZE MPI_FILE_SET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_size__ mpi_file_set_size__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_size mpi_file_set_size +#else +#pragma _HP_SECONDARY_DEF pmpi_file_set_size_ mpi_file_set_size_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_SET_SIZE as PMPI_FILE_SET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_size__ as pmpi_file_set_size__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_size as pmpi_file_set_size +#else +#pragma _CRI duplicate mpi_file_set_size_ as pmpi_file_set_size_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_set_size_ PMPI_FILE_SET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_size_ pmpi_file_set_size__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_size pmpi_file_set_size_ +#endif +#define mpi_file_set_size_ pmpi_file_set_size +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_size_ pmpi_file_set_size +#endif +#define mpi_file_set_size_ pmpi_file_set_size_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_set_size_ MPI_FILE_SET_SIZE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_size_ mpi_file_set_size__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_size mpi_file_set_size_ +#endif +#define mpi_file_set_size_ mpi_file_set_size +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_size_ mpi_file_set_size +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_set_size_(MPI_Fint *fh,MPI_Offset *size, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_set_size_(MPI_Fint *fh,MPI_Offset *size, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_set_size(fh_c,*size); +} + diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/set_viewf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_viewf.c new file mode 100644 index 0000000000..97151d978f --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/set_viewf.c @@ -0,0 +1,182 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#ifdef _UNICOS +#include +#endif +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_SET_VIEW( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint *, char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak MPI_FILE_SET_VIEW = PMPI_FILE_SET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_view__( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint *, char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_set_view__ = pmpi_file_set_view__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_set_view( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint *, char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_set_view = pmpi_file_set_view +#else +extern FORTRAN_API void FORT_CALL mpi_file_set_view_( MPI_Fint *, MPI_Offset *, MPI_Fint *, MPI_Fint *, char * FORT_MIXED_LEN_DECL, MPI_Fint *, MPI_Fint * FORT_END_LEN_DECL ); +#pragma weak mpi_file_set_view_ = pmpi_file_set_view_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_SET_VIEW MPI_FILE_SET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_view__ mpi_file_set_view__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_set_view mpi_file_set_view +#else +#pragma _HP_SECONDARY_DEF pmpi_file_set_view_ mpi_file_set_view_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_SET_VIEW as PMPI_FILE_SET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_view__ as pmpi_file_set_view__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_set_view as pmpi_file_set_view +#else +#pragma _CRI duplicate mpi_file_set_view_ as pmpi_file_set_view_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_set_view_ PMPI_FILE_SET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_view_ pmpi_file_set_view__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_view pmpi_file_set_view_ +#endif +#define mpi_file_set_view_ pmpi_file_set_view +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_set_view_ pmpi_file_set_view +#endif +#define mpi_file_set_view_ pmpi_file_set_view_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_set_view_ MPI_FILE_SET_VIEW +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_set_view_ mpi_file_set_view__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_view mpi_file_set_view_ +#endif +#define mpi_file_set_view_ mpi_file_set_view +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_set_view_ mpi_file_set_view +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_set_view_(MPI_Fint *fh,MPI_Offset *disp,MPI_Fint *etype, + MPI_Fint *filetype,char *datarep,MPI_Fint *info, MPI_Fint *ierr, + int str_len ); + +void mpi_file_set_view_(MPI_Fint *fh,MPI_Offset *disp,MPI_Fint *etype, + MPI_Fint *filetype,char *datarep,MPI_Fint *info, MPI_Fint *ierr, + int str_len ) +{ + char *newstr; + MPI_File fh_c; + int i, real_len; + MPI_Datatype etype_c, filetype_c; + MPI_Info info_c; + + etype_c = MPI_Type_f2c(*etype); + filetype_c = MPI_Type_f2c(*filetype); + info_c = MPI_Info_f2c(*info); + + /* strip trailing blanks in datarep */ + if (datarep <= (char *) 0) { + FPRINTF(stderr, "MPI_File_set_view: datarep is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + for (i=str_len-1; i>=0; i--) if (datarep[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_File_set_view: datarep is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + real_len = i + 1; + + newstr = (char *) ADIOI_Malloc((real_len+1)*sizeof(char)); + ADIOI_Strncpy(newstr, datarep, real_len); + newstr[real_len] = '\0'; + + fh_c = MPI_File_f2c(*fh); + + *ierr = MPI_File_set_view(fh_c,*disp,etype_c,filetype_c,newstr,info_c); + + ADIOI_Free(newstr); +} + +#else + +#ifdef _UNICOS +void mpi_file_set_view_(MPI_Fint *fh,MPI_Offset *disp,MPI_Datatype *etype, + MPI_Datatype *filetype,_fcd datarep_fcd,MPI_Fint *info, MPI_Fint *ierr) +{ + char *datarep = _fcdtocp(datarep_fcd); + int str_len = _fcdlen(datarep_fcd); +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_set_view_( MPI_Fint *fh, MPI_Offset *disp, MPI_Fint *etype, MPI_Fint *filetype, char *datarep FORT_MIXED_LEN_DECL, MPI_Fint *info, MPI_Fint *ierr FORT_END_LEN_DECL ); + +FORTRAN_API void FORT_CALL mpi_file_set_view_( MPI_Fint *fh, MPI_Offset *disp, MPI_Fint *etype, MPI_Fint *filetype, char *datarep FORT_MIXED_LEN(str_len), MPI_Fint *info, MPI_Fint *ierr FORT_END_LEN(str_len) ) +{ +#endif + char *newstr; + MPI_File fh_c; + int i, real_len; + MPI_Info info_c; + + info_c = MPI_Info_f2c(*info); + + /* strip trailing blanks in datarep */ + if (datarep <= (char *) 0) { + FPRINTF(stderr, "MPI_File_set_view: datarep is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + for (i=str_len-1; i>=0; i--) if (datarep[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_File_set_view: datarep is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + real_len = i + 1; + + newstr = (char *) ADIOI_Malloc((real_len+1)*sizeof(char)); + ADIOI_Strncpy(newstr, datarep, real_len); + newstr[real_len] = '\0'; + + fh_c = MPI_File_f2c(*fh); + + *ierr = MPI_File_set_view(fh_c,*disp,*etype,*filetype,newstr,info_c); + + ADIOI_Free(newstr); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/wr_atallbf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/wr_atallbf.c new file mode 100644 index 0000000000..836dd378ae --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/wr_atallbf.c @@ -0,0 +1,122 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_AT_ALL_BEGIN( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_AT_ALL_BEGIN = PMPI_FILE_WRITE_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_at_all_begin__( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_write_at_all_begin__ = pmpi_file_write_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_at_all_begin( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_write_at_all_begin = pmpi_file_write_at_all_begin +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_at_all_begin_( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_write_at_all_begin_ = pmpi_file_write_at_all_begin_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_AT_ALL_BEGIN MPI_FILE_WRITE_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_begin__ mpi_file_write_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_begin mpi_file_write_at_all_begin +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_begin_ mpi_file_write_at_all_begin_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_AT_ALL_BEGIN as PMPI_FILE_WRITE_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_at_all_begin__ as pmpi_file_write_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_at_all_begin as pmpi_file_write_at_all_begin +#else +#pragma _CRI duplicate mpi_file_write_at_all_begin_ as pmpi_file_write_at_all_begin_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_at_all_begin_ PMPI_FILE_WRITE_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_at_all_begin_ pmpi_file_write_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_begin pmpi_file_write_at_all_begin_ +#endif +#define mpi_file_write_at_all_begin_ pmpi_file_write_at_all_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_begin_ pmpi_file_write_at_all_begin +#endif +#define mpi_file_write_at_all_begin_ pmpi_file_write_at_all_begin_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_at_all_begin_ MPI_FILE_WRITE_AT_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_at_all_begin_ mpi_file_write_at_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_at_all_begin mpi_file_write_at_all_begin_ +#endif +#define mpi_file_write_at_all_begin_ mpi_file_write_at_all_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_at_all_begin_ mpi_file_write_at_all_begin +#endif +#endif +#endif + + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_write_at_all_begin_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, MPI_Fint *ierr ); + +void mpi_file_write_at_all_begin_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_write_at_all_begin(fh_c,*offset,buf,*count,datatype_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_at_all_begin_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_at_all_begin_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_write_at_all_begin(fh_c,*offset,buf,*count,(MPI_Datatype)*datatype); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/wr_atallef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/wr_atallef.c new file mode 100644 index 0000000000..7426c48bf2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/wr_atallef.c @@ -0,0 +1,103 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_AT_ALL_END( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_AT_ALL_END = PMPI_FILE_WRITE_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_at_all_end__( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_at_all_end__ = pmpi_file_write_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_at_all_end( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_at_all_end = pmpi_file_write_at_all_end +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_at_all_end_( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_at_all_end_ = pmpi_file_write_at_all_end_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_AT_ALL_END MPI_FILE_WRITE_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_end__ mpi_file_write_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_end mpi_file_write_at_all_end +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_end_ mpi_file_write_at_all_end_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_AT_ALL_END as PMPI_FILE_WRITE_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_at_all_end__ as pmpi_file_write_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_at_all_end as pmpi_file_write_at_all_end +#else +#pragma _CRI duplicate mpi_file_write_at_all_end_ as pmpi_file_write_at_all_end_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_at_all_end_ PMPI_FILE_WRITE_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_at_all_end_ pmpi_file_write_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_end pmpi_file_write_at_all_end_ +#endif +#define mpi_file_write_at_all_end_ pmpi_file_write_at_all_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_end_ pmpi_file_write_at_all_end +#endif +#define mpi_file_write_at_all_end_ pmpi_file_write_at_all_end_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_at_all_end_ MPI_FILE_WRITE_AT_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_at_all_end_ mpi_file_write_at_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_at_all_end mpi_file_write_at_all_end_ +#endif +#define mpi_file_write_at_all_end_ mpi_file_write_at_all_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_at_all_end_ mpi_file_write_at_all_end +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_at_all_end_(MPI_Fint *fh,void *buf,MPI_Status *status, + MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_at_all_end_(MPI_Fint *fh,void *buf,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + + *ierr = MPI_File_write_at_all_end(fh_c,buf,status); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/write_allbf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_allbf.c new file mode 100644 index 0000000000..e47d3cd200 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_allbf.c @@ -0,0 +1,117 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_ALL_BEGIN( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_ALL_BEGIN = PMPI_FILE_WRITE_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_all_begin__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_write_all_begin__ = pmpi_file_write_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_all_begin( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_write_all_begin = pmpi_file_write_all_begin +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_all_begin_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_write_all_begin_ = pmpi_file_write_all_begin_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_ALL_BEGIN MPI_FILE_WRITE_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_begin__ mpi_file_write_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_begin mpi_file_write_all_begin +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_begin_ mpi_file_write_all_begin_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_ALL_BEGIN as PMPI_FILE_WRITE_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_all_begin__ as pmpi_file_write_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_all_begin as pmpi_file_write_all_begin +#else +#pragma _CRI duplicate mpi_file_write_all_begin_ as pmpi_file_write_all_begin_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_all_begin_ PMPI_FILE_WRITE_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_all_begin_ pmpi_file_write_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_begin pmpi_file_write_all_begin_ +#endif +#define mpi_file_write_all_begin_ pmpi_file_write_all_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_begin_ pmpi_file_write_all_begin +#endif +#define mpi_file_write_all_begin_ pmpi_file_write_all_begin_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_all_begin_ MPI_FILE_WRITE_ALL_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_all_begin_ mpi_file_write_all_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_all_begin mpi_file_write_all_begin_ +#endif +#define mpi_file_write_all_begin_ mpi_file_write_all_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_all_begin_ mpi_file_write_all_begin +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_write_all_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ); +void mpi_file_write_all_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ){ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_write_all_begin(fh_c,buf,*count,datatype_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_all_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ); +FORTRAN_API void FORT_CALL mpi_file_write_all_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_write_all_begin(fh_c,buf,*count,(MPI_Datatype)*datatype); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/write_allef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_allef.c new file mode 100644 index 0000000000..9ccc1eb8db --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_allef.c @@ -0,0 +1,101 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_ALL_END( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_ALL_END = PMPI_FILE_WRITE_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_all_end__( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_all_end__ = pmpi_file_write_all_end__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_all_end( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_all_end = pmpi_file_write_all_end +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_all_end_( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_all_end_ = pmpi_file_write_all_end_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_ALL_END MPI_FILE_WRITE_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_end__ mpi_file_write_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_end mpi_file_write_all_end +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_end_ mpi_file_write_all_end_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_ALL_END as PMPI_FILE_WRITE_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_all_end__ as pmpi_file_write_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_all_end as pmpi_file_write_all_end +#else +#pragma _CRI duplicate mpi_file_write_all_end_ as pmpi_file_write_all_end_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_all_end_ PMPI_FILE_WRITE_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_all_end_ pmpi_file_write_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_end pmpi_file_write_all_end_ +#endif +#define mpi_file_write_all_end_ pmpi_file_write_all_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_end_ pmpi_file_write_all_end +#endif +#define mpi_file_write_all_end_ pmpi_file_write_all_end_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_all_end_ MPI_FILE_WRITE_ALL_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_all_end_ mpi_file_write_all_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_all_end mpi_file_write_all_end_ +#endif +#define mpi_file_write_all_end_ mpi_file_write_all_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_all_end_ mpi_file_write_all_end +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_all_end_(MPI_Fint *fh,void *buf,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_all_end_(MPI_Fint *fh,void *buf,MPI_Status *status, MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + + *ierr = MPI_File_write_all_end(fh_c,buf,status); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/write_allf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_allf.c new file mode 100644 index 0000000000..bddcac1509 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_allf.c @@ -0,0 +1,119 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_ALL( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_ALL = PMPI_FILE_WRITE_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_all__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_all__ = pmpi_file_write_all__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_all( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_all = pmpi_file_write_all +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_all_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_all_ = pmpi_file_write_all_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_ALL MPI_FILE_WRITE_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all__ mpi_file_write_all__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all mpi_file_write_all +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_ mpi_file_write_all_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_ALL as PMPI_FILE_WRITE_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_all__ as pmpi_file_write_all__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_all as pmpi_file_write_all +#else +#pragma _CRI duplicate mpi_file_write_all_ as pmpi_file_write_all_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_all_ PMPI_FILE_WRITE_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_all_ pmpi_file_write_all__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all pmpi_file_write_all_ +#endif +#define mpi_file_write_all_ pmpi_file_write_all +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_all_ pmpi_file_write_all +#endif +#define mpi_file_write_all_ pmpi_file_write_all_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_all_ MPI_FILE_WRITE_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_all_ mpi_file_write_all__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_all mpi_file_write_all_ +#endif +#define mpi_file_write_all_ mpi_file_write_all +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_all_ mpi_file_write_all +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_write_all_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_write_all_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ){ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_write_all(fh_c,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_all_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_all_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_write_all(fh_c,buf,*count,*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/write_atallf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_atallf.c new file mode 100644 index 0000000000..030e7ae359 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_atallf.c @@ -0,0 +1,125 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_AT_ALL( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_AT_ALL = PMPI_FILE_WRITE_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_at_all__( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_at_all__ = pmpi_file_write_at_all__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_at_all( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_at_all = pmpi_file_write_at_all +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_at_all_( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_at_all_ = pmpi_file_write_at_all_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_AT_ALL MPI_FILE_WRITE_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all__ mpi_file_write_at_all__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all mpi_file_write_at_all +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_ mpi_file_write_at_all_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_AT_ALL as PMPI_FILE_WRITE_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_at_all__ as pmpi_file_write_at_all__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_at_all as pmpi_file_write_at_all +#else +#pragma _CRI duplicate mpi_file_write_at_all_ as pmpi_file_write_at_all_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_at_all_ PMPI_FILE_WRITE_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_at_all_ pmpi_file_write_at_all__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all pmpi_file_write_at_all_ +#endif +#define mpi_file_write_at_all_ pmpi_file_write_at_all +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_all_ pmpi_file_write_at_all +#endif +#define mpi_file_write_at_all_ pmpi_file_write_at_all_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_at_all_ MPI_FILE_WRITE_AT_ALL +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_at_all_ mpi_file_write_at_all__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_at_all mpi_file_write_at_all_ +#endif +#define mpi_file_write_at_all_ mpi_file_write_at_all +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_at_all_ mpi_file_write_at_all +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_write_at_all_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_write_at_all_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_write_at_all(fh_c,*offset,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_at_all_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_at_all_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_write_at_all(fh_c,*offset,buf,*count,*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/write_atf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_atf.c new file mode 100644 index 0000000000..8ba429dcc6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_atf.c @@ -0,0 +1,125 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_AT( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_AT = PMPI_FILE_WRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_at__( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_at__ = pmpi_file_write_at__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_at( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_at = pmpi_file_write_at +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_at_( MPI_Fint *, MPI_Offset *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_at_ = pmpi_file_write_at_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_AT MPI_FILE_WRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at__ mpi_file_write_at__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at mpi_file_write_at +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_ mpi_file_write_at_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_AT as PMPI_FILE_WRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_at__ as pmpi_file_write_at__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_at as pmpi_file_write_at +#else +#pragma _CRI duplicate mpi_file_write_at_ as pmpi_file_write_at_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_at_ PMPI_FILE_WRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_at_ pmpi_file_write_at__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at pmpi_file_write_at_ +#endif +#define mpi_file_write_at_ pmpi_file_write_at +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_at_ pmpi_file_write_at +#endif +#define mpi_file_write_at_ pmpi_file_write_at_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_at_ MPI_FILE_WRITE_AT +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_at_ mpi_file_write_at__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_at mpi_file_write_at_ +#endif +#define mpi_file_write_at_ mpi_file_write_at +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_at_ mpi_file_write_at +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_write_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_write_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_write_at(fh_c,*offset,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_at_(MPI_Fint *fh,MPI_Offset *offset,void *buf, + MPI_Fint *count,MPI_Fint *datatype, + MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_write_at(fh_c,*offset,buf,*count,*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/write_ordbf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_ordbf.c new file mode 100644 index 0000000000..41b9accfbe --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_ordbf.c @@ -0,0 +1,119 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_ORDERED_BEGIN( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_ORDERED_BEGIN = PMPI_FILE_WRITE_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_ordered_begin__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_write_ordered_begin__ = pmpi_file_write_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_ordered_begin( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_write_ordered_begin = pmpi_file_write_ordered_begin +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_ordered_begin_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Fint * ); +#pragma weak mpi_file_write_ordered_begin_ = pmpi_file_write_ordered_begin_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_ORDERED_BEGIN MPI_FILE_WRITE_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_begin__ mpi_file_write_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_begin mpi_file_write_ordered_begin +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_begin_ mpi_file_write_ordered_begin_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_ORDERED_BEGIN as PMPI_FILE_WRITE_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_ordered_begin__ as pmpi_file_write_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_ordered_begin as pmpi_file_write_ordered_begin +#else +#pragma _CRI duplicate mpi_file_write_ordered_begin_ as pmpi_file_write_ordered_begin_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_ordered_begin_ PMPI_FILE_WRITE_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_ordered_begin_ pmpi_file_write_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_begin pmpi_file_write_ordered_begin_ +#endif +#define mpi_file_write_ordered_begin_ pmpi_file_write_ordered_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_begin_ pmpi_file_write_ordered_begin +#endif +#define mpi_file_write_ordered_begin_ pmpi_file_write_ordered_begin_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_ordered_begin_ MPI_FILE_WRITE_ORDERED_BEGIN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_ordered_begin_ mpi_file_write_ordered_begin__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_ordered_begin mpi_file_write_ordered_begin_ +#endif +#define mpi_file_write_ordered_begin_ mpi_file_write_ordered_begin +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_ordered_begin_ mpi_file_write_ordered_begin +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_write_ordered_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ); + +void mpi_file_write_ordered_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ){ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_write_ordered_begin(fh_c,buf,*count,datatype_c); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_ordered_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_ordered_begin_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype, MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_write_ordered_begin(fh_c,buf,*count,*datatype); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/write_ordef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_ordef.c new file mode 100644 index 0000000000..a979f70eee --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_ordef.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_ORDERED_END( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_ORDERED_END = PMPI_FILE_WRITE_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_ordered_end__( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_ordered_end__ = pmpi_file_write_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_ordered_end( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_ordered_end = pmpi_file_write_ordered_end +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_ordered_end_( MPI_Fint *, void*, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_ordered_end_ = pmpi_file_write_ordered_end_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_ORDERED_END MPI_FILE_WRITE_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_end__ mpi_file_write_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_end mpi_file_write_ordered_end +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_end_ mpi_file_write_ordered_end_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_ORDERED_END as PMPI_FILE_WRITE_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_ordered_end__ as pmpi_file_write_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_ordered_end as pmpi_file_write_ordered_end +#else +#pragma _CRI duplicate mpi_file_write_ordered_end_ as pmpi_file_write_ordered_end_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_ordered_end_ PMPI_FILE_WRITE_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_ordered_end_ pmpi_file_write_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_end pmpi_file_write_ordered_end_ +#endif +#define mpi_file_write_ordered_end_ pmpi_file_write_ordered_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_end_ pmpi_file_write_ordered_end +#endif +#define mpi_file_write_ordered_end_ pmpi_file_write_ordered_end_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_ordered_end_ MPI_FILE_WRITE_ORDERED_END +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_ordered_end_ mpi_file_write_ordered_end__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_ordered_end mpi_file_write_ordered_end_ +#endif +#define mpi_file_write_ordered_end_ mpi_file_write_ordered_end +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_ordered_end_ mpi_file_write_ordered_end +#endif +#endif +#endif + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_ordered_end_(MPI_Fint *fh,void *buf,MPI_Status *status, + MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_ordered_end_(MPI_Fint *fh,void *buf,MPI_Status *status, MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + + *ierr = MPI_File_write_ordered_end(fh_c,buf,status); +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/write_ordf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_ordf.c new file mode 100644 index 0000000000..fe96406d9b --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_ordf.c @@ -0,0 +1,119 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_ORDERED( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_ORDERED = PMPI_FILE_WRITE_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_ordered__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_ordered__ = pmpi_file_write_ordered__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_ordered( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_ordered = pmpi_file_write_ordered +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_ordered_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_ordered_ = pmpi_file_write_ordered_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_ORDERED MPI_FILE_WRITE_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered__ mpi_file_write_ordered__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered mpi_file_write_ordered +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_ mpi_file_write_ordered_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_ORDERED as PMPI_FILE_WRITE_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_ordered__ as pmpi_file_write_ordered__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_ordered as pmpi_file_write_ordered +#else +#pragma _CRI duplicate mpi_file_write_ordered_ as pmpi_file_write_ordered_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_ordered_ PMPI_FILE_WRITE_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_ordered_ pmpi_file_write_ordered__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered pmpi_file_write_ordered_ +#endif +#define mpi_file_write_ordered_ pmpi_file_write_ordered +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ordered_ pmpi_file_write_ordered +#endif +#define mpi_file_write_ordered_ pmpi_file_write_ordered_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_ordered_ MPI_FILE_WRITE_ORDERED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_ordered_ mpi_file_write_ordered__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_ordered mpi_file_write_ordered_ +#endif +#define mpi_file_write_ordered_ mpi_file_write_ordered +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_ordered_ mpi_file_write_ordered +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_write_ordered_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_write_ordered_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ){ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_write_ordered(fh_c,buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_ordered_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_ordered_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ){ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_write_ordered(fh_c,buf,*count,*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/write_shf.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_shf.c new file mode 100644 index 0000000000..30d80e0ee6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/write_shf.c @@ -0,0 +1,121 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE_SHARED( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE_SHARED = PMPI_FILE_WRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_shared__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_shared__ = pmpi_file_write_shared__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write_shared( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_shared = pmpi_file_write_shared +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_shared_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_shared_ = pmpi_file_write_shared_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE_SHARED MPI_FILE_WRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_shared__ mpi_file_write_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write_shared mpi_file_write_shared +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_shared_ mpi_file_write_shared_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE_SHARED as PMPI_FILE_WRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_shared__ as pmpi_file_write_shared__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write_shared as pmpi_file_write_shared +#else +#pragma _CRI duplicate mpi_file_write_shared_ as pmpi_file_write_shared_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_shared_ PMPI_FILE_WRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_shared_ pmpi_file_write_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_shared pmpi_file_write_shared_ +#endif +#define mpi_file_write_shared_ pmpi_file_write_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_shared_ pmpi_file_write_shared +#endif +#define mpi_file_write_shared_ pmpi_file_write_shared_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_shared_ MPI_FILE_WRITE_SHARED +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_shared_ mpi_file_write_shared__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_shared mpi_file_write_shared_ +#endif +#define mpi_file_write_shared_ mpi_file_write_shared +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_shared_ mpi_file_write_shared +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_write_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_write_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_write_shared(fh_c, buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_shared_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_write_shared(fh_c, buf,*count,*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fortran/writef.c b/ompi/mca/io/romio314/romio/mpi-io/fortran/writef.c new file mode 100644 index 0000000000..9b07ba095f --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fortran/writef.c @@ -0,0 +1,121 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_FILE_WRITE( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak MPI_FILE_WRITE = PMPI_FILE_WRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write__( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write__ = pmpi_file_write__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_file_write( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write = pmpi_file_write +#else +extern FORTRAN_API void FORT_CALL mpi_file_write_( MPI_Fint *, void*, MPI_Fint *, MPI_Fint *, MPI_Status*, MPI_Fint * ); +#pragma weak mpi_file_write_ = pmpi_file_write_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_FILE_WRITE MPI_FILE_WRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write__ mpi_file_write__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_file_write mpi_file_write +#else +#pragma _HP_SECONDARY_DEF pmpi_file_write_ mpi_file_write_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_FILE_WRITE as PMPI_FILE_WRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_file_write__ as pmpi_file_write__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_file_write as pmpi_file_write +#else +#pragma _CRI duplicate mpi_file_write_ as pmpi_file_write_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_file_write_ PMPI_FILE_WRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_ pmpi_file_write__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write pmpi_file_write_ +#endif +#define mpi_file_write_ pmpi_file_write +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_file_write_ pmpi_file_write +#endif +#define mpi_file_write_ pmpi_file_write_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_file_write_ MPI_FILE_WRITE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_file_write_ mpi_file_write__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write mpi_file_write_ +#endif +#define mpi_file_write_ mpi_file_write +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_file_write_ mpi_file_write +#endif +#endif +#endif + +#if defined(MPIHP) || defined(MPILAM) +/* Prototype to keep compiler happy */ +void mpi_file_write_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +void mpi_file_write_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + MPI_Datatype datatype_c; + + fh_c = MPI_File_f2c(*fh); + datatype_c = MPI_Type_f2c(*datatype); + + *ierr = MPI_File_write(fh_c, buf,*count,datatype_c,status); +} +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL mpi_file_write_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL mpi_file_write_(MPI_Fint *fh,void *buf,MPI_Fint *count, + MPI_Fint *datatype,MPI_Status *status, MPI_Fint *ierr ) +{ + MPI_File fh_c; + + fh_c = MPI_File_f2c(*fh); + *ierr = MPI_File_write(fh_c, buf,*count,*datatype,status); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/fsync.c b/ompi/mca/io/romio314/romio/mpi-io/fsync.c new file mode 100644 index 0000000000..0e4f1b964a --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/fsync.c @@ -0,0 +1,76 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_sync = PMPI_File_sync +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_sync MPI_File_sync +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_sync as PMPI_File_sync +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_sync(MPI_File fh) __attribute__((weak,alias("PMPI_File_sync"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_sync - Causes all previous writes to be transferred + to the storage device + +Input Parameters: +. fh - file handle (handle) + +.N fortran +@*/ +int MPI_File_sync(MPI_File fh) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_SYNC"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILESYNC, TRDTBLOCK, adio_fh, + MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + /* --BEGIN ERROR HANDLING-- */ + if ((adio_fh <= (MPI_File) 0) || ((adio_fh)->cookie != ADIOI_FILE_COOKIE)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iobadfh", 0); + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + } + MPIO_CHECK_WRITABLE(fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + ADIO_Flush(adio_fh, &error_code); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, adio_fh, MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_amode.c b/ompi/mca/io/romio314/romio/mpi-io/get_amode.c new file mode 100644 index 0000000000..4770c83959 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_amode.c @@ -0,0 +1,55 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_amode = PMPI_File_get_amode +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_amode MPI_File_get_amode +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_amode as PMPI_File_get_amode +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_amode(MPI_File fh, int *amode) __attribute__((weak,alias("PMPI_File_get_amode"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_amode - Returns the file access mode + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. amode - access mode (integer) + +.N fortran +@*/ +int MPI_File_get_amode(MPI_File fh, int *amode) +{ + int error_code=MPI_SUCCESS; + static char myname[] = "MPI_FILE_GET_AMODE"; + ADIO_File adio_fh; + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + *amode = adio_fh->access_mode; + +fn_exit: + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_atom.c b/ompi/mca/io/romio314/romio/mpi-io/get_atom.c new file mode 100644 index 0000000000..1a9eae1389 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_atom.c @@ -0,0 +1,55 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_atomicity = PMPI_File_get_atomicity +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_atomicity MPI_File_get_atomicity +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_atomicity as PMPI_File_get_atomicity +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_atomicity(MPI_File fh, int *flag) __attribute__((weak,alias("PMPI_File_get_atomicity"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_atomicity - Returns the atomicity mode + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. flag - true if atomic mode, false if nonatomic mode (logical) + +.N fortran +@*/ +int MPI_File_get_atomicity(MPI_File fh, int *flag) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_GET_ATOMICITY"; + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + *flag = adio_fh->atomicity; + +fn_exit: + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_bytoff.c b/ompi/mca/io/romio314/romio/mpi-io/get_bytoff.c new file mode 100644 index 0000000000..f5cb452e5a --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_bytoff.c @@ -0,0 +1,71 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" +#include "adioi.h" /* ADIOI_Get_byte_offset() prototype */ + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_byte_offset = PMPI_File_get_byte_offset +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_byte_offset MPI_File_get_byte_offset +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_byte_offset as PMPI_File_get_byte_offset +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_byte_offset(MPI_File fh, MPI_Offset offset, MPI_Offset *disp) __attribute__((weak,alias("PMPI_File_get_byte_offset"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_byte_offset - Returns the absolute byte position in + the file corresponding to "offset" etypes relative to + the current view + +Input Parameters: +. fh - file handle (handle) +. offset - offset (nonnegative integer) + +Output Parameters: +. disp - absolute byte position of offset (nonnegative integer) + +.N fortran +@*/ +int MPI_File_get_byte_offset(MPI_File fh, MPI_Offset offset, MPI_Offset *disp) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_GET_BYTE_OFFSET"; + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + + if (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; + } + + MPIO_CHECK_NOT_SEQUENTIAL_MODE(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + ADIOI_Get_byte_offset(adio_fh, offset, disp); + +fn_exit: + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_errh.c b/ompi/mca/io/romio314/romio/mpi-io/get_errh.c new file mode 100644 index 0000000000..5a4d9ee484 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_errh.c @@ -0,0 +1,71 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" +#include "adio_extern.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_errhandler = PMPI_File_get_errhandler +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_errhandler MPI_File_get_errhandler +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_errhandler as PMPI_File_get_errhandler +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_errhandler(MPI_File file, MPI_Errhandler *errhandler) __attribute__((weak,alias("PMPI_File_get_errhandler"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_errhandler - Returns the error handler for a file + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. errhandler - error handler (handle) + +.N fortran +@*/ +int MPI_File_get_errhandler(MPI_File mpi_fh, MPI_Errhandler *errhandler) +{ + int error_code = MPI_SUCCESS; + ADIO_File fh; + static char myname[] = "MPI_FILE_GET_ERRHANDLER"; + MPIU_THREADPRIV_DECL; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (mpi_fh == MPI_FILE_NULL) { + *errhandler = ADIOI_DFLT_ERR_HANDLER; + } + else { + fh = MPIO_File_resolve(mpi_fh); + /* --BEGIN ERROR HANDLING-- */ + if ((fh <= (MPI_File) 0) || ((fh)->cookie != ADIOI_FILE_COOKIE)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iobadfh", 0); + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + *errhandler = fh->err_handler; + } + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_extent.c b/ompi/mca/io/romio314/romio/mpi-io/get_extent.c new file mode 100644 index 0000000000..31a841c070 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_extent.c @@ -0,0 +1,59 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_type_extent = PMPI_File_get_type_extent +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_type_extent MPI_File_get_type_extent +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_type_extent as PMPI_File_get_type_extent +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_type_extent(MPI_File fh, MPI_Datatype datatype, MPI_Aint *extent) __attribute__((weak,alias("PMPI_File_get_type_extent"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_type_extent - Returns the extent of datatype in the file + +Input Parameters: +. fh - file handle (handle) +. datatype - datatype (handle) + +Output Parameters: +. extent - extent of the datatype (nonnegative integer) + +.N fortran +@*/ +int MPI_File_get_type_extent(MPI_File fh, MPI_Datatype datatype, MPI_Aint *extent) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_GET_TYPE_EXTENT"; + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + MPIO_CHECK_DATATYPE(adio_fh, datatype, myname, error_code); + /* --END ERROR HANDLING-- */ + + /* FIXME: handle other file data representations */ + + error_code = MPI_Type_extent(datatype, extent); + +fn_exit: + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_group.c b/ompi/mca/io/romio314/romio/mpi-io/get_group.c new file mode 100644 index 0000000000..4d82ed8cb1 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_group.c @@ -0,0 +1,64 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_group = PMPI_File_get_group +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_group MPI_File_get_group +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_group as PMPI_File_get_group +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_group(MPI_File fh, MPI_Group *group) __attribute__((weak,alias("PMPI_File_get_group"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_group - Returns the group of processes that + opened the file + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. group - group that opened the file (handle) + +.N fortran +@*/ +int MPI_File_get_group(MPI_File fh, MPI_Group *group) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_GET_GROUP"; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + + /* note: this will return the group of processes that called open, but + * with deferred open this might not be the group of processes that + * actually opened the file from the file system's perspective + */ + error_code = MPI_Comm_group(adio_fh->comm, group); + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_info.c b/ompi/mca/io/romio314/romio/mpi-io/get_info.c new file mode 100644 index 0000000000..1d0b397411 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_info.c @@ -0,0 +1,62 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_info = PMPI_File_get_info +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_info MPI_File_get_info +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_info as PMPI_File_get_info +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_info(MPI_File fh, MPI_Info *info_used) __attribute__((weak,alias("PMPI_File_get_info"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_info - Returns the hints for a file that are actually being used by MPI + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. info_used - info object (handle) + +.N fortran +@*/ +int MPI_File_get_info(MPI_File fh, MPI_Info *info_used) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_GET_INFO"; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + error_code = MPI_Info_dup(adio_fh->info, info_used); + /* --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; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_posn.c b/ompi/mca/io/romio314/romio/mpi-io/get_posn.c new file mode 100644 index 0000000000..49d8e4919b --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_posn.c @@ -0,0 +1,59 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" +#include "adioi.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_position = PMPI_File_get_position +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_position MPI_File_get_position +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_position as PMPI_File_get_position +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_position(MPI_File fh, MPI_Offset *offset) __attribute__((weak,alias("PMPI_File_get_position"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_position - Returns the current position of the + individual file pointer in etype units relative to + the current view + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. offset - offset of individual file pointer (nonnegative integer) + +.N fortran +@*/ +int MPI_File_get_position(MPI_File fh, MPI_Offset *offset) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_GET_POSITION"; + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + MPIO_CHECK_NOT_SEQUENTIAL_MODE(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + ADIOI_Get_position(adio_fh, offset); + +fn_exit: + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_posn_sh.c b/ompi/mca/io/romio314/romio/mpi-io/get_posn_sh.c new file mode 100644 index 0000000000..c6172c9d73 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_posn_sh.c @@ -0,0 +1,64 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_position_shared = PMPI_File_get_position_shared +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_position_shared MPI_File_get_position_shared +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_position_shared as PMPI_File_get_position_shared +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_position_shared(MPI_File fh, MPI_Offset *offset) __attribute__((weak,alias("PMPI_File_get_position_shared"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_position_shared - Returns the current position of the + shared file pointer in etype units relative to the current view + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. offset - offset of shared file pointer (nonnegative integer) + +.N fortran +@*/ +int MPI_File_get_position_shared(MPI_File fh, MPI_Offset *offset) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_GET_POSITION_SHARED"; + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + MPIO_CHECK_NOT_SEQUENTIAL_MODE(adio_fh, myname, error_code); + MPIO_CHECK_FS_SUPPORTS_SHARED(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + ADIOI_TEST_DEFERRED(adio_fh, myname, &error_code); + + ADIO_Get_shared_fp(adio_fh, 0, offset, &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: + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_size.c b/ompi/mca/io/romio314/romio/mpi-io/get_size.c new file mode 100644 index 0000000000..d7836c2791 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_size.c @@ -0,0 +1,86 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_size = PMPI_File_get_size +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_size MPI_File_get_size +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_size as PMPI_File_get_size +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_size(MPI_File fh, MPI_Offset *size) __attribute__((weak,alias("PMPI_File_get_size"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_get_size - Returns the file size + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. size - size of the file in bytes (nonnegative integer) + +.N fortran +@*/ +int MPI_File_get_size(MPI_File fh, MPI_Offset *size) +{ + int error_code; + ADIO_File adio_fh; + ADIO_Fcntl_t *fcntl_struct; + static char myname[] = "MPI_FILE_GET_SIZE"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEGETSIZE, TRDTBLOCK, adio_fh, + MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + if(size == NULL){ + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**nullptr", "**nullptr %s", "size"); + goto fn_fail; + } + /* --END ERROR HANDLING-- */ + + ADIOI_TEST_DEFERRED(adio_fh, myname, &error_code); + + fcntl_struct = (ADIO_Fcntl_t *) ADIOI_Malloc(sizeof(ADIO_Fcntl_t)); + ADIO_Fcntl(adio_fh, ADIO_FCNTL_GET_FSIZE, fcntl_struct, &error_code); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + *size = fcntl_struct->fsize; + ADIOI_Free(fcntl_struct); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, adio_fh, MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + +fn_exit: + return error_code; +fn_fail: + /* --BEGIN ERROR HANDLING-- */ + error_code = MPIO_Err_return_file(fh, error_code); + goto fn_exit; + /* --END ERROR HANDLING-- */ +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/get_view.c b/ompi/mca/io/romio314/romio/mpi-io/get_view.c new file mode 100644 index 0000000000..f2d288952c --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/get_view.c @@ -0,0 +1,102 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_get_view = PMPI_File_get_view +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_get_view MPI_File_get_view +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_get_view as PMPI_File_get_view +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_get_view(MPI_File fh, MPI_Offset *disp, MPI_Datatype *etype, MPI_Datatype *filetype, + char *datarep) __attribute__((weak,alias("PMPI_File_get_view"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif +#ifdef MPISGI +#include "mpisgi2.h" +#endif + +/*@ + MPI_File_get_view - Returns the file view + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. disp - displacement (nonnegative integer) +. etype - elementary datatype (handle) +. filetype - filetype (handle) +. datarep - data representation (string) + +.N fortran +@*/ +int MPI_File_get_view(MPI_File fh, MPI_Offset *disp, MPI_Datatype *etype, + MPI_Datatype *filetype, char *datarep) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_GET_VIEW"; + int i, j, k, combiner; + MPI_Datatype copy_etype, copy_filetype; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + + if (datarep <= (char *) 0) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iodatarepnomem", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + *disp = adio_fh->disp; + ADIOI_Strncpy(datarep, + (adio_fh->is_external32 ? "external32": "native"), MPI_MAX_DATAREP_STRING); + + MPI_Type_get_envelope(adio_fh->etype, &i, &j, &k, &combiner); + if (combiner == MPI_COMBINER_NAMED) *etype = adio_fh->etype; + else { + /* FIXME: It is wrong to use MPI_Type_contiguous; the user could choose to + re-implement MPI_Type_contiguous in an unexpected way. Either use + MPIR_Barrier_impl as in MPICH or PMPI_Type_contiguous */ + MPI_Type_contiguous(1, adio_fh->etype, ©_etype); + + /* FIXME: Ditto for MPI_Type_commit - use NMPI or PMPI */ + MPI_Type_commit(©_etype); + *etype = copy_etype; + } + /* FIXME: Ditto for MPI_Type_xxx - use NMPI or PMPI */ + MPI_Type_get_envelope(adio_fh->filetype, &i, &j, &k, &combiner); + if (combiner == MPI_COMBINER_NAMED) *filetype = adio_fh->filetype; + else { + MPI_Type_contiguous(1, adio_fh->filetype, ©_filetype); + + MPI_Type_commit(©_filetype); + *filetype = copy_filetype; + } + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/glue/Makefile.mk b/ompi/mca/io/romio314/romio/mpi-io/glue/Makefile.mk new file mode 100644 index 0000000000..05954a167c --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/glue/Makefile.mk @@ -0,0 +1,14 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +include $(top_srcdir)/mpi-io/glue/default/Makefile.mk +include $(top_srcdir)/mpi-io/glue/mpich/Makefile.mk + +if !BUILD_ROMIO_EMBEDDED +romio_other_sources += \ + mpi-io/glue/large_count.c +endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/glue/default/Makefile.mk b/ompi/mca/io/romio314/romio/mpi-io/glue/default/Makefile.mk new file mode 100644 index 0000000000..96995410b7 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/glue/default/Makefile.mk @@ -0,0 +1,13 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if MPIO_GLUE_DEFAULT +romio_other_sources += \ + mpi-io/glue/default/mpio_file.c \ + mpi-io/glue/default/mpio_err.c +endif MPIO_GLUE_DEFAULT + diff --git a/ompi/mca/io/romio314/romio/mpi-io/glue/default/mpio_err.c b/ompi/mca/io/romio314/romio/mpi-io/glue/default/mpio_err.c new file mode 100644 index 0000000000..fbfc8a2c97 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/glue/default/mpio_err.c @@ -0,0 +1,88 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include +#include + +#include "mpioimpl.h" +#include "adio_extern.h" + +/* Default error handling implementation. + * + * Note that only MPI_ERRORS_ARE_FATAL and MPI_ERRORS_RETURN are + * handled correctly; other handlers cause an abort. + */ + +int MPIO_Err_create_code(int lastcode, int fatal, const char fcname[], + int line, int error_class, const char generic_msg[], + const char specific_msg[], ... ) +{ + va_list Argp; + int idx = 0; + char *buf; + + buf = (char *) ADIOI_Malloc(1024); + if (buf != NULL) { + idx += ADIOI_Snprintf(buf, 1023, "%s (line %d): ", fcname, line); + if (specific_msg == NULL) { + ADIOI_Snprintf(&buf[idx], 1023 - idx, "%s\n", generic_msg); + } + else { + va_start(Argp, specific_msg); + vsnprintf(&buf[idx], 1023 - idx, specific_msg, Argp); + va_end(Argp); + } + FPRINTF(stderr, "%s", buf); + ADIOI_Free(buf); + } + + return error_class; +} + +int MPIO_Err_return_file(MPI_File mpi_fh, int error_code) +{ + ADIO_File adio_fh; + + if (mpi_fh == MPI_FILE_NULL) + { + if (ADIOI_DFLT_ERR_HANDLER == MPI_ERRORS_ARE_FATAL || + ADIOI_DFLT_ERR_HANDLER != MPI_ERRORS_RETURN) + { + MPI_Abort(MPI_COMM_WORLD, 1); + } + else + { + return error_code; + } + } + + adio_fh = MPIO_File_resolve(mpi_fh); + + if (adio_fh->err_handler == MPI_ERRORS_ARE_FATAL || + adio_fh->err_handler != MPI_ERRORS_RETURN) + { + MPI_Abort(MPI_COMM_WORLD, 1); + } + else + { + return error_code; + } +} + +int MPIO_Err_return_comm(MPI_Comm mpi_comm, int error_code) +{ + MPI_Errhandler errh; + + MPI_Errhandler_get(mpi_comm, &errh); + + if (errh == MPI_ERRORS_ARE_FATAL || + errh != MPI_ERRORS_RETURN) + { + MPI_Abort(mpi_comm, 1); + } + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/glue/default/mpio_file.c b/ompi/mca/io/romio314/romio/mpi-io/glue/default/mpio_file.c new file mode 100644 index 0000000000..7a43b01b94 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/glue/default/mpio_file.c @@ -0,0 +1,90 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +/* Hooks for allocation of MPI_File handles. + * + * Three functions are used in ROMIO for allocation/deallocation + * of MPI_File structures: + * - MPIO_File_create(size) + * - MPIO_File_resolve(mpi_fh) + * - MPIO_File_free(mpi_fh) + * + */ + +MPI_File MPIO_File_create(int size) +{ + MPI_File mpi_fh; + + mpi_fh = (MPI_File) ADIOI_Calloc(size,1); + return mpi_fh; +} + +ADIO_File MPIO_File_resolve(MPI_File mpi_fh) +{ + return mpi_fh; +} + +void MPIO_File_free(MPI_File *mpi_fh) +{ + ADIOI_Free(*mpi_fh); + *mpi_fh = MPI_FILE_NULL; +} + +extern ADIO_File *ADIOI_Ftable; +extern int ADIOI_Ftable_ptr; +extern int ADIOI_Ftable_max; + +MPI_File MPIO_File_f2c(MPI_Fint fh) +{ +#ifndef INT_LT_POINTER + return (MPI_File) ((void *) fh); + /* the extra cast is to get rid of a compiler warning on Exemplar. + The warning is because MPI_File points to a structure containing + longlongs, which may be 8-byte aligned. But MPI_Fint itself + may not be 8-byte aligned.*/ +#else + if (!fh) return MPI_FILE_NULL; + if ((fh < 0) || (fh > ADIOI_Ftable_ptr)) { + FPRINTF(stderr, "MPI_File_f2c: Invalid file handle\n"); + /* there is no way to return an error from MPI_File_f2c */ + return MPI_FILE_NULL; + } + return ADIOI_Ftable[fh]; +#endif +} + +MPI_Fint MPIO_File_c2f(MPI_File fh) +{ +#ifndef INT_LT_POINTER + return (MPI_Fint) fh; +#else + int i; + + if ((fh <= (MPI_File) 0) || (fh->cookie != ADIOI_FILE_COOKIE)) + return (MPI_Fint) 0; + if (!ADIOI_Ftable) { + ADIOI_Ftable_max = 1024; + ADIOI_Ftable = (MPI_File *) + ADIOI_Malloc(ADIOI_Ftable_max*sizeof(MPI_File)); + ADIOI_Ftable_ptr = 0; /* 0 can't be used though, because + MPI_FILE_NULL=0 */ + for (i=0; i +#include + +#include "mpioimpl.h" +#include "adio_extern.h" + +/* MPICH error handling implementation */ +/* FIXME: These external prototypes should be included from + mpich/src/include/mpiext.h */ +int MPIR_Err_create_code_valist(int, int, const char [], int, int, + const char [], const char [], va_list ); +int MPIR_Err_is_fatal(int); + +void MPIR_Get_file_error_routine( MPI_Errhandler, + void (**)(MPI_File *, int *, ...), + int * ); +int MPIR_File_call_cxx_errhandler( MPI_File *, int *, + void (*)(MPI_File *, int *, ... ) ); + +typedef int (* MPIR_Err_get_class_string_func_t)(int error, char *str, int length); +void MPIR_Err_get_string( int, char *, int, MPIR_Err_get_class_string_func_t ); + +struct MPID_Comm; +int MPID_Abort(struct MPID_Comm *comm, int mpi_errno, int exit_code, const char *error_msg); + +int MPIO_Err_create_code(int lastcode, int fatal, const char fcname[], + int line, int error_class, const char generic_msg[], + const char specific_msg[], ... ) +{ + va_list Argp; + int error_code; + + va_start(Argp, specific_msg); + + error_code = MPIR_Err_create_code_valist(lastcode, fatal, fcname, line, + error_class, generic_msg, + specific_msg, Argp); + + va_end(Argp); + + return error_code; +} + +int MPIO_Err_return_file(MPI_File mpi_fh, int error_code) +{ + MPI_Errhandler e; + void (*c_errhandler)(MPI_File *, int *, ... ); + int kind; /* Error handler kind (see below) */ + char error_msg[4096]; + int len; + + /* If the file pointer is not valid, we use the handler on + MPI_FILE_NULL (MPI-2, section 9.7). For now, this code assumes that + MPI_FILE_NULL has the default handler (return). FIXME. See + below - the set error handler uses ADIOI_DFLT_ERR_HANDLER; + */ + + /* First, get the handler and the corresponding function */ + if (mpi_fh == MPI_FILE_NULL) { + e = ADIOI_DFLT_ERR_HANDLER; + } + else { + ADIO_File fh; + + fh = MPIO_File_resolve(mpi_fh); + e = fh->err_handler; + } + + /* Actually, e is just the value provide by the MPICH routines + file_set_errhandler. This is actually a *pointer* to the + errhandler structure. We don't know that, so we ask + the MPICH code to translate this object into an error handler. + kind = 0: errors are fatal + kind = 1: errors return + kind = 2: errors call function + */ + if (e == MPI_ERRORS_RETURN || e == MPIR_ERRORS_THROW_EXCEPTIONS || !e) { + /* FIXME: This is a hack in case no error handler was set */ + kind = 1; + c_errhandler = 0; + } + else { + MPIR_Get_file_error_routine( e, &c_errhandler, &kind ); + } + + /* --BEGIN ERROR HANDLING-- */ + if (MPIR_Err_is_fatal(error_code) || kind == 0) + { + ADIOI_Snprintf(error_msg, 4096, "I/O error: "); + len = (int)strlen(error_msg); + MPIR_Err_get_string(error_code, &error_msg[len], 4096-len, NULL); + MPID_Abort(NULL, MPI_SUCCESS, error_code, error_msg); + } + /* --END ERROR HANDLING-- */ + else if (kind == 2) { + (*c_errhandler)( &mpi_fh, &error_code, 0 ); + } + else if (kind == 3) { + MPIR_File_call_cxx_errhandler( &mpi_fh, &error_code, c_errhandler ); + } + + /* kind == 1 just returns */ + return error_code; +} + +int MPIO_Err_return_comm(MPI_Comm mpi_comm, int error_code) +{ + /* note: MPI calls inside the MPICH implementation are prefixed + * with an "N", indicating a nested call. + */ + MPI_Comm_call_errhandler(mpi_comm, error_code); + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/glue/mpich/mpio_file.c b/ompi/mca/io/romio314/romio/mpi-io/glue/mpich/mpio_file.c new file mode 100644 index 0000000000..6f6c902832 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/glue/mpich/mpio_file.c @@ -0,0 +1,92 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#include "adio_extern.h" + +/* Hooks for allocation of MPI_File handles. + * + * Three functions are used in ROMIO for allocation/deallocation + * of MPI_File structures: + * - MPIO_File_create(size) + * - MPIO_File_resolve(mpi_fh) + * - MPIO_File_free(mpi_fh) + * + */ + +MPI_File MPIO_File_create(int size) +{ + MPI_File mpi_fh; + + mpi_fh = (MPI_File) ADIOI_Calloc(size,1); + return mpi_fh; +} + +ADIO_File MPIO_File_resolve(MPI_File mpi_fh) +{ + return mpi_fh; +} + +void MPIO_File_free(MPI_File *mpi_fh) +{ + ADIOI_Free(*mpi_fh); + *mpi_fh = MPI_FILE_NULL; +} + +MPI_File MPIO_File_f2c(MPI_Fint fh) +{ +#ifndef INT_LT_POINTER + return (MPI_File) ((void *) fh); + /* the extra cast is to get rid of a compiler warning on Exemplar. + The warning is because MPI_File points to a structure containing + longlongs, which may be 8-byte aligned. But MPI_Fint itself + may not be 8-byte aligned.*/ +#else + if (!fh) return MPI_FILE_NULL; + if ((fh < 0) || (fh > ADIOI_Ftable_ptr)) { + /* there is no way to return an error from MPI_File_f2c */ + return MPI_FILE_NULL; + } + return ADIOI_Ftable[fh]; +#endif +} + +MPI_Fint MPIO_File_c2f(MPI_File fh) +{ +#ifndef INT_LT_POINTER + return (MPI_Fint) fh; +#else + int i; + + if ((fh <= (MPI_File) 0) || (fh->cookie != ADIOI_FILE_COOKIE)) + return (MPI_Fint) 0; + + if (fh->fortran_handle != -1) + return fh->fortran_handle; + + if (!ADIOI_Ftable) { + ADIOI_Ftable_max = 1024; + ADIOI_Ftable = (MPI_File *) + ADIOI_Malloc(ADIOI_Ftable_max*sizeof(MPI_File)); + ADIOI_Ftable_ptr = 0; /* 0 can't be used though, because + MPI_FILE_NULL=0 */ + for (i=0; ifortran_handle = ADIOI_Ftable_ptr; + return (MPI_Fint) ADIOI_Ftable_ptr; +#endif +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/glue/openmpi/Makefile.mk b/ompi/mca/io/romio314/romio/mpi-io/glue/openmpi/Makefile.mk new file mode 100644 index 0000000000..ab7c15078e --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/glue/openmpi/Makefile.mk @@ -0,0 +1,13 @@ +## -*- Mode: Makefile; -*- +## vim: set ft=automake : +## +## (C) 2011 by Argonne National Laboratory. +## See COPYRIGHT in top-level directory. +## + +if MPIO_GLUE_OPENMPI +romio_other_sources += \ + mpi-io/glue/openmpi/mpio_file.c \ + mpi-io/glue/openmpi/mpio_err.c +endif MPIO_GLUE_OPENMPI + diff --git a/ompi/mca/io/romio314/romio/mpi-io/glue/openmpi/mpio_err.c b/ompi/mca/io/romio314/romio/mpi-io/glue/openmpi/mpio_err.c new file mode 100644 index 0000000000..2dddaee8ed --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/glue/openmpi/mpio_err.c @@ -0,0 +1,52 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include +#include + +#include "mpioimpl.h" +#include "adio_extern.h" + +/* Default error handling implementation. + * + * Note that only MPI_ERRORS_ARE_FATAL and MPI_ERRORS_RETURN are + * handled correctly; other handlers cause an abort. + */ + +int MPIO_Err_create_code(int lastcode, int fatal, const char fcname[], + int line, int error_class, const char generic_msg[], + const char specific_msg[], ...) +{ + va_list Argp; + int idx = 0; + char *buf; + + buf = (char *) ADIOI_Malloc(1024); + if (buf != NULL) { + idx += ADIOI_Snprintf(buf, 1023, "%s (line %d): ", fcname, line); + if (specific_msg == NULL) { + ADIOI_Snprintf(&buf[idx], 1023 - idx, "%s\n", generic_msg); + } + else { + va_start(Argp, specific_msg); + vsnprintf(&buf[idx], 1023 - idx, specific_msg, Argp); + va_end(Argp); + } + ADIOI_Free(buf); + } + + return error_class; +} + +int MPIO_Err_return_file(MPI_File mpi_fh, int error_code) +{ + return error_code; +} + +int MPIO_Err_return_comm(MPI_Comm mpi_comm, int error_code) +{ + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/glue/openmpi/mpio_file.c b/ompi/mca/io/romio314/romio/mpi-io/glue/openmpi/mpio_file.c new file mode 100644 index 0000000000..e3ac2e7796 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/glue/openmpi/mpio_file.c @@ -0,0 +1,95 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * + * Copyright (C) 2004 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#include "adio_extern.h" + +/* Hooks for allocation of MPI_File handles. + * + * Three functions are used in ROMIO for allocation/deallocation + * of MPI_File structures: + * - MPIO_File_create(size) + * - MPIO_File_resolve(mpi_fh) + * - MPIO_File_free(mpi_fh) + * + */ + +MPI_File MPIO_File_create(int size) +{ + MPI_File mpi_fh; + + mpi_fh = (MPI_File) ADIOI_Calloc(size, 1); + return mpi_fh; +} + +ADIO_File MPIO_File_resolve(MPI_File mpi_fh) +{ + return mpi_fh; +} + +void MPIO_File_free(MPI_File * mpi_fh) +{ + ADIOI_Free(*mpi_fh); + *mpi_fh = MPI_FILE_NULL; +} + +/* these functions aren't needed with the way Open MPI uses ROMIO */ +#if 0 + + +MPI_File MPIO_File_f2c(MPI_Fint fh) +{ +#ifndef INT_LT_POINTER + return (MPI_File) ((void *) fh); + /* the extra cast is to get rid of a compiler warning on Exemplar. + * The warning is because MPI_File points to a structure containing + * longlongs, which may be 8-byte aligned. But MPI_Fint itself + * may not be 8-byte aligned. */ +#else + if (!fh) + return MPI_FILE_NULL; + if ((fh < 0) || (fh > ADIOI_Ftable_ptr)) { + FPRINTF(stderr, "MPI_File_f2c: Invalid file handle\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + return ADIOI_Ftable[fh]; +#endif +} + +MPI_Fint MPIO_File_c2f(MPI_File fh) +{ +#ifndef INT_LT_POINTER + return (MPI_Fint) fh; +#else + int i; + + if ((fh <= (MPI_File) 0) || (fh->cookie != ADIOI_FILE_COOKIE)) + return (MPI_Fint) 0; + if (!ADIOI_Ftable) { + ADIOI_Ftable_max = 1024; + ADIOI_Ftable = (MPI_File *) + ADIOI_Malloc(ADIOI_Ftable_max * sizeof(MPI_File)); + ADIOI_Ftable_ptr = 0; /* 0 can't be used though, because + * MPI_FILE_NULL=0 */ + for (i = 0; i < ADIOI_Ftable_max; i++) + ADIOI_Ftable[i] = MPI_FILE_NULL; + } + if (ADIOI_Ftable_ptr == ADIOI_Ftable_max - 1) { + ADIOI_Ftable = (MPI_File *) ADIOI_Realloc(ADIOI_Ftable, + (ADIOI_Ftable_max + 1024) * sizeof(MPI_File)); + for (i = ADIOI_Ftable_max; i < ADIOI_Ftable_max + 1024; i++) + ADIOI_Ftable[i] = MPI_FILE_NULL; + ADIOI_Ftable_max += 1024; + } + ADIOI_Ftable_ptr++; + ADIOI_Ftable[ADIOI_Ftable_ptr] = fh; + return (MPI_Fint) ADIOI_Ftable_ptr; +#endif +} + +#endif /* #if 0 */ diff --git a/ompi/mca/io/romio314/romio/mpi-io/ioreq_c2f.c b/ompi/mca/io/romio314/romio/mpi-io/ioreq_c2f.c new file mode 100644 index 0000000000..30f4b95057 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/ioreq_c2f.c @@ -0,0 +1,82 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPIO_Request_c2f = PMPIO_Request_c2f +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPIO_Request_c2f MPIO_Request_c2f +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPIO_Request_c2f as PMPIO_Request_c2f +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif +#include "adio_extern.h" + +/*@ + MPIO_Request_c2f - Translates a C I/O-request handle to a + Fortran I/O-request handle + +Input Parameters: +. request - C I/O-request handle (handle) + +Return Value: + Fortran I/O-request handle (integer) +@*/ +#ifdef HAVE_MPI_GREQUEST +MPI_Fint MPIO_Request_c2f(MPIO_Request request) +{ + return ((MPI_Fint)request); +} +#else + +MPI_Fint MPIO_Request_c2f(MPIO_Request request) +{ +#ifndef INT_LT_POINTER + return (MPI_Fint) request; +#else + int i; + MPIU_THREADPRIV_DECL; + + /* We can make this test outside of the ALLFUNC mutex because it does + not access any shared data */ + if ((request <= (MPIO_Request) 0) || (request->cookie != ADIOI_REQ_COOKIE)) + { + return (MPI_Fint) 0; + } + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + if (!ADIOI_Reqtable) { + ADIOI_Reqtable_max = 1024; + ADIOI_Reqtable = (MPIO_Request *) + ADIOI_Malloc(ADIOI_Reqtable_max*sizeof(MPIO_Request)); + ADIOI_Reqtable_ptr = 0; /* 0 can't be used though, because + MPIO_REQUEST_NULL=0 */ + for (i=0; iPMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif +#include "adio_extern.h" + +/*@ + MPIO_Request_f2c - Translates a Fortran I/O-request handle to + a C I/O-request handle + +Input Parameters: +. request - Fortran I/O-request handle (integer) + +Return Value: + C I/O-request handle (handle) +@*/ +#ifdef HAVE_MPI_GREQUEST +MPIO_Request MPIO_Request_f2c(MPI_Fint request) { + return((MPIO_Request) request); +} +#else +MPIO_Request MPIO_Request_f2c(MPI_Fint request) +{ + int error_code; + static char myname[] = "MPIO_REQUEST_F2C"; + MPIU_THREADPRIV_DECL; + +#ifndef INT_LT_POINTER + return (MPIO_Request) request; +#else + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (!request) { + return MPIO_REQUEST_NULL; + } + /* --BEGIN ERROR HANDLING-- */ + if ((request < 0) || (request > ADIOI_Reqtable_ptr)) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_REQUEST, + "**request", 0); + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + return MPIO_REQUEST_NULL; + } + /* --END ERROR HANDLING-- */ + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return ADIOI_Reqtable[request]; +#endif +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/iotest.c b/ompi/mca/io/romio314/romio/mpi-io/iotest.c new file mode 100644 index 0000000000..9ca273d49d --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/iotest.c @@ -0,0 +1,95 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPIO_Test = PMPIO_Test +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPIO_Test MPIO_Test +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPIO_Test as PMPIO_Test +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPIO_Test - Test the completion of a nonblocking read or write + +Input Parameters: +. request - request object (handle) + +Output Parameters: +. flag - true if operation completed (logical) +. status - status object (Status) + +.N fortran +@*/ +#ifdef HAVE_MPI_GREQUEST +int MPIO_Test(MPIO_Request *request, int *flag, MPI_Status *status) +{ + return (MPI_Test(request, flag, status)); +} +#else +int MPIO_Test(MPIO_Request *request, int *flag, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPIO_TEST"; + MPIU_THREADPRIV_DECL; +#ifdef MPI_hpux + int fl_xmpi; + + if (*request != MPIO_REQUEST_NULL) { + HPMP_IO_WSTART(fl_xmpi, BLKMPIOTEST, TRDTSYSTEM, (*request)->fd); + } +#endif /* MPI_hpux */ + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (*request == MPIO_REQUEST_NULL) { + error_code = MPI_SUCCESS; + goto fn_exit; + } + + /* --BEGIN ERROR HANDLING-- */ + if ((*request < (MPIO_Request) 0) || + ((*request)->cookie != ADIOI_REQ_COOKIE)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_REQUEST, + "**request", 0); + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + switch ((*request)->optype) { + case ADIOI_READ: + *flag = ADIO_ReadDone(request, status, &error_code); + break; + case ADIOI_WRITE: + *flag = ADIO_WriteDone(request, status, &error_code); + break; + } + +#ifdef MPI_hpux + HPMP_IO_WEND(fl_xmpi); +#endif /* MPI_hpux */ + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/iotestall.c b/ompi/mca/io/romio314/romio/mpi-io/iotestall.c new file mode 100644 index 0000000000..d88aeb7766 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/iotestall.c @@ -0,0 +1,77 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPIO_Testall = PMPIO_Testall +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPIO_Testall MPIO_Testall +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPIO_Testall as PMPIO_Testall +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* + This is a temporary function until we switch to using MPI-2's generalized + requests. +*/ + +int MPIO_Testall(int count, MPIO_Request requests[], int *flag, + MPI_Status statuses[]) +{ + int done, i, err; + MPIU_THREADPRIV_DECL; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + if (count == 1) { + err = MPIO_Test( requests, flag, statuses ); + goto fn_exit; + } + + /* This is actually very difficult to do. We can't use MPIO_Test, + since we must change the requests only if *ALL* requests are complete + */ + /* FIXME: THIS IS NOT CORRECT (see above). But most applications won't + care */ + done = 1; + for (i=0; iPMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* + This is a temporary function until we switch to using MPI-2's generalized + requests. +*/ + +int MPIO_Testany(int count, MPIO_Request requests[], int *index, + int *flag, MPI_Status *status) +{ + int i, err; + MPIU_THREADPRIV_DECL; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (count == 1) { + err = MPIO_Test( requests, flag, status ); + if (!err) *index = 0; + goto fn_exit; + } + + /* Check for no active requests */ + for (i=0; iMPI_SOURCE = MPI_ANY_SOURCE; + status->MPI_TAG = MPI_ANY_TAG; + MPIR_STATUS_SET_COUNT(*status, 0); + MPIR_STATUS_SET_CANCEL_BIT(*status, 0); + } +#endif + err = MPI_SUCCESS; + goto fn_exit; + } + + err = MPI_SUCCESS; + for (i=0; iPMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* + This is a temporary function until we switch to using MPI-2's generalized + requests. +*/ + +int MPIO_Testsome(int count, MPIO_Request requests[], int *outcount, + int indices[], MPI_Status *statuses) +{ + int i, err; + int flag; + MPIU_THREADPRIV_DECL; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (count == 1) { + err = MPIO_Test( requests, &flag, statuses ); + if (!err) { + if (flag) { + indices[0] = 0; + *outcount = 1; + } + else { + *outcount = 0; + } + } + goto fn_exit; + } + + /* Check for no active requests */ + for (i=0; iPMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPIO_Wait - Waits for the completion of a nonblocking read or write + +Input Parameters: +. request - request object (handle) + +Output Parameters: +. status - status object (Status) + +.N fortran +@*/ +#ifdef HAVE_MPI_GREQUEST +int MPIO_Wait(MPIO_Request *request, MPI_Status *status) +{ + return(MPI_Wait(request, status)); +} +#else +int MPIO_Wait(MPIO_Request *request, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPIO_WAIT"; + MPIU_THREADPRIV_DECL; + +#ifdef MPI_hpux + int fl_xmpi; + + if (*request != MPIO_REQUEST_NULL) { + HPMP_IO_WSTART(fl_xmpi, BLKMPIOWAIT, TRDTBLOCK, (*request)->fd); + } +#endif /* MPI_hpux */ + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (*request == MPIO_REQUEST_NULL) { + error_code = MPI_SUCCESS; + goto fn_exit; + } + + + /* --BEGIN ERROR HANDLING-- */ + if ((*request < (MPIO_Request) 0) || + ((*request)->cookie != ADIOI_REQ_COOKIE)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_REQUEST, + "**request", 0); + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + switch ((*request)->optype) { + case ADIOI_READ: + ADIO_ReadComplete(request, status, &error_code); + break; + case ADIOI_WRITE: + ADIO_WriteComplete(request, status, &error_code); + break; + } + +#ifdef MPI_hpux + HPMP_IO_WEND(fl_xmpi); +#endif /* MPI_hpux */ + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/iowaitall.c b/ompi/mca/io/romio314/romio/mpi-io/iowaitall.c new file mode 100644 index 0000000000..84c15cd27e --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/iowaitall.c @@ -0,0 +1,74 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 2003 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPIO_Waitall = PMPIO_Waitall +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPIO_Waitall MPIO_Waitall +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPIO_Waitall as PMPIO_Waitall +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* + This is a temporary function until we switch to using MPI-2's generalized + requests. +*/ + +int MPIO_Waitall( int count, MPIO_Request requests[], MPI_Status statuses[] ) +{ + int notdone, i, flag, err; + MPIU_THREADPRIV_DECL; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (count == 1) { + err = MPIO_Wait(requests, statuses); + goto fn_exit; + } + + + do { + notdone = 0; + for (i=0; iPMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* + This is a temporary function until we switch to using MPI-2's generalized + requests. +*/ + +int MPIO_Waitany(int count, MPIO_Request requests[], int *index, + MPI_Status *status) +{ + int i, flag, err; + MPIU_THREADPRIV_DECL; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (count == 1) { + err = MPIO_Wait( requests, status ); + if (!err) *index = 0; + goto fn_exit; + } + + /* Check for no active requests */ + for (i=0; iMPI_SOURCE = MPI_ANY_SOURCE; + status->MPI_TAG = MPI_ANY_TAG; + MPIR_STATUS_SET_COUNT(*status, 0); + MPIR_STATUS_SET_CANCEL_BIT(*status, 0); + } +#endif + err = MPI_SUCCESS; + goto fn_exit; + } + + err = MPI_SUCCESS; + do { + flag = 0; + for (i=0; iPMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* + This is a temporary function until we switch to using MPI-2's generalized + requests. +*/ + +int MPIO_Waitsome(int count, MPIO_Request requests[], int *outcount, + int indices[], MPI_Status *statuses) +{ + int i, flag, err; + MPIU_THREADPRIV_DECL; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (count == 1) { + err = MPIO_Wait( requests, statuses ); + if (!err) { + *outcount = 1; + indices[0] = 0; + } + goto fn_exit; + } + + /* Check for no active requests */ + for (i=0; iPMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +#ifdef HAVE_MPI_GREQUEST +#include "mpiu_greq.h" +#endif + +/*@ + MPI_File_iread - Nonblocking read using individual 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(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Request *request) +{ + int error_code=MPI_SUCCESS; + static char myname[] = "MPI_FILE_IREAD"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEIREAD, TRDTSYSTEM, fh, datatype, + count); +#endif /* MPI_hpux */ + + + error_code = MPIOI_File_iread(fh, (MPI_Offset) 0, ADIO_INDIVIDUAL, + buf, count, datatype, myname, request); + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(fh, error_code); + /* --END ERROR HANDLING-- */ + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} + +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +int MPIOI_File_iread(MPI_File fh, MPI_Offset offset, int file_ptr_type, void *buf, int count, + MPI_Datatype datatype, char *myname, MPI_Request *request) +{ + int error_code, buftype_is_contig, filetype_is_contig; + MPI_Count datatype_size; + ADIO_Status status; + ADIO_File adio_fh; + ADIO_Offset off, bufsize; + 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); + + 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_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); + 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); + + 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 { + off = adio_fh->fp_ind; + } + + if (!(adio_fh->atomicity)) + ADIO_IreadContig(adio_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(adio_fh, ADIO_LOCKS)) + { + ADIOI_WRITE_LOCK(adio_fh, off, SEEK_SET, bufsize); + } + + ADIO_ReadContig(adio_fh, buf, count, datatype, file_ptr_type, + off, &status, &error_code); + + if (ADIO_Feature(adio_fh, ADIO_LOCKS)) + { + 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, file_ptr_type, + offset, request, &error_code); + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/iread_at.c b/ompi/mca/io/romio314/romio/mpi-io/iread_at.c new file mode 100644 index 0000000000..29bda8462f --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/iread_at.c @@ -0,0 +1,75 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_iread_at = PMPI_File_iread_at +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_iread_at MPI_File_iread_at +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_iread_at as PMPI_File_iread_at +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_iread_at(MPI_File fh, MPI_Offset offset, void *buf, int count, MPI_Datatype datatype, + MPIO_Request *request) __attribute__((weak,alias("PMPI_File_iread_at"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +#ifdef HAVE_MPI_GREQUEST +#include "mpiu_greq.h" +#endif + +/*@ + MPI_File_iread_at - Nonblocking read using explicit 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; + static char myname[] = "MPI_FILE_IREAD_AT"; + +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEIREADAT, TRDTSYSTEM, fh, datatype, + count); +#endif /* MPI_hpux */ + + + error_code = MPIOI_File_iread(fh, offset, ADIO_EXPLICIT_OFFSET, buf, + count, datatype, myname, request); + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(fh, error_code); + /* --END ERROR HANDLING-- */ + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/iread_sh.c b/ompi/mca/io/romio314/romio/mpi-io/iread_sh.c new file mode 100644 index 0000000000..b6713463fb --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/iread_sh.c @@ -0,0 +1,140 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_iread_shared = PMPI_File_iread_shared +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_iread_shared MPI_File_iread_shared +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_iread_shared as PMPI_File_iread_shared +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_iread_shared(MPI_File fh, void *buf, int count, MPI_Datatype datatype, + MPIO_Request *request) __attribute__((weak,alias("PMPI_File_iread_shared"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +#ifdef HAVE_MPI_GREQUEST +#include "mpiu_greq.h" + +/*@ + 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; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/iwrite.c b/ompi/mca/io/romio314/romio/mpi-io/iwrite.c new file mode 100644 index 0000000000..cd4f69fbc5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/iwrite.c @@ -0,0 +1,168 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_iwrite = PMPI_File_iwrite +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_iwrite MPI_File_iwrite +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_iwrite as PMPI_File_iwrite +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_iwrite(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPIO_Request *request) __attribute__((weak,alias("PMPI_File_iwrite"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_iwrite - Nonblocking 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: +. request - request object (handle) + +.N fortran +@*/ +#ifdef HAVE_MPI_GREQUEST +#include "mpiu_greq.h" +#endif + +int MPI_File_iwrite(MPI_File fh, ROMIO_CONST void *buf, int count, + MPI_Datatype datatype, MPI_Request *request) +{ + int error_code=MPI_SUCCESS; + static char myname[] = "MPI_FILE_IWRITE"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEIWRITE, TRDTSYSTEM, fh, datatype, + count); +#endif /* MPI_hpux */ + + + error_code = MPIOI_File_iwrite(fh, (MPI_Offset) 0, ADIO_INDIVIDUAL, + buf, count, datatype, myname, request); + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(fh, error_code); + /* --END ERROR HANDLING-- */ + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} + +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +int MPIOI_File_iwrite(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + const void *buf, + int count, + MPI_Datatype datatype, + char *myname, + MPI_Request *request) +{ + int error_code, buftype_is_contig, filetype_is_contig; + MPI_Count datatype_size; + ADIO_Status status; + ADIO_Offset off, bufsize; + ADIO_File adio_fh; + 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); + + 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_INTEGRAL_ETYPE(adio_fh, count, datatype_size, myname, error_code); + MPIO_CHECK_WRITABLE(adio_fh, myname, error_code); + MPIO_CHECK_NOT_SEQUENTIAL_MODE(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); + + if (buftype_is_contig && filetype_is_contig) { + /* convert sizes to bytes */ + bufsize = datatype_size * count; + if (file_ptr_type == ADIO_EXPLICIT_OFFSET) { + off = adio_fh->disp + adio_fh->etype_size * offset; + } + else { + off = adio_fh->fp_ind; + } + + if (!(adio_fh->atomicity)) { + ADIO_IwriteContig(adio_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(adio_fh, ADIO_LOCKS) ) + { + ADIOI_WRITE_LOCK(adio_fh, off, SEEK_SET, bufsize); + } + + ADIO_WriteContig(adio_fh, buf, count, datatype, file_ptr_type, off, + &status, &error_code); + + if (ADIO_Feature(adio_fh, ADIO_LOCKS) ) + { + 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_IwriteStrided(adio_fh, buf, count, datatype, file_ptr_type, + offset, request, &error_code); + } +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/iwrite_at.c b/ompi/mca/io/romio314/romio/mpi-io/iwrite_at.c new file mode 100644 index 0000000000..10862bd033 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/iwrite_at.c @@ -0,0 +1,80 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_iwrite_at = PMPI_File_iwrite_at +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_iwrite_at MPI_File_iwrite_at +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_iwrite_at as PMPI_File_iwrite_at +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_iwrite_at(MPI_File fh, MPI_Offset offset, const void *buf, int count, + MPI_Datatype datatype, MPIO_Request *request) + __attribute__((weak,alias("PMPI_File_iwrite_at"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_iwrite_at - Nonblocking write using explicit offset + +Input Parameters: +. fh - file handle (handle) +. offset - file offset (nonnegative integer) +. buf - initial address of buffer (choice) +. count - number of elements in buffer (nonnegative integer) +. datatype - datatype of each buffer element (handle) + +Output Parameters: +. request - request object (handle) + +.N fortran +@*/ +#ifdef HAVE_MPI_GREQUEST +#include "mpiu_greq.h" +#endif + +int MPI_File_iwrite_at(MPI_File fh, MPI_Offset offset, ROMIO_CONST void *buf, + int count, MPI_Datatype datatype, + MPIO_Request *request) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_IWRITE_AT"; + +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEIWRITEAT, TRDTSYSTEM, + fh, datatype, count); +#endif /* MPI_hpux */ + + + adio_fh = MPIO_File_resolve(fh); + + error_code = MPIOI_File_iwrite(adio_fh, offset, ADIO_EXPLICIT_OFFSET, buf, + count, datatype, myname, request); + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count) +#endif /* MPI_hpux */ + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/iwrite_sh.c b/ompi/mca/io/romio314/romio/mpi-io/iwrite_sh.c new file mode 100644 index 0000000000..c436221c14 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/iwrite_sh.c @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_iwrite_shared = PMPI_File_iwrite_shared +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_iwrite_shared MPI_File_iwrite_shared +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_iwrite_shared as PMPI_File_iwrite_shared +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_iwrite_shared(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPIO_Request *request) __attribute__((weak,alias("PMPI_File_iwrite_shared"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_iwrite_shared - Nonblocking 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: +. request - request object (handle) + +.N fortran +@*/ +#ifdef HAVE_MPI_GREQUEST +#include "mpiu_greq.h" +#endif + +int MPI_File_iwrite_shared(MPI_File fh, ROMIO_CONST void *buf, int count, + MPI_Datatype datatype, MPIO_Request *request) +{ + int error_code, buftype_is_contig, filetype_is_contig; + ADIO_File adio_fh; + ADIO_Offset incr, bufsize; + MPI_Count datatype_size; + ADIO_Status status; + ADIO_Offset off, shared_fp; + static char myname[] = "MPI_FILE_IWRITE_SHARED"; + + 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); + 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); + } + + /* contiguous or strided? */ + if (buftype_is_contig && filetype_is_contig) { + /* convert sizes to bytes */ + bufsize = datatype_size * count; + off = adio_fh->disp + adio_fh->etype_size * shared_fp; + if (!(adio_fh->atomicity)) + ADIO_IwriteContig(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_WriteContig(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); + + MPIO_Completed_request_create(&adio_fh, bufsize, &error_code, request); + } + } + else + ADIO_IwriteStrided(adio_fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, + shared_fp, request, &error_code); + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/mpich_fileutil.c b/ompi/mca/io/romio314/romio/mpi-io/mpich_fileutil.c new file mode 100644 index 0000000000..b853b588fa --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/mpich_fileutil.c @@ -0,0 +1,60 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpioimpl.h" +#include "adio_extern.h" + +#ifdef MPICH + +/* Forward ref for the routine to extract and set the error handler + in a ROMIO File structure. FIXME: These should be imported from a common + header file that is also used in errhan/file_set_errhandler.c + */ +int MPIR_ROMIO_Get_file_errhand( MPI_File, MPI_Errhandler * ); +int MPIR_ROMIO_Set_file_errhand( MPI_File, MPI_Errhandler ); +void MPIR_Get_file_error_routine( MPI_Errhandler, + void (**)(MPI_File *, int *, ...), + int * ); + +/* These next two routines are used to allow MPICH to access/set the + error handers in the MPI_File structure until MPICH knows about the + file structure, and to handle the errhandler structure, which + includes a reference count. Not currently used. */ +int MPIR_ROMIO_Set_file_errhand( MPI_File file_ptr, MPI_Errhandler e ) +{ + if (file_ptr == MPI_FILE_NULL) ADIOI_DFLT_ERR_HANDLER = e; + /* --BEGIN ERROR HANDLING-- */ + else if (file_ptr->cookie != ADIOI_FILE_COOKIE) { + return MPI_ERR_FILE; + } + /* --END ERROR HANDLING-- */ + else + file_ptr->err_handler = e; + return 0; +} +int MPIR_ROMIO_Get_file_errhand( MPI_File file_ptr, MPI_Errhandler *e ) +{ + if (file_ptr == MPI_FILE_NULL) { + if (ADIOI_DFLT_ERR_HANDLER == MPI_ERRORS_RETURN) + *e = 0; + else { + *e = ADIOI_DFLT_ERR_HANDLER; + } + } + /* --BEGIN ERROR HANDLING-- */ + else if (file_ptr->cookie != ADIOI_FILE_COOKIE) { + return MPI_ERR_FILE; + } + /* --END ERROR HANDLING-- */ + else { + if (file_ptr->err_handler == MPI_ERRORS_RETURN) + *e = 0; + else + *e = file_ptr->err_handler; + } + return 0; +} + +#endif /* MPICH */ diff --git a/ompi/mca/io/romio314/romio/mpi-io/mpioimpl.h b/ompi/mca/io/romio314/romio/mpi-io/mpioimpl.h new file mode 100644 index 0000000000..77b18cba93 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/mpioimpl.h @@ -0,0 +1,77 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + + +/* header file for MPI-IO implementation. not intended to be + user-visible */ + +#ifndef MPIOIMPL_INCLUDE +#define MPIOIMPL_INCLUDE + +#include "adio.h" +#include "mpio.h" + +#ifdef ROMIO_INSIDE_MPICH +#include "glue_romio.h" + +#define MPIU_THREAD_CS_ENTER(name_,ctx_) MPIU_THREAD_CS_ENTER_##name_(ctx_) +#define MPIU_THREAD_CS_EXIT(name_,ctx_) MPIU_THREAD_CS_EXIT_##name_(ctx_) +#define MPIU_THREAD_CS_ENTER_ALLFUNC(ctx_) MPIR_Ext_cs_enter_allfunc() +#define MPIU_THREAD_CS_EXIT_ALLFUNC(ctx_) MPIR_Ext_cs_exit_allfunc() + +/* committed datatype checking support in ROMIO */ +#define MPIO_DATATYPE_ISCOMMITTED(dtype_, err_) \ + do { \ + err_ = MPIR_Ext_datatype_iscommitted(dtype_); \ + } while (0) + +#else /* not ROMIO_INSIDE_MPICH */ +/* Any MPI implementation that wishes to follow the thread-safety and + error reporting features provided by MPICH must implement these + four functions. Defining these as empty should not change the behavior + of correct programs */ +#define MPIU_THREAD_CS_ENTER(x,y) +#define MPIU_THREAD_CS_EXIT(x,y) +#define MPIO_DATATYPE_ISCOMMITTED(dtype_, err_) do {} while (0) +#ifdef HAVE_WINDOWS_H +#define MPIU_UNREFERENCED_ARG(a) a +#else +#define MPIU_UNREFERENCED_ARG(a) +#endif +#endif /* ROMIO_INSIDE_MPICH */ + +/* info is a linked list of these structures */ +struct MPIR_Info { + int cookie; + char *key, *value; + struct MPIR_Info *next; +}; + +#define MPIR_INFO_COOKIE 5835657 + +MPI_Delete_function ADIOI_End_call; + +/* common initialization routine */ +void MPIR_MPIOInit(int * error_code); + +#ifdef HAVE_MPIIO_CONST +#define ROMIO_CONST const +#else +#define ROMIO_CONST +#endif + +#include "mpiu_external32.h" + + +#include "mpioprof.h" + +#ifdef MPI_hpux +# include "mpioinst.h" +#endif /* MPI_hpux */ + +#endif + diff --git a/ompi/mca/io/romio314/romio/mpi-io/mpioprof.h b/ompi/mca/io/romio314/romio/mpi-io/mpioprof.h new file mode 100644 index 0000000000..32e3c7c90a --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/mpioprof.h @@ -0,0 +1,205 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +/* + This header file converts all MPI_ names into PMPI_ names, for + building the profiling interface + */ + +#ifdef MPIO_BUILD_PROFILING + +#undef MPI_File_open +#define MPI_File_open PMPI_File_open +#undef MPI_File_close +#define MPI_File_close PMPI_File_close +#undef MPI_File_delete +#define MPI_File_delete PMPI_File_delete +#undef MPI_File_set_size +#define MPI_File_set_size PMPI_File_set_size +#undef MPI_File_preallocate +#define MPI_File_preallocate PMPI_File_preallocate +#undef MPI_File_get_size +#define MPI_File_get_size PMPI_File_get_size +#undef MPI_File_get_group +#define MPI_File_get_group PMPI_File_get_group +#undef MPI_File_get_amode +#define MPI_File_get_amode PMPI_File_get_amode +#undef MPI_File_set_info +#define MPI_File_set_info PMPI_File_set_info +#undef MPI_File_get_info +#define MPI_File_get_info PMPI_File_get_info + +#undef MPI_File_set_view +#define MPI_File_set_view PMPI_File_set_view +#undef MPI_File_get_view +#define MPI_File_get_view PMPI_File_get_view + +#undef MPI_File_read_at +#define MPI_File_read_at PMPI_File_read_at +#undef MPI_File_read_at_all +#define MPI_File_read_at_all PMPI_File_read_at_all +#undef MPI_File_write_at +#define MPI_File_write_at PMPI_File_write_at +#undef MPI_File_write_at_all +#define MPI_File_write_at_all PMPI_File_write_at_all +#undef MPI_File_iread_at +#define MPI_File_iread_at PMPI_File_iread_at +#undef MPI_File_iwrite_at +#define MPI_File_iwrite_at PMPI_File_iwrite_at + +#undef MPI_File_read +#define MPI_File_read PMPI_File_read +#undef MPI_File_read_all +#define MPI_File_read_all PMPI_File_read_all +#undef MPI_File_write +#define MPI_File_write PMPI_File_write +#undef MPI_File_write_all +#define MPI_File_write_all PMPI_File_write_all +#undef MPI_File_iread +#define MPI_File_iread PMPI_File_iread +#undef MPI_File_iwrite +#define MPI_File_iwrite PMPI_File_iwrite +#undef MPI_File_seek +#define MPI_File_seek PMPI_File_seek +#undef MPI_File_get_position +#define MPI_File_get_position PMPI_File_get_position +#undef MPI_File_get_byte_offset +#define MPI_File_get_byte_offset PMPI_File_get_byte_offset + +#undef MPI_File_read_shared +#define MPI_File_read_shared PMPI_File_read_shared +#undef MPI_File_write_shared +#define MPI_File_write_shared PMPI_File_write_shared +#undef MPI_File_iread_shared +#define MPI_File_iread_shared PMPI_File_iread_shared +#undef MPI_File_iwrite_shared +#define MPI_File_iwrite_shared PMPI_File_iwrite_shared +#undef MPI_File_read_ordered +#define MPI_File_read_ordered PMPI_File_read_ordered +#undef MPI_File_write_ordered +#define MPI_File_write_ordered PMPI_File_write_ordered +#undef MPI_File_seek_shared +#define MPI_File_seek_shared PMPI_File_seek_shared +#undef MPI_File_get_position_shared +#define MPI_File_get_position_shared PMPI_File_get_position_shared + +#undef MPI_File_read_at_all_begin +#define MPI_File_read_at_all_begin PMPI_File_read_at_all_begin +#undef MPI_File_read_at_all_end +#define MPI_File_read_at_all_end PMPI_File_read_at_all_end +#undef MPI_File_write_at_all_begin +#define MPI_File_write_at_all_begin PMPI_File_write_at_all_begin +#undef MPI_File_write_at_all_end +#define MPI_File_write_at_all_end PMPI_File_write_at_all_end +#undef MPI_File_read_all_begin +#define MPI_File_read_all_begin PMPI_File_read_all_begin +#undef MPI_File_read_all_end +#define MPI_File_read_all_end PMPI_File_read_all_end +#undef MPI_File_write_all_begin +#define MPI_File_write_all_begin PMPI_File_write_all_begin +#undef MPI_File_write_all_end +#define MPI_File_write_all_end PMPI_File_write_all_end +#undef MPI_File_read_ordered_begin +#define MPI_File_read_ordered_begin PMPI_File_read_ordered_begin +#undef MPI_File_read_ordered_end +#define MPI_File_read_ordered_end PMPI_File_read_ordered_end +#undef MPI_File_write_ordered_begin +#define MPI_File_write_ordered_begin PMPI_File_write_ordered_begin +#undef MPI_File_write_ordered_end +#define MPI_File_write_ordered_end PMPI_File_write_ordered_end + +#undef MPI_File_get_type_extent +#define MPI_File_get_type_extent PMPI_File_get_type_extent +#undef MPI_Register_datarep +#define MPI_Register_datarep PMPI_Register_datarep +#undef MPI_File_set_atomicity +#define MPI_File_set_atomicity PMPI_File_set_atomicity +#undef MPI_File_get_atomicity +#define MPI_File_get_atomicity PMPI_File_get_atomicity +#undef MPI_File_sync +#define MPI_File_sync PMPI_File_sync + +#undef MPI_Type_create_subarray +#define MPI_Type_create_subarray PMPI_Type_create_subarray +#undef MPI_Type_create_darray +#define MPI_Type_create_darray PMPI_Type_create_darray + +#undef MPI_File_set_errhandler +#define MPI_File_set_errhandler PMPI_File_set_errhandler +#undef MPI_File_get_errhandler +#define MPI_File_get_errhandler PMPI_File_get_errhandler + +#if !defined(MPI_File_f2c) || defined(MPICH_RENAMING_MPI_FUNCS) +#undef MPI_File_f2c +#define MPI_File_f2c PMPI_File_f2c +#undef MPI_File_c2f +#define MPI_File_c2f PMPI_File_c2f +#endif + +#undef MPIO_Test +#undef PMPIO_Test +#define MPIO_Test PMPIO_Test +#undef MPIO_Wait +#undef PMPIO_Wait +#define MPIO_Wait PMPIO_Wait +#undef MPIO_Testall +#define MPIO_Testall PMPIO_Testall +#undef MPIO_Waitall +#define MPIO_Waitall PMPIO_Waitall +#undef MPIO_Testany +#define MPIO_Testany PMPIO_Testany +#undef MPIO_Waitany +#define MPIO_Waitany PMPIO_Waitany +#undef MPIO_Testsome +#define MPIO_Testsome PMPIO_Testsome +#undef MPIO_Waitsome +#define MPIO_Waitsome PMPIO_Waitsome +#undef MPIO_Request_f2c +#define MPIO_Request_f2c PMPIO_Request_f2c +#undef MPIO_Request_c2f +#define MPIO_Request_c2f PMPIO_Request_c2f + +#if defined(HAVE_MPI_INFO_SRC) /* only in info source directory */ + +#undef MPI_Info_create +#define MPI_Info_create PMPI_Info_create +#undef MPI_Info_set +#define MPI_Info_set PMPI_Info_set +#undef MPI_Info_delete +#define MPI_Info_delete PMPI_Info_delete +#undef MPI_Info_get +#define MPI_Info_get PMPI_Info_get +#undef MPI_Info_get_valuelen +#define MPI_Info_get_valuelen PMPI_Info_get_valuelen +#undef MPI_Info_get_nkeys +#define MPI_Info_get_nkeys PMPI_Info_get_nkeys +#undef MPI_Info_get_nthkey +#define MPI_Info_get_nthkey PMPI_Info_get_nthkey +#undef MPI_Info_dup +#define MPI_Info_dup PMPI_Info_dup +#undef MPI_Info_free +#define MPI_Info_free PMPI_Info_free +#undef MPI_Info_c2f +#define MPI_Info_c2f PMPI_Info_c2f +#undef MPI_Info_f2c +#define MPI_Info_f2c PMPI_Info_f2c + +#endif + +#undef MPI_Grequest_start +#define MPI_Grequest_start PMPI_Grequest_start +#undef MPI_Grequest_complete +#define MPI_Grequest_complete PMPI_Grequest_complete +#undef MPI_Status_set_cancelled +#define MPI_Status_set_cancelled PMPI_Status_set_cancelled + +#undef MPIX_Grequest_start +#define MPIX_Grequest_start PMPIX_Grequest_start +#undef MPIX_Grequest_class_create +#define MPIX_Grequest_class_create PMPIX_Grequest_class_create + +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/mpir-mpioinit.c b/ompi/mca/io/romio314/romio/mpi-io/mpir-mpioinit.c new file mode 100644 index 0000000000..be78b45e98 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/mpir-mpioinit.c @@ -0,0 +1,56 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2009 UChicago/Argonne LLC + * See COPYRIGHT in top-level directory. + */ +#include +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +extern int ADIO_Init_keyval; + +/* common code to stuff an attribute on a communicator for the purpose of + * cleaning up in MPI_Finalize() */ + +void MPIR_MPIOInit(int * error_code) { + + int flag; + char myname[] = "MPIR_MPIOInit"; + + /* first check if ADIO has been initialized. If not, initialize it */ + if (ADIO_Init_keyval == MPI_KEYVAL_INVALID) { + MPI_Initialized(&flag); + + /* --BEGIN ERROR HANDLING-- */ + if (!flag) { + *error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, __LINE__, + MPI_ERR_OTHER, "**initialized", 0); + *error_code = MPIO_Err_return_file(MPI_FILE_NULL, *error_code); + return; + } + /* --END ERROR HANDLING-- */ + + MPI_Keyval_create(MPI_NULL_COPY_FN, ADIOI_End_call, &ADIO_Init_keyval, + (void *) 0); + + /* put a dummy attribute on MPI_COMM_SELF, because we want the delete + function to be called when MPI_COMM_SELF is freed. Clarified + in MPI-2 section 4.8, the standard mandates that attributes on + MPI_COMM_SELF get cleaned up early in MPI_Finalize */ + + MPI_Attr_put(MPI_COMM_SELF, ADIO_Init_keyval, (void *) 0); + + /* initialize ADIO */ + ADIO_Init( (int *)0, (char ***)0, error_code); + } + *error_code = MPI_SUCCESS; +} +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/mpi-io/mpiu_external32.c b/ompi/mca/io/romio314/romio/mpi-io/mpiu_external32.c new file mode 100644 index 0000000000..ce2253bb4b --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/mpiu_external32.c @@ -0,0 +1,172 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* (C) 2012 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ + +#include "mpioimpl.h" +#include "mpiu_external32.h" + +#ifdef HAVE_WEAK_SYMBOLS +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +int MPIU_write_external32_conversion_fn (const void *userbuf, MPI_Datatype datatype, + int count, void *filebuf) +{ + int position_i = 0; + MPI_Aint position = 0; + MPI_Aint bytes = 0; + int mpi_errno = MPI_SUCCESS; + int is_contig = 0; + + ADIOI_Datatype_iscontig(datatype, &is_contig); + mpi_errno = MPI_Pack_external_size("external32", count, datatype, &bytes); + if (mpi_errno != MPI_SUCCESS) + goto fn_exit; + + if (is_contig) + { +#ifdef HAVE_MPIIO_CONST + mpi_errno = MPI_Pack_external("external32", userbuf, count, + datatype, filebuf, bytes, &position); +#else + mpi_errno = MPI_Pack_external("external32", (void *)userbuf, count, + datatype, filebuf, bytes, &position); +#endif + if (mpi_errno != MPI_SUCCESS) + goto fn_exit; + } + else + { + void *tmp_buf = NULL; + tmp_buf = ADIOI_Malloc(bytes); + if (!tmp_buf) + { + mpi_errno = MPI_ERR_NO_MEM; + goto fn_exit; + } + +#ifdef HAVE_MPIIO_CONST + mpi_errno = MPI_Pack_external("external32", userbuf, count, + datatype, tmp_buf, bytes, &position); +#else + mpi_errno = MPI_Pack_external("external32", (void *)userbuf, count, + datatype, tmp_buf, bytes, &position); +#endif + if (mpi_errno != MPI_SUCCESS) + { + ADIOI_Free(tmp_buf); + goto fn_exit; + } + + mpi_errno = MPI_Unpack(tmp_buf, bytes, &position_i, filebuf, count, + datatype, MPI_COMM_WORLD); + if (mpi_errno != MPI_SUCCESS) + { + ADIOI_Free(tmp_buf); + goto fn_exit; + } + + ADIOI_Free(tmp_buf); + } +fn_exit: + return mpi_errno; +} + +int MPIU_read_external32_conversion_fn(void *userbuf, MPI_Datatype datatype, + int count, void *filebuf) +{ + int position_i = 0; + MPI_Aint position = 0; + MPI_Aint bytes = 0; + int mpi_errno = MPI_SUCCESS; + int is_contig = 0; + + ADIOI_Datatype_iscontig(datatype, &is_contig); + mpi_errno = MPI_Pack_external_size("external32", count, datatype, &bytes); + if (mpi_errno != MPI_SUCCESS) + goto fn_exit; + + if (is_contig) + { + mpi_errno = MPI_Unpack_external("external32", filebuf, bytes, + &position, userbuf, count, datatype); + if (mpi_errno != MPI_SUCCESS) + goto fn_exit; + } + else + { + void *tmp_buf = NULL; + tmp_buf = ADIOI_Malloc(bytes); + if (!tmp_buf) + { + mpi_errno = MPI_ERR_NO_MEM; + goto fn_exit; + } + + mpi_errno = MPI_Pack(filebuf, count, datatype, tmp_buf, bytes, + &position_i, MPI_COMM_WORLD); + if (mpi_errno != MPI_SUCCESS) + { + ADIOI_Free(tmp_buf); + goto fn_exit; + } + + mpi_errno = MPI_Unpack_external("external32", tmp_buf, bytes, + &position, userbuf, count, datatype); + if (mpi_errno != MPI_SUCCESS) + { + ADIOI_Free(tmp_buf); + goto fn_exit; + } + + ADIOI_Free(tmp_buf); + } +fn_exit: + return mpi_errno; +} +int MPIU_datatype_full_size(MPI_Datatype datatype, MPI_Aint *size) +{ + int error_code = MPI_SUCCESS; + MPI_Aint true_extent = 0; + MPI_Aint true_lb = 0; + + error_code = MPI_Type_get_true_extent(datatype, &true_lb, &true_extent); + if (error_code != MPI_SUCCESS) + goto fn_exit; + + *size = true_extent; +fn_exit: + return error_code; +} + +/* given a buffer, count, and datatype, return an apropriately allocated, sized + * and external32-formatted buffer, suitable for handing off to a subsequent + * write routine. Caller is responsible for freeing 'newbuf' */ +int MPIU_external32_buffer_setup(const void * buf, int count, MPI_Datatype type, void **newbuf) +{ + + MPI_Aint datatype_size=0, bytes=0; + int error_code; + + error_code = MPIU_datatype_full_size(type, &datatype_size); + if (error_code != MPI_SUCCESS) + return error_code; + + bytes = datatype_size * count; + *newbuf = ADIOI_Malloc(bytes); + + error_code = MPIU_write_external32_conversion_fn(buf, type, count, *newbuf); + if (error_code != MPI_SUCCESS) { + ADIOI_Free(newbuf); + return error_code; + } + return MPI_SUCCESS; +} + + +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/mpi-io/mpiu_greq.c b/ompi/mca/io/romio314/romio/mpi-io/mpiu_greq.c new file mode 100644 index 0000000000..cb6e9d2ed4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/mpiu_greq.c @@ -0,0 +1,49 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include +#include "mpioimpl.h" +#include "mpiu_greq.h" + +#ifdef HAVE_WEAK_SYMBOLS +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +int MPIU_Greq_query_fn(void *extra_state, MPI_Status *status) +{ + int foo; + + /* can't touch user's MPI_ERROR, so hold it for a moment */ + foo = status->MPI_ERROR; + + /* get the status from the blocking operation */ + memcpy(status, extra_state, sizeof(MPI_Status)); + + /* restore MPI_ERROR to whatever it had when we got it */ + status->MPI_ERROR = foo; + + /* and let Test|Wait know we weren't canceled */ + MPI_Status_set_cancelled(status, 0); + + return MPI_SUCCESS; +} + +int MPIU_Greq_free_fn(void *extra_state) +{ + /* frees the memory allocated in MPIO_Completed_request_create */ + ADIOI_Free(extra_state); + + return MPI_SUCCESS; +} +int MPIU_Greq_cancel_fn(void *extra_state, int complete) +{ + MPIU_UNREFERENCED_ARG(extra_state); + MPIU_UNREFERENCED_ARG(complete); + + /* can't cancel */ + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/open.c b/ompi/mca/io/romio314/romio/mpi-io/open.c new file mode 100644 index 0000000000..a2a68c95f2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/open.c @@ -0,0 +1,209 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_open = PMPI_File_open +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_open MPI_File_open +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_open as PMPI_File_open +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_open(MPI_Comm comm, const char *filename, int amode, MPI_Info info, MPI_File *fh) __attribute__((weak,alias("PMPI_File_open"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* for user-definde reduce operator */ +#include "adio_extern.h" + + +extern int ADIO_Init_keyval; + +/*@ + MPI_File_open - Opens a file + +Input Parameters: +. comm - communicator (handle) +. filename - name of file to open (string) +. amode - file access mode (integer) +. info - info object (handle) + +Output Parameters: +. fh - file handle (handle) + +.N fortran +@*/ +int MPI_File_open(MPI_Comm comm, ROMIO_CONST char *filename, int amode, + MPI_Info info, MPI_File *fh) +{ + int error_code = MPI_SUCCESS, file_system, flag, tmp_amode=0, rank; + char *tmp; + MPI_Comm dupcomm = MPI_COMM_NULL; + ADIOI_Fns *fsops; + static char myname[] = "MPI_FILE_OPEN"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_OPEN_START(fl_xmpi, comm); +#endif /* MPI_hpux */ + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_COMM(comm, myname, error_code); + MPIO_CHECK_INFO_ALL(info, error_code, comm); + /* --END ERROR HANDLING-- */ + + error_code = MPI_Comm_test_inter(comm, &flag); + /* --BEGIN ERROR HANDLING-- */ + if (error_code || flag) + { + error_code = MPIO_Err_create_code(error_code, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_COMM, + "**commnotintra", 0); + goto fn_fail; + } + + if ( ((amode&MPI_MODE_RDONLY)?1:0) + ((amode&MPI_MODE_RDWR)?1:0) + + ((amode&MPI_MODE_WRONLY)?1:0) != 1 ) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_AMODE, + "**fileamodeone", 0); + goto fn_fail; + } + + if ((amode & MPI_MODE_RDONLY) && + ((amode & MPI_MODE_CREATE) || (amode & MPI_MODE_EXCL))) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_AMODE, + "**fileamoderead", 0); + goto fn_fail; + } + + if ((amode & MPI_MODE_RDWR) && (amode & MPI_MODE_SEQUENTIAL)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_AMODE, + "**fileamodeseq", 0); + goto fn_fail; + } + + MPI_Comm_dup(comm, &dupcomm); + +/* check if ADIO has been initialized. If not, initialize it */ + MPIR_MPIOInit(&error_code); + if (error_code != MPI_SUCCESS) goto fn_fail; + +/* check if amode is the same on all processes: at first glance, one might try + * to use a built-in operator like MPI_BAND, but we need every mpi process to + * agree the amode was not the same. Consider process A with + * MPI_MODE_CREATE|MPI_MODE_RDWR, and B with MPI_MODE_RDWR: MPI_BAND yields + * MPI_MODE_RDWR. A determines amodes are different, but B proceeds having not + * detected an error */ + MPI_Allreduce(&amode, &tmp_amode, 1, MPI_INT, ADIO_same_amode, dupcomm); + + if (tmp_amode == ADIO_AMODE_NOMATCH) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_NOT_SAME, + "**fileamodediff", 0); + goto fn_fail; + } + /* --END ERROR HANDLING-- */ + + file_system = -1; + + /* resolve file system type from file name; this is a collective call */ + ADIO_ResolveFileType(dupcomm, filename, &file_system, &fsops, &error_code); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + { + /* ADIO_ResolveFileType() will print as informative a message as it + * possibly can or call MPIO_Err_setmsg. We just need to propagate + * the error up. + */ + goto fn_fail; + } + + /* --END ERROR HANDLING-- */ + + /* strip off prefix if there is one, but only skip prefixes + * if they are greater than length one to allow for windows + * drive specifications (e.g. c:\...) */ + + tmp = strchr(filename, ':'); + if (tmp > filename + 1) { + filename = tmp + 1; + } + +/* use default values for disp, etype, filetype */ + + *fh = ADIO_Open(comm, dupcomm, filename, file_system, fsops, amode, 0, + MPI_BYTE, MPI_BYTE, info, ADIO_PERM_NULL, &error_code); + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) { + goto fn_fail; + } + /* --END ERROR HANDLING-- */ + + /* if MPI_MODE_SEQUENTIAL requested, file systems cannot do explicit offset + * or independent file pointer accesses, leaving not much else aside from + * shared file pointer accesses. */ + if ( !ADIO_Feature((*fh), ADIO_SHARED_FP) && (amode & MPI_MODE_SEQUENTIAL)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_UNSUPPORTED_OPERATION, + "**iosequnsupported", 0); + ADIO_Close(*fh, &error_code); + goto fn_fail; + } + + /* determine name of file that will hold the shared file pointer */ + /* can't support shared file pointers on a file system that doesn't + support file locking. */ + if ((error_code == MPI_SUCCESS) && + ADIO_Feature((*fh), ADIO_SHARED_FP)) { + MPI_Comm_rank(dupcomm, &rank); + ADIOI_Shfp_fname(*fh, rank, &error_code); + if (error_code != MPI_SUCCESS) + goto fn_fail; + + /* if MPI_MODE_APPEND, set the shared file pointer to end of file. + indiv. file pointer already set to end of file in ADIO_Open. + Here file view is just bytes. */ + if ((*fh)->access_mode & MPI_MODE_APPEND) { + if (rank == (*fh)->hints->ranklist[0]) /* only one person need set the sharedfp */ + ADIO_Set_shared_fp(*fh, (*fh)->fp_ind, &error_code); + MPI_Barrier(dupcomm); + } + } + +#ifdef MPI_hpux + HPMP_IO_OPEN_END(fl_xmpi, *fh, comm); +#endif /* MPI_hpux */ + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +fn_fail: + /* --BEGIN ERROR HANDLING-- */ + if (dupcomm != MPI_COMM_NULL) MPI_Comm_free(&dupcomm); + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + /* --END ERROR HANDLING-- */ +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/prealloc.c b/ompi/mca/io/romio314/romio/mpi-io/prealloc.c new file mode 100644 index 0000000000..3853f8da66 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/prealloc.c @@ -0,0 +1,107 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_preallocate = PMPI_File_preallocate +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_preallocate MPI_File_preallocate +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_preallocate as PMPI_File_preallocate +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_preallocate(MPI_File fh, MPI_Offset size) __attribute__((weak,alias("PMPI_File_preallocate"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_preallocate - Preallocates storage space for a file + +Input Parameters: +. fh - file handle (handle) +. size - size to preallocate (nonnegative integer) + +.N fortran +@*/ +int MPI_File_preallocate(MPI_File fh, MPI_Offset size) +{ + ADIO_Fcntl_t *fcntl_struct; + int error_code=0, mynod=0; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_PREALLOCATE"; + MPI_Offset tmp_sz, max_sz, min_sz; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEPREALLOCATE, TRDTBLOCK, + adio_fh, MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + + if (size < 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iobadsize", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + + tmp_sz = size; + MPI_Allreduce(&tmp_sz, &max_sz, 1, ADIO_OFFSET, MPI_MAX, adio_fh->comm); + MPI_Allreduce(&tmp_sz, &min_sz, 1, ADIO_OFFSET, MPI_MIN, adio_fh->comm); + + if (max_sz != min_sz) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**notsame", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + if (size == 0) goto fn_exit; + + ADIOI_TEST_DEFERRED(adio_fh, myname, &error_code); + + MPI_Comm_rank(adio_fh->comm, &mynod); + if (!mynod) { + fcntl_struct = (ADIO_Fcntl_t *) ADIOI_Malloc(sizeof(ADIO_Fcntl_t)); + fcntl_struct->diskspace = size; + ADIO_Fcntl(adio_fh, ADIO_FCNTL_SET_DISKSPACE, fcntl_struct, &error_code); + ADIOI_Free(fcntl_struct); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + } + MPI_Barrier(adio_fh->comm); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, adio_fh, MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + /* TODO: bcast result? */ + if (!mynod) return error_code; + else return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/rd_atallb.c b/ompi/mca/io/romio314/romio/mpi-io/rd_atallb.c new file mode 100644 index 0000000000..a7120b3da2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/rd_atallb.c @@ -0,0 +1,54 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_at_all_begin = PMPI_File_read_at_all_begin +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_at_all_begin MPI_File_read_at_all_begin +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_at_all_begin as PMPI_File_read_at_all_begin +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_at_all_begin(MPI_File fh, MPI_Offset offset, void *buf, int count, + MPI_Datatype datatype) __attribute__((weak,alias("PMPI_File_read_at_all_begin"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_read_at_all_begin - Begin a split collective read using explicit 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) + +.N fortran +@*/ +int MPI_File_read_at_all_begin(MPI_File fh, MPI_Offset offset, void *buf, + int count, MPI_Datatype datatype) +{ + int error_code; + static char myname[] = "MPI_FILE_READ_AT_ALL_BEGIN"; + + error_code = MPIOI_File_read_all_begin(fh, offset, + ADIO_EXPLICIT_OFFSET, + buf, count, datatype, myname); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/rd_atalle.c b/ompi/mca/io/romio314/romio/mpi-io/rd_atalle.c new file mode 100644 index 0000000000..207d5ba369 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/rd_atalle.c @@ -0,0 +1,50 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_at_all_end = PMPI_File_read_at_all_end +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_at_all_end MPI_File_read_at_all_end +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_at_all_end as PMPI_File_read_at_all_end +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_at_all_end(MPI_File fh, void *buf, MPI_Status *status) __attribute__((weak,alias("PMPI_File_read_at_all_end"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_read_at_all_end - Complete a split collective read using + explicit offset + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. buf - initial address of buffer (choice) +. status - status object (Status) + +.N fortran +@*/ +int MPI_File_read_at_all_end(MPI_File fh, void *buf, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_READ_AT_ALL_END"; + + + error_code = MPIOI_File_read_all_end(fh, buf, myname, status); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/read.c b/ompi/mca/io/romio314/romio/mpi-io/read.c new file mode 100644 index 0000000000..ff109bd4f6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read.c @@ -0,0 +1,187 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read = PMPI_File_read +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read MPI_File_read +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read as PMPI_File_read +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) + __attribute__((weak,alias("PMPI_File_read"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPI_File_read - Read using individual 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(MPI_File fh, void *buf, int count, + MPI_Datatype datatype, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_READ"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEREAD, TRDTBLOCK, fh, datatype, count); +#endif /* MPI_hpux */ + + error_code = MPIOI_File_read(fh, (MPI_Offset) 0, ADIO_INDIVIDUAL, buf, + count, datatype, myname, status); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} + +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +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; + + 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); + + 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: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/read_all.c b/ompi/mca/io/romio314/romio/mpi-io/read_all.c new file mode 100644 index 0000000000..72ea518e19 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read_all.c @@ -0,0 +1,142 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_all = PMPI_File_read_all +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_all MPI_File_read_all +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_all as PMPI_File_read_all +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_all(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) + __attribute__((weak,alias("PMPI_File_read_all"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPI_File_read_all - Collective read using individual 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_all(MPI_File fh, void *buf, int count, + MPI_Datatype datatype, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_READ_ALL"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEREADALL, TRDTBLOCK, fh, datatype, count); +#endif /* MPI_hpux */ + + error_code = MPIOI_File_read_all(fh, (MPI_Offset) 0, + ADIO_INDIVIDUAL, buf, + count, datatype, myname, status); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} + +/* Note: MPIOI_File_read_all also used by MPI_File_read_at_all */ +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +int MPIOI_File_read_all(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; + MPI_Count datatype_size; + ADIO_File adio_fh; + void *xbuf=NULL, *e32_buf=NULL; + + 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); + + 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_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); + MPIO_CHECK_COUNT_SIZE(adio_fh, count, datatype_size, myname, error_code); + /* --END ERROR HANDLING-- */ + + 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; + } + + ADIO_ReadStridedColl(adio_fh, xbuf, count, datatype, file_ptr_type, + offset, status, &error_code); + + /* --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(xbuf, datatype, + count, e32_buf); + ADIOI_Free(e32_buf); + } + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/read_allb.c b/ompi/mca/io/romio314/romio/mpi-io/read_allb.c new file mode 100644 index 0000000000..3f0fd90728 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read_allb.c @@ -0,0 +1,139 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_all_begin = PMPI_File_read_all_begin +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_all_begin MPI_File_read_all_begin +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_all_begin as PMPI_File_read_all_begin +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_all_begin(MPI_File fh, void *buf, int count, MPI_Datatype datatype) + __attribute__((weak,alias("PMPI_File_read_all_begin"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_read_all_begin - Begin a split collective read using individual 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) + +.N fortran +@*/ +int MPI_File_read_all_begin(MPI_File fh, void *buf, int count, + MPI_Datatype datatype) +{ + int error_code; + static char myname[] = "MPI_FILE_READ_ALL_BEGIN"; + + error_code = MPIOI_File_read_all_begin(fh, (MPI_Offset) 0, + ADIO_INDIVIDUAL, buf, count, + datatype, myname); + + return error_code; +} + +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +int MPIOI_File_read_all_begin(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + void *buf, + int count, + MPI_Datatype datatype, + char *myname) +{ + int error_code; + MPI_Count datatype_size; + ADIO_File adio_fh; + void *xbuf=NULL, *e32_buf=NULL; + + 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); + + 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_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); + + if (adio_fh->split_coll_count) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iosplitcoll", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + MPIO_CHECK_COUNT_SIZE(adio_fh, count, datatype_size, myname, error_code); + /* --END ERROR HANDLING-- */ + + adio_fh->split_coll_count = 1; + + 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; + } + + ADIO_ReadStridedColl(adio_fh, xbuf, count, datatype, file_ptr_type, + offset, &adio_fh->split_status, &error_code); + + /* --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(xbuf, datatype, + count, e32_buf); + ADIOI_Free(e32_buf); + } + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/read_alle.c b/ompi/mca/io/romio314/romio/mpi-io/read_alle.c new file mode 100644 index 0000000000..a86c465b12 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read_alle.c @@ -0,0 +1,90 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_all_end = PMPI_File_read_all_end +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_all_end MPI_File_read_all_end +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_all_end as PMPI_File_read_all_end +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_all_end(MPI_File fh, void *buf, MPI_Status *status) __attribute__((weak,alias("PMPI_File_read_all_end"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_read_all_end - Complete a split collective read using + individual file pointer + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. buf - initial address of buffer (choice) +. status - status object (Status) + +.N fortran +@*/ +int MPI_File_read_all_end(MPI_File fh, void *buf, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_IREAD"; + + error_code = MPIOI_File_read_all_end(fh, buf, myname, status); + + return error_code; +} + +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +int MPIOI_File_read_all_end(MPI_File fh, + void *buf, + char *myname, + MPI_Status *status) +{ + int error_code = MPI_SUCCESS; + ADIO_File adio_fh; + + MPIU_UNREFERENCED_ARG(buf); + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + + if (!(adio_fh->split_coll_count)) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iosplitcollnone", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + +#ifdef HAVE_STATUS_SET_BYTES + if (status != MPI_STATUS_IGNORE) + *status = adio_fh->split_status; +#endif + adio_fh->split_coll_count = 0; + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/read_at.c b/ompi/mca/io/romio314/romio/mpi-io/read_at.c new file mode 100644 index 0000000000..53dc8c42e3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read_at.c @@ -0,0 +1,66 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_at = PMPI_File_read_at +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_at MPI_File_read_at +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_at as PMPI_File_read_at +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_at(MPI_File fh, MPI_Offset offset, void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) __attribute__((weak,alias("PMPI_File_read_at"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPI_File_read_at - Read using explicit 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) +. status - status object (Status) + +.N fortran +@*/ +int MPI_File_read_at(MPI_File fh, MPI_Offset offset, void *buf, + int count, MPI_Datatype datatype, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_READ_AT"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEREADAT, TRDTBLOCK, fh, datatype, + count); +#endif /* MPI_hpux */ + + /* ADIOI_File_read() defined in mpi-io/read.c */ + error_code = MPIOI_File_read(fh, offset, ADIO_EXPLICIT_OFFSET, buf, + count, datatype, myname, status); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/read_atall.c b/ompi/mca/io/romio314/romio/mpi-io/read_atall.c new file mode 100644 index 0000000000..2bed66be4d --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read_atall.c @@ -0,0 +1,68 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_at_all = PMPI_File_read_at_all +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_at_all MPI_File_read_at_all +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_at_all as PMPI_File_read_at_all +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_at_all(MPI_File fh, MPI_Offset offset, void * buf, int count, + MPI_Datatype datatype, MPI_Status *status) + __attribute__((weak,alias("PMPI_File_read_at_all"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPI_File_read_at_all - Collective read using explicit 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) +. status - status object (Status) + +.N fortran +@*/ +int MPI_File_read_at_all(MPI_File fh, MPI_Offset offset, void *buf, + int count, MPI_Datatype datatype, + MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_IREAD_AT"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEREADATALL, TRDTBLOCK, fh, datatype, + count); +#endif /* MPI_hpux */ + + error_code = MPIOI_File_read_all(fh, offset, ADIO_EXPLICIT_OFFSET, buf, + count, datatype, myname, status); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/read_ord.c b/ompi/mca/io/romio314/romio/mpi-io/read_ord.c new file mode 100644 index 0000000000..5bfe77ce39 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read_ord.c @@ -0,0 +1,111 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_ordered = PMPI_File_read_ordered +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_ordered MPI_File_read_ordered +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_ordered as PMPI_File_read_ordered +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_ordered(MPI_File fh, void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) __attribute__((weak,alias("PMPI_File_read_ordered"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPI_File_read_ordered - Collective 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_ordered(MPI_File fh, void *buf, int count, + MPI_Datatype datatype, MPI_Status *status) +{ + int error_code, nprocs, myrank; + ADIO_Offset incr; + MPI_Count datatype_size; + int source, dest; + static char myname[] = "MPI_FILE_READ_ORDERED"; + ADIO_Offset shared_fp=0; + ADIO_File adio_fh; + + 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_TEST_DEFERRED(adio_fh, "MPI_File_read_ordered", &error_code); + + MPI_Comm_size(adio_fh->comm, &nprocs); + MPI_Comm_rank(adio_fh->comm, &myrank); + + incr = (count*datatype_size)/adio_fh->etype_size; + + /* Use a message as a 'token' to order the operations */ + source = myrank - 1; + dest = myrank + 1; + if (source < 0) source = MPI_PROC_NULL; + if (dest >= nprocs) dest = MPI_PROC_NULL; + MPI_Recv(NULL, 0, MPI_BYTE, source, 0, adio_fh->comm, MPI_STATUS_IGNORE); + + ADIO_Get_shared_fp(adio_fh, incr, &shared_fp, &error_code); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) { + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + MPI_Send(NULL, 0, MPI_BYTE, dest, 0, adio_fh->comm); + + ADIO_ReadStridedColl(adio_fh, buf, count, datatype, ADIO_EXPLICIT_OFFSET, + shared_fp, status, &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,); + + /* FIXME: Check for error code from ReadStridedColl? */ + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/read_ordb.c b/ompi/mca/io/romio314/romio/mpi-io/read_ordb.c new file mode 100644 index 0000000000..32971f1213 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read_ordb.c @@ -0,0 +1,137 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_ordered_begin = PMPI_File_read_ordered_begin +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_ordered_begin MPI_File_read_ordered_begin +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_ordered_begin as PMPI_File_read_ordered_begin +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_ordered_begin(MPI_File fh, void *buf, int count, MPI_Datatype datatype) + __attribute__((weak,alias("PMPI_File_read_ordered_begin"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_read_ordered_begin - Begin a split collective 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) + +.N fortran +@*/ +int MPI_File_read_ordered_begin(MPI_File fh, void *buf, int count, + MPI_Datatype datatype) +{ + int error_code, nprocs, myrank; + MPI_Count datatype_size; + int source, dest; + ADIO_Offset shared_fp, incr; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_READ_ORDERED_BEGIN"; + void *xbuf=NULL, *e32_buf=NULL; + + 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); + + if (adio_fh->split_coll_count) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iosplitcoll", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + adio_fh->split_coll_count = 1; + + + 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_TEST_DEFERRED(adio_fh, myname, &error_code); + + MPI_Comm_size(adio_fh->comm, &nprocs); + MPI_Comm_rank(adio_fh->comm, &myrank); + + incr = (count*datatype_size)/adio_fh->etype_size; + /* Use a message as a 'token' to order the operations */ + source = myrank - 1; + dest = myrank + 1; + if (source < 0) source = MPI_PROC_NULL; + if (dest >= nprocs) dest = MPI_PROC_NULL; + MPI_Recv(NULL, 0, MPI_BYTE, source, 0, adio_fh->comm, MPI_STATUS_IGNORE); + + ADIO_Get_shared_fp(adio_fh, incr, &shared_fp, &error_code); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + { + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + MPI_Send(NULL, 0, MPI_BYTE, dest, 0, adio_fh->comm); + + 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; + } + + + ADIO_ReadStridedColl(adio_fh, xbuf, count, datatype, ADIO_EXPLICIT_OFFSET, + shared_fp, &adio_fh->split_status, &error_code); + + /* --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(xbuf, datatype, + count, e32_buf); + ADIOI_Free(e32_buf); + } + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/read_orde.c b/ompi/mca/io/romio314/romio/mpi-io/read_orde.c new file mode 100644 index 0000000000..5bf853ed7c --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read_orde.c @@ -0,0 +1,75 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_ordered_end = PMPI_File_read_ordered_end +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_ordered_end MPI_File_read_ordered_end +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_ordered_end as PMPI_File_read_ordered_end +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_ordered_end(MPI_File fh, void *buf, MPI_Status *status) __attribute__((weak,alias("PMPI_File_read_ordered_end"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_read_ordered_end - Complete a split collective read using shared file pointer + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. buf - initial address of buffer (choice) +. status - status object (Status) + +.N fortran +@*/ +int MPI_File_read_ordered_end(MPI_File fh, void *buf, MPI_Status *status) +{ + int error_code=MPI_SUCCESS; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_READ_ORDERED_END"; + + MPIU_UNREFERENCED_ARG(buf); + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + + if (!(adio_fh->split_coll_count)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iosplitcollnone", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + +#ifdef HAVE_STATUS_SET_BYTES + if (status != MPI_STATUS_IGNORE) + *status = adio_fh->split_status; +#endif + adio_fh->split_coll_count = 0; + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/read_sh.c b/ompi/mca/io/romio314/romio/mpi-io/read_sh.c new file mode 100644 index 0000000000..8f2ed6d114 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/read_sh.c @@ -0,0 +1,155 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_read_shared = PMPI_File_read_shared +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_read_shared MPI_File_read_shared +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_read_shared as PMPI_File_read_shared +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_read_shared(MPI_File fh, void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) __attribute__((weak,alias("PMPI_File_read_shared"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + 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, buftype_is_contig, filetype_is_contig; + static char myname[] = "MPI_FILE_READ_SHARED"; + MPI_Count datatype_size; + ADIO_Offset off, shared_fp, incr, bufsize; + ADIO_File adio_fh; + void *xbuf=NULL, *e32_buf=NULL; + + 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_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_FS_SUPPORTS_SHARED(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); + + 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) + { + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + 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; + } + + /* contiguous or strided? */ + 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 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 ((adio_fh->atomicity) && (adio_fh->file_system != ADIO_NFS)) + ADIOI_WRITE_LOCK(adio_fh, off, SEEK_SET, bufsize); + + ADIO_ReadContig(adio_fh, xbuf, count, datatype, ADIO_EXPLICIT_OFFSET, + off, status, &error_code); + + if ((adio_fh->atomicity) && (adio_fh->file_system != ADIO_NFS)) + ADIOI_UNLOCK(adio_fh, off, SEEK_SET, bufsize); + } + else + { + ADIO_ReadStrided(adio_fh, xbuf, count, datatype, ADIO_EXPLICIT_OFFSET, + shared_fp, 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(xbuf, datatype, + count, e32_buf); + ADIOI_Free(e32_buf); + } +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/register_datarep.c b/ompi/mca/io/romio314/romio/mpi-io/register_datarep.c new file mode 100644 index 0000000000..b6f1d68e9d --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/register_datarep.c @@ -0,0 +1,145 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" +#include "adio_extern.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Register_datarep = PMPI_Register_datarep +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Register_datarep MPI_Register_datarep +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Register_datarep as PMPI_Register_datarep +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_Register_datarep(const char *datarep, MPI_Datarep_conversion_function *read_conversion_fn, + MPI_Datarep_conversion_function *write_conversion_fn, + MPI_Datarep_extent_function *dtype_file_extent_fn, void *extra_state) __attribute__((weak,alias("PMPI_Register_datarep"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Register_datarep - Register functions for user-defined data + representations + +Input Parameters: ++ datarep - data representation name (string) +. read_conversion_fn - function invoked to convert from file representation to + native representation (function) +. write_conversion_fn - function invoked to convert from native representation to + file representation (function) +. dtype_file_extent_fn - function invoked to get the exted of a datatype as represented + in the file (function) +- extra_state - pointer to extra state that is passed to each of the + three functions + + Notes: + This function allows the user to provide routines to convert data from + an external representation, used within a file, and the native representation, + used within the CPU. There is one predefined data representation, + 'external32'. Please consult the MPI-2 standard for details on this + function. + +.N fortran + + @*/ +int MPI_Register_datarep(ROMIO_CONST char *datarep, + MPI_Datarep_conversion_function *read_conversion_fn, + MPI_Datarep_conversion_function *write_conversion_fn, + MPI_Datarep_extent_function *dtype_file_extent_fn, + void *extra_state) +{ + int error_code; + ADIOI_Datarep *adio_datarep; + static char myname[] = "MPI_REGISTER_DATAREP"; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + /* --BEGIN ERROR HANDLING-- */ + /* check datarep name (use strlen instead of strnlen because + strnlen is not portable) */ + if (datarep == NULL || + strlen(datarep) < 1 || + strlen(datarep) > MPI_MAX_DATAREP_STRING) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**datarepname", 0); + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + MPIR_MPIOInit(&error_code); + if (error_code != MPI_SUCCESS) goto fn_exit; + + /* --BEGIN ERROR HANDLING-- */ + /* check datarep isn't already registered */ + for (adio_datarep = ADIOI_Datarep_head; adio_datarep; adio_datarep = adio_datarep->next) { + if (!strncmp(datarep, adio_datarep->name, MPI_MAX_DATAREP_STRING)) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_DUP_DATAREP, + "**datarepused", + "**datarepused %s", + datarep); + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + } + } + + /* Check Non-NULL Read and Write conversion function pointer */ + /* Read and Write conversions are currently not supported. */ + if ( (read_conversion_fn != NULL) || (write_conversion_fn != NULL) ) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_CONVERSION, + "**drconvnotsupported", 0); + + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + } + + /* check extent function pointer */ + if (dtype_file_extent_fn == NULL) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**datarepextent", 0); + error_code = MPIO_Err_return_file(MPI_FILE_NULL, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + adio_datarep = ADIOI_Malloc(sizeof(ADIOI_Datarep)); + adio_datarep->name = ADIOI_Strdup(datarep); + adio_datarep->state = extra_state; + adio_datarep->read_conv_fn = read_conversion_fn; + adio_datarep->write_conv_fn = write_conversion_fn; + adio_datarep->extent_fn = dtype_file_extent_fn; + adio_datarep->next = ADIOI_Datarep_head; + + ADIOI_Datarep_head = adio_datarep; + + error_code = MPI_SUCCESS; + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/seek.c b/ompi/mca/io/romio314/romio/mpi-io/seek.c new file mode 100644 index 0000000000..c4ed20f223 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/seek.c @@ -0,0 +1,139 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" +#include "adioi.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_seek = PMPI_File_seek +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_seek MPI_File_seek +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_seek as PMPI_File_seek +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_seek(MPI_File fh, MPI_Offset offset, int whence) __attribute__((weak,alias("PMPI_File_seek"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_seek - Updates the individual file pointer + +Input Parameters: +. fh - file handle (handle) +. offset - file offset (integer) +. whence - update mode (state) + +.N fortran +@*/ +int MPI_File_seek(MPI_File fh, MPI_Offset offset, int whence) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_SEEK"; + MPI_Offset curr_offset, eof_offset; + +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILESEEK, TRDTBLOCK, adio_fh, MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + + 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_NOT_SEQUENTIAL_MODE(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + switch(whence) { + case MPI_SEEK_SET: + /* --BEGIN ERROR HANDLING-- */ + if (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-- */ + break; + case MPI_SEEK_CUR: + /* find offset corr. to current location of file pointer */ + ADIOI_Get_position(adio_fh, &curr_offset); + offset += curr_offset; + + /* --BEGIN ERROR HANDLING-- */ + if (offset < 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_ARG, + "**ionegoffset", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + break; + case MPI_SEEK_END: + /* we can in many cases do seeks w/o a file actually opened, but not in + * the MPI_SEEK_END case */ + ADIOI_TEST_DEFERRED(adio_fh, "MPI_File_seek", &error_code); + + /* find offset corr. to end of file */ + ADIOI_Get_eof_offset(adio_fh, &eof_offset); + offset += eof_offset; + + /* --BEGIN ERROR HANDLING-- */ + if (offset < 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, myname, + __LINE__, MPI_ERR_ARG, + "**ionegoffset", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + break; + default: + /* --BEGIN ERROR HANDLING-- */ + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iobadwhence", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + /* --END ERROR HANDLING-- */ + } + + ADIO_SeekIndividual(adio_fh, offset, ADIO_SEEK_SET, &error_code); + /* TODO: what do we do with this error? */ + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, adio_fh, MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + + error_code = MPI_SUCCESS; + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/seek_sh.c b/ompi/mca/io/romio314/romio/mpi-io/seek_sh.c new file mode 100644 index 0000000000..772852c9d0 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/seek_sh.c @@ -0,0 +1,184 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_seek_shared = PMPI_File_seek_shared +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_seek_shared MPI_File_seek_shared +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_seek_shared as PMPI_File_seek_shared +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_seek_shared(MPI_File fh, MPI_Offset offset, int whence) __attribute__((weak,alias("PMPI_File_seek_shared"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_seek_shared - Updates the shared file pointer + +Input Parameters: +. fh - file handle (handle) +. offset - file offset (integer) +. whence - update mode (state) + +.N fortran +@*/ +int MPI_File_seek_shared(MPI_File fh, MPI_Offset offset, int whence) +{ + int error_code=MPI_SUCCESS, tmp_whence, myrank; + static char myname[] = "MPI_FILE_SEEK_SHARED"; + MPI_Offset curr_offset, eof_offset, tmp_offset; + ADIO_File adio_fh; + + 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_NOT_SEQUENTIAL_MODE(adio_fh, myname, error_code); + MPIO_CHECK_FS_SUPPORTS_SHARED(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + tmp_offset = offset; + MPI_Bcast(&tmp_offset, 1, ADIO_OFFSET, 0, adio_fh->comm); + /* --BEGIN ERROR HANDLING-- */ + if (tmp_offset != offset) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**notsame", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + tmp_whence = whence; + MPI_Bcast(&tmp_whence, 1, MPI_INT, 0, adio_fh->comm); + /* --BEGIN ERROR HANDLING-- */ + if (tmp_whence != whence) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iobadwhence", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + ADIOI_TEST_DEFERRED(adio_fh, "MPI_File_seek_shared", &error_code); + + MPI_Comm_rank(adio_fh->comm, &myrank); + + if (!myrank) + { + switch(whence) + { + case MPI_SEEK_SET: + /* --BEGIN ERROR HANDLING-- */ + if (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-- */ + break; + case MPI_SEEK_CUR: + /* get current location of shared file pointer */ + ADIO_Get_shared_fp(adio_fh, 0, &curr_offset, &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(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + offset += curr_offset; + /* --BEGIN ERROR HANDLING-- */ + if (offset < 0) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**ionegoffset", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + break; + case MPI_SEEK_END: + /* find offset corr. to end of file */ + ADIOI_Get_eof_offset(adio_fh, &eof_offset); + offset += eof_offset; + /* --BEGIN ERROR HANDLING-- */ + if (offset < 0) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_ARG, + "**ionegoffset", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + break; + default: + /* --BEGIN ERROR HANDLING-- */ + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iobadwhence", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + /* --END ERROR HANDLING-- */ + } + + ADIO_Set_shared_fp(adio_fh, offset, &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(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + } + + /* FIXME: explain why the barrier is necessary */ + MPI_Barrier(adio_fh->comm); + + error_code = MPI_SUCCESS; + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/set_atom.c b/ompi/mca/io/romio314/romio/mpi-io/set_atom.c new file mode 100644 index 0000000000..2012116704 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/set_atom.c @@ -0,0 +1,91 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_set_atomicity = PMPI_File_set_atomicity +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_set_atomicity MPI_File_set_atomicity +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_set_atomicity as PMPI_File_set_atomicity +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_set_atomicity(MPI_File fh, int flag) __attribute__((weak,alias("PMPI_File_set_atomicity"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_set_atomicity - Sets the atomicity mode + +Input Parameters: +. fh - file handle (handle) +. flag - true to set atomic mode, false to set nonatomic mode (logical) + +.N fortran +@*/ +int MPI_File_set_atomicity(MPI_File fh, int flag) +{ + int error_code, tmp_flag; + static char myname[] = "MPI_FILE_SET_ATOMICITY"; + ADIO_Fcntl_t *fcntl_struct; + ADIO_File adio_fh; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + ADIOI_TEST_DEFERRED(adio_fh, myname, &error_code); + + if (flag) flag = 1; /* take care of non-one values! */ + +/* check if flag is the same on all processes */ + tmp_flag = flag; + MPI_Bcast(&tmp_flag, 1, MPI_INT, 0, adio_fh->comm); + + /* --BEGIN ERROR HANDLING-- */ + if (tmp_flag != flag) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**notsame", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + if (adio_fh->atomicity == flag){ + error_code = MPI_SUCCESS; + goto fn_exit; + } + + + fcntl_struct = (ADIO_Fcntl_t *) ADIOI_Malloc(sizeof(ADIO_Fcntl_t)); + fcntl_struct->atomicity = flag; + ADIO_Fcntl(adio_fh, ADIO_FCNTL_SET_ATOMICITY, fcntl_struct, &error_code); + /* TODO: what do we do with this error code? */ + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + + ADIOI_Free(fcntl_struct); + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/set_errh.c b/ompi/mca/io/romio314/romio/mpi-io/set_errh.c new file mode 100644 index 0000000000..793f480486 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/set_errh.c @@ -0,0 +1,76 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" +#include "adio_extern.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_set_errhandler = PMPI_File_set_errhandler +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_set_errhandler MPI_File_set_errhandler +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_set_errhandler as PMPI_File_set_errhandler +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_set_errhandler(MPI_File file, MPI_Errhandler errhandler) __attribute__((weak,alias("PMPI_File_set_errhandler"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_set_errhandler - Sets the error handler for a file + +Input Parameters: +. fh - file handle (handle) +. errhandler - error handler (handle) + +.N fortran +@*/ +int MPI_File_set_errhandler(MPI_File mpi_fh, MPI_Errhandler errhandler) +{ + int error_code = MPI_SUCCESS; + static char myname[] = "MPI_FILE_SET_ERRHANDLER"; + ADIO_File fh; + MPIU_THREADPRIV_DECL; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + if (mpi_fh == MPI_FILE_NULL) { + ADIOI_DFLT_ERR_HANDLER = errhandler; + } + else { + fh = MPIO_File_resolve(mpi_fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + if ((errhandler != MPI_ERRORS_RETURN) && + (errhandler != MPI_ERRORS_ARE_FATAL)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_UNSUPPORTED_OPERATION, + "**fileopunsupported", + 0); + error_code = MPIO_Err_return_file(fh, error_code); + goto fn_exit; + } + + fh->err_handler = errhandler; + } + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/set_info.c b/ompi/mca/io/romio314/romio/mpi-io/set_info.c new file mode 100644 index 0000000000..1d95f2cc30 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/set_info.c @@ -0,0 +1,66 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_set_info = PMPI_File_set_info +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_set_info MPI_File_set_info +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_set_info as PMPI_File_set_info +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_set_info(MPI_File fh, MPI_Info info) __attribute__((weak,alias("PMPI_File_set_info"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_set_info - Sets new values for the hints associated with a file + +Input Parameters: +. fh - file handle (handle) +. info - info object (handle) + +.N fortran +@*/ +int MPI_File_set_info(MPI_File fh, MPI_Info info) +{ + int error_code; + static char myname[] = "MPI_FILE_SET_INFO"; + ADIO_File adio_fh; + + 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_INFO_ALL(info, error_code, fh->comm); + /* --END ERROR HANDLING-- */ + + /* set new info */ + ADIO_SetInfo(adio_fh, info, &error_code); + +fn_exit: + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +fn_fail: + goto fn_exit; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/set_size.c b/ompi/mca/io/romio314/romio/mpi-io/set_size.c new file mode 100644 index 0000000000..74c3f6cd18 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/set_size.c @@ -0,0 +1,105 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_set_size = PMPI_File_set_size +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_set_size MPI_File_set_size +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_set_size as PMPI_File_set_size +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_set_size(MPI_File fh, MPI_Offset size) __attribute__((weak,alias("PMPI_File_set_size"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_set_size - Sets the file size + +Input Parameters: +. fh - file handle (handle) +. size - size to truncate or expand file (nonnegative integer) + +.N fortran +@*/ +int MPI_File_set_size(MPI_File fh, MPI_Offset size) +{ + int error_code; + ADIO_File adio_fh; + static char myname[] = "MPI_FILE_SET_SIZE"; + MPI_Offset tmp_sz, max_sz, min_sz; + +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILESETSIZE, TRDTBLOCK, adio_fh, + MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + + 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_NOT_SEQUENTIAL_MODE(adio_fh, myname, error_code); + + if (size < 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iobadsize", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + MPIO_CHECK_WRITABLE(fh, myname, error_code); + /* --END ERROR HANDLING-- */ + + tmp_sz = size; + MPI_Allreduce(&tmp_sz, &max_sz, 1, ADIO_OFFSET, MPI_MAX, adio_fh->comm); + MPI_Allreduce(&tmp_sz, &min_sz, 1, ADIO_OFFSET, MPI_MIN, adio_fh->comm); + + /* --BEGIN ERROR HANDLING-- */ + if (max_sz != min_sz) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**notsame", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + if (!ADIO_Feature(adio_fh, ADIO_SCALABLE_RESIZE)) { + /* rare stupid file systems (like NFS) need to carry out resize on all + * processes */ + ADIOI_TEST_DEFERRED(adio_fh, "MPI_File_set_size", &error_code); + } + + ADIO_Resize(adio_fh, size, &error_code); + /* TODO: what to do with error code? */ + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, adio_fh, MPI_DATATYPE_NULL, -1); +#endif /* MPI_hpux */ + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/set_view.c b/ompi/mca/io/romio314/romio/mpi-io/set_view.c new file mode 100644 index 0000000000..4a820a88e3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/set_view.c @@ -0,0 +1,204 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_set_view = PMPI_File_set_view +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_set_view MPI_File_set_view +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_set_view as PMPI_File_set_view +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_set_view(MPI_File fh, MPI_Offset disp, MPI_Datatype etype, MPI_Datatype filetype, + const char *datarep, MPI_Info info) __attribute__((weak,alias("PMPI_File_set_view"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_set_view - Sets the file view + +Input Parameters: +. fh - file handle (handle) +. disp - displacement (nonnegative integer) +. etype - elementary datatype (handle) +. filetype - filetype (handle) +. datarep - data representation (string) +. info - info object (handle) + +.N fortran +@*/ +int MPI_File_set_view(MPI_File fh, MPI_Offset disp, MPI_Datatype etype, + MPI_Datatype filetype, ROMIO_CONST char *datarep, MPI_Info info) +{ + int error_code; + MPI_Count filetype_size, etype_size; + static char myname[] = "MPI_FILE_SET_VIEW"; + ADIO_Offset shared_fp, byte_off; + ADIO_File adio_fh; + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + + if ((disp < 0) && (disp != MPI_DISPLACEMENT_CURRENT)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iobaddisp", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + + /* rudimentary checks for incorrect etype/filetype.*/ + if (etype == MPI_DATATYPE_NULL) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**ioetype", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + MPIO_DATATYPE_ISCOMMITTED(etype, error_code); + if (error_code != MPI_SUCCESS) { + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + + if (filetype == MPI_DATATYPE_NULL) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iofiletype", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + MPIO_DATATYPE_ISCOMMITTED(filetype, error_code); + if (error_code != MPI_SUCCESS) { + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + + if ((adio_fh->access_mode & MPI_MODE_SEQUENTIAL) && + (disp != MPI_DISPLACEMENT_CURRENT)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iodispifseq", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + + if ((disp == MPI_DISPLACEMENT_CURRENT) && + !(adio_fh->access_mode & MPI_MODE_SEQUENTIAL)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iodispifseq", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + MPIO_CHECK_INFO_ALL(info, error_code, adio_fh->comm); + /* --END ERROR HANDLING-- */ + + MPI_Type_size_x(filetype, &filetype_size); + MPI_Type_size_x(etype, &etype_size); + + /* --BEGIN ERROR HANDLING-- */ + if (etype_size != 0 && filetype_size % etype_size != 0) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "**iofiletype", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + + if ((datarep == NULL) || (strcmp(datarep, "native") && + strcmp(datarep, "NATIVE") && + strcmp(datarep, "external32") && + strcmp(datarep, "EXTERNAL32") && + strcmp(datarep, "internal") && + strcmp(datarep, "INTERNAL")) ) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, + MPI_ERR_UNSUPPORTED_DATAREP, + "**unsupporteddatarep",0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + if (disp == MPI_DISPLACEMENT_CURRENT) { + MPI_Barrier(adio_fh->comm); + ADIO_Get_shared_fp(adio_fh, 0, &shared_fp, &error_code); + /* TODO: check error code */ + + MPI_Barrier(adio_fh->comm); + ADIOI_Get_byte_offset(adio_fh, shared_fp, &byte_off); + /* TODO: check error code */ + + disp = byte_off; + } + + ADIO_Set_view(adio_fh, disp, etype, filetype, info, &error_code); + + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) { + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + /* reset shared file pointer to zero */ + if (ADIO_Feature(adio_fh, ADIO_SHARED_FP) && + (adio_fh->shared_fp_fd != ADIO_FILE_NULL)) + { + /* only one process needs to set it to zero, but I don't want to + create the shared-file-pointer file if shared file pointers have + not been used so far. Therefore, every process that has already + opened the shared-file-pointer file sets the shared file pointer + to zero. If the file was not opened, the value is automatically + zero. Note that shared file pointer is stored as no. of etypes + relative to the current view, whereas indiv. file pointer is + stored in bytes. */ + + ADIO_Set_shared_fp(adio_fh, 0, &error_code); + /* --BEGIN ERROR HANDLING-- */ + if (error_code != MPI_SUCCESS) + error_code = MPIO_Err_return_file(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + } + + if (ADIO_Feature(adio_fh, ADIO_SHARED_FP)) + { + MPI_Barrier(adio_fh->comm); /* for above to work correctly */ + } + if (strcmp(datarep, "external32") && strcmp(datarep, "EXTERNAL32")) + adio_fh->is_external32 = 0; + else + adio_fh->is_external32 = 1; + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +fn_fail: + /* --BEGIN ERROR HANDLING-- */ + error_code = MPIO_Err_return_file(fh, error_code); + goto fn_exit; + /* --END ERROR HANDLING-- */ +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/wr_atallb.c b/ompi/mca/io/romio314/romio/mpi-io/wr_atallb.c new file mode 100644 index 0000000000..83eb28bc88 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/wr_atallb.c @@ -0,0 +1,53 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_at_all_begin = PMPI_File_write_at_all_begin +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_at_all_begin MPI_File_write_at_all_begin +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_at_all_begin as PMPI_File_write_at_all_begin +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_at_all_begin(MPI_File fh, MPI_Offset offset, const void *buf, int count, + MPI_Datatype datatype) __attribute__((weak,alias("PMPI_File_write_at_all_begin"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_write_at_all_begin - Begin a split collective write using + explicit offset + +Input Parameters: +. fh - file handle (handle) +. offset - file offset (nonnegative integer) +. buf - initial address of buffer (choice) +. count - number of elements in buffer (nonnegative integer) +. datatype - datatype of each buffer element (handle) + +.N fortran +@*/ +int MPI_File_write_at_all_begin(MPI_File fh, MPI_Offset offset, ROMIO_CONST void *buf, + int count, MPI_Datatype datatype) +{ + int error_code; + static char myname[] = "MPI_FILE_WRITE_AT_ALL_BEGIN"; + + error_code = MPIOI_File_write_all_begin(fh, offset, + ADIO_EXPLICIT_OFFSET, + buf, count, datatype, myname); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/wr_atalle.c b/ompi/mca/io/romio314/romio/mpi-io/wr_atalle.c new file mode 100644 index 0000000000..fa2ab51423 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/wr_atalle.c @@ -0,0 +1,48 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_at_all_end = PMPI_File_write_at_all_end +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_at_all_end MPI_File_write_at_all_end +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_at_all_end as PMPI_File_write_at_all_end +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_at_all_end(MPI_File fh, const void *buf, MPI_Status *status) __attribute__((weak,alias("PMPI_File_write_at_all_end"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_write_at_all_end - Complete a split collective write using explicit offset + +Input Parameters: +. fh - file handle (handle) +. buf - initial address of buffer (choice) + +Output Parameters: +. status - status object (Status) + +.N fortran +@*/ +int MPI_File_write_at_all_end(MPI_File fh, ROMIO_CONST void *buf, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_WRITE_AT_ALL_END"; + + error_code = MPIOI_File_write_all_end(fh, buf, myname, status); + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/write.c b/ompi/mca/io/romio314/romio/mpi-io/write.c new file mode 100644 index 0000000000..899991d489 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write.c @@ -0,0 +1,186 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write = PMPI_File_write +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write MPI_File_write +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write as PMPI_File_write +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) __attribute__((weak,alias("PMPI_File_write"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + 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, ROMIO_CONST void *buf, int count, + MPI_Datatype datatype, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_WRITE"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEWRITE, TRDTBLOCK, fh, datatype, count); +#endif /* MPI_hpux */ + + error_code = MPIOI_File_write(fh, (MPI_Offset) 0, ADIO_INDIVIDUAL, buf, + count, datatype, myname, status); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} + +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +int MPIOI_File_write(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + const 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_Offset off, bufsize; + ADIO_File adio_fh; + void *e32buf=NULL; + const void *xbuf=NULL; + + 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); + + 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_WRITABLE(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) { + error_code = MPIU_external32_buffer_setup(buf, count, datatype, &e32buf); + if (error_code != MPI_SUCCESS) + goto fn_exit; + + xbuf = e32buf; + } + + if (buftype_is_contig && filetype_is_contig) + { + /* convert bufcount 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. Locking doesn't + work on PIOFS and PVFS, and on NFS it is done in the + ADIO_WriteContig. + */ + + if ((adio_fh->atomicity) && ADIO_Feature(adio_fh, ADIO_LOCKS)) + { + ADIOI_WRITE_LOCK(adio_fh, off, SEEK_SET, bufsize); + } + + ADIO_WriteContig(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 + { + /* For strided and atomic mode, locking is done in ADIO_WriteStrided */ + ADIO_WriteStrided(adio_fh, xbuf, count, datatype, file_ptr_type, + offset, status, &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: + if (e32buf!= NULL) ADIOI_Free(e32buf); + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/write_all.c b/ompi/mca/io/romio314/romio/mpi-io/write_all.c new file mode 100644 index 0000000000..ab77a95b61 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write_all.c @@ -0,0 +1,134 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_all = PMPI_File_write_all +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_all MPI_File_write_all +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_all as PMPI_File_write_all +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_all(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) __attribute__((weak,alias("PMPI_File_write_all"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPI_File_write_all - Collective 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_all(MPI_File fh, ROMIO_CONST void *buf, int count, + MPI_Datatype datatype, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_WRITE_ALL"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEWRITEALL, TRDTBLOCK, fh, datatype, count); +#endif /* MPI_hpux */ + + error_code = MPIOI_File_write_all(fh, (MPI_Offset) 0, + ADIO_INDIVIDUAL, buf, + count, datatype, myname, status); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} + +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +int MPIOI_File_write_all(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + const void *buf, + int count, + MPI_Datatype datatype, + char *myname, + MPI_Status *status) +{ + int error_code; + MPI_Count datatype_size; + ADIO_File adio_fh; + void *e32buf=NULL; + const void *xbuf=NULL; + + 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); + + 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_INTEGRAL_ETYPE(adio_fh, count, datatype_size, myname, error_code); + MPIO_CHECK_WRITABLE(adio_fh, myname, error_code); + MPIO_CHECK_NOT_SEQUENTIAL_MODE(adio_fh, myname, error_code); + MPIO_CHECK_COUNT_SIZE(adio_fh, count, datatype_size, myname, error_code); + /* --END ERROR HANDLING-- */ + + xbuf = buf; + if (adio_fh->is_external32) { + error_code = MPIU_external32_buffer_setup(buf, count, datatype, &e32buf); + if (error_code != MPI_SUCCESS) + goto fn_exit; + + xbuf = e32buf; + } + ADIO_WriteStridedColl(adio_fh, xbuf, count, datatype, file_ptr_type, + offset, status, &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: + if (e32buf != NULL) ADIOI_Free(e32buf); + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/write_allb.c b/ompi/mca/io/romio314/romio/mpi-io/write_allb.c new file mode 100644 index 0000000000..4678477c3b --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write_allb.c @@ -0,0 +1,132 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_all_begin = PMPI_File_write_all_begin +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_all_begin MPI_File_write_all_begin +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_all_begin as PMPI_File_write_all_begin +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_all_begin(MPI_File fh, const void *buf, int count, MPI_Datatype datatype) + __attribute__((weak,alias("PMPI_File_write_all_begin"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_write_all_begin - Begin a split collective 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) + +.N fortran +@*/ +int MPI_File_write_all_begin(MPI_File fh, ROMIO_CONST void *buf, int count, + MPI_Datatype datatype) +{ + int error_code; + static char myname[] = "MPI_FILE_WRITE_ALL_BEGIN"; + + error_code = MPIOI_File_write_all_begin(fh, (MPI_Offset) 0, + ADIO_INDIVIDUAL, buf, count, + datatype, myname); + + return error_code; +} + +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +int MPIOI_File_write_all_begin(MPI_File fh, + MPI_Offset offset, + int file_ptr_type, + const void *buf, + int count, + MPI_Datatype datatype, + char *myname) +{ + int error_code; + MPI_Count datatype_size; + ADIO_File adio_fh; + void *e32buf=NULL; + const void *xbuf=NULL; + + 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); + MPIO_CHECK_NOT_SEQUENTIAL_MODE(adio_fh, 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; + } + + if (adio_fh->split_coll_count) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iosplitcoll", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + adio_fh->split_coll_count = 1; + + MPI_Type_size_x(datatype, &datatype_size); + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_INTEGRAL_ETYPE(adio_fh, count, datatype_size, myname, error_code); + MPIO_CHECK_COUNT_SIZE(adio_fh, count, datatype_size, myname, error_code); + /* --END ERROR HANDLING-- */ + + + xbuf = buf; + if (adio_fh->is_external32) { + error_code = MPIU_external32_buffer_setup(buf, count, datatype, &e32buf); + if (error_code != MPI_SUCCESS) + goto fn_exit; + + xbuf = e32buf; + } + + adio_fh->split_datatype = datatype; + ADIO_WriteStridedColl(adio_fh, xbuf, count, datatype, file_ptr_type, + offset, &adio_fh->split_status, &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: + if ( e32buf != NULL) ADIOI_Free(e32buf); + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/write_alle.c b/ompi/mca/io/romio314/romio/mpi-io/write_alle.c new file mode 100644 index 0000000000..8b999a1eb5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write_alle.c @@ -0,0 +1,95 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_all_end = PMPI_File_write_all_end +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_all_end MPI_File_write_all_end +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_all_end as PMPI_File_write_all_end +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_all_end(MPI_File fh, const void *buf, MPI_Status *status) __attribute__((weak,alias("PMPI_File_write_all_end"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_write_all_end - Complete a split collective write using individual file pointer + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. buf - initial address of buffer (choice) +. status - status object (Status) + +.N fortran +@*/ +int MPI_File_write_all_end(MPI_File fh, ROMIO_CONST void *buf, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_WRITE_ALL_END"; + + error_code = MPIOI_File_write_all_end(fh, buf, myname, status); + + return error_code; +} + +/* prevent multiple definitions of this routine */ +#ifdef MPIO_BUILD_PROFILING +int MPIOI_File_write_all_end(MPI_File fh, + const void *buf, + char *myname, + MPI_Status *status) +{ + int error_code; + ADIO_File adio_fh; + + MPIU_UNREFERENCED_ARG(buf); + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + + if (!(adio_fh->split_coll_count)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iosplitcollnone", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + +#ifdef HAVE_STATUS_SET_BYTES + /* FIXME - we should really ensure that the split_datatype remains + valid by incrementing the ref count in the write_allb.c routine + and decrement it here after setting the bytes */ + if (status != MPI_STATUS_IGNORE) + *status = adio_fh->split_status; +#endif + adio_fh->split_coll_count = 0; + + error_code = MPI_SUCCESS; + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + return error_code; +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi-io/write_at.c b/ompi/mca/io/romio314/romio/mpi-io/write_at.c new file mode 100644 index 0000000000..4362322b67 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write_at.c @@ -0,0 +1,66 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_at = PMPI_File_write_at +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_at MPI_File_write_at +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_at as PMPI_File_write_at +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_at(MPI_File fh, MPI_Offset offset, const void * buf, int count, + MPI_Datatype datatype, MPI_Status *status) + __attribute__((weak,alias("PMPI_File_write_at"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPI_File_write_at - Write using explicit offset + +Input Parameters: +. fh - file handle (handle) +. offset - file offset (nonnegative integer) +. 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_at(MPI_File fh, MPI_Offset offset, ROMIO_CONST void *buf, + int count, MPI_Datatype datatype, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_WRITE_AT"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEWRITEAT, TRDTBLOCK, fh, datatype, count); +#endif /* MPI_hpux */ + + /* MPIOI_File_write() defined in mpi-io/write.c */ + error_code = MPIOI_File_write(fh, offset, ADIO_EXPLICIT_OFFSET, buf, + count, datatype, myname, status); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/write_atall.c b/ompi/mca/io/romio314/romio/mpi-io/write_atall.c new file mode 100644 index 0000000000..6f815cdd4c --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write_atall.c @@ -0,0 +1,67 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_at_all = PMPI_File_write_at_all +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_at_all MPI_File_write_at_all +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_at_all as PMPI_File_write_at_all +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_at_all(MPI_File fh, MPI_Offset offset, const void *buf, int count, + MPI_Datatype datatype, MPI_Status *status) + __attribute__((weak,alias("PMPI_File_write_at_all"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPI_File_write_at_all - Collective write using explicit offset + +Input Parameters: +. fh - file handle (handle) +. offset - file offset (nonnegative integer) +. 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_at_all(MPI_File fh, MPI_Offset offset, ROMIO_CONST void *buf, + int count, MPI_Datatype datatype, + MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_WRITE_AT_ALL"; +#ifdef MPI_hpux + int fl_xmpi; + + HPMP_IO_START(fl_xmpi, BLKMPIFILEWRITEATALL, TRDTBLOCK, fh, datatype, count); +#endif /* MPI_hpux */ + + error_code = MPIOI_File_write_all(fh, offset, ADIO_EXPLICIT_OFFSET, + buf, count, datatype, myname, status); + +#ifdef MPI_hpux + HPMP_IO_END(fl_xmpi, fh, datatype, count); +#endif /* MPI_hpux */ + return error_code; +} + diff --git a/ompi/mca/io/romio314/romio/mpi-io/write_ord.c b/ompi/mca/io/romio314/romio/mpi-io/write_ord.c new file mode 100644 index 0000000000..60c14f3e80 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write_ord.c @@ -0,0 +1,128 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + * + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_ordered = PMPI_File_write_ordered +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_ordered MPI_File_write_ordered +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_ordered as PMPI_File_write_ordered +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_ordered(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) __attribute__((weak,alias("PMPI_File_write_ordered"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + MPI_File_write_ordered - Collective 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_ordered(MPI_File fh, ROMIO_CONST void *buf, int count, + MPI_Datatype datatype, MPI_Status *status) +{ + int error_code, nprocs, myrank; + ADIO_Offset incr; + MPI_Count datatype_size; + int source, dest; + static char myname[] = "MPI_FILE_WRITE_ORDERED"; + ADIO_Offset shared_fp; + ADIO_File adio_fh; + void *e32buf=NULL; + const void *xbuf; + + 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_TEST_DEFERRED(adio_fh, myname, &error_code); + + MPI_Comm_size(adio_fh->comm, &nprocs); + MPI_Comm_rank(adio_fh->comm, &myrank); + + incr = (count*datatype_size)/adio_fh->etype_size; + /* Use a message as a 'token' to order the operations */ + source = myrank - 1; + dest = myrank + 1; + if (source < 0) source = MPI_PROC_NULL; + if (dest >= nprocs) dest = MPI_PROC_NULL; + MPI_Recv(NULL, 0, MPI_BYTE, source, 0, adio_fh->comm, MPI_STATUS_IGNORE); + + ADIO_Get_shared_fp(adio_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(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + MPI_Send(NULL, 0, MPI_BYTE, dest, 0, adio_fh->comm); + + xbuf = buf; + if (adio_fh->is_external32) { + error_code = MPIU_external32_buffer_setup(buf, count, datatype, &e32buf); + if (error_code != MPI_SUCCESS) + goto fn_exit; + + xbuf = e32buf; + } + + ADIO_WriteStridedColl(adio_fh, xbuf, count, datatype, ADIO_EXPLICIT_OFFSET, + shared_fp, status, &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: + if (e32buf != NULL) ADIOI_Free(e32buf); + MPIU_THREAD_CS_EXIT(ALLFUNC,); + + /* FIXME: Check for error code from WriteStridedColl? */ + return error_code; +} + diff --git a/ompi/mca/io/romio314/romio/mpi-io/write_ordb.c b/ompi/mca/io/romio314/romio/mpi-io/write_ordb.c new file mode 100644 index 0000000000..77bbab030e --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write_ordb.c @@ -0,0 +1,132 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_ordered_begin = PMPI_File_write_ordered_begin +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_ordered_begin MPI_File_write_ordered_begin +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_ordered_begin as PMPI_File_write_ordered_begin +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_ordered_begin(MPI_File fh, const void *buf, int count, MPI_Datatype datatype) + __attribute__((weak,alias("PMPI_File_write_ordered_begin"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_write_ordered_begin - Begin a split collective write 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) + +.N fortran +@*/ +int MPI_File_write_ordered_begin(MPI_File fh, ROMIO_CONST void *buf, int count, + MPI_Datatype datatype) +{ + int error_code, nprocs, myrank; + ADIO_Offset incr; + MPI_Count datatype_size; + int source, dest; + static char myname[] = "MPI_FILE_WRITE_ORDERED_BEGIN"; + ADIO_Offset shared_fp; + ADIO_File adio_fh; + void *e32buf = NULL; + const void *xbuf=NULL; + + 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); + + if (adio_fh->split_coll_count) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iosplitcoll", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + adio_fh->split_coll_count = 1; + + 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_TEST_DEFERRED(adio_fh, myname, &error_code); + + MPI_Comm_size(adio_fh->comm, &nprocs); + MPI_Comm_rank(adio_fh->comm, &myrank); + + incr = (count*datatype_size)/adio_fh->etype_size; + /* Use a message as a 'token' to order the operations */ + source = myrank - 1; + dest = myrank + 1; + if (source < 0) source = MPI_PROC_NULL; + if (dest >= nprocs) dest = MPI_PROC_NULL; + MPI_Recv(NULL, 0, MPI_BYTE, source, 0, adio_fh->comm, MPI_STATUS_IGNORE); + + ADIO_Get_shared_fp(adio_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(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + MPI_Send(NULL, 0, MPI_BYTE, dest, 0, adio_fh->comm); + + xbuf = buf; + if (adio_fh->is_external32) { + error_code = MPIU_external32_buffer_setup(buf, count, datatype, &e32buf); + if (error_code != MPI_SUCCESS) + goto fn_exit; + + xbuf = e32buf; + } + + ADIO_WriteStridedColl(adio_fh, xbuf, count, datatype, ADIO_EXPLICIT_OFFSET, + shared_fp, &adio_fh->split_status, &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,); + + /* FIXME: Check for error code from WriteStridedColl? */ + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/write_orde.c b/ompi/mca/io/romio314/romio/mpi-io/write_orde.c new file mode 100644 index 0000000000..a0a6eea461 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write_orde.c @@ -0,0 +1,75 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_ordered_end = PMPI_File_write_ordered_end +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_ordered_end MPI_File_write_ordered_end +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_ordered_end as PMPI_File_write_ordered_end +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_ordered_end(MPI_File fh, const void *buf, MPI_Status *status) __attribute__((weak,alias("PMPI_File_write_ordered_end"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_File_write_ordered_end - Complete a split collective write using shared file pointer + +Input Parameters: +. fh - file handle (handle) + +Output Parameters: +. buf - initial address of buffer (choice) +. status - status object (Status) + +.N fortran +@*/ +int MPI_File_write_ordered_end(MPI_File fh, ROMIO_CONST void *buf, MPI_Status *status) +{ + int error_code; + static char myname[] = "MPI_FILE_WRITE_ORDERED_END"; + ADIO_File adio_fh; + + MPIU_UNREFERENCED_ARG(buf); + + MPIU_THREAD_CS_ENTER(ALLFUNC,); + + adio_fh = MPIO_File_resolve(fh); + + /* --BEGIN ERROR HANDLING-- */ + MPIO_CHECK_FILE_HANDLE(adio_fh, myname, error_code); + + if (!(adio_fh->split_coll_count)) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_IO, + "**iosplitcollnone", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + +#ifdef HAVE_STATUS_SET_BYTES + if (status != MPI_STATUS_IGNORE) + *status = adio_fh->split_status; +#endif + adio_fh->split_coll_count = 0; + + +fn_exit: + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi-io/write_sh.c b/ompi/mca/io/romio314/romio/mpi-io/write_sh.c new file mode 100644 index 0000000000..fc2b7b23de --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi-io/write_sh.c @@ -0,0 +1,149 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_File_write_shared = PMPI_File_write_shared +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_File_write_shared MPI_File_write_shared +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_File_write_shared as PMPI_File_write_shared +/* end of weak pragmas */ +#elif defined(HAVE_WEAK_ATTRIBUTE) +int MPI_File_write_shared(MPI_File fh, const void *buf, int count, MPI_Datatype datatype, + MPI_Status *status) __attribute__((weak,alias("PMPI_File_write_shared"))); +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/* status object not filled currently */ + +/*@ + 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 fh, ROMIO_CONST void *buf, int count, + MPI_Datatype datatype, MPI_Status *status) +{ + int error_code, buftype_is_contig, filetype_is_contig; + ADIO_Offset bufsize; + static char myname[] = "MPI_FILE_READ_SHARED"; + MPI_Count datatype_size, incr; + ADIO_Offset off, shared_fp; + ADIO_File adio_fh; + void *e32buf = NULL; + const void *xbuf = NULL; + + 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_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_FS_SUPPORTS_SHARED(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); + + 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) + { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, + myname, __LINE__, MPI_ERR_INTERN, + "**iosharedfailed", 0); + error_code = MPIO_Err_return_file(adio_fh, error_code); + goto fn_exit; + } + /* --END ERROR HANDLING-- */ + + xbuf = buf; + if (adio_fh->is_external32) { + error_code = MPIU_external32_buffer_setup(buf, count, datatype, &e32buf); + if (error_code != MPI_SUCCESS) + goto fn_exit; + + xbuf = e32buf; + } + + if (buftype_is_contig && filetype_is_contig) + { + /* convert bufocunt and shared_fp to bytes */ + bufsize = datatype_size * count; + off = adio_fh->disp + adio_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 ((adio_fh->atomicity) && (adio_fh->file_system != ADIO_NFS)) + ADIOI_WRITE_LOCK(adio_fh, off, SEEK_SET, bufsize); + + ADIO_WriteContig(adio_fh, xbuf, count, datatype, ADIO_EXPLICIT_OFFSET, + off, status, &error_code); + + if ((adio_fh->atomicity) && (adio_fh->file_system != ADIO_NFS)) + ADIOI_UNLOCK(adio_fh, off, SEEK_SET, bufsize); + } + else + { + ADIO_WriteStrided(adio_fh, xbuf, 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(adio_fh, error_code); + /* --END ERROR HANDLING-- */ + +fn_exit: + if (e32buf != NULL) ADIOI_Free(e32buf); + MPIU_THREAD_CS_EXIT(ALLFUNC,); + return error_code; +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/array/Makefile.in b/ompi/mca/io/romio314/romio/mpi2-other/array/Makefile.in new file mode 100644 index 0000000000..41a366e398 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/array/Makefile.in @@ -0,0 +1,80 @@ +CC = @CC@ +AR = @AR@ +LIBNAME = @LIBNAME@ +RANLIB = @RANLIB@ +srcdir = @srcdir@ +CC_SHL = @CC_SHL@ +SHLIBNAME = @SHLIBNAME@ + +INCLUDE_DIR = -I@MPI_INCLUDE_DIR@ -I../../include -I${srcdir}/../../mpi-io -I${srcdir}/../../adio/include -I../../adio/include +CFLAGS = @CPPFLAGS@ @CFLAGS@ $(MPIOPROFILE) $(INCLUDE_DIR) + +top_builddir = @master_topbuild_dir@ +LIBTOOL = @LIBTOOL@ +C_COMPILE_SHL = $(CC_SHL) + +@VPATH@ + +MPIO_OBJECTS = subarray.o darray.o + +MPIO_TMP_POBJECTS = subarray.p darray.p + +MPIO_REAL_POBJECTS = _subarray.o _darray.o + +all: $(LIBNAME) + @if [ "@ENABLE_SHLIB@" != "none" ] ; then \ + $(MAKE) $(SHLIBNAME).la ;\ + fi + +.SUFFIXES: $(SUFFIXES) .p .sp .lo + +.c.o: + $(CC) $(CFLAGS) -c $< +.c.lo: + $(C_COMPILE_SHL) $(CFLAGS) -c $< -o _s$*.o + @mv -f _s$*.o $*.lo + +.c.p: + @cp $(srcdir)/$*.c _$*.c + $(CC) $(CFLAGS) -c _$*.c + @rm -f _$*.c + +.c.sp: + $(C_COMPILE_SHL) $(CFLAGS) -c $< -o _$*.lo + +profile: $(MPIO_REAL_POBJECTS) + $(AR) $(LIBNAME) $(MPIO_REAL_POBJECTS) + $(RANLIB) $(LIBNAME) + @if [ "@ENABLE_SHLIB@" != "none" ] ; then \ + $(MAKE) P$(SHLIBNAME).la ;\ + fi + @rm -f _*.o + +$(LIBNAME): $(MPIO_OBJECTS) + $(AR) $(LIBNAME) $(MPIO_OBJECTS) + $(RANLIB) $(LIBNAME) + +MPIO_LOOBJECTS = $(MPIO_OBJECTS:.o=.lo) +$(SHLIBNAME).la: $(MPIO_LOOBJECTS) + $(AR) $(SHLIBNAME).la $(MPIO_LOOBJECTS) + +# -------------------------------------------------------------------------- +# We use P$(SHLBNAME) simply to distinguish the regular lib build from the +# profiling library build +MPIO_LOPOBJECTS = $(MPIO_REAL_POBJECTS:.o=.lo) +MPIO_TMP_LOPOBJECTS = ${MPIO_TMP_POBJECTS:.p=.sp} +P$(SHLIBNAME).la: $(MPIO_TMP_LOPOBJECTS) + $(AR) $(SHLIBNAME).la $(MPIO_LOPOBJECTS) +# -------------------------------------------------------------------------- + +clean: + @rm -f *.o *.lo *.gcno *.gcda *.bb *.bbg + @rm -f ${srcdir}/*.gcno ${srcdir}/*.gcda + @rm -f ${srcdir}/*.bb ${srcdir}/*.bbg + +# Rules for the profiling objects +_subarray.o: subarray.c + $(CC) $(CFLAGS) -c $(srcdir)/subarray.c -o _subarray.o +_darray.o: darray.c + $(CC) $(CFLAGS) -c $(srcdir)/darray.c -o _darray.o + diff --git a/ompi/mca/io/romio314/romio/mpi2-other/array/darray.c b/ompi/mca/io/romio314/romio/mpi2-other/array/darray.c new file mode 100644 index 0000000000..6918c5ec70 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/array/darray.c @@ -0,0 +1,209 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Type_create_darray = PMPI_Type_create_darray +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Type_create_darray MPI_Type_create_darray +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Type_create_darray as PMPI_Type_create_darray +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ +MPI_Type_create_darray - Creates a datatype corresponding to a distributed, multidimensional array + +Input Parameters: +. size - size of process group (positive integer) +. rank - rank in process group (nonnegative integer) +. ndims - number of array dimensions as well as process grid dimensions (positive integer) +. array_of_gsizes - number of elements of type oldtype in each dimension of global array (array of positive integers) +. array_of_distribs - distribution of array in each dimension (array of state) +. array_of_dargs - distribution argument in each dimension (array of positive integers) +. array_of_psizes - size of process grid in each dimension (array of positive integers) +. order - array storage order flag (state) +. oldtype - old datatype (handle) + +Output Parameters: +. newtype - new datatype (handle) + +.N fortran +@*/ +int MPI_Type_create_darray(int size, int rank, int ndims, + int *array_of_gsizes, int *array_of_distribs, + int *array_of_dargs, int *array_of_psizes, + int order, MPI_Datatype oldtype, + MPI_Datatype *newtype) +{ + int err, error_code; + int i; + MPI_Aint orig_extent, size_with_aint; + MPI_Offset size_with_offset; + static char myname[] = "MPI_TYPE_CREATE_DARRAY"; + + /* --BEGIN ERROR HANDLING-- */ + if (size <= 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid size argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (rank < 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid rank argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (ndims <= 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid ndoms argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (array_of_gsizes <= (int *) 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid array_of_gsizes argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (array_of_distribs <= (int *) 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid array_of_distribs argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (array_of_dargs <= (int *) 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid array_of_dargs argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (array_of_psizes <= (int *) 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid array_of_psizes argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + + for (i=0; iPMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_type_create_darray_ PMPI_TYPE_CREATE_DARRAY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_type_create_darray_ pmpi_type_create_darray__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_type_create_darray pmpi_type_create_darray_ +#endif +#define mpi_type_create_darray_ pmpi_type_create_darray +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_type_create_darray_ pmpi_type_create_darray +#endif +#define mpi_type_create_darray_ pmpi_type_create_darray_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_type_create_darray_ MPI_TYPE_CREATE_DARRAY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_type_create_darray_ mpi_type_create_darray__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_type_create_darray mpi_type_create_darray_ +#endif +#define mpi_type_create_darray_ mpi_type_create_darray +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_type_create_darray_ mpi_type_create_darray +#endif +#endif +#endif + +#ifdef MPIHP +/* Prototype to keep compiler happy */ +void mpi_type_create_darray_(int *size,int *rank,int *ndims, + int *array_of_gsizes,int *array_of_distribs, + int *array_of_dargs,int *array_of_psizes, + int *order, MPI_Fint *oldtype, + MPI_Fint *newtype, int *ierr ); + +void mpi_type_create_darray_(int *size,int *rank,int *ndims, + int *array_of_gsizes,int *array_of_distribs, + int *array_of_dargs,int *array_of_psizes, + int *order, MPI_Fint *oldtype, + MPI_Fint *newtype, int *ierr ) +{ + MPI_Datatype oldtype_c, newtype_c; + + oldtype_c = MPI_Type_f2c(*oldtype); + + *ierr = MPI_Type_create_darray(*size,*rank,*ndims,array_of_gsizes,array_of_distribs,array_of_dargs,array_of_psizes,*order,oldtype_c,&newtype_c); + + *newtype = MPI_Type_c2f(newtype_c); +} + +#else +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL void mpi_type_create_darray_(MPI_Fint *size,MPI_Fint *rank,MPI_Fint *ndims, + MPI_Fint *array_of_gsizes,MPI_Fint *array_of_distribs, + MPI_Fint *array_of_dargs,MPI_Fint *array_of_psizes, + MPI_Fint *order,MPI_Fint *oldtype, + MPI_Fint *newtype, MPI_Fint *ierr); + +FORTRAN_API void FORT_CALL void mpi_type_create_darray_(MPI_Fint *size,MPI_Fint *rank,MPI_Fint *ndims, + MPI_Fint *array_of_gsizes,MPI_Fint *array_of_distribs, + MPI_Fint *array_of_dargs,MPI_Fint *array_of_psizes, + MPI_Fint *order,MPI_Fint *oldtype, + MPI_Fint *newtype, MPI_Fint *ierr ) +{ + *ierr = MPI_Type_create_darray(*size,*rank,*ndims,array_of_gsizes,array_of_distribs,array_of_dargs,array_of_psizes,*order,*oldtype,newtype); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi2-other/array/fortran/subarrayf.c b/ompi/mca/io/romio314/romio/mpi2-other/array/fortran/subarrayf.c new file mode 100644 index 0000000000..7a2e54a530 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/array/fortran/subarrayf.c @@ -0,0 +1,127 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "adio.h" +#include "mpio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +extern FORTRAN_API void FORT_CALL MPI_TYPE_CREATE_SUBARRAY(MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *); +#pragma weak MPI_TYPE_CREATE_SUBARRAY = PMPI_TYPE_CREATE_SUBARRAY +#elif defined(FORTRANDOUBLEUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_type_create_subarray__(MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *); +#pragma weak mpi_type_create_subarray__ = pmpi_type_create_subarray__ +#elif !defined(FORTRANUNDERSCORE) +extern FORTRAN_API void FORT_CALL mpi_type_create_subarray(MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *); +#pragma weak mpi_type_create_subarray = pmpi_type_create_subarray +#else +extern FORTRAN_API void FORT_CALL mpi_type_create_subarray_(MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *); +#pragma weak mpi_type_create_subarray_ = pmpi_type_create_subarray_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_TYPE_CREATE_SUBARRAY MPI_TYPE_CREATE_SUBARRAY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_type_create_subarray__ mpi_type_create_subarray__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_type_create_subarray mpi_type_create_subarray +#else +#pragma _HP_SECONDARY_DEF pmpi_type_create_subarray_ mpi_type_create_subarray_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_TYPE_CREATE_SUBARRAY as PMPI_TYPE_CREATE_SUBARRAY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_type_create_subarray__ as pmpi_type_create_subarray__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_type_create_subarray as pmpi_type_create_subarray +#else +#pragma _CRI duplicate mpi_type_create_subarray_ as pmpi_type_create_subarray_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#ifdef FORTRANCAPS +#define mpi_type_create_subarray_ PMPI_TYPE_CREATE_SUBARRAY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_type_create_subarray_ pmpi_type_create_subarray__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_type_create_subarray pmpi_type_create_subarray_ +#endif +#define mpi_type_create_subarray_ pmpi_type_create_subarray +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_type_create_subarray_ pmpi_type_create_subarray +#endif +#define mpi_type_create_subarray_ pmpi_type_create_subarray_ +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_type_create_subarray_ MPI_TYPE_CREATE_SUBARRAY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_type_create_subarray_ mpi_type_create_subarray__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_type_create_subarray mpi_type_create_subarray_ +#endif +#define mpi_type_create_subarray_ mpi_type_create_subarray +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_type_create_subarray_ mpi_type_create_subarray +#endif +#endif +#endif + +#ifdef MPIHP +/* Prototype to keep compiler happy */ +void mpi_type_create_subarray_(int *ndims,int *array_of_sizes, + int *array_of_subsizes,int *array_of_starts, + int *order,MPI_Fint *oldtype, + MPI_Fint *newtype, int *ierr ); + +void mpi_type_create_subarray_(int *ndims,int *array_of_sizes, + int *array_of_subsizes,int *array_of_starts, + int *order,MPI_Fint *oldtype, + MPI_Fint *newtype, int *ierr ) +{ + MPI_Datatype oldtype_c, newtype_c; + + oldtype_c = MPI_Type_f2c(*oldtype); + + *ierr = MPI_Type_create_subarray(*ndims,array_of_sizes,array_of_subsizes,array_of_starts,*order,oldtype_c,&newtype_c); + *newtype = MPI_Type_c2f(newtype_c); +} + +#else + +/* Prototype to keep compiler happy */ +FORTRAN_API void FORT_CALL void mpi_type_create_subarray_(MPI_Fint *ndims,MPI_Fint *array_of_sizes, + MPI_Fint *array_of_subsizes,MPI_Fint *array_of_starts, + MPI_Fint *order,MPI_Fint *oldtype, + MPI_Fint *newtype, MPI_Fint *ierr ); + +FORTRAN_API void FORT_CALL void mpi_type_create_subarray_(MPI_Fint *ndims,MPI_Fint *array_of_sizes, + MPI_Fint *array_of_subsizes,MPI_Fint *array_of_starts, + MPI_Fint *order,MPI_Fint *oldtype, + MPI_Fint *newtype, MPI_Fint *ierr ) +{ +*ierr = MPI_Type_create_subarray(*ndims,array_of_sizes,array_of_subsizes,array_of_starts,*order,*oldtype,newtype); +} +#endif diff --git a/ompi/mca/io/romio314/romio/mpi2-other/array/subarray.c b/ompi/mca/io/romio314/romio/mpi2-other/array/subarray.c new file mode 100644 index 0000000000..69974c7505 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/array/subarray.c @@ -0,0 +1,174 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Type_create_subarray = PMPI_Type_create_subarray +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Type_create_subarray MPI_Type_create_subarray +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Type_create_subarray as PMPI_Type_create_subarray +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ +MPI_Type_create_subarray - Creates a datatype describing a subarray of a multidimensional array + +Input Parameters: +. ndims - number of array dimensions (positive integer) +. array_of_sizes - number of elements of type oldtype in each dimension of the full array (array of positive integers) +. array_of_subsizes - number of elements of type oldtype in each dimension of the subarray (array of positive integers) +. array_of_starts - starting coordinates of the subarray in each dimension (array of nonnegative integers) +. order - array storage order flag (state) +. oldtype - old datatype (handle) + +Output Parameters: +. newtype - new datatype (handle) + +.N fortran +@*/ +int MPI_Type_create_subarray(int ndims, int *array_of_sizes, + int *array_of_subsizes, int *array_of_starts, + int order, MPI_Datatype oldtype, + MPI_Datatype *newtype) +{ + MPI_Aint extent, size_with_aint; + int i, err, error_code; + MPI_Offset size_with_offset; + + /* --BEGIN ERROR HANDLING-- */ + if (ndims <= 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid ndims argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (array_of_sizes <= (int *) 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid array_of_sizes argument", + 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (array_of_subsizes <= (int *) 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid array_of_subsizes argument", + 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (array_of_starts <= (int *) 0) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid array_of_starts argument", + 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + + for (i=0; i array_of_sizes[i]) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid subsize argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + if (array_of_starts[i] > (array_of_sizes[i] - array_of_subsizes[i])) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid start argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + } + + /* order argument checked below */ + + if (oldtype == MPI_DATATYPE_NULL) { + error_code = MPIO_Err_create_code(MPI_SUCCESS, + MPIR_ERR_RECOVERABLE, + myname, __LINE__, MPI_ERR_ARG, + "Invalid type argument", 0); + return MPIO_Err_return_comm(MPI_COMM_SELF, error_code); + } + + MPI_Type_extent(oldtype, &extent); + +/* check if MPI_Aint is large enough for size of global array. + if not, complain. */ + + size_with_aint = extent; + for (i=0; iPMPI */ +#include "mpioprof.h" +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_info_create_ MPI_INFO_CREATE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_create_ mpi_info_create__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_create mpi_info_create_ +#endif +#define mpi_info_create_ mpi_info_create +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_create_ mpi_info_create +#endif +#endif +#endif + +void mpi_info_create_(MPI_Fint *info, int *ierr ) +{ + MPI_Info info_c; + + *ierr = MPI_Info_create(&info_c); + *info = MPI_Info_c2f(info_c); +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_deletef.c b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_deletef.c new file mode 100644 index 0000000000..f7a7bb4d58 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_deletef.c @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpio.h" +#include "adio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) +#ifdef FORTRANCAPS +#define mpi_info_delete_ PMPI_INFO_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_delete_ pmpi_info_delete__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_delete pmpi_info_delete_ +#endif +#define mpi_info_delete_ pmpi_info_delete +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_delete_ pmpi_info_delete +#endif +#define mpi_info_delete_ pmpi_info_delete_ +#endif + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +#pragma weak MPI_INFO_DELETE = PMPI_INFO_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma weak mpi_info_delete__ = pmpi_info_delete__ +#elif !defined(FORTRANUNDERSCORE) +#pragma weak mpi_info_delete = pmpi_info_delete +#else +#pragma weak mpi_info_delete_ = pmpi_info_delete_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_INFO_DELETE MPI_INFO_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_delete__ mpi_info_delete__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_delete mpi_info_delete +#else +#pragma _HP_SECONDARY_DEF pmpi_info_delete_ mpi_info_delete_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_INFO_DELETE as PMPI_INFO_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_info_delete__ as pmpi_info_delete__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_info_delete as pmpi_info_delete +#else +#pragma _CRI duplicate mpi_info_delete_ as pmpi_info_delete_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_info_delete_ MPI_INFO_DELETE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_delete_ mpi_info_delete__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_delete mpi_info_delete_ +#endif +#define mpi_info_delete_ mpi_info_delete +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_delete_ mpi_info_delete +#endif +#endif +#endif + +void mpi_info_delete_(MPI_Fint *info, char *key, int *ierr, int keylen) +{ + MPI_Info info_c; + char *newkey; + int new_keylen, lead_blanks, i; + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_delete: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + /* strip leading and trailing blanks in key */ + lead_blanks = 0; + for (i=0; i=0; i--) if (key[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_Info_delete: key is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + new_keylen = i + 1 - lead_blanks; + key += lead_blanks; + + newkey = (char *) ADIOI_Malloc((new_keylen+1)*sizeof(char)); + ADIOI_Strncpy(newkey, key, new_keylen); + newkey[new_keylen] = '\0'; + + info_c = MPI_Info_f2c(*info); + *ierr = MPI_Info_delete(info_c, newkey); + ADIOI_Free(newkey); +} + diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_dupf.c b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_dupf.c new file mode 100644 index 0000000000..87162005ab --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_dupf.c @@ -0,0 +1,94 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpio.h" +#include "adio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) +#ifdef FORTRANCAPS +#define mpi_info_dup_ PMPI_INFO_DUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_dup_ pmpi_info_dup__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_dup pmpi_info_dup_ +#endif +#define mpi_info_dup_ pmpi_info_dup +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_dup_ pmpi_info_dup +#endif +#define mpi_info_dup_ pmpi_info_dup_ +#endif + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +#pragma weak MPI_INFO_DUP = PMPI_INFO_DUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma weak mpi_info_dup__ = pmpi_info_dup__ +#elif !defined(FORTRANUNDERSCORE) +#pragma weak mpi_info_dup = pmpi_info_dup +#else +#pragma weak mpi_info_dup_ = pmpi_info_dup_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_INFO_DUP MPI_INFO_DUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_dup__ mpi_info_dup__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_dup mpi_info_dup +#else +#pragma _HP_SECONDARY_DEF pmpi_info_dup_ mpi_info_dup_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_INFO_DUP as PMPI_INFO_DUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_info_dup__ as pmpi_info_dup__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_info_dup as pmpi_info_dup +#else +#pragma _CRI duplicate mpi_info_dup_ as pmpi_info_dup_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_info_dup_ MPI_INFO_DUP +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_dup_ mpi_info_dup__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_dup mpi_info_dup_ +#endif +#define mpi_info_dup_ mpi_info_dup +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_dup_ mpi_info_dup +#endif +#endif +#endif + +void mpi_info_dup_(MPI_Fint *info, MPI_Fint *newinfo, int *ierr ) +{ + MPI_Info info_c, newinfo_c; + + info_c = MPI_Info_f2c(*info); + *ierr = MPI_Info_dup(info_c, &newinfo_c); + *newinfo = MPI_Info_c2f(newinfo_c); +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_freef.c b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_freef.c new file mode 100644 index 0000000000..5f200c9622 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_freef.c @@ -0,0 +1,95 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpio.h" +#include "adio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) +#ifdef FORTRANCAPS +#define mpi_info_free_ PMPI_INFO_FREE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_free_ pmpi_info_free__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_free pmpi_info_free_ +#endif +#define mpi_info_free_ pmpi_info_free +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_free_ pmpi_info_free +#endif +#define mpi_info_free_ pmpi_info_free_ +#endif + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +#pragma weak MPI_INFO_FREE = PMPI_INFO_FREE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma weak mpi_info_free__ = pmpi_info_free__ +#elif !defined(FORTRANUNDERSCORE) +#pragma weak mpi_info_free = pmpi_info_free +#else +#pragma weak mpi_info_free_ = pmpi_info_free_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_INFO_FREE MPI_INFO_FREE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_free__ mpi_info_free__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_free mpi_info_free +#else +#pragma _HP_SECONDARY_DEF pmpi_info_free_ mpi_info_free_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_INFO_FREE as PMPI_INFO_FREE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_info_free__ as pmpi_info_free__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_info_free as pmpi_info_free +#else +#pragma _CRI duplicate mpi_info_free_ as pmpi_info_free_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_info_free_ MPI_INFO_FREE +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_free_ mpi_info_free__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_free mpi_info_free_ +#endif +#define mpi_info_free_ mpi_info_free +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_free_ mpi_info_free +#endif +#endif +#endif + +void mpi_info_free_(MPI_Fint *info, int *ierr ) +{ + MPI_Info info_c; + + info_c = MPI_Info_f2c(*info); + *ierr = MPI_Info_free(&info_c); + *info = MPI_Info_c2f(info_c); +} + diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_getf.c b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_getf.c new file mode 100644 index 0000000000..ae60cc22b0 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_getf.c @@ -0,0 +1,144 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpio.h" +#include "adio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) +#ifdef FORTRANCAPS +#define mpi_info_get_ PMPI_INFO_GET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_get_ pmpi_info_get__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_get pmpi_info_get_ +#endif +#define mpi_info_get_ pmpi_info_get +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_get_ pmpi_info_get +#endif +#define mpi_info_get_ pmpi_info_get_ +#endif + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +#pragma weak MPI_INFO_GET = PMPI_INFO_GET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma weak mpi_info_get__ = pmpi_info_get__ +#elif !defined(FORTRANUNDERSCORE) +#pragma weak mpi_info_get = pmpi_info_get +#else +#pragma weak mpi_info_get_ = pmpi_info_get_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_INFO_GET MPI_INFO_GET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_get__ mpi_info_get__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_get mpi_info_get +#else +#pragma _HP_SECONDARY_DEF pmpi_info_get_ mpi_info_get_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_INFO_GET as PMPI_INFO_GET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_info_get__ as pmpi_info_get__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_info_get as pmpi_info_get +#else +#pragma _CRI duplicate mpi_info_get_ as pmpi_info_get_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_info_get_ MPI_INFO_GET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_get_ mpi_info_get__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_get mpi_info_get_ +#endif +#define mpi_info_get_ mpi_info_get +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_get_ mpi_info_get +#endif +#endif +#endif + +void mpi_info_get_(MPI_Fint *info, char *key, int *valuelen, char *value, + int *flag, int *ierr, int keylen, int valspace) +{ + MPI_Info info_c; + char *newkey, *tmpvalue; + int new_keylen, lead_blanks, i, tmpvaluelen; + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_get: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + /* strip leading and trailing blanks in key */ + lead_blanks = 0; + for (i=0; i=0; i--) if (key[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_Info_get: key is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + new_keylen = i + 1 - lead_blanks; + key += lead_blanks; + + newkey = (char *) ADIOI_Malloc((new_keylen+1)*sizeof(char)); + ADIOI_Strncpy(newkey, key, new_keylen); + newkey[new_keylen] = '\0'; + + if (value <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_get: value is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + if (*valuelen <= 0) { + FPRINTF(stderr, "MPI_Info_get: Invalid valuelen argument\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + if (*valuelen > valspace) { + FPRINTF(stderr, "MPI_Info_get: valuelen is greater than the amount of memory available in value\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + tmpvalue = (char *) ADIOI_Malloc((*valuelen + 1)*sizeof(char)); + + info_c = MPI_Info_f2c(*info); + *ierr = MPI_Info_get(info_c, newkey, *valuelen, tmpvalue, flag); + + if (*flag) { + tmpvaluelen = strlen(tmpvalue); + ADIOI_Strncpy(value, tmpvalue, tmpvaluelen); + /* blank pad the remaining space */ + for (i=tmpvaluelen; iPMPI */ +#include "mpioprof.h" +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_info_get_nkeys_ MPI_INFO_GET_NKEYS +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_get_nkeys_ mpi_info_get_nkeys__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_get_nkeys mpi_info_get_nkeys_ +#endif +#define mpi_info_get_nkeys_ mpi_info_get_nkeys +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_get_nkeys_ mpi_info_get_nkeys +#endif +#endif +#endif + +void mpi_info_get_nkeys_(MPI_Fint *info, int *nkeys, int *ierr ) +{ + MPI_Info info_c; + + info_c = MPI_Info_f2c(*info); + *ierr = MPI_Info_get_nkeys(info_c, nkeys); +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_getnthf.c b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_getnthf.c new file mode 100644 index 0000000000..5434fe3dd3 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_getnthf.c @@ -0,0 +1,120 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpio.h" +#include "adio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) +#ifdef FORTRANCAPS +#define mpi_info_get_nthkey_ PMPI_INFO_GET_NTHKEY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_get_nthkey_ pmpi_info_get_nthkey__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_get_nthkey pmpi_info_get_nthkey_ +#endif +#define mpi_info_get_nthkey_ pmpi_info_get_nthkey +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_get_nthkey_ pmpi_info_get_nthkey +#endif +#define mpi_info_get_nthkey_ pmpi_info_get_nthkey_ +#endif + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +#pragma weak MPI_INFO_GET_NTHKEY = PMPI_INFO_GET_NTHKEY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma weak mpi_info_get_nthkey__ = pmpi_info_get_nthkey__ +#elif !defined(FORTRANUNDERSCORE) +#pragma weak mpi_info_get_nthkey = pmpi_info_get_nthkey +#else +#pragma weak mpi_info_get_nthkey_ = pmpi_info_get_nthkey_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_INFO_GET_NTHKEY MPI_INFO_GET_NTHKEY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_get_nthkey__ mpi_info_get_nthkey__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_get_nthkey mpi_info_get_nthkey +#else +#pragma _HP_SECONDARY_DEF pmpi_info_get_nthkey_ mpi_info_get_nthkey_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_INFO_GET_NTHKEY as PMPI_INFO_GET_NTHKEY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_info_get_nthkey__ as pmpi_info_get_nthkey__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_info_get_nthkey as pmpi_info_get_nthkey +#else +#pragma _CRI duplicate mpi_info_get_nthkey_ as pmpi_info_get_nthkey_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_info_get_nthkey_ MPI_INFO_GET_NTHKEY +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_get_nthkey_ mpi_info_get_nthkey__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_get_nthkey mpi_info_get_nthkey_ +#endif +#define mpi_info_get_nthkey_ mpi_info_get_nthkey +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_get_nthkey_ mpi_info_get_nthkey +#endif +#endif +#endif + +void mpi_info_get_nthkey_(MPI_Fint *info, int *n, char *key, int *ierr, + int keylen) +{ + MPI_Info info_c; + int i, tmpkeylen; + char *tmpkey; + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_get_nthkey: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + tmpkey = (char *) ADIOI_Malloc((MPI_MAX_INFO_KEY+1) * sizeof(char)); + info_c = MPI_Info_f2c(*info); + *ierr = MPI_Info_get_nthkey(info_c, *n, tmpkey); + + tmpkeylen = strlen(tmpkey); + + if (tmpkeylen <= keylen) { + ADIOI_Strncpy(key, tmpkey, tmpkeylen); + + /* blank pad the remaining space */ + for (i=tmpkeylen; iPMPI */ +#include "mpioprof.h" +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_info_get_valuelen_ MPI_INFO_GET_VALUELEN +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_get_valuelen_ mpi_info_get_valuelen__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_get_valuelen mpi_info_get_valuelen_ +#endif +#define mpi_info_get_valuelen_ mpi_info_get_valuelen +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_get_valuelen_ mpi_info_get_valuelen +#endif +#endif +#endif + +void mpi_info_get_valuelen_(MPI_Fint *info, char *key, int *valuelen, + int *flag, int *ierr, int keylen ) +{ + MPI_Info info_c; + char *newkey; + int new_keylen, lead_blanks, i; + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_get_valuelen: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + /* strip leading and trailing blanks in key */ + lead_blanks = 0; + for (i=0; i=0; i--) if (key[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_Info_get_valuelen: key is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + new_keylen = i + 1 - lead_blanks; + key += lead_blanks; + + newkey = (char *) ADIOI_Malloc((new_keylen+1)*sizeof(char)); + ADIOI_Strncpy(newkey, key, new_keylen); + newkey[new_keylen] = '\0'; + + info_c = MPI_Info_f2c(*info); + *ierr = MPI_Info_get_valuelen(info_c, newkey, valuelen, flag); + ADIOI_Free(newkey); +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_setf.c b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_setf.c new file mode 100644 index 0000000000..6b6458d261 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/fortran/info_setf.c @@ -0,0 +1,146 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpio.h" +#include "adio.h" + + +#if defined(MPIO_BUILD_PROFILING) || defined(HAVE_WEAK_SYMBOLS) +#ifdef FORTRANCAPS +#define mpi_info_set_ PMPI_INFO_SET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_set_ pmpi_info_set__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_set pmpi_info_set_ +#endif +#define mpi_info_set_ pmpi_info_set +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF pmpi_info_set_ pmpi_info_set +#endif +#define mpi_info_set_ pmpi_info_set_ +#endif + +#if defined(HAVE_WEAK_SYMBOLS) +#if defined(HAVE_PRAGMA_WEAK) +#if defined(FORTRANCAPS) +#pragma weak MPI_INFO_SET = PMPI_INFO_SET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma weak mpi_info_set__ = pmpi_info_set__ +#elif !defined(FORTRANUNDERSCORE) +#pragma weak mpi_info_set = pmpi_info_set +#else +#pragma weak mpi_info_set_ = pmpi_info_set_ +#endif + +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#if defined(FORTRANCAPS) +#pragma _HP_SECONDARY_DEF PMPI_INFO_SET MPI_INFO_SET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_set__ mpi_info_set__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _HP_SECONDARY_DEF pmpi_info_set mpi_info_set +#else +#pragma _HP_SECONDARY_DEF pmpi_info_set_ mpi_info_set_ +#endif + +#elif defined(HAVE_PRAGMA_CRI_DUP) +#if defined(FORTRANCAPS) +#pragma _CRI duplicate MPI_INFO_SET as PMPI_INFO_SET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#pragma _CRI duplicate mpi_info_set__ as pmpi_info_set__ +#elif !defined(FORTRANUNDERSCORE) +#pragma _CRI duplicate mpi_info_set as pmpi_info_set +#else +#pragma _CRI duplicate mpi_info_set_ as pmpi_info_set_ +#endif + +/* end of weak pragmas */ +#endif +/* Include mapping from MPI->PMPI */ +#include "mpioprof.h" +#endif + +#else + +#ifdef FORTRANCAPS +#define mpi_info_set_ MPI_INFO_SET +#elif defined(FORTRANDOUBLEUNDERSCORE) +#define mpi_info_set_ mpi_info_set__ +#elif !defined(FORTRANUNDERSCORE) +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_set mpi_info_set_ +#endif +#define mpi_info_set_ mpi_info_set +#else +#if defined(HPUX) || defined(SPPUX) +#pragma _HP_SECONDARY_DEF mpi_info_set_ mpi_info_set +#endif +#endif +#endif + + +void mpi_info_set_(MPI_Fint *info, char *key, char *value, int *ierr, + int keylen, int vallen) +{ + MPI_Info info_c; + char *newkey, *newvalue; + int new_keylen, new_vallen, lead_blanks, i; + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_set: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + if (value <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_set: value is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + /* strip leading and trailing blanks in key */ + lead_blanks = 0; + for (i=0; i=0; i--) if (key[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_Info_set: key is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + new_keylen = i + 1 - lead_blanks; + key += lead_blanks; + + newkey = (char *) ADIOI_Malloc((new_keylen+1)*sizeof(char)); + ADIOI_Strncpy(newkey, key, new_keylen); + newkey[new_keylen] = '\0'; + + + /* strip leading and trailing blanks in value */ + lead_blanks = 0; + for (i=0; i=0; i--) if (value[i] != ' ') break; + if (i < 0) { + FPRINTF(stderr, "MPI_Info_set: value is a blank string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + new_vallen = i + 1 - lead_blanks; + value += lead_blanks; + + newvalue = (char *) ADIOI_Malloc((new_vallen+1)*sizeof(char)); + ADIOI_Strncpy(newvalue, value, new_vallen); + newvalue[new_vallen] = '\0'; + + + info_c = MPI_Info_f2c(*info); + *ierr = MPI_Info_set(info_c, newkey, newvalue); + ADIOI_Free(newkey); + ADIOI_Free(newvalue); +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_c2f.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_c2f.c new file mode 100644 index 0000000000..4486887b54 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_c2f.c @@ -0,0 +1,64 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_c2f = PMPI_Info_c2f +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_c2f MPI_Info_c2f +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_c2f as PMPI_Info_c2f +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif +#include "adio_extern.h" + +/*@ + MPI_Info_c2f - Translates a C info handle to a Fortran info handle + +Input Parameters: +. info - C info handle (integer) + +Return Value: + Fortran info handle (handle) +@*/ +MPI_Fint MPI_Info_c2f(MPI_Info info) +{ +#ifndef INT_LT_POINTER + return (MPI_Fint) info; +#else + int i; + + if ((info <= (MPI_Info) 0) || (info->cookie != MPIR_INFO_COOKIE)) + return (MPI_Fint) 0; + if (!MPIR_Infotable) { + MPIR_Infotable_max = 1024; + MPIR_Infotable = (MPI_Info *) + ADIOI_Malloc(MPIR_Infotable_max*sizeof(MPI_Info)); + MPIR_Infotable_ptr = 0; /* 0 can't be used though, because + MPI_INFO_NULL=0 */ + for (i=0; iPMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Info_create - Creates a new info object + +Output Parameters: +. info - info object (handle) + +.N fortran +@*/ +int MPI_Info_create(MPI_Info *info) +{ + int error_code; + + MPIR_MPIOInit(&error_code); + if (error_code != MPI_SUCCESS) goto fn_exit; + + *info = (MPI_Info) ADIOI_Malloc(sizeof(struct MPIR_Info)); + (*info)->cookie = MPIR_INFO_COOKIE; + (*info)->key = 0; + (*info)->value = 0; + (*info)->next = 0; + /* this is the first structure in this linked list. it is + always kept empty. new (key,value) pairs are added after it. */ + +fn_exit: + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_delete.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_delete.c new file mode 100644 index 0000000000..06ec27ee8d --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_delete.c @@ -0,0 +1,83 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_delete = PMPI_Info_delete +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_delete MPI_Info_delete +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_delete as PMPI_Info_delete +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Info_delete - Deletes a (key,value) pair from info + +Input Parameters: +. info - info object (handle) +. key - key (string) + +.N fortran +@*/ +int MPI_Info_delete(MPI_Info info, char *key) +{ + MPI_Info prev, curr; + int done; + + if ((info <= (MPI_Info) 0) || (info->cookie != MPIR_INFO_COOKIE)) { + FPRINTF(stderr, "MPI_Info_delete: Invalid info object\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_delete: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (strlen(key) > MPI_MAX_INFO_KEY) { + FPRINTF(stderr, "MPI_Info_delete: key is longer than MPI_MAX_INFO_KEY\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (!strlen(key)) { + FPRINTF(stderr, "MPI_Info_delete: key is a null string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + prev = info; + curr = info->next; + done = 0; + + while (curr) { + if (!strcmp(curr->key, key)) { + ADIOI_Free(curr->key); + ADIOI_Free(curr->value); + prev->next = curr->next; + ADIOI_Free(curr); + done = 1; + break; + } + prev = curr; + curr = curr->next; + } + + if (!done) { + FPRINTF(stderr, "MPI_Info_delete: key not defined in info\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_dup.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_dup.c new file mode 100644 index 0000000000..a1c1a9969f --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_dup.c @@ -0,0 +1,66 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_dup = PMPI_Info_dup +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_dup MPI_Info_dup +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_dup as PMPI_Info_dup +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Info_dup - Returns a duplicate of the info object + +Input Parameters: +. info - info object (handle) + +Output Parameters: +. newinfo - duplicate of info object (handle) + +.N fortran +@*/ +int MPI_Info_dup(MPI_Info info, MPI_Info *newinfo) +{ + MPI_Info curr_old, curr_new; + + if ((info <= (MPI_Info) 0) || (info->cookie != MPIR_INFO_COOKIE)) { + FPRINTF(stderr, "MPI_Info_dup: Invalid info object\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + *newinfo = (MPI_Info) ADIOI_Malloc(sizeof(struct MPIR_Info)); + curr_new = *newinfo; + curr_new->cookie = MPIR_INFO_COOKIE; + curr_new->key = 0; + curr_new->value = 0; + curr_new->next = 0; + + curr_old = info->next; + while (curr_old) { + curr_new->next = (MPI_Info) ADIOI_Malloc(sizeof(struct MPIR_Info)); + curr_new = curr_new->next; + curr_new->cookie = 0; /* cookie not set on purpose */ + curr_new->key = ADIOI_Strdup(curr_old->key); + curr_new->value = ADIOI_Strdup(curr_old->value); + curr_new->next = 0; + + curr_old = curr_old->next; + } + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_f2c.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_f2c.c new file mode 100644 index 0000000000..49d8ae5eec --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_f2c.c @@ -0,0 +1,49 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_f2c = PMPI_Info_f2c +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_f2c MPI_Info_f2c +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_f2c as PMPI_Info_f2c +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif +#include "adio_extern.h" + +/*@ + MPI_Info_f2c - Translates a Fortran info handle to a C info handle + +Input Parameters: +. info - Fortran info handle (integer) + +Return Value: + C info handle (handle) +@*/ +MPI_Info MPI_Info_f2c(MPI_Fint info) +{ + +#ifndef INT_LT_POINTER + return (MPI_Info) info; +#else + if (!info) return MPI_INFO_NULL; + if ((info < 0) || (info > MPIR_Infotable_ptr)) { + FPRINTF(stderr, "MPI_Info_f2c: Invalid info handle\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + return MPIR_Infotable[info]; +#endif +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_free.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_free.c new file mode 100644 index 0000000000..e682ce0cd5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_free.c @@ -0,0 +1,56 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_free = PMPI_Info_free +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_free MPI_Info_free +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_free as PMPI_Info_free +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Info_free - Frees an info object + +Input Parameters: +. info - info object (handle) + +.N fortran +@*/ +int MPI_Info_free(MPI_Info *info) +{ + MPI_Info curr, next; + + if ((*info <= (MPI_Info) 0) || ((*info)->cookie != MPIR_INFO_COOKIE)) { + FPRINTF(stderr, "MPI_Info_free: Invalid info object\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + curr = (*info)->next; + ADIOI_Free(*info); + *info = MPI_INFO_NULL; + + while (curr) { + next = curr->next; + ADIOI_Free(curr->key); + ADIOI_Free(curr->value); + ADIOI_Free(curr); + curr = next; + } + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_get.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_get.c new file mode 100644 index 0000000000..ca4274672b --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_get.c @@ -0,0 +1,88 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_get = PMPI_Info_get +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_get MPI_Info_get +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_get as PMPI_Info_get +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Info_get - Retrieves the value associated with a key + +Input Parameters: +. info - info object (handle) +. key - key (string) +. valuelen - length of value argument (integer) + +Output Parameters: +. value - value (string) +. flag - true if key defined, false if not (boolean) + +.N fortran +@*/ +int MPI_Info_get(MPI_Info info, char *key, int valuelen, char *value, int *flag) +{ + MPI_Info curr; + + if ((info <= (MPI_Info) 0) || (info->cookie != MPIR_INFO_COOKIE)) { + FPRINTF(stderr, "MPI_Info_get: Invalid info object\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_get: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (strlen(key) > MPI_MAX_INFO_KEY) { + FPRINTF(stderr, "MPI_Info_get: key is longer than MPI_MAX_INFO_KEY\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (!strlen(key)) { + FPRINTF(stderr, "MPI_Info_get: key is a null string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (valuelen <= 0) { + FPRINTF(stderr, "MPI_Info_get: Invalid valuelen argument\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (value <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_get: value is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + curr = info->next; + *flag = 0; + + while (curr) { + if (!strcmp(curr->key, key)) { + ADIOI_Strncpy(value, curr->value, valuelen); + value[valuelen] = '\0'; + *flag = 1; + break; + } + curr = curr->next; + } + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_getnks.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_getnks.c new file mode 100644 index 0000000000..fd20826950 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_getnks.c @@ -0,0 +1,55 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_get_nkeys = PMPI_Info_get_nkeys +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_get_nkeys MPI_Info_get_nkeys +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_get_nkeys as PMPI_Info_get_nkeys +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Info_get_nkeys - Returns the number of currently defined keys in info + +Input Parameters: +. info - info object (handle) + +Output Parameters: +. nkeys - number of defined keys (integer) + +.N fortran +@*/ +int MPI_Info_get_nkeys(MPI_Info info, int *nkeys) +{ + MPI_Info curr; + + if ((info <= (MPI_Info) 0) || (info->cookie != MPIR_INFO_COOKIE)) { + FPRINTF(stderr, "MPI_Info_get_nkeys: Invalid info object\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + curr = info->next; + *nkeys = 0; + + while (curr) { + curr = curr->next; + (*nkeys)++; + } + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_getnth.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_getnth.c new file mode 100644 index 0000000000..fa325c41cc --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_getnth.c @@ -0,0 +1,74 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_get_nthkey = PMPI_Info_get_nthkey +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_get_nthkey MPI_Info_get_nthkey +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_get_nthkey as PMPI_Info_get_nthkey +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Info_get_nthkey - Returns the nth defined key in info + +Input Parameters: +. info - info object (handle) +. n - key number (integer) + +Output Parameters: +. keys - key (string) + +.N fortran +@*/ +int MPI_Info_get_nthkey(MPI_Info info, int n, char *key) +{ + MPI_Info curr; + int nkeys, i; + + if ((info <= (MPI_Info) 0) || (info->cookie != MPIR_INFO_COOKIE)) { + FPRINTF(stderr, "MPI_Info_get_nthkey: Invalid info object\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_get: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + curr = info->next; + nkeys = 0; + while (curr) { + curr = curr->next; + nkeys++; + } + + if ((n < 0) || (n >= nkeys)) { + FPRINTF(stderr, "MPI_Info_get_nthkey: n is an invalid number\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + curr = info->next; + i = 0; + while (i < n) { + curr = curr->next; + i++; + } + ADIOI_Strncpy(key, curr->key, MPI_MAX_INFO_KEY); + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_getvln.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_getvln.c new file mode 100644 index 0000000000..b484929b72 --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_getvln.c @@ -0,0 +1,76 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_get_valuelen = PMPI_Info_get_valuelen +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_get_valuelen MPI_Info_get_valuelen +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_get_valuelen as PMPI_Info_get_valuelen +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Info_get_valuelen - Retrieves the length of the value associated with a key + +Input Parameters: +. info - info object (handle) +. key - key (string) + +Output Parameters: +. valuelen - length of value argument (integer) +. flag - true if key defined, false if not (boolean) + +.N fortran +@*/ +int MPI_Info_get_valuelen(MPI_Info info, char *key, int *valuelen, int *flag) +{ + MPI_Info curr; + + if ((info <= (MPI_Info) 0) || (info->cookie != MPIR_INFO_COOKIE)) { + FPRINTF(stderr, "MPI_Info_get_valuelen: Invalid info object\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_get_valuelen: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (strlen(key) > MPI_MAX_INFO_KEY) { + FPRINTF(stderr, "MPI_Info_get_valuelen: key is longer than MPI_MAX_INFO_KEY\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (!strlen(key)) { + FPRINTF(stderr, "MPI_Info_get_valuelen: key is a null string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + curr = info->next; + *flag = 0; + + while (curr) { + if (!strcmp(curr->key, key)) { + *valuelen = strlen(curr->value); + *flag = 1; + break; + } + curr = curr->next; + } + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/mpi2-other/info/info_set.c b/ompi/mca/io/romio314/romio/mpi2-other/info/info_set.c new file mode 100644 index 0000000000..e60d89d79e --- /dev/null +++ b/ompi/mca/io/romio314/romio/mpi2-other/info/info_set.c @@ -0,0 +1,98 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * Copyright (C) 1997 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "mpioimpl.h" + +#ifdef HAVE_WEAK_SYMBOLS + +#if defined(HAVE_PRAGMA_WEAK) +#pragma weak MPI_Info_set = PMPI_Info_set +#elif defined(HAVE_PRAGMA_HP_SEC_DEF) +#pragma _HP_SECONDARY_DEF PMPI_Info_set MPI_Info_set +#elif defined(HAVE_PRAGMA_CRI_DUP) +#pragma _CRI duplicate MPI_Info_set as PMPI_Info_set +/* end of weak pragmas */ +#endif + +/* Include mapping from MPI->PMPI */ +#define MPIO_BUILD_PROFILING +#include "mpioprof.h" +#endif + +/*@ + MPI_Info_set - Adds a (key,value) pair to info + +Input Parameters: +. info - info object (handle) +. key - key (string) +. value - value (string) + +.N fortran +@*/ +int MPI_Info_set(MPI_Info info, char *key, char *value) +{ + MPI_Info prev, curr; + + if ((info <= (MPI_Info) 0) || (info->cookie != MPIR_INFO_COOKIE)) { + FPRINTF(stderr, "MPI_Info_set: Invalid info object\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (key <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_set: key is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (value <= (char *) 0) { + FPRINTF(stderr, "MPI_Info_set: value is an invalid address\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (strlen(key) > MPI_MAX_INFO_KEY) { + FPRINTF(stderr, "MPI_Info_set: key is longer than MPI_MAX_INFO_KEY\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (strlen(value) > MPI_MAX_INFO_VAL) { + FPRINTF(stderr, "MPI_Info_set: value is longer than MPI_MAX_INFO_VAL\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (!strlen(key)) { + FPRINTF(stderr, "MPI_Info_set: key is a null string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + if (!strlen(value)) { + FPRINTF(stderr, "MPI_Info_set: value is a null string\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + prev = info; + curr = info->next; + + while (curr) { + if (!strcmp(curr->key, key)) { + ADIOI_Free(curr->value); + curr->value = ADIOI_Strdup(value); + break; + } + prev = curr; + curr = curr->next; + } + + if (!curr) { + prev->next = (MPI_Info) ADIOI_Malloc(sizeof(struct MPIR_Info)); + curr = prev->next; + curr->cookie = 0; /* cookie not set on purpose */ + curr->key = ADIOI_Strdup(key); + curr->value = ADIOI_Strdup(value); + curr->next = 0; + } + + return MPI_SUCCESS; +} diff --git a/ompi/mca/io/romio314/romio/test-internal/Makefile.am b/ompi/mca/io/romio314/romio/test-internal/Makefile.am new file mode 100644 index 0000000000..ec7c7eb0ef --- /dev/null +++ b/ompi/mca/io/romio314/romio/test-internal/Makefile.am @@ -0,0 +1,26 @@ +# -*- Mode: Makefile; -*- +# +# (C) 2011 by Argonne National Laboratory. +# See COPYRIGHT in top-level directory. +# + +# This directory is only listed in DIST_SUBDIRS, not SUBDIRS, so its contents +# will not be built by default, but it will participate in "make distclean" and +# friends. + +# override the normal compilers for the tests +CC = $(TEST_CC) + +# because := is not universally avalible, we have to play games to use the +# user-specified LDFLAGS and OUR_LIBS env. variables (if set) +OUR_LIBS = $(TEST_LIBNAME) $(MPI_LIB) $(ROMIO_LIBLIST) + +LDADD = $(OUR_LIBS) + +AM_CPPFLAGS = $(ROMIO_INCLUDE) +AM_CFLAGS = $(USER_CFLAGS) + +CTESTS = file_realms_test io_bounds_test heap_test + +noinst_PROGRAMS = $(CTESTS) + diff --git a/ompi/mca/io/romio314/romio/test-internal/file_realms_test.c b/ompi/mca/io/romio314/romio/test-internal/file_realms_test.c new file mode 100644 index 0000000000..b848259e0e --- /dev/null +++ b/ompi/mca/io/romio314/romio/test-internal/file_realms_test.c @@ -0,0 +1,76 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "../adio/include/adio.h" +#include "../adio/include/adio_extern.h" +#include "mpi.h" + +int main (int argc, char **argv) +{ + int i; + ADIO_File fd; + ADIO_Offset min_st_offset, max_end_offset; + int rank; + int nprocs_for_coll; + int lb; + MPI_Count size, extent; + + MPI_Init (&argc, &argv); + MPI_Comm_rank (MPI_COMM_WORLD, &rank); + + if (argc != 4) { + if (!rank) + printf ("Usage: file_realms_test \n" + " simulates file_realm calculation\n"); + MPI_Finalize(); + return 1; + } + + nprocs_for_coll = atoi (argv[1]); + + min_st_offset = atoi (argv[2]); + max_end_offset = atoi (argv[3]); + + if (max_end_offset < min_st_offset){ + if (!rank) + printf ("end offset %lld is less then start offset %lld\n", + max_end_offset, min_st_offset); + MPI_Finalize(); + return 1; + } + + printf ("min_st_offset = %lld\nmax_end_offset = %lld\n", + min_st_offset, max_end_offset); + + fd = (ADIO_File) ADIOI_Malloc (sizeof (struct ADIOI_FileD)); + fd->hints = (ADIOI_Hints *) + ADIOI_Malloc (sizeof(struct ADIOI_Hints_struct)); + fd->hints->cb_nodes = nprocs_for_coll; + ADIOI_Calc_file_realms (fd, min_st_offset, max_end_offset); + + for (i=0; i < nprocs_for_coll; i++) { + printf ("file_realm_st_offs[%d] = %lld\n", i, fd->file_realm_st_offs[i]); + } + for (i=0; i < nprocs_for_coll; i++) { + MPI_Type_size_x (fd->file_realm_types[i], &size); + printf ("file_realm [%d] size = %d\n", i, size); + } + for (i=0; i < nprocs_for_coll; i++) { + MPI_Type_get_extent (fd->file_realm_types[i], &lb, &extent); + printf ("file_realm [%d] extent = %d\n", i, extent); + } + + for (i=0; i < nprocs_for_coll; i++) + MPI_Type_free (&fd->file_realm_types[i]); + ADIOI_Free (fd->file_realm_st_offs); + ADIOI_Free (fd->file_realm_types); + ADIOI_Free (fd->hints); + ADIOI_Free (fd); + + MPI_Finalize(); + + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test-internal/heap_test.c b/ompi/mca/io/romio314/romio/test-internal/heap_test.c new file mode 100644 index 0000000000..2f0041df36 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test-internal/heap_test.c @@ -0,0 +1,459 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "../adio/include/heap-sort.h" +#include +#include +#include +#include + +#define PREDEF_TESTS 2 +/* test types */ +#define ALL 0 +#define RANDOM -1 +#define CUSTOM -2 + +/* ACTIONS */ +#define BUILD 0 +#define INSERT 1 +#define EXTRACT 2 +#define EXTRACT_INSERT 3 + +typedef struct { + char name[64]; + int heap_size; + int print; + int verify; + int action_arr_sz; + int *action_arr; + int *action_count_arr; + ADIO_Offset *offsets; + ADIO_Offset *correct_order; +} test_params_t; + +void print_usage(); +void print_keys(ADIO_Offset* offsets, int size); +void print_params(test_params_t *params); +int run_test(test_params_t *test); +void fill_random_test(test_params_t *params); +void init_predefined_test(test_params_t *params, int index); +void dumb_sort(test_params_t *params); + +int main(int argc, char **argv) { + int i, print = 1, verify = 1; + int adding_elements; + int curr_add_idx; + int test_type = RANDOM; + test_params_t predefined_tests[PREDEF_TESTS]; + test_params_t test; + + /* parse args */ + adding_elements = 0; + curr_add_idx = 0; + if (argc == 1) { + print_usage(); + return 1; + } + i = 1; + while (i < argc) { + if (!strcmp("-A", argv[i])) { + adding_elements = 0; + test_type = ALL; + i++; + } + else if (!strcmp("-T", argv[i])) { + adding_elements = 0; + test_type = atoi(argv[i+1]); + i += 2; + } + else if (!strcmp("-r", argv[i])) { + adding_elements = 0; + test.heap_size = atoi(argv[i+1]); + if (test.heap_size <= 0) { + printf("heap size should be a positive integer\n"); + return 1; + } + test.offsets = (ADIO_Offset *) malloc(test.heap_size*sizeof(ADIO_Offset)); + test_type = RANDOM; + i += 2; + } + else if (!strcmp("-e", argv[i])) { + test.heap_size = argc - 2; + if (test.heap_size <= 0) { + printf("need at least one key\n"); + return 1; + } + test.offsets = (ADIO_Offset *) malloc(test.heap_size*sizeof(ADIO_Offset)); + adding_elements = 1; + test_type = CUSTOM; + i++; + } + else if (!strcmp("-v", argv[i])) { + verify = 1; + i++; + } + else if (!strcmp("-p", argv[i])) { + print = 1; + i++; + } + else if (!strcmp("-V", argv[i])) { + verify = 0; + i++; + } + else if (!strcmp("-P", argv[i])) { + print = 0; + i++; + } + else if (adding_elements) { + test.offsets[curr_add_idx] = atoi(argv[i]); + curr_add_idx++; + i++; + } + else { + printf("Illegal argument: %s", argv[i]); + print_usage(); + return 1; + } + } + + if (test_type == RANDOM) { + fill_random_test(&test); + strcpy(test.name, "RANDOMIZED TEST"); + } + else if (test_type == CUSTOM) + strcpy(test.name, "CUSTOM TEST"); + if ((test_type == CUSTOM) || (test_type == RANDOM)) { + test.print = print; + test.verify = verify; + test.action_arr_sz = 2; + test.action_arr = (int *) malloc(test.action_arr_sz*sizeof(int)); + test.action_count_arr = (int *) malloc(test.action_arr_sz*sizeof(int)); + /* build the entire heap */ + /* test.action_arr[0] = BUILD; + test.action_count_arr[0] = 1; */ + /* insert keys one at a time */ + test.action_arr[0] = INSERT; + test.action_count_arr[0] = test.heap_size; + /* extract all the keys */ + test.action_arr[1] = EXTRACT; + test.action_count_arr[1] = test.heap_size; + + if (verify) { + test.correct_order = (ADIO_Offset *)malloc(test.heap_size*sizeof(ADIO_Offset)); + dumb_sort(&test); + } + if (print) + print_params(&test); + run_test(&test); + } + else { + if (test_type == ALL) { + for (i=0; i\n" + " -r Create a random test and verify of size \n" + " -e test with the space delimited list of keys\n" + " -p print parameters and keys (default)\n" + " -P do not print parameters and keys\n" + " -v verify keys (default)\n" + " -V do not verify keys\n" + ); +} + +void print_keys(ADIO_Offset *offsets, int size) { + int i; + for (i=0; i < size; i++) + printf("%lld ", offsets[i]); +} + +void print_params(test_params_t *params) { + int i; + static char action_map[3][8] = {"BUILD", "INSERT", "EXTRACT"}; + + printf("----------------Test Parameters---------------\n"); + printf("Actions:\n"); + for (i=0; iaction_arr_sz; i++) { + printf("%sx%d\n", action_map[params->action_arr[i]], + params->action_count_arr[i]); + } + + printf("Initial order :\n"); + print_keys(params->offsets, params->heap_size); + printf("\n"); + + if (params->verify) { + printf("Expected order:\n"); + print_keys(params->correct_order, params->heap_size); + printf("\n"); + } + printf("----------------------------------------------\n"); +} + +void fill_random_test(test_params_t *params) { + int i; + int max_key; + time_t seed; + int order = 0; + + time(&seed); + srand(seed); + + order = 0; + max_key = 1; + while (order < 25) { + max_key *= 10; + if (!((int) (params->heap_size / max_key))) + break; + order++; + } + for (i=0; i < params->heap_size; i++) + params->offsets[i] = (rand() % max_key); +} + +void dumb_sort(test_params_t *params) { + ADIO_Offset *offsets, tmp_offset; + int i, j; + + offsets = params->correct_order; + memcpy(offsets, params->offsets, params->heap_size*sizeof(ADIO_Offset)); + for (i=0; i < params->heap_size; i++) { + for (j=i; j < params->heap_size; j++) { + if (offsets[j] < offsets[i]) { + tmp_offset = offsets[i]; + offsets[i] = offsets[j]; + offsets[j] = tmp_offset; + } + } + } +} + +int run_test(test_params_t *test) { + heap_t myheap; + ADIO_Offset *extracted; + int stored_proc; + ADIO_Offset stored_reg_max_len; + int i, j, k, err_flag = 0; + int curr_insert_idx = 0; + int curr_extract_idx = 0; + + create_heap(&myheap, test->heap_size); + myheap.size = 0; + + extracted = (ADIO_Offset *) malloc(test->heap_size * sizeof(ADIO_Offset)); + for (i=0; i < test->action_arr_sz; i++) { + for (j=0; jaction_count_arr[i]; j++) { + switch (test->action_arr[i]) + { + case BUILD: + myheap.size = test->heap_size; + for (k=0; k < test->heap_size; k++) { + myheap.nodes[k].offset = test->offsets[k]; + myheap.nodes[k].proc = k; + } + build_heap(&myheap); + break; + case INSERT: + ADIOI_Heap_insert(&myheap, test->offsets[curr_insert_idx], + curr_insert_idx, curr_insert_idx); + curr_insert_idx++; + break; + case EXTRACT: + heap_extract_min(&myheap, &extracted[curr_extract_idx], + &stored_proc, &stored_reg_max_len); + if (test->verify && (extracted[curr_extract_idx] != + test->correct_order[curr_extract_idx])) + err_flag++; + curr_extract_idx++; + break; + case EXTRACT_INSERT: + heap_extract_min(&myheap, &extracted[curr_extract_idx], + &stored_proc, &stored_reg_max_len); + if (test->verify &&(extracted[curr_extract_idx] != + test->correct_order[curr_extract_idx])) + err_flag++; + curr_extract_idx++; + + ADIOI_Heap_insert(&myheap, test->offsets[curr_insert_idx], + curr_insert_idx, curr_insert_idx); + curr_insert_idx++; + break; + default: + break; + } + } + } + + if (test->verify) { + if (err_flag) { + printf("***%s FAILED***\n", test->name); + if (test->print) { + printf("Min extraction:\n"); + print_keys(extracted, test->heap_size); + printf("\n"); + } + } + else + printf("***%s PASSED***\n", test->name); + } + + free_heap(&myheap); + free(extracted); + /* clean up test params */ + free(test->offsets); + if (test->verify) + free(test->correct_order); + free(test->action_arr); + free(test->action_count_arr); + + return err_flag; +} + +void init_predefined_test(test_params_t *params, int index) { + + switch (index) + { + case 0: + strcpy(params->name, "TEST 1"); + params->heap_size = 15; + params->action_arr_sz = 3; + + /* allocate space */ + params->action_arr = + (int *) malloc (params->action_arr_sz*sizeof(int)); + params->action_count_arr = + (int *) malloc (params->action_arr_sz*sizeof(int)); + params->offsets = (ADIO_Offset *) malloc(params->heap_size*sizeof(ADIO_Offset)); + if (params->verify) + params->correct_order = + (ADIO_Offset *) malloc(params->heap_size*sizeof(ADIO_Offset)); + + /* Set procs */ + params->offsets[0] = 65; + params->offsets[1] = 53; + params->offsets[2] = 51; + params->offsets[3] = 74; + params->offsets[4] = 1; + params->offsets[5] = 3; + params->offsets[6] = 86; + params->offsets[7] = 82; + params->offsets[8] = 42; + params->offsets[9] = 62; + params->offsets[10] = 33; + params->offsets[11] = 12; + params->offsets[12] = 79; + params->offsets[13] = 13; + params->offsets[14] = 28; + + if (params->verify) { + params->correct_order[0] = 1; + params->correct_order[1] = 3; + params->correct_order[2] = 12; + params->correct_order[3] = 33; + params->correct_order[4] = 13; + params->correct_order[5] = 28; + params->correct_order[6] = 42; + params->correct_order[7] = 51; + params->correct_order[8] = 53; + params->correct_order[9] = 62; + params->correct_order[10] = 65; + params->correct_order[11] = 74; + params->correct_order[12] = 79; + params->correct_order[13] = 82; + params->correct_order[14] = 86; + } + + params->action_arr[0] = INSERT; + params->action_arr[1] = EXTRACT_INSERT; + params->action_arr[11] = EXTRACT; + + params->action_count_arr[0] = 10; + params->action_count_arr[1] = 5; + params->action_count_arr[11] = 10; + break; + case 1: + strcpy(params->name, "TEST 1"); + params->heap_size = 15; + params->action_arr_sz = 3; + + /* allocate space */ + params->action_arr = + (int *) malloc (params->action_arr_sz*sizeof(int)); + params->action_count_arr = + (int *) malloc (params->action_arr_sz*sizeof(int)); + params->offsets = (ADIO_Offset *) malloc(params->heap_size*sizeof(ADIO_Offset)); + if (params->verify) + params->correct_order = + (ADIO_Offset *) malloc(params->heap_size*sizeof(ADIO_Offset)); + + /* Set values */ + params->offsets[0] = 65; + params->offsets[1] = 53; + params->offsets[2] = 51; + params->offsets[3] = 74; + params->offsets[4] = 1; + params->offsets[5] = 3; + params->offsets[6] = 86; + params->offsets[7] = 82; + params->offsets[8] = 42; + params->offsets[9] = 62; + params->offsets[10] = 33; + params->offsets[11] = 12; + params->offsets[12] = 79; + params->offsets[13] = 13; + params->offsets[14] = 28; + + if (params->verify) { + params->correct_order[0] = 1; + params->correct_order[1] = 3; + params->correct_order[2] = 12; + params->correct_order[3] = 33; + params->correct_order[4] = 13; + params->correct_order[5] = 28; + params->correct_order[6] = 42; + params->correct_order[7] = 51; + params->correct_order[8] = 53; + params->correct_order[9] = 62; + params->correct_order[10] = 65; + params->correct_order[11] = 74; + params->correct_order[12] = 79; + params->correct_order[13] = 82; + params->correct_order[14] = 86; + } + + params->action_arr[0] = INSERT; + params->action_arr[1] = EXTRACT_INSERT; + params->action_arr[11] = EXTRACT; + + params->action_count_arr[0] = 10; + params->action_count_arr[1] = 5; + params->action_count_arr[11] = 10; + break; + default: + break; + } +} diff --git a/ompi/mca/io/romio314/romio/test-internal/io_bounds_test.c b/ompi/mca/io/romio314/romio/test-internal/io_bounds_test.c new file mode 100644 index 0000000000..f7514764e4 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test-internal/io_bounds_test.c @@ -0,0 +1,302 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * Copyright (C) 2008 University of Chicago. + * See COPYRIGHT notice in top-level directory. + */ + +#include "../adio/include/adio.h" +#include "../adio/include/adioi.h" +#include "../adio/include/adio_extern.h" +#include "mpi.h" + +#define PREDEF_TESTS 5 +#define MAX_OFF_LENS 4 + +typedef struct { + ADIO_Offset offset; + int count; + int type_blocklens[MAX_OFF_LENS]; + int type_indices[MAX_OFF_LENS]; + MPI_Datatype type_oldtypes[MAX_OFF_LENS]; + int type_count; + + ADIO_Offset correct_st_offset; + ADIO_Offset correct_end_offset; +} test_param_t; + +int run_test (test_param_t *test); +int setup_predefined (test_param_t *tests_arr, int count); +int print_usage (void); +int print_test_params (test_param_t *test); + +int main (int argc, char **argv) { + int rank; + int run_test_number = 0; + int failed; + int while_condition; + int i; + + test_param_t predefined_tests[PREDEF_TESTS]; + + MPI_Init (&argc, &argv); + MPI_Comm_rank (MPI_COMM_WORLD, &rank); + + if (argc != 1) { + if (!rank) { + printf ("Use only one process\n"); + print_usage (); + } + MPI_Finalize(); + return 1; + } + i = 1; + while (i < argc) { + if (!strcmp (argv[i], "-A")) { + run_test_number = 0; + i++; + } + else if (!strcmp (argv[i], "-T")) { + run_test_number = atoi (argv[i+1]); + if ((run_test_number > PREDEF_TESTS) || (run_test_number < 1)) { + if (!rank) + printf ("Invalid test number, only %d tests\n", + PREDEF_TESTS); + MPI_Finalize (); + return 1; + } + i += 2; + } + else { + if (!rank) { + printf ("Invalid Argument: %s\n", argv[i]); + print_usage (); + } + i++; + } + } + + setup_predefined (predefined_tests, PREDEF_TESTS); + + if (!run_test_number) { + i = 0; + while_condition = PREDEF_TESTS; + } + else { + i = run_test_number - 1; + while_condition = run_test_number; + } + while (i < while_condition) { + printf ("***** Test %d *****\n", i+1); + failed = run_test (&predefined_tests[i]); + printf ("******************\n"); + i++; + } + + MPI_Finalize (); + + return 0; +} + +int run_test (test_param_t *test) { + ADIO_Offset st_offset, end_offset; + MPI_File fh; + int is_contig; + int ind_err = 0, exp_err = 0; + + MPI_Datatype filetype; + + MPI_Type_struct (test->type_count, test->type_blocklens, + test->type_indices, test->type_oldtypes, &filetype); + MPI_Type_commit (&filetype); + + MPI_File_open (MPI_COMM_WORLD, "test_file.txt" , MPI_MODE_RDWR, + MPI_INFO_NULL, &fh); + + MPI_File_set_view (fh, 0, MPI_BYTE, filetype, "native", MPI_INFO_NULL); + + MPI_File_seek (fh, test->offset, MPI_SEEK_SET); + ADIOI_Calc_bounds ((ADIO_File) fh, test->count, MPI_BYTE, ADIO_INDIVIDUAL, + test->offset, &st_offset, &end_offset); + + ind_err = 0; + if (st_offset != test->correct_st_offset) { + printf ("Individual st_offset = %lld end_offset = %lld\n", + st_offset, end_offset); + ind_err = 1; + } + if (end_offset != test->correct_end_offset) { + printf ("Individual st_offset = %lld end_offset = %lld\n", + st_offset, end_offset); + ind_err = 1; + } + MPI_File_close (&fh); + if (ind_err) + printf ("Individual Calc FAILED\n"); + + MPI_File_open (MPI_COMM_WORLD, "test_file.txt" , MPI_MODE_RDWR, + MPI_INFO_NULL, &fh); + + if (!is_contig) + MPI_File_set_view (fh, 0, MPI_BYTE, filetype, "native", MPI_INFO_NULL); + + MPI_File_seek (fh, 0, MPI_SEEK_SET); + ADIOI_Calc_bounds ((ADIO_File) fh, test->count, MPI_BYTE, + ADIO_EXPLICIT_OFFSET, test->offset, &st_offset, + &end_offset); + + exp_err = 0; + if (st_offset != test->correct_st_offset) { + printf ("Explicit st_offset = %lld end_offset = %lld\n", + st_offset, end_offset); + exp_err = 1; + } + if (end_offset != test->correct_end_offset) { + printf ("Explicit st_offset = %lld end_offset = %lld\n", + st_offset, end_offset); + exp_err = 1; + } + if (exp_err) + printf ("Explicit Calc FAILED\n"); + + MPI_File_close (&fh); + + if (!is_contig) + MPI_Type_free (&filetype); + + return (exp_err || ind_err); +} + +int print_usage () +{ + printf ( + "Usage:\n" + " io_bounds_test -A -T \n"); +} + +int print_test_params (test_param_t *test) +{ + int i; + printf ( + "I/O offset: %lld\n" + "bytes: %d\n" + "Filetype [n](disp, lens, type):\n", + test->offset, test->count); + + for (i=0; itype_count; i++) { + printf ( + " [%d](%lld, %d, ", + i, + test->type_blocklens[i], + test->type_indices[i]); + if (test->type_oldtypes[i] == MPI_BYTE) { + printf ( "%s)\n", "MPI_BYTE"); + } + else if (test->type_oldtypes[i] == MPI_UB) { + printf ( "%s)\n", "MPI_UB"); + } + else if (test->type_oldtypes[i] == MPI_LB) { + printf ( "%s)\n", "MPI_LB"); + } + } + printf ( + "Expected Start offset: %lld\n" + "Expected End offset: %lld\n", + test->correct_st_offset, + test->correct_end_offset); +} + +int setup_predefined (test_param_t *tests_arr, int count) +{ + int i; + for (i=0; i < PREDEF_TESTS; i++) { + switch (i) + { + case 0: + tests_arr[i].offset = 0; + tests_arr[i].count = 0; + tests_arr[i].type_count = 0; + tests_arr[i].type_indices[0] = 0; + tests_arr[i].type_blocklens[0] = 0; + tests_arr[i].type_oldtypes[0] = MPI_BYTE; + tests_arr[i].type_indices[1] = 0; + tests_arr[i].type_blocklens[1] = 0; + tests_arr[i].type_oldtypes[1] = MPI_BYTE; + tests_arr[i].type_indices[2] = 0; + tests_arr[i].type_blocklens[2] = 0; + tests_arr[i].type_oldtypes[2] = MPI_BYTE; + tests_arr[i].type_indices[3] = 0; + tests_arr[i].type_blocklens[3] = 0; + tests_arr[i].type_oldtypes[3] = MPI_BYTE; + break; + case 1: + tests_arr[i].offset = 0; + tests_arr[i].count = 0; + tests_arr[i].type_count = 0; + tests_arr[i].type_indices[0] = 0; + tests_arr[i].type_blocklens[0] = 0; + tests_arr[i].type_oldtypes[0] = MPI_BYTE; + tests_arr[i].type_indices[1] = 0; + tests_arr[i].type_blocklens[1] = 0; + tests_arr[i].type_oldtypes[1] = MPI_BYTE; + tests_arr[i].type_indices[2] = 0; + tests_arr[i].type_blocklens[2] = 0; + tests_arr[i].type_oldtypes[2] = MPI_BYTE; + tests_arr[i].type_indices[3] = 0; + tests_arr[i].type_blocklens[3] = 0; + tests_arr[i].type_oldtypes[3] = MPI_BYTE; + break; + case 2: + tests_arr[i].offset = 0; + tests_arr[i].count = 0; + tests_arr[i].type_count = 0; + tests_arr[i].type_indices[0] = 0; + tests_arr[i].type_blocklens[0] = 0; + tests_arr[i].type_oldtypes[0] = MPI_BYTE; + tests_arr[i].type_indices[1] = 0; + tests_arr[i].type_blocklens[1] = 0; + tests_arr[i].type_oldtypes[1] = MPI_BYTE; + tests_arr[i].type_indices[2] = 0; + tests_arr[i].type_blocklens[2] = 0; + tests_arr[i].type_oldtypes[2] = MPI_BYTE; + tests_arr[i].type_indices[3] = 0; + tests_arr[i].type_blocklens[3] = 0; + tests_arr[i].type_oldtypes[3] = MPI_BYTE; + break; + case 3: + tests_arr[i].offset = 0; + tests_arr[i].count = 0; + tests_arr[i].type_count = 0; + tests_arr[i].type_indices[0] = 0; + tests_arr[i].type_blocklens[0] = 0; + tests_arr[i].type_oldtypes[0] = MPI_BYTE; + tests_arr[i].type_indices[1] = 0; + tests_arr[i].type_blocklens[1] = 0; + tests_arr[i].type_oldtypes[1] = MPI_BYTE; + tests_arr[i].type_indices[2] = 0; + tests_arr[i].type_blocklens[2] = 0; + tests_arr[i].type_oldtypes[2] = MPI_BYTE; + tests_arr[i].type_indices[3] = 0; + tests_arr[i].type_blocklens[3] = 0; + tests_arr[i].type_oldtypes[3] = MPI_BYTE; + break; + case 4: + tests_arr[i].offset = 0; + tests_arr[i].count = 0; + tests_arr[i].type_count = 0; + tests_arr[i].type_indices[0] = 0; + tests_arr[i].type_blocklens[0] = 0; + tests_arr[i].type_oldtypes[0] = MPI_BYTE; + tests_arr[i].type_indices[1] = 0; + tests_arr[i].type_blocklens[1] = 0; + tests_arr[i].type_oldtypes[1] = MPI_BYTE; + tests_arr[i].type_indices[2] = 0; + tests_arr[i].type_blocklens[2] = 0; + tests_arr[i].type_oldtypes[2] = MPI_BYTE; + tests_arr[i].type_indices[3] = 0; + tests_arr[i].type_blocklens[3] = 0; + tests_arr[i].type_oldtypes[3] = MPI_BYTE; + break; + } + } + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/.codingcheck b/ompi/mca/io/romio314/romio/test/.codingcheck new file mode 100644 index 0000000000..0d0a655fa8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/.codingcheck @@ -0,0 +1,13 @@ +# +# We allow these routines for the romio test programs +%romioTestRoutines = ( + 'printf' => sys, 'fprintf' => sys , 'sprintf' => sys, 'vprintf' => sys, + 'strcpy' => sys, 'strncpy' => sys, 'strcat' => sys, + 'malloc' => sys, 'free' => sys, 'calloc' => sys, 'strdup' => sys, + 'assert' => sys, 'snprintf' => sys, + ); +if (defined(&PushAllowFuncNames)) { + &PushAllowFuncNames( "romioTestRoutines", "tree", "add" ); +} + +1; diff --git a/ompi/mca/io/romio314/romio/test/Makefile.am b/ompi/mca/io/romio314/romio/test/Makefile.am new file mode 100644 index 0000000000..caa5be91e7 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/Makefile.am @@ -0,0 +1,43 @@ +# -*- Mode: Makefile; -*- +# +# (C) 2011 by Argonne National Laboratory. +# See COPYRIGHT in top-level directory. +# + +# This directory is only listed in DIST_SUBDIRS, not SUBDIRS, so its contents +# will not be built by default, but it will participate in "make distclean" and +# friends. + +# override the normal compilers for the tests +CC = $(TEST_CC) +F77 = $(TEST_F77) + +# because := is not universally avalible, we have to play games to use the +# user-specified LDFLAGS and OUR_LIBS env. variables (if set) +OUR_LIBS = $(TEST_LIBNAME) $(MPI_LIB) + +LDADD = $(OUR_LIBS) + +AM_CPPFLAGS = $(ROMIO_INCLUDE) +AM_CFLAGS = $(USER_CFLAGS) +AM_FFLAGS = $(USER_FFLAGS) + +CTESTS = simple perf async coll_test coll_perf misc file_info excl large_array \ + atomicity noncontig i_noncontig noncontig_coll split_coll shared_fp \ + large_file psimple error status noncontig_coll2 aggregation1 aggregation2 \ + async-multiple ordered_fp hindexed external32 types_with_zeros darray_read +FTESTS = fcoll_test fperf fmisc pfcoll_test + + +noinst_PROGRAMS = $(CTESTS) + +if BUILD_F77_TESTS + +noinst_PROGRAMS += $(FTESTS) +fperf_SOURCES = fperf.f +fcoll_test_SOURCES = fcoll_test.f +fmisc_SOURCES = fmisc.f +pfcoll_test_SOURCES = pfcoll_test.f + +endif BUILD_F77_TESTS + diff --git a/ompi/mca/io/romio314/romio/test/Mfile.in b/ompi/mca/io/romio314/romio/test/Mfile.in new file mode 100644 index 0000000000..c2e1c29825 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/Mfile.in @@ -0,0 +1,84 @@ +ALL: default + +# This is a special Makefile.in source for use by the test suite (see the +# configure in examples/test) +##### User configurable options ##### + +MPIR_HOME = @MPIR_HOME@ +CC = @MPICC@ +CLINKER = @MPICC@ +CCC = @MPICPLUSPLUS@ +CCLINKER = $(CCC) +F77 = @MPIF77@ +F90BASE = @MPIF90BASE@ +F90 = @MPIF90@ +FLINKER = @MPIF77@ +OPTFLAGS = @OPTFLAGS@ +MPIFDEP = @MPIFDEP@ +### End User configurable options ### + +SHELL = /bin/sh +prefix = @prefix@ +top_srcdir = @top_srcdir@ +srcdir = @srcdir@ +@VPATH@ + +PROFLIB = +CFLAGS = @CFLAGS@ @DEFS@ $(OPTFLAGS) +CCFLAGS = $(CFLAGS) +FFLAGS = $(OPTFLAGS) @FFLAGS@ +# Use LIBS to add any special libraries for C programs +LIBS = @LIB_PATH@ @LIB_LIST@ +# Use FLIBS to add any special libraries for Fortran programs +FLIBS = @FLIB_PATH@ @LIB_LIST@ @F77EXTRALIBS@ +EXECS = $(CTESTS) $(FTESTS) +OTHEREXECS = +CTESTS = simple perf async coll_test coll_perf misc file_info excl \ + large_array \ + atomicity noncontig i_noncontig noncontig_coll split_coll shared_fp \ + large_file psimple error status noncontig_coll2 +FTESTS = fcoll_test fperf fmisc pfcoll_test + +default: $(EXECS) + +# +# Note that runtests builds the executables as required +testing: + -./runtests $(TESTARGS) + +all: testing + +fortran_tests: $(FTESTS) +# +# The Fortran tests must be built with the Fortran linker +fperf: fperf.f + $(F77) $(USER_FFLAGS) -o $@ $< $(FLIBS) + +# Some of the Fortran tests must be derived, so their code will be in the +# LOCAL directory +fcoll_test: fcoll_test.f + $(F77) $(USER_FFLAGS) -o fcoll_test fcoll_test.f $(FLIBS) + +fmisc: fmisc.f + $(F77) $(USER_FFLAGS) -o fmisc fmisc.f $(FLIBS) + +pfcoll_test: pfcoll_test.f + $(F77) $(USER_FFLAGS) -o pfcoll_test pfcoll_test.f $(FLIBS) + +# +# Make sure that we remove executables for specific architectures +clean: + @-rm -f *.o *~ PI* $(EXECS) *.out core pt2pt.diff $(OTHEREXECS) \ + *.trace rdb.* startup.* mpif.h ${srcdir}/*.o *.stdo + @-rm -f work.pc work.pcl + @-for file in $(EXECS) Makefile ; do \ + rm -f $$file.sun4 $$file.alpha $$file.IRIX $$file.freebsd ;\ + done +.c: + $(CC) $(CFLAGS) -o $* $< $(LIBS) +.c.o: + $(CC) $(CFLAGS) -c $< +.o: + ${CLINKER} $(OPTFLAGS) -o $* $*.o $(LIBS) +.f.o: + $(F77) $(FFLAGS) -c $< diff --git a/ompi/mca/io/romio314/romio/test/README b/ompi/mca/io/romio314/romio/test/README new file mode 100644 index 0000000000..dbab8e393d --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/README @@ -0,0 +1,84 @@ +This directory contains a few example programs. + +Each program takes the filename as a command-line argument +"-fname filename". + +If you are using "mpirun" to run an MPI program, you can run the +program "simple" with two processes as follows: + mpirun -np 2 simple -fname test + + +simple.c: Each process creates its own file, writes to it, reads it + back, and checks the data read. + +psimple.c: Same as simple.c but uses the PMPI versions of all MPI routines + +error.c: Tests if error messages are printed correctly + +status.c: Tests if the status object is filled correctly by I/O functions + +perf.c: A simple read and write performance test. Each process writes + 4Mbytes to a file at a location determined by its rank and + reads it back. For a different access size, change the value + of SIZE in the code. The bandwidth is reported for two cases: + (1) without including MPI_File_sync and (2) including + MPI_File_sync. + +async.c: This program is the same as simple.c, except that it uses + asynchronous I/O. + +coll_test.c: This program tests the use of collective I/O. It writes + a 3D block-distributed array to a file corresponding to the + global array in row-major (C) order, reads it back, and checks + that the data read is correct. The global array size has been + set to 32^3. If you are running it on NFS, which is very slow, + you may want to reduce that size to 16^3. + +coll_perf.c: Measures the I/O bandwidth for writing/reading a 3D + block-distributed array to a file corresponding to the global array + in row-major (C) order. The global array size has been + set to 128^3. If you are running it on NFS, which is very slow, + you may want to reduce that size to 16^3. + +misc.c: Tests various miscellaneous MPI-IO functions + +atomicity.c: Tests whether atomicity semantics are satisfied for + overlapping accesses in atomic mode. The probability of detecting + errors is higher if you run it on 8 or more processes. + +large_file.c: Tests access to large files. Writes a 4-Gbyte file and + reads it back. Run it only on one process and on a file system + on which ROMIO supports large files. + +large_array.c: Tests writing and reading a 4-Gbyte distributed array using + the distributed array datatype constructor. Works only on file + systems that support 64-bit file sizes and MPI implementations + that support 64-bit MPI_Aint. + +file_info.c: Tests the setting and retrieval of hints via + MPI_File_set_info and MPI_File_get_info + +excl.c: Tests MPI_File_open with MPI_MODE_EXCL + +noncontig.c: Tests noncontiguous accesses in memory and file using + independent I/O. Run it on two processes only. + +noncontig_coll.c: Same as noncontig.c, but uses collective I/O + +noncontig_coll2.c: Same as noncontig_coll.c, but exercises the + cb_config_list hint and aggregation handling more. + +i_noncontig.c: Same as noncontig.c, but uses nonblocking I/O + +shared_fp.c: Tests the shared file pointer functions + +split_coll.c: Tests the split collective I/O functions + +fperf.f: Fortran version of perf.c + +fcoll_test.f: Fortran version of coll_test.c + +pfcoll_test.f: Same as fcoll_test.f but uses the PMPI versions of + all MPI routines + +fmisc.f: Fortran version of misc.c diff --git a/ompi/mca/io/romio314/romio/test/aggregation1.c b/ompi/mca/io/romio314/romio/test/aggregation1.c new file mode 100644 index 0000000000..dee42d60a5 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/aggregation1.c @@ -0,0 +1,266 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2007 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ + +/* Test case from John Bent (ROMIO req #835) + * Aggregation code was not handling certain access patterns when collective + * buffering forced */ +#define _XOPEN_SOURCE 500 /* strdup not in string.h otherwsie */ +#include +#include +#include +#include +#include + +#define NUM_OBJS 4 +#define OBJ_SIZE 1048576 + +extern char *optarg; +extern int optind, opterr, optopt; + + +char *prog = NULL; +int debug = 0; + +static void +Usage( int line ) { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if ( rank == 0 ) { + fprintf( stderr, + "Usage (line %d): %s [-d] [-h] -f filename\n" + "\t-d for debugging\n" + "\t-h to turn on the hints to force collective aggregation\n", + line, prog ); + } + exit( 0 ); +} + +static void +fatal_error( int mpi_ret, MPI_Status *mpi_stat, const char *msg ) { + fprintf( stderr, "Fatal error %s: %d\n", msg, mpi_ret ); + MPI_Abort( MPI_COMM_WORLD, -1 ); +} + +static void +print_hints( int rank, MPI_File *mfh ) { + MPI_Info info; + int nkeys; + int i, dummy_int; + char key[1024]; + char value[1024]; + + MPI_Barrier( MPI_COMM_WORLD ); + if ( rank == 0 ) { + MPI_File_get_info( *mfh, &info ); + MPI_Info_get_nkeys( info, &nkeys ); + + printf( "HINTS:\n" ); + for( i = 0; i < nkeys; i++ ) { + MPI_Info_get_nthkey( info, i, key ); + printf( "%35s -> ", key ); + MPI_Info_get( info, key, 1024, value, &dummy_int ); + printf( "%s\n", value ); + } + MPI_Info_free(&info); + } + MPI_Barrier( MPI_COMM_WORLD ); +} + +static void +fill_buffer( char *buffer, int bufsize, int rank, MPI_Offset offset ) { + memset( (void*)buffer, 0, bufsize ); + snprintf( buffer, bufsize, "Hello from %d at %lld\n", rank, offset ); +} + +static MPI_Offset +get_offset( int rank, int num_objs, int obj_size, int which_obj ) { + MPI_Offset offset; + offset = (MPI_Offset)rank * num_objs * obj_size + which_obj * obj_size; + return offset; +} + +static void +write_file( char *target, int rank, MPI_Info *info ) { + MPI_File wfh; + MPI_Status mpi_stat; + int mpi_ret; + int i; + char *buffer; + + buffer = malloc(OBJ_SIZE); + + if ( debug ) printf( "%d writing file %s\n", rank, target ); + + if( (mpi_ret = MPI_File_open(MPI_COMM_WORLD, target, + MPI_MODE_WRONLY | MPI_MODE_CREATE, *info, &wfh ) ) + != MPI_SUCCESS ) + { + fatal_error( mpi_ret, NULL, "open for write" ); + } + + for( i = 0; i < NUM_OBJS; i++ ) { + MPI_Offset offset = get_offset( rank, NUM_OBJS, OBJ_SIZE, i ); + fill_buffer( buffer, OBJ_SIZE, rank, offset ); + if ( debug ) printf( "%s", buffer ); + if ( (mpi_ret = MPI_File_write_at_all( wfh, offset, buffer, OBJ_SIZE, + MPI_CHAR, &mpi_stat ) ) != MPI_SUCCESS ) + { + fatal_error( mpi_ret, &mpi_stat, "write" ); + } + } + + if ( debug ) print_hints( rank, &wfh ); + + if( (mpi_ret = MPI_File_close( &wfh ) ) != MPI_SUCCESS ) { + fatal_error( mpi_ret, NULL, "close for write" ); + } + if ( debug ) printf( "%d wrote file %s\n", rank, target ); + free(buffer); +} + +static int +reduce_corruptions( int corrupt_blocks ) { + int mpi_ret; + int sum; + if ( ( mpi_ret = MPI_Reduce( &corrupt_blocks, &sum, 1, + MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD ) ) != MPI_SUCCESS ) + { + fatal_error( mpi_ret, NULL, "MPI_Reduce" ); + } + return sum; +} + +static void +read_file( char *target, int rank, MPI_Info *info, int *corrupt_blocks ) { + MPI_File rfh; + MPI_Status mpi_stat; + int mpi_ret; + int i; + char *buffer; + char *verify_buf = NULL; + buffer = malloc(OBJ_SIZE); + verify_buf = (char *)malloc(OBJ_SIZE); + + if ( debug ) printf( "%d reading file %s\n", rank, target ); + + if( (mpi_ret = MPI_File_open(MPI_COMM_WORLD, target, + MPI_MODE_RDONLY, *info, &rfh ) ) != MPI_SUCCESS ) + { + fatal_error( mpi_ret, NULL, "open for read" ); + } + + for( i = 0; i < NUM_OBJS; i++ ) { + MPI_Offset offset = get_offset( rank, NUM_OBJS, OBJ_SIZE, i ); + fill_buffer( verify_buf, OBJ_SIZE, rank, offset ); + if ( debug ) printf( "Expecting %s", buffer ); + if ( (mpi_ret = MPI_File_read_at_all( rfh, offset, buffer, OBJ_SIZE, + MPI_CHAR, &mpi_stat ) ) != MPI_SUCCESS ) + { + fatal_error( mpi_ret, &mpi_stat, "read" ); + } + if ( memcmp( verify_buf, buffer, OBJ_SIZE ) != 0 ) { + (*corrupt_blocks)++; + printf( "Corruption at %lld\n", offset ); + if ( debug ) { + printf( "\tExpecting %s\n" + "\tRecieved %s\n", + verify_buf, buffer ); + } + } + } + + if( (mpi_ret = MPI_File_close( &rfh ) ) != MPI_SUCCESS ) { + fatal_error( mpi_ret, NULL, "close for read" ); + } + free (buffer); + free(verify_buf); + +} + +static void +set_hints( MPI_Info *info ) { + MPI_Info_set( *info, "romio_cb_write", "enable" ); + MPI_Info_set( *info, "romio_no_indep_rw", "1" ); + MPI_Info_set( *info, "cb_nodes", "1" ); + MPI_Info_set( *info, "cb_buffer_size", "4194304" ); +} + +/* +void +set_hints( MPI_Info *info, char *hints ) { + char *delimiter = " "; + char *hints_cp = strdup( hints ); + char *key = strtok( hints_cp, delimiter ); + char *val; + while( key ) { + val = strtok( NULL, delimiter ); + if ( debug ) printf( "HINT: %s = %s\n", key, val ); + if ( ! val ) { + Usage( __LINE__ ); + } + MPI_Info_set( *info, key, val ); + key = strtok( NULL, delimiter ); + } + free( hints_cp ); +} +*/ + +int +main( int argc, char *argv[] ) { + int nproc = 1, rank = 0; + char *target = NULL; + int c; + MPI_Info info; + int mpi_ret; + int corrupt_blocks = 0; + + MPI_Init( &argc, &argv ); + MPI_Comm_size(MPI_COMM_WORLD, &nproc); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if( (mpi_ret = MPI_Info_create(&info)) != MPI_SUCCESS) { + if(rank == 0) fatal_error( mpi_ret, NULL, "MPI_info_create.\n"); + } + + prog = strdup( argv[0] ); + + while( ( c = getopt( argc, argv, "df:h" ) ) != EOF ) { + switch( c ) { + case 'd': + debug = 1; + break; + case 'f': + target = strdup( optarg ); + break; + case 'h': + set_hints( &info ); + break; + default: + Usage( __LINE__ ); + } + } + if ( ! target ) { + Usage( __LINE__ ); + } + + write_file( target, rank, &info ); + read_file( target, rank, &info, &corrupt_blocks ); + + corrupt_blocks = reduce_corruptions( corrupt_blocks ); + if ( rank == 0 ) { + if (corrupt_blocks == 0) { + fprintf(stdout, " No Errors\n"); + } else { + fprintf(stdout, "%d/%d blocks corrupt\n", + corrupt_blocks, nproc * NUM_OBJS ); + } + } + MPI_Info_free(&info); + + MPI_Finalize(); + free(prog); + exit( 0 ); +} diff --git a/ompi/mca/io/romio314/romio/test/aggregation2.c b/ompi/mca/io/romio314/romio/test/aggregation2.c new file mode 100644 index 0000000000..a35ebe0caf --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/aggregation2.c @@ -0,0 +1,89 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2007 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ + +/* Look for regressions in aggregator code. A more simple access pattern than + * aggregation1 */ + +#include + +#include +#include +#include + +#include +#include + +#include + +#define BUFSIZE 512 + +static void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + +int main(int argc, char ** argv) +{ + MPI_Info info = MPI_INFO_NULL; + MPI_File fh; + MPI_Offset off=0; + MPI_Status status; + int errcode; + int i, rank, errs=0, toterrs, buffer[BUFSIZE], buf2[BUFSIZE]; + + MPI_Init(&argc, &argv); + + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + MPI_Info_create(&info); + MPI_Info_set(info, "romio_cb_write", "enable"); + MPI_Info_set(info, "cb_nodes", "1"); + + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + MPI_Info_free(&info); + MPI_Finalize(); + + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/async-multiple.c b/ompi/mca/io/romio314/romio/test/async-multiple.c new file mode 100644 index 0000000000..ec9726ce55 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/async-multiple.c @@ -0,0 +1,139 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- + * vim: ts=8 sts=4 sw=4 noexpandtab + * + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +#define SIZE (65536) +#define NR_NBOPS (32) + +/* Uses asynchronous I/O. Each process writes to separate files and + reads them back. The file name is taken as a command-line argument, + and the process rank is appended to it.*/ + +void handle_error(int errcode, const char *str); + +void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} +int main(int argc, char **argv) +{ + int *buf, i, rank, nints, len; + char *filename, *tmp; + int errs=0, toterrs; + MPI_File fh; + MPI_Status status[NR_NBOPS]; + MPI_Request request[NR_NBOPS]; + int errcode = 0; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!rank) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: async -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+10); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+10); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + + buf = (int *) malloc(SIZE); + nints = SIZE/sizeof(int); + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + + free(buf); + free(filename); + free(tmp); + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/async.c b/ompi/mca/io/romio314/romio/test/async.c new file mode 100644 index 0000000000..8882716dfe --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/async.c @@ -0,0 +1,138 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +#define SIZE (65536) + +/* Uses asynchronous I/O. Each process writes to separate files and + reads them back. The file name is taken as a command-line argument, + and the process rank is appended to it.*/ + +void handle_error(int errcode, const char *str); + +void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} +int main(int argc, char **argv) +{ + int *buf, i, rank, nints, len; + char *filename, *tmp; + int errs=0, toterrs; + MPI_File fh; + MPI_Status status; + MPIO_Request request; + int errcode = 0; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!rank) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: async -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+10); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+10); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + + buf = (int *) malloc(SIZE); + nints = SIZE/sizeof(int); + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + + free(buf); + free(filename); + free(tmp); + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/atomicity.c b/ompi/mca/io/romio314/romio/test/atomicity.c new file mode 100644 index 0000000000..7797075ed9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/atomicity.c @@ -0,0 +1,210 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* tests whether atomicity semantics are satisfied for overlapping accesses + in atomic mode. The probability of detecting errors is higher if you run + it on 8 or more processes. */ + +/* The file name is taken as a command-line argument. */ + +#define BUFSIZE 10000 /* no. of integers */ +#define VERBOSE 0 +int main(int argc, char **argv) +{ + int *writebuf, *readbuf, i, mynod, nprocs, len, err; + char *filename; + int errs=0, toterrs; + MPI_Datatype newtype; + MPI_File fh; + MPI_Status status; + MPI_Info info; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: coll_test -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + writebuf = (int *) malloc(BUFSIZE*sizeof(int)); + readbuf = (int *) malloc(BUFSIZE*sizeof(int)); + +/* test atomicity of contiguous accesses */ + +/* initialize file to all zeros */ + if (!mynod) { + MPI_File_delete(filename, MPI_INFO_NULL); + MPI_File_open(MPI_COMM_SELF, filename, MPI_MODE_CREATE | + MPI_MODE_RDWR, MPI_INFO_NULL, &fh); + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + MPI_Type_free(&newtype); + MPI_Info_free(&info); + free(writebuf); + free(readbuf); + free(filename); + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/big_extents.c b/ompi/mca/io/romio314/romio/test/big_extents.c new file mode 100644 index 0000000000..a1a9e5ff68 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/big_extents.c @@ -0,0 +1,212 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2007 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ + +/* a test to exercise very large extents: on most platforms with 32 bit + * integers, we'd expect these tests to give unexpected values. On platforms + * with 64 bit integers, these tests will be fine. On BlueGene we're not sure + * yet :> + */ + + +#include +#include +#include +#include + +#define CHECK(fn) {int errcode; errcode = (fn); if (errcode != MPI_SUCCESS) handle_error(errcode, NULL); } + + +static void handle_error(int errcode, char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + +static void typestats(MPI_Datatype type) +{ + MPI_Aint lb, extent; + MPI_Count size; + + MPI_Type_get_extent(type, &lb, &extent); + MPI_Type_size_x(type, &size); + + printf("dtype %d: lb = %ld extent = %ld size = %ld...", + type, (long)lb, (long)extent, size); + +} + +static int verify_type(char *filename, MPI_Datatype type, + int64_t expected_extent, int do_coll) +{ + int rank, canary; + MPI_Count tsize; + int compare=-1; + int errs=0, toterrs=0; + MPI_Status status; + MPI_File fh; + + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + CHECK( MPI_File_open(MPI_COMM_WORLD, filename, + MPI_MODE_CREATE|MPI_MODE_RDWR, MPI_INFO_NULL, &fh)); + CHECK( MPI_File_set_view(fh, rank*sizeof(int), + MPI_BYTE, type, "native", MPI_INFO_NULL)); + + MPI_Type_size_x(type, &tsize); + + canary=rank+1000000; + + /* skip over first instance of type */ + if (do_coll) { + CHECK( MPI_File_write_at_all(fh, tsize, &canary, 1, MPI_INT, &status)); + } else { + CHECK( MPI_File_write_at(fh, tsize, &canary, 1, MPI_INT, &status)); + } + + CHECK( MPI_File_set_view(fh, 0, MPI_INT, MPI_INT, "native", + MPI_INFO_NULL)); + + if (do_coll) { + CHECK( MPI_File_read_at_all(fh, expected_extent/sizeof(int)+rank, + &compare, 1, MPI_INT, &status)); + } else { + CHECK( MPI_File_read_at(fh, expected_extent/sizeof(int)+rank, + &compare, 1, MPI_INT, &status)); + } + + if (compare != canary) + errs=1; + MPI_Allreduce(&errs, &toterrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); + + MPI_File_close(&fh); + + if (toterrs) { + printf("%d: got %d expected %d\n", rank, compare, canary); + /* keep file if there's an error */ + } else { + if (rank == 0) MPI_File_delete(filename, MPI_INFO_NULL); + } + + return (toterrs); + +} + +static int testtype(char *filename, MPI_Datatype type, int64_t expected_extent) +{ + int rank, ret, errs=0; + int collective=1, nocollective=0; + + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (!rank) typestats(type); + + ret = verify_type(filename, type, expected_extent, nocollective); + if (ret) { + errs++; + fprintf(stderr, "type %d failed indep\n", type); + } else + if (!rank) printf("indep: OK "); + + ret = verify_type(filename, type, expected_extent, collective); + if (ret) { + errs++; + fprintf(stderr, "type %d failed collective\n", type); + } else + if (!rank) printf("coll: OK\n"); + + return errs; +} + +int main(int argc, char **argv) +{ + int count=2; + int blocks[2]; + int disps[2]; + + int ndims=2; + int sizes[2]; + int subs[2]; + int starts[2]; + + MPI_Datatype baseindex, indexed1G, indexed3G, indexed6G; + MPI_Datatype subarray1G, subarray3G, subarray6G; + int ret, rank; + + MPI_Init(&argc, &argv); + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + /* base type: 1MB indexed type of ints*/ + count = 2; + blocks[0] = 1; + disps[0] = 0; + blocks[1] = 1; + disps[1] = 1024*256-1; + + MPI_Type_indexed(count, blocks, disps, MPI_INT, &baseindex); + /* simple case: 1GB extent */ + MPI_Type_contiguous(1024, baseindex, &indexed1G); + MPI_Type_commit(&indexed1G); + + /* a little trickier: 3Gb extent */ + MPI_Type_contiguous(3072, baseindex, &indexed3G); + MPI_Type_commit(&indexed3G); + + /* and finally 6GB extent */ + MPI_Type_contiguous(6144, baseindex, &indexed6G); + MPI_Type_commit(&indexed6G); + + /* TODO: + * - add a darray test + * - add a test with crazy extents */ + sizes[0] = 1024*16; + sizes[1] = 1024*16; + subs[0] = subs[1] = 256; + starts[0] = starts[1] = 0; + + MPI_Type_create_subarray(ndims, sizes, subs, starts, + MPI_ORDER_C, MPI_INT, &subarray1G); + MPI_Type_commit(&subarray1G); + + sizes[1] = 1024*16*3; + MPI_Type_create_subarray(ndims, sizes, subs, starts, + MPI_ORDER_C, MPI_INT, &subarray3G); + MPI_Type_commit(&subarray3G); + + sizes[1] = 1024*16*6; + MPI_Type_create_subarray(ndims, sizes, subs, starts, + MPI_ORDER_C, MPI_INT, &subarray6G); + MPI_Type_commit(&subarray6G); + + /* assume command line arguments make it out to all processes */ + ret = testtype(argv[1], indexed1G, (int64_t)1024*1024*1024); + + ret = testtype(argv[1], indexed3G, (int64_t)1024*1024*1024*3); + + ret = testtype(argv[1], indexed6G, (int64_t)1024*1024*1024*6); + + ret = testtype(argv[1], subarray1G, (int64_t)1024*1024*1024); + + ret = testtype(argv[1], subarray3G, (int64_t)1024*1024*1024*3); + + ret = testtype(argv[1], subarray6G, (int64_t)1024*1024*1024*6); + + if(!ret && !rank) fprintf(stderr, " No Errors\n"); + + MPI_Finalize(); + return (-ret); + +} +/* + * vim: ts=8 sts=4 sw=4 noexpandtab + */ diff --git a/ompi/mca/io/romio314/romio/test/coll_perf.c b/ompi/mca/io/romio314/romio/test/coll_perf.c new file mode 100644 index 0000000000..0f9042d5ff --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/coll_perf.c @@ -0,0 +1,151 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* The file name is taken as a command-line argument. */ + +/* Measures the I/O bandwidth for writing/reading a 3D + block-distributed array to a file corresponding to the global array + in row-major (C) order. + Note that the file access pattern is noncontiguous. + + Array size 128^3. For other array sizes, change array_of_gsizes below.*/ + + +int main(int argc, char **argv) +{ + MPI_Datatype newtype; + int i, ndims, array_of_gsizes[3], array_of_distribs[3]; + int order, nprocs, len, *buf, mynod; + MPI_Count bufcount; + int array_of_dargs[3], array_of_psizes[3]; + MPI_File fh; + MPI_Status status; + double stim, write_tim, new_write_tim, write_bw; + double read_tim, new_read_tim, read_bw; + char *filename; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: coll_perf -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + + ndims = 3; + order = MPI_ORDER_C; + + array_of_gsizes[0] = 128*17; + array_of_gsizes[1] = 128*9; + array_of_gsizes[2] = 128*11; + + array_of_distribs[0] = MPI_DISTRIBUTE_BLOCK; + array_of_distribs[1] = MPI_DISTRIBUTE_BLOCK; + array_of_distribs[2] = MPI_DISTRIBUTE_BLOCK; + + array_of_dargs[0] = MPI_DISTRIBUTE_DFLT_DARG; + array_of_dargs[1] = MPI_DISTRIBUTE_DFLT_DARG; + array_of_dargs[2] = MPI_DISTRIBUTE_DFLT_DARG; + + for (i=0; i +#include +#include + +/* A 32^3 array. For other array sizes, change array_of_gsizes below. */ + +/* Uses collective I/O. Writes a 3D block-distributed array to a file + corresponding to the global array in row-major (C) order, reads it + back, and checks that the data read is correct. */ + +/* The file name is taken as a command-line argument. */ + +/* Note that the file access pattern is noncontiguous. */ + +void handle_error(int errcode, const char *str); + +void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + +int main(int argc, char **argv) +{ + MPI_Datatype newtype; + int i, ndims, array_of_gsizes[3], array_of_distribs[3]; + int order, nprocs, j, len; + int array_of_dargs[3], array_of_psizes[3]; + int *readbuf, *writebuf, mynod, *tmpbuf, array_size; + MPI_Count bufcount; + char *filename; + int errs=0, toterrs; + MPI_File fh; + MPI_Status status; + MPI_Request request; + MPI_Info info = MPI_INFO_NULL; + int errcode; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: coll_test -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + +/* create the distributed array filetype */ + ndims = 3; + order = MPI_ORDER_C; + + array_of_gsizes[0] = 32; + array_of_gsizes[1] = 32; + array_of_gsizes[2] = 32; + + array_of_distribs[0] = MPI_DISTRIBUTE_BLOCK; + array_of_distribs[1] = MPI_DISTRIBUTE_BLOCK; + array_of_distribs[2] = MPI_DISTRIBUTE_BLOCK; + + array_of_dargs[0] = MPI_DISTRIBUTE_DFLT_DARG; + array_of_dargs[1] = MPI_DISTRIBUTE_DFLT_DARG; + array_of_dargs[2] = MPI_DISTRIBUTE_DFLT_DARG; + + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + + MPI_Type_free(&newtype); + free(readbuf); + free(writebuf); + free(filename); + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/creat_excl.c b/ompi/mca/io/romio314/romio/test/creat_excl.c new file mode 100644 index 0000000000..858df00e8a --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/creat_excl.c @@ -0,0 +1,134 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include +/* + * the new defered open code made some changes to the way we manage CREAT|EXCL, + * so test out that code path */ + +struct options { + char *fname; + int verbose; + int do_aggregation; +}; +typedef struct options options; + + +void handle_error(int errcode, char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + +void parse_args(int argc, char ** argv, int rank, options *opts) +{ + int i, len=0; + if (rank == 0) { + i = 1; + while (i < argc) { + if (strcmp("-fname", argv[i]) == 0) { + len = strlen(argv[i+1]); + opts->fname = (char *) malloc(len + 1); + strcpy(opts->fname, argv[i+1]); + i+=2;/* option and argument */ + continue; + } + if (strcmp("-aggregate", argv[i]) == 0) { + opts->do_aggregation = 1; + i++; + continue; + } + if (strcmp("-verbose", argv[i]) == 0) { + opts->verbose = 1; + i++; + continue; + } + } + if (opts->fname == NULL) { /* didn't get a filename */ + fprintf(stderr, "Usage: %s -fname filename [-aggregate] [-verbose]\n", argv[0]); + MPI_Abort(MPI_COMM_WORLD, 1); + } + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(opts->fname, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + MPI_Bcast(&(opts->do_aggregation), 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&(opts->verbose), 1, MPI_INT, 0, MPI_COMM_WORLD); + } else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + opts->fname = (char *) malloc(len + 1); + MPI_Bcast(opts->fname, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + MPI_Bcast(&(opts->do_aggregation), 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&(opts->verbose), 1, MPI_INT, 0, MPI_COMM_WORLD); + } + +} + +int main(int argc, char ** argv) { + int nprocs, mynod, errcode; + options my_options = {NULL, 0, 0}; + MPI_File fh; + MPI_Status status; + MPI_Info info; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + + parse_args(argc, argv, mynod, &my_options); + + if (my_options.do_aggregation) { + MPI_Info_create(&info); + MPI_Info_set(info, "romio_no_indep_rw", "true"); + MPI_Info_set(info, "cb_config_list", "leela.mcs.anl.gov:1"); + } else { + info = MPI_INFO_NULL; + } + + /* create the file w/o EXCL: this must not fail */ + errcode = MPI_File_open(MPI_COMM_WORLD, my_options.fname, + MPI_MODE_CREATE|MPI_MODE_RDWR, info, &fh); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_open"); + } + + errcode = MPI_File_close(&fh); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_close"); + } + + /* now try to open w/ CREAT|EXCL: this must fail */ + errcode = MPI_File_open(MPI_COMM_WORLD, my_options.fname, + MPI_MODE_CREATE|MPI_MODE_EXCL|MPI_MODE_RDWR, info, &fh); + if (errcode == MPI_SUCCESS) { + handle_error(errcode, "MPI_File_open: expected an error: got"); + } + + /* ignore the error: File_delete is not aggregator-aware */ + MPI_File_delete(my_options.fname, info); + + /* this must succeed: the file no longer exists */ + errcode = MPI_File_open(MPI_COMM_WORLD, my_options.fname, + MPI_MODE_CREATE|MPI_MODE_EXCL|MPI_MODE_RDWR, info, &fh); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_open"); + } + + errcode = MPI_File_close(&fh); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_close"); + } + + if (mynod == 0) { + printf(" No Errors\n"); + } + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/darray_read.c b/ompi/mca/io/romio314/romio/test/darray_read.c new file mode 100644 index 0000000000..e4eb709e8e --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/darray_read.c @@ -0,0 +1,124 @@ + +#include +#include +#include + +#define NSIDE 5 +#define NBLOCK 3 +#define NPROC 2 + +#define CHECK(fn) {int errcode; errcode = (fn); if (errcode != MPI_SUCCESS) handle_error(errcode, #fn);} + +static void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + + +int main(int argc, char *argv[]) +{ + int i, j, nerrors=0, total_errors=0; + + int rank, size; + int bpos; + + MPI_Datatype darray; + MPI_Status status; + MPI_File mpi_fh; + + /* Define array distribution + A 2x2 block size works with ROMIO, a 3x3 block size breaks it. */ + int distrib[2] = { MPI_DISTRIBUTE_CYCLIC, MPI_DISTRIBUTE_CYCLIC }; + int bsize[2] = { NBLOCK, NBLOCK }; + int gsize[2] = { NSIDE, NSIDE }; + int psize[2] = { NPROC, NPROC }; + + double data[NSIDE*NSIDE]; + double *ldata, *pdata; + + int tsize, nelem; + + MPI_File dfile; + + MPI_Init(&argc, &argv); + + MPI_Comm_size(MPI_COMM_WORLD, &size); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + /* Set up type */ + CHECK(MPI_Type_create_darray(size, rank, 2, gsize, distrib, + bsize, psize, MPI_ORDER_FORTRAN, MPI_DOUBLE, &darray)); + CHECK(MPI_Type_commit(&darray)); + CHECK(MPI_Type_size(darray, &tsize)); + nelem = tsize / sizeof(double); + + for(i = 0; i < (NSIDE*NSIDE); i++) data[i] = i; + + if (rank == 0) { + CHECK(MPI_File_open(MPI_COMM_SELF, argv[1], + MPI_MODE_CREATE|MPI_MODE_WRONLY, MPI_INFO_NULL, &dfile)); + CHECK(MPI_File_write(dfile, data, NSIDE*NSIDE, MPI_DOUBLE, &status)); + CHECK(MPI_File_close(&dfile)); + } + MPI_Barrier(MPI_COMM_WORLD); + + /* Allocate buffer */ + ldata = (double *)malloc(tsize); + pdata = (double *)malloc(tsize); + + /* Use Pack to pull out array */ + bpos = 0; + CHECK(MPI_Pack(data, 1, darray, pdata, tsize, &bpos, MPI_COMM_WORLD)); + + MPI_Barrier(MPI_COMM_WORLD); + + /* Read in array from file. */ + CHECK(MPI_File_open(MPI_COMM_WORLD, argv[1], MPI_MODE_RDONLY, MPI_INFO_NULL, &mpi_fh)); + CHECK(MPI_File_set_view(mpi_fh, 0, MPI_DOUBLE, darray, "native", MPI_INFO_NULL)); + CHECK(MPI_File_read_all(mpi_fh, ldata, nelem, MPI_DOUBLE, &status)); + CHECK(MPI_File_close(&mpi_fh)); + + for(i = 0; i < size; i++) { +#ifdef VERBOSE + MPI_Barrier(MPI_COMM_WORLD); + if(rank == i) { + printf("=== Rank %i === (%i elements) \nPacked: ", rank, nelem); + for(j = 0; j < nelem; j++) { + printf("%4.1f ", pdata[j]); + fflush(stdout); + } + printf("\nRead: "); + for(j = 0; j < nelem; j++) { + printf("%4.1f ", ldata[j]); + fflush(stdout); + } + printf("\n\n"); + fflush(stdout); + } +#endif + if(rank == i) { + for (j=0; j< nelem; j++) { + if (pdata[j] != ldata[j]) { + fprintf(stderr, "rank %d at index %d: packbuf %4.1f filebuf %4.1f\n", + rank, j, pdata[j], ldata[j]); + nerrors++; + } + } + } + } + MPI_Allreduce(&nerrors, &total_errors, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); + if (rank == 0 && total_errors == 0) + printf(" No Errors\n"); + + free(ldata); + free(pdata); + MPI_Type_free(&darray); + MPI_Finalize(); + + exit(total_errors); + +} diff --git a/ompi/mca/io/romio314/romio/test/error.c b/ompi/mca/io/romio314/romio/test/error.c new file mode 100644 index 0000000000..ee24e96459 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/error.c @@ -0,0 +1,106 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +#define VERBOSE 0 +/* tests if error message is printed correctly */ + +int main(int argc, char **argv) +{ + int i, rank, len, err; + int errs = 0; + char *filename, *tmp; + MPI_File fh; + char string[MPI_MAX_ERROR_STRING]; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + +#if VERBOSE + if (!rank) { + fprintf(stderr, "Tests if errors are reported correctly...\n"); + fprintf(stderr, "Should say \"Invalid displacement argument\"\n\n"); + } +#endif + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!rank) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: simple -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+10); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+10); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + /* each process opens a separate file called filename.'myrank' */ + tmp = (char *) malloc(len+10); + strcpy(tmp, filename); + sprintf(filename, "%s.%d", tmp, rank); + + err = MPI_File_open(MPI_COMM_SELF, filename, MPI_MODE_CREATE+MPI_MODE_RDWR, + MPI_INFO_NULL, &fh); + err = MPI_File_set_view(fh, -1, MPI_BYTE, MPI_BYTE, "native", + MPI_INFO_NULL); + /* disp is deliberately passed as -1 */ + + /* This test is designed for ROMIO specifically and tests for a + specific error message */ + if (err != MPI_SUCCESS) { + MPI_Error_string(err, string, &len); + if (!rank) { +#if VERBOSE + fprintf(stderr, "%s\n", string); +#else + /* check for the word "displacement" in the message. + This allows other formatting of the message */ + if (strstr( string, "displacement" ) == 0) { + fprintf( stderr, "Unexpected error message %s\n", string ); + errs++; + } +#endif + } + } + else { + errs++; + fprintf( stderr, "File set view did not return an error\n" ); + } + + MPI_File_close(&fh); + + free(filename); + free(tmp); + + if (!rank) { + if (errs == 0) { + printf( " No Errors\n" ); + } + else { + printf( " Found %d errors\n", errs ); + } + } + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/excl.c b/ompi/mca/io/romio314/romio/test/excl.c new file mode 100644 index 0000000000..e48bb3deee --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/excl.c @@ -0,0 +1,84 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* tests MPI_MODE_EXCL */ + +int main(int argc, char **argv) +{ + MPI_File fh; + int rank, len, err, i; + int errs=0, toterrs; + char *filename; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!rank) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: excl -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+10); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+10); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + + if (!rank) MPI_File_delete(filename, MPI_INFO_NULL); + MPI_Barrier(MPI_COMM_WORLD); + + /* this open should succeed */ + err = MPI_File_open(MPI_COMM_WORLD, filename, + MPI_MODE_CREATE | MPI_MODE_EXCL | MPI_MODE_RDWR, MPI_INFO_NULL , &fh); + if (err != MPI_SUCCESS) { + errs++; + fprintf(stderr, "Process %d: open failed when it should have succeeded\n", rank); + } + else MPI_File_close(&fh); + + MPI_Barrier(MPI_COMM_WORLD); + + /* this open should fail */ + err = MPI_File_open(MPI_COMM_WORLD, filename, + MPI_MODE_CREATE | MPI_MODE_EXCL | MPI_MODE_RDWR, MPI_INFO_NULL , &fh); + if (err == MPI_SUCCESS) { + errs++; + fprintf(stderr, "Process %d: open succeeded when it should have failed\n", rank); + } + + MPI_Allreduce( &errs, &toterrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD ); + if (rank == 0) { + if( toterrs > 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + + free(filename); + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/external32.c b/ompi/mca/io/romio314/romio/test/external32.c new file mode 100644 index 0000000000..bca3555ae8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/external32.c @@ -0,0 +1,97 @@ +/* + * This code was written by Intel Corporation. Copyright (C) 2011-2012 Intel Corporation. + * Intel provides this material to Argonne National Laboratory subject to + * Software Grant and Corporate Contributor License Agreement dated February 8, 2012. + * + * See COPYRIGHT in top-level directory. + */ + +#include +#include +#include "mpi.h" + +#define TEST_LE 0x1 +#define TEST_BE 0x2 +#define TEST_FILENAME "test.datarep" + +#define CHECK(fn) {int errcode; errcode = (fn); if (errcode != MPI_SUCCESS) handle_error(errcode, NULL); } + +static void handle_error(int errcode, char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: (%d) %s\n", str, errcode, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + + + +static void is_little_or_big_endian( const char* datarep, char* c, char* c_le, int len ) { + int i, is_le = 1, is_be = 1; + for( i = 0; i < len; i++ ) { + is_le = is_le && ( c[i] == c_le[i] ); + is_be = is_be && ( c[i] == c_le[len-1-i] ); + } + printf( "%s datarep is ", datarep ); + switch ((is_le ? TEST_LE : 0x0) | (is_be ? TEST_BE : 0x0) ) { + case TEST_LE: printf( "LITTLE ENDIAN\n" ); break; + case TEST_BE: printf( "BIG ENDIAN\n" ); break; + case TEST_LE | TEST_BE: printf( "LITTLE or BIG ENDIAN\n" ); break; + default: printf( "unknown\n" ); break; + } +} + +/* This test checks if datareps given are little- or big-endian */ +int main( int argc, char* argv[] ) { + int sample_i = 123456789, i, j; + char sample_i_le[4] = {0x15,0xcd,0x5b,0x07}, c[4]; + const char* datarep[3] = { "native", "external32", "internal" }; + MPI_File fileh; + int rank; + FILE* fileh_std; + + if( sizeof(int) != 4 ) { printf( "non-supported sizeof(int)=%ld\n", sizeof(int) ); return (-1); } + + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + + /* For each datarep */ + for( i = 0; i < 3; i++ ) { + + /* Open file */ + CHECK(MPI_File_open( MPI_COMM_WORLD, TEST_FILENAME, + MPI_MODE_RDWR | MPI_MODE_CREATE, MPI_INFO_NULL, &fileh ) ); + + /* Set view */ + CHECK(MPI_File_set_view( fileh, 0, MPI_INT, MPI_INT, datarep[i], MPI_INFO_NULL )); + + /* Write into file */ + CHECK(MPI_File_write_at( fileh, (MPI_Offset)rank, (void*)&sample_i, 1, + MPI_INT, MPI_STATUS_IGNORE )); + + /* Close file */ + CHECK(MPI_File_close( &fileh )); + + /* Check if your datarep is little or big endian */ + MPI_Barrier( MPI_COMM_WORLD ); + if( rank == 0 ) { + fileh_std = fopen( TEST_FILENAME, "r" ); + for( j = 0; j < 4; j++ ) { + if( feof( fileh_std ) ) { printf( "unexpected eof, aborted\n" ); return (-1); } + fscanf( fileh_std, "%c", &c[j] ); + } + is_little_or_big_endian( datarep[i], c, sample_i_le, 4 ); + fclose( fileh_std ); + } + + /* Delete file */ + if( rank == 0 ) { + CHECK(MPI_File_delete( TEST_FILENAME, MPI_INFO_NULL )); + } + } + + MPI_Finalize(); + + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/fcoll_test.f.in b/ompi/mca/io/romio314/romio/test/fcoll_test.f.in new file mode 100644 index 0000000000..9c2b172218 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/fcoll_test.f.in @@ -0,0 +1,176 @@ +! -*- Mode: Fortran; -*- +! +! (C) 2001 by Argonne National Laboratory. +! See COPYRIGHT in top-level directory. +! + program main + implicit none + + include 'mpif.h' + @F77MPIOINC@ + +! Fortran equivalent of coll_test.c + + integer FILESIZE + parameter (FILESIZE=32*32*32*4) + +! A 32^3 array. For other array sizes, change FILESIZE above and +! array_of_gsizes below. + +! Uses collective I/O. Writes a 3D block-distributed array to a file +! corresponding to the global array in row-major (C) order, reads it +! back, and checks that the data read is correct. + +! Note that the file access pattern is noncontiguous. + + integer newtype, i, ndims, array_of_gsizes(3) + integer order, intsize, nprocs, j, array_of_distribs(3) + integer array_of_dargs(3), array_of_psizes(3) + integer readbuf(FILESIZE), writebuf(FILESIZE), bufcount + integer mynod, tmpbuf(FILESIZE), array_size, argc, iargc + integer fh, status(MPI_STATUS_SIZE), request, ierr + character*1024 str ! used to store the filename + integer errs, toterrs + @FORTRAN_MPI_OFFSET@ disp + @FTESTDEFINE@ + + errs = 0 + call MPI_INIT(ierr) + call MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr) + call MPI_COMM_RANK(MPI_COMM_WORLD, mynod, ierr) + +! process 0 takes the file name as a command-line argument and +! broadcasts it to other processes + + if (mynod .eq. 0) then + argc = @F77IARGC@ + i = 0 + @F77GETARG@ + do while ((i .lt. argc) .and. (str .ne. '-fname')) + i = i + 1 + @F77GETARG@ + end do + if (i .ge. argc) then + print * + print *, '*# Usage: fcoll_test -fname filename' + print * + call MPI_ABORT(MPI_COMM_WORLD, 1, ierr) + end if + + i = i + 1 + @F77GETARG@ + call MPI_BCAST(str, 1024, MPI_CHARACTER, 0, & + & MPI_COMM_WORLD, ierr) + else + call MPI_BCAST(str, 1024, MPI_CHARACTER, 0, & + & MPI_COMM_WORLD, ierr) + end if + + +! create the distributed array filetype + + ndims = 3 + order = MPI_ORDER_FORTRAN + + array_of_gsizes(1) = 32 + array_of_gsizes(2) = 32 + array_of_gsizes(3) = 32 + + array_of_distribs(1) = MPI_DISTRIBUTE_BLOCK + array_of_distribs(2) = MPI_DISTRIBUTE_BLOCK + array_of_distribs(3) = MPI_DISTRIBUTE_BLOCK + + array_of_dargs(1) = MPI_DISTRIBUTE_DFLT_DARG + array_of_dargs(2) = MPI_DISTRIBUTE_DFLT_DARG + array_of_dargs(3) = MPI_DISTRIBUTE_DFLT_DARG + + do i=1, ndims + array_of_psizes(i) = 0 + end do + + call MPI_DIMS_CREATE(nprocs, ndims, array_of_psizes, ierr) + + call MPI_TYPE_CREATE_DARRAY(nprocs, mynod, ndims, & + & array_of_gsizes, array_of_distribs, array_of_dargs, & + & array_of_psizes, order, MPI_INTEGER, newtype, ierr) + + call MPI_TYPE_COMMIT(newtype, ierr) + +! initialize writebuf + + call MPI_TYPE_SIZE(newtype, bufcount, ierr) + call MPI_TYPE_SIZE(MPI_INTEGER, intsize, ierr) + bufcount = bufcount/intsize + do i=1, bufcount + writebuf(i) = 1 + end do + + do i=1, FILESIZE + tmpbuf(i) = 0 + end do + + call MPI_IRECV(tmpbuf, 1, newtype, mynod, 10, MPI_COMM_WORLD, & + & request, ierr) + call MPI_SEND(writebuf, bufcount, MPI_INTEGER, mynod, 10, & + & MPI_COMM_WORLD, ierr) + call MPI_WAIT(request, status, ierr) + + j = 1 + array_size = array_of_gsizes(1) * array_of_gsizes(2) * & + & array_of_gsizes(3) + do i=1, array_size + if (tmpbuf(i) .ne. 0) then + writebuf(j) = i + j = j + 1 + end if + end do + +! end of initialization + +! write the array to the file + + call MPI_FILE_OPEN(MPI_COMM_WORLD, str, & + & MPI_MODE_CREATE+MPI_MODE_RDWR, MPI_INFO_NULL, fh, ierr) + + disp = 0 + call MPI_FILE_SET_VIEW(fh, disp, MPI_INTEGER, newtype, "native", & + & MPI_INFO_NULL, ierr) + call MPI_FILE_WRITE_ALL(fh, writebuf, bufcount, MPI_INTEGER, & + & status, ierr) + call MPI_FILE_CLOSE(fh, ierr) + +! now read it back + + call MPI_FILE_OPEN(MPI_COMM_WORLD, str, & + & MPI_MODE_CREATE+MPI_MODE_RDWR, MPI_INFO_NULL, fh, ierr) + + call MPI_FILE_SET_VIEW(fh, disp, MPI_INTEGER, newtype, "native", & + & MPI_INFO_NULL, ierr) + call MPI_FILE_READ_ALL(fh, readbuf, bufcount, MPI_INTEGER, & + & status, ierr) + call MPI_FILE_CLOSE(fh, ierr) + +! check the data read + do i=1, bufcount + if (readbuf(i) .ne. writebuf(i)) then + errs = errs + 1 + print *, 'Node ', mynod, ' readbuf ', readbuf(i), & + & ' writebuf ', writebuf(i), ' i', i + end if + end do + + call MPI_TYPE_FREE(newtype, ierr) + call MPI_Allreduce( errs, toterrs, 1, MPI_INTEGER, MPI_SUM, & + $ MPI_COMM_WORLD, ierr ) + if (mynod .eq. 0) then + if( toterrs .gt. 0 ) then + print *, 'Found ', toterrs, ' errors' + else + print *, ' No Errors' + endif + endif + + call MPI_FINALIZE(ierr) + + stop + end diff --git a/ompi/mca/io/romio314/romio/test/file_info.c b/ompi/mca/io/romio314/romio/test/file_info.c new file mode 100644 index 0000000000..fba618974f --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/file_info.c @@ -0,0 +1,421 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ + +/* Change for BG/L made by Hao Yu, yuh@us.ibm.com + */ + +#include "mpi.h" +#include +#include +#include + +static void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} +/* this test wants to compare the hints it gets from a file with a set of + * default hints. These hints are specific to the MPI-IO implementation, so if + * you want to test something besides the default you'll have to use a command + * line argument */ + +typedef struct hint_defaults { + int cb_buffer_size; + int ind_rd_buffer_size; + int ind_wr_buffer_size; + const char *romio_cb_read; + const char *romio_cb_write; + const char *cb_config_list; +} hint_defaults; + +hint_defaults UFS_DEFAULTS = { + .cb_buffer_size = 16777216, + .ind_rd_buffer_size = 4194304, + .ind_wr_buffer_size = 524288, + .romio_cb_read = "automatic", + .romio_cb_write = "automatic", + .cb_config_list = "*:1" +}; + +hint_defaults BLUEGENE_DEFAULTS = { + .cb_buffer_size = 16777216, + .ind_rd_buffer_size = 4194304, + .ind_wr_buffer_size = 4194304, + .romio_cb_read = "enable", + .romio_cb_write = "enable", + .cb_config_list = NULL}; + +/* #undef INFO_DEBUG */ + +/* Test will print out information about unexpected hint keys or values that + * differ from the default. Since this is often interesting but rarely an + * error, default will be to increment errror cound for true error conditions + * but not print out these "interesting" non-error cases. */ + +static int verbose = 0; +static int test_ufs = 0; +static int test_bluegene = 0; + +int main(int argc, char **argv) +{ + int i, len, nkeys, flag, mynod, default_striping_factor=0, nprocs, errs = 0; + MPI_File fh; + MPI_Info info, info_used; + char *filename, key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL]; + hint_defaults *defaults; + int ret; + + MPI_Init(&argc,&argv); + + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + if (!strcmp("-v", *argv)) verbose = 1; + else if (!strcmp("-u", *argv)) test_ufs = 1; + else if (!strcmp("-b", *argv)) test_bluegene = 1; + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: file_info [-v] -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + MPI_Bcast(&verbose, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&test_ufs, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&test_bluegene, 1, MPI_INT, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + MPI_Bcast(&verbose, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&test_ufs, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&test_bluegene, 1, MPI_INT, 0, MPI_COMM_WORLD); + } + if (test_ufs) { + defaults = &UFS_DEFAULTS; + } else if (test_bluegene) { + defaults = &BLUEGENE_DEFAULTS; + } else { + defaults = NULL; + } + + +/* open the file with MPI_INFO_NULL */ + ret = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, + MPI_INFO_NULL, &fh); + if (ret != MPI_SUCCESS) handle_error(ret, "MPI_File_open"); + +/* check the default values set by ROMIO */ + MPI_File_get_info(fh, &info_used); + MPI_Info_get_nkeys(info_used, &nkeys); + + if (defaults != NULL) { + for (i=0; icb_buffer_size) { + errs++; + if (verbose) fprintf(stderr, "cb_buffer_size is %d; should be %d\n", + atoi(value), defaults->cb_buffer_size); + } + } + else if (!strcmp("romio_cb_read", key)) { + if (strcmp(defaults->romio_cb_read, value)) { + errs++; + if (verbose) fprintf(stderr, "romio_cb_read is set to %s; should be %s\n", + value, defaults->romio_cb_read); + } + } + else if (!strcmp("romio_cb_write", key)) { + if (strcmp(defaults->romio_cb_write, value)) { + errs++; + if (verbose) fprintf(stderr, "romio_cb_write is set to %s; should be %s\n", + value, defaults->romio_cb_write); + } + } + else if (!strcmp("cb_nodes", key)) { + /* unreliable test -- just ignore value */ + } + else if (!strcmp("romio_no_indep_rw", key)) { + if (strcmp("false", value)) { + errs++; + if (verbose) fprintf(stderr, "romio_no_indep_rw is set to %s; should be %s\n", + value, "false"); + } + } + else if (!strcmp("ind_rd_buffer_size", key)) { + if (atoi(value) != defaults->ind_rd_buffer_size) { + errs++; + if (verbose) fprintf(stderr, "ind_rd_buffer_size is %d; should be %d\n", + atoi(value), defaults->ind_rd_buffer_size); + } + } + else if (!strcmp("ind_wr_buffer_size", key)) { + if (atoi(value) != defaults->ind_wr_buffer_size) { + errs++; + if (verbose) fprintf(stderr, "ind_wr_buffer_size is %d; should be %d\n", + atoi(value), defaults->ind_wr_buffer_size); + } + } + else if (!strcmp("romio_ds_read", key)) { + if (strcmp("automatic", value)) { + errs++; + if (verbose) fprintf(stderr, "romio_ds_read is set to %s; should be %s\n", + value, "automatic"); + } + } + else if (!strcmp("romio_ds_write", key)) { + /* Unreliable test -- value is file system dependent. Ignore. */ + } + else if (!strcmp("cb_config_list", key)) { +#ifndef SKIP_CB_CONFIG_LIST_TEST + if (strcmp(defaults->cb_config_list, value)) { + errs++; + if (verbose) fprintf(stderr, "cb_config_list is set to %s; should be %s\n", + value, defaults->cb_config_list); + } +#endif + } + /* don't care about the defaults for these keys */ + else if (!strcmp("romio_cb_pfr", key)) { + } + else if (!strcmp("romio_cb_fr_types", key)) { + } + else if (!strcmp("romio_cb_fr_alignment", key)) { + } + else if (!strcmp("romio_cb_ds_threshold", key)) { + } + else if (!strcmp("romio_cb_alltoall", key)) { + } + else { + if (verbose) fprintf(stderr, "unexpected key %s (not counted as an error)\n", key); + } + } + } + MPI_Info_free(&info_used); + + MPI_File_close(&fh); + + /* delete the file */ + if (!mynod) MPI_File_delete(filename, MPI_INFO_NULL); + MPI_Barrier(MPI_COMM_WORLD); + +/* set new info values. */ + + MPI_Info_create(&info); + +/* The following four hints are accepted on all machines. They can + be specified at file-open time or later (any number of times). */ + + /* buffer size for collective I/O */ + MPI_Info_set(info, "cb_buffer_size", "8388608"); + + /* number of processes that actually perform I/O in collective I/O */ + sprintf(value, "%d", nprocs/2); + MPI_Info_set(info, "cb_nodes", value); + + /* buffer size for data sieving in independent reads */ + MPI_Info_set(info, "ind_rd_buffer_size", "2097152"); + + /* buffer size for data sieving in independent writes */ + MPI_Info_set(info, "ind_wr_buffer_size", "1048576"); + + +/* The following three hints related to file striping are accepted only + on Intel PFS and IBM PIOFS file systems and are ignored elsewhere. + They can be specified only at file-creation time; if specified later + they will be ignored. */ + + /* number of I/O devices across which the file will be striped. + accepted only if 0 < value < default_striping_factor; + ignored otherwise */ + if (default_striping_factor - 1 > 0) { + sprintf(value, "%d", default_striping_factor-1); + MPI_Info_set(info, "striping_factor", value); + } + else { + sprintf(value, "%d", default_striping_factor); + MPI_Info_set(info, "striping_factor", value); + } + + /* the striping unit in bytes */ + MPI_Info_set(info, "striping_unit", "131072"); + +#ifndef SKIP_CB_CONFIG_LIST_TEST + /* set the cb_config_list so we'll get deterministic cb_nodes output */ + MPI_Info_set(info, "cb_config_list", "*:*"); +#endif + + /* the I/O device number from which to start striping the file. + accepted only if 0 <= value < default_striping_factor; + ignored otherwise */ + sprintf(value, "%d", default_striping_factor-2); + MPI_Info_set(info, "start_iodevice", value); + + +/* The following hint about PFS server buffering is accepted only on + Intel PFS. It can be specified anytime. */ + MPI_Info_set(info, "pfs_svr_buf", "true"); + +/* open the file and set new info */ + ret = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, + info, &fh); + if (ret != MPI_SUCCESS) handle_error(ret, "MPI_File_open"); + +/* check the values set */ + ret = MPI_File_get_info(fh, &info_used); + if (ret != MPI_SUCCESS) handle_error(ret, "MPI_File_get_info"); + MPI_Info_get_nkeys(info_used, &nkeys); + + for (i=0; i 0) && (atoi(value) != default_striping_factor-1)) { + errs++; + if (verbose) fprintf(stderr, "striping_factor is %d; should be %d\n", + atoi(value), default_striping_factor-1); + } + else if (atoi(value) != default_striping_factor) { + errs++; + if (verbose) fprintf(stderr, "striping_factor is %d; should be %d\n", + atoi(value), default_striping_factor); + } + } + else if (!strcmp("cb_buffer_size", key)) { + if (atoi(value) != 8388608) { + errs++; + if (verbose) fprintf(stderr, "cb_buffer_size is %d; should be %d\n", + atoi(value), 8388608); + } + } + /* only check the hints we set */ + else if (!strcmp("cb_nodes", key)) { + /* unreliable test: just skip */ + } + else if (!strcmp("romio_no_indep_rw", key)) { + if (strcmp("false", value)) { + errs++; + if (verbose) fprintf(stderr, "romio_no_indep_rw is set to %s; should be %s\n", + value, "false"); + } + } + else if (!strcmp("ind_rd_buffer_size", key)) { + if (atoi(value) != 2097152) { + errs++; + if (verbose) fprintf(stderr, "ind_rd_buffer_size is %d; should be %d\n", + atoi(value), 2097152); + } + } + else if (!strcmp("ind_wr_buffer_size", key)) { + if (atoi(value) != 1048576) { + errs++; + if (verbose) fprintf(stderr, "ind_wr_buffer_size is %d; should be %d\n", + atoi(value), 1048576); + } + } + else if (!strcmp("romio_ds_read", key)) { + if (strcmp("automatic", value)) { + errs++; + if (verbose) fprintf(stderr, "romio_ds_read is set to %s; should be %s\n", + value, "automatic"); + } + } + else if (!strcmp("romio_ds_write", key)) { + /* Unreliable test -- value is file system dependent. Ignore. */ + } + else if (!strcmp("cb_config_list", key)) { +#ifndef SKIP_CB_CONFIG_LIST_TEST + if (strcmp("*:*", value)) { + errs++; + if (verbose) fprintf(stderr, "cb_config_list is set to %s; should be %s\n", + value, "*:*"); + } +#endif + } + else if (!strcmp("romio_cb_pfr", key)) { + if(strcmp("disable", value)) { + errs++; + if (verbose) fprintf(stderr, "romio_cb_pfr is set to %s; should be %s\n", + value, "automatic"); + } + } + else if (!strcmp("romio_cb_fr_types", key)) { + if(strcmp("aar", value)) { + errs++; + if (verbose) fprintf(stderr, "romio_cb_fr_types is set to %s; should be %s\n", + value, "aar"); + } + } + else if (!strcmp("romio_cb_fr_alignment", key)) { + if(strcmp("1", value)) { + errs++; + if (verbose) fprintf(stderr, "romio_cb_fr_alignment is set to %s; should be %s\n", + value, "1"); + } + } + else if (!strcmp("romio_cb_ds_threshold", key)) { + if(strcmp("0", value)) { + errs++; + if (verbose) fprintf(stderr, "romio_cb_ds_threshold is set to %s; should be %s\n", + value, "0"); + } + } + else if (!strcmp("romio_cb_alltoall", key)) { + if(strcmp("automatic", value)) { + errs++; + if (verbose) fprintf(stderr, "romio_cb_alltoall is set to %s; should be %s\n", + value, "automatic"); + } + } + + else { + if (verbose) fprintf(stderr, "unexpected key %s (not counted as an error)\n", key); + } + } + + /* Q: SHOULD WE BOTHER LOOKING AT THE OTHER PROCESSES? */ + if (!mynod) { + if (errs) fprintf(stderr, "Found %d errors.\n", errs); + else printf(" No Errors\n"); + } + + MPI_File_close(&fh); + free(filename); + MPI_Info_free(&info_used); + MPI_Info_free(&info); + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/fmisc.f.in b/ompi/mca/io/romio314/romio/test/fmisc.f.in new file mode 100644 index 0000000000..5bfaa038b2 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/fmisc.f.in @@ -0,0 +1,205 @@ +! -*- Mode: Fortran; -*- +! +! (C) 2001 by Argonne National Laboratory. +! See COPYRIGHT in top-level directory. +! + program main + implicit none + + include 'mpif.h' + @F77MPIOINC@ + +! Fortran equivalent of misc.c +! tests various miscellaneous functions. + + integer buf(1024), amode, fh, status(MPI_STATUS_SIZE) + logical flag + integer ierr, newtype, i, group + integer etype, filetype, mynod, argc, iargc + integer errs, toterrs + logical verbose + character*7 datarep + character*1024 str ! used to store the filename + @FORTRAN_MPI_OFFSET@ disp, offset, filesize + @FTESTDEFINE@ + + errs = 0 + verbose = .false. + call MPI_INIT(ierr) + call MPI_COMM_RANK(MPI_COMM_WORLD, mynod, ierr) + +! process 0 takes the file name as a command-line argument and +! broadcasts it to other processes + + if (mynod .eq. 0) then + argc = @F77IARGC@ + i = 0 + @F77GETARG@ + do while ((i .lt. argc) .and. (str .ne. '-fname')) + i = i + 1 + @F77GETARG@ + end do + if (i .ge. argc) then + print * + print *, '*# Usage: fmisc -fname filename' + print * + call MPI_ABORT(MPI_COMM_WORLD, 1, ierr) + end if + + i = i + 1 + @F77GETARG@ + call MPI_BCAST(str, 1024, MPI_CHARACTER, 0, & + & MPI_COMM_WORLD, ierr) + else + call MPI_BCAST(str, 1024, MPI_CHARACTER, 0, & + & MPI_COMM_WORLD, ierr) + end if + + + call MPI_FILE_OPEN(MPI_COMM_WORLD, str, & + & MPI_MODE_CREATE + MPI_MODE_RDWR, MPI_INFO_NULL, fh, ierr) + + call MPI_FILE_WRITE(fh, buf, 1024, MPI_INTEGER, status, ierr) + + call MPI_FILE_SYNC(fh, ierr) + + call MPI_FILE_GET_AMODE(fh, amode, ierr) + if (mynod .eq. 0 .and. verbose) then + print *, ' testing MPI_FILE_GET_AMODE' + end if + if (amode .ne. (MPI_MODE_CREATE + MPI_MODE_RDWR)) then + errs = errs + 1 + print *, 'amode is ', amode, ', should be ', MPI_MODE_CREATE & + & + MPI_MODE_RDWR + end if + + call MPI_FILE_GET_ATOMICITY(fh, flag, ierr) + if (flag) then + errs = errs + 1 + print *, 'atomicity is ', flag, ', should be .FALSE.' + end if + if (mynod .eq. 0 .and. verbose) then + print *, ' setting atomic mode' + end if + call MPI_FILE_SET_ATOMICITY(fh, .TRUE., ierr) + call MPI_FILE_GET_ATOMICITY(fh, flag, ierr) + if (.not. flag) then + errs = errs + 1 + print *, 'atomicity is ', flag, ', should be .TRUE.' + end if + call MPI_FILE_SET_ATOMICITY(fh, .FALSE., ierr) + if (mynod .eq. 0 .and. verbose) then + print *, ' reverting back to nonatomic mode' + end if + + call MPI_TYPE_VECTOR(10, 10, 20, MPI_INTEGER, newtype, ierr) + call MPI_TYPE_COMMIT(newtype, ierr) + + disp = 1000 + call MPI_FILE_SET_VIEW(fh, disp, MPI_INTEGER, newtype, 'native', & + & MPI_INFO_NULL, ierr) + if (mynod .eq. 0 .and. verbose) then + print *, ' testing MPI_FILE_GET_VIEW' + end if + + disp = 0 + call MPI_FILE_GET_VIEW(fh, disp, etype, filetype, datarep, ierr) + if ((disp .ne. 1000) .or. (datarep .ne. 'native')) then + errs = errs + 1 + print *, 'disp = ', disp, ', datarep = ', datarep, & + & ', should be 1000, native' + end if + + if (mynod .eq. 0 .and. verbose) then + print *, ' testing MPI_FILE_GET_BYTE_OFFSET' + end if + offset = 10 + call MPI_FILE_GET_BYTE_OFFSET(fh, offset, disp, ierr) + if (disp .ne. 1080) then + errs = errs + 1 + print *, 'byte offset = ', disp, ', should be 1080' + end if + + call MPI_FILE_GET_GROUP(fh, group, ierr) + + if (mynod .eq. 0 .and. verbose) then + print *, ' setting file size to 1060 bytes' + end if + filesize = 1060 + call MPI_FILE_SET_SIZE(fh, filesize, ierr) + call MPI_BARRIER(MPI_COMM_WORLD, ierr) + call MPI_FILE_SYNC(fh, ierr) + filesize = 0 + call MPI_FILE_GET_SIZE(fh, filesize, ierr) + if (filesize .ne. 1060) then + errs = errs + 1 + print *, 'file size = ', filesize, ', should be 1060' + end if + + if (mynod .eq. 0 .and. verbose) then + print *, ' seeking to eof and testing MPI_FILE_GET_POSITION' + end if + offset = 0 + call MPI_FILE_SEEK(fh, offset, MPI_SEEK_END, ierr) + call MPI_FILE_GET_POSITION(fh, offset, ierr) + if (offset .ne. 10) then + errs = errs + 1 + print *, 'file pointer posn = ', offset, ', should be 10' + end if + + if (mynod .eq. 0 .and. verbose) then + print *, ' testing MPI_FILE_GET_BYTE_OFFSET' + end if + call MPI_FILE_GET_BYTE_OFFSET(fh, offset, disp, ierr) + if (disp .ne. 1080) then + errs = errs + 1 + print *, 'byte offset = ', disp, ', should be 1080' + end if + call MPI_BARRIER(MPI_COMM_WORLD, ierr) + + if (mynod .eq. 0 .and. verbose) then + print *, ' testing MPI_FILE_SEEK with MPI_SEEK_CUR' + end if + offset = -10 + call MPI_FILE_SEEK(fh, offset, MPI_SEEK_CUR, ierr) + call MPI_FILE_GET_POSITION(fh, offset, ierr) + call MPI_FILE_GET_BYTE_OFFSET(fh, offset, disp, ierr) + if (disp .ne. 1000) then + errs = errs + 1 + print *, 'file pointer posn in bytes = ', disp, & + & ', should be 1000' + end if + + if (mynod .eq. 0 .and. verbose) then + print *, ' preallocating disk space up to 8192 bytes' + end if + filesize = 8192 + call MPI_FILE_PREALLOCATE(fh, filesize, ierr) + + if (mynod .eq. 0 .and. verbose) then + print *, ' closing the file and deleting it' + end if + call MPI_FILE_CLOSE(fh, ierr) + + call MPI_BARRIER(MPI_COMM_WORLD, ierr) + if (mynod .eq. 0) then + call MPI_FILE_DELETE(str, MPI_INFO_NULL, ierr) + end if + + call MPI_Allreduce( errs, toterrs, 1, MPI_INTEGER, MPI_SUM, & + $ MPI_COMM_WORLD, ierr ) + if (mynod .eq. 0) then + if( toterrs .gt. 0 ) then + print *, 'Found ', toterrs, ' errors' + else + print *, ' No Errors' + endif + endif + + call MPI_TYPE_FREE(newtype, ierr) + call MPI_TYPE_FREE(filetype, ierr) + call MPI_GROUP_FREE(group, ierr) + call MPI_FINALIZE(ierr) + + stop + end diff --git a/ompi/mca/io/romio314/romio/test/fperf.f.in b/ompi/mca/io/romio314/romio/test/fperf.f.in new file mode 100644 index 0000000000..e4ff4d15eb --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/fperf.f.in @@ -0,0 +1,180 @@ +! -*- Mode: Fortran; -*- +! +! (C) 2001 by Argonne National Laboratory. +! See COPYRIGHT in top-level directory. +! + program main + implicit none + + include 'mpif.h' + @F77MPIOINC@ + +! Fortran equivalent of perf.c + + integer SIZE + parameter (SIZE=1048576*4) +! read/write size per node in bytes + + integer buf(SIZE/4), j, mynod, nprocs, ntimes, flag + double precision stim, read_tim, write_tim, new_read_tim + double precision new_write_tim, min_read_tim, min_write_tim + double precision read_bw, write_bw + integer fh, status(MPI_STATUS_SIZE), ierr, argc, iargc, i + character*1024 str ! used to store the filename + @FORTRAN_MPI_OFFSET@ offset + @FTESTDEFINE@ + + ntimes = 5 + min_read_tim = 10000000.0D0 + min_write_tim = 10000000.0D0 + + call MPI_INIT(ierr) + call MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr) + call MPI_COMM_RANK(MPI_COMM_WORLD, mynod, ierr) + +! process 0 takes the file name as a command-line argument and +! broadcasts it to other processes + + if (mynod .eq. 0) then + argc = @F77IARGC@ + i = 0 + @F77GETARG@ + do while ((i .lt. argc) .and. (str .ne. '-fname')) + i = i + 1 + @F77GETARG@ + end do + if (i .ge. argc) then + print * + print *, '*# Usage: fperf -fname filename' + print * + call MPI_ABORT(MPI_COMM_WORLD, 1, ierr) + end if + + i = i + 1 + @F77GETARG@ + call MPI_BCAST(str, 1024, MPI_CHARACTER, 0, & + & MPI_COMM_WORLD, ierr) + print *, 'Access size per process = ', SIZE, ' bytes', & + & ', ntimes = ', ntimes + else + call MPI_BCAST(str, 1024, MPI_CHARACTER, 0, & + & MPI_COMM_WORLD, ierr) + end if + + + offset = mynod*SIZE + do j=1, ntimes + call MPI_FILE_OPEN(MPI_COMM_WORLD, str, & + & MPI_MODE_CREATE+MPI_MODE_RDWR, MPI_INFO_NULL, fh, ierr) + + call MPI_FILE_SEEK(fh, offset, MPI_SEEK_SET, ierr) + + call MPI_BARRIER(MPI_COMM_WORLD, ierr) + stim = MPI_WTIME() + call MPI_FILE_WRITE(fh, buf, SIZE, MPI_BYTE, status, ierr) + write_tim = MPI_WTIME() - stim + + call MPI_FILE_CLOSE(fh, ierr) + + call MPI_BARRIER(MPI_COMM_WORLD, ierr) + + call MPI_FILE_OPEN(MPI_COMM_WORLD, str, & + & MPI_MODE_CREATE+MPI_MODE_RDWR, MPI_INFO_NULL, fh, ierr) + + call MPI_FILE_SEEK(fh, offset, MPI_SEEK_SET, ierr) + + call MPI_BARRIER(MPI_COMM_WORLD, ierr) + stim = MPI_WTIME() + call MPI_FILE_READ(fh, buf, SIZE, MPI_BYTE, status, ierr) + read_tim = MPI_WTIME() - stim + + call MPI_FILE_CLOSE(fh, ierr) + + call MPI_ALLREDUCE(write_tim, new_write_tim, 1, & + & MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_WORLD, ierr) + call MPI_ALLREDUCE(read_tim, new_read_tim, 1, & + & MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_WORLD, ierr) + + if (new_read_tim .lt. min_read_tim) then + min_read_tim = new_read_tim + end if + if (new_write_tim .lt. min_write_tim) then + min_write_tim = new_write_tim + end if + end do + + if (mynod .eq. 0) then + read_bw = (SIZE*nprocs*1.0D0)/(min_read_tim*1000000.0D0) + write_bw = (SIZE*nprocs*1.0D0)/(min_write_tim*1000000.0D0) + print *, 'Write bandwidth without file sync = ', & + & write_bw, ' Mbytes/sec' + print *, 'Read bandwidth without prior file sync = ', & + & read_bw, ' Mbytes/sec' + end if + + min_read_tim = 10000000.0D0 + min_write_tim = 10000000.0D0 + + flag = 0 + do j=1, ntimes + call MPI_FILE_OPEN(MPI_COMM_WORLD, str, & + & MPI_MODE_CREATE+MPI_MODE_RDWR, MPI_INFO_NULL, fh, ierr) + + call MPI_FILE_SEEK(fh, offset, MPI_SEEK_SET, ierr) + + call MPI_BARRIER(MPI_COMM_WORLD, ierr) + stim = MPI_WTIME() + call MPI_FILE_WRITE(fh, buf, SIZE, MPI_BYTE, status, ierr) + call MPI_FILE_SYNC(fh, ierr) + write_tim = MPI_WTIME() - stim + if (ierr .eq. MPI_ERR_UNKNOWN) then + flag = 1 + end if + + call MPI_FILE_CLOSE(fh, ierr) + + call MPI_BARRIER(MPI_COMM_WORLD, ierr) + + call MPI_FILE_OPEN(MPI_COMM_WORLD, str, & + & MPI_MODE_CREATE+MPI_MODE_RDWR, MPI_INFO_NULL, fh, ierr) + + call MPI_FILE_SEEK(fh, offset, MPI_SEEK_SET, ierr) + + call MPI_BARRIER(MPI_COMM_WORLD, ierr) + stim = MPI_WTIME() + call MPI_FILE_READ(fh, buf, SIZE, MPI_BYTE, status, ierr) + read_tim = MPI_WTIME() - stim + + call MPI_FILE_CLOSE(fh, ierr) + + call MPI_ALLREDUCE(write_tim, new_write_tim, 1, & + & MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_WORLD, ierr) + call MPI_ALLREDUCE(read_tim, new_read_tim, 1, & + & MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_WORLD, ierr) + + if (new_read_tim .lt. min_read_tim) then + min_read_tim = new_read_tim + end if + if (new_write_tim .lt. min_write_tim) then + min_write_tim = new_write_tim + end if + + end do + + if (mynod .eq. 0) then + if (flag .eq. 1) then + print *, 'MPI_FILE_SYNC returns error.' + else + read_bw = (SIZE*nprocs*1.0D0)/(min_read_tim*1000000.0D0) + write_bw = (SIZE*nprocs*1.0D0)/(min_write_tim*1000000.0D0) + print *, 'Write bandwidth including file sync = ', & + & write_bw, ' Mbytes/sec' + print *, 'Read bandwidth after file sync = ', & + & read_bw, ' Mbytes/sec' + end if + end if + + call MPI_FINALIZE(ierr) + + stop + end diff --git a/ompi/mca/io/romio314/romio/test/hindexed.c b/ompi/mca/io/romio314/romio/test/hindexed.c new file mode 100644 index 0000000000..ebc0ae81c6 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/hindexed.c @@ -0,0 +1,260 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +/* Wei-keng Liao (wkliao@ece.northwestern.edu) September 8, 2008 */ +#include +#include +#include +#include + +#define YLEN 5 +#define XLEN 10 +#define SUB_XLEN 3 + +/* rjl: I was just too lazy to compute this at run-time */ +char compare_buf[XLEN*4][YLEN*4] = { + {'0','1','2',0,0,'3','4','5',0,0,'D','E','F',0,0,'G','H','I'}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {'6','7','8',0,0,'9',':',';',0,0,'J','K','L',0,0,'M','N','O'}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {'X','Y','Z',0,0,'[','\\',']',0,0,'l','m','n',0,0,'o','p','q'}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {'^','_','`',0,0,'a','b','c',0,0,'r','s','t',0,0,'u','v','w'}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {'0','1','2',0,0,'3','4','5',0,0,'D','E','F',0,0,'G','H','I'}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {'6','7','8',0,0,'9',':',';',0,0,'J','K','L',0,0,'M','N','O'}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {'X','Y','Z',0,0,'[','\\',']',0,0,'l','m','n',0,0,'o','p','q'}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {'^','_','`',0,0,'a','b','c',0,0,'r','s','t',0,0,'u','v','w'}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} +}; + + +/* set this if you want a dump of the global array +#define VERBOSE 1 +*/ + +/*----< main() >------------------------------------------------------------*/ +int main(int argc, char **argv) { + int i, j, err, rank, np, num_io; + char *buf, *filename; + int rank_dim[2], array_of_sizes[2]; + int array_of_subsizes[2]; + int count, *blocklengths, global_array_size; + MPI_Count ftype_size; + MPI_Aint *displacements; + MPI_File fh; + MPI_Datatype ftype; + MPI_Status status; + MPI_Offset offset=0; + int nr_errors=0; +#ifdef VERBOSE + int k; +#endif + + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &np); + + if (np != 4) { + if (!rank) printf("Please run with 4 processes. Exiting ...\n\n"); + MPI_Finalize(); + return 1; + } + + filename = argv[1]; + + num_io = 2; + + /*-----------------------------------------------------------------------*/ + /* process rank in each dimension */ + rank_dim[0] = rank / 2; + rank_dim[1] = rank % 2; + + /* global 2D array size */ + array_of_sizes[0] = YLEN * 2; + array_of_sizes[1] = XLEN * 2; + + global_array_size = array_of_sizes[0] * array_of_sizes[1]; + + array_of_subsizes[0] = YLEN / 2; + array_of_subsizes[1] = XLEN * SUB_XLEN / 5; + + offset = rank_dim[0] * YLEN * array_of_sizes[1] + + rank_dim[1] * XLEN; + + /* define data type for file view */ + count = array_of_subsizes[0] * 2; /* 2 is the no. blocks along X */ + blocklengths = (int*) malloc(count*sizeof(int)); + displacements = (MPI_Aint*)malloc(count*sizeof(MPI_Aint)); + for (i=0; i0 && j%XLEN==0) printf(" "); + if (*ptr != 0) + printf(" %c",*ptr); + else + printf(" "); + ptr++; + } + printf("\n"); + } + printf("\n"); + } +#endif + ptr = rd_buf; + for(i=0; i<2*YLEN*num_io; i++) { + for(j=0; j<2*XLEN; j++) { + if( *ptr != compare_buf[i][j]) { + fprintf(stderr, "expected %d got %d at [%d][%d]\n", + *ptr, compare_buf[i][j], i, j); + nr_errors++; + } + ptr++; + } + } + free(rd_buf); + + if (nr_errors == 0) + fprintf(stdout, " No Errors\n"); + else + fprintf(stderr, "Found %d errors\n", nr_errors); + } + + free(blocklengths); + free(displacements); + free(buf); + MPI_Type_free(&ftype); + MPI_Finalize(); + return 0; +} + +/* command-line outputs are: (the global array is written twice) + +% mpiexec -n 4 wkl_subarray +------------------------------------------------------- + [ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 ] + +[ 0] 0 1 2 3 4 5 D E F G H I +[ 1] +[ 2] 6 7 8 9 : ; J K L M N O +[ 3] +[ 4] +[ 5] X Y Z [ \ ] l m n o p q +[ 6] +[ 7] ^ _ ` a b c r s t u v w +[ 8] +[ 9] + +[10] 0 1 2 3 4 5 D E F G H I +[11] +[12] 6 7 8 9 : ; J K L M N O +[13] +[14] +[15] X Y Z [ \ ] l m n o p q +[16] +[17] ^ _ ` a b c r s t u v w +[18] +[19] + +*/ + diff --git a/ompi/mca/io/romio314/romio/test/i_noncontig.c b/ompi/mca/io/romio314/romio/test/i_noncontig.c new file mode 100644 index 0000000000..db5bd36f0f --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/i_noncontig.c @@ -0,0 +1,267 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* tests noncontiguous reads/writes using nonblocking I/O */ + +#define SIZE 5000 + +#define VERBOSE 0 + +int main(int argc, char **argv) +{ + int *buf, i, mynod, nprocs, len, b[3]; + int errs=0, toterrs; + MPI_Aint d[3]; + MPI_File fh; + MPI_Status status; + char *filename; + MPI_Datatype typevec, newtype, t[3]; + MPIO_Request req; + + MPI_Init(&argc,&argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + + if (nprocs != 2) { + fprintf(stderr, "Run this program on two processes\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: i_noncontig -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + buf = (int *) malloc(SIZE*sizeof(int)); + + MPI_Type_vector(SIZE/2, 1, 2, MPI_INT, &typevec); + + b[0] = b[1] = b[2] = 1; + d[0] = 0; + d[1] = mynod*sizeof(int); + d[2] = SIZE*sizeof(int); + t[0] = MPI_LB; + t[1] = typevec; + t[2] = MPI_UB; + + MPI_Type_struct(3, b, d, t, &newtype); + MPI_Type_commit(&newtype); + MPI_Type_free(&typevec); + + if (!mynod) { +#if VERBOSE + fprintf(stderr, "\ntesting noncontiguous in memory, noncontiguous in file using nonblocking I/O\n"); +#endif + MPI_File_delete(filename, MPI_INFO_NULL); + } + MPI_Barrier(MPI_COMM_WORLD); + + MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | + MPI_MODE_RDWR, MPI_INFO_NULL, &fh); + + MPI_File_set_view(fh, 0, MPI_INT, newtype, "native", MPI_INFO_NULL); + + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + MPI_Type_free(&newtype); + free(buf); + free(filename); + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/large_array.c b/ompi/mca/io/romio314/romio/test/large_array.c new file mode 100644 index 0000000000..617c895dc9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/large_array.c @@ -0,0 +1,145 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* Writes a 4-Gbyte distributed array, reads it back, and then deletes the + file. Uses collective I/O. */ +/* The file name is taken as a command-line argument. */ +/* Run it only on a machine with sufficient memory and a file system + on which ROMIO supports large files, i.e., PIOFS, XFS, SFS, and HFS */ + +/* This program will work only if the MPI implementation defines MPI_Aint + as a 64-bit integer. */ + +int main(int argc, char **argv) +{ + MPI_Datatype newtype; + int i, ndims, array_of_gsizes[3], array_of_distribs[3]; + int order, nprocs, len, flag, err; + int array_of_dargs[3], array_of_psizes[3]; + int *readbuf, *writebuf, mynod; + MPI_Count bufcount; + char filename[1024]; + MPI_File fh; + MPI_Status status; + MPI_Aint size_with_aint; + MPI_Offset size_with_offset; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: large_array -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + fprintf(stderr, "This program creates a 4 Gbyte file. Don't run it if you don't have that much disk space!\n"); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + +/* create the distributed array filetype */ + ndims = 3; + order = MPI_ORDER_C; + + array_of_gsizes[0] = 1024; + array_of_gsizes[1] = 1024; + array_of_gsizes[2] = 4*1024/sizeof(int); + + array_of_distribs[0] = MPI_DISTRIBUTE_BLOCK; + array_of_distribs[1] = MPI_DISTRIBUTE_BLOCK; + array_of_distribs[2] = MPI_DISTRIBUTE_BLOCK; + + array_of_dargs[0] = MPI_DISTRIBUTE_DFLT_DARG; + array_of_dargs[1] = MPI_DISTRIBUTE_DFLT_DARG; + array_of_dargs[2] = MPI_DISTRIBUTE_DFLT_DARG; + + for (i=0; i +#include +#include + +/* writes a file of size 4 Gbytes and reads it back. + should be run on one process only*/ +/* The file name is taken as a command-line argument. */ +/* Can be used only on file systems on which ROMIO supports large files, + i.e., PIOFS, XFS, SFS, and HFS. */ + +#define SIZE 1048576*4 /* no. of long longs in each write/read */ +#define NTIMES 128 /* no. of writes/reads */ + +int main(int argc, char **argv) +{ + MPI_File fh; + MPI_Status status; + MPI_Offset size; + long long *buf, i; + char *filename; + int j, mynod, nprocs, len, flag, err; + + MPI_Init(&argc,&argv); + + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + + if (nprocs != 1) { + fprintf(stderr, "Run this program on one process only\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: large -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + fprintf(stderr, "This program creates an 4 Gbyte file. Don't run it if you don't have that much disk space!\n"); + + buf = (long long *) malloc(SIZE * sizeof(long long)); + if (!buf) { + fprintf(stderr, "not enough memory to allocate buffer\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + MPI_File_open(MPI_COMM_SELF, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, + MPI_INFO_NULL, &fh); + + for (i=0; i +#include +#include + +/* tests various miscellaneous functions. */ +#define VERBOSE 0 + +static void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); +} + +int main(int argc, char **argv) +{ + int buf[1024], amode, flag, mynod, len, i; + int errs = 0, toterrs; + MPI_File fh; + MPI_Status status; + MPI_Datatype newtype; + MPI_Offset disp, offset; + MPI_Group group; + MPI_Datatype etype, filetype; + char datarep[25], *filename; + int errcode=0; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: misc -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + + errcode = MPI_File_open(MPI_COMM_WORLD, filename, + MPI_MODE_CREATE | MPI_MODE_RDWR, MPI_INFO_NULL, &fh); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_open"); + } + + errcode = MPI_File_write(fh, buf, 1024, MPI_INT, &status); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_write"); + } + + errcode = MPI_File_sync(fh); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_sync"); + } + + errcode = MPI_File_get_amode(fh, &amode); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_amode"); + } +#if VERBOSE + if (!mynod) fprintf(stderr, "testing MPI_File_get_amode\n"); +#endif + if (amode != (MPI_MODE_CREATE | MPI_MODE_RDWR)) { + errs++; + fprintf(stderr, "amode is %d, should be %d\n\n", + amode, MPI_MODE_CREATE | MPI_MODE_RDWR); + } + + errcode = MPI_File_get_atomicity(fh, &flag); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_atomicity"); + } + if (flag) { + errs++; + fprintf(stderr, "atomicity is %d, should be 0\n", flag); + } +#if VERBOSE + if (!mynod) fprintf(stderr, "setting atomic mode\n"); +#endif + errcode = MPI_File_set_atomicity(fh, 1); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_set_atomicity"); + } + errcode = MPI_File_get_atomicity(fh, &flag); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_atomicity"); + } + if (!flag) { + errs++; + fprintf(stderr, "atomicity is %d, should be 1\n", flag); + } + errcode = MPI_File_set_atomicity(fh, 0); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_set_atomicity"); + } +#if VERBOSE + if (!mynod) fprintf(stderr, "reverting back to nonatomic mode\n"); +#endif + + MPI_Type_vector(10, 10, 20, MPI_INT, &newtype); + MPI_Type_commit(&newtype); + + errcode = MPI_File_set_view(fh, 1000, MPI_INT, newtype, "native", MPI_INFO_NULL); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_set_view"); + } +#if VERBOSE + if (!mynod) fprintf(stderr, "testing MPI_File_get_view\n"); +#endif + errcode = MPI_File_get_view(fh, &disp, &etype, &filetype, datarep); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_view"); + } + if ((disp != 1000) || strcmp(datarep, "native")) { + errs++; + fprintf(stderr, "disp = %@LL@, datarep = %s, should be 1000, native\n\n", disp, datarep); + } +#if VERBOSE + if (!mynod) fprintf(stderr, "testing MPI_File_get_byte_offset\n"); +#endif + errcode = MPI_File_get_byte_offset(fh, 10, &disp); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_byte_offset"); + } + if (disp != (1000+20*sizeof(int))) { + errs++; + fprintf(stderr, "byte offset = %@LL@, should be %d\n\n", + disp, (int) (1000+20*sizeof(int))); + } + + errcode = MPI_File_get_group(fh, &group); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_group"); + } + +#if VERBOSE + if (!mynod) fprintf(stderr, "testing MPI_File_set_size\n"); +#endif + errcode = MPI_File_set_size(fh, 1000+15*sizeof(int)); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_set_size"); + } + MPI_Barrier(MPI_COMM_WORLD); + errcode = MPI_File_sync(fh); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_sync"); + } + errcode = MPI_File_get_size(fh, &disp); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_size"); + } + if (disp != 1000+15*sizeof(int)) { + errs++; + fprintf(stderr, "file size = %@LL@, should be %d\n\n", + disp, (int) (1000+15*sizeof(int))); + } + +#if VERBOSE + if (!mynod) fprintf(stderr, "seeking to eof and testing MPI_File_get_position\n"); +#endif + errcode = MPI_File_seek(fh, 0, MPI_SEEK_END); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_seek"); + } + errcode = MPI_File_get_position(fh, &disp); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_position"); + } + if (disp != 10) { + errs++; + fprintf(stderr, "file pointer posn = %@LL@, should be 10\n\n", disp); + } + +#if VERBOSE + if (!mynod) fprintf(stderr, "testing MPI_File_get_byte_offset\n"); +#endif + errcode = MPI_File_get_byte_offset(fh, disp, &offset); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_byte_offset"); + } + if (offset != (1000+20*sizeof(int))) { + errs++; + fprintf(stderr, "byte offset = %@LL@, should be %d\n\n", + offset, (int) (1000+20*sizeof(int))); + } + MPI_Barrier(MPI_COMM_WORLD); + +#if VERBOSE + if (!mynod) fprintf(stderr, "testing MPI_File_seek with MPI_SEEK_CUR\n"); +#endif + errcode = MPI_File_seek(fh, -10, MPI_SEEK_CUR); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_seek"); + } + errcode = MPI_File_get_position(fh, &disp); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_position"); + } + errcode = MPI_File_get_byte_offset(fh, disp, &offset); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_get_byte_offset"); + } + if (offset != 1000) { + errs++; + fprintf(stderr, "file pointer posn in bytes = %@LL@, should be 1000\n\n", offset); + } + +#if VERBOSE + if (!mynod) fprintf(stderr, "preallocating disk space up to 8192 bytes\n"); +#endif + errcode = MPI_File_preallocate(fh, 8192); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_Preallocate"); + } + +#if VERBOSE + if (!mynod) fprintf(stderr, "closing the file and deleting it\n"); +#endif + MPI_File_close(&fh); + + MPI_Barrier(MPI_COMM_WORLD); + if (!mynod) MPI_File_delete(filename, MPI_INFO_NULL); + + MPI_Allreduce( &errs, &toterrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD ); + if (mynod == 0) { + if( toterrs > 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + MPI_Type_free(&newtype); + MPI_Type_free(&filetype); + MPI_Group_free(&group); + free(filename); + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/noncontig.c b/ompi/mca/io/romio314/romio/test/noncontig.c new file mode 100644 index 0000000000..8be18dc670 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/noncontig.c @@ -0,0 +1,267 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* tests noncontiguous reads/writes using independent I/O */ + +#define SIZE 5000 + +#define VERBOSE 0 +int main(int argc, char **argv) +{ + int *buf, i, mynod, nprocs, len, b[3]; + int errs=0, toterrs; + MPI_Aint d[3]; + MPI_File fh; + MPI_Status status; + char *filename; + MPI_Datatype typevec, newtype, t[3]; + MPI_Info info; + + MPI_Init(&argc,&argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + + if (nprocs != 2) { + fprintf(stderr, "Run this program on two processes\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes (length first, then string) */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: noncontig -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + buf = (int *) malloc(SIZE*sizeof(int)); + + MPI_Type_vector(SIZE/2, 1, 2, MPI_INT, &typevec); + + /* create a struct type with explicitly set LB and UB; displacements + * of typevec are such that the types for the two processes won't + * overlap. + */ + b[0] = b[1] = b[2] = 1; + d[0] = 0; + d[1] = mynod*sizeof(int); + d[2] = SIZE*sizeof(int); + t[0] = MPI_LB; + t[1] = typevec; + t[2] = MPI_UB; + + /* keep the struct, ditch the vector */ + MPI_Type_struct(3, b, d, t, &newtype); + MPI_Type_commit(&newtype); + MPI_Type_free(&typevec); + + MPI_Info_create(&info); + /* I am setting these info values for testing purposes only. It is + better to use the default values in practice. */ + MPI_Info_set(info, "ind_rd_buffer_size", "1209"); + MPI_Info_set(info, "ind_wr_buffer_size", "1107"); + + if (!mynod) { +#if VERBOSE + fprintf(stderr, "\ntesting noncontiguous in memory, noncontiguous in file using independent I/O\n"); +#endif + MPI_File_delete(filename, MPI_INFO_NULL); + } + MPI_Barrier(MPI_COMM_WORLD); + + MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, + info, &fh); + + /* set the file view for each process -- now writes go into the non- + * overlapping but interleaved region defined by the struct type up above + */ + MPI_File_set_view(fh, 0, MPI_INT, newtype, "native", info); + + /* fill our buffer with a pattern and write, using our type again */ + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + MPI_Type_free(&newtype); + MPI_Info_free(&info); + free(buf); + free(filename); + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/noncontig_coll.c b/ompi/mca/io/romio314/romio/test/noncontig_coll.c new file mode 100644 index 0000000000..2916776a63 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/noncontig_coll.c @@ -0,0 +1,236 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* tests noncontiguous reads/writes using collective I/O */ + +#define SIZE 5000 + +#define VERBOSE 0 +int main(int argc, char **argv) +{ + int *buf, i, mynod, nprocs, len, b[3]; + int errs=0, toterrs; + MPI_Aint d[3]; + MPI_File fh; + MPI_Status status; + char *filename; + MPI_Datatype typevec, newtype, t[3]; + + MPI_Init(&argc,&argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + + if (nprocs != 2) { + fprintf(stderr, "Run this program on two processes\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: noncontig_coll -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + buf = (int *) malloc(SIZE*sizeof(int)); + + MPI_Type_vector(SIZE/2, 1, 2, MPI_INT, &typevec); + + b[0] = b[1] = b[2] = 1; + d[0] = 0; + d[1] = mynod*sizeof(int); + d[2] = SIZE*sizeof(int); + t[0] = MPI_LB; + t[1] = typevec; + t[2] = MPI_UB; + + MPI_Type_struct(3, b, d, t, &newtype); + MPI_Type_commit(&newtype); + MPI_Type_free(&typevec); + + if (!mynod) { +#if VERBOSE + fprintf(stderr, "\ntesting noncontiguous in memory, noncontiguous in file using collective I/O\n"); +#endif + MPI_File_delete(filename, MPI_INFO_NULL); + } + MPI_Barrier(MPI_COMM_WORLD); + + MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, + MPI_INFO_NULL, &fh); + + MPI_File_set_view(fh, 0, MPI_INT, newtype, "native", MPI_INFO_NULL); + + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + + MPI_Type_free(&newtype); + free(buf); + free(filename); + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/noncontig_coll2.c b/ompi/mca/io/romio314/romio/test/noncontig_coll2.c new file mode 100644 index 0000000000..4699da89ac --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/noncontig_coll2.c @@ -0,0 +1,539 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* tests noncontiguous reads/writes using collective I/O */ + +/* this test is almost exactly like noncontig_coll.c with the following changes: + * + * . generalized file writing/reading to handle arbitrary number of processors + * . provides the "cb_config_list" hint with several permutations of the + * avaliable processors. + * [ makes use of code copied from ROMIO's ADIO code to collect the names of + * the processors ] + */ + +/* we are going to muck with this later to make it evenly divisible by however many compute nodes we have */ +#define STARTING_SIZE 5000 + +int test_file(char *filename, int mynod, int nprocs, char * cb_hosts, + const char *msg, int verbose); + +#define ADIOI_Free free +#define ADIOI_Malloc malloc +#define FPRINTF fprintf +/* I have no idea what the "D" stands for; it's how things are done in adio.h + */ +struct ADIO_cb_name_arrayD { + int refct; + int namect; + char **names; +}; +typedef struct ADIO_cb_name_arrayD *ADIO_cb_name_array; + +void handle_error(int errcode, const char *str); +int cb_gather_name_array(MPI_Comm comm, ADIO_cb_name_array *arrayp); +void default_str(int mynod, int len, ADIO_cb_name_array array, char *dest); +void reverse_str(int mynod, int len, ADIO_cb_name_array array, char *dest); +void reverse_alternating_str(int mynod, int len, ADIO_cb_name_array array, char *dest); +void simple_shuffle_str(int mynod, int len, ADIO_cb_name_array array, char *dest); + + +void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + + +/* cb_gather_name_array() - gather a list of processor names from all processes + * in a communicator and store them on rank 0. + * + * This is a collective call on the communicator(s) passed in. + * + * Obtains a rank-ordered list of processor names from the processes in + * "dupcomm". + * + * Returns 0 on success, -1 on failure. + * + * NOTE: Needs some work to cleanly handle out of memory cases! + */ +int cb_gather_name_array(MPI_Comm comm, ADIO_cb_name_array *arrayp) +{ + /* this is copied from ROMIO, but since this test is for correctness, + * not performance, note that we have removed the parts where ROMIO + * uses a keyval to cache the name array. We'll just rebuild it if we + * need to */ + + char my_procname[MPI_MAX_PROCESSOR_NAME], **procname = 0; + int *procname_len = NULL, my_procname_len, *disp = NULL, i; + int commsize, commrank; + ADIO_cb_name_array array = NULL; + + MPI_Comm_size(comm, &commsize); + MPI_Comm_rank(comm, &commrank); + + MPI_Get_processor_name(my_procname, &my_procname_len); + + /* allocate space for everything */ + array = (ADIO_cb_name_array) malloc(sizeof(*array)); + if (array == NULL) { + return -1; + } + array->refct = 1; + + if (commrank == 0) { + /* process 0 keeps the real list */ + array->namect = commsize; + + array->names = (char **) ADIOI_Malloc(sizeof(char *) * commsize); + if (array->names == NULL) { + return -1; + } + procname = array->names; /* simpler to read */ + + procname_len = (int *) ADIOI_Malloc(commsize * sizeof(int)); + if (procname_len == NULL) { + return -1; + } + } + else { + /* everyone else just keeps an empty list as a placeholder */ + array->namect = 0; + array->names = NULL; + } + /* gather lengths first */ + MPI_Gather(&my_procname_len, 1, MPI_INT, + procname_len, 1, MPI_INT, 0, comm); + + if (commrank == 0) { +#ifdef CB_CONFIG_LIST_DEBUG + for (i=0; i < commsize; i++) { + FPRINTF(stderr, "len[%d] = %d\n", i, procname_len[i]); + } +#endif + + for (i=0; i < commsize; i++) { + /* add one to the lengths because we need to count the + * terminator, and we are going to use this list of lengths + * again in the gatherv. + */ + procname_len[i]++; + procname[i] = malloc(procname_len[i]); + if (procname[i] == NULL) { + return -1; + } + } + + /* create our list of displacements for the gatherv. we're going + * to do everything relative to the start of the region allocated + * for procname[0] + * + * I suppose it is theoretically possible that the distance between + * malloc'd regions could be more than will fit in an int. We don't + * cover that case. + */ + disp = malloc(commsize * sizeof(int)); + disp[0] = 0; + for (i=1; i < commsize; i++) { + disp[i] = (int) (procname[i] - procname[0]); + } + + } + + /* now gather strings */ + if (commrank == 0) { + MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR, + procname[0], procname_len, disp, MPI_CHAR, + 0, comm); + } + else { + /* if we didn't do this, we would need to allocate procname[] + * on all processes...which seems a little silly. + */ + MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR, + NULL, NULL, NULL, MPI_CHAR, 0, comm); + } + + if (commrank == 0) { + /* no longer need the displacements or lengths */ + free(disp); + free(procname_len); + +#ifdef CB_CONFIG_LIST_DEBUG + for (i=0; i < commsize; i++) { + fprintf(stderr, "name[%d] = %s\n", i, procname[i]); + } +#endif + } + + *arrayp = array; + return 0; +} + +void default_str(int mynod, int len, ADIO_cb_name_array array, char *dest) +{ + char *ptr; + int i, p; + if (!mynod) { + ptr = dest; + for (i=0; inamect; i++ ) { + p = snprintf(ptr, len, "%s,", array->names[i]); + ptr += p; + } + /* chop off that last comma */ + dest[strlen(dest) - 1] = '\0'; + } + MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD); +} +void reverse_str(int mynod, int len, ADIO_cb_name_array array, char *dest) +{ + char *ptr; + int i, p; + if (!mynod) { + ptr = dest; + for (i=(array->namect - 1); i >= 0; i-- ) { + p = snprintf(ptr, len, "%s,", array->names[i]); + ptr += p; + } + dest[strlen(dest) - 1] = '\0'; + } + MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD); +} + +void reverse_alternating_str(int mynod, int len, ADIO_cb_name_array array, char *dest) +{ + char *ptr; + int i, p; + if (!mynod) { + ptr = dest; + /* evens */ + for (i=(array->namect - 1); i>= 0; i-=2 ) { + p = snprintf(ptr, len, "%s,", array->names[i]); + ptr += p; + } + /* odds */ + for (i=(array->namect - 2); i > 0; i-=2 ) { + p = snprintf(ptr, len, "%s,", array->names[i]); + ptr += p; + } + dest[strlen(dest) - 1] = '\0'; + } + MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD); +} + +void simple_shuffle_str(int mynod, int len, ADIO_cb_name_array array, char *dest) +{ + char *ptr; + int i, p; + if (!mynod) { + ptr = dest; + for (i=(array->namect / 2 ); i < array->namect; i++) { + p = snprintf(ptr, len, "%s,", array->names[i]); + ptr += p; + } + for (i=0; i < (array->namect / 2); i++ ) { + p = snprintf(ptr, len, "%s,", array->names[i]); + ptr += p; + } + dest[strlen(dest) - 1] = '\0'; + } + MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD); +} + +int main(int argc, char **argv) +{ + int i, mynod, nprocs, len, errs=0, sum_errs=0, verbose=0; + char *filename; + char * cb_config_string; + int cb_config_len; + ADIO_cb_name_array array; + + + MPI_Init(&argc,&argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + + + /* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + /* TODO: at some point, accept -v for verbose */ + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: noncontig_coll -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + /* want to hint the cb_config_list, but do so in a non-sequential way */ + cb_gather_name_array(MPI_COMM_WORLD, &array); + + /* sanity check */ + if (!mynod) { + if (array->namect < 2 ) { + fprintf(stderr, "Run this test on two or more hosts\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + } + /* get space for the permuted cb_config_string */ + if (!mynod) { + cb_config_len = 0; + for (i=0; i < array->namect; i++) { + /* +1: space for either a , or \0 if last */ + cb_config_len += strlen(array->names[i]) + 1; + } + ++cb_config_len; + } + MPI_Bcast(&cb_config_len, 1, MPI_INT, 0, MPI_COMM_WORLD); + if ( (cb_config_string = malloc(cb_config_len)) == NULL ) { + perror("malloc"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + + /* first, no hinting */ + errs += test_file(filename, mynod, nprocs, NULL, "collective w/o hinting", verbose); + + /* hint, but no change in order */ + default_str(mynod, cb_config_len, array, cb_config_string); + errs += test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: default order", verbose); + + /* reverse order */ + reverse_str(mynod, cb_config_len, array, cb_config_string); + errs += test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: reverse order", verbose); + + /* reverse, every other */ + reverse_alternating_str(mynod, cb_config_len, array, cb_config_string); + errs += test_file(filename, mynod, nprocs, cb_config_string,"collective w/ hinting: permutation1", verbose); + + /* second half, first half */ + simple_shuffle_str(mynod, cb_config_len, array, cb_config_string); + errs += test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: permutation2", verbose); + + MPI_Allreduce(&errs, &sum_errs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); + + if (!mynod) { + if (sum_errs) fprintf(stderr, "Found %d error cases\n", sum_errs); + else printf(" No Errors\n"); + } + free(filename); + free(cb_config_string); + MPI_Finalize(); + return 0; +} + +#define SEEDER(x,y,z) ((x)*1000000 + (y) + (x)*(z)) + +int test_file(char *filename, int mynod, int nprocs, char * cb_hosts, const char *msg, int verbose) +{ + MPI_Datatype typevec, newtype, t[3]; + int *buf, i, b[3], errcode, errors=0; + MPI_File fh; + MPI_Aint d[3]; + MPI_Status status; + int SIZE = (STARTING_SIZE/nprocs)*nprocs; + MPI_Info info; + + if (mynod==0 && verbose) fprintf(stderr, "%s\n", msg); + + buf = (int *) malloc(SIZE*sizeof(int)); + if (buf == NULL) { + perror("test_file"); + MPI_Abort(MPI_COMM_WORLD, -1); + } + + + if (cb_hosts != NULL ) { + MPI_Info_create(&info); + MPI_Info_set(info, "cb_config_list", cb_hosts); + } else { + info = MPI_INFO_NULL; + } + + MPI_Type_vector(SIZE/nprocs, 1, nprocs, MPI_INT, &typevec); + + b[0] = b[1] = b[2] = 1; + d[0] = 0; + d[1] = mynod*sizeof(int); + d[2] = SIZE*sizeof(int); + t[0] = MPI_LB; + t[1] = typevec; + t[2] = MPI_UB; + + MPI_Type_struct(3, b, d, t, &newtype); + MPI_Type_commit(&newtype); + MPI_Type_free(&typevec); + + if (!mynod) { + if(verbose) fprintf(stderr, "\ntesting noncontiguous in memory, noncontiguous in file using collective I/O\n"); + MPI_File_delete(filename, info); + } + MPI_Barrier(MPI_COMM_WORLD); + + errcode = MPI_File_open(MPI_COMM_WORLD, filename, + MPI_MODE_CREATE | MPI_MODE_RDWR, info, &fh); + if (errcode != MPI_SUCCESS) { + handle_error(errcode, "MPI_File_open"); + } + + MPI_File_set_view(fh, 0, MPI_INT, newtype, "native", info); + + for (i=0; i +#include +#include + +#define COUNT (200) +#undef TIMING + +void handle_error(int errcode, const char *str); + +void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + +/* tests shared file pointer functions */ + +int main(int argc, char **argv) +{ + int *buf, i, rank, nprocs, len, sum; + int global_sum; + int errs=0, toterrs, errcode; + char *filename; + MPI_File fh; + MPI_Status status; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + double wr_stime, wr_etime, wr_time, wr_sumtime; + double rd_stime, rd_etime, rd_time, rd_sumtime; + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!rank) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: shared_fp -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+10); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+10); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + buf = (int *) malloc(COUNT * sizeof(int)); + + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); +#ifdef TIMING + fprintf( stderr, "nprocs: %d bytes: %d write: %f read %f\n", + nprocs, COUNT*sizeof(int), wr_sumtime, rd_sumtime); +#endif + } + } + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/perf.c b/ompi/mca/io/romio314/romio/test/perf.c new file mode 100644 index 0000000000..b72cf145f8 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/perf.c @@ -0,0 +1,160 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* A simple performance test. The file name is taken as a + command-line argument. */ + +#define SIZE (1048576*4) /* read/write size per node in bytes */ + +int main(int argc, char **argv) +{ + int *buf, i, j, mynod, nprocs, ntimes=5, len, err, flag; + double stim, read_tim, write_tim, new_read_tim, new_write_tim; + double min_read_tim=10000000.0, min_write_tim=10000000.0, read_bw, write_bw; + MPI_File fh; + MPI_Status status; + char *filename; + + MPI_Init(&argc,&argv); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: perf -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + fprintf(stderr, "Access size per process = %d bytes, ntimes = %d\n", SIZE, ntimes); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + + buf = (int *) malloc(SIZE); + + for (j=0; j +#include +#include + +#define SIZE (65536) + +/* This is the same as simple.c, but uses the PMPI versions of all + MPI functions in order to test the profiling interface. */ + +/* Each process writes to separate files and reads them back. + The file name is taken as a command-line argument, and the process rank + is appended to it. */ + +int main(int argc, char **argv) +{ + int *buf, i, rank, nints, len; + char *filename, *tmp; + int errs=0, toterrs; + MPI_File fh; + MPI_Status status; + + PMPI_Init(&argc,&argv); + PMPI_Comm_rank(MPI_COMM_WORLD, &rank); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!rank) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: simple -fname filename\n\n"); + PMPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+10); + strcpy(filename, *argv); + PMPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + PMPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + PMPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+10); + PMPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + + buf = (int *) malloc(SIZE); + nints = SIZE/sizeof(int); + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + + free(buf); + free(filename); + free(tmp); + + PMPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/rtest.in b/ompi/mca/io/romio314/romio/test/rtest.in new file mode 100644 index 0000000000..c6fd305843 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/rtest.in @@ -0,0 +1,131 @@ +#! /bin/sh +# +# Run some of the tests. If any arguments are provided, pass them to the +# test programs. +# +# -mvhome is needed for the ANL SP, and is ignored by others +args=@MPIRUNARGS@ +device=@DEVICE@ +top_srcdir=@top_srcdir@ +srcdir=@srcdir@ +MPICH_VERSION=@MPICH_VERSION@ +STOPFILE=$HOME/.stopmpichtests +mpirun=${MPIRUN:-"@MPIRUN@"} +MAKE="@MAKE@" +FILENAME=test +# +# Load basic procedures +. ${top_srcdir}/runbase +# +# Set mpirun to the name/path of the mpirun program +FindMPIRUN +# +# +test_mpi2=@HAS_MPI2@ +runtests=1 +quiet=0 +makeeach=0 +writesummaryfile=no +MAKE="@MAKE@" +for arg in "$@" ; do + case $arg in + -checkonly ) + runtests=0 + ;; + -margs=*) + margs=`echo $arg | sed 's/-margs=//'` + args="$args $margs" + ;; + -summaryfile=*) + writesummaryfile=yes + summaryfile=`echo A$arg | sed 's/A-summaryfile=//'` + ;; + -small) + makeeach=1 + ;; + -fname=*) + FILENAME=`echo $arg|sed 's/-*fname=//'` + ;; + -quiet) + shift + quiet=1 + ;; + -help|-u) + echo "runtests [-checkonly] [-margs='...']" + echo "run tests in this directory. If -checkonly set, just run" + echo "the differences check (do NO rerun the test programs)." + echo "If -margs is used, these options are passed to mpirun." + echo "If -small is used, the examples are built, run, and deleted." + exit 1 + ;; + *) + if test -n "$arg" ; then + echo "runtests: Unknown argument ($arg)" + exit 1 + fi + ;; + esac +done + +# If the programs are not available, run make. +if [ ! -x simple -a $makeeach = 0 -a $runtests = 1 ] ; then + $MAKE default +fi + +testfiles="" +if [ $runtests = 1 ] ; then + + +RunTest simple 4 "**** Testing simple.c ****" "-fname $FILENAME" + +RunTest async 4 "**** Testing async.c ****" "-fname $FILENAME" + +RunTest atomicity 4 "**** Testing atomicity.out ****" "-fname $FILENAME" + +RunTest coll_test 4 "**** Testing coll_test.out ****" "-fname $FILENAME" + +RunTest excl 4 "**** Testing excl.c ****" "-fname $FILENAME" + +RunTest file_info 4 "**** Testing file_info.c ****" "-fname $FILENAME" + +RunTest i_noncontig 2 "**** Testing i_noncontig.c ****" "-fname $FILENAME" + +RunTest noncontig 2 "**** Testing noncontig.c ****" "-fname $FILENAME" + +RunTest noncontig_coll 2 "**** Testing noncontig_coll.c ****" "-fname $FILENAME" + +RunTest noncontig_coll2 4 "**** Testing noncontig_coll2.c ****" "-fname $FILENAME" + +RunTest misc 4 "**** Testing misc.c ****" "-fname $FILENAME" + +RunTest shared_fp 4 "**** Testing shared_fp.c ****" "-fname $FILENAME" + +RunTest split_coll 4 "**** Testing split_coll.c ****" "-fname $FILENAME" + +RunTest psimple 4 "**** Testing psimple.c ****" "-fname $FILENAME" + +RunTest error 1 "**** Testing error.c ****" "-fname $FILENAME" + +RunTest status 1 "**** Testing status.c ****" "-fname $FILENAME" + +# +# Run Fortran tests ONLY if Fortran available +if [ @HAS_FORTRAN@ = 1 ] ; then + RunTest fmisc 4 "**** Testing fmisc.f ****" "-fname $FILENAME" + + RunTest fcoll_test 4 "**** Testing fcoll_test.f ****" "-fname $FILENAME" + + RunTest pfcoll_test 4 "**** Testing pfcoll_test.f ****" "-fname $FILENAME" +fi + +else + # Just run checks + testfiles=`echo *.out` +fi + +echo '*** Checking for differences from expected output ***' +CheckAllOutput context.diff +exit 0 + + + diff --git a/ompi/mca/io/romio314/romio/test/runtests.in b/ompi/mca/io/romio314/romio/test/runtests.in new file mode 100644 index 0000000000..2b8643e500 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/runtests.in @@ -0,0 +1,479 @@ +#! /bin/sh +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +mpirun="@MPIRUN@" +STOPFILE=${MPITEST_STOPTEST:-"$HOME/.stopmpichtests"} +# +# If the programs are not available, run make. +runtests=1 +makeeach=0 +check_at_once=1 +quiet=0 +MAKE="@MAKE@" +srcdir=@srcdir@ +check_canrun=0 +subset_only=0 +FILENAME=test +# Using shifts should remove args from the list. +for arg in "$@" ; do + case $arg in + -checkonly) + shift + runtests=0 + ;; + -margs=*) + shift + margs=`echo $arg | sed 's/-margs=//'` + args="$args $margs" + ;; + -echo) + shift + set -x + ;; + -check) + check_canrun=1 + ;; + -quiet) + shift + quiet=1 + ;; + -small) + shift + makeeach=1 + ;; + -subset) + shift + subset_only=1 + ;; + -fname=*) + FILENAME=`echo $arg|sed 's/-*fname=//'` + ;; + -atend) + shift + check_at_once=0 + ;; + -help|-u) + shift + echo "runtests [-fname=FILENAME] [-checkonly] [-atend] [-check]" + echo "run tests in this directory. If -checkonly set, just run" + echo "the differences check (do NOT rerun the test programs)." + echo "If -small is used, the examples are built, run, and deleted." + echo "If -atend is used, the success of the tests is checked only" + echo "at the end of the test rather than also after each test." + echo "If -check is used, only a single simple test is run; this" + echo "is used to check that mpirun can run an MPI program." + echo "If -subset is used, we skip tests for atomicity and shared" + echo "file pointers which can fail on some distributed file systems" + exit 1 + ;; + *) + if test -n "$arg" ; then + echo "Passing remaining arguments to programs ($*)" + break + fi + ;; + esac +done + +# MakeExe program-name +MakeExe() { + if [ -s $STOPFILE ] ; then + echo "Found stopfile; exiting" + exit 0 + fi + if [ ! -x $1 ] ; then + $MAKE $1 + if [ ! -x $1 ] ; then + echo "Could not build executable $1; aborting tests" + exit 1 + fi + fi +} +# CleanExe program-name +CleanExe() { + if [ $makeeach = 1 ] ; then + rm -f $1 $1.o + fi +} +# Output marker +OutTime() { + if [ $quiet = 0 ] ; then + if [ -z "$hostname" ] ; then + hostname=`hostname` + fi + d=`date` + echo "$hostname : $d" + fi +} + +# Do an "on the fly" check for problems. +CheckOutput() { + bfile=$1 + if [ $check_at_once = 1 ] ; then + stdfile=${srcdir}/std/$bfile.std + if [ ! -s $bfile.out ] ; then + echo "No output file $bfile.out!" + elif [ -s $stdfile ] ; then + stdfile2=${stdfile}2 + # Handle Fortran systems that generate stop statements + rm -f ${bfile}.tout + grep -v 'FORTRAN STOP' ${bfile}.out > ${bfile}.tout + if diff -b $bfile.tout $stdfile > /dev/null ; then + true + elif [ -s $stdfile2 ] ; then + # check for alternate in case configuration has fewer datatypes + if diff -b $bfile.tout $stdfile2 > /dev/null ; then + true + else + echo "Differences in $bfile.out" + diff -b $bfile.tout $stdfile + nodiff=0 + fi + else + echo "Differences in $bfile.out" + diff -b $bfile.tout $stdfile + fi + rm -f ${bfile}.tout + else + echo "Can not find file $stdfile to compare against for test $bfile" + fi + fi +} + +# nothing uses this function yet... just toying with the concept +RunTest() { + OutTime + testfiles="$testfiles ${1}.out" + rm -rf ${1}.out + MakeExe simple + rm -rf $FILENAME* + echo "**** Testing ${1}.c ****" + mpirun -np 4 ./${1} -fname $FILENAME "$@" >>${1}.out 2>1 + CheckOutput ${1} + CleanExe ${1} +} + +# If the programs are not available, run make. +if [ ! -x simple -a $makeeach = 0 ] ; then + $MAKE default +fi +# +testfiles="" +if [ $runtests = 1 ] ; then +echo '**** Testing I/O functions ****' +# +OutTime +testfiles="$testfiles simple.out" +\rm -f simple.out +MakeExe simple +\rm -f $FILENAME* +echo '**** Testing simple.c ****' +$mpirun -np 4 ./simple -fname $FILENAME +# CheckOutput simple +CleanExe simple +# +OutTime +testfiles="$testfiles async.out" +\rm -f async.out +MakeExe async +\rm -f $FILENAME* +echo '**** Testing async.c ****' +$mpirun -np 4 ./async -fname $FILENAME +# CheckOutput async +CleanExe async +# +OutTime +testfiles="$testfiles async-multi.out" +\rm -f async-multi.out +MakeExe async-multiple +\rm -f $FILENAME* +echo '**** Testing async-multiple.c ****' +$mpirun -np 4 ./async-multiple -fname $FILENAME +# CheckOutput async-multiple +CleanExe async-multiple +# +OutTime +if [ $subset_only -eq 0 ] ; then + testfiles="$testfiles atomicity.out" + \rm -f atomicity.out + MakeExe atomicity + \rm -f $FILENAME* + echo '**** Testing atomicity.c ****' + # Atomicity test recommends at least 8 processes (separate processors + # even better) + $mpirun -np 4 ./atomicity -fname $FILENAME + # CheckOutput atomicity + CleanExe atomicity + # + OutTime +fi +testfiles="$testfiles coll_test.out" +\rm -f coll_test.out +MakeExe coll_test +\rm -f $FILENAME* +echo '**** Testing coll_test.c ****' +$mpirun -np 4 ./coll_test -fname $FILENAME +# CheckOutput coll_test +CleanExe coll_test +# +OutTime +testfiles="$testfiles excl.out" +\rm -f excl.out +MakeExe excl +\rm -f $FILENAME* +echo '**** Testing excl.c ****' +$mpirun -np 4 ./excl -fname $FILENAME +# CheckOutput excl +CleanExe excl +# +OutTime +testfiles="$testfiles file_info.out" +\rm -f file_info.out +MakeExe file_info +\rm -f $FILENAME* +echo '**** Testing file_info.c ****' +$mpirun -np 4 ./file_info -fname $FILENAME +# CheckOutput file_info +CleanExe file_info +# +OutTime +testfiles="$testfiles i_noncontig.out" +\rm -f i_noncontig.out +MakeExe i_noncontig +\rm -f $FILENAME* +echo '**** Testing i_noncontig.c ****' +$mpirun -np 2 ./i_noncontig -fname $FILENAME +# CheckOutput i_noncontig +CleanExe i_noncontig +# +OutTime +testfiles="$testfiles noncontig.out" +\rm -f noncontig.out +MakeExe noncontig +\rm -f $FILENAME* +echo '**** Testing noncontig.c ****' +$mpirun -np 2 ./noncontig -fname $FILENAME +# CheckOutput noncontig +CleanExe noncontig +# +OutTime +testfiles="$testfiles noncontig_coll.out" +\rm -f noncontig_coll.out +MakeExe noncontig_coll +\rm -f $FILENAME* +echo '**** Testing noncontig_coll.c ****' +$mpirun -np 2 ./noncontig_coll -fname $FILENAME +# CheckOutput noncontig_coll +CleanExe noncontig_coll +# +OutTime +testfiles="$testfiles noncontig_coll2.out" +\rm -f noncontig_coll2.out +MakeExe noncontig_coll2 +\rm -f $FILENAME* +echo '**** Testing noncontig_coll2.c ****' +$mpirun -np 4 ./noncontig_coll2 -fname $FILENAME +# CheckOutput noncontig_coll2 +CleanExe noncontig_coll2 +MakeExe aggregation1 +echo '**** Testing aggregation1 ****' +$mpirun -np 4 ./aggregation1 -h -f $FILENAME +# CheckOutput aggregation1 +CleanExe aggregation1 +MakeExe aggregation2 +echo '**** Testing aggregation2 ****' +$mpirun -np 4 ./aggregation2 $FILENAME +# CheckOutput aggregation2 +CleanExe aggregation2 +MakeExe hindexed +echo '**** Testing hindexed ****' +$mpirun -np 4 ./hindexed $FILENAME +# CheckOutput hindexed +CleanExe hindexed +# +#echo '**** Testing write_all_test (run 1)****' +#$mpirun -np 4 ./write_all_test -nzp 2 -zplace 2 -nzw 2 -naw 2 -size 100 \ +# -offm 8 -hints romio_cb_write enable -fname $FILENAME +#echo '**** Testing write_all_test (run 2)****' +#$mpirun -np 4 ./write_all_test -nzp 2 -zplace 2 -nzw 2 -naw 2 -size 100 \ +# -offm 4 -hints romio_cb_write enable -fname $FILENAME +#CleanExe write_all_test +OutTime +if [ $subset_only -eq 0 ] ; then + testfiles="$testfiles misc.out" + \rm -f misc.out + MakeExe misc + \rm -f $FILENAME* + echo '**** Testing misc.c ****' + $mpirun -np 4 ./misc -fname $FILENAME + # CheckOutput misc + CleanExe misc + # + OutTime +fi +if [ $subset_only -eq 0 ] ; then + testfiles="$testfiles shared_fp.out" + \rm -f shared_fp.out + MakeExe shared_fp + \rm -f $FILENAME* + echo '**** Testing shared_fp.c ****' + $mpirun -np 4 ./shared_fp -fname $FILENAME + # CheckOutput shared_fp + CleanExe shared_fp + # + OutTime + testfiles="$testfiles ordered_fp.out" + \rm -f ordered_fp.out + MakeExe ordered_fp + \rm -f $FILENAME* + echo '**** Testing ordered_fp.c ****' + $mpirun -np 4 ./ordered_fp -fname $FILENAME + CleanExe ordered_fp + # + OutTime +fi +testfiles="$testfiles split_coll.out" +\rm -f split_coll.out +MakeExe split_coll +\rm -f $FILENAME* +echo '**** Testing split_coll.c ****' +$mpirun -np 4 ./split_coll -fname $FILENAME +# CheckOutput split_coll +CleanExe split_coll +# +OutTime +testfiles="$testfiles psimple.out" +\rm -f psimple.out +MakeExe psimple +\rm -f $FILENAME* +echo '**** Testing psimple.c ****' +$mpirun -np 4 ./psimple -fname $FILENAME +# CheckOutput psimple +CleanExe psimple +# +OutTime +testfiles="$testfiles error.out" +\rm -f error.out +MakeExe error +\rm -f $FILENAME* +echo '**** Testing error.c ****' +$mpirun -np 1 ./error -fname $FILENAME +# CheckOutput error +CleanExe error +# +OutTime +testfiles="$testfiles status.out" +\rm -f status.out +MakeExe status +\rm -f $FILENAME* +echo '**** Testing status.c ****' +# Some systems have a status program. +$mpirun -np 1 ./status -fname $FILENAME +# CheckOutput status +CleanExe status +testfiles="$testfiles types_with_zeros.out" +\rm -f types_with_zeros.out +MakeExe types_with_zeros +\rm -f $FILENAME* +echo '**** Testing types_with_zeros ****' +$mpirun -np 2 ./types_with_zeros $FILENAME +CleanExe types_with_zeros +testfiles="$testfiles darray_read.out" +\rm -f darray_read.out +MakeExe darray_read +\rm -f $FILENAME* +echo '**** Testing darray_read ****' +$mpirun -np 4 ./darray_read $FILENAME +CleanExe darray_read +# +if [ @NOF77@ = 0 ] ; then + echo "" + echo "FORTRAN TESTS" + OutTime + if [ $subset_only -eq 0 ] ; then + testfiles="$testfiles fmisc.out" + \rm -f fmisc.out + MakeExe fmisc + \rm -f $FILENAME* + echo '**** Testing fmisc.f ****' + $mpirun -np 4 ./fmisc -fname $FILENAME + # CheckOutput fmisc + CleanExe fmisc + # + OutTime + fi + testfiles="$testfiles fcoll_test.out" + \rm -f fcoll_test.out + MakeExe fcoll_test + \rm -f $FILENAME* + echo '**** Testing fcoll_test.f ****' + $mpirun -np 4 ./fcoll_test -fname $FILENAME + # CheckOutput fcoll_test + CleanExe fcoll_test +# + OutTime + testfiles="$testfiles pfcoll_test.out" + \rm -f pfcoll_test.out + MakeExe pfcoll_test + \rm -f $FILENAME* + echo '**** Testing pfcoll_test.f ****' + $mpirun -np 4 ./pfcoll_test -fname $FILENAME + # CheckOutput pfcoll_test + CleanExe pfcoll_test +# +echo "" +fi +# +else + # Just run checks + testfiles=`echo *.out` + if test "$testfiles" = "*.out" ; then + echo "No output files remain from previous test!" + exit 1 + fi +fi +# +# echo '*** Checking for differences from expected output ***' +# rm -f iotests.diff +# nodiff=1 +# for file in $testfiles ; do +# stdfile="${srcdir}/std/`basename $file .out`.std" +# # if basename is sendrecv or isndrcv, then we may want to test +# # with .std2 as well. We should really separate out the long double +# # tests ... +# if [ -s $stdfile ] ; then +# stdfile2=${stdfile}2 +# # Handle Fortran systems that generate stop statements +# bfile="`basename $file .out`.tout" +# rm -f ${bfile} +# grep -v 'FORTRAN STOP' ${file} > ${bfile} +# if diff -b $bfile $stdfile > /dev/null ; then +# true +# elif [ -s $stdfile2 ] ; then +# # check for alternate in case configuration has fewer datatypes +# if diff -b $bfile $stdfile2 > /dev/null ; then +# true +# else +# echo "Differences in `basename $file .out`" >> iotests.diff +# diff -b $bfile $stdfile >> iotests.diff +# nodiff=0 +# fi +# else +# echo "Differences in `basename $file .out`" >> iotests.diff +# diff -b $bfile $stdfile >> iotests.diff +# nodiff=0 +# fi +# rm -f ${bfile} +# else +# echo "Can not find file $stdfile to compare against for test `basename $file .out`" +# nodiff=0 +# fi +# done +# if [ -s iotests.diff ] ; then +# cat iotests.diff +# elif [ $nodiff = 1 ] ; then +# echo "-- No differences found; test successful" +# fi + exit 0 + diff --git a/ompi/mca/io/romio314/romio/test/shared_fp.c b/ompi/mca/io/romio314/romio/test/shared_fp.c new file mode 100644 index 0000000000..df41bdd818 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/shared_fp.c @@ -0,0 +1,122 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +#define COUNT 1024 + +void handle_error(int errcode, const char *str); + +void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + +/* tests shared file pointer functions */ + +int main(int argc, char **argv) +{ + int *buf, i, rank, nprocs, len, sum, global_sum; + int errs=0, toterrs, errcode; + char *filename; + MPI_File fh; + MPI_Status status; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!rank) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: shared_fp -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+10); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+10); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + buf = (int *) malloc(COUNT * sizeof(int)); + + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/simple.c b/ompi/mca/io/romio314/romio/test/simple.c new file mode 100644 index 0000000000..2e90c9dca9 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/simple.c @@ -0,0 +1,119 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +#define SIZE (65536) + +static void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} +/* Each process writes to separate files and reads them back. + The file name is taken as a command-line argument, and the process rank + is appended to it. */ + +int main(int argc, char **argv) +{ + int *buf, i, rank, nints, len; + char *filename, *tmp; + int errs = 0, toterrs, errcode; + MPI_File fh; + MPI_Status status; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!rank) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: simple -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+10); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+10); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + + buf = (int *) malloc(SIZE); + nints = SIZE/sizeof(int); + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + + free(buf); + free(filename); + free(tmp); + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/split_coll.c b/ompi/mca/io/romio314/romio/test/split_coll.c new file mode 100644 index 0000000000..cc3d039b56 --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/split_coll.c @@ -0,0 +1,160 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +/* A 32^3 array. For other array sizes, change array_of_gsizes below. */ + +/* Uses split collective I/O. Writes a 3D block-distributed array to a file + corresponding to the global array in row-major (C) order, reads it + back, and checks that the data read is correct. */ + +/* The file name is taken as a command-line argument. */ + +/* Note that the file access pattern is noncontiguous. */ + +int main(int argc, char **argv) +{ + MPI_Datatype newtype; + int i, ndims, array_of_gsizes[3], array_of_distribs[3]; + int order, nprocs, j, len; + int array_of_dargs[3], array_of_psizes[3]; + int *readbuf, *writebuf, mynod, *tmpbuf, array_size; + MPI_Count bufcount; + int errs=0, toterrs; + char *filename; + MPI_File fh; + MPI_Status status; + MPI_Request request; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &mynod); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!mynod) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: coll_test -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+1); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+1); + MPI_Bcast(filename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + +/* create the distributed array filetype */ + ndims = 3; + order = MPI_ORDER_C; + + array_of_gsizes[0] = 32; + array_of_gsizes[1] = 32; + array_of_gsizes[2] = 32; + + array_of_distribs[0] = MPI_DISTRIBUTE_BLOCK; + array_of_distribs[1] = MPI_DISTRIBUTE_BLOCK; + array_of_distribs[2] = MPI_DISTRIBUTE_BLOCK; + + array_of_dargs[0] = MPI_DISTRIBUTE_DFLT_DARG; + array_of_dargs[1] = MPI_DISTRIBUTE_DFLT_DARG; + array_of_dargs[2] = MPI_DISTRIBUTE_DFLT_DARG; + + for (i=0; i 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + + MPI_Type_free(&newtype); + free(readbuf); + free(writebuf); + free(filename); + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/status.c b/ompi/mca/io/romio314/romio/test/status.c new file mode 100644 index 0000000000..d64d5b2b0e --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/status.c @@ -0,0 +1,93 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2001 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include + +#define SIZE (65536) + +/* Checks if the status objects is filled correctly by I/O functions */ + +int main(int argc, char **argv) +{ + int *buf, i, rank, nints, len, count, elements; + char *filename, *tmp; + int errs=0, toterrs; + MPI_File fh; + MPI_Status status; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + +/* process 0 takes the file name as a command-line argument and + broadcasts it to other processes */ + if (!rank) { + i = 1; + while ((i < argc) && strcmp("-fname", *argv)) { + i++; + argv++; + } + if (i >= argc) { + fprintf(stderr, "\n*# Usage: simple -fname filename\n\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + } + argv++; + len = strlen(*argv); + filename = (char *) malloc(len+10); + strcpy(filename, *argv); + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + else { + MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD); + filename = (char *) malloc(len+10); + MPI_Bcast(filename, len+10, MPI_CHAR, 0, MPI_COMM_WORLD); + } + + buf = (int *) malloc(SIZE); + nints = SIZE/sizeof(int); + + /* each process opens a separate file called filename.'myrank' */ + tmp = (char *) malloc(len+10); + strcpy(tmp, filename); + sprintf(filename, "%s.%d", tmp, rank); + + MPI_File_open(MPI_COMM_SELF, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, + MPI_INFO_NULL, &fh); + MPI_File_write(fh, buf, nints, MPI_INT, &status); + + MPI_Get_count(&status, MPI_INT, &count); + MPI_Get_elements(&status, MPI_INT, &elements); + if (!rank) { + if (count != nints) { + errs++; + printf("count = %d, should be %d\n", count, nints); + } + if (elements != nints) { + errs++; + printf("elements = %d, should be %d\n", elements, nints); + } + } + + MPI_File_close(&fh); + + MPI_Allreduce( &errs, &toterrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD ); + if (rank == 0) { + if( toterrs > 0) { + fprintf( stderr, "Found %d errors\n", toterrs ); + } + else { + fprintf( stdout, " No Errors\n" ); + } + } + free(buf); + free(filename); + free(tmp); + + MPI_Finalize(); + return 0; +} diff --git a/ompi/mca/io/romio314/romio/test/types_with_zeros.c b/ompi/mca/io/romio314/romio/test/types_with_zeros.c new file mode 100644 index 0000000000..9506a06dbd --- /dev/null +++ b/ompi/mca/io/romio314/romio/test/types_with_zeros.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include +#include + +#include + +#define MAXLEN 9 + +static void handle_error(int errcode, const char *str) +{ + char msg[MPI_MAX_ERROR_STRING]; + int resultlen; + MPI_Error_string(errcode, msg, &resultlen); + fprintf(stderr, "%s: %s\n", str, msg); + MPI_Abort(MPI_COMM_WORLD, 1); +} + +enum { + INDEXED, + HINDEXED, + STRUCT +} testcases; + +static int test_indexed_with_zeros(char *filename, int testcase) +{ + int i, rank, np, buflen, num, err, nr_errors=0; + int nelms[MAXLEN], buf[MAXLEN], indices[MAXLEN], blocklen[MAXLEN]; + MPI_File fh; + MPI_Status status; + MPI_Datatype filetype; + MPI_Datatype types[MAXLEN]; + MPI_Aint addrs[MAXLEN]; + + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &np); + + /* set up the number of integers to write in each iteration */ + for (i=0; i +#include +#include +#include + +/* + * This program tests to see if fcntl returns success when asked to + * establish a file lock. This test is intended for use on file systems + * such as NFS that may not implement file locks. ROMIO makes use + * of file locks to implement certain operations, and may not work + * properly if file locks are not available. + * + * This is a simple test and has at least two limitations: + * + * 1. Some implementations of NFS are known to return success for + * setting a file lock when in fact no lock has been set. This + * test will not detect such erroneous implementations of NFS + * + * 2. Some implementations will hang (enter and wait indefinitately) + * within the fcntl call. This program will also hang in that case. + * Under normal conditions, this program should only take a few seconds to + * run. + * + * The program prints a message showing the success or failure of + * setting the file lock and sets the return status to 0 on success and + * non-zero on failure. If there is a failure, the system routine + * perror is also called to explain the reason. + */ + +/* style: allow:printf:2 sig:0 */ + +int main( int argc, char *argv[] ) +{ + struct flock lock; + int fd, err; + char *filename; + + /* Set the filename. Either arg[1] or conftest.dat */ + if (argc > 1 && argv[1]) { + filename = argv[1]; + } + else { + filename = "conftest.dat"; + } + + + lock.l_type = F_WRLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 100; + + fd = open(filename, O_RDWR | O_CREAT, 0644); + + err = fcntl(fd, F_SETLKW, &lock); + + if (err) { + printf( "Failed to set a file lock on %s\n", filename ); + perror( "Reason " ); + } + else { + printf( "fcntl claims success in setting a file lock on %s\n", filename ); + } + /* printf("err = %d, errno = %d\n", err, errno); */ + close(fd); + unlink( filename ); + return err; +} diff --git a/ompi/mca/io/romio314/romio/util/romioinstall.in b/ompi/mca/io/romio314/romio/util/romioinstall.in new file mode 100644 index 0000000000..95a6309231 --- /dev/null +++ b/ompi/mca/io/romio314/romio/util/romioinstall.in @@ -0,0 +1,220 @@ +#!/bin/sh +# +# This script needs to be built by configure. +# +# This is a script to install ROMIO. It can be invoked with +# make install +# +# (if you used -prefix at configure time) or, +# +# make install prefix=/usr/local/romio (or whatever directory you like) +# +# in the top-level romio directory +# +PREFIX=@prefix@ +ROMIO_HOME=@ROMIO_HOME@ +ARCH=@ARCH@ +RANLIB=@RANLIB@ +TOP_BUILD_DIR=@top_build_dir@ +# LAM Do we want to install or uninstall? +WANT_INSTALL=1 +# +# Default paths (set at configure time) +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +sbindir=@sbindir@ +includedir=@includedir@ +#sysconfdir=@sysconfdir@ +libdir=@libdir@ +#sharedlib_dir=@sharedlib_dir@ +mandir=@mandir@ +htmldir=@htmldir@ +# datarootdir required as of autoconf 2.60 +datarootdir=@datatrootdir@ +#datadir=@datadir@ +docdir=@docdir@ +## Location of sources +#top_srcdir=@top_srcdir@ +# +# File access mode +MODE=0644 +XMODE=0755 +replace=1 +verbose=0 + +failmode=soft + +# Shell procedures to copy files and create directories +# +# We could use install, but install is too different and too hard to +# test. So here are the routines to copy file, make directories, and +# replace #...# and @...@ in files +CP=cp +# +MkDir() { + if [ ! -e $1 ]; then mkdir $1 ; fi +} +CopyFile() { +if [ -z "$3" ] ; then +mode=$MODE +else +mode=$3 +fi +if [ -d $2 ] ; then +dest=$2/`basename $1` +else + dest=$2 +fi +if [ $replace = 0 -a -f $dest ] ; then + if [ $verbose = 1 ] ; then echo "$dest exists; not changed" ; fi +elif [ -d $1 ] ; then + echo ">>> $1 is a directory; not copied <<<" + errs=`expr $errs + 1` + if [ $failmode = "hard" ] ; then exit 1 ; fi +elif [ ! -f $1 ] ; then + echo "**File $1 does not exist (or is not a regular file)!" + errs=`expr $errs + 1` + if [ $failmode = "hard" ] ; then exit 1 ; fi +else + if [ $verbose = 1 ] ; then echo "Copying $1 to $dest" ; fi + # We don't delete the file in the event that we are copying the + # file over itself (we SHOULD check for that separately, by checking + # that directories are distinct) + #if [ -f $dest ] ; then $Show rm -f $dest ; fi + $Show $CP $1 $dest + rc=$? + if [ $rc != 0 ] ; then + echo "**Error copying file $1 to $dest **" + errs=`expr $errs + 1` + if [ $failmode = "hard" ] ; then exit $rc ; fi + else + echo "rm -f $dest" >> $UNINSTALLFILE + fi + $Show chmod $mode $dest + rc=$? + if [ $rc != 0 ] ; then + echo "**Error setting mode on file $dest**" + errs=`expr $errs + 1` + if [ $chmodefailmode = "hard" ] ; then exit $rc ; fi + fi +fi +} + +# +# A version of copy file that preserves file dates +CopyFileP() { + CP="cp -p" + CopyFile $1 $2 $3 + CP=cp +} + +# +for arg in "$@" ; do + case "$arg" in + -prefix=*) + PREFIX=`echo $arg | sed -e 's/-prefix=//'` + prefix=$PREFIX + ;; +# LAM Added -uninstall option + -uninstall) + WANT_INSTALL=0 + ;; + *) + echo "romioinstall: Unrecognized argument $arg ." + exit 1 + ;; + esac +done +if test -z "$prefix" ; then + echo "Usage: make install prefix=/usr/local/romio (or whatever directory you like)" + echo "in the top-level romio directory" +fi + +# Uninstall filename +if [ -z "$UNINSTALLFILE" ] ; then + UNINSTALLFILE="$sbindir/romiouninstall" + MkDir `dirname $UNINSTALLFILE` +fi + +# LAM top-level switch to install or uninstall +if test "$WANT_INSTALL" = "1"; then + +# Directories + +# Files + MkDir $prefix + + echo "copying directory $ROMIO_HOME/doc to $docdir" + MkDir $docdir + for file in COPYRIGHT README users-guide.ps.gz ; do + CopyFile $ROMIO_HOME/$file $docdir + done + + echo "copying directory include to $includedir" + MkDir $includedir + for file in include/*.h ; do + CopyFile $file $includedir + done + + MkDir $libdir + echo "copying directory $TOP_BUILD_DIR/lib to $libdir" + #cp -r $ROMIO_HOME/lib $PREFIX + #chmod 755 $PREFIX/lib + for file in $TOP_BUILD_DIR/lib/* ; do + if [ -f $file ] ; then + CopyFileP $file $libdir + fi + done + # Romio also copies directories in the lib directory. + + if [ -z "$mandir" ] ; then + mandir=$PREFIX/man + fi + echo "copying directory $ROMIO_HOME/man to $mandir" + MkDir $mandir + MkDir $mandir/man3 + for file in $ROMIO_HOME/man/man3/* ; do + CopyFile $file $mandir/man3 + done + + if [ -z "$exampledir" ] ; then exampledir=$PREFIX/examples ; fi + echo "copying directory $ROMIO_HOME/test to $exampledir" + MkDir $exampledir + MkDir $exampledir/std + for file in $ROMIO_HOME/test/std/* ; do + CopyFile $file $exampledir/std + done + CopyFile test/Makefile $exampledir + CopyFile test/README $exampledir + for file in test/*.c test/*.f test/runtests ; do + CopyFile $file $exampledir + done + # Ranlib should not be necessary if cp -p is used + #$RANLIB $PREFIX/lib/$ARCH/libmpio.a + # change the include and lib paths in Makefile in the test directory + + echo "updating paths in $exampledir/Makefile" + TMPNEWINC=-I$includedir + TMPNEWLIB=$libdir/$ARCH/libmpio.a + NEWINC=`echo $TMPNEWINC | sed 's/\//\\\\\//g'` + NEWLIB=`echo $TMPNEWLIB | sed 's/\//\\\\\//g'` + sed -e 5s/INCLUDE_DIR[\ ]*=\ [/a-z0-9.A-Z_-]*/INCLUDE_DIR\ =\ $NEWINC/ \ + -e 6s/LIBS[\ ]*=\ [/a-z0-9.A-Z_-]*/LIBS\ =\ $NEWLIB/ $exampledir/Makefile\ + > $exampledir/.romiotmp + mv $exampledir/.romiotmp $exampledir/Makefile + + # + MkDir $sbindir + echo "rm -f $UNINSTALLFILE" >> $UNINSTALLFILE + # Add the directory removes to the UNINSTALL file + for dir in $dirlist ; do + echo "if [ -d $dir ] ; then rmdir $dir ; fi" >> $UNINSTALLFILE + done +else + +# LAM do all the things for uninstall -- do the opposite of above. +# This whole section is new. + $sbindir/romiouninstall + echo "ROMIO uninstalled" +fi diff --git a/ompi/mca/io/romio314/romio/util/tarch b/ompi/mca/io/romio314/romio/util/tarch new file mode 100755 index 0000000000..ccccf4d514 --- /dev/null +++ b/ompi/mca/io/romio314/romio/util/tarch @@ -0,0 +1,120 @@ +#! /bin/sh +# set -x +# +# Returns the arch of the machine. This file is from MPICH. +# +# First, try some special cases: +if [ -d "/dev/elan" ] ; then + FARCH="meiko" +elif [ -f /usr/bin/uxpm ] && /usr/bin/uxpm ; then + FARCH="UXPM" +elif [ -f /usr/bin/uxpv ] && /usr/bin/uxpv ; then + FARCH="uxpv" +fi +if [ -n "$FARCH" ] ; then + echo $FARCH + exit 0 +fi +# +# Try to find uname +for dir in /bin /usr/bin /usr/local/bin ; do + if [ -x $dir/uname ] ; then + UNAME="$dir/uname" + break + fi +done +# +# Get uname -s, uname -m, and arch values +# +if [ -n "$UNAME" ] ; then + ARCHLIST="`uname -s`" + ARCHLIST="$ARCHLIST `uname -m`" +fi +# +# Get ARCH variable name +if [ -n "$ARCH" ] ; then + ARCHLIST="$ARCHLIST $ARCH" +fi +# +# Get arch command +if [ -x /bin/arch ] ; then + ARCHLIST="$ARCHLIST `/bin/arch`" +elif [ -x /usr/local/bin/arch ] ; then + ARCHLIST="$ARCHLIST `/usr/local/bin/arch`" +fi +# +# GARCH is a guess if we don't find something better +GARCH= +# Now, weed through all of these values until we find something useful. +for LARCH in $ARCHLIST ; do + # Remove blanks + LARCH=`echo $LARCH | sed 's/ //g'` + # Get the first 4 characters (you'd be surprised) + # LARCH4=`expr "$LARCH" : "\(....\)"` + # LARCH6=`expr "$LARCH" : "\(......\)"` + case $LARCH in + SUPER-UX) FARCH=SX4; break ;; + AIX|RIOS) FARCH=rs6000; break ;; + HP-UX) + if [ -a /dev/kmem ] ; then + FARCH=hpux ; + else + FARCH=sppux ; + fi + break ;; + IRIX64|IRIX) FARCH=$LARCH ; break ;; + Linux) FARCH=LINUX ; break ;; + i586|i486|i86pc) + GARCH=$LARCH ;; + sun4*) + Version=`$UNAME -r` + # In "improving" SunOS, the useful feature of "substr" was withdrawn + # from expr. Can't let the users have life too easy, can we? This + # means that we can't just use + # set MajorVersion = `expr substr $Version 1 1` + # because it won't work on Solaris systems. The following should work + # on both: + MajorVersion=`expr "$Version" : "\(.\)"` + if [ "$MajorVersion" -ge 5 ] ; then + FARCH=solaris + else + FARCH=sun4 + fi + break ;; + hp9000*|hp7000*) + if [ -a /dev/kmem ] ; then + FARCH=hpux ; + else + FARCH=sppux ; + fi + break ;; + Darwin*) + FARCH=Darwin + break ;; + + mips|dec-5000) FARCH=dec5000 ; break ;; + next) FARCH=NeXT ; break ;; + KSR1|KSR2) FARCH=ksr ; break ;; + FreeBSD) FARCH=freebsd ; break ;; + OpenBSD) FARCH=openbsd ; break ;; + NetBSD) FARCH=netbsd ; break ;; + + # The following are guesses + IP12|iris-4d) GARCH=IRIX ;; + cray|CRAY*) GARCH=CRAY ;; + i386) GARCH=ipsc2 ;; + ULTRIX|RISC) GARCH=dec5000 ;; + esac + LLARCH=$LARCH +done +if [ -z "$FARCH" ] ; then + FARCH=$GARCH + if [ -z "$FARCH" ] ; then + FARCH=$LLARCH + fi + if [ -z "$FARCH" ] ; then + FARCH=unknown + fi +fi +echo $FARCH +exit 0