Start with the code from IOR-2.10.3

master
Christopher J. Morrone 2011-06-17 12:20:43 -07:00
commit a56d39e6f1
34 changed files with 11675 additions and 0 deletions

256
COPYRIGHT Normal file
View File

@ -0,0 +1,256 @@
Copyright (c) 2003, The Regents of the University of California.
Produced at the Lawrence Livermore National Laboratory.
Written by William Loewe <loewe6@llnl.gov>, Tyce McLarty <mclarty3@llnl.gov>,
and Christopher Morrone <morrone2@llnl.gov>.
UCRL-CODE-2003-016.
All rights reserved.
This file is part of IOR.
Please also read Our Notice and GNU General Public License.
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) version 2, dated June 1991.
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 terms and conditions of 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, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE
Our Preamble Notice
A. This notice is required to be provided under our contract with the U.S.
Department of Energy (DOE). This work was produced at the University of
California, Lawrence Livermore National Laboratory under Contract No.
W-7405-ENG-48 with the DOE.
B. Neither the United States Government nor the University of California nor
any of their employees, makes any warranty, express or implied, or assumes any
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.
C. Also, reference herein to any specific commercial products, process, or
services by trade name, trademark, manufacturer or otherwise does not
necessarily constitute or imply its endorsement, recommendation, or favoring
by the United States Government or the University of California. The views and
opinions of authors expressed herein do not necessarily state or reflect those
of the United States Government or the University of California, and shall not
be used for advertising or product endorsement purposes.
The precise terms and conditions for copying, distribution and modification
follows.
GNU Terms and Conditions for Copying, Distribution, and Modification
0. This License applies to any program or other work which contains a notice
placed by the copyright holder saying it may be distributed under the terms of
this General Public License. The "Program," below, refers to any such program
or work, and a "work based on the Program" means either the Program or any
derivative work under copyright law: that is to say, a work containing the
Program or a portion of it, either verbatim or with modifications and/or
translated into another language. (Hereinafter, translation is included
without limitation in the term "modification".) Each licensee is addressed as
"you."
Activities other than copying, distribution and modification are not covered by
this License; they are outside its scope. The act of running the Program is
not restricted, and the output from the Program is covered only if its contents
constitute a work based on the Program (independent of having been made by
running the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code as
you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this License
and to the absence of any warranty; and give any other recipients of the
Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may
at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it,
thus forming a work based on the Program, and copy and distribute such
modifications or work under the terms of Section 1 above, provided that you
also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating
that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole
or in part contains or is derived from the Program or any part thereof,
to be licensed as a whole at no charge to all third parties under the terms
of this License.
c) If the modified program normally reads commands interactively when run,
you must cause it, when started running for such interactive use in the
most ordinary way, to print or display an announcement including an
appropriate copyright notice and a notice that there is no warranty (or
else, saying that you provide a warranty) and that users may redistribute
the program under these conditions, and telling the user how to view a copy
of this License. (Exception: if the Program itself is interactive but does
not normally print such an announcement, your work based on the Program is
not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable
sections of that work are not derived from the Program, and can be reasonably
considered independent and separate works in themselves, then this License, and
its terms, do not apply to those sections when you distribute them as separate
work. But when you distribute the same section as part of a whole which is a
work based on the Program, the distribution of the whole must be on the terms
of this License, whose permissions for other licensees extend to the entire
whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your
rights to work written entirely by you; rather, the intent is to exercise the
right to control the distribution of derivative or collective works based on
the Program.
In addition, mere aggregation of another work not based on the Program with the
Program (or with a work based on the Program) on a volume of a storage or
distribution medium does not bring the other work under the scope of this
License.
3. You may copy and distribute the Program (or a work based on it, under
Section 2) in object code or executable form under the terms of Sections 1 and
2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source
code, which must be distributed under the terms of Sections 1 and 2 above
on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to
give any third party, for a charge no more than your cost of physically
performing source distribution, a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of Sections 1
and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to
distribute corresponding source code. (This alternative is allowed only
for noncommercial distribution and only if you received the program in
object code or executable form with such an offer, in accord with
Subsection b above.)
The source code for a work means the preferred form the work for making
modifications to it. For an executable work, complete source code means all
the source code for all modules it contains, plus any associated interface
definition files, plus the scripts used to control compilation and installation
of the executable. However, as a special exception, the source code
distributed need not include anything that is normally distributed (in either
source or binary form) with the major components (compiler, kernel, and so on)
of the operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the source
code from the same place counts as distribution of the source code, even though
third parties are not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as
expressly provided under this License. Any attempt otherwise to copy, modify,
sublicense or distribute the Program is void, and will automatically terminate
your rights under this License. However, parties who have received copies, or
rights, from you under this License will not have their licenses terminated so
long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it.
However, nothing else grants you permission to modify or distribute the Program
or its derivative works. These actions are prohibited by law if you do not
accept this License. Therefore, by modifying or distributing the Program (or
any work based on the Program), you indicate your acceptance of this License to
do so, and all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program),
the recipient automatically receives a license from the original licensor to
copy, distribute or modify the Program subject to these terms and conditions.
You may not impose any further restrictions on the recipients' exercise of the
rights granted herein. You are not responsible for enforcing compliance by
third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues), conditions
are imposed on you (whether by court order, agreement or otherwise) that
contradict the conditions of this License, they do not excuse you from the
conditions of this License. If you cannot distribute so as to satisfy
simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Program at all.
For example, if a patent license would not permit royalty-free redistribution
of the Program by all those who receive copies directly or indirectly through
you, then the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply and
the section as a whole is intended to apply in other circumstances.
It is not the purpose to this section to induce you to infringe any patents or
other property right claims or to contest validity of any such claims; this
section has the sole purpose of protecting the integrity of the free software
distribution system, which is implemented by public license practices. Many
people have made generous contributions to the wide range of software
distributed through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing to
distribute software through any other system and a licensee cannot impose that
choice.
This section is intended to make thoroughly clear what is believed to be a
consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain
countries either by patents or by copyrighted interfaces, the original
copyright holder who places the Program under this License may add an explicit
geographical distribution limitation excluding those countries, so that
distribution is permitted only in or among countries not thus excluded. In
such case, this License incorporates the limitation as if written in the body
of this License.
9. The Free Software Foundation may publish revised and/or new versions of the
General Public License from time to time. Such new versions will be similar in
spirit to the present version, but may differ in detail to address new problems
or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any later
version," you have the option of following the terms and conditions either of
that version of any later version published by the Free Software Foundation.
If the Program does not specify a version number of this License, you may
choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs
whose distribution conditions are different, write to the author to ask for
permission. For software which is copyrighted by the Free Software Foundation,
write to the Free Software Foundation; we sometimes make exceptions for this.
Our decision to grant permission will be guided by the two goals of preserving
the free status of all derivatives of our free software and or promoting the
sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

414
IOR.vcproj Normal file
View File

@ -0,0 +1,414 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="IOR"
ProjectGUID="{8F7A919E-29D8-4E1E-8755-912DFB764A32}"
RootNamespace="IOR"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="getopt;&quot;$(CCP_INC)&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
EnablePREfast="false"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="msmpi.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="$(CCP_LIB32)"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(CCP_INC)&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="msmpi.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="$(CCP_LIB64)"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="getopt;&quot;$(CCP_INC)&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="msmpi.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="$(CCP_LIB32)"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="getopt;&quot;$(CCP_INC)&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="msmpi.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="$(CCP_LIB64)"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="docs"
>
<File
RelativePath=".\COPYRIGHT"
>
</File>
<File
RelativePath=".\README"
>
</File>
<File
RelativePath=".\RELEASE_LOG"
>
</File>
<File
RelativePath=".\UNDOCUMENTED_OPTIONS"
>
</File>
<File
RelativePath=".\USER_GUIDE"
>
</File>
</Filter>
<File
RelativePath=".\src\C\aiori-MPIIO.c"
>
</File>
<File
RelativePath=".\src\C\aiori-noHDF5.c"
>
</File>
<File
RelativePath=".\src\C\aiori-noNCMPI.c"
>
</File>
<File
RelativePath=".\src\C\aiori-POSIX.c"
>
</File>
<File
RelativePath=".\src\C\aiori.h"
>
</File>
<File
RelativePath=".\src\C\defaults.h"
>
</File>
<File
RelativePath=".\src\C\win\getopt.c"
>
</File>
<File
RelativePath=".\src\C\win\getopt.h"
>
</File>
<File
RelativePath=".\src\C\IOR-aiori.h"
>
</File>
<File
RelativePath=".\src\C\IOR.c"
>
</File>
<File
RelativePath=".\src\C\IOR.h"
>
</File>
<File
RelativePath=".\src\C\iordef.h"
>
</File>
<File
RelativePath=".\src\C\parse_options.c"
>
</File>
<File
RelativePath=".\src\C\utilities.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

32
Makefile Normal file
View File

@ -0,0 +1,32 @@
#/*****************************************************************************\
#* *
#* Copyright (c) 2003, The Regents of the University of California *
#* See the file COPYRIGHT for a complete copyright notice and license. *
#* *
#*******************************************************************************
#*
#* CVS info:
#* $RCSfile: Makefile,v $
#* $Revision: 1.1.1.1 $
#* $Date: 2007/10/15 23:36:54 $
#* $Author: rklundt $
#*
#* Purpose:
#* Make IOR executable.
#*
#* gmake posix -- IOR with only POSIX interface
#* gmake mpiio -- IOR with only POSIX and MPIIO interfaces
#* gmake hdf5 -- IOR with POSIX, MPIIO, and HDF5 interfaces
#* gmake ncmpi -- IOR with POSIX, MPIIO, and NCMPI interfaces
#* gmake all -- IOR with POSIX, MPIIO, HDF5, and NCMPI interfaces
#* gmake clean -- remove executable and object files
#*
#\*****************************************************************************/
SRC = ./src/C
posix:
(cd $(SRC) && $(MAKE) posix)
%:
(cd $(SRC) && $(MAKE) $@)

11
README Normal file
View File

@ -0,0 +1,11 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
\******************************************************************************/
This collection of files contains the source (in /src) and Makefile for
building IOR. In /scripts, there are scripts for simulating I/O behavior of
various parallel applications. For more information, please read the User
Guide.

147
RELEASE_LOG Normal file
View File

@ -0,0 +1,147 @@
Changes in IOR-2.10.3
* bug 2962326 "Segmentation Fault When Summarizing Results" fixed
* bug 2786285 "-Wrong number of parameters to function H5Dcreate" fixed
(NOTE: to compile for HDF5 1.6 libs use "-D H5_USE_16_API")
* bug 1992514 "delay (-d) doesn't work" fixed
Contributed by demyn@users.sourceforge.net
* Ported to Windows. Required changes related to 'long' types, which on Windows
are always 32-bits, even on 64-bit systems. Missing system headers and
functions acount for most of the remaining changes.
New files for Windows:
- IOR/ior.vcproj - Visual C project file
- IOR/src/C/win/getopt.{h,c} - GNU getopt() support
See updates in the USER_GUIDE for build instructions on Windows.
* Fixed bug in incrementing transferCount
* Fixed bugs in SummarizeResults with mismatched format specifiers
* Fixed inconsistencies between option names, -h output, and the USER_GUIDE.
Changes in IOR-2.10.2:
Hodson, 8/18/2008:
The modifications to IOR-2.10.1 extend existing random I/O capabilities and
enhance performance output statistics.
cli script Description
----- ----------------- ----------------------------------------
1) -A N testnum - test reference number for easier test
identification in log files
2) -Q N taskpernodeoffset - for read tests. Use with -C & -Z options
If -C (reordertasks) specified,
then node offset read by CONSTANT N.
If -Z (reordertasksrandom) specified,
then node offset read by RANDOM >= N.
3) -Z reordertasksrandom - random node task ordering for read tests
In this case, processes read
data written by other processes with
node offsets specified by the -Q option
and -X option.
4) -X N reordertasksrandomseed - random seed for -Z (reordertasksrandom)
If N>=0, use same seed for all iters
If N< 0, use different seed for ea. iter
5) -Y fsyncperwrite - perform fsync after every POSIX write
Fixes in IOR-2.10.1:
* added '-J' setAlignment option for HDF5 alignment in bytes; default value
is 1, which does not set alignment
* changed how HDF5 and PnetCDF calculate performance -- formerly each used
the size of the stat()'ed file; changed it to be number of data bytes
transferred. these library-generated files can have large headers and
filler as well as sparse file content
* found potential overflow error in cast -- using IOR_offset_t, not int now
* replaced HAVE_HDF5_NO_FILL macro to instead directly check if H5_VERS_MAJOR
H5_VERS_MINOR are defined; if so, then must be HDF5-1.6.x or higher for
no-fill usage.
* corrected IOR_GetFileSize() function to point to HDF5 and NCMPI versions of
IOR_GetFileSize() calls
* changed the netcdf dataset from 1D array to 4D array, where the 4 dimensions
are: [segmentCount][numTasksWorld][numTransfers][transferSize]
This patch from Wei-keng Liao allows for file sizes > 4GB (provided no
single dimension is > 4GB).
* finalized random-capability release
* changed statvfs() to be for __sun (SunOS) only
* retired Python GUI
Fixes in IOR-2.10.0.1:
* Cleaned up WriteOrRead(), reducing much to smaller functions.
* Added random capability for transfer offset.
* modified strtok(NULL, " \t\r\n") in ExtractHints() so no trailing characters
* added capability to set hints in NCMPI
Fixes in IOR-2.9.6.1:
* for 'pvfs2:' filename prefix, now skips DisplayFreeSpace(); formerly this
caused a problem with statvfs()
* changed gethostname() to MPI_Get_processor_name() so for certain cases
when gethostname() would only return the frontend node name
* added SunOS compiler settings for makefile
* updated O_DIRECT usage for SunOS compliance
* changed statfs() to instead use statvfs() for SunOS compliance
* renamed compiler directive _USE_LUSTRE to _MANUALLY_SET_LUSTRE_STRIPING
Fixes in IOR-2.9.5:
* Wall clock deviation time relabeled to be "Start time skew across all tasks".
* Added notification for "Using reorderTasks '-C' (expecting block, not cyclic,
task assignment)"
* Corrected bug with read performance with stonewalling (was using full size,
stat'ed file instead of bytes transfered).
Fixes in IOR-2.9.4:
* Now using IOR_offset_t instead of int for tmpOffset in IOR.c:WriteOrRead().
Formerly, this would cause error in file(s) > 2GB for ReadCheck. The
more-commonly-used WriteCheck option was not affected by this.
Fixes in IOR-2.9.3:
* Changed FILE_DELIMITER from ':' to '@'.
* Any time skew between nodes is automatically adjusted so that all nodes
are calibrated to the root node's time.
* Wall clock deviation time is still reported, but have removed the warning
message that was generated for this. (Didn't add much new information,
just annoyed folks.)
* The '-j' outlierThreshold option now is set to 0 (off) as default. To use
this, set to a positive integer N, and any task who's time (for open,
access, etc.) is not within N seconds of the mean of all the tasks will show
up as an outlier.
Fixes in IOR-2.9.2:
* Simple cleanup of error messages, format, etc.
* Changed error reporting so that with VERBOSITY=2 (-vv) any error encountered
is displayed. Previously, this was with VERBOSITY=3, along with full test
parameters, environment, and all access times of operations.
* Added deadlineForStonewalling option (-D). This option is used for measuring
the amount of data moved in a fixed time. After the barrier, each task
starts its own timer, begins moving data, and the stops moving data at a
prearranged time. Instead of measuring the amount of time to move a fixed
amount of data, this option measures the amount of data moved in a fixed
amount of time. The objective is to prevent tasks slow to complete from
skewing the performance.
Fixes in IOR-2.9.1:
* Updated test script to run through file1:file2 cases.
* Program exit code is now total numbers of errors (both writecheck and
readcheck for all iterations), unless quitOnError (-q) is set.
* For various failure situations, replace abort with warning, including:
- failed uname() for platform name now gives warning
- failed unlink() of data file now gives warning
- failed fsync() of data file now gives warning
- failed open() of nonexistent script file now gives warning
* Changed labelling for error checking output to be (hopefully) more
clear in details on errors for diagnostics.
* Another fix for -o file1:file2 option.
* Corrected bug in GetTestFileName() -- now possible to handle -o file1:file2
cases for file-per-proc.
Fixes in IOR-2.9.0:
* Improved checkRead option to reread data from different node (to avoid
cache) and then compare both reads.
* Added outlierThreshold (-j) option to give warning if any task is more than
this number of seconds from the mean of all participating tasks. If so, the
task is identified, its time (start, elapsed create, elapsed transfer,
elapsed close, or end) is reported, as is the mean and standard deviation for
all tasks. The default for this is 5, i.e. any task not within 5 seconds of
the mean for those times is displayed. This value can be set with
outlierThreshold=<value> or -j <value>.
* Correct for clock skew between nodes - if skew greater than wallclock
deviation threshold (WC_DEV_THRESHOLD) in seconds, then broadcast root
node's timestamp and adjust by the difference. WC_DEV_THRESHOLD currently
set to 5.
* Added a Users Guide.

36
UNDOCUMENTED_OPTIONS Normal file
View File

@ -0,0 +1,36 @@
To use these options, modify USE_UNDOC_OPT=TRUE in iordef.h and then recompile.
For passing arguments to the executable for these options, use this format:
'-O option1=1,option2=0'
Options:
* fillTheFileSystem -- limits unnecessary output for showing performance, etc.
The command line '-w -k -m -i 123 -F -O fillTheFileSystem=5' has each task
creating (and keeping) 123 files, showing the time between every fifth file.
* includeDeleteTime -- use with '-O includeDeleteTime=1' to have time to
delete file included in write performance time. Note that if this file
is deleted after the write, there's nothing available for the read back
or checking.
* multiReRead -- use with '-i 5 -v -k -w -W -O multiReRead=1' to have 1 write
of file, followed by 4 reads w/data checking.
* NFS_serverCount -- use with other NFS_* options, -F, and -o to write/read
files across multiple NFS servers. Set the server count to > 0 to enable.
The format is: 'NFS_rootPath/NFS_serverName[0..NFS_serverCount-1]/outFile'.
Each file is written round-robin to a different NFS server.
* NFS_rootPath -- use with NFS_server* options for path to NFS servers.
* NFS_serverName -- ise with NFS_* options for NFS server prefix. Specific
NFS server number is appended to this name, e.g. nfs123.
* corruptFile -- corrupts file after writing for determining data-checking
reliability.
Note:
* cbif.c (Change Byte In File) is a simple utility to check the value of
a file offset; also allows changing a single byte at an offset.

735
USER_GUIDE Normal file
View File

