Commit 3266825f authored by Shane Snyder's avatar Shane Snyder

Merge branch 'master' into lustre-mod

Conflicts:
	ChangeLog
parents 1c2df3e1 5e1a0963
......@@ -4,13 +4,22 @@ Darshan Release Change Log
Darshan-3.0.0
=============
* install darshan-null-log-format.h header when installing
darshan-util component, otherwise compiler errors are
generated when building external tools that use
libdarshan-util
* update docs to give debugging tips for cases where
Darshan logs are not generated
* fix shared library regression test script to check for
potential errors with Darshan symbols rather than
failing silently in these cases
* bug fix for determining minimum non-zero counters in
shared file reductions in all modules
* loosen Darshan's PMPI symbol check to prevent inadvertent
disabling of Darshan for some MPICH builds
* update runtime docs to give information on upgrading Darshan
* bug fix for resolving MPI_Gather when LDPRELOADing Darshan's
shared libraries (reported by Richard Hedges)
* bug fix for resolving MPI_Gather and MPI_Barrier when LDPRELOADing
Darshan's shared libraries (reported by Richard Hedges and Rob Latham)
* add more helpful error handling when opening 2.x version log files
* port darshan-diff utility over to new log file format
* fix numerous configure bugs on Cray systems
......
......@@ -12,7 +12,7 @@ DARSHAN_LD_FLAGS="@LDFLAGS@"
# in turn used one of those HLLs).
PRE_LD_FLAGS="-L$DARSHAN_LIB_PATH $DARSHAN_LD_FLAGS -ldarshan -lz -Wl,@$DARSHAN_SHARE_PATH/ld-opts/darshan-base-ld-opts"
POST_LD_FLAGS="-L$DARSHAN_LIB_PATH -ldarshan -lz -lrt -lpthread"
POST_LD_FLAGS="-L$DARSHAN_LIB_PATH -Wl,--start-group -ldarshan -ldarshan-stubs -Wl,--end-group -lz -lrt -lpthread"
usage="\
Usage: darshan-config [--pre-ld-flags] [--post-ld-flags]"
......
......@@ -282,6 +282,10 @@ print OUTPUT<<"EOF";
if [ \$? -eq 0 ] ; then
CXXMPICH=-lmpicxx
fi
bgqlib_out=`grep -m 1 -Po "libmpichcxx-\\S+" \$tmpfile`
if [ \$? -eq 0 ] ; then
CXXMPICH=`echo \$bgqlib_out | sed 's/libmpichcxx-\\(.*\\)\\.a.*/-lmpichcxx-\\1/'`
fi
rm \$tmpfile >& /dev/null
......
......@@ -287,7 +287,13 @@ print OUTPUT<<"EOF";
if [ \$rc_cnk_check -eq 0 ] ; then
FMPICH=-lfmpich.cnk
else
FMPICH=-lfmpich
bgqlib_out=`grep -Po "libmpichf\\S\+\-\\S\+" \$tmpfile 2>/dev/null`
rc_bgqlib_check=\$?
if [ \$rc_bgqlib_check -eq 0 ] ; then
FMPICH=`echo \$bgqlib_out | sed 's/libmpich\\(.*\\)-\\(.*\\).a/-lmpich\\1-\\2/'`
else
FMPICH=-lfmpich
fi
fi
fi
......
......@@ -169,8 +169,8 @@ Example for MPICH 3.1 or earlier:
----
export MPICC_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-cc
export MPICXX_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-cxx
export MPICF77_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-f
export MPICF90_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-f
export MPIF77_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-f
export MPIF90_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-f
----
Examples for command line use:
......@@ -213,17 +213,36 @@ environment variable to insert instrumentation at run time. The executables
should be compiled using the normal, unmodified MPI compiler.
To use this mechanism, set the `LD_PRELOAD` environment variable to the full
path to the Darshan shared library, as in this example:
path to the Darshan shared library. The preferred method of inserting Darshan
instrumentation in this case is to set the LD_PRELOAD variable specifically
for the application of interest. Typically this is possible using
command line arguments offered by the `mpirun` or `mpiexec` scripts or by
the job scheduler:
----
export LD_PRELOAD=/home/carns/darshan-install/lib/libdarshan.so
mpiexec -n 4 -env LD_PRELOAD /home/carns/darshan-install/lib/libdarshan.so mpi-io-test
----
----
srun -n 4 --export=LD_PRELOAD=/home/carns/darshan-install/lib/libdarshan.so mpi-io-test
----
For sequential programs, the following will set LD_PRELOAD for process duration only:
----
env LD_PRELOAD=/home/carns/darshan-install/lib/libdarshan.so mpi-io-test
----
Other environments may have other specific options for controlling this behavior.
Please check your local site documentation for details.
You can then run your application as usual. Some environments may require a
special `mpirun` or `mpiexec` command line argument to propagate the
environment variable to all processes. Other environments may require a
scheduler submission option to control this behavior. Please check your
local site documentation for details.
It is also possible to just export LD_PRELOAD as follows, but it is recommended
against doing that to prevent Darshan and MPI symbols from being pulled into
unrelated binaries:
----
export LD_PRELOAD=/home/carns/darshan-install/lib/libdarshan.so
----
=== Instrumenting dynamically-linked Fortran applications
......@@ -294,8 +313,8 @@ Blue Gene profiling configuration example:
----
export MPICC_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-bg-cc
export MPICXX_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-bg-cxx
export MPICF77_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-bg-f
export MPICF90_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-bg-f
export MPIF77_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-bg-f
export MPIF90_PROFILE=$DARSHAN_PREFIX/share/mpi-profile/darshan-bg-f
----
=== Cray platforms (XE, XC, or similar)
......@@ -511,3 +530,47 @@ behavior at runtime:
* DARSHAN_LOGPATH: specifies the path to write Darshan log files to. Note that this directory needs to be formatted using the darshan-mk-log-dirs script.
* DARSHAN_LOGFILE: specifies the path (directory + Darshan log file name) to write the output Darshan log to. This overrides the default Darshan behavior of automatically generating a log file name and adding it to a log file directory formatted using darshan-mk-log-dirs script.
* DARSHAN_MODMEM: specifies the maximum amount of memory (in MiB) a Darshan instrumentation module can consume at runtime.
== Debugging
=== No log file
In cases where Darshan is not generating a log file for an application, some common things to check are:
* Check stderr to ensure Darshan isn't indicating any internal errors (e.g., invalid log file path)
For statically linked executables:
* Ensure that Darshan symbols are present in the underlying executable by running `nm` on it:
----
> nm test | grep darshan
0000000000772260 b darshan_core
0000000000404440 t darshan_core_cleanup
00000000004049b0 T darshan_core_initialize
000000000076b660 d darshan_core_mutex
00000000004070a0 T darshan_core_register_module
----
* Make sure the application executable is statically linked:
** In general, we encourage the use of purely statically linked executables when using the static
instrumentation method given in link:darshan-runtime.html#_instrumenting_statically_linked_applications[Section 5]
** If purely static executables are not an option, we encourage users to use the LD_PRELOAD method of
instrumentation given in link:darshan-runtime.html#_instrumenting_dynamically_linked_applications[Section 6]
** Statically linked executables are the default on Cray platforms and the IBM BG platforms;
statically linked executables can be explicitly requested using the `-static` compile option to most compilers
** You can verify that an executable is purely statically linked by using the `file` command:
----
> file mpi-io-test
mpi-io-test: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=9893e599e7a560159ccf547b4c4ba5671f65ba32, not stripped
----
* Ensure that the linker is correctly linking in Darshan's runtime libraries:
** A common mistake is to explicitly link in the underlying MPI libraries (e.g., `-lmpich` or `-lmpichf90`)
in the link command, which can interfere with Darshan's instrumentation
*** These libraries are usually linked in automatically by the compiler
*** MPICH's `mpicc` comipler's `-show` flag can be used to examine the invoked link command, for instance
** The linker's `-y` option can be used to verify that Darshan is properly intercepting MPI_Init
function (e.g. by setting `CFLAGS='-Wl,-yMPI_Init'`), which it uses to initialize its runtime structures
----
/usr/common/software/darshan/3.0.0-pre3/lib/libdarshan.a(darshan-core-init-finalize.o): definition of MPI_Init
----
......@@ -137,6 +137,7 @@ DARSHAN_FORWARD_DECL(PMPI_Gather, int, (const void *sendbuf, int sendcount, MPI_
#else
DARSHAN_FORWARD_DECL(PMPI_Gather, int, (void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm));
#endif
DARSHAN_FORWARD_DECL(PMPI_Barrier, int, (MPI_Comm comm));
void resolve_mpi_symbols (void)
{
......@@ -197,6 +198,7 @@ void resolve_mpi_symbols (void)
MAP_OR_FAIL(PMPI_Send);
MAP_OR_FAIL(PMPI_Recv);
MAP_OR_FAIL(PMPI_Gather);
MAP_OR_FAIL(PMPI_Barrier);
return;
}
......
......@@ -52,6 +52,7 @@ char* darshan_path_exclusions[] = {
"/sbin/",
"/sys/",
"/proc/",
"/var/",
NULL
};
......@@ -261,12 +262,12 @@ void darshan_core_shutdown()
darshan_record_id *mod_shared_recs;
int shared_rec_cnt = 0;
double start_log_time;
double open1, open2;
double job1, job2;
double rec1, rec2;
double open1 = 0, open2 = 0;
double job1 = 0, job2 = 0;
double rec1 = 0, rec2 = 0;
double mod1[DARSHAN_MAX_MODS] = {0};
double mod2[DARSHAN_MAX_MODS] = {0};
double header1, header2;
double header1 = 0, header2 = 0;
double tm_end;
uint64_t gz_fp = 0;
MPI_File log_fh;
......
......@@ -117,7 +117,8 @@ hid_t DARSHAN_DECL(H5Fcreate)(const char *filename, unsigned flags,
file = hdf5_file_by_name_sethid(filename, ret);
if(file)
{
if(file->file_record->fcounters[HDF5_F_OPEN_TIMESTAMP] == 0)
if(file->file_record->fcounters[HDF5_F_OPEN_TIMESTAMP] == 0 ||
file->file_record->fcounters[HDF5_F_OPEN_TIMESTAMP] > tm1)
file->file_record->fcounters[HDF5_F_OPEN_TIMESTAMP] = tm1;
file->file_record->counters[HDF5_OPENS] += 1;
}
......@@ -156,7 +157,8 @@ hid_t DARSHAN_DECL(H5Fopen)(const char *filename, unsigned flags,
file = hdf5_file_by_name_sethid(filename, ret);
if(file)
{
if(file->file_record->fcounters[HDF5_F_OPEN_TIMESTAMP] == 0)
if(file->file_record->fcounters[HDF5_F_OPEN_TIMESTAMP] == 0 ||
file->file_record->fcounters[HDF5_F_OPEN_TIMESTAMP] > tm1)
file->file_record->fcounters[HDF5_F_OPEN_TIMESTAMP] = tm1;
file->file_record->counters[HDF5_OPENS] += 1;
}
......
......@@ -153,7 +153,8 @@ static void mpiio_shutdown(void);
file->file_record->counters[MPIIO_COLL_OPENS] += 1; \
if(__info != MPI_INFO_NULL) \
file->file_record->counters[MPIIO_HINTS] += 1; \
if(file->file_record->fcounters[MPIIO_F_OPEN_TIMESTAMP] == 0) \
if(file->file_record->fcounters[MPIIO_F_OPEN_TIMESTAMP] == 0 || \
file->file_record->fcounters[MPIIO_F_OPEN_TIMESTAMP] > __tm1) \
file->file_record->fcounters[MPIIO_F_OPEN_TIMESTAMP] = __tm1; \
DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[MPIIO_F_META_TIME], __tm1, __tm2, file->last_meta_end); \
} while(0)
......@@ -174,7 +175,8 @@ static void mpiio_shutdown(void);
if(file->last_io_type == DARSHAN_IO_WRITE) \
file->file_record->counters[MPIIO_RW_SWITCHES] += 1; \
file->last_io_type = DARSHAN_IO_READ; \
if(file->file_record->fcounters[MPIIO_F_READ_START_TIMESTAMP] == 0) \
if(file->file_record->fcounters[MPIIO_F_READ_START_TIMESTAMP] == 0 || \
file->file_record->fcounters[MPIIO_F_READ_START_TIMESTAMP] > __tm1) \
file->file_record->fcounters[MPIIO_F_READ_START_TIMESTAMP] = __tm1; \
file->file_record->fcounters[MPIIO_F_READ_END_TIMESTAMP] = __tm2; \
if(file->file_record->fcounters[MPIIO_F_MAX_READ_TIME] < __elapsed) { \
......@@ -199,7 +201,8 @@ static void mpiio_shutdown(void);
if(file->last_io_type == DARSHAN_IO_READ) \
file->file_record->counters[MPIIO_RW_SWITCHES] += 1; \
file->last_io_type = DARSHAN_IO_WRITE; \
if(file->file_record->fcounters[MPIIO_F_WRITE_START_TIMESTAMP] == 0) \
if(file->file_record->fcounters[MPIIO_F_READ_START_TIMESTAMP] == 0 || \
file->file_record->fcounters[MPIIO_F_READ_START_TIMESTAMP] > __tm1) \
file->file_record->fcounters[MPIIO_F_WRITE_START_TIMESTAMP] = __tm1; \
file->file_record->fcounters[MPIIO_F_WRITE_END_TIMESTAMP] = __tm2; \
if(file->file_record->fcounters[MPIIO_F_MAX_WRITE_TIME] < __elapsed) { \
......
......@@ -114,7 +114,8 @@ int DARSHAN_DECL(ncmpi_create)(MPI_Comm comm, const char *path,
file = pnetcdf_file_by_name_setncid(path, (*ncidp));
if(file)
{
if(file->file_record->fcounters[PNETCDF_F_OPEN_TIMESTAMP] == 0)
if(file->file_record->fcounters[PNETCDF_F_OPEN_TIMESTAMP] == 0 ||
file->file_record->fcounters[PNETCDF_F_OPEN_TIMESTAMP] > tm1)
file->file_record->fcounters[PNETCDF_F_OPEN_TIMESTAMP] = tm1;
DARSHAN_MPI_CALL(PMPI_Comm_size)(comm, &comm_size);
if(comm_size == 1)
......@@ -162,7 +163,8 @@ int DARSHAN_DECL(ncmpi_open)(MPI_Comm comm, const char *path,
file = pnetcdf_file_by_name_setncid(path, (*ncidp));
if(file)
{
if(file->file_record->fcounters[PNETCDF_F_OPEN_TIMESTAMP] == 0)
if(file->file_record->fcounters[PNETCDF_F_OPEN_TIMESTAMP] == 0 ||
file->file_record->fcounters[PNETCDF_F_OPEN_TIMESTAMP] > tm1)
file->file_record->fcounters[PNETCDF_F_OPEN_TIMESTAMP] = tm1;
DARSHAN_MPI_CALL(PMPI_Comm_size)(comm, &comm_size);
if(comm_size == 1)
......
......@@ -231,7 +231,8 @@ static void posix_shutdown(void);
file->file_record->counters[POSIX_FOPENS] += 1; \
else \
file->file_record->counters[POSIX_OPENS] += 1; \
if(file->file_record->fcounters[POSIX_F_OPEN_TIMESTAMP] == 0) \
if(file->file_record->fcounters[POSIX_F_OPEN_TIMESTAMP] == 0 || \
file->file_record->fcounters[POSIX_F_OPEN_TIMESTAMP] > __tm1) \
file->file_record->fcounters[POSIX_F_OPEN_TIMESTAMP] = __tm1; \
DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[POSIX_F_META_TIME], __tm1, __tm2, file->last_meta_end); \
} while(0)
......@@ -278,7 +279,8 @@ static void posix_shutdown(void);
if(file->last_io_type == DARSHAN_IO_WRITE) \
file->file_record->counters[POSIX_RW_SWITCHES] += 1; \
file->last_io_type = DARSHAN_IO_READ; \
if(file->file_record->fcounters[POSIX_F_READ_START_TIMESTAMP] == 0) \
if(file->file_record->fcounters[POSIX_F_READ_START_TIMESTAMP] == 0 || \
file->file_record->fcounters[POSIX_F_READ_START_TIMESTAMP] > __tm1) \
file->file_record->fcounters[POSIX_F_READ_START_TIMESTAMP] = __tm1; \
file->file_record->fcounters[POSIX_F_READ_END_TIMESTAMP] = __tm2; \
if(file->file_record->fcounters[POSIX_F_MAX_READ_TIME] < __elapsed) { \
......@@ -329,7 +331,8 @@ static void posix_shutdown(void);
if(file->last_io_type == DARSHAN_IO_READ) \
file->file_record->counters[POSIX_RW_SWITCHES] += 1; \
file->last_io_type = DARSHAN_IO_WRITE; \
if(file->file_record->fcounters[POSIX_F_WRITE_START_TIMESTAMP] == 0) \
if(file->file_record->fcounters[POSIX_F_WRITE_START_TIMESTAMP] == 0 || \
file->file_record->fcounters[POSIX_F_WRITE_START_TIMESTAMP] > __tm1) \
file->file_record->fcounters[POSIX_F_WRITE_START_TIMESTAMP] = __tm1; \
file->file_record->fcounters[POSIX_F_WRITE_END_TIMESTAMP] = __tm2; \
if(file->file_record->fcounters[POSIX_F_MAX_WRITE_TIME] < __elapsed) { \
......
#!/bin/bash
# submit job and get job id
jobid=`qsub --env DARSHAN_LOGFILE=$DARSHAN_LOGFILE --mode c16 --proccount $DARSHAN_DEFAULT_NPROCS -A SSSPPg -t 10 -n 1 --output $DARSHAN_TMP/$$-tmp.out --error $DARSHAN_TMP/$$-tmp.err --debuglog $DARSHAN_TMP/$$-tmp.debuglog "$@"`
jobid=`qsub --env DARSHAN_LOGFILE=$DARSHAN_LOGFILE --mode c16 --proccount $DARSHAN_DEFAULT_NPROCS -A radix-io -t 10 -n 1 --output $DARSHAN_TMP/$$-tmp.out --error $DARSHAN_TMP/$$-tmp.err --debuglog $DARSHAN_TMP/$$-tmp.debuglog "$@"`
if [ $? -ne 0 ]; then
echo "Error: failed to qsub $@"
exit 1
......
......@@ -45,6 +45,17 @@ fi
# set up environment for tests according to platform
source $DARSHAN_TESTDIR/$DARSHAN_PLATFORM/env.sh
# in case of using LD_PRELOAD, it is possible errors with Darshan symbols
# (e..g, forgetting to resolve a symbol Darshan wraps using dlsym) can
# cause arbitrary binaries to crash. We check the output of the true
# command to successfully identify failures like this and exit
true_out=`/bin/true 2>&1`
if [ $? -ne 0 -o -n "$true_out" ]; then
echo -n $true_out > tmp
echo "environment setup failed"
exit 1
fi
failure_count=0
for i in `ls $DARSHAN_TESTDIR/test-cases/*.sh`; do
......
......@@ -3,7 +3,7 @@
PROG=cxxpi
# set log file path; remove previous log if present
export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan.gz
export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan
rm -f ${DARSHAN_LOGFILE}
# compile
......
......@@ -3,7 +3,7 @@
PROG=fperf-f77
# set log file path; remove previous log if present
export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan.gz
export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan
rm -f ${DARSHAN_LOGFILE}
# compile
......
......@@ -3,7 +3,7 @@
PROG=fperf-f90
# set log file path; remove previous log if present
export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan.gz
export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan
rm -f ${DARSHAN_LOGFILE}
# compile
......
......@@ -3,7 +3,7 @@
PROG=mpi-io-test
# set log file path; remove previous log if present
export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan.gz
export DARSHAN_LOGFILE=$DARSHAN_TMP/${PROG}.darshan
rm -f ${DARSHAN_LOGFILE}
# compile
......
......@@ -137,6 +137,7 @@ endif
install -m 644 $(srcdir)/darshan-pnetcdf-logutils.h $(includedir)
install -m 644 $(srcdir)/darshan-bgq-logutils.h $(includedir)
install -m 644 $(srcdir)/darshan-null-logutils.h $(includedir)
install -m 644 $(srcdir)/../darshan-null-log-format.h $(includedir)
install -m 644 $(srcdir)/../darshan-posix-log-format.h $(includedir)
install -m 644 $(srcdir)/../darshan-mpiio-log-format.h $(includedir)
install -m 644 $(srcdir)/../darshan-hdf5-log-format.h $(includedir)
......@@ -158,7 +159,7 @@ endif
clean::
rm -f *.o *.po *.a darshan-analyzer darshan-convert darshan-parser jenkins-hash-gen
rm -f *.o *.po *.a darshan-analyzer darshan-convert darshan-diff darshan-parser jenkins-hash-gen
distclean:: clean
rm -f darshan-runtime-config.h aclocal.m4 autom4te.cache/* config.status config.log Makefile util/bin/darshan-job-summary.pl
......
......@@ -3538,7 +3538,7 @@ then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
BZLIB_OLD_LDFLAGS=$LDFLAGS
BZLIB_OLD_CPPFLAGS=$LDFLAGS
BZLIB_OLD_CPPFLAGS=$CPPFLAGS
LDFLAGS="$LDFLAGS -L${BZLIB_HOME}/lib"
CPPFLAGS="$CPPFLAGS -I${BZLIB_HOME}/include"
......
#!/usr/bin/perl -w
#!/usr/bin/env perl
#
# Copyright (C) 2015 University of Chicago.
......@@ -19,6 +19,8 @@
# jobid2 key1=val1 key2=val2
#
use warnings;
my $darshan_convert = "./darshan-convert";
my $jenkins_hash_gen = "./jenkins-hash-gen";
......
......@@ -230,8 +230,7 @@ int main(int argc, char **argv)
darshan_fd outfile;
int i;
int mount_count;
char** mnt_pts;
char** fs_types;
struct darshan_mnt_info *mnt_data_array;
struct darshan_record_ref *rec_hash = NULL;
struct darshan_record_ref *ref, *tmp;
char mod_buf[DEF_MOD_BUF_SIZE];
......@@ -299,7 +298,7 @@ int main(int argc, char **argv)
return(-1);
}
ret = darshan_log_getmounts(infile, &mnt_pts, &fs_types, &mount_count);
ret = darshan_log_getmounts(infile, &mnt_data_array, &mount_count);
if(ret < 0)
{
darshan_log_close(infile);
......@@ -308,7 +307,7 @@ int main(int argc, char **argv)
return(-1);
}
ret = darshan_log_putmounts(outfile, mnt_pts, fs_types, mount_count);
ret = darshan_log_putmounts(outfile, mnt_data_array, mount_count);
if(ret < 0)
{
darshan_log_close(infile);
......@@ -389,16 +388,8 @@ int main(int argc, char **argv)
darshan_log_close(infile);
darshan_log_close(outfile);
for(i=0; i<mount_count; i++)
{
free(mnt_pts[i]);
free(fs_types[i]);
}
if(mount_count > 0)
{
free(mnt_pts);
free(fs_types);
}
free(mnt_data_array);
HASH_ITER(hlink, rec_hash, ref, tmp)
{
......
#!/usr/bin/perl -w
#!/usr/bin/env perl
#
# (C) 2015 by Argonne National Laboratory.
# See COPYRIGHT in top-level directory.
......@@ -7,6 +7,7 @@
# Set via configure
my $PREFIX="@prefix@";
use warnings;
use lib "@prefix@/lib";
use TeX::Encode;
use Encode;
......
......@@ -66,6 +66,7 @@ struct darshan_fd_int_state
struct darshan_dz_state dz;
};
static int darshan_mnt_info_cmp(const void *a, const void *b);
static int darshan_log_getheader(darshan_fd fd);
static int darshan_log_putheader(darshan_fd fd);
static int darshan_log_seek(darshan_fd fd, off_t offset);
......@@ -374,14 +375,14 @@ int darshan_log_putexe(darshan_fd fd, char *buf)
/* darshan_log_getmounts()
*
* retrieves mount table information from the log. Note that mnt_pts and
* fs_types are arrays that will be allocated by the function and must be
* freed by the caller. count will indicate the size of the arrays
* retrieves mount table information from the log. Note that mnt_data_array
* is an array that will be allocated by the function and must be
* freed by the caller. count will indicate the size of the array
*
* returns 0 on success, -1 on failure
*/
int darshan_log_getmounts(darshan_fd fd, char*** mnt_pts,
char*** fs_types, int* count)
int darshan_log_getmounts(darshan_fd fd, struct darshan_mnt_info **mnt_data_array,
int* count)
{
struct darshan_fd_int_state *state = fd->state;
char *pos;
......@@ -416,34 +417,27 @@ int darshan_log_getmounts(darshan_fd fd, char*** mnt_pts,
}
/* allocate output arrays */
*mnt_pts = malloc((*count)*sizeof(char*));
assert(*mnt_pts);
*fs_types = malloc((*count)*sizeof(char*));
assert(*fs_types);
*mnt_data_array = malloc((*count)*sizeof(**mnt_data_array));
assert(*mnt_data_array);
/* work backwards through the table and parse each line (except for
/* work through the table and parse each line (except for
* first, which holds command line information)
*/
while((pos = strrchr(state->exe_mnt_data, '\n')) != NULL)
pos = state->exe_mnt_data;
while((pos = strchr(pos, '\n')) != NULL)
{
/* overestimate string lengths */
(*mnt_pts)[array_index] = malloc(DARSHAN_EXE_LEN);
assert((*mnt_pts)[array_index]);
(*fs_types)[array_index] = malloc(DARSHAN_EXE_LEN);
assert((*fs_types)[array_index]);
ret = sscanf(++pos, "%s\t%s", (*fs_types)[array_index],
(*mnt_pts)[array_index]);
ret = sscanf(++pos, "%s\t%s", (*mnt_data_array)[array_index].mnt_type,
(*mnt_data_array)[array_index].mnt_path);
if(ret != 2)
{
fprintf(stderr, "Error: poorly formatted mount table in darshan log file.\n");
return(-1);
}
pos--;
*pos = '\0';
array_index++;
}
qsort(*mnt_data_array, *count, sizeof(**mnt_data_array), darshan_mnt_info_cmp);
return(0);
}
......@@ -456,7 +450,8 @@ int darshan_log_getmounts(darshan_fd fd, char*** mnt_pts,
*
* returns 0 on success, -1 on failure
*/
int darshan_log_putmounts(darshan_fd fd, char** mnt_pts, char** fs_types, int count)
int darshan_log_putmounts(darshan_fd fd, struct darshan_mnt_info *mnt_data_array,
int count)
{
struct darshan_fd_int_state *state = fd->state;
int i;
......@@ -472,7 +467,7 @@ int darshan_log_putmounts(darshan_fd fd, char** mnt_pts, char** fs_types, int co
tmp = mnt_dat;
for(i=count-1; i>=0; i--)
{
sprintf(line, "\n%s\t%s", fs_types[i], mnt_pts[i]);
sprintf(line, "\n%s\t%s", mnt_data_array[i].mnt_type, mnt_data_array[i].mnt_path);
memcpy(tmp, line, strlen(line));
tmp += strlen(line);
......@@ -827,6 +822,19 @@ void darshan_log_close(darshan_fd fd)
/* **************************************************** */
static int darshan_mnt_info_cmp(const void *a, const void *b)
{
struct darshan_mnt_info *m_a = (struct darshan_mnt_info *)a;
struct darshan_mnt_info *m_b = (struct darshan_mnt_info *)b;
if(strlen(m_a->mnt_path) > strlen(m_b->mnt_path))
return(-1);
else if(strlen(m_a->mnt_path) < strlen(m_b->mnt_path))
return(1);
else
return(0);
}
/* read the header of the darshan log and set internal fd data structures
* NOTE: this is the only portion of the darshan log that is uncompressed
*
......
......@@ -7,7 +7,7 @@
#ifndef __DARSHAN_LOG_UTILS_H
#define __DARSHAN_LOG_UTILS_H
#include <linux/limits.h>
#include <limits.h>
#include <zlib.h>
#ifdef HAVE_LIBBZ2
#include <bzlib.h>
......@@ -47,6 +47,12 @@ struct darshan_record_ref
UT_hash_handle hlink;
};
struct darshan_mnt_info
{
char mnt_type[DARSHAN_EXE_LEN];
char mnt_path[DARSHAN_EXE_LEN];
};
/* functions to be implemented by each module for integration with
* darshan log file utilities (e.g., parser & convert tools)
*/
......@@ -116,10 +122,10 @@ int darshan_log_getjob(darshan_fd fd, struct darshan_job *job);
int darshan_log_putjob(darshan_fd fd, struct darshan_job *job);
int darshan_log_getexe(darshan_fd fd, char *buf);
int darshan_log_putexe(darshan_fd fd, char *buf);
int darshan_log_getmounts(darshan_fd fd, char*** mnt_pts,
char*** fs_types, int* count);
int darshan_log_putmounts(darshan_fd fd, char** mnt_pts,
char** fs_types, int count);
int darshan_log_getmounts(darshan_fd fd, struct darshan_mnt_info **mnt_data_array,
int* count);
int darshan_log_putmounts(darshan_fd fd, struct darshan_mnt_info *mnt_data_array,
int count);
int darshan_log_gethash(darshan_fd fd, struct darshan_record_ref **hash);
int darshan_log_puthash(darshan_fd fd, struct darshan_record_ref *hash);
int darshan_log_getmod(darshan_fd fd, darshan_module_id mod_id,
......
......@@ -205,8 +205,7 @@ int main(int argc, char **argv)
struct darshan_record_ref *rec_hash = NULL;
struct darshan_record_ref *ref, *tmp_ref;
int mount_count;
char** mnt_pts;
char** fs_types;
struct darshan_mnt_info *mnt_data_array;
time_t tmp_time = 0;
char *token;
char *save;
......@@ -248,7 +247,7 @@ int main(int argc, char **argv)
}
/* get the mount information for this log */
ret = darshan_log_getmounts(fd, &mnt_pts, &fs_types, &mount_count);
ret = darshan_log_getmounts(fd, &mnt_data_array, &mount_count);
if(ret < 0)
{
darshan_log_close(fd);
......@@ -318,7 +317,8 @@ int main(int argc, char **argv)
printf("# -------------------------------------------------------\n");
for(i=0; i<mount_count; i++)
{
printf("# mount entry:\t%s\t%s\n", mnt_pts[i], fs_types[i]);
printf("# mount entry:\t%s\t%s\n", mnt_data_array[i].mnt_path,
mnt_data_array[i].mnt_type);
}
if(mask & OPTION_BASE)
......@@ -417,10 +417,11 @@ int main(int argc, char **argv)
/* get mount point and fs type associated with this record */
for(j=0; j<mount_count; j++)
{
if(strncmp(mnt_pts[j], ref->rec.name, strlen(mnt_pts[j])) == 0)
if(strncmp(mnt_data_array[j].mnt_path, ref->rec.name,
strlen(mnt_data_array[j].mnt_path)) == 0)
{
mnt_pt = mnt_pts[j];
fs_type = fs_types[j];
mnt_pt = mnt_data_array[j].mnt_path;
fs_type = mnt_data_array[j].mnt_type;
break;
}
}
......@@ -557,7 +558,7 @@ int main(int argc, char **argv)
printf("# I/O timing for unique files (seconds):\n");
printf("# ...........................\n");
printf("# unique files: slowest_rank_io_time: %lf\n", pdata.slowest_rank_time);
printf("# unique files: slowest_rank_meta_time: %lf\n", pdata.slowest_rank_meta_time);
printf("# unique files: slowest_rank_meta_only_time: %lf\n", pdata.slowest_rank_meta_time);
printf("# unique files: slowest rank: %d\n", pdata.slowest_rank_rank);
printf("#\n");
printf("# I/O timing for shared files (seconds):\n");
......@@ -633,15 +634,9 @@ cleanup:
}
/* free mount info */
for(i=0; i<mount_count; i++)
{
free(mnt_pts[i]);
free(fs_types[i]);
}
if(mount_count > 0)
{
free(mnt_pts);
free(fs_types);
free(mnt_data_array);
}
return(ret);
......@@ -1355,7 +1350,6 @@ void calc_perf(perf_data_t *pdata,
if (pdata->slowest_rank_time + pdata->shared_time_by_slowest)
pdata->agg_perf_by_slowest = ((double)pdata->total_bytes / 1048576.0) /
(pdata->slowest_rank_time +
pdata->slowest_rank_meta_time +
pdata->shared_time_by_slowest);
return;
......
......@@ -394,7 +394,7 @@ Job performance information can be generated using the `--perf` command-line opt
# I/O timing for unique files (seconds):
# ...........................
# unique files: slowest_rank_io_time: 0.000000
# unique files: slowest_rank_meta_time: 0.000000
# unique files: slowest_rank_meta_only_time: 0.000000
# unique files: slowest_rank: 0
#
# I/O timing for shared files (seconds):
......@@ -430,7 +430,7 @@ type of file access.
* unique files: slowest_rank_io_time: total I/O time for unique files
(including both metadata + data transfer time)
* unique files: slowest_rank_meta_time: metadata time for unique files
* unique files: slowest_rank_meta_only_time: metadata time for unique files
* unique files: slowest_rank: the rank of the slowest process
.I/O timing for shared files