Commit db79f903 authored by Cong Xu's avatar Cong Xu

Check in Darshan eXtended Lustre Tracing(DXLT) code

1. Use Lustre Module in Darshan
2. Integrate DXLT IO tracing code into one module
3. Add hooks in POSIX and MPI Modules
4. Add Intel copyright
Signed-off-by: Cong Xu's avatarCong Xu <cong.xu@intel.com>
parent 0bf9973e
/*
* Copyright (C) 2016 Intel Corporation.
* See COPYRIGHT in top-level directory.
*/
#ifndef __DARSHAN_DXLT_LOG_FORMAT_H
#define __DARSHAN_DXLT_LOG_FORMAT_H
/* current DXLT log format version */
#define DXLT_POSIX_VER 1
#define DXLT_MPIIO_VER 1
/*
* DXLT, the segment_info structure maintains detailed Segment IO tracing
* information
*/
typedef struct segment_info {
int64_t offset;
int64_t length;
double start_time;
double end_time;
} segment_info;
#define X(a) a,
#undef X
/* file record structure for DXLT files. a record is created and stored for
* every DXLT file opened by the original application. For the DXLT module,
* the record includes:
* - a darshan_base_record structure, which contains the record id & rank
* - integer file I/O statistics (open, read/write counts, etc)
* - floating point I/O statistics (timestamps, cumulative timers, etc.)
*/
struct dxlt_file_record {
struct darshan_base_record base_rec;
int64_t shared_record; /* -1 means it is a shared file record */
int32_t stripe_size;
int32_t stripe_count;
OST_ID *ost_ids;
int64_t write_count;
int64_t write_available_buf;
segment_info *write_traces;
int64_t read_count;
int64_t read_available_buf;
segment_info *read_traces;
};
#endif /* __DARSHAN_DXLT_LOG_FORMAT_H */
...@@ -117,6 +117,8 @@ struct darshan_base_record ...@@ -117,6 +117,8 @@ struct darshan_base_record
#include "darshan-bgq-log-format.h" #include "darshan-bgq-log-format.h"
#include "darshan-lustre-log-format.h" #include "darshan-lustre-log-format.h"
#include "darshan-stdio-log-format.h" #include "darshan-stdio-log-format.h"
/* DXLT */
#include "darshan-dxlt-log-format.h"
/* X-macro for keeping module ordering consistent */ /* X-macro for keeping module ordering consistent */
/* NOTE: first val used to define module enum values, /* NOTE: first val used to define module enum values,
...@@ -136,7 +138,10 @@ struct darshan_base_record ...@@ -136,7 +138,10 @@ struct darshan_base_record
X(DARSHAN_PNETCDF_MOD, "PNETCDF", DARSHAN_PNETCDF_VER, &pnetcdf_logutils) \ X(DARSHAN_PNETCDF_MOD, "PNETCDF", DARSHAN_PNETCDF_VER, &pnetcdf_logutils) \
X(DARSHAN_BGQ_MOD, "BG/Q", DARSHAN_BGQ_VER, &bgq_logutils) \ X(DARSHAN_BGQ_MOD, "BG/Q", DARSHAN_BGQ_VER, &bgq_logutils) \
X(DARSHAN_LUSTRE_MOD, "LUSTRE", DARSHAN_LUSTRE_VER, &lustre_logutils) \ X(DARSHAN_LUSTRE_MOD, "LUSTRE", DARSHAN_LUSTRE_VER, &lustre_logutils) \
X(DARSHAN_STDIO_MOD, "STDIO", DARSHAN_STDIO_VER, &stdio_logutils) X(DARSHAN_STDIO_MOD, "STDIO", DARSHAN_STDIO_VER, &stdio_logutils) \
/* DXLT */ \
X(DXLT_POSIX_MOD, "X_POSIX", DXLT_POSIX_VER, &dxlt_posix_logutils) \
X(DXLT_MPIIO_MOD, "X_MPIIO", DXLT_MPIIO_VER, &dxlt_mpiio_logutils)
/* unique identifiers to distinguish between available darshan modules */ /* unique identifiers to distinguish between available darshan modules */
/* NOTES: - valid ids range from [0...DARSHAN_MAX_MODS-1] /* NOTES: - valid ids range from [0...DARSHAN_MAX_MODS-1]
......
...@@ -35,8 +35,8 @@ CFLAGS_SHARED = -DDARSHAN_CONFIG_H=\"darshan-runtime-config.h\" -I . -I$(srcdir) ...@@ -35,8 +35,8 @@ CFLAGS_SHARED = -DDARSHAN_CONFIG_H=\"darshan-runtime-config.h\" -I . -I$(srcdir)
LIBS = -lz @LIBBZ2@ LIBS = -lz @LIBBZ2@
DARSHAN_STATIC_MOD_OBJS = lib/darshan-posix.o lib/darshan-mpiio.o lib/darshan-hdf5.o lib/darshan-pnetcdf.o lib/darshan-stdio.o DARSHAN_STATIC_MOD_OBJS = lib/darshan-posix.o lib/darshan-mpiio.o lib/darshan-hdf5.o lib/darshan-pnetcdf.o lib/darshan-stdio.o lib/darshan-dxlt.o
DARSHAN_DYNAMIC_MOD_OBJS = lib/darshan-posix.po lib/darshan-mpiio.po lib/darshan-hdf5.po lib/darshan-pnetcdf.po lib/darshan-stdio.po DARSHAN_DYNAMIC_MOD_OBJS = lib/darshan-posix.po lib/darshan-mpiio.po lib/darshan-hdf5.po lib/darshan-pnetcdf.po lib/darshan-stdio.po lib/darshan-dxlt.po
ifdef DARSHAN_USE_BGQ ifdef DARSHAN_USE_BGQ
DARSHAN_STATIC_MOD_OBJS += lib/darshan-bgq.o DARSHAN_STATIC_MOD_OBJS += lib/darshan-bgq.o
...@@ -127,6 +127,12 @@ lib/darshan-stdio.o: lib/darshan-stdio.c darshan.h darshan-common.h $(DARSHAN_LO ...@@ -127,6 +127,12 @@ lib/darshan-stdio.o: lib/darshan-stdio.c darshan.h darshan-common.h $(DARSHAN_LO
lib/darshan-stdio.po: lib/darshan-stdio.c darshan.h darshan-dynamic.h darshan-common.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-stdio-log-format.h | lib lib/darshan-stdio.po: lib/darshan-stdio.c darshan.h darshan-dynamic.h darshan-common.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-stdio-log-format.h | lib
$(CC) $(CFLAGS_SHARED) -c $< -o $@ $(CC) $(CFLAGS_SHARED) -c $< -o $@
lib/darshan-dxlt.o: lib/darshan-dxlt.c darshan.h darshan-common.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-dxlt-log-format.h | lib
$(CC) $(CFLAGS) -c $< -o $@
lib/darshan-dxlt.po: lib/darshan-dxlt.c darshan.h darshan-dynamic.h darshan-common.h $(DARSHAN_LOG_FORMAT) $(srcdir)/../darshan-dxlt-log-format.h | lib
$(CC) $(CFLAGS_SHARED) -c $< -o $@
lib/lookup3.o: lib/lookup3.c lib/lookup3.o: lib/lookup3.c
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
......
...@@ -38,11 +38,12 @@ ...@@ -38,11 +38,12 @@
#define DARSHAN_DEF_MMAP_LOG_PATH "/tmp" #define DARSHAN_DEF_MMAP_LOG_PATH "/tmp"
#endif #endif
/* DXLT */
/* Maximum amount of memory per instrumentation module in MiB */ /* Maximum amount of memory per instrumentation module in MiB */
#ifdef __DARSHAN_MOD_MEM_MAX #ifdef __DARSHAN_MOD_MEM_MAX
#define DARSHAN_MOD_MEM_MAX (__DARSHAN_MOD_MEM_MAX * 1024 * 1024) #define DARSHAN_MOD_MEM_MAX (__DARSHAN_MOD_MEM_MAX * 1024 * 1024)
#else #else
#define DARSHAN_MOD_MEM_MAX (2 * 1024 * 1024) /* 2 MiB default */ #define DARSHAN_MOD_MEM_MAX (4 * 1024 * 1024) /* 4 MiB default */
#endif #endif
/* default name record buf can store 2048 records of size 100 bytes */ /* default name record buf can store 2048 records of size 100 bytes */
......
/*
* Copyright (C) 2016 Intel Corporation.
* See COPYRIGHT notice in top-level directory.
*
*/
#define _XOPEN_SOURCE 500
#define _GNU_SOURCE
#include "darshan-runtime-config.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <search.h>
#include <assert.h>
#include <libgen.h>
#include <pthread.h>
#include "utlist.h"
#include "uthash.h"
#include "darshan.h"
#include "darshan-dynamic.h"
#ifndef HAVE_OFF64_T
typedef int64_t off64_t;
#endif
#ifdef DARSHAN_LUSTRE
#include <lustre/lustre_user.h>
#endif
#define IO_TRACE_BUF_SIZE 1024
struct dxlt_record_ref_tracker
{
void *rec_ref_p;
UT_hash_handle hlink;
};
/* The dxlt_file_record_ref structure maintains necessary runtime metadata
* for the DXLT file record (dxlt_file_record structure, defined in
* darshan-dxlt-log-format.h) pointed to by 'file_rec'. This metadata
* assists with the instrumenting of specific statistics in the file record.
*
* NOTE: we use the 'darshan_record_ref' interface (in darshan-common) to
* associate different types of handles with this dxlt_file_record_ref struct.
* This allows us to index this struct (and the underlying file record) by using
* either the corresponding Darshan record identifier (derived from the filename)
* or by a generated file descriptor, for instance. Note that, while there should
* only be a single Darshan record identifier that indexes a dxlt_file_record_ref,
* there could be multiple open file descriptors that index it.
*/
struct dxlt_file_record_ref
{
struct dxlt_file_record *file_rec;
int fs_type; /* same as darshan_fs_info->fs_type */
};
/* The dxlt_runtime structure maintains necessary state for storing
* DXLT file records and for coordinating with darshan-core at
* shutdown time.
*/
struct dxlt_posix_runtime
{
void *rec_id_hash;
void *fd_hash;
int file_rec_count;
};
struct dxlt_mpiio_runtime
{
void *rec_id_hash;
void *fh_hash;
int file_rec_count;
};
void dxlt_posix_runtime_initialize(
void);
void dxlt_mpiio_runtime_initialize(
void);
void dxlt_posix_track_new_file_record(
darshan_record_id rec_id, const char *path);
void dxlt_mpiio_track_new_file_record(
darshan_record_id rec_id, const char *path);
void dxlt_posix_add_record_ref(darshan_record_id rec_id, int fd);
void dxlt_mpiio_add_record_ref(darshan_record_id rec_id, MPI_File fh);
static void dxlt_instrument_fs_data(
darshan_record_id rec_id, int fs_type, struct dxlt_file_record *file_rec);
static void dxlt_posix_cleanup_runtime(
void);
static void dxlt_mpiio_cleanup_runtime(
void);
static void dxlt_posix_shutdown(
MPI_Comm mod_comm, darshan_record_id *shared_recs,
int shared_rec_count, void **dxlt_buf, int *dxlt_buf_sz);
static void dxlt_mpiio_shutdown(
MPI_Comm mod_comm, darshan_record_id *shared_recs,
int shared_rec_count, void **dxlt_buf, int *dxlt_buf_sz);
#ifdef DARSHAN_LUSTRE
/* XXX modules don't expose an API for other modules, so use extern to get
* Lustre instrumentation function
*/
extern void dxlt_get_lustre_stripe_info(
darshan_record_id rec_id, struct dxlt_file_record *file_rec);
#endif
static struct dxlt_posix_runtime *dxlt_posix_runtime = NULL;
static struct dxlt_mpiio_runtime *dxlt_mpiio_runtime = NULL;
static pthread_mutex_t dxlt_posix_runtime_mutex =
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static pthread_mutex_t dxlt_mpiio_runtime_mutex =
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static int posix_my_rank = -1;
static int mpiio_my_rank = -1;
static int instrumentation_disabled = 0;
static int darshan_mem_alignment = 1;
#define DXLT_POSIX_LOCK() pthread_mutex_lock(&dxlt_posix_runtime_mutex)
#define DXLT_POSIX_UNLOCK() pthread_mutex_unlock(&dxlt_posix_runtime_mutex)
#define DXLT_MPIIO_LOCK() pthread_mutex_lock(&dxlt_mpiio_runtime_mutex)
#define DXLT_MPIIO_UNLOCK() pthread_mutex_unlock(&dxlt_mpiio_runtime_mutex)
/**********************************************************
* Wrappers for DXLT I/O functions of interest *
**********************************************************/
void check_io_trace_buf(struct dxlt_file_record *file_rec)
{
int write_count = file_rec->write_count;
int write_available_buf = file_rec->write_available_buf;
if (write_count >= write_available_buf) {
write_available_buf += IO_TRACE_BUF_SIZE;
file_rec->write_traces =
(segment_info *)realloc(file_rec->write_traces,
write_available_buf * sizeof(segment_info));
file_rec->write_available_buf = write_available_buf;
}
int read_count = file_rec->read_count;
int read_available_buf = file_rec->read_available_buf;
if (read_count >= read_available_buf) {
read_available_buf += IO_TRACE_BUF_SIZE;
file_rec->read_traces =
(segment_info *)realloc(file_rec->read_traces,
read_available_buf * sizeof(segment_info));
file_rec->read_available_buf = read_available_buf;
}
}
void dxlt_posix_write(int fd, int64_t offset, int64_t length,
double start_time, double end_time)
{
struct dxlt_file_record_ref* rec_ref = NULL;
struct dxlt_file_record *file_rec;
rec_ref = darshan_lookup_record_ref(dxlt_posix_runtime->fd_hash,
&fd, sizeof(int));
if (!rec_ref) {
fprintf(stderr, "Error: dxlt_posix_write unable to find rec_ref.\n");
return;
}
file_rec = rec_ref->file_rec;
if (dxlt_posix_runtime) {
check_io_trace_buf(file_rec);
}
file_rec->write_traces[file_rec->write_count].offset = offset;
file_rec->write_traces[file_rec->write_count].length = length;
file_rec->write_traces[file_rec->write_count].start_time = start_time;
file_rec->write_traces[file_rec->write_count].end_time = end_time;
file_rec->write_count += 1;
}
void dxlt_posix_read(int fd, int64_t offset, int64_t length,
double start_time, double end_time)
{
struct dxlt_file_record_ref* rec_ref = NULL;
struct dxlt_file_record *file_rec;
rec_ref = darshan_lookup_record_ref(dxlt_posix_runtime->fd_hash,
&fd, sizeof(int));
if (!rec_ref) {
fprintf(stderr, "Error: dxlt_posix_read unable to find rec_ref.\n");
return;
}
file_rec = rec_ref->file_rec;
if (dxlt_posix_runtime) {
check_io_trace_buf(file_rec);
}
file_rec->read_traces[file_rec->read_count].offset = offset;
file_rec->read_traces[file_rec->read_count].length = length;
file_rec->read_traces[file_rec->read_count].start_time = start_time;
file_rec->read_traces[file_rec->read_count].end_time = end_time;
file_rec->read_count += 1;
}
void dxlt_mpiio_write(MPI_File fh, int64_t length,
double start_time, double end_time)
{
struct dxlt_file_record_ref* rec_ref = NULL;
struct dxlt_file_record *file_rec;
rec_ref = darshan_lookup_record_ref(dxlt_mpiio_runtime->fh_hash,
&fh, sizeof(MPI_File));
if (!rec_ref) {
fprintf(stderr, "Error: dxlt_mpiio_write unable to find rec_ref.\n");
return;
}
file_rec = rec_ref->file_rec;
if (dxlt_mpiio_runtime) {
check_io_trace_buf(file_rec);
}
file_rec->write_traces[file_rec->write_count].length = length;
file_rec->write_traces[file_rec->write_count].start_time = start_time;
file_rec->write_traces[file_rec->write_count].end_time = end_time;
file_rec->write_count += 1;
}
void dxlt_mpiio_read(MPI_File fh, int64_t length,
double start_time, double end_time)
{
struct dxlt_file_record_ref* rec_ref = NULL;
struct dxlt_file_record *file_rec;
rec_ref = darshan_lookup_record_ref(dxlt_mpiio_runtime->fh_hash,
&fh, sizeof(MPI_File));
if (!rec_ref) {
fprintf(stderr, "Error: dxlt_mpiio_read unable to find rec_ref.\n");
return;
}
file_rec = rec_ref->file_rec;
if (dxlt_mpiio_runtime) {
check_io_trace_buf(file_rec);
}
file_rec->read_traces[file_rec->read_count].length = length;
file_rec->read_traces[file_rec->read_count].start_time = start_time;
file_rec->read_traces[file_rec->read_count].end_time = end_time;
file_rec->read_count += 1;
}
/**********************************************************
* Internal functions for manipulating DXLT module state *
**********************************************************/
/* initialize internal DXLT module data structures and register with darshan-core */
void dxlt_posix_runtime_initialize()
{
int psx_buf_size;
/* try and store a default number of records for this module */
psx_buf_size = DARSHAN_DEF_MOD_REC_COUNT * sizeof(struct dxlt_file_record);
/* register the DXLT module with darshan core */
darshan_core_register_module(
DXLT_POSIX_MOD,
&dxlt_posix_shutdown,
&psx_buf_size,
&posix_my_rank,
&darshan_mem_alignment);
/* return if darshan-core does not provide enough module memory */
if(psx_buf_size < sizeof(struct dxlt_file_record))
{
darshan_core_unregister_module(DXLT_POSIX_MOD);
return;
}
dxlt_posix_runtime = malloc(sizeof(*dxlt_posix_runtime));
if(!dxlt_posix_runtime)
{
darshan_core_unregister_module(DXLT_POSIX_MOD);
return;
}
memset(dxlt_posix_runtime, 0, sizeof(*dxlt_posix_runtime));
return;
}
void dxlt_mpiio_runtime_initialize()
{
int psx_buf_size;
/* try and store a default number of records for this module */
psx_buf_size = DARSHAN_DEF_MOD_REC_COUNT * sizeof(struct dxlt_file_record);
/* register the DXLT module with darshan core */
darshan_core_register_module(
DXLT_MPIIO_MOD,
&dxlt_mpiio_shutdown,
&psx_buf_size,
&mpiio_my_rank,
&darshan_mem_alignment);
/* return if darshan-core does not provide enough module memory */
if(psx_buf_size < sizeof(struct dxlt_file_record))
{
darshan_core_unregister_module(DXLT_MPIIO_MOD);
return;
}
dxlt_mpiio_runtime = malloc(sizeof(*dxlt_mpiio_runtime));
if(!dxlt_mpiio_runtime)
{
darshan_core_unregister_module(DXLT_MPIIO_MOD);
return;
}
memset(dxlt_mpiio_runtime, 0, sizeof(*dxlt_mpiio_runtime));
return;
}
void dxlt_posix_track_new_file_record(
darshan_record_id rec_id, const char *path)
{
struct dxlt_file_record_ref *rec_ref = NULL;
struct dxlt_file_record *file_rec = NULL;
struct darshan_fs_info fs_info;
int ret;
rec_ref = malloc(sizeof(*rec_ref));
if(!rec_ref)
return;
memset(rec_ref, 0, sizeof(*rec_ref));
/* add a reference to this file record based on record id */
ret = darshan_add_record_ref(&(dxlt_posix_runtime->rec_id_hash), &rec_id,
sizeof(darshan_record_id), rec_ref);
if(ret == 0)
{
free(rec_ref);
return;
}
/* register the actual file record with darshan-core so it is persisted
* in the log file
*/
file_rec = darshan_core_register_record(
rec_id,
path,
DXLT_POSIX_MOD,
sizeof(struct dxlt_file_record),
&fs_info);
if(!file_rec)
{
darshan_delete_record_ref(&(dxlt_posix_runtime->rec_id_hash),
&rec_id, sizeof(darshan_record_id));
free(rec_ref);
return;
}
/*
* Registering this file record was successful, so initialize
* some fields */
file_rec->base_rec.id = rec_id;
file_rec->base_rec.rank = posix_my_rank;
file_rec->write_count = 0;
file_rec->write_available_buf = IO_TRACE_BUF_SIZE;
file_rec->write_traces = malloc(IO_TRACE_BUF_SIZE *
sizeof(segment_info));
file_rec->read_count = 0;
file_rec->read_available_buf = IO_TRACE_BUF_SIZE;
file_rec->read_traces = malloc(IO_TRACE_BUF_SIZE *
sizeof(segment_info));
rec_ref->file_rec = file_rec;
rec_ref->fs_type = fs_info.fs_type;
dxlt_posix_runtime->file_rec_count++;
}
void dxlt_mpiio_track_new_file_record(
darshan_record_id rec_id, const char *path)
{
struct dxlt_file_record *file_rec = NULL;
struct dxlt_file_record_ref *rec_ref = NULL;
struct darshan_fs_info fs_info;
int ret;
rec_ref = malloc(sizeof(*rec_ref));
if(!rec_ref)
return;
memset(rec_ref, 0, sizeof(*rec_ref));
/* add a reference to this file record based on record id */
ret = darshan_add_record_ref(&(dxlt_mpiio_runtime->rec_id_hash), &rec_id,
sizeof(darshan_record_id), rec_ref);
if(ret == 0)
{
free(rec_ref);
return;
}
/* register the actual file record with darshan-core so it is persisted
* in the log file
*/
file_rec = darshan_core_register_record(
rec_id,
path,
DXLT_MPIIO_MOD,
sizeof(struct dxlt_file_record),
&fs_info);
if(!file_rec)
{
darshan_delete_record_ref(&(dxlt_mpiio_runtime->rec_id_hash),
&rec_id, sizeof(darshan_record_id));
free(rec_ref);
return;
}
/* registering this file record was successful, so initialize
* some fields
*/
file_rec->base_rec.id = rec_id;
file_rec->base_rec.rank = mpiio_my_rank;
file_rec->write_count = 0;
file_rec->write_available_buf = IO_TRACE_BUF_SIZE;
file_rec->write_traces = malloc(IO_TRACE_BUF_SIZE *
sizeof(segment_info));
file_rec->read_count = 0;
file_rec->read_available_buf = IO_TRACE_BUF_SIZE;
file_rec->read_traces = malloc(IO_TRACE_BUF_SIZE *
sizeof(segment_info));
rec_ref->file_rec = file_rec;
rec_ref->fs_type = fs_info.fs_type;
dxlt_mpiio_runtime->file_rec_count++;
}
void dxlt_posix_add_record_ref(darshan_record_id rec_id, int fd)
{
struct dxlt_file_record_ref *rec_ref = NULL;
struct dxlt_file_record *file_rec;
int i;
rec_ref = darshan_lookup_record_ref(dxlt_posix_runtime->rec_id_hash, &rec_id,
sizeof(darshan_record_id));
assert(rec_ref);
darshan_add_record_ref(&(dxlt_posix_runtime->fd_hash), &fd,
sizeof(int), rec_ref);
/* get Lustre stripe information */
file_rec = rec_ref->file_rec;
dxlt_instrument_fs_data(rec_id, rec_ref->fs_type, file_rec);
}
void dxlt_mpiio_add_record_ref(darshan_record_id rec_id, MPI_File fh)
{
struct dxlt_file_record_ref *rec_ref = NULL;
rec_ref = darshan_lookup_record_ref(dxlt_mpiio_runtime->rec_id_hash, &rec_id,
sizeof(darshan_record_id));
assert(rec_ref);
darshan_add_record_ref(&(dxlt_mpiio_runtime->fh_hash), &fh,
sizeof(MPI_File), rec_ref);
}
static void dxlt_instrument_fs_data(
darshan_record_id rec_id, int fs_type, struct dxlt_file_record *file_rec)
{
#ifdef DARSHAN_LUSTRE
/* allow lustre to generate a record if we configured with lustre support */
if(fs_type == LL_SUPER_MAGIC)
{
dxlt_get_lustre_stripe_info(rec_id, file_rec);
return;
}
#endif
return;
}
void dxlt_clear_record_refs(void **hash_head_p, int free_flag)
{
struct dxlt_record_ref_tracker *ref_tracker, *tmp;
struct dxlt_record_ref_tracker *ref_tracker_head =
*(struct dxlt_record_ref_tracker **)hash_head_p;
struct dxlt_file_record_ref *rec_ref;
struct dxlt_file_record *file_rec;
/* iterate the hash table and remove/free all reference trackers */
HASH_ITER(hlink, ref_tracker_head, ref_tracker, tmp)
{
HASH_DELETE(hlink, ref_tracker_head, ref_tracker);
if (free_flag) {
rec_ref = (struct dxlt_file_record_ref *)ref_tracker->rec_ref_p;
file_rec = rec_ref->file_rec;
if (file_rec->ost_ids)
free(file_rec->ost_ids);
if (file_rec->write_traces)
free(file_rec->write_traces);
if (file_rec->read_traces)
free(file_rec->read_traces);
free(rec_ref);
}
free(ref_tracker);
}
*hash_head_p = ref_tracker_head;
return;
}
static void dxlt_posix_cleanup_runtime()
{
dxlt_clear_record_refs(&(dxlt_posix_runtime->fd_hash), 0);
dxlt_clear_record_refs(&(dxlt_posix_runtime->rec_id_hash), 1);
free(dxlt_posix_runtime);
dxlt_posix_runtime = NULL;
return;
}
static void dxlt_mpiio_cleanup_runtime()
{
dxlt_clear_record_refs(&(dxlt_mpiio_runtime->fh_hash), 0);
dxlt_clear_record_refs(&(dxlt_mpiio_runtime->rec_id_hash), 1);
free(dxlt_mpiio_runtime);
dxlt_mpiio_runtime = NULL;
return;
}
/********************************************************************************
* shutdown function exported by this module for coordinating with darshan-core *
********************************************************************************/
static void dxlt_posix_shutdown(
MPI_Comm mod_comm,
darshan_record_id *shared_recs,
int shared_rec_count,
void **dxlt_posix_buf,
int *dxlt_posix_buf_sz)
{
struct dxlt_file_record_ref *rec_ref;
struct dxlt_file_record *file_rec;
int i, idx;
int64_t offset;
int64_t length;
int64_t rank;
double start_time;
double end_time;
int64_t record_size = 0;
int64_t record_write_count = 0;
int64_t record_read_count = 0;
void *tmp_buf_ptr = *dxlt_posix_buf;
int32_t stripe_size;
int32_t stripe_count;
int32_t ost_idx;
int64_t cur_offset;
OST_ID *ost_ids;
assert(dxlt_posix_runtime);
DXLT_POSIX_LOCK();
int dxlt_rec_count = dxlt_posix_runtime->file_rec_count;
struct dxlt_record_ref_tracker *ref_tracker, *tmp;
struct dxlt_record_ref_tracker *ref_tracker_head =
(struct dxlt_record_ref_tracker *)(dxlt_posix_runtime->rec_id_hash);
*dxlt_posix_buf_sz = 0;
HASH_ITER(hlink, ref_tracker_head, ref_tracker, tmp) {