@ -0,0 +1,735 @@
/*****************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
\*****************************************************************************/
/********************* Modifications to IOR-2.10.1 ****************************
* Hodson, 8/18/2008: *
* Documentation updated for the following new option: *
* The modifications to IOR-2.10.1 extend existing random I/O capabilities and *
* enhance performance output statistics. *
* *
* cli script Description *
* ----- ----------------- ----------------------------------------*
* 1) -A N testnum - test reference number for easier test *
* identification in log files *
* 2) -Q N taskpernodeoffset - for read tests. Use with -C & -Z options*
* If -C (reordertasks) specified, *
* then node offset read by CONSTANT N. *
* If -Z (reordertasksrandom) specified, *
* then node offset read by RANDOM >= N. *
* 3) -Z reordertasksrandom - random node task ordering for read tests*
* In this case, processes read *
* data written by other processes with *
* node offsets specified by the -Q option *
* and -X option. *
* 4) -X N reordertasksrandomseed - random seed for -Z (reordertasksrandom) *
* If N>=0, use same seed for all iters *
* If N< 0, use different seed for ea. iter*
* 5) -Y fsyncperwrite - perform fsync after every POSIX write *
\*****************************************************************************/
IOR USER GUIDE
Index:
* Basics
1. Description
2. Building IOR
3. Running IOR
4. Options
* More Information
5. Option details
6. Verbosity levels
7. Using Scripts
* Troubleshooting
8. Compatibility with older versions
* Frequently Asked Questions
9. How do I . . . ?
* Output
10. Enhanced output description
*******************
* 1. DESCRIPTION *
*******************
IOR can be used for testing performance of parallel file systems using various
interfaces and access patterns. IOR uses MPI for process synchronization.
IOR version 2 is a complete rewrite of the original IOR (Interleaved-Or-Random)
version 1 code.
*******************
* 2. BUILDING IOR *
*******************
Build Instructions:
Type 'gmake [posix|mpiio|hdf5|ncmpi|all]' from the IOR/ directory.
On some platforms, e.g., Cray XT, specify "CC=cc" to build using "cc" instead of "mpicc".
In IOR/src/C, the file Makefile.config currently has settings for AIX, Linux,
OSF1 (TRU64), and IRIX64 to model on. Note that MPI must be present for
building/running IOR, and that MPI I/O must be available for MPI I/O, HDF5,
and Parallel netCDF builds. As well, HDF5 and Parallel netCDF libraries are
necessary for those builds. All IOR builds include the POSIX interface.
You can build IOR as a native Windows application. One way to do this is to
use the "Microsoft Windows SDK", which is available as a free download and
includes development tools like the Visual C++ compiler. To build IOR with
MPI-IO support, also download and install the "Microsoft HPC Pack SDK".
Once these packages are installed on your Windows build system, follow these
steps:
1. Open a "CMD Shell" under the Start menu Microsoft Windows SDK group.
2. cd to the IOR directory containing ior.vcproj
3. Run: vcbuild ior.vcproj "Release|x64"
ior.exe will be created in the directory IOR/x64/Release. "Debug|x64",
"Release|Win32", and "Debug|Win32" configurations can also be built.
To build IOR without MPI-IO support, first edit ior.vcproj and replace
aiori-MPIIO.c with aiori-noMPIIO.c.
******************
* 3. RUNNING IOR *
******************
Two ways to run IOR:
* Command line with arguments -- executable followed by command line options.
E.g., to execute: IOR -w -r -o filename
This performs a write and a read to the file 'filename'.
* Command line with scripts -- any arguments on the command line will
establish the default for the test run, but a script may be used in
conjunction with this for varying specific tests during an execution of the
code.
E.g., to execute: IOR -W -f script
This defaults all tests in 'script' to use write data checking.
**************
* 4. OPTIONS *
**************
These options are to be used on the command line. E.g., 'IOR -a POSIX -b 4K'.
-A N testNum -- test number for reference in some output
-a S api -- API for I/O [POSIX|MPIIO|HDF5|NCMPI]
-b N blockSize -- contiguous bytes to write per task (e.g.: 8, 4k, 2m, 1g)
-B useO_DIRECT -- uses O_DIRECT for POSIX, bypassing I/O buffers
-c collective -- collective I/O
-C reorderTasks -- changes task ordering to n+1 ordering for readback
-Q N taskPerNodeOffset for read tests use with -C & -Z options (-C constant N, -Z at least N) [!HDF5]
-Z reorderTasksRandom -- changes task ordering to random ordering for readback
-X N reorderTasksRandomSeed -- random seed for -Z option
-d N interTestDelay -- delay between reps in seconds
-D N deadlineForStonewalling -- seconds before stopping write or read phase
-Y fsyncPerWrite -- perform fsync after each POSIX write
-e fsync -- perform fsync upon POSIX write close
-E useExistingTestFile -- do not remove test file before write access
-f S scriptFile -- test script name
-F filePerProc -- file-per-process
-g intraTestBarriers -- use barriers between open, write/read, and close
-G N setTimeStampSignature -- set value for time stamp signature
-h showHelp -- displays options and help
-H showHints -- show hints
-i N repetitions -- number of repetitions of test
-I individualDataSets -- datasets not shared by all procs [not working]
-j N outlierThreshold -- warn on outlier N seconds from mean
-J N setAlignment -- HDF5 alignment in bytes (e.g.: 8, 4k, 2m, 1g)
-k keepFile -- don't remove the test file(s) on program exit
-K keepFileWithError -- keep error-filled file(s) after data-checking
-l storeFileOffset -- use file offset as stored signature
-m multiFile -- use number of reps (-i) for multiple file count
-n noFill -- no fill in HDF5 file creation
-N N numTasks -- number of tasks that should participate in the test
-o S testFile -- full name for test
-O S string of IOR directives (e.g. -O checkRead=1,lustreStripeCount=32)
-p preallocate -- preallocate file size
-P useSharedFilePointer -- use shared file pointer [not working]
-q quitOnError -- during file error-checking, abort on error
-r readFile -- read existing file
-R checkRead -- check read after read
-s N segmentCount -- number of segments
-S useStridedDatatype -- put strided access into datatype [not working]
-t N transferSize -- size of transfer in bytes (e.g.: 8, 4k, 2m, 1g)
-T N maxTimeDuration -- max time in minutes to run tests
-u uniqueDir -- use unique directory name for each file-per-process
-U S hintsFileName -- full name for hints file
-v verbose -- output information (repeating flag increases level)
-V useFileView -- use MPI_File_set_view
-w writeFile -- write file
-W checkWrite -- check read after write
-x singleXferAttempt -- do not retry transfer if incomplete
-z randomOffset -- access is to random, not sequential, offsets within a file
NOTES: * S is a string, N is an integer number.
* For transfer and block sizes, the case-insensitive K, M, and G
suffices are recognized. I.e., '4k' or '4K' is accepted as 4096.
*********************
* 5. OPTION DETAILS *
*********************
For each of the general settings, note the default is shown in brackets.
IMPORTANT NOTE: For all true/false options below [1]=true, [0]=false
IMPORTANT NOTE: Contrary to appearance, the script options below are NOT case sensitive
GENERAL:
========
* testNum - test reference number for some output [-1]
* api - must be set to one of POSIX, MPIIO, HDF5, or NCMPI
depending on test [POSIX]
* testFile - name of the output file [testFile]
NOTE: with filePerProc set, the tasks can round
robin across multiple file names '-o S@S@S'
* hintsFileName - name of the hints file []
* repetitions - number of times to run each test [1]
* multiFile - creates multiple files for single-shared-file or
file-per-process modes; i.e. each iteration creates
a new file [0=FALSE]
* reorderTasksConstant - reorders tasks by a constant node offset for writing/reading neighbor's
data from different nodes [0=FALSE]
* taskPerNodeOffset - for read tests. Use with -C & -Z options. [1]
With reorderTasks, constant N. With reordertasksrandom, >= N
* reorderTasksRandom - reorders tasks to random ordering for readback [0=FALSE]
* reorderTasksRandomSeed - random seed for reordertasksrandom option. [0]
>0, same seed for all iterations. <0, different seed for each iteration
* quitOnError - upon error encountered on checkWrite or checkRead,
display current error and then stop execution;
if not set, count errors and continue [0=FALSE]
* numTasks - number of tasks that should participate in the test
[0]
NOTE: 0 denotes all tasks
* interTestDelay - this is the time in seconds to delay before
beginning a write or read in a series of tests [0]
NOTE: it does not delay before a check write or
check read
* outlierThreshold - gives warning if any task is more than this number
of seconds from the mean of all participating tasks.
If so, the task is identified, its time (start,
elapsed create, elapsed transfer, elapsed close, or
end) is reported, as is the mean and standard
deviation for all tasks. The default for this is 0,
which turns it off. If set to a positive value, for
example 3, any task not within 3 seconds of the mean
displays its times. [0]
* intraTestBarriers - use barrier between open, write/read, and close [0=FALSE]
* uniqueDir - create and use unique directory for each
file-per-process [0=FALSE]
* writeFile - writes file(s), first deleting any existing file [1=TRUE]
NOTE: the defaults for writeFile and readFile are
set such that if there is not at least one of
the following -w, -r, -W, or -R, it is assumed
that -w and -r are expected and are
consequently used -- this is only true with
the command line, and may be overridden in
a script
* readFile - reads existing file(s) (from current or previous
run) [1=TRUE]
NOTE: see writeFile notes
* filePerProc - accesses a single file for each processor; default
is a single file accessed by all processors [0=FALSE]
* checkWrite - read data back and check for errors against known
pattern; can be used independently of writeFile [0=FALSE]
NOTES: * data checking is not timed and does not
affect other performance timings
* all errors tallied and returned as program
exit code, unless quitOnError set
* checkRead - reread data and check for errors between reads; can
be used independently of readFile [0=FALSE]
NOTE: see checkWrite notes
* keepFile - stops removal of test file(s) on program exit [0=FALSE]
* keepFileWithError - ensures that with any error found in data-checking,
the error-filled file(s) will not be deleted [0=FALSE]
* useExistingTestFile - do not remove test file before write access [0=FALSE]
* segmentCount - number of segments in file [1]
NOTES: * a segment is a contiguous chunk of data
accessed by multiple clients each writing/
reading their own contiguous data;
comprised of blocks accessed by multiple
clients
* with HDF5 this repeats the pattern of an
entire shared dataset
* blockSize - size (in bytes) of a contiguous chunk of data
accessed by a single client; it is comprised of one
or more transfers [1048576]
* transferSize - size (in bytes) of a single data buffer to be
transferred in a single I/O call [262144]
* verbose - output information [0]
NOTE: this can be set to levels 0-5 on the command
line; repeating the -v flag will increase
verbosity level
* setTimeStampSignature - set value for time stamp signature [0]
NOTE: used to rerun tests with the exact data
pattern by setting data signature to contain
positive integer value as timestamp to be
written in data file; if set to 0, is
disabled
* showHelp - display options and help [0=FALSE]
* storeFileOffset - use file offset as stored signature when writing
file [0=FALSE]
NOTE: this will affect performance measurements
* maxTimeDuration - max time in minutes to run tests [0]
NOTES: * setting this to zero (0) unsets this option
* this option allows the current read/write
to complete without interruption
* deadlineForStonewalling - seconds before stopping write or read phase [0]
NOTES: * used for measuring the amount of data moved
in a fixed time. After the barrier, each
task starts its own timer, begins moving
data, and the stops moving data at a pre-
arranged time. Instead of measuring the
amount of time to move a fixed amount of
data, this option measures the amount of
data moved in a fixed amount of time. The
objective is to prevent tasks slow to
complete from skewing the performance.
* setting this to zero (0) unsets this option
* this option is incompatible w/data checking
* randomOffset - access is to random, not sequential, offsets within a file [0=FALSE]
NOTES: * this option is currently incompatible with:
-checkRead
-storeFileOffset
-MPIIO collective or useFileView
-HDF5 or NCMPI
POSIX-ONLY:
===========
* useO_DIRECT - use O_DIRECT for POSIX, bypassing I/O buffers [0]
* singleXferAttempt - will not continue to retry transfer entire buffer
until it is transferred [0=FALSE]
NOTE: when performing a write() or read() in POSIX,
there is no guarantee that the entire
requested size of the buffer will be
transferred; this flag keeps the retrying a
single transfer until it completes or returns
an error
* fsyncPerWrite - perform fsync after each POSIX write [0=FALSE]
* fsync - perform fsync after POSIX write close [0=FALSE]
MPIIO-ONLY:
===========
* preallocate - preallocate the entire file before writing [0=FALSE]
* useFileView - use an MPI datatype for setting the file view option
to use individual file pointer [0=FALSE]
NOTE: default IOR uses explicit file pointers
* useSharedFilePointer - use a shared file pointer [0=FALSE] (not working)
NOTE: default IOR uses explicit file pointers
* useStridedDatatype - create a datatype (max=2GB) for strided access; akin
to MULTIBLOCK_REGION_SIZE [0] (not working)
HDF5-ONLY:
==========
* individualDataSets - within a single file each task will access its own
dataset [0=FALSE] (not working)
NOTE: default IOR creates a dataset the size of
numTasks * blockSize to be accessed by all
tasks
* noFill - no pre-filling of data in HDF5 file creation [0=FALSE]
* setAlignment - HDF5 alignment in bytes (e.g.: 8, 4k, 2m, 1g) [1]
MPIIO-, HDF5-, AND NCMPI-ONLY:
==============================
* collective - uses collective operations for access [0=FALSE]
* showHints - show hint/value pairs attached to open file [0=FALSE]
NOTE: not available in NCMPI
LUSTRE-SPECIFIC:
================
* lustreStripeCount - set the lustre stripe count for the test file(s) [0]
* lustreStripeSize - set the lustre stripe size for the test file(s) [0]
* lustreStartOST - set the starting OST for the test file(s) [-1]
* lustreIgnoreLocks - disable lustre range locking [0]
***********************
* 6. VERBOSITY LEVELS *
***********************
The verbosity of output for IOR can be set with -v. Increasing the number of
-v instances on a command line sets the verbosity higher.
Here is an overview of the information shown for different verbosity levels:
0 - default; only bare essentials shown
1 - max clock deviation, participating tasks, free space, access pattern,
commence/verify access notification w/time
2 - rank/hostname, machine name, timer used, individual repetition
performance results, timestamp used for data signature
3 - full test details, transfer block/offset compared, individual data
checking errors, environment variables, task writing/reading file name,
all test operation times
4 - task id and offset for each transfer
5 - each 8-byte data signature comparison (WARNING: more data to STDOUT
than stored in file, use carefully)
********************
* 7. USING SCRIPTS *
********************
IOR can use a script with the command line. Any options on the command line
will be considered the default settings for running the script. (I.e.,
'IOR -W -f script' will have all tests in the script run with the -W option as
default.) The script itself can override these settings and may be set to run
run many different tests of IOR under a single execution. The command line is:
IOR/bin/IOR -f script
In IOR/scripts, there are scripts of testcases for simulating I/O behavior of
various application codes. Details are included in each script as necessary.
An example of a script:
===============> start script <===============
IOR START
api=[POSIX|MPIIO|HDF5|NCMPI]
testFile=testFile
hintsFileName=hintsFile
repetitions=8
multiFile=0
interTestDelay=5
readFile=1
writeFile=1
filePerProc=0
checkWrite=0
checkRead=0
keepFile=1
quitOnError=0
segmentCount=1
blockSize=32k
outlierThreshold=0
setAlignment=1
transferSize=32
singleXferAttempt=0
individualDataSets=0
verbose=0
numTasks=32
collective=1
preallocate=0
useFileView=0
keepFileWithError=0
setTimeStampSignature=0
useSharedFilePointer=0
useStridedDatatype=0
uniqueDir=0
fsync=0
storeFileOffset=0
maxTimeDuration=60
deadlineForStonewalling=0
useExistingTestFile=0
useO_DIRECT=0
showHints=0
showHelp=0
RUN
# additional tests are optional
<snip>
RUN
<snip>
RUN
IOR STOP
===============> stop script <===============
NOTES: * Not all test parameters need be set. The defaults can be viewed in
IOR/src/C/defaults.h.
* White space is ignored in script, as are comments starting with '#'.
****************************************
* 8. COMPATIBILITY WITH OLDER VERSIONS *
****************************************
1) IOR version 1 (c. 1996-2002) and IOR version 2 (c. 2003-present) are
incompatible. Input decks from one will not work on the other. As version
1 is not included in this release, this shouldn't be case for concern. All
subsequent compatibility issues are for IOR version 2.
2) IOR versions prior to release 2.8 provided data size and rates in powers
of two. E.g., 1 MB/sec referred to 1,048,576 bytes per second. With the
IOR release 2.8 and later versions, MB is now defined as 1,000,000 bytes
and MiB is 1,048,576 bytes.
3) In IOR versions 2.5.3 to 2.8.7, IOR could be run without any command line
options. This assumed that if both write and read options (-w -r) were
omitted, the run with them both set as default. Later, it became clear
that in certain cases (data checking, e.g.) this caused difficulties. In
IOR versions 2.8.8 and later, if not one of the -w -r -W or -R options is
set, then -w and -r are set implicitly.
*********************************
* 9. FREQUENTLY ASKED QUESTIONS *
*********************************
HOW DO I PERFORM MULTIPLE DATA CHECKS ON AN EXISTING FILE?
Use this command line: IOR -k -E -W -i 5 -o file
-k keeps the file after the access rather than deleting it
-E uses the existing file rather than truncating it first
-W performs the writecheck
-i number of iterations of checking
-o filename
On versions of IOR prior to 2.8.8, you need the -r flag also, otherwise
you'll first overwrite the existing file. (In earlier versions, omitting -w
and -r implied using both. This semantic has been subsequently altered to be
omitting -w, -r, -W, and -R implied using both -w and -r.)
If you're running new tests to create a file and want repeat data checking on
this file multiple times, there is an undocumented option for this. It's -O
multiReRead=1, and you'd need to have an IOR version compiled with the
USE_UNDOC_OPT=1 (in iordef.h). The command line would look like this:
IOR -k -E -w -W -i 5 -o file -O multiReRead=1
For the first iteration, the file would be written (w/o data checking). Then
for any additional iterations (four, in this example) the file would be
reread for whatever data checking option is used.
HOW DOES IOR CALCULATE PERFORMANCE?
IOR performs get a time stamp START, then has all participating tasks open a
shared or independent file, transfer data, close the file(s), and then get a
STOP time. A stat() or MPI_File_get_size() is performed on the file(s) and
compared against the aggregate amount of data transferred. If this value
does not match, a warning is issued and the amount of data transferred as
calculated from write(), e.g., return codes is used. The calculated
bandwidth is the amount of data transferred divided by the elapsed
STOP-minus-START time.
IOR also gets time stamps to report the open, transfer, and close times.
Each of these times is based on the earliest start time for any task and the
latest stop time for any task. Without using barriers between these
operations (-g), the sum of the open, transfer, and close times may not equal
the elapsed time from the first open to the last close.
HOW DO I ACCESS MULTIPLE FILE SYSTEMS IN IOR?
It is possible when using the filePerProc option to have tasks round-robin
across multiple file names. Rather than use a single file name '-o file',
additional names '-o file1@file2@file3' may be used. In this case, a file
per process would have three different file names (which may be full path
names) to access. The '@' delimiter is arbitrary, and may be set in the
FILENAME_DELIMITER definition in iordef.h.
Note that this option of multiple filenames only works with the filePerProc
-F option. This will not work for shared files.
HOW DO I BALANCE LOAD ACROSS MULTIPLE FILE SYSTEMS?
As for the balancing of files per file system where different file systems
offer different performance, additional instances of the same destination
path can generally achieve good balance.
For example, with FS1 getting 50% better performance than FS2, set the '-o'
flag such that there are additional instances of the FS1 directory. In this
case, '-o FS1/file@FS1/file@FS1/file@FS2/file@FS2/file' should adjust for
the performance difference and balance accordingly.
HOW DO I USE STONEWALLING?
To use stonewalling (-D), it's generally best to separate write testing from
read testing. Start with writing a file with '-D 0' (stonewalling disabled)
to determine how long the file takes to be written. If it takes 10 seconds
for the data transfer, run again with a shorter duration, '-D 7' e.g., to
stop before the file would be completed without stonewalling. For reading,
it's best to create a full file (not an incompletely written file from a
stonewalling run) and then run with stonewalling set on this preexisting
file. If a write and read test are performed in the same run with
stonewalling, it's likely that the read will encounter an error upon hitting
the EOF. Separating the runs can correct for this. E.g.,
IOR -w -k -o file -D 10 # write and keep file, stonewall after 10 seconds
IOR -r -E -o file -D 7 # read existing file, stonewall after 7 seconds
Also, when running multiple iterations of a read-only stonewall test, it may
be necessary to set the -D value high enough so that each iteration is not
reading from cache. Otherwise, in some cases, the first iteration may show
100 MB/s, the next 200 MB/s, the third 300 MB/s. Each of these tests is
actually reading the same amount from disk in the allotted time, but they
are also reading the cached data from the previous test each time to get the
increased performance. Setting -D high enough so that the cache is
overfilled will prevent this.
HOW DO I BYPASS CACHING WHEN READING BACK A FILE I'VE JUST WRITTEN?
One issue with testing file systems is handling cached data. When a file is
written, that data may be stored locally on the node writing the file. When
the same node attempts to read the data back from the file system either for
performance or data integrity checking, it may be reading from its own cache
rather from the file system.
The reorderTasks '-C' option attempts to address this by having a different
node read back data than wrote it. For example, node N writes the data to
file, node N+1 reads back the data for read performance, node N+2 reads back
the data for write data checking, and node N+3 reads the data for read data
checking, comparing this with the reread data from node N+4. The objective
is to make sure on file access that the data is not being read from cached
data.
Node 0: writes data
Node 1: reads data
Node 2: reads written data for write checking
Node 3: reads written data for read checking
Node 4: reads written data for read checking, comparing with Node 3
The algorithm for skipping from N to N+1, e.g., expects consecutive task
numbers on nodes (block assignment), not those assigned round robin (cyclic
assignment). For example, a test running 6 tasks on 3 nodes would expect
tasks 0,1 on node 0; tasks 2,3 on node 1; and tasks 4,5 on node 2. Were the
assignment for tasks-to-node in round robin fashion, there would be tasks 0,3
on node 0; tasks 1,4 on node 1; and tasks 2,5 on node 2. In this case, there
would be no expectation that a task would not be reading from data cached on
a node.
HOW DO I USE HINTS?
It is possible to pass hints to the I/O library or file system layers
following this form:
'setenv IOR_HINT__<layer>__<hint> <value>'
For example:
'setenv IOR_HINT__MPI__IBM_largeblock_io true'
'setenv IOR_HINT__GPFS__important_hint true'
or, in a file in the form:
'IOR_HINT__<layer>__<hint>=<value>'
Note that hints to MPI from the HDF5 or NCMPI layers are of the form:
'setenv IOR_HINT__MPI__<hint> <value>'
HOW DO I EXPLICITY SET THE FILE DATA SIGNATURE?
The data signature for a transfer contains the MPI task number, transfer-
buffer offset, and also timestamp for the start of iteration. As IOR works
with 8-byte long long ints, the even-numbered long longs written contain a
32-bit MPI task number and a 32-bit timestamp. The odd-numbered long longs
contain a 64-bit transferbuffer offset (or file offset if the '-l'
storeFileOffset option is used). To set the timestamp value, use '-G' or
setTimeStampSignature.
HOW DO I EASILY CHECK OR CHANGE A BYTE IN AN OUTPUT DATA FILE?
There is a simple utility IOR/src/C/cbif/cbif.c that may be built. This is a
stand-alone, serial application called cbif (Change Byte In File). The
utility allows a file offset to be checked, returning the data at that
location in IOR's data check format. It also allows a byte at that location
to be changed.
HOW DO I CORRECT FOR CLOCK SKEW BETWEEN NODES IN A CLUSTER?
To correct for clock skew between nodes, IOR compares times between nodes,
then broadcasts the root node's timestamp so all nodes can adjust by the
difference. To see an egregious outlier, use the '-j' option. Be sure
to set this value high enough to only show a node outside a certain time
from the mean.
WHAT HAPPENED TO THE GUI?
In versions of IOR earlier than 2.9.x, there was a GUI available. Over time
it became clear that it wasn't find enough use to warrant maintenance. It
was retired in IOR-2.10.x.
**************************
* 10. OUTPUT DESCRIPTION *
**************************
(FIXME -- this section needs updating and some rewrite.)
Output Statistics:
The quantity "aggregate operations/sec" was added to the existing "aggregate data rate" test log print file.
An "operation" is defined to be a write or read within an open/close [open/write|read/close].
Multiple writes or reads within an open/close are also counted as multiple operations.
Also various other test relevant quantities are printed on a single "grepable" line using the pattern EXCEL.
This way, output from large parameter space runs can easily be imported to excel for analysis. Below is an example.
grep EXCEL :IOR.o406550
Operation Max (MiB) Min (MiB) Mean (MiB) Std Dev Max (OPs) Min (OPs) Mean (OPs) Std Dev Mean(s)
--------- --------- --------- ---------- ------- --------- --------- ---------- ------- -------
read 309.30 17.20 164.67 73.80 309.30 17.20 164.67 73.80 0.06581
(line-continued)
#Tasks tPN reps fPP reord reordoff reordrand seed segcnt blksiz xsize aggsize
8 2 100 1 0 1 0 0 1 1048576 1048576 8388608 5 EXCEL
Where:
Max (MiB) - Maximum aggregate data rate of 100 iterations (reps)
Min (MiB) - Minumum aggregate data rate of 100 iterations (reps)
Mean(MiB) - Mean aggregate data rate of 100 iterations (reps)
Std Dev - Standard deviation aggregate data rate of 100 iterations (reps)
Max (OPs) - Maximum aggregate operations per second of 100 iterations (reps)
Min (OPs) - Minimum aggregate operations per second of 100 iterations (reps)
Mean (OPs)- Mean aggregate operations per second of 100 iterations (reps)
Std Dev - Standard deviation aggregate operations per second of 100 iteration (reps)
Mean(s) - Mean time per iteration (seconds)
#Tasks - number of I/O processes
tPN - number of I/O processes per node (per shared memory environment)
reps - number of times (iterations) each test is run.
The max,min,mean,ave,sdev above are calculated over "reps" tests
fPP - files per process
reord - constant node offset flag for reads
reordoff - node offset for reads
reordrand - random node offset flag for reads
seed - random seed for node random node offset
segcnt - number of seqments per file
blksiz - total MBytes written/read per process
xsize - total MBytes written/read per process per operation
aggsize - total Mbytes written/read by all processes per operations
5 - testnum
EXCEL - grep pattern for this summary print
More detail information can be obtained with AT LEAST "-v -v" [verbose=0] level and grepping "XXCEL".
This includes a file "contention" histogram showing the number of files accessed 0,1,2,3,... times for a specified random pattern.

24
scripts/exampleScript Normal file
View File

@ -0,0 +1,24 @@
IOR START
testFile = /tmp/work/swh13/testfile
filePerProc=1
api=POSIX
repetitions=2
verbose=1
reordertasksrandom=1
reordertasksrandomseed=-113
RUN
verbose = 2
repetitions=1#more foo
reordertasksconstant=1
#foobar
blockSize=10m
transferSize=128k
randomoffset=1
RUN
verbose = 0
#blockSize=
transferSize=64k
RUN
IOR STOP

93
scripts/run_script.cnl Normal file
View File

@ -0,0 +1,93 @@
#!/bin/bash -x
#PBS -N IOR
#PBS -j oe
#PBS -q batch
#PBS -A stf006
#PBS -V
#PBS -l walltime=0:60:00,size=8
VERS=IOR-2.10.1.ornl.16
WORK=/tmp/work/${USER}
echo $PBS_O_WORKDIR
cd /ccs/proj/quadcore
tar -czvf ${WORK}/${VERS}.tar.gz ./${VERS}
cd ${WORK}
rm -fr ./${VERS}
tar -xzvf ${WORK}/${VERS}.tar.gz
cd ${WORK}/${VERS}
gmake clean
gmake mpiio
EXEC=${WORK}/${VERS}/src/C/IOR
IODIR=/tmp/work/swh13/test_files_x
cd ${WORK}/${VERS}/tests
which mpirun
rm -fr $IODIR
mkdir $IODIR
let "w=128"
let "s=1024*1024"
let "i=3"
MPIRUN="aprun -n"
RESULTS="."
let "tid=1"
XFERS="1048576 262144 32768 4096 1024"
XFERS="262144"
for xfer in `echo $XFERS`
do
let "n=8"
until [ "$n" -gt 8 ]
do
let "m=$n/4"
#TESTS="POSIX MPIIO HDF5 NCMPI"
TESTS="POSIX MPIIO"
for test in `echo $TESTS`
do
runid="p$n.$xfer.${test}"
date
V=" "
BLOCKS="1 10 1 10 1 10"
for blocks in `echo $BLOCKS`
do
let "block=${xfer} * ${blocks}"
#fileperproc tests
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -w -z ${V} -F -o $IODIR/testwrite.${runid} -Y -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -w -z ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -C ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -C -Q $m ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -Z -Q $m ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -Z -Q $m -X 13 ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -Z -Q $m -X -13 ${V} -F -o $IODIR/testwrite.${runid} -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
#shared tests
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -w -z ${V} -o $IODIR/testwrite.${runid} -Y -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -w ${V} -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z ${V} -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
#test mutually exclusive options
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -C ${V} -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -Z ${V} -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -Z -C ${V} -o $IODIR/testwrite.${runid} -i${i} -m -t ${xfer} -b ${block} -d 0.0
let "tid=$tid + 17"
V=$V" -v"
done #blocks
date
done #test
let "n = $n * 2"
done #n
done #xfer
exit

93
scripts/run_script.linux Normal file
View File

@ -0,0 +1,93 @@
#!/bin/bash -x
#PBS -N IOR
#PBS -j oe
#PBS -q batch
#PBS -A stf006
#PBS -V
#PBS -l walltime=0:60:00,nodes=8:ppn=2
VERS=IOR-2.10.1
WORK=/tmp/work/${USER}
echo $PBS_O_WORKDIR
cd /ccs/proj/quadcore
tar -czvf ${WORK}/${VERS}.tar.gz ./${VERS}
cd ${WORK}
rm -fr ./${VERS}
tar -xzvf ${WORK}/${VERS}.tar.gz
cd ${WORK}/${VERS}
gmake clean
gmake mpiio
EXEC=${WORK}/${VERS}/src/C/IOR
IODIR=/tmp/work/swh13/test_files_x
cd ${WORK}/${VERS}/tests
which mpirun
rm -fr $IODIR
mkdir $IODIR
let "w=128"
let "s=1024*1024"
let "i=3"
MPIRUN="mpirun -np"
RESULTS="."
let "tid=1"
XFERS="1048576 262144 32768 4096 1024"
XFERS="262144"
for xfer in `echo $XFERS`
do
let "n=8"
until [ "$n" -gt 8 ]
do
let "m=$n/4"
#TESTS="POSIX MPIIO HDF5 NCMPI"
TESTS="POSIX MPIIO"
for test in `echo $TESTS`
do
runid="p$n.$xfer.${test}"
date
V=" "
BLOCKS="1 10 1 10 1 10"
for blocks in `echo $BLOCKS`
do
let "block=${xfer} * ${blocks}"
#fileperproc tests
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -w -z ${V} -F -o $IODIR/testwrite.${runid} -Y -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -w -z ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -C ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -C -Q $m ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -Z -Q $m ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -Z -Q $m -X 13 ${V} -F -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -Z -Q $m -X -13 ${V} -F -o $IODIR/testwrite.${runid} -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
#shared tests
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -w -z ${V} -o $IODIR/testwrite.${runid} -Y -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -w ${V} -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z ${V} -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
#test mutually exclusive options
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -C ${V} -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -z -Z ${V} -o $IODIR/testwrite.${runid} -k -e -i${i} -m -t ${xfer} -b ${block} -d 0.1
${MPIRUN} $n ${EXEC} -A ${tid} -a ${test} -r -Z -C ${V} -o $IODIR/testwrite.${runid} -i${i} -m -t ${xfer} -b ${block} -d 0.0
let "tid=$tid + 17"
V=$V" -v"
done #blocks
date
done #test
let "n = $n * 2"
done #n
done #xfer
exit

39
src/C/IOR-aiori.h Normal file
View File

@ -0,0 +1,39 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: IOR-aiori.h,v $
* $Revision: 1.1.1.1 $
* $Date: 2007/10/15 23:36:54 $
* $Author: rklundt $
*
* Purpose:
* This is a header file that contains the abstract prototypes
* needed for IOR.c.
*
\******************************************************************************/
#ifndef _IOR_AIORI_H
#define _IOR_AIORI_H
#include "IOR.h"
/**************************** P R O T O T Y P E S *****************************/
/* abstract IOR interfaces used in aiori-*.c */
void * (*IOR_Create) (char *, IOR_param_t *);
void * (*IOR_Open) (char *, IOR_param_t *);
IOR_offset_t (*IOR_Xfer) (int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
void (*IOR_Close) (void *, IOR_param_t *);
void (*IOR_Delete) (char *, IOR_param_t *);
void (*IOR_SetVersion) (IOR_param_t *);
void (*IOR_Fsync) (void *, IOR_param_t *);
IOR_offset_t (*IOR_GetFileSize) (IOR_param_t *, MPI_Comm, char *);
#endif /* not _IOR_AIORI_H */

2693
src/C/IOR.c Normal file

File diff suppressed because it is too large Load Diff

105
src/C/IOR.h Normal file
View File

@ -0,0 +1,105 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: IOR.h,v $
* $Revision: 1.2 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* This is a header file that contains the definitions and prototypes
* needed for IOR.c.
*
\******************************************************************************/
#ifndef _IOR_H
#define _IOR_H
#include "aiori.h" /* abstract IOR interfaces */
#include "iordef.h" /* IOR Definitions */
/*************************** D E F I N I T I O N S ****************************/
/* define the queuing structure for the test parameters */
typedef struct IOR_queue_t {
IOR_param_t testParameters;
struct IOR_queue_t * nextTest;
} IOR_queue_t;
/**************************** P R O T O T Y P E S *****************************/
/* functions used in IOR.c */
void AioriBind (char *);
void CheckForOutliers (IOR_param_t *, double **, int, int);
void CheckFileSize (IOR_param_t *, IOR_offset_t, int);
char * CheckTorF (char *);
size_t CompareBuffers (void *, void *, size_t,
IOR_offset_t, IOR_param_t *, int);
int CountErrors (IOR_param_t *, int, int);
int CountTasksPerNode(int, MPI_Comm);
void * CreateBuffer (size_t);
IOR_queue_t * CreateNewTest (int);
void DelaySecs (int);
void DisplayFreespace (IOR_param_t *);
void DisplayOutliers (int, double, char *, int, int);
void DisplayUsage (char **);
void DistributeHints (void);
void FillBuffer (void *, IOR_param_t *,
unsigned long long, int);
void FreeBuffers (int, void *, void *, void *, IOR_offset_t *);
void GetPlatformName (char *);
void GetTestFileName (char *, IOR_param_t *);
double GetTimeStamp (void);
char * HumanReadable (IOR_offset_t, int);
IOR_offset_t IOR_GetFileSize_POSIX (IOR_param_t *, MPI_Comm, char *);
IOR_offset_t IOR_GetFileSize_MPIIO (IOR_param_t *, MPI_Comm, char *);
char * LowerCase (char *);
void OutputToRoot (int, MPI_Comm, char *);
void PPDouble (int, double, char *);
char * PrependDir (IOR_param_t *, char *);
IOR_queue_t * ParseCommandLine (int, char **);
char ** ParseFileName (char *, int *);
void ReadCheck (void *, void *, void *, void *, IOR_param_t *,
IOR_offset_t, IOR_offset_t, IOR_offset_t *,
IOR_offset_t *, int, int *);
void ReduceIterResults(IOR_param_t *, double **, int, int);
int Regex (char *, char *);
void RemoveFile (char *, int, IOR_param_t *);
int Regex (char *, char *);
void SetupXferBuffers (void **, void **, void **,
IOR_param_t *, int, int);
IOR_queue_t * SetupTests (int, char **);
void ShowFileSystemSize (char *);
void ShowInfo (int, char **, IOR_param_t *);
void ShowSetup (IOR_param_t *);
void ShowTest (IOR_param_t *);
void SummarizeResults (IOR_param_t *);
void TestIoSys (IOR_param_t *);
double TimeDeviation (void);
void ValidTests (IOR_param_t *);
IOR_offset_t WriteOrRead (IOR_param_t *, void *, int);
void WriteTimes (IOR_param_t *, double **, int, int);
/* functions used in utilities.c */
char * CurrentTimeString(void);
void DumpBuffer (void *, size_t);
void ExtractHint (char *, char *, char *);
void SetHints (MPI_Info *, char *);
void ShowHints (MPI_Info *);
IOR_offset_t StringToBytes (char *);
#if USE_UNDOC_OPT
void CorruptFile (char *, IOR_param_t *, int, int);
void ModifyByteInFile (char *, IOR_offset_t, int);
#endif /* USE_UNDOC_OPTS */
void SeedRandGen (MPI_Comm);
#endif /* not _IOR_H */

69
src/C/Makefile Normal file
View File

@ -0,0 +1,69 @@
#/*****************************************************************************\
#* *
#* Copyright (c) 2003, The Regents of the University of California *
#* See the file COPYRIGHT for a complete copyright notice and license. *
#* *
#*******************************************************************************
#*
#* CVS info:
#* $RCSfile: Makefile,v $
#* $Revision: 1.1.1.1 $
#* $Date: 2007/10/15 23:36:54 $
#* $Author: rklundt $
#*
#* Purpose:
#* Make IOR executable.
#*
#* gmake posix -- IOR with only POSIX interfaces
#* gmake mpiio -- IOR with only POSIX and MPIIO interfaces
#* gmake hdf5 -- IOR with POSIX, MPIIO, and HDF5 interfaces
#* gmake ncmpi -- IOR with POSIX, MPIIO, and NCMPI interfaces
#* gmake all -- IOR with POSIX, MPIIO, HDF5, and NCMPI interfaces
#* gmake clean -- remove executable and object files
#*
#\*****************************************************************************/
include Makefile.config
# Requires GNU Make
OS=$(shell uname)
SRCS = IOR.c utilities.c parse_options.c
OBJS = $(SRCS:.c=.o)
posix: $(OBJS) aiori-POSIX.o aiori-noMPIIO.o aiori-noHDF5.o aiori-noNCMPI.o
$(CC) -o IOR $(OBJS) \
aiori-POSIX.o aiori-noMPIIO.o aiori-noHDF5.o aiori-noNCMPI.o \
$(LDFLAGS)
mpiio: $(OBJS) aiori-POSIX.o aiori-MPIIO.o aiori-noHDF5.o aiori-noNCMPI.o
$(CC) -o IOR $(OBJS) \
aiori-POSIX.o aiori-MPIIO.o aiori-noHDF5.o aiori-noNCMPI.o \
$(LDFLAGS)
hdf5: $(OBJS) aiori-POSIX.o aiori-MPIIO.o aiori-HDF5.o aiori-noNCMPI.o
$(CC) $(LDFLAGS_HDF5) -o IOR $(OBJS) \
aiori-POSIX.o aiori-MPIIO.o aiori-HDF5.o aiori-noNCMPI.o
ncmpi: $(OBJS) aiori-POSIX.o aiori-MPIIO.o aiori-noHDF5.o aiori-NCMPI.o
$(CC) $(LDFLAGS_NCMPI) -o IOR $(OBJS) \
aiori-POSIX.o aiori-MPIIO.o aiori-noHDF5.o aiori-NCMPI.o
all: $(OBJS) aiori-POSIX.o aiori-MPIIO.o aiori-HDF5.o aiori-NCMPI.o
$(CC) $(LDFLAGS_HDF5) $(LDFLAGS_NCMPI) -o IOR $(OBJS) \
aiori-POSIX.o aiori-MPIIO.o aiori-HDF5.o aiori-NCMPI.o
clean:
-rm -f *.o IOR
aiori-MPIIO.o: aiori-MPIIO.c
$(CC) -c aiori-MPIIO.c
aiori-HDF5.o: aiori-HDF5.c
$(CC) $(CCFLAGS_HDF5) -c aiori-HDF5.c
aiori-NCMPI.o: aiori-NCMPI.c
$(CC) $(CCFLAGS_NCMPI) -c aiori-NCMPI.c
.c.o:
$(CC) $(CCFLAGS) -c $<

90
src/C/Makefile.config Normal file
View File

@ -0,0 +1,90 @@
#/*****************************************************************************\
#* *
#* Copyright (c) 2003, The Regents of the University of California *
#* See the file COPYRIGHT for a complete copyright notice and license. *
#* *
#*******************************************************************************
#*
#* CVS info:
#* $RCSfile: Makefile.config,v $
#* $Revision: 1.3 $
#* $Date: 2008/12/02 17:12:14 $
#* $Author: rklundt $
#*
#* Purpose:
#* Maintain compilation settings for various platforms.
#*
#\*****************************************************************************/
################
# AIX SETTINGS #
################
CC.AIX = mpcc -q64
CCFLAGS.AIX = -g -D_LARGE_FILES
# -qwarn64 -qinfo=all -D_NO_MPI_TIMER
LDFLAGS.AIX = #-bmaxdata:0x80000000
HDF5_DIR.AIX = /usr/local/tools/hdf5/hdf5-1.6.5/parallel
#NCMPI_DIR.AIX = /usr/local/netcdf/parallel-netcdf-0.9.4_64bit
NCMPI_DIR.AIX = /g/g0/$(shell whoami)/LIBS/INSTALLS/parallel-netcdf-1.0.2pre2/aix_5_64_fed
###################
# IRIX64 SETTINGS #
###################
CC.IRIX64 = /usr/local/mpich-1.2.2/irix-n32/bin/mpicc
CCFLAGS.IRIX64 = -g
# -D_NO_MPI_TIMER
LDFLAGS.IRIX64 =
HDF5_DIR.IRIX64 = /usr/local/tools/hdf5/hdf5-1.6.0/parallel
NCMPI_DIR.IRIX64 =
##################
# LINUX SETTINGS #
##################
CC.Linux = mpicc
CCFLAGS.Linux = -g -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 #-D_MANUALLY_SET_LUSTRE_STRIPING -Wall -pedantic -D_NO_MPI_TIMER
#LDFLAGS.Linux = -L/usr/lib/mpi/mpi_gnu/lib -lmpio
#LDFLAGS.Linux = -L/usr/lib/mpi/mpi_intel/lib -lmpio
LDFLAGS.Linux =
#HDF5_DIR.Linux = /usr/local/tools/hdf5/hdf5-1.6.5/parallel
#NCMPI_DIR.Linux = /g/g0/$(shell whoami)/LIBS/INSTALLS/parallel-netcdf-1.0.2pre2/chaos_3_x86_elan3
##################
# SunOS SETTINGS #
##################
CC.SunOS = mpicc
CCFLAGS.SunOS = -g -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
LDFLAGS.SunOS = -Llib -lmpich
HDF5_DIR.SunOS =
NCMPI_DIR.SunOS =
################
# BGL SETTINGS #
################
CC.BGL = mpgcc
CCFLAGS.BGL = -g -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
LDFLAGS.BGL =
HDF5_DIR.BGL =
NCMPI_DIR.BGL =
#########################
# OSF1 (TRU64) SETTINGS #
#########################
CC.OSF1 = /usr/local/new_mpi/bin/mpicc
CCFLAGS.OSF1 = -g -ieee
LDFLAGS.OSF1 =
HDF5_DIR.OSF1 = /usr/local/hdf5/hdf5-1.4.5/mpich-1.2.4shm/prod/bit64/shared
NCMPI_DIR.OSF1 =
################################################################################
CC = $(CC.$(OS))
CCFLAGS = $(CCFLAGS.$(OS))
LDFLAGS = $(LDFLAGS.$(OS)) -lm
CCFLAGS_HDF5 = $(CCFLAGS.$(OS)) -I$(HDF5_DIR.$(OS))/include
LDFLAGS_HDF5 = $(LDFLAGS.$(OS)) -L$(HDF5_DIR.$(OS))/lib -lhdf5 -lm -lz
CCFLAGS_NCMPI = $(CCFLAGS.$(OS)) -I$(NCMPI_DIR.$(OS))/include
LDFLAGS_NCMPI = $(LDFLAGS.$(OS)) -L$(NCMPI_DIR.$(OS))/lib -lpnetcdf -lm

581
src/C/aiori-HDF5.c Normal file
View File

@ -0,0 +1,581 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: aiori-HDF5.c,v $
* $Revision: 1.2 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* Implementation of abstract I/O interface for HDF5.
*
\******************************************************************************/
#include "aiori.h" /* abstract IOR interface */
#include <errno.h> /* sys_errlist */
#include <stdio.h> /* only for fprintf() */
#include <stdlib.h>
#include <sys/stat.h>
#include <hdf5.h>
#define NUM_DIMS 1 /* number of dimensions to data set */
/******************************************************************************/
/*
* HDF5_CHECK will display a custom error message and then exit the program
*/
/*
* should use MPI_Abort(), not exit(), in this macro; some versions of
* MPI, however, hang with HDF5 property lists et al. left unclosed
*/
/*
* for versions later than hdf5-1.6, the H5Eget_[major|minor]() functions
* have been deprecated and replaced with H5Eget_msg()
*/
#if H5_VERS_MAJOR > 1 && H5_VERS_MINOR > 6
#define HDF5_CHECK(HDF5_RETURN, MSG) do { \
char resultString[1024]; \
\
if (HDF5_RETURN < 0) { \
fprintf(stdout, "** error **\n"); \
fprintf(stdout, "ERROR in %s (line %d): %s.\n", \
__FILE__, __LINE__, MSG); \
strcpy(resultString, H5Eget_major((H5E_major_t)HDF5_RETURN)); \
if (strcmp(resultString, "Invalid major error number") != 0) \
fprintf(stdout, "HDF5 %s\n", resultString); \
strcpy(resultString, H5Eget_minor((H5E_minor_t)HDF5_RETURN)); \
if (strcmp(resultString, "Invalid minor error number") != 0) \
fprintf(stdout, "%s\n", resultString); \
fprintf(stdout, "** exiting **\n"); \
exit(-1); \
} \
} while(0)
#else /* ! (H5_VERS_MAJOR > 1 && H5_VERS_MINOR > 6) */
#define HDF5_CHECK(HDF5_RETURN, MSG) do { \
char resultString[1024]; \
\
if (HDF5_RETURN < 0) { \
fprintf(stdout, "** error **\n"); \
fprintf(stdout, "ERROR in %s (line %d): %s.\n", \
__FILE__, __LINE__, MSG); \
/* \
* H5Eget_msg(hid_t mesg_id, H5E_type_t* mesg_type, \
* char* mesg, size_t size) \
*/ \
fprintf(stdout, "** exiting **\n"); \
exit(-1); \
} \
} while(0)
#endif /* H5_VERS_MAJOR > 1 && H5_VERS_MINOR > 6 */
/**************************** P R O T O T Y P E S *****************************/
IOR_offset_t SeekOffset_HDF5 (void *, IOR_offset_t, IOR_param_t *);
void SetHints (MPI_Info *, char *);
void SetupDataSet_HDF5(void *, IOR_param_t *);
void ShowHints (MPI_Info *);
/************************** D E C L A R A T I O N S ***************************/
extern int errno, /* error number */
rank,
rankOffset,
verbose; /* verbose output */
extern MPI_Comm testComm;
static hid_t xferPropList; /* xfer property list */
hid_t dataSet; /* data set id */
hid_t dataSpace; /* data space id */
hid_t fileDataSpace; /* file data space id */
hid_t memDataSpace; /* memory data space id */
int newlyOpenedFile; /* newly opened file */
/***************************** F U N C T I O N S ******************************/
/******************************************************************************/
/*
* Create and open a file through the HDF5 interface.
*/
void *
IOR_Create_HDF5(char * testFileName,
IOR_param_t * param)
{
return IOR_Open_HDF5(testFileName, param);
} /* IOR_Create_HDF5() */
/******************************************************************************/
/*
* Open a file through the HDF5 interface.
*/
void *
IOR_Open_HDF5(char * testFileName,
IOR_param_t * param)
{
hid_t accessPropList,
createPropList;
hsize_t memStart[NUM_DIMS],
dataSetDims[NUM_DIMS],
memStride[NUM_DIMS],
memCount[NUM_DIMS],
memBlock[NUM_DIMS],
memDataSpaceDims[NUM_DIMS];
int tasksPerDataSet;
unsigned fd_mode = (unsigned)0;
hid_t *fd;
MPI_Comm comm;
MPI_Info mpiHints = MPI_INFO_NULL;
fd = (hid_t *)malloc(sizeof(hid_t));
if (fd == NULL) ERR("Unable to malloc file descriptor");
/*
* HDF5 uses different flags than those for POSIX/MPIIO
*/
if (param->open == WRITE) { /* WRITE flags */
param->openFlags = IOR_TRUNC;
} else { /* READ or check WRITE/READ flags */
param->openFlags = IOR_RDONLY;
}
/* set IOR file flags to HDF5 flags */
/* -- file open flags -- */
if (param->openFlags & IOR_RDONLY) {fd_mode |= H5F_ACC_RDONLY;}
if (param->openFlags & IOR_WRONLY) {
fprintf(stdout, "File write only not implemented in HDF5\n");
}
if (param->openFlags & IOR_RDWR) {fd_mode |= H5F_ACC_RDWR;}
if (param->openFlags & IOR_APPEND) {
fprintf(stdout, "File append not implemented in HDF5\n");
}
if (param->openFlags & IOR_CREAT) {fd_mode |= H5F_ACC_CREAT;}
if (param->openFlags & IOR_EXCL) {fd_mode |= H5F_ACC_EXCL;}
if (param->openFlags & IOR_TRUNC) {fd_mode |= H5F_ACC_TRUNC;}
if (param->openFlags & IOR_DIRECT) {
fprintf(stdout, "O_DIRECT not implemented in HDF5\n");
}
/* set up file creation property list */
createPropList = H5Pcreate(H5P_FILE_CREATE);
HDF5_CHECK(createPropList, "cannot create file creation property list");
/* set size of offset and length used to address HDF5 objects */
HDF5_CHECK(H5Pset_sizes(createPropList, sizeof(hsize_t), sizeof(hsize_t)),
"cannot set property list properly");
/* set up file access property list */
accessPropList = H5Pcreate(H5P_FILE_ACCESS);
HDF5_CHECK(accessPropList, "cannot create file access property list");
/*
* someday HDF5 implementation will allow subsets of MPI_COMM_WORLD
*/
/* store MPI communicator info for the file access property list */
if (param->filePerProc) {
comm = MPI_COMM_SELF;
} else {
comm = testComm;
}
SetHints(&mpiHints, param->hintsFileName);
/*
* note that with MP_HINTS_FILTERED=no, all key/value pairs will
* be in the info object. The info object that is attached to
* the file during MPI_File_open() will only contain those pairs
* deemed valid by the implementation.
*/
/* show hints passed to file */
if (rank == 0 && param->showHints) {
fprintf(stdout, "\nhints passed to access property list {\n");
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
}
HDF5_CHECK(H5Pset_fapl_mpio(accessPropList, comm, mpiHints),
"cannot set file access property list");
/* set alignment */
HDF5_CHECK(H5Pset_alignment(accessPropList, param->setAlignment,
param->setAlignment), "cannot set alignment");
/* open file */
if (param->open == WRITE) { /* WRITE */
*fd = H5Fcreate(testFileName, fd_mode,
createPropList, accessPropList);
HDF5_CHECK(*fd, "cannot create file");
} else { /* READ or CHECK */
*fd = H5Fopen(testFileName, fd_mode, accessPropList);
HDF5_CHECK(*fd, "cannot open file");
}
/* show hints actually attached to file handle */
if (param->showHints || (1) /* WEL - this needs fixing */) {
if (rank == 0 && (param->showHints) /* WEL - this needs fixing */) {
WARN("showHints not working for HDF5");
}
} else {
MPI_Info mpiHintsCheck = MPI_INFO_NULL;
hid_t apl;
apl = H5Fget_access_plist(*fd);
HDF5_CHECK(H5Pget_fapl_mpio(apl, &comm, &mpiHintsCheck),
"cannot get info object through HDF5");
if (rank == 0) {
fprintf(stdout,
"\nhints returned from opened file (HDF5) {\n");
ShowHints(&mpiHintsCheck);
fprintf(stdout, "}\n");
if (1 == 1) { /* request the MPIIO file handle and its hints */
MPI_File * fd_mpiio;
HDF5_CHECK(H5Fget_vfd_handle(*fd, apl, (void **)&fd_mpiio),
"cannot get MPIIO file handle");
MPI_CHECK(MPI_File_get_info(*fd_mpiio, &mpiHintsCheck),
"cannot get info object through MPIIO");
fprintf(stdout,
"\nhints returned from opened file (MPIIO) {\n");
ShowHints(&mpiHintsCheck);
fprintf(stdout, "}\n");
}
}
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
}
/* this is necessary for resetting various parameters
needed for reopening and checking the file */
newlyOpenedFile = TRUE;
HDF5_CHECK(H5Pclose(createPropList), "cannot close creation property list");
HDF5_CHECK(H5Pclose(accessPropList), "cannot close access property list");
/* create property list for serial/parallel access */
xferPropList = H5Pcreate(H5P_DATASET_XFER);
HDF5_CHECK(xferPropList, "cannot create transfer property list");
/* set data transfer mode */
if (param->collective) {
HDF5_CHECK(H5Pset_dxpl_mpio(xferPropList, H5FD_MPIO_COLLECTIVE),
"cannot set collective data transfer mode");
} else {
HDF5_CHECK(H5Pset_dxpl_mpio(xferPropList, H5FD_MPIO_INDEPENDENT),
"cannot set independent data transfer mode");
}
/* set up memory data space for transfer */
memStart[0] = (hsize_t)0;
memCount[0] = (hsize_t)1;
memStride[0] = (hsize_t)(param->transferSize / sizeof(IOR_size_t));
memBlock[0] = (hsize_t)(param->transferSize / sizeof(IOR_size_t));
memDataSpaceDims[0] = (hsize_t)param->transferSize;
memDataSpace = H5Screate_simple(NUM_DIMS, memDataSpaceDims, NULL);
HDF5_CHECK(memDataSpace, "cannot create simple memory data space");
/* define hyperslab for memory data space */
HDF5_CHECK(H5Sselect_hyperslab(memDataSpace, H5S_SELECT_SET,
memStart, memStride, memCount, memBlock),
"cannot create hyperslab");
/* set up parameters for fpp or different dataset count */
if (param->filePerProc) {
tasksPerDataSet = 1;
} else {
if (param->individualDataSets) {
/* each task in segment has single data set */
tasksPerDataSet = 1;
} else {
/* share single data set across all tasks in segment */
tasksPerDataSet = param->numTasks;
}
}
dataSetDims[0] = (hsize_t)((param->blockSize / sizeof(IOR_size_t))
* tasksPerDataSet);
/* create a simple data space containing information on size
and shape of data set, and open it for access */
dataSpace = H5Screate_simple(NUM_DIMS, dataSetDims, NULL);
HDF5_CHECK(dataSpace, "cannot create simple data space");
return(fd);
} /* IOR_Open_HDF5() */
/******************************************************************************/
/*
* Write or read access to file using the HDF5 interface.
*/
IOR_offset_t
IOR_Xfer_HDF5(int access,
void * fd,
IOR_size_t * buffer,
IOR_offset_t length,
IOR_param_t * param)
{
static int firstReadCheck = FALSE,
startNewDataSet;
IOR_offset_t segmentPosition,
segmentSize;
/*
* this toggle is for the read check operation, which passes through
* this function twice; note that this function will open a data set
* only on the first read check and close only on the second
*/
if (access == READCHECK) {
if (firstReadCheck == TRUE) {
firstReadCheck = FALSE;
} else {
firstReadCheck = TRUE;
}
}
/* determine by offset if need to start new data set */
if (param->filePerProc == TRUE) {
segmentPosition = (IOR_offset_t)0;
segmentSize = param->blockSize;
} else {
segmentPosition = (IOR_offset_t)((rank + rankOffset) % param->numTasks)
* param->blockSize;
segmentSize = (IOR_offset_t)(param->numTasks) * param->blockSize;
}
if ((IOR_offset_t)((param->offset - segmentPosition) % segmentSize) == 0) {
/*
* ordinarily start a new data set, unless this is the
* second pass through during a read check
*/
startNewDataSet = TRUE;
if (access == READCHECK && firstReadCheck != TRUE) {
startNewDataSet = FALSE;
}
}
/* create new data set */
if (startNewDataSet == TRUE) {
/* if just opened this file, no data set to close yet */
if (newlyOpenedFile != TRUE) {
HDF5_CHECK(H5Dclose(dataSet), "cannot close data set");
HDF5_CHECK(H5Sclose(fileDataSpace),
"cannot close file data space");
}
SetupDataSet_HDF5(fd, param);
}
SeekOffset_HDF5(fd, param->offset, param);
/* this is necessary to reset variables for reaccessing file */
startNewDataSet = FALSE;
newlyOpenedFile = FALSE;
/* access the file */
if (access == WRITE) { /* WRITE */
HDF5_CHECK(H5Dwrite(dataSet, H5T_NATIVE_LLONG,
memDataSpace, fileDataSpace,
xferPropList, buffer),
"cannot write to data set");
} else { /* READ or CHECK */
HDF5_CHECK(H5Dread(dataSet, H5T_NATIVE_LLONG,
memDataSpace, fileDataSpace,
xferPropList, buffer),
"cannot read from data set");
}
return(length);
} /* IOR_Xfer_HDF5() */
/******************************************************************************/
/*
* Perform fsync().
*/
void
IOR_Fsync_HDF5(void * fd, IOR_param_t * param)
{
;
} /* IOR_Fsync_HDF5() */
/******************************************************************************/
/*
* Close a file through the HDF5 interface.
*/
void
IOR_Close_HDF5(void * fd,
IOR_param_t * param)
{
if (param->fd_fppReadCheck == NULL) {
HDF5_CHECK(H5Dclose(dataSet), "cannot close data set");
HDF5_CHECK(H5Sclose(dataSpace), "cannot close data space");
HDF5_CHECK(H5Sclose(fileDataSpace), "cannot close file data space");
HDF5_CHECK(H5Sclose(memDataSpace), "cannot close memory data space");
HDF5_CHECK(H5Pclose(xferPropList),
" cannot close transfer property list");
}
HDF5_CHECK(H5Fclose(*(hid_t *)fd), "cannot close file");
free(fd);
} /* IOR_Close_HDF5() */
/******************************************************************************/
/*
* Delete a file through the HDF5 interface.
*/
void
IOR_Delete_HDF5(char * testFileName, IOR_param_t * param)
{
if (unlink(testFileName) != 0) WARN("cannot delete file");
} /* IOR_Delete_HDF5() */
/******************************************************************************/
/*
* Determine api version.
*/
void
IOR_SetVersion_HDF5(IOR_param_t *test)
{
unsigned major, minor, release;
if (H5get_libversion(&major, &minor, &release) < 0) {
WARN("cannot get HDF5 library version");
} else {
sprintf(test->apiVersion, "%s-%u.%u.%u",
test->api, major, minor, release);
}
#ifndef H5_HAVE_PARALLEL
strcat(test->apiVersion, " (Serial)");
#else /* H5_HAVE_PARALLEL */
strcat(test->apiVersion, " (Parallel)");
#endif /* not H5_HAVE_PARALLEL */
} /* IOR_SetVersion_HDF5() */
/************************ L O C A L F U N C T I O N S ***********************/
/******************************************************************************/
/*
* Seek to offset in file using the HDF5 interface and set up hyperslab.
*/
IOR_offset_t
SeekOffset_HDF5(void *fd,
IOR_offset_t offset,
IOR_param_t * param)
{
IOR_offset_t segmentSize;
hsize_t hsStride[NUM_DIMS],
hsCount[NUM_DIMS],
hsBlock[NUM_DIMS];
hsize_t hsStart[NUM_DIMS];
if (param->filePerProc == TRUE) {
segmentSize = (IOR_offset_t)param->blockSize;
} else {
segmentSize = (IOR_offset_t)(param->numTasks) * param->blockSize;
}
/* create a hyperslab representing the file data space */
if (param->individualDataSets) {
/* start at zero offset if not */
hsStart[0] = (hsize_t)((offset % param->blockSize)
/ sizeof(IOR_size_t));
} else {
/* start at a unique offset if shared */
hsStart[0] = (hsize_t)((offset % segmentSize) / sizeof(IOR_size_t));
}
hsCount[0] = (hsize_t)1;
hsStride[0] = (hsize_t)(param->transferSize / sizeof(IOR_size_t));
hsBlock[0] = (hsize_t)(param->transferSize / sizeof(IOR_size_t));
/* retrieve data space from data set for hyperslab */
fileDataSpace = H5Dget_space(dataSet);
HDF5_CHECK(fileDataSpace, "cannot get data space from data set");
HDF5_CHECK(H5Sselect_hyperslab(fileDataSpace, H5S_SELECT_SET,
hsStart, hsStride, hsCount, hsBlock),
"cannot select hyperslab");
return(offset);
} /* SeekOffset_HDF5() */
/******************************************************************************/
/*
* Create HDF5 data set.
*/
void
SetupDataSet_HDF5(void * fd,
IOR_param_t * param)
{
char dataSetName[MAX_STR];
hid_t dataSetPropList;
int dataSetID;
static int dataSetSuffix = 0;
/* may want to use an extendable dataset (H5S_UNLIMITED) someday */
/* may want to use a chunked dataset (H5S_CHUNKED) someday */
/* need to reset suffix counter if newly-opened file */
if (newlyOpenedFile) dataSetSuffix = 0;
/* may want to use individual access to each data set someday */
if (param->individualDataSets) {
dataSetID = (rank + rankOffset) % param->numTasks;
} else {
dataSetID = 0;
}
sprintf(dataSetName, "%s-%04d.%04d", "Dataset", dataSetID, dataSetSuffix++);
if (param->open == WRITE) { /* WRITE */
/* create data set */
dataSetPropList = H5Pcreate(H5P_DATASET_CREATE);
/* check if hdf5 available */
#if defined (H5_VERS_MAJOR) && defined (H5_VERS_MINOR)
/* no-fill option not available until hdf5-1.6.x */
#if (H5_VERS_MAJOR > 0 && H5_VERS_MINOR > 5)
if (param->noFill == TRUE) {
if (rank == 0 && verbose >= VERBOSE_1) {
fprintf(stdout, "\nusing 'no fill' option\n");
}
HDF5_CHECK(H5Pset_fill_time(dataSetPropList,
H5D_FILL_TIME_NEVER),
"cannot set fill time for property list");
}
#else
char errorString[MAX_STR];
sprintf(errorString, "'no fill' option not available in %s", test->apiVersion);
ERR(errorString);
#endif
#else
WARN("unable to determine HDF5 version for 'no fill' usage");
#endif
dataSet = H5Dcreate(*(hid_t *)fd, dataSetName, H5T_NATIVE_LLONG,
dataSpace, dataSetPropList);
HDF5_CHECK(dataSet, "cannot create data set");
} else { /* READ or CHECK */
dataSet = H5Dopen(*(hid_t *)fd, dataSetName);
HDF5_CHECK(dataSet, "cannot create data set");
}
} /* SetupDataSet_HDF5() */
/******************************************************************************/
/*
* Use MPIIO call to get file size.
*/
IOR_offset_t
IOR_GetFileSize_HDF5(IOR_param_t * test,
MPI_Comm testComm,
char * testFileName)
{
return(IOR_GetFileSize_MPIIO(test, testComm, testFileName));
} /* IOR_GetFileSize_HDF5() */

470
src/C/aiori-MPIIO.c Normal file
View File

@ -0,0 +1,470 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: aiori-MPIIO.c,v $
* $Revision: 1.2 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* Implementation of abstract I/O interface for MPIIO.
*
\******************************************************************************/
#include "aiori.h" /* abstract IOR interface */
#include <errno.h> /* sys_errlist */
#include <stdio.h> /* only for fprintf() */
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#ifndef MPIAPI
# define MPIAPI /* defined as __stdcall on Windows */
#endif
/**************************** P R O T O T Y P E S *****************************/
static IOR_offset_t SeekOffset_MPIIO (MPI_File, IOR_offset_t,
IOR_param_t *);
void SetHints (MPI_Info *, char *);
void ShowHints (MPI_Info *);
/************************** D E C L A R A T I O N S ***************************/
extern int errno;
extern int rank;
extern int rankOffset;
extern int verbose;
extern MPI_Comm testComm;
/***************************** F U N C T I O N S ******************************/
/******************************************************************************/
/*
* Create and open a file through the MPIIO interface.
*/
void *
IOR_Create_MPIIO(char * testFileName,
IOR_param_t * param)
{
return IOR_Open_MPIIO(testFileName, param);
} /* IOR_Create_MPIIO() */
/******************************************************************************/
/*
* Open a file through the MPIIO interface. Setup file view.
*/
void *
IOR_Open_MPIIO(char * testFileName,
IOR_param_t * param)
{
int fd_mode = (int)0,
offsetFactor,
tasksPerFile,
transfersPerBlock = param->blockSize
/ param->transferSize;
struct fileTypeStruct {
int globalSizes[2],
localSizes[2],
startIndices[2];
} fileTypeStruct;
MPI_File * fd;
MPI_Comm comm;
MPI_Info mpiHints = MPI_INFO_NULL;
fd = (MPI_File *)malloc(sizeof(MPI_File));
if (fd == NULL) ERR("Unable to malloc MPI_File");
*fd = 0;
/* set IOR file flags to MPIIO flags */
/* -- file open flags -- */
if (param->openFlags & IOR_RDONLY) {fd_mode |= MPI_MODE_RDONLY;}
if (param->openFlags & IOR_WRONLY) {fd_mode |= MPI_MODE_WRONLY;}
if (param->openFlags & IOR_RDWR) {fd_mode |= MPI_MODE_RDWR;}
if (param->openFlags & IOR_APPEND) {fd_mode |= MPI_MODE_APPEND;}
if (param->openFlags & IOR_CREAT) {fd_mode |= MPI_MODE_CREATE;}
if (param->openFlags & IOR_EXCL) {fd_mode |= MPI_MODE_EXCL;}
if (param->openFlags & IOR_TRUNC) {
fprintf(stdout, "File truncation not implemented in MPIIO\n");
}
if (param->openFlags & IOR_DIRECT) {
fprintf(stdout, "O_DIRECT not implemented in MPIIO\n");
}
/*
* MPI_MODE_UNIQUE_OPEN mode optimization eliminates the overhead of file
* locking. Only open a file in this mode when the file will not be con-
* currently opened elsewhere, either inside or outside the MPI environment.
*/
fd_mode |= MPI_MODE_UNIQUE_OPEN;
if (param->filePerProc) {
comm = MPI_COMM_SELF;
} else {
comm = testComm;
}
SetHints(&mpiHints, param->hintsFileName);
/*
* note that with MP_HINTS_FILTERED=no, all key/value pairs will
* be in the info object. The info object that is attached to
* the file during MPI_File_open() will only contain those pairs
* deemed valid by the implementation.
*/
/* show hints passed to file */
if (rank == 0 && param->showHints) {
fprintf(stdout, "\nhints passed to MPI_File_open() {\n");
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
}
MPI_CHECK(MPI_File_open(comm, testFileName, fd_mode, mpiHints, fd),
"cannot open file");
/* show hints actually attached to file handle */
if (rank == 0 && param->showHints) {
MPI_CHECK(MPI_File_get_info(*fd, &mpiHints),
"cannot get file info");
fprintf(stdout, "\nhints returned from opened file {\n");
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
}
/* preallocate space for file */
if (param->preallocate && param->open == WRITE) {
MPI_CHECK(MPI_File_preallocate(*fd,
(MPI_Offset)(param->segmentCount*param->blockSize*param->numTasks)),
"cannot preallocate file");
}
/* create file view */
if (param->useFileView) {
/* create contiguous transfer datatype */
MPI_CHECK(MPI_Type_contiguous(param->transferSize / sizeof(IOR_size_t),
MPI_LONG_LONG_INT, &param->transferType),
"cannot create contiguous datatype");
MPI_CHECK(MPI_Type_commit(&param->transferType),
"cannot commit datatype");
if (param->filePerProc) {
offsetFactor = 0;
tasksPerFile = 1;
} else {
offsetFactor = (rank + rankOffset) % param->numTasks;
tasksPerFile = param->numTasks;
}
/*
* create file type using subarray
*/
fileTypeStruct.globalSizes[0] = 1;
fileTypeStruct.globalSizes[1] = transfersPerBlock * tasksPerFile;
fileTypeStruct.localSizes[0] = 1;
fileTypeStruct.localSizes[1] = transfersPerBlock;
fileTypeStruct.startIndices[0] = 0;
fileTypeStruct.startIndices[1] = transfersPerBlock * offsetFactor;
MPI_CHECK(MPI_Type_create_subarray(2, fileTypeStruct.globalSizes,
fileTypeStruct.localSizes,
fileTypeStruct.startIndices,
MPI_ORDER_C, param->transferType,
&param->fileType),
"cannot create subarray");
MPI_CHECK(MPI_Type_commit(&param->fileType), "cannot commit datatype");
MPI_CHECK(MPI_File_set_view(*fd, (MPI_Offset)0,
param->transferType, param->fileType,
"native", (MPI_Info)MPI_INFO_NULL),
"cannot set file view");
}
return((void *)fd);
} /* IOR_Open_MPIIO() */
/******************************************************************************/
/*
* Write or read access to file using the MPIIO interface.
*/
IOR_offset_t
IOR_Xfer_MPIIO(int access,
void * fd,
IOR_size_t * buffer,
IOR_offset_t length,
IOR_param_t * param)
{
int (MPIAPI *Access) (MPI_File, void *, int,
MPI_Datatype, MPI_Status *);
int (MPIAPI *Access_at) (MPI_File, MPI_Offset, void *, int,
MPI_Datatype,MPI_Status *);
int (MPIAPI *Access_all) (MPI_File, void *, int,
MPI_Datatype, MPI_Status *);
int (MPIAPI *Access_at_all) (MPI_File, MPI_Offset, void *, int,
MPI_Datatype, MPI_Status *);
/*
* this needs to be properly implemented:
*
* int (*Access_ordered)(MPI_File, void *, int,
* MPI_Datatype, MPI_Status *);
*/
MPI_Status status;
/* point functions to appropriate MPIIO calls */
if (access == WRITE) { /* WRITE */
Access = MPI_File_write;
Access_at = MPI_File_write_at;
Access_all = MPI_File_write_all;
Access_at_all = MPI_File_write_at_all;
/*
* this needs to be properly implemented:
*
* Access_ordered = MPI_File_write_ordered;
*/
} else { /* READ or CHECK */
Access = MPI_File_read;
Access_at = MPI_File_read_at;
Access_all = MPI_File_read_all;
Access_at_all = MPI_File_read_at_all;
/*
* this needs to be properly implemented:
*
* Access_ordered = MPI_File_read_ordered;
*/
}
/*
* 'useFileView' uses derived datatypes and individual file pointers
*/
if (param->useFileView) {
/* find offset in file */
if (SeekOffset_MPIIO(*(MPI_File *)fd, param->offset, param) < 0) {
/* if unsuccessful */
length = -1;
} else {
/*
* 'useStridedDatatype' fits multi-strided pattern into a datatype;
* must use 'length' to determine repetitions (fix this for
* multi-segments someday, WEL):
* e.g., 'IOR -s 2 -b 32K -t 32K -a MPIIO -S'
*/
if (param->useStridedDatatype) {
length = param->segmentCount;
} else {
length = 1;
}
if (param->collective) {
/* individual, collective call */
MPI_CHECK(Access_all(*(MPI_File *)fd, buffer, length,
param->transferType, &status),
"cannot access collective");
} else {
/* individual, noncollective call */
MPI_CHECK(Access(*(MPI_File *)fd, buffer, length,
param->transferType, &status),
"cannot access noncollective");
}
length *= param->transferSize; /* for return value in bytes */
}
} else {
/*
* !useFileView does not use derived datatypes, but it uses either
* shared or explicit file pointers
*/
if (param->useSharedFilePointer) {
/* find offset in file */
if (SeekOffset_MPIIO(*(MPI_File *)fd, param->offset, param) < 0) {
/* if unsuccessful */
length = -1;
} else {
/* shared, collective call */
/*
* this needs to be properly implemented:
*
* MPI_CHECK(Access_ordered(fd.MPIIO, buffer, length,
* MPI_BYTE, &status),
* "cannot access shared, collective");
*/
fprintf(stdout, "useSharedFilePointer not implemented\n");
}
} else {
if (param->collective) {
/* explicit, collective call */
MPI_CHECK(Access_at_all(*(MPI_File *)fd, param->offset,
buffer, length, MPI_BYTE, &status),
"cannot access explicit, collective");
} else {
/* explicit, noncollective call */
MPI_CHECK(Access_at(*(MPI_File *)fd, param->offset, buffer,
length, MPI_BYTE, &status),
"cannot access explicit, noncollective");
}
}
}
return(length);
} /* IOR_Xfer_MPIIO() */
/******************************************************************************/
/*
* Perform fsync().
*/
void
IOR_Fsync_MPIIO(void * fd, IOR_param_t * param)
{
;
} /* IOR_Fsync_MPIIO() */
/******************************************************************************/
/*
* Close a file through the MPIIO interface.
*/
void
IOR_Close_MPIIO(void * fd,
IOR_param_t * param)
{
MPI_CHECK(MPI_File_close((MPI_File *)fd), "cannot close file");
if ((param->useFileView == TRUE) && (param->fd_fppReadCheck == NULL)) {
/*
* need to free the datatype, so done in the close process
*/
MPI_CHECK(MPI_Type_free(&param->fileType),
"cannot free MPI file datatype");
MPI_CHECK(MPI_Type_free(&param->transferType),
"cannot free MPI transfer datatype");
}
free(fd);
} /* IOR_Close_MPIIO() */
/******************************************************************************/
/*
* Delete a file through the MPIIO interface.
*/
void
IOR_Delete_MPIIO(char * testFileName, IOR_param_t * param)
{
MPI_CHECK(MPI_File_delete(testFileName, (MPI_Info)MPI_INFO_NULL),
"cannot delete file");
} /* IOR_Delete_MPIIO() */
/******************************************************************************/
/*
* Determine api version.
*/
void
IOR_SetVersion_MPIIO(IOR_param_t *test)
{
int version, subversion;
MPI_CHECK(MPI_Get_version(&version, &subversion),
"cannot get MPI version");
sprintf(test->apiVersion, "%s (version=%d, subversion=%d)",
test->api, version, subversion);
} /* IOR_SetVersion_MPIIO() */
/************************ L O C A L F U N C T I O N S ***********************/
/******************************************************************************/
/*
* Seek to offset in file using the MPIIO interface.
*/
static IOR_offset_t
SeekOffset_MPIIO(MPI_File fd,
IOR_offset_t offset,
IOR_param_t * param)
{
int offsetFactor,
tasksPerFile;
IOR_offset_t tempOffset;
tempOffset = offset;
if (param->filePerProc) {
offsetFactor = 0;
tasksPerFile = 1;
} else {
offsetFactor = (rank + rankOffset) % param->numTasks;
tasksPerFile = param->numTasks;
}
if (param->useFileView) {
/* recall that offsets in a file view are
counted in units of transfer size */
if (param->filePerProc) {
tempOffset = tempOffset / param->transferSize;
} else {
/*
* this formula finds a file view offset for a task
* from an absolute offset
*/
tempOffset = ((param->blockSize / param->transferSize)
* (tempOffset / (param->blockSize * tasksPerFile)))
+ (((tempOffset % (param->blockSize * tasksPerFile))
- (offsetFactor * param->blockSize))
/ param->transferSize);
}
}
MPI_CHECK(MPI_File_seek(fd, tempOffset, MPI_SEEK_SET),
"cannot seek offset");
return(offset);
} /* SeekOffset_MPIIO() */
/******************************************************************************/
/*
* Use MPI_File_get_size() to return aggregate file size.
*/
IOR_offset_t
IOR_GetFileSize_MPIIO(IOR_param_t * test,
MPI_Comm testComm,
char * testFileName)
{
IOR_offset_t aggFileSizeFromStat,
tmpMin, tmpMax, tmpSum;
MPI_File fd;
MPI_CHECK(MPI_File_open(testComm, testFileName, MPI_MODE_RDONLY,
MPI_INFO_NULL, &fd),
"cannot open file to get file size");
MPI_CHECK(MPI_File_get_size(fd, &aggFileSizeFromStat),
"cannot get file size");
MPI_CHECK(MPI_File_close(&fd), "cannot close file");
if (test->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, testComm),
"cannot total data moved");
aggFileSizeFromStat = tmpSum;
} else {
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpMin, 1,
MPI_LONG_LONG_INT, MPI_MIN, testComm),
"cannot total data moved");
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpMax, 1,
MPI_LONG_LONG_INT, MPI_MAX, testComm),
"cannot total data moved");
if (tmpMin != tmpMax) {
if (rank == 0) {
WARN("inconsistent file size by different tasks");
}
/* incorrect, but now consistent across tasks */
aggFileSizeFromStat = tmpMin;
}
}
return(aggFileSizeFromStat);
} /* IOR_GetFileSize_MPIIO() */

406
src/C/aiori-NCMPI.c Normal file
View File

@ -0,0 +1,406 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: aiori-NCMPI.c,v $
* $Revision: 1.2 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* Implementation of abstract I/O interface for Parallel NetCDF (NCMPI).
*
\******************************************************************************/
#include "aiori.h" /* abstract IOR interface */
#include <errno.h> /* sys_errlist */
#include <stdio.h> /* only for fprintf() */
#include <stdlib.h>
#include <sys/stat.h>
#include <pnetcdf.h>
#define NUM_DIMS 3 /* number of dimensions to data set */
/******************************************************************************/
/*
* NCMPI_CHECK will display a custom error message and then exit the program
*/
#define NCMPI_CHECK(NCMPI_RETURN, MSG) do { \
char resultString[1024]; \
\
if (NCMPI_RETURN < 0) { \
fprintf(stdout, "** error **\n"); \
fprintf(stdout, "ERROR in %s (line %d): %s.\n", \
__FILE__, __LINE__, MSG); \
fprintf(stdout, "ERROR: %s.\n", ncmpi_strerror(NCMPI_RETURN)); \
fprintf(stdout, "** exiting **\n"); \
exit(-1); \
} \
} while(0)
/**************************** P R O T O T Y P E S *****************************/
int GetFileMode(IOR_param_t *);
void SetHints (MPI_Info *, char *);
void ShowHints (MPI_Info *);
/************************** D E C L A R A T I O N S ***************************/
extern int errno, /* error number */
numTasksWorld,
rank,
rankOffset,
verbose; /* verbose output */
extern MPI_Comm testComm;
/***************************** F U N C T I O N S ******************************/
/******************************************************************************/
/*
* Create and open a file through the NCMPI interface.
*/
void *
IOR_Create_NCMPI(char * testFileName,
IOR_param_t * param)
{
int * fd;
int fd_mode;
MPI_Info mpiHints = MPI_INFO_NULL;
/* Wei-keng Liao: read and set MPI file hints from hintsFile */
SetHints(&mpiHints, param->hintsFileName);
if (rank == 0 && param->showHints) {
fprintf(stdout, "\nhints passed to MPI_File_open() {\n");
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
}
fd = (int *)malloc(sizeof(int));
if (fd == NULL) ERR("Unable to malloc file descriptor");
fd_mode = GetFileMode(param);
NCMPI_CHECK(ncmpi_create(testComm, testFileName, fd_mode,
mpiHints, fd), "cannot create file");
/* Wei-keng Liao: print the MPI file hints currently used */
/* WEL - add when ncmpi_get_file_info() is in current parallel-netcdf release
if (rank == 0 && param->showHints) {
MPI_CHECK(ncmpi_get_file_info(*fd, &mpiHints),
"cannot get file info");
fprintf(stdout, "\nhints returned from opened file {\n");
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
}
*/
/* Wei-keng Liao: free up the mpiHints object */
/* WEL - this needs future fix from next release of PnetCDF
if (mpiHints != MPI_INFO_NULL)
MPI_CHECK(MPI_Info_free(&mpiHints), "cannot free file info");
*/
return(fd);
} /* IOR_Create_NCMPI() */
/******************************************************************************/
/*
* Open a file through the NCMPI interface.
*/
void *
IOR_Open_NCMPI(char * testFileName,
IOR_param_t * param)
{
int * fd;
int fd_mode;
MPI_Info mpiHints = MPI_INFO_NULL;
/* Wei-keng Liao: read and set MPI file hints from hintsFile */
SetHints(&mpiHints, param->hintsFileName);
if (rank == 0 && param->showHints) {
fprintf(stdout, "\nhints passed to MPI_File_open() {\n");
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
}
fd = (int *)malloc(sizeof(int));
if (fd == NULL) ERR("Unable to malloc file descriptor");
fd_mode = GetFileMode(param);
NCMPI_CHECK(ncmpi_open(testComm, testFileName, fd_mode,
mpiHints, fd), "cannot open file");
/* Wei-keng Liao: print the MPI file hints currently used */
/* WEL - add when ncmpi_get_file_info() is in current parallel-netcdf release
if (rank == 0 && param->showHints) {
MPI_CHECK(ncmpi_get_file_info(*fd, &mpiHints),
"cannot get file info");
fprintf(stdout, "\nhints returned from opened file {\n");
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
}
*/
/* Wei-keng Liao: free up the mpiHints object */
/* WEL - this needs future fix from next release of PnetCDF
if (mpiHints != MPI_INFO_NULL)
MPI_CHECK(MPI_Info_free(&mpiHints), "cannot free file info");
*/
return(fd);
} /* IOR_Open_NCMPI() */
/******************************************************************************/
/*
* Write or read access to file using the NCMPI interface.
*/
IOR_offset_t
IOR_Xfer_NCMPI(int access,
void * fd,
IOR_size_t * buffer,
IOR_offset_t length,
IOR_param_t * param)
{
char * bufferPtr = (char *)buffer;
static int firstReadCheck = FALSE,
startDataSet;
int var_id,
dim_id[NUM_DIMS];
MPI_Offset bufSize[NUM_DIMS],
offset[NUM_DIMS];
IOR_offset_t segmentPosition;
int segmentNum,
transferNum;
/* Wei-keng Liao: In IOR.c line 1979 says "block size must be a multiple
of transfer size." Hence, length should always == param->transferSize
below. I leave it here to double check.
*/
if (length != param->transferSize) {
char errMsg[256];
sprintf(errMsg,"length(%lld) != param->transferSize(%lld)\n",
length, param->transferSize);
NCMPI_CHECK(-1, errMsg);
}
/* determine by offset if need to start data set */
if (param->filePerProc == TRUE) {
segmentPosition = (IOR_offset_t)0;
} else {
segmentPosition = (IOR_offset_t)((rank + rankOffset) % param->numTasks)
* param->blockSize;
}
if ((int)(param->offset - segmentPosition) == 0) {
startDataSet = TRUE;
/*
* this toggle is for the read check operation, which passes through
* this function twice; note that this function will open a data set
* only on the first read check and close only on the second
*/
if (access == READCHECK) {
if (firstReadCheck == TRUE) {
firstReadCheck = FALSE;
} else {
firstReadCheck = TRUE;
}
}
}
if (startDataSet == TRUE &&
(access != READCHECK || firstReadCheck == TRUE)) {
if (access == WRITE) {
int numTransfers = param->blockSize / param->transferSize;
/* Wei-keng Liao: change 1D array to 3D array of dimensions:
[segmentCount*numTasksWorld][numTransfers][transferSize]
Requirement: none of these dimensions should be > 4G,
*/
NCMPI_CHECK(ncmpi_def_dim(*(int *)fd, "segments_times_np",
NC_UNLIMITED, &dim_id[0]),
"cannot define data set dimensions");
NCMPI_CHECK(ncmpi_def_dim(*(int *)fd, "number_of_transfers",
numTransfers, &dim_id[1]),
"cannot define data set dimensions");
NCMPI_CHECK(ncmpi_def_dim(*(int *)fd, "transfer_size",
param->transferSize, &dim_id[2]),
"cannot define data set dimensions");
NCMPI_CHECK(ncmpi_def_var(*(int *)fd, "data_var", NC_BYTE,
NUM_DIMS, dim_id, &var_id),
"cannot define data set variables");
NCMPI_CHECK(ncmpi_enddef(*(int *)fd),
"cannot close data set define mode");
} else {
NCMPI_CHECK(ncmpi_inq_varid(*(int *)fd, "data_var", &var_id),
"cannot retrieve data set variable");
}
if (param->collective == FALSE) {
NCMPI_CHECK(ncmpi_begin_indep_data(*(int *)fd),
"cannot enable independent data mode");
}
param->var_id = var_id;
startDataSet = FALSE;
}
var_id = param->var_id;
/* Wei-keng Liao: calculate the segment number */
segmentNum = param->offset / (param->numTasks * param->blockSize);
/* Wei-keng Liao: calculate the transfer number in each block */
transferNum = param->offset % param->blockSize / param->transferSize;
/* Wei-keng Liao: read/write the 3rd dim of the dataset, each is of
amount param->transferSize */
bufSize[0] = 1;
bufSize[1] = 1;
bufSize[2] = param->transferSize;
offset[0] = segmentNum * numTasksWorld + rank;
offset[1] = transferNum;
offset[2] = 0;
/* access the file */
if (access == WRITE) { /* WRITE */
if (param->collective) {
NCMPI_CHECK(ncmpi_put_vara_all(*(int *)fd, var_id, offset, bufSize,
bufferPtr, length, MPI_BYTE),
"cannot write to data set");
} else {
NCMPI_CHECK(ncmpi_put_vara(*(int *)fd, var_id, offset, bufSize,
bufferPtr, length, MPI_BYTE),
"cannot write to data set");
}
} else { /* READ or CHECK */
if (param->collective == TRUE) {
NCMPI_CHECK(ncmpi_get_vara_all(*(int *)fd, var_id, offset, bufSize,
bufferPtr, length, MPI_BYTE),
"cannot read from data set");
} else {
NCMPI_CHECK(ncmpi_get_vara(*(int *)fd, var_id, offset, bufSize,
bufferPtr, length, MPI_BYTE),
"cannot read from data set");
}
}
return(length);
} /* IOR_Xfer_NCMPI() */
/******************************************************************************/
/*
* Perform fsync().
*/
void
IOR_Fsync_NCMPI(void * fd, IOR_param_t * param)
{
;
} /* IOR_Fsync_NCMPI() */
/******************************************************************************/
/*
* Close a file through the NCMPI interface.
*/
void
IOR_Close_NCMPI(void * fd,
IOR_param_t * param)
{
if (param->collective == FALSE) {
NCMPI_CHECK(ncmpi_end_indep_data(*(int *)fd),
"cannot disable independent data mode");
}
NCMPI_CHECK(ncmpi_close(*(int *)fd), "cannot close file");
free(fd);
} /* IOR_Close_NCMPI() */
/******************************************************************************/
/*
* Delete a file through the NCMPI interface.
*/
void
IOR_Delete_NCMPI(char * testFileName, IOR_param_t * param)
{
if (unlink(testFileName) != 0) WARN("cannot delete file");
} /* IOR_Delete_NCMPI() */
/******************************************************************************/
/*
* Determine api version.
*/
void
IOR_SetVersion_NCMPI(IOR_param_t * test)
{
sprintf(test->apiVersion, "%s (%s)",
test->api, ncmpi_inq_libvers());
} /* IOR_SetVersion_NCMPI() */
/************************ L O C A L F U N C T I O N S ***********************/
/******************************************************************************/
/*
* Return the correct file mode for NCMPI.
*/
int
GetFileMode(IOR_param_t * param)
{
int fd_mode = 0;
/* set IOR file flags to NCMPI flags */
/* -- file open flags -- */
if (param->openFlags & IOR_RDONLY) {fd_mode |= NC_NOWRITE;}
if (param->openFlags & IOR_WRONLY) {
fprintf(stdout, "File write only not implemented in NCMPI\n");
}
if (param->openFlags & IOR_RDWR) {fd_mode |= NC_WRITE;}
if (param->openFlags & IOR_APPEND) {
fprintf(stdout, "File append not implemented in NCMPI\n");
}
if (param->openFlags & IOR_CREAT) {fd_mode |= NC_CLOBBER;}
if (param->openFlags & IOR_EXCL) {
fprintf(stdout, "Exclusive access not implemented in NCMPI\n");
}
if (param->openFlags & IOR_TRUNC) {
fprintf(stdout, "File truncation not implemented in NCMPI\n");
}
if (param->openFlags & IOR_DIRECT) {
fprintf(stdout, "O_DIRECT not implemented in NCMPI\n");
}
/* Wei-keng Liao: to enable > 4GB file size */
fd_mode |= NC_64BIT_OFFSET;
return(fd_mode);
} /* GetFileMode() */
/******************************************************************************/
/*
* Use MPIIO call to get file size.
*/
IOR_offset_t
IOR_GetFileSize_NCMPI(IOR_param_t * test,
MPI_Comm testComm,
char * testFileName)
{
return(IOR_GetFileSize_MPIIO(test, testComm, testFileName));
} /* IOR_GetFileSize_NCMPI() */

388
src/C/aiori-POSIX.c Normal file
View File

@ -0,0 +1,388 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: aiori-POSIX.c,v $
* $Revision: 1.3 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* Implementation of abstract I/O interface for POSIX.
*
\******************************************************************************/
/********************* Modifications to IOR-2.10.1 ****************************
* hodson - 8/18/2008: *
* Added fsyncPerWrite option to do POSIX fsync after each POSIX write *
* More info on cannot delete file error message *
******************************************************************************/
#include "aiori.h" /* abstract IOR interface */
#ifdef __linux__
# include <sys/ioctl.h> /* necessary for: */
# define __USE_GNU /* O_DIRECT and */
# include <fcntl.h> /* IO operations */
# undef __USE_GNU
#endif /* __linux__ */
#include <errno.h> /* sys_errlist */
#include <fcntl.h> /* IO operations */
#include <stdio.h> /* only for fprintf() */
#include <stdlib.h>
#include <sys/stat.h>
#ifdef _MANUALLY_SET_LUSTRE_STRIPING
# include <lustre/lustre_user.h>
#endif /* _MANUALLY_SET_LUSTRE_STRIPING */
#ifndef open64 /* necessary for TRU64 -- */
# define open64 open /* unlikely, but may pose */
#endif /* not open64 */ /* conflicting prototypes */
#ifndef lseek64 /* necessary for TRU64 -- */
# define lseek64 lseek /* unlikely, but may pose */
#endif /* not lseek64 */ /* conflicting prototypes */
#ifndef O_BINARY /* Required on Windows */
# define O_BINARY 0
#endif
/**************************** P R O T O T Y P E S *****************************/
/************************** D E C L A R A T I O N S ***************************/
extern int errno;
extern int rank;
extern int rankOffset;
extern int verbose;
extern MPI_Comm testComm;
/***************************** F U N C T I O N S ******************************/
/******************************************************************************/
/*
* Creat and open a file through the POSIX interface.
*/
void *
IOR_Create_POSIX(char * testFileName,
IOR_param_t * param)
{
int fd_oflag = O_BINARY;
int *fd;
fd = (int *)malloc(sizeof(int));
if (fd == NULL) ERR("Unable to malloc file descriptor");
if (param->useO_DIRECT == TRUE) {
/* note that TRU64 needs O_DIRECTIO, SunOS uses directio(),
and everyone else needs O_DIRECT */
#ifndef O_DIRECT
# ifndef O_DIRECTIO
WARN("cannot use O_DIRECT");
# define O_DIRECT 000000
# else /* O_DIRECTIO */
# define O_DIRECT O_DIRECTIO
# endif /* not O_DIRECTIO */
#endif /* not O_DIRECT */
fd_oflag |= O_DIRECT;
}
#ifndef _MANUALLY_SET_LUSTRE_STRIPING
/* If the lustre striping parameters are not the defaults */
if (param->lustre_stripe_count != 0
|| param->lustre_stripe_size != 0
|| param->lustre_start_ost != -1
|| param->lustre_ignore_locks) {
ERR("This IOR was not compiled with Lustre support!");
}
fd_oflag |= O_CREAT | O_RDWR;
*fd = open64(testFileName, fd_oflag, 0664);
if (*fd < 0) ERR("cannot open file");
#else /* _MANUALLY_SET_LUSTRE_STRIPING */
/* If the lustre striping parameters are not the defaults */
if (param->lustre_stripe_count != 0
|| param->lustre_stripe_size != 0
|| param->lustre_start_ost != -1) {
/* In the single-shared-file case, task 0 has to creat the
file with the Lustre striping options before any other processes
open the file */
if (!param->filePerProc && rank != 0) {
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
fd_oflag |= O_RDWR;
*fd = open64(testFileName, fd_oflag, 0664);
if (*fd < 0) ERR("cannot open file");
} else {
struct lov_user_md opts = { 0 };
/* Setup Lustre IOCTL striping pattern structure */
opts.lmm_magic = LOV_USER_MAGIC;
opts.lmm_stripe_size = param->lustre_stripe_size;
opts.lmm_stripe_offset = param->lustre_start_ost;
opts.lmm_stripe_count = param->lustre_stripe_count;
/* File needs to be opened O_EXCL because we cannot set
Lustre striping information on a pre-existing file. */
fd_oflag |= O_CREAT | O_EXCL | O_RDWR | O_LOV_DELAY_CREATE;
*fd = open64(testFileName, fd_oflag, 0664);
if (*fd < 0) {
fprintf(stdout, "\nUnable to open '%s': %s\n",
testFileName, strerror(errno));
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error");
} else if (ioctl(*fd, LL_IOC_LOV_SETSTRIPE, &opts)) {
char *errmsg = "stripe already set";
if (errno != EEXIST && errno != EALREADY)
errmsg = strerror(errno);
fprintf(stdout, "\nError on ioctl for '%s' (%d): %s\n",
testFileName, *fd, errmsg);
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error");
}
if (!param->filePerProc)
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
}
} else {
fd_oflag |= O_CREAT | O_RDWR;
*fd = open64(testFileName, fd_oflag, 0664);
if (*fd < 0) ERR("cannot open file");
}
if (param->lustre_ignore_locks) {
int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK;
if (ioctl(*fd, LL_IOC_SETFLAGS, &lustre_ioctl_flags) == -1)
ERR("cannot set ioctl");
}
#endif /* not _MANUALLY_SET_LUSTRE_STRIPING */
return((void *)fd);
} /* IOR_Create_POSIX() */
/******************************************************************************/
/*
* Open a file through the POSIX interface.
*/
void *
IOR_Open_POSIX(char * testFileName,
IOR_param_t * param)
{
int fd_oflag = O_BINARY;
int *fd;
fd = (int *)malloc(sizeof(int));
if (fd == NULL) ERR("Unable to malloc file descriptor");
if (param->useO_DIRECT == TRUE) {
/* note that TRU64 needs O_DIRECTIO, SunOS uses directio(),
and everyone else needs O_DIRECT */
#ifndef O_DIRECT
# ifndef O_DIRECTIO
WARN("cannot use O_DIRECT");
# define O_DIRECT 000000
# else /* O_DIRECTIO */
# define O_DIRECT O_DIRECTIO
# endif /* not O_DIRECTIO */
#endif /* not O_DIRECT */
fd_oflag |= O_DIRECT;
}
fd_oflag |= O_RDWR;
*fd = open64(testFileName, fd_oflag);
if (*fd < 0) ERR("cannot open file");
#ifdef _MANUALLY_SET_LUSTRE_STRIPING
if (param->lustre_ignore_locks) {
int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK;
if (verbose >= VERBOSE_1) {
fprintf(stdout, "** Disabling lustre range locking **\n");
}
if (ioctl(*fd, LL_IOC_SETFLAGS, &lustre_ioctl_flags) == -1)
ERR("cannot set ioctl");
}
#endif /* _MANUALLY_SET_LUSTRE_STRIPING */
return((void *)fd);
} /* IOR_Open_POSIX() */
/******************************************************************************/
/*
* Write or read access to file using the POSIX interface.
*/
IOR_offset_t
IOR_Xfer_POSIX(int access,
void * file,
IOR_size_t * buffer,
IOR_offset_t length,
IOR_param_t * param)
{
int xferRetries = 0;
long long remaining = (long long)length;
char * ptr = (char *)buffer;
long long rc;
int fd;
fd = *(int *)file;
/* seek to offset */
if (lseek64(fd, param->offset, SEEK_SET) == -1)
ERR("seek failed");
while (remaining > 0) {
/* write/read file */
if (access == WRITE) { /* WRITE */
if (verbose >= VERBOSE_4) {
fprintf(stdout, "task %d writing to offset %lld\n",
rank, param->offset + length - remaining);
}
rc = write(fd, ptr, remaining);
if (param->fsyncPerWrite == TRUE) IOR_Fsync_POSIX(&fd, param);
} else { /* READ or CHECK */
if (verbose >= VERBOSE_4) {
fprintf(stdout, "task %d reading from offset %lld\n",
rank, param->offset + length - remaining);
}
rc = read(fd, ptr, remaining);
if (rc == 0)
ERR("hit EOF prematurely");
}
if (rc == -1)
ERR("transfer failed");
if (rc != remaining) {
fprintf(stdout,
"WARNING: Task %d requested transfer of %lld bytes,\n",
rank, remaining);
fprintf(stdout,
" but transferred %lld bytes at offset %lld\n",
rc, param->offset + length - remaining);
if (param->singleXferAttempt == TRUE)
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "barrier error");
}
if (rc < remaining) {
if (xferRetries > MAX_RETRY)
ERR("too many retries -- aborting");
if (xferRetries == 0) {
if (access == WRITE) {
WARN("This file system requires support of partial write()s");
} else {
WARN("This file system requires support of partial read()s");
}
fprintf(stdout,
"WARNING: Requested xfer of %lld bytes, but xferred %lld bytes\n",
remaining, rc);
}
if (verbose >= VERBOSE_2) {
fprintf(stdout, "Only transferred %lld of %lld bytes\n",
rc, remaining);
}
}
if (rc > remaining) /* this should never happen */
ERR("too many bytes transferred!?!");
remaining -= rc;
ptr += rc;
xferRetries++;
}
return(length);
} /* IOR_Xfer_POSIX() */
/******************************************************************************/
/*
* Perform fsync().
*/
void
IOR_Fsync_POSIX(void * fd, IOR_param_t * param)
{
if (fsync(*(int *)fd) != 0) WARN("cannot perform fsync on file");
} /* IOR_Fsync_POSIX() */
/******************************************************************************/
/*
* Close a file through the POSIX interface.
*/
void
IOR_Close_POSIX(void *fd,
IOR_param_t * param)
{
if (close(*(int *)fd) != 0) ERR("cannot close file");
free(fd);
} /* IOR_Close_POSIX() */
/******************************************************************************/
/*
* Delete a file through the POSIX interface.
*/
void
IOR_Delete_POSIX(char * testFileName, IOR_param_t * param)
{
char errmsg[256];
sprintf(errmsg,"[RANK %03d]:cannot delete file %s\n",rank,testFileName);
if (unlink(testFileName) != 0) WARN(errmsg);
} /* IOR_Delete_POSIX() */
/******************************************************************************/
/*
* Determine api version.
*/
void
IOR_SetVersion_POSIX(IOR_param_t *test)
{
strcpy(test->apiVersion, test->api);
} /* IOR_SetVersion_POSIX() */
/******************************************************************************/
/*
* Use POSIX stat() to return aggregate file size.
*/
IOR_offset_t
IOR_GetFileSize_POSIX(IOR_param_t * test,
MPI_Comm testComm,
char * testFileName)
{
struct stat stat_buf;
IOR_offset_t aggFileSizeFromStat,
tmpMin, tmpMax, tmpSum;
if (stat(testFileName, &stat_buf) != 0) {
ERR("cannot get status of written file");
}
aggFileSizeFromStat = stat_buf.st_size;
if (test->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, testComm),
"cannot total data moved");
aggFileSizeFromStat = tmpSum;
} else {
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpMin, 1,
MPI_LONG_LONG_INT, MPI_MIN, testComm),
"cannot total data moved");
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpMax, 1,
MPI_LONG_LONG_INT, MPI_MAX, testComm),
"cannot total data moved");
if (tmpMin != tmpMax) {
if (rank == 0) {
WARN("inconsistent file size by different tasks");
}
/* incorrect, but now consistent across tasks */
aggFileSizeFromStat = tmpMin;
}
}
return(aggFileSizeFromStat);
} /* IOR_GetFileSize_POSIX() */

81
src/C/aiori-noHDF5.c Normal file
View File

@ -0,0 +1,81 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: aiori-noHDF5.c,v $
* $Revision: 1.2 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* Empty HDF5 functions for when compiling without HDF5 support.
*
\******************************************************************************/
#include "aiori.h"
void *
IOR_Create_HDF5(char * testFileName,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with HDF5 support");
return 0;
}
void *
IOR_Open_HDF5(char * testFileName,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with HDF5 support");
return 0;
}
IOR_offset_t
IOR_Xfer_HDF5(int access,
void * fd,
IOR_size_t * buffer,
IOR_offset_t length,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with HDF5 support");
return 0;
}
void
IOR_Fsync_HDF5(void * fd, IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with HDF5 support");
}
void
IOR_Close_HDF5(void * fd,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with HDF5 support");
}
void
IOR_Delete_HDF5(char * testFileName, IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with HDF5 support");
}
void
IOR_SetVersion_HDF5(IOR_param_t *test)
{
ERR("This copy of IOR was not compiled with HDF5 support");
}
IOR_offset_t
IOR_GetFileSize_HDF5(IOR_param_t * test,
MPI_Comm testComm,
char * testFileName)
{
ERR("This copy of IOR was not compiled with HDF5 support");
return 0;
}

81
src/C/aiori-noMPIIO.c Normal file
View File

@ -0,0 +1,81 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: aiori-noMPIIO.c,v $
* $Revision: 1.1.1.1 $
* $Date: 2007/10/15 23:36:54 $
* $Author: rklundt $
*
* Purpose:
* Empty MPIIO functions for when compiling without MPIIO support.
*
\******************************************************************************/
#include "aiori.h"
void *
IOR_Create_MPIIO(char * testFileName,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with MPIIO support");
return 0;
}
void *
IOR_Open_MPIIO(char * testFileName,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with MPIIO support");
return 0;
}
IOR_offset_t
IOR_Xfer_MPIIO(int access,
void * fd,
IOR_size_t * buffer,
IOR_offset_t length,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with MPIIO support");
return 0;
}
void
IOR_Fsync_MPIIO(void * fd, IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with MPIIO support");
}
void
IOR_Close_MPIIO(void * fd,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with MPIIO support");
}
void
IOR_Delete_MPIIO(char * testFileName, IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with MPIIO support");
}
void
IOR_SetVersion_MPIIO(IOR_param_t *test)
{
ERR("This copy of IOR was not compiled with MPIIO support");
}
IOR_offset_t
IOR_GetFileSize_MPIIO(IOR_param_t * test,
MPI_Comm testComm,
char * testFileName)
{
ERR("This copy of IOR was not compiled with MPIIO support");
return 0;
}

81
src/C/aiori-noNCMPI.c Normal file
View File

@ -0,0 +1,81 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: aiori-noNCMPI.c,v $
* $Revision: 1.2 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* Empty NCMPI functions for when compiling without NCMPI support.
*
\******************************************************************************/
#include "aiori.h"
void *
IOR_Create_NCMPI(char * testFileName,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with NCMPI support");
return 0;
}
void *
IOR_Open_NCMPI(char * testFileName,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with NCMPI support");
return 0;
}
IOR_offset_t
IOR_Xfer_NCMPI(int access,
void * fd,
IOR_size_t * buffer,
IOR_offset_t length,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with NCMPI support");
return 0;
}
void
IOR_Fsync_NCMPI(void * fd, IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with NCMPI support");
}
void
IOR_Close_NCMPI(void * fd,
IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with NCMPI support");
}
void
IOR_Delete_NCMPI(char * testFileName, IOR_param_t * param)
{
ERR("This copy of IOR was not compiled with NCMPI support");
}
void
IOR_SetVersion_NCMPI(IOR_param_t *test)
{
ERR("This copy of IOR was not compiled with NCMPI support");
}
IOR_offset_t
IOR_GetFileSize_NCMPI(IOR_param_t * test,
MPI_Comm testComm,
char * testFileName)
{
ERR("This copy of IOR was not compiled with NCMPI support");
return 0;
}

234
src/C/aiori.h Normal file
View File

@ -0,0 +1,234 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: aiori.h,v $
* $Revision: 1.3 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* This is a header file that contains the definitions and prototypes
* needed for the abstract I/O interfaces necessary for IOR.
*
\******************************************************************************/
/********************* Modifications to IOR-2.10.1 *****************************
* hodson - 8/18/2008: Added option flags for the following new options *
* int TestNum; * test reference number *
* double * writeVal; * array to write results - IOPS added *
* double * readVal; * array to read results - IOPS added *
* int taskPerNodeOffset; * task node offset for reading files *
* int reorderTasksRandom; * reorder tasks for random file read back *
* int reorderTasksRandomSeed; * reorder tasks for random file read seed *
* int fsyncPerWrite; * fsync() after each write *
*******************************************************************************/
#ifndef _AIORI_H
#define _AIORI_H
#include "iordef.h" /* IOR Definitions */
#include <mpi.h>
#ifndef MPI_FILE_NULL
# include <mpio.h>
#endif /* not MPI_FILE_NULL */
#include <string.h>
/*************************** D E F I N I T I O N S ****************************/
/* -- file open flags -- */
#define IOR_RDONLY 1 /* read only */
#define IOR_WRONLY 2 /* write only */
#define IOR_RDWR 4 /* read/write */
#define IOR_APPEND 8 /* append */
#define IOR_CREAT 16 /* create */
#define IOR_TRUNC 32 /* truncate */
#define IOR_EXCL 64 /* exclusive */
#define IOR_DIRECT 128 /* bypass I/O buffers */
/* -- file mode flags -- */
#define IOR_IRWXU 1 /* read, write, execute perm: owner */
#define IOR_IRUSR 2 /* read permission: owner */
#define IOR_IWUSR 4 /* write permission: owner */
#define IOR_IXUSR 8 /* execute permission: owner */
#define IOR_IRWXG 16 /* read, write, execute perm: group */
#define IOR_IRGRP 32 /* read permission: group */
#define IOR_IWGRP 64 /* write permission: group */
#define IOR_IXGRP 128 /* execute permission: group */
#define IOR_IRWXO 256 /* read, write, execute perm: other */
#define IOR_IROTH 512 /* read permission: other */
#define IOR_IWOTH 1024 /* write permission: other */
#define IOR_IXOTH 2048 /* execute permission: other */
/******************************************************************************/
/*
* The parameter struct holds all of the "global" data to be passed,
* as well as results to be parsed.
*
* NOTE: If this is changed, also change:
* defaultParameters [defaults.h]
* DisplayUsage() [IOR.c]
* ShowTest() [IOR.c]
* DecodeDirective() [parse_options.c]
* ParseCommandLine() [parse_options.c]
* USER_GUIDE
*/
typedef struct
{
char debug[MAX_STR]; /* debug info string */
unsigned int mode; /* file permissions */
unsigned int openFlags; /* open flags */
int TestNum; /* test reference number */
char api[MAX_STR]; /* API for I/O */
char apiVersion[MAX_STR]; /* API version */
char platform[MAX_STR]; /* platform type */
char testFileName[MAXPATHLEN]; /* full name for test */
char testFileName_fppReadCheck[MAXPATHLEN];/* filename for fpp read check */
char hintsFileName[MAXPATHLEN]; /* full name for hints file */
char options[MAXPATHLEN]; /* options string */
int numTasks; /* number of tasks for test */
int nodes; /* number of nodes for test */
int tasksPerNode; /* number of tasks per node */
int repetitions; /* number of repetitions of test */
int repCounter; /* rep counter */
int multiFile; /* multiple files */
int interTestDelay; /* delay between reps in seconds */
double * writeVal[2]; /* array to write results */
double * readVal[2]; /* array to read results */
int open; /* flag for writing or reading */
int readFile; /* read of existing file */
int writeFile; /* write of file */
int filePerProc; /* single file or file-per-process */
int reorderTasks; /* reorder tasks for read back and check */
int taskPerNodeOffset; /* task node offset for reading files */
int reorderTasksRandom; /* reorder tasks for random file read back */
int reorderTasksRandomSeed; /* reorder tasks for random file read seed */
int checkWrite; /* check read after write */
int checkRead; /* check read after read */
int keepFile; /* don't delete the testfile on exit */
int keepFileWithError; /* don't delete the testfile with errors */
int errorFound; /* error found in data check */
int quitOnError; /* quit code when error in check */
int collective; /* collective I/O */
IOR_offset_t segmentCount; /* number of segments (or HDF5 datasets) */
IOR_offset_t blockSize; /* contiguous bytes to write per task */
IOR_offset_t transferSize; /* size of transfer in bytes */
IOR_offset_t offset; /* offset for read/write */
IOR_offset_t * aggFileSizeFromCalc; /* calculated aggregate file size */
IOR_offset_t * aggFileSizeFromStat; /* stat() aggregate file size */
IOR_offset_t * aggFileSizeFromXfer; /* transfered aggregate file size */
IOR_offset_t * aggFileSizeForBW; /* aggregate file size used for b/w */
int preallocate; /* preallocate file size */
int useFileView; /* use MPI_File_set_view */
int useSharedFilePointer; /* use shared file pointer */
int useStridedDatatype; /* put strided access into datatype */
int useO_DIRECT; /* use O_DIRECT, bypassing I/O buffers */
int showHints; /* show hints */
int showHelp; /* show options and help */
int uniqueDir; /* use unique directory for each fpp */
int useExistingTestFile; /* do not delete test file before access */
int storeFileOffset; /* use file offset as stored signature */
int deadlineForStonewalling; /* max time in seconds to run any test phase */
int maxTimeDuration; /* max time in minutes to run tests */
int outlierThreshold; /* warn on outlier N seconds from mean */
int verbose; /* verbosity */
int setTimeStampSignature; /* set time stamp signature */
unsigned int timeStampSignatureValue; /* value for time stamp signature */
void * fd_fppReadCheck; /* additional fd for fpp read check */
int randomSeed; /* random seed for write/read check */
int randomOffset; /* access is to random offsets */
MPI_Comm testComm; /* MPI communicator */
/* POSIX variables */
int singleXferAttempt; /* do not retry transfer if incomplete */
int fsyncPerWrite; /* fsync() after each write */
int fsync; /* fsync() after write */
/* MPI variables */
MPI_Datatype transferType; /* datatype for transfer */
MPI_Datatype fileType; /* filetype for file view */
/* HDF5 variables */
int individualDataSets; /* datasets not shared by all procs */
int noFill; /* no fill in file creation */
IOR_offset_t setAlignment; /* alignment in bytes */
/* NCMPI variables */
int var_id; /* variable id handle for data set */
/* Lustre variables */
int lustre_stripe_count;
int lustre_stripe_size;
int lustre_start_ost;
int lustre_ignore_locks;
#if USE_UNDOC_OPT
int corruptFile;
int fillTheFileSystem;
int includeDeleteTime;
int multiReRead;
/* NFS variables */
char NFS_rootPath[MAXPATHLEN]; /* absolute path to NFS servers */
char NFS_serverName[MAXPATHLEN]; /* prefix for NFS server name */
int NFS_serverCount; /* number of NFS servers to be used */
#endif /* USE_UNDOC_OPT */
int id; /* test's unique ID */
int intraTestBarriers; /* barriers between open/op and op/close */
} IOR_param_t;
/**************************** P R O T O T Y P E S *****************************/
/* functions for aiori-*.c */
/* POSIX-specific functions */
void * IOR_Create_POSIX (char *, IOR_param_t *);
void * IOR_Open_POSIX (char *, IOR_param_t *);
IOR_offset_t IOR_Xfer_POSIX (int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
void IOR_Close_POSIX (void *, IOR_param_t *);
void IOR_Delete_POSIX (char *, IOR_param_t *);
void IOR_SetVersion_POSIX (IOR_param_t *);
void IOR_Fsync_POSIX (void *, IOR_param_t *);
IOR_offset_t IOR_GetFileSize_POSIX (IOR_param_t *, MPI_Comm, char *);
/* MPIIO-specific functions */
void * IOR_Create_MPIIO (char *, IOR_param_t *);
void * IOR_Open_MPIIO (char *, IOR_param_t *);
IOR_offset_t IOR_Xfer_MPIIO (int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
void IOR_Close_MPIIO (void *, IOR_param_t *);
void IOR_Delete_MPIIO (char *, IOR_param_t *);
void IOR_SetVersion_MPIIO (IOR_param_t *);
void IOR_Fsync_MPIIO (void *, IOR_param_t *);
IOR_offset_t IOR_GetFileSize_MPIIO (IOR_param_t *, MPI_Comm, char *);
/* HDF5-specific functions */
void * IOR_Create_HDF5 (char *, IOR_param_t *);
void * IOR_Open_HDF5 (char *, IOR_param_t *);
IOR_offset_t IOR_Xfer_HDF5 (int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
void IOR_Close_HDF5 (void *, IOR_param_t *);
void IOR_Delete_HDF5 (char *, IOR_param_t *);
void IOR_SetVersion_HDF5 (IOR_param_t *);
void IOR_Fsync_HDF5 (void *, IOR_param_t *);
IOR_offset_t IOR_GetFileSize_HDF5 (IOR_param_t *, MPI_Comm, char *);
/* NCMPI-specific functions */
void * IOR_Create_NCMPI (char *, IOR_param_t *);
void * IOR_Open_NCMPI (char *, IOR_param_t *);
IOR_offset_t IOR_Xfer_NCMPI (int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
void IOR_Close_NCMPI (void *, IOR_param_t *);
void IOR_Delete_NCMPI (char *, IOR_param_t *);
void IOR_SetVersion_NCMPI (IOR_param_t *);
void IOR_Fsync_NCMPI (void *, IOR_param_t *);
IOR_offset_t IOR_GetFileSize_NCMPI (IOR_param_t *, MPI_Comm, char *);
#endif /* not _AIORI_H */

5
src/C/cbif/Makefile Normal file
View File

@ -0,0 +1,5 @@
all:
$(CC) cbif.c -o cbif
clean:
rm -f cbif

135
src/C/cbif/cbif.c Normal file
View File

@ -0,0 +1,135 @@
/******************************************************************************\
* *
* Copyright (c) 2006, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: cbif.c,v $
* $Revision: 1.1.1.1 $
* $Date: 2007/10/15 23:36:54 $
* $Author: rklundt $
*
* Purpose:
* Changes a specific Byte offset In File
*
\******************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define ERR(MSG) do { \
fprintf(stdout, "** error **\n"); \
fprintf(stdout, "ERROR in %s (line %d): %s.\n", \
__FILE__, __LINE__, MSG); \
fprintf(stdout, "ERROR: %s\n", strerror(errno)); \
fprintf(stdout, "** exiting **\n"); \
fflush(stdout); \
exit(1); \
} while (0)
#define BYTE_BOUNDARY 8
int
main(int argc, char **argv)
{
int i;
int fd;
int value;
unsigned char oldBuffer[BYTE_BOUNDARY];
unsigned char newBuffer[BYTE_BOUNDARY];
char *fileName;
long long int offset;
long long int alignedOffset;
long long int bufferIndex;
long long int indexMask = (long long int)(BYTE_BOUNDARY - 1);
long long int alignedMask = (long long int)(BYTE_BOUNDARY - 1)
^ (long long int)(-1);
/* check usage */
if (argc != 3 && argc !=4) {
printf("Usage: %s <filename> <offset> [<newValue>]\n", argv[0]);
printf("Returns value of byte offset, or modifies to new value.\n");
exit(1);
}
/* gather arguments */
fileName = argv[1];
sscanf(argv[2], "%lld", &offset);
alignedOffset = offset & alignedMask;
bufferIndex = offset & indexMask;
if (argc == 4) {
sscanf(argv[3], "%d", &value);
if (value < 0 || value > 255) ERR("ERROR: <value> must be 0-255");
}
/* open file */
fd = open64(fileName, O_RDWR);
if (fd < 0) ERR("ERROR: Unable to open file");
/* seek to offset */
if (lseek64(fd, alignedOffset, SEEK_SET) == -1)
ERR("ERROR: Unable to seek to file offset");
/* read into buffer */
if (read(fd, &oldBuffer, BYTE_BOUNDARY) <= 0)
ERR("ERROR: Unable to read file offset");
if (argc == 4) {
/* write from buffer */
/* update buffer with new value */
memcpy(newBuffer, oldBuffer, BYTE_BOUNDARY);
newBuffer[bufferIndex] = (unsigned char)value;
/* seek to offset */
if (lseek64(fd, alignedOffset, SEEK_SET) == -1)
ERR("ERROR: Unable to seek to file offset");
/* write buffer */
if (write(fd, &newBuffer, BYTE_BOUNDARY) != BYTE_BOUNDARY)
ERR("ERROR: Unable to write to file offset");
}
/* print data */
/* print header */
if (argc == 3) {
fprintf(stdout, "offset: original value: \n");
fprintf(stdout, "------------------ ------------------\n");
} else {
fprintf(stdout,
"offset: original value: new value: \n");
fprintf(stdout,
"------------------ ------------------ ------------------\n");
}
/* next hex, multiple bytes */
fprintf(stdout, "0x%016x 0x", alignedOffset);
for (i = 0; i < BYTE_BOUNDARY; i++) {
fprintf(stdout, "%02x", oldBuffer[i]);
}
if (argc == 4) {
fprintf(stdout, " 0x");
for (i = 0; i < BYTE_BOUNDARY; i++) {
fprintf(stdout, "%02x", newBuffer[i]);
}
}
fprintf(stdout, "\n");
/* finally decimal, single byte */
fprintf(stdout, "%-16lld %-3d (0x%02x)", offset,
oldBuffer[bufferIndex], oldBuffer[bufferIndex]);
if (argc == 4) {
fprintf(stdout, " %-3d (0x%02x)\n",
newBuffer[bufferIndex], newBuffer[bufferIndex]);
}
fprintf(stdout, "\n");
/* finished */
fflush(stdout);
close(fd);
return(0);
} /* main() */

149
src/C/defaults.h Normal file
View File

@ -0,0 +1,149 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: defaults.h,v $
* $Revision: 1.3 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* This is a header file that contains the default settings necessary for
* IOR.
*
\******************************************************************************/
/********************* Modifications to IOR-2.10.1 *****************************
* hodson - 8/18/2008: Added Default values for the following variables *
* int TestNum; * test reference number *
* int taskPerNodeOffset; * task node offset for reading files *
* int reorderTasksRandom; * reorder tasks for random file read back *
* int reorderTasksRandomSeed; * reorder tasks for random file read seed *
* int fsyncPerWrite; * fsync() after each write *
*******************************************************************************/
#ifndef _IOR_DEFAULTS_H
#define _IOR_DEFAULTS_H
#include "aiori.h"
/*************************** D E F I N I T I O N S ****************************/
/******************************************************************************/
/*
* Default parameter settings for a test script. This should be the minimum
* test runnable.
*/
IOR_param_t defaultParameters = {
"", /* debug info string */
IOR_IRUSR | /* file permissions */
IOR_IWUSR |
IOR_IRGRP |
IOR_IWGRP,
IOR_RDWR | /* open flags POSIX/MPIIO */
IOR_CREAT,
-1, /* test reference number */
"POSIX", /* api */
"", /* api version */
"HOST(OSTYPE)", /* platform */
"testFile", /* test file */
"", /* filename for fpp read check */
"", /* hints file */
"", /* options */
0, /* numTasks */
1, /* nodes */
1, /* tasks per node */
1, /* repetitions */
-1, /* rep counter */
0, /* multiple files */
0, /* intertest delay */
NULL, NULL, /* write results array */
NULL, NULL, /* read results array */
WRITE, /* used in HDF5 for create(WRITE) and open(READ) */
TRUE, /* read flag */
TRUE, /* write flag */
FALSE, /* file-per-proc flag */
FALSE, /* reorder tasks */
1, /* task file offset for read */
FALSE, /* reorder tasks random */
0, /* reorder tasks random seed offset value*/
FALSE, /* check write */
FALSE, /* check read */
FALSE, /* keep test file on exit */
FALSE, /* keep test file with errors */
FALSE, /* error found in data check */
FALSE, /* halt on error */
FALSE, /* collective I/O */
1, /* segment count */
1048576, /* block size */
262144, /* transfer size */
0, /* offset */
NULL, /* expected aggregate file size array */
NULL, /* stat'ed aggregate file size array */
NULL, /* xfered aggregate file size array */
NULL, /* aggregate file size array used for b/w */
FALSE, /* preallocate file size */
FALSE, /* use file view */
FALSE, /* use shared file pointer */
FALSE, /* use strided datatype */
FALSE, /* use O_DIRECT, bypassing I/O buffers */
FALSE, /* show hints */
FALSE, /* show help */
FALSE, /* unique directory for each file-per-process */
FALSE, /* do not delete test file before access */
FALSE, /* use file offset as stored signature */
0, /* deadline in seconds for any test phase (0=off) */
0, /* max time in minutes to run tests (0=off) */
0, /* warn on outlier N seconds from mean (0=off) */
0, /* verbosity */
0, /* set time stamp signature */
0, /* time stamp signature value */
NULL, /* additional fd for fpp read check */
-1, /* random seed for write/read check */
0, /* access is to random, not sequential, offsets */
MPI_COMM_WORLD, /* MPI communicator */
/* POSIX */
FALSE, /* single transfer (no retry) */
FALSE, /* fsync after each POSIX write */
FALSE, /* fsync after POSIX write close */
/* MPI */
0, /* MPI transfer datatype */
0, /* MPI file view datatype */
/* HDF5 */
FALSE, /* individual data sets */
FALSE, /* no fill */
1, /* alignment */
/* NCMPI */
0, /* var_id handle for datasets */
/* Lustre */
0, /* lustre_stripe_count */
0, /* lustre_stripe_size */
-1, /* lustre_start_ost */
0, /* lustre_ignore_locks */
#if USE_UNDOC_OPT
0, /* corrupt file(s) */
0, /* fill the file system */
0, /* include delete time */
0, /* multiple rereads of file */
/* NFS */
"", /* absolute path to NFS servers */
"", /* prefix for NFS server name */
0, /* number of NFS servers to be used */
#endif /* USE_UNDOC_OPT */
0, /* test's unique ID */
0 /* intraTestBarriers */
};
#endif /* not _IOR_DEFAULTS_H */

221
src/C/iordef.h Normal file
View File

@ -0,0 +1,221 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: iordef.h,v $
* $Revision: 1.4 $
* $Date: 2010/08/02 16:43:14 $
* $Author: rklundt $
*
* Purpose:
* This is a header file that contains the definitions and macros
* needed for IOR.
*
\******************************************************************************/
#ifndef _IORDEF_H
#define _IORDEF_H
#ifdef _WIN32
# define _CRT_SECURE_NO_WARNINGS
# define _CRT_RAND_S
# pragma warning(4 : 4996) /* Don't complain about POSIX names */
# pragma warning(4 : 4267) /* '=' : conversion from 'size_t' to 'int' */
# pragma warning(4 : 4244) /* 'function' : conversion from 'IOR_offset_t' to 'int' */
# include <Windows.h>
# include <stdlib.h>
# include <io.h>
# include <direct.h>
# include <string.h>
# include "win/getopt.h"
# define MAXPATHLEN 1024
# define F_OK 00
# define W_OK 02
# define R_OK 04
# define X_OK 04
# define lseek _lseeki64
# define fsync _commit
# define mkdir(dir, mode) _mkdir(dir)
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
# define srandom srand
# define random() (rand() * (RAND_MAX+1) + rand()) /* Note: only 30 bits */
# define sleep(X) Sleep((X)*1000)
# define getpagesize() 4096
#else
# include <sys/param.h> /* MAXPATHLEN */
# include <unistd.h>
#endif
#include <mpi.h>
#include <stdio.h>
#include <errno.h>
/************************** D E C L A R A T I O N S ***************************/
extern int numTasks, /* MPI variables */
rank,
rankOffset,
verbose; /* verbose output */
/*************************** D E F I N I T I O N S ****************************/
#define IOR_RELEASE "IOR-2.10.3"
#ifndef FALSE
# define FALSE 0
#endif /* not FALSE */
#ifndef TRUE
# define TRUE 1
#endif /* not TRUE */
#ifndef NULL
# define NULL ((void *)0)
#endif /* not NULL */
#define KILOBYTE 1000
#define MEGABYTE 1000000
#define GIGABYTE 1000000000
#define KIBIBYTE (1 << 10)
#define MEBIBYTE (1 << 20)
#define GIBIBYTE (1 << 30)
/* for displaying MiB or MB */
#define BASE_TWO 0
#define BASE_TEN 1
/* any write/read access in code */
#define WRITE 0
#define WRITECHECK 1
#define READ 2
#define READCHECK 3
#define CHECK 4
/* verbosity settings */
#define VERBOSE_0 0
#define VERBOSE_1 1
#define VERBOSE_2 2
#define VERBOSE_3 3
#define VERBOSE_4 4
#define VERBOSE_5 5
#define MAX_STR 1024 /* max string length */
#define MAX_HINTS 16 /* max number of hints */
#define MAX_RETRY 10000 /* max retries for POSIX xfer */
#define DELIMITERS " \t\r\n=" /* ReadScript() */
#define FILENAME_DELIMITER '@' /* ParseFileName() */
/* MACROs for debugging */
#define HERE fprintf(stdout, "** LINE %d (TASK=%d) **\n", \
__LINE__, rank);
/* Other MACROs */
#define USE_UNDOC_OPT TRUE /* USE UNDOCumented OPTion */
typedef long long int IOR_offset_t;
typedef long long int IOR_size_t;
/******************************** M A C R O S *********************************/
/******************************************************************************/
/*
* WARN_RESET will display a custom error message and set value to default
*/
#define WARN_RESET(MSG, VAL) do { \
test->VAL = defaultParameters.VAL; \
if (rank == 0) { \
fprintf(stdout, "WARNING: %s. Using value of %d.\n", \
MSG, test->VAL); \
} \
fflush(stdout); \
} while (0)
/******************************************************************************/
/*
* WARN will display a custom error message as well as an error string from
* sys_errlist, but will not exit the program
*/
#define WARN(MSG) do { \
if (verbose > VERBOSE_2) { \
fprintf(stdout, "WARNING: %s, in %s (line %d).\n", \
MSG, __FILE__, __LINE__); \
} else { \
fprintf(stdout, "WARNING: %s.\n", MSG); \
} \
fflush(stdout); \
} while (0)
/******************************************************************************/
/*
* ERR will display a custom error message as well as an error string from
* sys_errlist and then exit the program
*/
#define ERR(MSG) do { \
fprintf(stdout, "** error **\n"); \
fprintf(stdout, "ERROR in %s (line %d): %s.\n", \
__FILE__, __LINE__, MSG); \
fprintf(stdout, "ERROR: %s\n", strerror(errno)); \
fprintf(stdout, "** exiting **\n"); \
fflush(stdout); \
MPI_Abort(MPI_COMM_WORLD, -1); \
} while (0)
/******************************************************************************/
/*
* MPI_CHECK will display a custom error message as well as an error string
* from the MPI_STATUS and then exit the program
*/
#define MPI_CHECK(MPI_STATUS, MSG) do { \
char resultString[MPI_MAX_ERROR_STRING]; \
int resultLength; \
\
if (MPI_STATUS != MPI_SUCCESS) { \
fprintf(stdout, "** error **\n"); \
fprintf(stdout, "ERROR in %s (line %d): %s.\n", \
__FILE__, __LINE__, MSG); \
MPI_Error_string(MPI_STATUS, resultString, &resultLength); \
fprintf(stdout, "MPI %s\n", resultString); \
fprintf(stdout, "** exiting **\n"); \
fflush(stdout); \
MPI_Abort(MPI_COMM_WORLD, -1); \
} \
} while(0)
/******************************************************************************/
/*
* System info for Windows.
*/
#ifdef _WIN32
struct utsname {
char sysname [16];
char nodename[257];
char release [16];
char version [16];
char machine [16];
};
extern int uname(struct utsname *name);
#endif /* _WIN32 */
#endif /* not _IORDEF_H */

434
src/C/parse_options.c Normal file
View File

@ -0,0 +1,434 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: parse_options.c,v $
* $Revision: 1.3 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* Parse commandline functions.
*
\******************************************************************************/
/********************* Modifications to IOR-2.10.1 *****************************
* hodson - 8/18/2008: Added parsing for the following variables *
* int TestNum; * test reference number *
* int taskPerNodeOffset; * task node offset for reading files *
* int reorderTasksRandom; * reorder tasks for random file read back *
* int reorderTasksRandomSeed; * reorder tasks for random file read seed *
* int fsyncPerWrite; * fsync() after each write *
*******************************************************************************/
#include "IOR.h"
#include "defaults.h" /* IOR defaults */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
IOR_param_t initialTestParams;
/******************************************************************************/
/*
* Check and correct all settings of each test in queue for correctness.
*/
void CheckRunSettings(IOR_queue_t *tests) {
while (tests != NULL) {
/* If no write/read/check action requested, set both write and read */
if (tests->testParameters.writeFile == FALSE
&& tests->testParameters.readFile == FALSE
&& tests->testParameters.checkWrite == FALSE
&& tests->testParameters.checkRead == FALSE) {
tests->testParameters.readFile = TRUE;
tests->testParameters.writeFile = TRUE;
}
/* If numTasks set to 0, use all tasks */
if (tests->testParameters.numTasks == 0) {
MPI_CHECK(MPI_Comm_size(MPI_COMM_WORLD,
&tests->testParameters.numTasks),
"MPI_Comm_size() error");
}
tests = tests->nextTest;
}
} /* CheckRunSettings() */
/******************************************************************************/
/*
* Set flags from commandline string/value pairs.
*/
void DecodeDirective(char *line, IOR_param_t *test)
{
char option[MAX_STR];
char value[MAX_STR];
int rc;
rc = sscanf(line, " %[^=# \t\r\n] = %[^# \t\r\n] ", option, value);
if (rc != 2 && rank == 0) {
fprintf(stdout, "Syntax error in configuration options: %s\n", line);
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error");
}
if (strcasecmp(option, "api") == 0) {
strcpy(test->api, value);
} else if (strcasecmp(option, "testnum") == 0) {
test->TestNum = atoi(value);
} else if (strcasecmp(option, "debug") == 0) {
strcpy(test->debug, value);
} else if (strcasecmp(option, "platform") == 0) {
strcpy(test->platform, value);
} else if (strcasecmp(option, "testfile") == 0) {
strcpy(test->testFileName, value);
} else if (strcasecmp(option, "hintsfilename") == 0) {
strcpy(test->hintsFileName, value);
} else if (strcasecmp(option, "deadlineforstonewalling") == 0) {
test->deadlineForStonewalling = atoi(value);
} else if (strcasecmp(option, "maxtimeduration") == 0) {
test->maxTimeDuration = atoi(value);
} else if (strcasecmp(option, "outlierthreshold") == 0) {
test->outlierThreshold = atoi(value);
} else if (strcasecmp(option, "nodes") == 0) {
test->nodes = atoi(value);
} else if (strcasecmp(option, "repetitions") == 0) {
test->repetitions = atoi(value);
} else if (strcasecmp(option, "intertestdelay") == 0) {
test->interTestDelay = atoi(value);
} else if (strcasecmp(option, "readfile") == 0) {
test->readFile = atoi(value);
} else if (strcasecmp(option, "writefile") == 0) {
test->writeFile = atoi(value);
} else if (strcasecmp(option, "fileperproc") == 0) {
test->filePerProc = atoi(value);
} else if (strcasecmp(option, "reordertasksconstant") == 0) {
test->reorderTasks = atoi(value);
} else if (strcasecmp(option, "taskpernodeoffset") == 0) {
test->taskPerNodeOffset = atoi(value);
} else if (strcasecmp(option, "reordertasksrandom") == 0) {
test->reorderTasksRandom = atoi(value);
} else if (strcasecmp(option, "reordertasksrandomSeed") == 0) {
test->reorderTasksRandomSeed = atoi(value);
} else if (strcasecmp(option, "checkwrite") == 0) {
test->checkWrite = atoi(value);
} else if (strcasecmp(option, "checkread") == 0) {
test->checkRead = atoi(value);
} else if (strcasecmp(option, "keepfile") == 0) {
test->keepFile = atoi(value);
} else if (strcasecmp(option, "keepfilewitherror") == 0) {
test->keepFileWithError = atoi(value);
} else if (strcasecmp(option, "multiFile") == 0) {
test->multiFile = atoi(value);
} else if (strcasecmp(option, "quitonerror") == 0) {
test->quitOnError = atoi(value);
} else if (strcasecmp(option, "segmentcount") == 0) {
test->segmentCount = StringToBytes(value);
} else if (strcasecmp(option, "blocksize") == 0) {
test->blockSize = StringToBytes(value);
} else if (strcasecmp(option, "transfersize") == 0) {
test->transferSize = StringToBytes(value);
} else if (strcasecmp(option, "setalignment") == 0) {
test->setAlignment = StringToBytes(value);
} else if (strcasecmp(option, "singlexferattempt") == 0) {
test->singleXferAttempt = atoi(value);
} else if (strcasecmp(option, "individualdatasets") == 0) {
test->individualDataSets = atoi(value);
} else if (strcasecmp(option, "intraTestBarriers") == 0) {
test->intraTestBarriers = atoi(value);
} else if (strcasecmp(option, "nofill") == 0) {
test->noFill = atoi(value);
} else if (strcasecmp(option, "verbose") == 0) {
test->verbose = atoi(value);
} else if (strcasecmp(option, "settimestampsignature") == 0) {
test->setTimeStampSignature = atoi(value);
} else if (strcasecmp(option, "collective") == 0) {
test->collective = atoi(value);
} else if (strcasecmp(option, "preallocate") == 0) {
test->preallocate = atoi(value);
} else if (strcasecmp(option, "storefileoffset") == 0) {
test->storeFileOffset = atoi(value);
} else if (strcasecmp(option, "usefileview") == 0) {
test->useFileView = atoi(value);
} else if (strcasecmp(option, "usesharedfilepointer") == 0) {
test->useSharedFilePointer = atoi(value);
} else if (strcasecmp(option, "useo_direct") == 0) {
test->useO_DIRECT = atoi(value);
} else if (strcasecmp(option, "usestrideddatatype") == 0) {
test->useStridedDatatype = atoi(value);
} else if (strcasecmp(option, "showhints") == 0) {
test->showHints = atoi(value);
} else if (strcasecmp(option, "showhelp") == 0) {
test->showHelp = atoi(value);
} else if (strcasecmp(option, "uniqueDir") == 0) {
test->uniqueDir = atoi(value);
} else if (strcasecmp(option, "useexistingtestfile") == 0) {
test->useExistingTestFile = atoi(value);
} else if (strcasecmp(option, "fsyncperwrite") == 0) {
test->fsyncPerWrite = atoi(value);
} else if (strcasecmp(option, "fsync") == 0) {
test->fsync = atoi(value);
} else if (strcasecmp(option, "randomoffset") == 0) {
test->randomOffset = atoi(value);
} else if (strcasecmp(option, "lustrestripecount") == 0) {
test->lustre_stripe_count = atoi(value);
} else if (strcasecmp(option, "lustrestripesize") == 0) {
test->lustre_stripe_size = StringToBytes(value);
} else if (strcasecmp(option, "lustrestartost") == 0) {
test->lustre_start_ost = atoi(value);
} else if (strcasecmp(option, "lustreignorelocks") == 0) {
test->lustre_ignore_locks = atoi(value);
#if USE_UNDOC_OPT
} else if (strcasecmp(option, "corruptFile") == 0) {
test->corruptFile = atoi(value);
} else if (strcasecmp(option, "fillTheFileSystem") == 0) {
test->fillTheFileSystem = atoi(value);
} else if (strcasecmp(option, "includeDeleteTime") == 0) {
test->includeDeleteTime = atoi(value);
} else if (strcasecmp(option, "multiReRead") == 0) {
test->multiReRead = atoi(value);
} else if (strcasecmp(option, "nfs_rootpath") == 0) {
strcpy(test->NFS_rootPath, value);
} else if (strcasecmp(option, "nfs_servername") == 0) {
strcpy(test->NFS_serverName, value);
} else if (strcasecmp(option, "nfs_servercount") == 0) {
test->NFS_serverCount = atoi(value);
#endif /* USE_UNDOC_OPT */
} else if (strcasecmp(option, "numtasks") == 0) {
test->numTasks = atoi(value);
} else {
if (rank == 0)
fprintf(stdout, "Unrecognized parameter \"%s\"\n", option);
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error");
}
} /* DecodeDirective() */
/******************************************************************************/
/*
* Parse a single line, which may contain multiple comma-seperated directives
*/
void
ParseLine(char *line, IOR_param_t *test)
{
char *start, *end;
start = line;
do {
end = strchr(start, ',');
if (end != NULL)
*end = '\0';
DecodeDirective(start, test);
start = end + 1;
} while (end != NULL);
} /* ParseLine() */
/******************************************************************************/
/*
* Determines if the string "haystack" contains only the string "needle", and
* possibly whitespace before and after needle. Function is case insensitive.
*/
int
contains_only(char *haystack, char *needle)
{
char *ptr, *end;
end = haystack + strlen(haystack);
/* skip over leading shitspace */
for (ptr = haystack; ptr < end; ptr++) {
if (!isspace(*ptr))
break;
}
/* check for "needle" */
if (strncasecmp(ptr, needle, strlen(needle)) != 0)
return 0;
/* make sure the rest of the line is only whitspace as well */
for (ptr += strlen(needle); ptr < end; ptr++) {
if (!isspace(*ptr))
return 0;
}
return 1;
} /* contains_only() */
/******************************************************************************/
/*
* Read the configuration script, allocating and filling in the structure of
* global parameters.
*/
IOR_queue_t *
ReadConfigScript(char * scriptName)
{
int test_num = 0;
int runflag = 0;
char linebuf[MAX_STR];
char empty[MAX_STR];
FILE *file;
IOR_queue_t *head = NULL;
IOR_queue_t *tail = NULL;
IOR_queue_t *newTest = NULL;
/* Initialize the first test */
head = CreateNewTest(test_num++);
tail = head;
/* open the script */
file = fopen(scriptName, "r");
if (file == NULL)
ERR("cannot open file");
/* search for the "IOR START" line */
while(fgets(linebuf, MAX_STR, file) != NULL) {
if (contains_only(linebuf, "ior start")) {
break;
}
}
/* Iterate over a block of IOR commands */
while(fgets(linebuf, MAX_STR, file) != NULL) {
/* skip empty lines */
if (sscanf(linebuf, "%s", empty) == -1)
continue;
/* skip lines containing only comments */
if (sscanf(linebuf, " #%s", empty) == 1)
continue;
if (contains_only(linebuf, "ior stop")) {
break;
} else if (contains_only(linebuf, "run")) {
runflag = 1;
} else {
/* If this directive was preceded by a "run" line, then
create and initialize a new test structure */
if (runflag) {
newTest = (IOR_queue_t *)malloc(sizeof(IOR_queue_t));
if (newTest == NULL)
ERR("malloc failed");
newTest->testParameters = tail->testParameters;
newTest->testParameters.id = test_num++;
tail->nextTest = newTest;
tail = newTest;
tail->nextTest = NULL;
runflag = 0;
}
ParseLine(linebuf, &tail->testParameters);
}
}
/* close the script */
if (fclose(file) != 0)
ERR("cannot close script file");
return(head);
} /* ReadConfigScript() */
/******************************************************************************/
/*
* Parse Commandline.
*/
IOR_queue_t *
ParseCommandLine(int argc, char ** argv)
{
static const char * opts
= "A:a:b:BcCQ:ZX:d:D:YeEf:FgG:hHi:j:J:IkKlmnN:o:O:pPqrRs:St:T:uU:vVwWxz";
int c, i;
static IOR_queue_t *tests = NULL;
/* suppress getopt() error message when a character is unrecognized */
opterr = 0;
initialTestParams = defaultParameters;
GetPlatformName(initialTestParams.platform);
initialTestParams.writeFile = initialTestParams.readFile = FALSE;
initialTestParams.checkWrite = initialTestParams.checkRead = FALSE;
while ((c = getopt(argc, argv, opts)) != -1) {
switch (c) {
case 'A': initialTestParams.TestNum = atoi(optarg); break;
case 'a': strcpy(initialTestParams.api, optarg); break;
case 'b': initialTestParams.blockSize =
StringToBytes(optarg); break;
case 'B': initialTestParams.useO_DIRECT = TRUE; break;
case 'c': initialTestParams.collective = TRUE; break;
case 'C': initialTestParams.reorderTasks = TRUE; break;
case 'Q': initialTestParams.taskPerNodeOffset =
atoi(optarg); break;
case 'Z': initialTestParams.reorderTasksRandom = TRUE; break;
case 'X': initialTestParams.reorderTasksRandomSeed =
atoi(optarg); break;
case 'd': initialTestParams.interTestDelay = atoi(optarg); break;
case 'D': initialTestParams.deadlineForStonewalling =
atoi(optarg); break;
case 'Y': initialTestParams.fsyncPerWrite = TRUE; break;
case 'e': initialTestParams.fsync = TRUE; break;
case 'E': initialTestParams.useExistingTestFile = TRUE; break;
case 'f': tests = ReadConfigScript(optarg); break;
case 'F': initialTestParams.filePerProc = TRUE; break;
case 'g': initialTestParams.intraTestBarriers = TRUE; break;
case 'G': initialTestParams.setTimeStampSignature =
atoi(optarg); break;
case 'h': initialTestParams.showHelp = TRUE; break;
case 'H': initialTestParams.showHints = TRUE; break;
case 'i': initialTestParams.repetitions = atoi(optarg); break;
case 'I': initialTestParams.individualDataSets = TRUE; break;
case 'j': initialTestParams.outlierThreshold =
atoi(optarg); break;
case 'J': initialTestParams.setAlignment =
StringToBytes(optarg); break;
case 'k': initialTestParams.keepFile = TRUE; break;
case 'K': initialTestParams.keepFileWithError = TRUE; break;
case 'l': initialTestParams.storeFileOffset = TRUE; break;
case 'm': initialTestParams.multiFile = TRUE; break;
case 'n': initialTestParams.noFill = TRUE; break;
case 'N': initialTestParams.numTasks = atoi(optarg); break;
case 'o': strcpy(initialTestParams.testFileName, optarg); break;
case 'O': ParseLine(optarg, &initialTestParams); break;
case 'p': initialTestParams.preallocate = TRUE; break;
case 'P': initialTestParams.useSharedFilePointer = TRUE; break;
case 'q': initialTestParams.quitOnError = TRUE; break;
case 'r': initialTestParams.readFile = TRUE; break;
case 'R': initialTestParams.checkRead = TRUE; break;
case 's': initialTestParams.segmentCount = atoi(optarg); break;
case 'S': initialTestParams.useStridedDatatype = TRUE; break;
case 't': initialTestParams.transferSize =
StringToBytes(optarg); break;
case 'T': initialTestParams.maxTimeDuration = atoi(optarg);break;
case 'u': initialTestParams.uniqueDir = TRUE; break;
case 'U': strcpy(initialTestParams.hintsFileName, optarg); break;
case 'v': initialTestParams.verbose++; break;
case 'V': initialTestParams.useFileView = TRUE; break;
case 'w': initialTestParams.writeFile = TRUE; break;
case 'W': initialTestParams.checkWrite = TRUE; break;
case 'x': initialTestParams.singleXferAttempt = TRUE; break;
case 'z': initialTestParams.randomOffset = TRUE; break;
default: fprintf (stdout, "ParseCommandLine: unknown option `-%c'.\n", optopt);
}
}
for (i = optind; i < argc; i++)
fprintf (stdout, "non-option argument: %s\n", argv[i]);
/* If an IOR script was not used, initialize test queue to the defaults */
if (tests == NULL) {
tests = (IOR_queue_t *) malloc (sizeof(IOR_queue_t));
if (!tests)
ERR("malloc failed");
tests->testParameters = initialTestParams;
tests->nextTest = NULL;
}
CheckRunSettings(tests);
return(tests);
} /* ParseCommandLine() */

539
src/C/utilities.c Normal file
View File

@ -0,0 +1,539 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* CVS info:
* $RCSfile: utilities.c,v $
* $Revision: 1.3 $
* $Date: 2008/12/02 17:12:14 $
* $Author: rklundt $
*
* Purpose:
* Additional utilities necessary for both MPIIO and HDF5.
*
\******************************************************************************/
/**********************Modifications to IOR-2.10.1 *****************************
* hodson, 8/18/2008: *
* Removed duplicate regex.h include (thanks to Brian Lucas) *
*******************************************************************************/
#include "aiori.h" /* abstract IOR interface */
#include "IOR.h" /* IOR functions */
#include <errno.h> /* sys_errlist */
#include <fcntl.h> /* open() */
#include <math.h> /* pow() */
#include <stdio.h> /* only for fprintf() */
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#ifndef _WIN32
# include <regex.h>
# ifdef __sun /* SunOS does not support statfs(), instead uses statvfs() */
# include <sys/statvfs.h>
# else /* !__sun */
# include <sys/statfs.h>
# endif /* __sun */
# include <sys/time.h> /* gettimeofday() */
#endif
/************************** D E C L A R A T I O N S ***************************/
extern int errno, /* error number */
numTasks, /* MPI variables */
rank,
rankOffset,
verbose; /* verbose output */
/***************************** F U N C T I O N S ******************************/
/******************************************************************************/
/*
* Returns string containing the current time.
*/
char *
CurrentTimeString(void)
{
static time_t currentTime;
char * currentTimePtr;
if ((currentTime = time(NULL)) == -1) ERR("cannot get current time");
if ((currentTimePtr = ctime(&currentTime)) == NULL) {
ERR("cannot read current time");
}
/* ctime string ends in \n */
return (currentTimePtr);
} /* CurrentTimeString() */
/******************************************************************************/
/*
* Dump transfer buffer.
*/
void
DumpBuffer(void *buffer,
size_t size)
{
size_t i, j;
unsigned long long *dumpBuf = (unsigned long long *)buffer;
for (i = 0; i < ((size/sizeof(IOR_size_t))/4); i++) {
for (j = 0; j < 4; j++) {
fprintf(stdout, "%016llx ", dumpBuf[4*i+j]);
}
fprintf(stdout, "\n");
}
return;
} /* DumpBuffer() */
/******************************************************************************/
/*
* Sends all strings to root nodes and displays.
*/
void
OutputToRoot(int numTasks, MPI_Comm comm, char * stringToDisplay)
{
int i;
int swapNeeded = TRUE;
int pairsToSwap;
char ** stringArray;
char tmpString[MAX_STR];
MPI_Status status;
/* malloc string array */
stringArray = (char **)malloc(sizeof(char *) * numTasks);
if (stringArray == NULL) ERR("out of memory");
for (i = 0; i < numTasks; i++) {
stringArray[i] = (char *)malloc(sizeof(char) * MAX_STR);
if (stringArray[i] == NULL) ERR("out of memory");
}
strcpy(stringArray[rank], stringToDisplay);
if (rank == 0) {
/* MPI_receive all strings */
for (i = 1; i < numTasks; i++) {
MPI_CHECK(MPI_Recv(stringArray[i], MAX_STR, MPI_CHAR,
MPI_ANY_SOURCE, MPI_ANY_TAG, comm, &status),
"MPI_Recv() error");
}
} else {
/* MPI_send string to root node */
MPI_CHECK(MPI_Send(stringArray[rank], MAX_STR, MPI_CHAR, 0, 0, comm),
"MPI_Send() error");
}
MPI_CHECK(MPI_Barrier(comm), "barrier error");
/* sort strings using bubblesort */
if (rank == 0) {
pairsToSwap = numTasks-1;
while (swapNeeded) {
swapNeeded = FALSE;
for (i = 0; i < pairsToSwap; i++) {
if (strcmp(stringArray[i], stringArray[i+1]) > 0) {
strcpy(tmpString, stringArray[i]);
strcpy(stringArray[i], stringArray[i+1]);
strcpy(stringArray[i+1], tmpString);
swapNeeded = TRUE;
}
}
pairsToSwap--;
}
}
/* display strings */
if (rank == 0) {
for (i = 0; i < numTasks; i++) {
fprintf(stdout, "%s\n", stringArray[i]);
}
}
/* free strings */
for (i = 0; i < numTasks; i++) {
free(stringArray[i]);
}
free(stringArray);
} /* OutputToRoot() */
/******************************************************************************/
/*
* Set hints for MPIIO, HDF5, or NCMPI.
*/
void
SetHints(MPI_Info * mpiHints, char * hintsFileName)
{
char hintString[MAX_STR],
settingVal[MAX_STR],
valueVal[MAX_STR];
extern char ** environ;
int i;
FILE * fd;
/*
* This routine checks for hints from the environment and/or from the
* hints files. The hints are of the form:
* 'IOR_HINT__<layer>__<hint>=<value>', where <layer> is either 'MPI'
* or 'GPFS', <hint> is the full name of the hint to be set, and <value>
* is the hint value. E.g., 'setenv IOR_HINT__MPI__IBM_largeblock_io true'
* or 'IOR_HINT__GPFS__hint=value' in the hints file.
*/
MPI_CHECK(MPI_Info_create(mpiHints), "cannot create info object");
/* get hints from environment */
for (i = 0; environ[i] != NULL; i++) {
/* if this is an IOR_HINT, pass the hint to the info object */
if (strncmp(environ[i], "IOR_HINT", strlen("IOR_HINT")) == 0) {
strcpy(hintString, environ[i]);
ExtractHint(settingVal, valueVal, hintString);
MPI_CHECK(MPI_Info_set(*mpiHints, settingVal, valueVal),
"cannot set info object");
}
}
/* get hints from hints file */
if (strcmp(hintsFileName, "") != 0) {
/* open the hint file */
fd = fopen(hintsFileName, "r");
if (fd == NULL) {
WARN("cannot open hints file");
} else {
/* iterate over hints file */
while(fgets(hintString, MAX_STR, fd) != NULL) {
if (strncmp(hintString, "IOR_HINT", strlen("IOR_HINT")) == 0) {
ExtractHint(settingVal, valueVal, hintString);
MPI_CHECK(MPI_Info_set(*mpiHints, settingVal, valueVal),
"cannot set info object");
}
}
/* close the hints files */
if (fclose(fd) != 0) ERR("cannot close hints file");
}
}
} /* SetHints() */
/******************************************************************************/
/*
* Extract key/value pair from hint string.
*/
void
ExtractHint(char * settingVal,
char * valueVal,
char * hintString)
{
char * settingPtr,
* valuePtr,
* tmpPtr1,
* tmpPtr2;
settingPtr = (char *)strtok(hintString, "=");
valuePtr = (char *)strtok(NULL, " \t\r\n");
tmpPtr1 = settingPtr;
tmpPtr2 = (char *)strstr(settingPtr, "IOR_HINT__MPI__");
if (tmpPtr1 == tmpPtr2) {
settingPtr += strlen("IOR_HINT__MPI__");
} else {
tmpPtr2 = (char *)strstr(settingPtr, "IOR_HINT__GPFS__");
if (tmpPtr1 == tmpPtr2) {
settingPtr += strlen("IOR_HINT__GPFS__");
fprintf(stdout,
"WARNING: Unable to set GPFS hints (not implemented.)\n");
}
}
strcpy(settingVal, settingPtr);
strcpy(valueVal, valuePtr);
} /* ExtractHint() */
/******************************************************************************/
/*
* Show all hints (key/value pairs) in an MPI_Info object.
*/
void ShowHints(MPI_Info * mpiHints)
{
char key[MPI_MAX_INFO_VAL],
value[MPI_MAX_INFO_VAL];
int flag,
i,
nkeys;
MPI_CHECK(MPI_Info_get_nkeys(*mpiHints, &nkeys),
"cannot get info object keys");
for (i = 0; i < nkeys; i++) {
MPI_CHECK(MPI_Info_get_nthkey(*mpiHints, i, key),
"cannot get info object key");
MPI_CHECK(MPI_Info_get(*mpiHints, key, MPI_MAX_INFO_VAL-1,
value, &flag),
"cannot get info object value");
fprintf(stdout,"\t%s = %s\n", key, value);
}
} /* ShowHints() */
/******************************************************************************/
/*
* Takes a string of the form 64, 8m, 128k, 4g, etc. and converts to bytes.
*/
IOR_offset_t
StringToBytes(char * size_str)
{
IOR_offset_t size = 0;
char range;
int rc;
rc = sscanf(size_str, "%lld%c", &size, &range);
if (rc == 2) {
switch ((int)range) {
case 'k': case 'K': size <<= 10; break;
case 'm': case 'M': size <<= 20; break;
case 'g': case 'G': size <<= 30; break;
}
} else if (rc == 0) {
size = -1;
}
return(size);
} /* StringToBytes() */
/******************************************************************************/
/*
* Displays size of file system and percent of data blocks and inodes used.
*/
void
ShowFileSystemSize(char *fileSystem)
{
#ifndef _WIN32 /* FIXME */
int error;
char realPath[MAX_STR];
char fileSystemUnitStr[MAX_STR] = "GiB";
char inodeUnitStr[MAX_STR] = "Mi";
long long int fileSystemUnitVal = 1024 * 1024 * 1024;
long long int inodeUnitVal = 1024 * 1024;
long long int totalFileSystemSize,
freeFileSystemSize,
totalInodes,
freeInodes;
double totalFileSystemSizeHR,
usedFileSystemPercentage,
usedInodePercentage;
#ifdef __sun /* SunOS does not support statfs(), instead uses statvfs() */
struct statvfs statusBuffer;
#else /* !__sun */
struct statfs statusBuffer;
#endif /* __sun */
#ifdef __sun
if (statvfs(fileSystem, &statusBuffer) != 0) {
ERR("unable to statvfs() file system");
}
#else /* !__sun */
if (statfs(fileSystem, &statusBuffer) != 0) {
ERR("unable to statfs() file system");
}
#endif /* __sun */
/* data blocks */
#ifdef __sun
totalFileSystemSize = statusBuffer.f_blocks * statusBuffer.f_frsize;
freeFileSystemSize = statusBuffer.f_bfree * statusBuffer.f_frsize;
#else /* !__sun */
totalFileSystemSize = statusBuffer.f_blocks * statusBuffer.f_bsize;
freeFileSystemSize = statusBuffer.f_bfree * statusBuffer.f_bsize;
#endif /* __sun */
usedFileSystemPercentage = (1 - ((double)freeFileSystemSize
/ (double)totalFileSystemSize)) * 100;
totalFileSystemSizeHR = (double)totalFileSystemSize
/ (double)fileSystemUnitVal;
if (totalFileSystemSizeHR > 1024) {
totalFileSystemSizeHR = totalFileSystemSizeHR / 1024;
strcpy(fileSystemUnitStr, "TiB");
}
/* inodes */
totalInodes = statusBuffer.f_files;
freeInodes = statusBuffer.f_ffree;
usedInodePercentage = (1 - ((double)freeInodes/(double)totalInodes)) * 100;
/* show results */
if (realpath(fileSystem, realPath) == NULL) {
ERR("unable to use realpath()");
}
fprintf(stdout, "Path: %s\n", realPath);
fprintf(stdout, "FS: %.1f %s Used FS: %2.1f%% ", totalFileSystemSizeHR,
fileSystemUnitStr, usedFileSystemPercentage);
fprintf(stdout, "Inodes: %.1f %s Used Inodes: %2.1f%%\n",
(double)totalInodes / (double)inodeUnitVal,
inodeUnitStr, usedInodePercentage);
fflush(stdout);
#endif /* _WIN32 */
return;
} /* ShowFileSystemSize() */
/******************************************************************************/
/*
* Return match of regular expression -- 0 is failure, 1 is success.
*/
int
Regex(char *string, char *pattern)
{
int retValue = 0;
#ifndef _WIN32 /* Okay to always not match */
regex_t regEx;
regmatch_t regMatch;
regcomp(&regEx, pattern, REG_EXTENDED);
if (regexec(&regEx, string, 1, &regMatch, 0) == 0) {
retValue = 1;
}
regfree(&regEx);
#endif
return(retValue);
} /* Regex() */
#if USE_UNDOC_OPT /* corruptFile */
/******************************************************************************/
/*
* Corrupt file to testing data checking options.
*/
void CorruptFile(char *testFileName,
IOR_param_t *test,
int rep,
int access)
{
IOR_offset_t tmpOff, range, eof;
char fileName[MAX_STR];
/* determine file name */
strcpy(fileName, testFileName);
if (access == READCHECK && test->filePerProc) {
strcpy(fileName, test->testFileName_fppReadCheck);
}
/* determine offset to modify */
SeedRandGen(test->testComm);
eof = test->aggFileSizeFromCalc[rep]
/ (test->filePerProc ? test->numTasks : 1);
if (access == WRITECHECK) {
range = eof - test->offset;
} else { /* READCHECK */
range = test->transferSize;
}
tmpOff = (IOR_offset_t)((rand()/(float)RAND_MAX) * range) + test->offset;
if (tmpOff >= eof) tmpOff = tmpOff / 2;
/* corrupt <fileName> at <offset> with <value> */
if (rank == 0 || test->filePerProc) {
ModifyByteInFile(fileName, tmpOff, 121);
}
return;
} /* CorruptFile() */
/******************************************************************************/
/*
* Modify byte in file - used to testing write/read data checking.
*/
void
ModifyByteInFile(char * fileName,
IOR_offset_t offset,
int byteValue)
{
int fd;
char oldValue[1],
value[1];
value[0] = (char)byteValue;
/* open file, show old value, update to new value */
fd = open(fileName, O_RDWR);
lseek(fd, offset, SEEK_SET);
read(fd, oldValue, 1);
fprintf(stdout,
"** DEBUG: offset %lld in %s changed from %d to %d **\n", offset,
fileName, (unsigned char)oldValue[0], (unsigned char)value[0]);
lseek(fd, offset, SEEK_SET);
write(fd, value, 1);
close(fd);
return;
} /* ModifyByteInFile() */
#endif /* USE_UNDOC_OPT - corruptFile */
/******************************************************************************/
/*
* Seed random generator.
*/
void
SeedRandGen(MPI_Comm testComm)
{
unsigned int randomSeed;
if (rank == 0) {
#ifdef _WIN32
rand_s(&randomSeed);
#else
struct timeval randGenTimer;
gettimeofday(&randGenTimer, (struct timezone *)NULL);
randomSeed = randGenTimer.tv_usec;
#endif
}
MPI_CHECK(MPI_Bcast(&randomSeed, 1, MPI_INT, 0,
testComm), "cannot broadcast random seed value");
srandom(randomSeed);
} /* SeedRandGen() */
/******************************************************************************/
/*
* System info for Windows.
*/
#ifdef _WIN32
int uname(struct utsname *name)
{
DWORD nodeNameSize = sizeof(name->nodename) - 1;
memset(name, 0, sizeof(struct utsname));
if (!GetComputerNameEx(ComputerNameDnsFullyQualified, name->nodename, &nodeNameSize))
ERR("GetComputerNameEx failed");
strncpy(name->sysname, "Windows", sizeof(name->sysname)-1);
/* FIXME - these should be easy to fetch */
strncpy(name->release, "-", sizeof(name->release)-1);
strncpy(name->version, "-", sizeof(name->version)-1);
strncpy(name->machine, "-", sizeof(name->machine)-1);
return 0;
}
#endif /* _WIN32 */

1185
src/C/win/getopt.c Normal file

File diff suppressed because it is too large Load Diff

189
src/C/win/getopt.h Normal file
View File

@ -0,0 +1,189 @@
/* getopt.h */
/* Declarations for getopt.
Copyright (C) 1989-1994, 1996-1999, 2001 Free Software
Foundation, Inc. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software
Foundation; either version 2.1 of the License, or
(at your option) any later version.
The GNU C Library 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 Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General
Public License along with the GNU C Library; if not, write
to the Free Software Foundation, Inc., 59 Temple Place,
Suite 330, Boston, MA 02111-1307 USA. */
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
standalone, or this is the first header included in the source file.
If we are being used with glibc, we need to include <features.h>, but
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
not defined, include <ctype.h>, which will pull in <features.h> for us
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
# include <ctype.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
# if (defined __STDC__ && __STDC__) || defined __cplusplus
const char *name;
# else
char *name;
# endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
#if (defined __STDC__ && __STDC__) || defined __cplusplus
# ifdef __cplusplus // __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts);
# else /* not __GNU_LIBRARY__ */
extern int getopt ();
# endif /* __GNU_LIBRARY__ */
# ifndef __need_getopt
extern int getopt_long (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
# endif
#else /* not __STDC__ */
extern int getopt ();
# ifndef __need_getopt
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
# endif
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */

46
testing/IOR-tester.README Normal file
View File

@ -0,0 +1,46 @@
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
\******************************************************************************/
The IOR-tester runs a series of tests to check and maintain the existing
functionality of the source code as code is modified. The IOR-tester creates
a default test, then modifies it to run test scripts. It runs a large number
of tests, most which are expected to pass, but some with an expectation of
failure.
To run the code, modify the 'DefaultTest' dictionary in the source code to
reflect the test file location, the executable location, etc. Then, run
the code using './IOR-tester.py'.
The expected-pass, pattern-independent tests include:
POSIX only:
o retry transfer
MPIIO only:
o hints
o preallocation
Both POSIX and MPIIO:
o repetition count
o intertest delay
o test file removal
o verbosity
The expected-pass, pattern-dependent tests include:
POSIX:
o write-only, read-only, write/read, and write/read check
o fpp and single file
o segmented, strided
o zero-length, 4-byte, and larger file, block, and transfer sizes
MPIIO (same as POSIX, but using MPIIO access):
o noncollective
o noncollective, file view
o collective
o collective, file view
The expected-fail tests include:
Both POSIX and MPIIO:
o repetition count

1611
testing/IOR-tester.py Executable file

File diff suppressed because it is too large Load Diff

2
testing/hintsFile Normal file
View File

@ -0,0 +1,2 @@
IOR_HINT__MPI__unrecognizedHint=true
IOR_HINT__MPI__IBM_largeblock_io=true