[Darshan-commits] [Git][darshan/darshan][dev-stdio] convert stdio module to use new apis

Philip Carns xgitlab at cels.anl.gov
Thu Jun 23 16:35:37 CDT 2016


Philip Carns pushed to branch dev-stdio at darshan / darshan


Commits:
ad6ea64f by Phil Carns at 2016-06-23T17:33:59-04:00
convert stdio module to use new apis

- eliminated 110 SLOC
- untested

- - - - -


2 changed files:

- darshan-runtime/lib/darshan-stdio.c
- darshan-stdio-log-format.h


Changes:

=====================================
darshan-runtime/lib/darshan-stdio.c
=====================================
--- a/darshan-runtime/lib/darshan-stdio.c
+++ b/darshan-runtime/lib/darshan-stdio.c
@@ -90,9 +90,6 @@
 #include <libgen.h>
 #include <pthread.h>
 
-#include "uthash.h"
-#include "utlist.h"
-
 #include "darshan.h"
 #include "darshan-dynamic.h"
 
@@ -125,67 +122,14 @@ DARSHAN_FORWARD_DECL(fsetpos, int, (FILE *stream, const fpos_t *pos));
 DARSHAN_FORWARD_DECL(fsetpos64, int, (FILE *stream, const fpos_t *pos));
 DARSHAN_FORWARD_DECL(rewind, void, (FILE *stream));
 
-/* The stdio_file_runtime structure maintains necessary runtime metadata
- * for the STDIO file record (darshan_stdio_record structure, defined in
- * darshan-stdio-log-format.h) pointed to by 'file_record'. This metadata
- * assists with the instrumenting of specific statistics in the file record.
- * 'hlink' is a hash table link structure used to add/remove this record
- * from the hash table of STDIO file records for this process. 
- *
- * RATIONALE: the STDIO module needs to track some stateful, volatile 
- * information about each open file (like the current file offset, most recent 
- * access time, etc.) to aid in instrumentation, but this information can't be
- * stored in the darshan_stdio_record struct because we don't want it to appear in
- * the final darshan log file.  We therefore associate a stdio_file_runtime
- * struct with each darshan_stdio_record struct in order to track this information.
-  *
- * NOTE: There is a one-to-one mapping of stdio_file_runtime structs to
- * darshan_stdio_record structs.
- *
- * NOTE: The stdio_file_runtime struct contains a pointer to a darshan_stdio_record
- * struct (see the *file_record member) rather than simply embedding an entire
- * darshan_stdio_record struct.  This is done so that all of the darshan_stdio_record
- * structs can be kept contiguous in memory as a single array to simplify
- * reduction, compression, and storage.
- */
-struct stdio_file_runtime
+/* structure to track stdio stats at runtime */
+struct stdio_file_record_ref
 {
-    struct darshan_stdio_record* file_record;
+    struct darshan_stdio_file* file_rec;
     int64_t offset;
     double last_meta_end;
     double last_read_end;
     double last_write_end;
-    UT_hash_handle hlink;
-};
-
-/* The stdio_file_runtime_ref structure is used to associate a STDIO
- * stream with an already existing STDIO file record. This is
- * necessary as many STDIO I/O functions take only an input stream,
- * but STDIO file records are indexed by their full file paths (i.e., darshan
- * record identifiers for STDIO files are created by hashing the file path).
- * In other words, this structure is necessary as it allows us to look up a
- * file record either by a pathname (stdio_file_runtime) or by STDIO stream 
- * (stdio_file_runtime_ref), depending on which parameters are
- * available. This structure includes another hash table link, since separate
- * hashes are maintained for stdio_file_runtime structures and stdio_file_runtime_ref
- * structures.
- *
- * RATIONALE: In theory the FILE* information could be included in the
- * stdio_file_runtime struct rather than in a separate structure here.  The
- * reason we don't do that is because the same file could be opened multiple
- * times by a given process with different stream pointers and thus
- * simulataneously referenced using different stream pointers.  This practice is
- * not common, but we must support it.
- *
- * NOTE: there are potentially multiple stdio_file_runtime_ref structures
- * referring to a single stdio_file_runtime structure.  Most of the time there is
- * only one, however.
- */
-struct stdio_file_runtime_ref
-{
-    struct stdio_file_runtime* file;
-    FILE* stream;
-    UT_hash_handle hlink;
 };
 
 /* The stdio_runtime structure maintains necessary state for storing
@@ -194,12 +138,9 @@ struct stdio_file_runtime_ref
  */
 struct stdio_runtime
 {
-    struct stdio_file_runtime* file_runtime_array;
-    struct darshan_stdio_record* file_record_array;
-    int file_array_size;
-    int file_array_ndx;
-    struct stdio_file_runtime* file_hash;
-    struct stdio_file_runtime_ref* stream_hash;
+    void *rec_id_hash;
+    void *stream_hash;
+    int file_rec_count;
 };
 
 static struct stdio_runtime *stdio_runtime = NULL;
@@ -209,82 +150,101 @@ static int darshan_mem_alignment = 1;
 static int my_rank = -1;
 
 static void stdio_runtime_initialize(void);
-static struct stdio_file_runtime* stdio_file_by_name(const char *name);
-static struct stdio_file_runtime* stdio_file_by_name_setstream(const char* name, FILE *stream);
-static struct stdio_file_runtime* stdio_file_by_stream(FILE* stream);
-static void stdio_file_close_stream(FILE *stream);
-
-static void stdio_begin_shutdown(void);
-static void stdio_get_output_data(MPI_Comm mod_comm, darshan_record_id *shared_recs,
-    int shared_rec_count, void **stdio_buf, int *stdio_buf_sz);
-static void stdio_shutdown(void);
+static void stdio_shutdown(
+    MPI_Comm mod_comm,
+    darshan_record_id *shared_recs,
+    int shared_rec_count,
+    void **stdio_buf,
+    int *stdio_buf_sz);
 static void stdio_record_reduction_op(void* infile_v, void* inoutfile_v,
     int *len, MPI_Datatype *datatype);
-static int stdio_record_compare(const void* a, const void* b);
+static struct stdio_file_record_ref *stdio_track_new_file_record(
+    darshan_record_id rec_id, const char *path);
+static void stdio_cleanup_runtime();
 
 #define STDIO_LOCK() pthread_mutex_lock(&stdio_runtime_mutex)
 #define STDIO_UNLOCK() pthread_mutex_unlock(&stdio_runtime_mutex)
 
+#define STDIO_PRE_RECORD() do { \
+    STDIO_LOCK(); \
+    if(!stdio_runtime && !instrumentation_disabled) stdio_runtime_initialize(); \
+    if(!stdio_runtime) { \
+        STDIO_UNLOCK(); \
+        return(ret); \
+    } \
+} while(0)
+
+#define STDIO_POST_RECORD() do { \
+    STDIO_UNLOCK(); \
+} while(0)
+
 #define STDIO_RECORD_OPEN(__ret, __path, __tm1, __tm2) do { \
-    struct stdio_file_runtime* file; \
-    char* exclude; \
-    int tmp_index = 0; \
+    darshan_record_id rec_id; \
+    struct stdio_file_record_ref* rec_ref; \
+    char *newpath; \
     if(__ret == NULL) break; \
-    while((exclude = darshan_path_exclusions[tmp_index])) { \
-        if(!(strncmp(exclude, __path, strlen(exclude)))) \
-            break; \
-        tmp_index++; \
+    newpath = darshan_clean_file_path(__path); \
+    if(!newpath) newpath = (char*)__path; \
+    if(darshan_core_excluded_path(newpath)) { \
+        if(newpath != (char*)__path) free(newpath); \
+        break; \
     } \
-    if(exclude) break; \
-    file = stdio_file_by_name_setstream(__path, __ret); \
-    if(!file) break; \
-    file->offset = 0; \
-    file->file_record->counters[STDIO_OPENS] += 1; \
-    if(file->file_record->fcounters[STDIO_F_OPEN_START_TIMESTAMP] == 0 || \
-     file->file_record->fcounters[STDIO_F_OPEN_START_TIMESTAMP] > __tm1) \
-        file->file_record->fcounters[STDIO_F_OPEN_START_TIMESTAMP] = __tm1; \
-    file->file_record->fcounters[STDIO_F_OPEN_END_TIMESTAMP] = __tm2; \
-    DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[STDIO_F_META_TIME], __tm1, __tm2, file->last_meta_end); \
+    rec_id = darshan_core_gen_record_id(newpath); \
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->rec_id_hash, &rec_id, sizeof(darshan_record_id)); \
+    if(!rec_ref) rec_ref = stdio_track_new_file_record(rec_id, newpath); \
+    if(!rec_ref) { \
+        if(newpath != (char*)__path) free(newpath); \
+        break; \
+    } \
+    rec_ref->offset = 0; \
+    rec_ref->file_rec->counters[STDIO_OPENS] += 1; \
+    if(rec_ref->file_rec->fcounters[STDIO_F_OPEN_START_TIMESTAMP] == 0 || \
+     rec_ref->file_rec->fcounters[STDIO_F_OPEN_START_TIMESTAMP] > __tm1) \
+        rec_ref->file_rec->fcounters[STDIO_F_OPEN_START_TIMESTAMP] = __tm1; \
+    rec_ref->file_rec->fcounters[STDIO_F_OPEN_END_TIMESTAMP] = __tm2; \
+    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[STDIO_F_META_TIME], __tm1, __tm2, rec_ref->last_meta_end); \
+    darshan_add_record_ref(&(stdio_runtime->stream_hash), &(__ret), sizeof(__ret), rec_ref); \
+    if(newpath != (char*)__path) free(newpath); \
 } while(0)
 
 
 #define STDIO_RECORD_READ(__fp, __bytes,  __tm1, __tm2) do{ \
+    struct stdio_file_record_ref* rec_ref; \
     int64_t this_offset; \
-    struct stdio_file_runtime* file; \
-    file = stdio_file_by_stream(__fp); \
-    if(!file) break; \
-    this_offset = file->offset; \
-    file->offset = this_offset + __bytes; \
-    if(file->file_record->counters[STDIO_MAX_BYTE_READ] < (this_offset + __bytes - 1)) \
-        file->file_record->counters[STDIO_MAX_BYTE_READ] = (this_offset + __bytes - 1); \
-    file->file_record->counters[STDIO_BYTES_READ] += __bytes; \
-    file->file_record->counters[STDIO_READS] += 1; \
-    if(file->file_record->fcounters[STDIO_F_READ_START_TIMESTAMP] == 0 || \
-     file->file_record->fcounters[STDIO_F_READ_START_TIMESTAMP] > __tm1) \
-        file->file_record->fcounters[STDIO_F_READ_START_TIMESTAMP] = __tm1; \
-    file->file_record->fcounters[STDIO_F_READ_END_TIMESTAMP] = __tm2; \
-    DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[STDIO_F_READ_TIME], __tm1, __tm2, file->last_write_end); \
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &(__fp), sizeof(int)); \
+    if(!rec_ref) break; \
+    this_offset = rec_ref->offset; \
+    rec_ref->offset = this_offset + __bytes; \
+    if(rec_ref->file_rec->counters[STDIO_MAX_BYTE_READ] < (this_offset + __bytes - 1)) \
+        rec_ref->file_rec->counters[STDIO_MAX_BYTE_READ] = (this_offset + __bytes - 1); \
+    rec_ref->file_rec->counters[STDIO_BYTES_READ] += __bytes; \
+    rec_ref->file_rec->counters[STDIO_READS] += 1; \
+    if(rec_ref->file_rec->fcounters[STDIO_F_READ_START_TIMESTAMP] == 0 || \
+     rec_ref->file_rec->fcounters[STDIO_F_READ_START_TIMESTAMP] > __tm1) \
+        rec_ref->file_rec->fcounters[STDIO_F_READ_START_TIMESTAMP] = __tm1; \
+    rec_ref->file_rec->fcounters[STDIO_F_READ_END_TIMESTAMP] = __tm2; \
+    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[STDIO_F_READ_TIME], __tm1, __tm2, rec_ref->last_write_end); \
 } while(0)
 
 #define STDIO_RECORD_WRITE(__fp, __bytes,  __tm1, __tm2, __fflush_flag) do{ \
+    struct stdio_file_record_ref* rec_ref; \
     int64_t this_offset; \
-    struct stdio_file_runtime* file; \
-    file = stdio_file_by_stream(__fp); \
-    if(!file) break; \
-    this_offset = file->offset; \
-    file->offset = this_offset + __bytes; \
-    if(file->file_record->counters[STDIO_MAX_BYTE_WRITTEN] < (this_offset + __bytes - 1)) \
-        file->file_record->counters[STDIO_MAX_BYTE_WRITTEN] = (this_offset + __bytes - 1); \
-    file->file_record->counters[STDIO_BYTES_WRITTEN] += __bytes; \
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &(__fp), sizeof(int)); \
+    if(!rec_ref) break; \
+    this_offset = rec_ref->offset; \
+    rec_ref->offset = this_offset + __bytes; \
+    if(rec_ref->file_rec->counters[STDIO_MAX_BYTE_WRITTEN] < (this_offset + __bytes - 1)) \
+        rec_ref->file_rec->counters[STDIO_MAX_BYTE_WRITTEN] = (this_offset + __bytes - 1); \
+    rec_ref->file_rec->counters[STDIO_BYTES_WRITTEN] += __bytes; \
     if(__fflush_flag) \
-        file->file_record->counters[STDIO_FLUSHES] += 1; \
+        rec_ref->file_rec->counters[STDIO_FLUSHES] += 1; \
     else \
-        file->file_record->counters[STDIO_WRITES] += 1; \
-    if(file->file_record->fcounters[STDIO_F_WRITE_START_TIMESTAMP] == 0 || \
-     file->file_record->fcounters[STDIO_F_WRITE_START_TIMESTAMP] > __tm1) \
-        file->file_record->fcounters[STDIO_F_WRITE_START_TIMESTAMP] = __tm1; \
-    file->file_record->fcounters[STDIO_F_WRITE_END_TIMESTAMP] = __tm2; \
-    DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[STDIO_F_WRITE_TIME], __tm1, __tm2, file->last_write_end); \
+        rec_ref->file_rec->counters[STDIO_WRITES] += 1; \
+    if(rec_ref->file_rec->fcounters[STDIO_F_WRITE_START_TIMESTAMP] == 0 || \
+     rec_ref->file_rec->fcounters[STDIO_F_WRITE_START_TIMESTAMP] > __tm1) \
+        rec_ref->file_rec->fcounters[STDIO_F_WRITE_START_TIMESTAMP] = __tm1; \
+    rec_ref->file_rec->fcounters[STDIO_F_WRITE_END_TIMESTAMP] = __tm2; \
+    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[STDIO_F_WRITE_TIME], __tm1, __tm2, rec_ref->last_write_end); \
 } while(0)
 
 FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
@@ -298,10 +258,9 @@ FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
     ret = __real_fopen(path, mode);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     STDIO_RECORD_OPEN(ret, path, tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -317,10 +276,9 @@ FILE* DARSHAN_DECL(fopen64)(const char *path, const char *mode)
     ret = __real_fopen64(path, mode);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     STDIO_RECORD_OPEN(ret, path, tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -336,10 +294,9 @@ FILE* DARSHAN_DECL(fdopen)(int fd, const char *mode)
     ret = __real_fdopen(fd, mode);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     STDIO_RECORD_OPEN(ret, "UNKNOWN-FDOPEN", tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -355,10 +312,9 @@ FILE* DARSHAN_DECL(freopen)(const char *path, const char *mode, FILE *stream)
     ret = __real_freopen(path, mode, stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     STDIO_RECORD_OPEN(ret, path, tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -374,10 +330,9 @@ FILE* DARSHAN_DECL(freopen64)(const char *path, const char *mode, FILE *stream)
     ret = __real_freopen64(path, mode, stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     STDIO_RECORD_OPEN(ret, path, tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -394,20 +349,19 @@ int DARSHAN_DECL(fflush)(FILE *fp)
     ret = __real_fflush(fp);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret >= 0)
         STDIO_RECORD_WRITE(fp, 0, tm1, tm2, 1);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
 
 int DARSHAN_DECL(fclose)(FILE *fp)
 {
-    struct stdio_file_runtime* file;
     double tm1, tm2;
     int ret;
+    struct stdio_file_record_ref *rec_ref;
 
     MAP_OR_FAIL(fclose);
 
@@ -415,21 +369,20 @@ int DARSHAN_DECL(fclose)(FILE *fp)
     ret = __real_fclose(fp);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
-    file = stdio_file_by_stream(fp);
-    if(file)
+    STDIO_PRE_RECORD();
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &fp, sizeof(fp));
+    if(rec_ref)
     {
-        if(file->file_record->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] == 0 ||
-         file->file_record->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] > tm1)
-           file->file_record->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] = tm1;
-        file->file_record->fcounters[STDIO_F_CLOSE_END_TIMESTAMP] = tm2;
+        if(rec_ref->file_rec->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] == 0 ||
+         rec_ref->file_rec->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] > tm1)
+           rec_ref->file_rec->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] = tm1;
+        rec_ref->file_rec->fcounters[STDIO_F_CLOSE_END_TIMESTAMP] = tm2;
         DARSHAN_TIMER_INC_NO_OVERLAP(
-            file->file_record->fcounters[STDIO_F_META_TIME],
-            tm1, tm2, file->last_meta_end);
-        stdio_file_close_stream(fp);
+            rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+            tm1, tm2, rec_ref->last_meta_end);
+        darshan_delete_record_ref(&(stdio_runtime->stream_hash), &fp, sizeof(fp));
     }
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -445,11 +398,10 @@ size_t DARSHAN_DECL(fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *st
     ret = __real_fwrite(ptr, size, nmemb, stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret > 0)
         STDIO_RECORD_WRITE(stream, size*ret, tm1, tm2, 0);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -466,11 +418,10 @@ int DARSHAN_DECL(fputc)(int c, FILE *stream)
     ret = __real_fputc(c, stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != EOF)
         STDIO_RECORD_WRITE(stream, 1, tm1, tm2, 0);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -486,11 +437,10 @@ int DARSHAN_DECL(putw)(int w, FILE *stream)
     ret = __real_putw(w, stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != EOF)
         STDIO_RECORD_WRITE(stream, sizeof(int), tm1, tm2, 0);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -508,11 +458,10 @@ int DARSHAN_DECL(fputs)(const char *s, FILE *stream)
     ret = __real_fputs(s, stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != EOF && ret > 0)
         STDIO_RECORD_WRITE(stream, strlen(s), tm1, tm2, 0);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -531,11 +480,10 @@ int DARSHAN_DECL(vfprintf)(FILE *stream, const char *format, va_list ap)
     end_off = ftell(stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret > 0)
         STDIO_RECORD_WRITE(stream, (end_off-start_off), tm1, tm2, 0);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -561,11 +509,10 @@ int DARSHAN_DECL(fprintf)(FILE *stream, const char *format, ...)
     end_off = ftell(stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret > 0)
         STDIO_RECORD_WRITE(stream, (end_off-start_off), tm1, tm2, 0);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -581,11 +528,10 @@ size_t DARSHAN_DECL(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
     ret = __real_fread(ptr, size, nmemb, stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret > 0)
         STDIO_RECORD_READ(stream, size*ret, tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -601,11 +547,10 @@ size_t DARSHAN_DECL(fgetc)(FILE *stream)
     ret = __real_fgetc(stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != EOF)
         STDIO_RECORD_READ(stream, 1, tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -622,11 +567,10 @@ size_t DARSHAN_DECL(_IO_getc)(FILE *stream)
     ret = __real__IO_getc(stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != EOF)
         STDIO_RECORD_READ(stream, 1, tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -643,11 +587,10 @@ size_t DARSHAN_DECL(_IO_putc)(int c, FILE *stream)
     ret = __real__IO_putc(c, stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != EOF)
         STDIO_RECORD_WRITE(stream, 1, tm1, tm2, 0);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -662,11 +605,10 @@ size_t DARSHAN_DECL(getw)(FILE *stream)
     ret = __real_getw(stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != EOF || ferror(stream) == 0)
         STDIO_RECORD_READ(stream, sizeof(int), tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -694,11 +636,10 @@ int DARSHAN_DECL(__isoc99_fscanf)(FILE *stream, const char *format, ...)
     end_off = ftell(stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != 0)
         STDIO_RECORD_READ(stream, (end_off-start_off), tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -724,11 +665,10 @@ int DARSHAN_DECL(fscanf)(FILE *stream, const char *format, ...)
     end_off = ftell(stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != 0)
         STDIO_RECORD_READ(stream, (end_off-start_off), tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -747,11 +687,10 @@ int DARSHAN_DECL(vfscanf)(FILE *stream, const char *format, va_list ap)
     end_off = ftell(stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != 0)
         STDIO_RECORD_READ(stream, end_off-start_off, tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -768,11 +707,10 @@ char* DARSHAN_DECL(fgets)(char *s, int size, FILE *stream)
     ret = __real_fgets(s, size, stream);
     tm2 = darshan_core_wtime();
 
-    STDIO_LOCK();
-    stdio_runtime_initialize();
+    STDIO_PRE_RECORD();
     if(ret != NULL)
         STDIO_RECORD_READ(stream, strlen(ret), tm1, tm2);
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return(ret);
 }
@@ -780,8 +718,8 @@ char* DARSHAN_DECL(fgets)(char *s, int size, FILE *stream)
 
 void DARSHAN_DECL(rewind)(FILE *stream)
 {
-    struct stdio_file_runtime* file;
     double tm1, tm2;
+    struct stdio_file_record_ref *rec_ref;
 
     MAP_OR_FAIL(rewind);
 
@@ -789,18 +727,27 @@ void DARSHAN_DECL(rewind)(FILE *stream)
     __real_rewind(stream);
     tm2 = darshan_core_wtime();
 
+    /* NOTE: we don't use STDIO_PRE_RECORD here because there is no return
+     * value in this wrapper.
+     */
     STDIO_LOCK();
-    stdio_runtime_initialize();
-    file = stdio_file_by_stream(stream);
-    if(file)
+    if(!stdio_runtime && !instrumentation_disabled) stdio_runtime_initialize();
+    if(!stdio_runtime) {
+        STDIO_UNLOCK();
+        return;
+    }
+
+    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+
+    if(rec_ref)
     {
-        file->offset = 0;
+        rec_ref->offset = 0;
         DARSHAN_TIMER_INC_NO_OVERLAP(
-            file->file_record->fcounters[STDIO_F_META_TIME],
-            tm1, tm2, file->last_meta_end);
-        file->file_record->counters[STDIO_SEEKS] += 1;
+            rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+            tm1, tm2, rec_ref->last_meta_end);
+        rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
     }
-    STDIO_UNLOCK();
+    STDIO_POST_RECORD();
 
     return;
 }
@@ -808,7 +755,7 @@ void DARSHAN_DECL(rewind)(FILE *stream)
 int DARSHAN_DECL(fseek)(FILE *stream, long offset, int whence)
 {
     int ret;
-    struct stdio_file_runtime* file;
+    struct stdio_file_record_ref *rec_ref;
     double tm1, tm2;
 
     MAP_OR_FAIL(fseek);
@@ -819,18 +766,17 @@ int DARSHAN_DECL(fseek)(FILE *stream, long offset, int whence)
 
     if(ret >= 0)
     {
-        STDIO_LOCK();
-        stdio_runtime_initialize();
-        file = stdio_file_by_stream(stream);
-        if(file)
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
         {
-            file->offset = ftell(stream);
+            rec_ref->offset = ftell(stream);
             DARSHAN_TIMER_INC_NO_OVERLAP(
-                file->file_record->fcounters[STDIO_F_META_TIME],
-                tm1, tm2, file->last_meta_end);
-            file->file_record->counters[STDIO_SEEKS] += 1;
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
         }
-        STDIO_UNLOCK();
+        STDIO_POST_RECORD();
     }
 
     return(ret);
@@ -839,7 +785,7 @@ int DARSHAN_DECL(fseek)(FILE *stream, long offset, int whence)
 int DARSHAN_DECL(fseeko)(FILE *stream, off_t offset, int whence)
 {
     int ret;
-    struct stdio_file_runtime* file;
+    struct stdio_file_record_ref *rec_ref;
     double tm1, tm2;
 
     MAP_OR_FAIL(fseeko);
@@ -850,18 +796,17 @@ int DARSHAN_DECL(fseeko)(FILE *stream, off_t offset, int whence)
 
     if(ret >= 0)
     {
-        STDIO_LOCK();
-        stdio_runtime_initialize();
-        file = stdio_file_by_stream(stream);
-        if(file)
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
         {
-            file->offset = ftell(stream);
+            rec_ref->offset = ftell(stream);
             DARSHAN_TIMER_INC_NO_OVERLAP(
-                file->file_record->fcounters[STDIO_F_META_TIME],
-                tm1, tm2, file->last_meta_end);
-            file->file_record->counters[STDIO_SEEKS] += 1;
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
         }
-        STDIO_UNLOCK();
+        STDIO_POST_RECORD();
     }
 
     return(ret);
@@ -870,7 +815,7 @@ int DARSHAN_DECL(fseeko)(FILE *stream, off_t offset, int whence)
 int DARSHAN_DECL(fseeko64)(FILE *stream, off_t offset, int whence)
 {
     int ret;
-    struct stdio_file_runtime* file;
+    struct stdio_file_record_ref *rec_ref;
     double tm1, tm2;
 
     MAP_OR_FAIL(fseeko64);
@@ -881,18 +826,17 @@ int DARSHAN_DECL(fseeko64)(FILE *stream, off_t offset, int whence)
 
     if(ret >= 0)
     {
-        STDIO_LOCK();
-        stdio_runtime_initialize();
-        file = stdio_file_by_stream(stream);
-        if(file)
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
         {
-            file->offset = ftell(stream);
+            rec_ref->offset = ftell(stream);
             DARSHAN_TIMER_INC_NO_OVERLAP(
-                file->file_record->fcounters[STDIO_F_META_TIME],
-                tm1, tm2, file->last_meta_end);
-            file->file_record->counters[STDIO_SEEKS] += 1;
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
         }
-        STDIO_UNLOCK();
+        STDIO_POST_RECORD();
     }
 
     return(ret);
@@ -901,7 +845,7 @@ int DARSHAN_DECL(fseeko64)(FILE *stream, off_t offset, int whence)
 int DARSHAN_DECL(fsetpos)(FILE *stream, const fpos_t *pos)
 {
     int ret;
-    struct stdio_file_runtime* file;
+    struct stdio_file_record_ref *rec_ref;
     double tm1, tm2;
 
     MAP_OR_FAIL(fsetpos);
@@ -912,18 +856,17 @@ int DARSHAN_DECL(fsetpos)(FILE *stream, const fpos_t *pos)
 
     if(ret >= 0)
     {
-        STDIO_LOCK();
-        stdio_runtime_initialize();
-        file = stdio_file_by_stream(stream);
-        if(file)
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
         {
-            file->offset = ftell(stream);
+            rec_ref->offset = ftell(stream);
             DARSHAN_TIMER_INC_NO_OVERLAP(
-                file->file_record->fcounters[STDIO_F_META_TIME],
-                tm1, tm2, file->last_meta_end);
-            file->file_record->counters[STDIO_SEEKS] += 1;
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
         }
-        STDIO_UNLOCK();
+        STDIO_POST_RECORD();
     }
 
     return(ret);
@@ -932,7 +875,7 @@ int DARSHAN_DECL(fsetpos)(FILE *stream, const fpos_t *pos)
 int DARSHAN_DECL(fsetpos64)(FILE *stream, const fpos_t *pos)
 {
     int ret;
-    struct stdio_file_runtime* file;
+    struct stdio_file_record_ref *rec_ref;
     double tm1, tm2;
 
     MAP_OR_FAIL(fsetpos64);
@@ -943,18 +886,17 @@ int DARSHAN_DECL(fsetpos64)(FILE *stream, const fpos_t *pos)
 
     if(ret >= 0)
     {
-        STDIO_LOCK();
-        stdio_runtime_initialize();
-        file = stdio_file_by_stream(stream);
-        if(file)
+        STDIO_PRE_RECORD();
+        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
+        if(rec_ref)
         {
-            file->offset = ftell(stream);
+            rec_ref->offset = ftell(stream);
             DARSHAN_TIMER_INC_NO_OVERLAP(
-                file->file_record->fcounters[STDIO_F_META_TIME],
-                tm1, tm2, file->last_meta_end);
-            file->file_record->counters[STDIO_SEEKS] += 1;
+                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
+                tm1, tm2, rec_ref->last_meta_end);
+            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
         }
-        STDIO_UNLOCK();
+        STDIO_POST_RECORD();
     }
 
     return(ret);
@@ -968,13 +910,10 @@ int DARSHAN_DECL(fsetpos64)(FILE *stream, const fpos_t *pos)
 /* initialize internal STDIO module data structures and register with darshan-core */
 static void stdio_runtime_initialize()
 {
-    int mem_limit;
-    struct darshan_module_funcs stdio_mod_fns =
-    {
-        .begin_shutdown = &stdio_begin_shutdown,
-        .get_output_data = &stdio_get_output_data,
-        .shutdown = &stdio_shutdown
-    };
+    int stdio_buf_size;
+
+    /* try to store default number of records for this module */
+    stdio_buf_size = DARSHAN_DEF_MOD_REC_COUNT * sizeof(struct darshan_stdio_file);
 
     /* don't do anything if already initialized or instrumenation is disabled */
     if(stdio_runtime || instrumentation_disabled)
@@ -983,216 +922,115 @@ static void stdio_runtime_initialize()
     /* register the stdio module with darshan core */
     darshan_core_register_module(
         DARSHAN_STDIO_MOD,
-        &stdio_mod_fns,
+        &stdio_shutdown,
         &my_rank,
-        &mem_limit,
+        &stdio_buf_size,
         &darshan_mem_alignment);
 
-    /* return if no memory assigned by darshan core */
-    if(mem_limit == 0)
+    /* return if darshan-core does not provide enough module memory */
+    if(stdio_buf_size < sizeof(struct darshan_stdio_file))
+    {
+        darshan_core_unregister_module(DARSHAN_POSIX_MOD);
         return;
+    }
 
     stdio_runtime = malloc(sizeof(*stdio_runtime));
     if(!stdio_runtime)
-        return;
-    memset(stdio_runtime, 0, sizeof(*stdio_runtime));
-
-    /* set maximum number of file records according to max memory limit */
-    /* NOTE: maximum number of records is based on the size of a stdio file record */
-    /* TODO: should we base memory usage off file record or total runtime structure sizes? */
-    stdio_runtime->file_array_size = mem_limit / sizeof(struct darshan_stdio_record);
-    stdio_runtime->file_array_ndx = 0;
-
-    /* allocate array of runtime file records */
-    stdio_runtime->file_runtime_array = malloc(stdio_runtime->file_array_size *
-                                               sizeof(struct stdio_file_runtime));
-    stdio_runtime->file_record_array = malloc(stdio_runtime->file_array_size *
-                                              sizeof(struct darshan_stdio_record));
-    if(!stdio_runtime->file_runtime_array || !stdio_runtime->file_record_array)
     {
-        stdio_runtime->file_array_size = 0;
+        darshan_core_unregister_module(DARSHAN_STDIO_MOD);
         return;
     }
-    memset(stdio_runtime->file_runtime_array, 0, stdio_runtime->file_array_size *
-           sizeof(struct stdio_file_runtime));
-    memset(stdio_runtime->file_record_array, 0, stdio_runtime->file_array_size *
-           sizeof(struct darshan_stdio_record));
-
-    return;
+    memset(stdio_runtime, 0, sizeof(*stdio_runtime));
 }
 
-/* get a STDIO file record for the given file path */
-static struct stdio_file_runtime* stdio_file_by_name(const char *name)
-{
-    struct stdio_file_runtime *file = NULL;
-    char *newname = NULL;
-    darshan_record_id file_id;
-    int file_alignment;
-    int limit_flag;
-
-    if(!stdio_runtime || instrumentation_disabled)
-        return(NULL);
-
-    newname = darshan_clean_file_path(name);
-    if(!newname)
-        newname = (char*)name;
-
-    limit_flag = (stdio_runtime->file_array_ndx >= stdio_runtime->file_array_size);
-
-    /* get a unique id for this file from darshan core */
-    darshan_core_register_record(
-        (void*)newname,
-        strlen(newname),
-        DARSHAN_STDIO_MOD,
-        1,
-        limit_flag,
-        &file_id,
-        &file_alignment);
-
-    /* the file record id is set to 0 if no memory is available for tracking
-     * new records -- just fall through and ignore this record
-     */
-    if(file_id == 0)
-    {
-        if(newname != name)
-            free(newname);
-        return(NULL);
-    }
-
-    /* search the hash table for this file record, and return if found */
-    HASH_FIND(hlink, stdio_runtime->file_hash, &file_id, sizeof(darshan_record_id), file);
-    if(file)
-    {
-        if(newname != name)
-            free(newname);
-        return(file);
-    }
-
-    /* no existing record, assign a new file record from the global array */
-    file = &(stdio_runtime->file_runtime_array[stdio_runtime->file_array_ndx]);
-    file->file_record = &(stdio_runtime->file_record_array[stdio_runtime->file_array_ndx]);
-    file->file_record->f_id = file_id;
-    file->file_record->rank = my_rank;
-
-    /* add new record to file hash table */
-    HASH_ADD(hlink, stdio_runtime->file_hash, file_record->f_id, sizeof(darshan_record_id), file);
-    stdio_runtime->file_array_ndx++;
-
-    if(newname != name)
-        free(newname);
-    return(file);
-}
+/************************************************************************
+ * Functions exported by this module for coordinating with darshan-core *
+ ************************************************************************/
 
-/* get a STDIO file record for the given file path, and also create a
- * reference structure using the returned stream
- */
-static struct stdio_file_runtime* stdio_file_by_name_setstream(const char* name, FILE *stream)
+static void stdio_record_reduction_op(void* infile_v, void* inoutfile_v,
+    int *len, MPI_Datatype *datatype)
 {
-    struct stdio_file_runtime* file;
-    struct stdio_file_runtime_ref* ref;
-
-    if(!stdio_runtime || instrumentation_disabled)
-        return(NULL);
-
-    /* find file record by name first */
-    file = stdio_file_by_name(name);
+    struct darshan_stdio_file tmp_file;
+    struct darshan_stdio_file *infile = infile_v;
+    struct darshan_stdio_file *inoutfile = inoutfile_v;
+    int i, j;
 
-    if(!file)
-        return(NULL);
+    assert(stdio_runtime);
 
-    /* search hash table for existing file ref for this stream */
-    HASH_FIND(hlink, stdio_runtime->stream_hash, &stream, sizeof(FILE*), ref);
-    if(ref)
+    for(i=0; i<*len; i++)
     {
-        /* we have a reference.  Make sure it points to the correct file
-         * and return it
-         */
-        ref->file = file;
-        return(file);
-    }
-
-    /* if we hit this point, then we don't have a reference for this stream 
-     * in the table yet.  Add it.
-     */
-    ref = malloc(sizeof(*ref));
-    if(!ref)
-        return(NULL);
-    memset(ref, 0, sizeof(*ref));
+        memset(&tmp_file, 0, sizeof(struct darshan_stdio_file));
+        tmp_file.base_rec.id = infile->base_rec.id;
+        tmp_file.base_rec.rank = -1;
 
-    ref->file = file;
-    ref->stream = stream;    
-    HASH_ADD(hlink, stdio_runtime->stream_hash, stream, sizeof(FILE*), ref);
-
-    return(file);
-}
-
-/* get a STDIO file record for the given stream */
-static struct stdio_file_runtime* stdio_file_by_stream(FILE *stream)
-{
-    struct stdio_file_runtime_ref* ref;
-
-    if(!stdio_runtime || instrumentation_disabled)
-        return(NULL);
-
-    /* search hash table for existing file ref for this stream */
-    HASH_FIND(hlink, stdio_runtime->stream_hash, &stream, sizeof(FILE*), ref);
-    if(ref)
-        return(ref->file);
+        /* sum */
+        for(j=STDIO_OPENS; j<=STDIO_BYTES_READ; j++)
+        {
+            tmp_file.counters[j] = infile->counters[j] + inoutfile->counters[j];
+        }
+        
+        /* max */
+        for(j=STDIO_MAX_BYTE_READ; j<=STDIO_MAX_BYTE_WRITTEN; j++)
+        {
+            if(infile->counters[j] > inoutfile->counters[j])
+                tmp_file.counters[j] = infile->counters[j];
+            else
+                tmp_file.counters[j] = inoutfile->counters[j];
+        }
 
-    return(NULL);
-}
+        /* sum */
+        for(j=STDIO_F_META_TIME; j<=STDIO_F_READ_TIME; j++)
+        {
+            tmp_file.fcounters[j] = infile->fcounters[j] + inoutfile->fcounters[j];
+        }
 
-/* free up reference data structures for the given stream */
-static void stdio_file_close_stream(FILE *stream)
-{
-    struct stdio_file_runtime_ref* ref;
+        /* min non-zero (if available) value */
+        for(j=STDIO_F_OPEN_START_TIMESTAMP; j<=STDIO_F_READ_START_TIMESTAMP; j++)
+        {
+            if((infile->fcounters[j] < inoutfile->fcounters[j] &&
+               infile->fcounters[j] > 0) || inoutfile->fcounters[j] == 0) 
+                tmp_file.fcounters[j] = infile->fcounters[j];
+            else
+                tmp_file.fcounters[j] = inoutfile->fcounters[j];
+        }
 
-    if(!stdio_runtime || instrumentation_disabled)
-        return;
+        /* max */
+        for(j=STDIO_F_OPEN_END_TIMESTAMP; j<=STDIO_F_READ_END_TIMESTAMP; j++)
+        {
+            if(infile->fcounters[j] > inoutfile->fcounters[j])
+                tmp_file.fcounters[j] = infile->fcounters[j];
+            else
+                tmp_file.fcounters[j] = inoutfile->fcounters[j];
+        }
 
-    /* search hash table for this stream */
-    HASH_FIND(hlink, stdio_runtime->stream_hash, &stream, sizeof(FILE*), ref);
-    if(ref)
-    {
-        /* we have a reference, delete it */
-        HASH_DELETE(hlink, stdio_runtime->stream_hash, ref);
-        free(ref);
+        /* update pointers */
+        *inoutfile = tmp_file;
+        inoutfile++;
+        infile++;
     }
 
     return;
 }
 
-/************************************************************************
- * Functions exported by this module for coordinating with darshan-core *
- ************************************************************************/
-
-static void stdio_begin_shutdown()
-{
-    assert(stdio_runtime);
-
-    STDIO_LOCK();
-    /* disable further instrumentation while Darshan shuts down */
-    instrumentation_disabled = 1;
-    STDIO_UNLOCK();
-
-    return;
-}
-
-static void stdio_get_output_data(
+static void stdio_shutdown(
     MPI_Comm mod_comm,
     darshan_record_id *shared_recs,
     int shared_rec_count,
     void **stdio_buf,
     int *stdio_buf_sz)
 {
-    struct stdio_file_runtime *file;
+    struct stdio_file_record_ref *rec_ref;
+    struct darshan_stdio_file *stdio_rec_buf = *(struct darshan_stdio_file **)stdio_buf;
     int i;
-    struct darshan_stdio_record *red_send_buf = NULL;
-    struct darshan_stdio_record *red_recv_buf = NULL;
+    struct darshan_stdio_file *red_send_buf = NULL;
+    struct darshan_stdio_file *red_recv_buf = NULL;
     MPI_Datatype red_type;
     MPI_Op red_op;
+    int stdio_rec_count;
 
+    STDIO_LOCK();
     assert(stdio_runtime);
+    stdio_rec_count = stdio_runtime->file_rec_count;
 
     /* if there are globally shared files, do a shared file reduction */
     /* NOTE: the shared file reduction is also skipped if the 
@@ -1203,28 +1041,26 @@ static void stdio_get_output_data(
         /* necessary initialization of shared records */
         for(i = 0; i < shared_rec_count; i++)
         {
-            HASH_FIND(hlink, stdio_runtime->file_hash, &shared_recs[i],
-                sizeof(darshan_record_id), file);
-            assert(file);
+            rec_ref = darshan_lookup_record_ref(stdio_runtime->rec_id_hash,
+                &shared_recs[i], sizeof(darshan_record_id));
+            assert(rec_ref);
 
-            file->file_record->rank = -1;
+            rec_ref->file_rec->base_rec.rank = -1;
         }
 
         /* sort the array of files descending by rank so that we get all of the 
          * shared files (marked by rank -1) in a contiguous portion at end 
          * of the array
          */
-        qsort(stdio_runtime->file_record_array, stdio_runtime->file_array_ndx,
-            sizeof(struct darshan_stdio_record), stdio_record_compare);
+        darshan_record_sort(stdio_rec_buf, stdio_rec_count, sizeof(struct darshan_stdio_file));
 
         /* make *send_buf point to the shared files at the end of sorted array */
-        red_send_buf =
-            &(stdio_runtime->file_record_array[stdio_runtime->file_array_ndx-shared_rec_count]);
+        red_send_buf = &(stdio_rec_buf[stdio_rec_count-shared_rec_count]);
 
         /* allocate memory for the reduction output on rank 0 */
         if(my_rank == 0)
         {
-            red_recv_buf = malloc(shared_rec_count * sizeof(struct darshan_stdio_record));
+            red_recv_buf = malloc(shared_rec_count * sizeof(struct darshan_stdio_file));
             if(!red_recv_buf)
             {
                 return;
@@ -1234,7 +1070,7 @@ static void stdio_get_output_data(
         /* construct a datatype for a STDIO file record.  This is serving no purpose
          * except to make sure we can do a reduction on proper boundaries
          */
-        DARSHAN_MPI_CALL(PMPI_Type_contiguous)(sizeof(struct darshan_stdio_record),
+        DARSHAN_MPI_CALL(PMPI_Type_contiguous)(sizeof(struct darshan_stdio_file),
             MPI_BYTE, &red_type);
         DARSHAN_MPI_CALL(PMPI_Type_commit)(&red_type);
 
@@ -1248,125 +1084,91 @@ static void stdio_get_output_data(
         /* clean up reduction state */
         if(my_rank == 0)
         {
-            int tmp_ndx = stdio_runtime->file_array_ndx - shared_rec_count;
-            memcpy(&(stdio_runtime->file_record_array[tmp_ndx]), red_recv_buf,
-                shared_rec_count * sizeof(struct darshan_stdio_record));
+            int tmp_ndx = stdio_rec_count - shared_rec_count;
+            memcpy(&(stdio_rec_buf[tmp_ndx]), red_recv_buf,
+                shared_rec_count * sizeof(struct darshan_stdio_file));
             free(red_recv_buf);
         }
         else
         {
-            stdio_runtime->file_array_ndx -= shared_rec_count;
+            stdio_rec_count -= shared_rec_count;
         }
 
         DARSHAN_MPI_CALL(PMPI_Type_free)(&red_type);
         DARSHAN_MPI_CALL(PMPI_Op_free)(&red_op);
     }
 
-    *stdio_buf = (void *)(stdio_runtime->file_record_array);
-    *stdio_buf_sz = stdio_runtime->file_array_ndx * sizeof(struct darshan_stdio_record);
+    /* update output buffer size to account for shared file reduction */
+    *stdio_buf_sz = stdio_rec_count * sizeof(struct darshan_stdio_file);
 
-    return;
-}
-
-/* compare function for sorting file records by descending rank */
-static int stdio_record_compare(const void* a_p, const void* b_p)
-{
-    const struct darshan_stdio_record* a = a_p;
-    const struct darshan_stdio_record* b = b_p;
+    /* shutdown internal structures used for instrumenting */
+    stdio_cleanup_runtime();
 
-    if(a->rank < b->rank)
-        return 1;
-    if(a->rank > b->rank)
-        return -1;
+    /* disable further instrumentation */
+    instrumentation_disabled = 1;
 
-    return 0;
+    STDIO_UNLOCK();
+    
+    return;
 }
 
-static void stdio_record_reduction_op(void* infile_v, void* inoutfile_v,
-    int *len, MPI_Datatype *datatype)
+static struct stdio_file_record_ref *stdio_track_new_file_record(
+    darshan_record_id rec_id, const char *path)
 {
-    struct darshan_stdio_record tmp_file;
-    struct darshan_stdio_record *infile = infile_v;
-    struct darshan_stdio_record *inoutfile = inoutfile_v;
-    int i, j;
+    struct darshan_stdio_file *file_rec = NULL;
+    struct stdio_file_record_ref *rec_ref = NULL;
+    int ret;
 
-    assert(stdio_runtime);
+    rec_ref = malloc(sizeof(*rec_ref));
+    if(!rec_ref)
+        return(NULL);
+    memset(rec_ref, 0, sizeof(*rec_ref));
 
-    for(i=0; i<*len; i++)
+    /* add a reference to this file record based on record id */
+    ret = darshan_add_record_ref(&(stdio_runtime->rec_id_hash), &rec_id,
+        sizeof(darshan_record_id), rec_ref);
+    if(ret == 0)
     {
-        memset(&tmp_file, 0, sizeof(struct darshan_stdio_record));
-        tmp_file.f_id = infile->f_id;
-        tmp_file.rank = -1;
-
-        /* sum */
-        for(j=STDIO_OPENS; j<=STDIO_BYTES_READ; j++)
-        {
-            tmp_file.counters[j] = infile->counters[j] + inoutfile->counters[j];
-        }
-        
-        /* max */
-        for(j=STDIO_MAX_BYTE_READ; j<=STDIO_MAX_BYTE_WRITTEN; j++)
-        {
-            if(infile->counters[j] > inoutfile->counters[j])
-                tmp_file.counters[j] = infile->counters[j];
-            else
-                tmp_file.counters[j] = inoutfile->counters[j];
-        }
-
-        /* sum */
-        for(j=STDIO_F_META_TIME; j<=STDIO_F_READ_TIME; j++)
-        {
-            tmp_file.fcounters[j] = infile->fcounters[j] + inoutfile->fcounters[j];
-        }
+        free(rec_ref);
+        return(NULL);
+    }
 
-        /* min non-zero (if available) value */
-        for(j=STDIO_F_OPEN_START_TIMESTAMP; j<=STDIO_F_READ_START_TIMESTAMP; j++)
-        {
-            if((infile->fcounters[j] < inoutfile->fcounters[j] &&
-               infile->fcounters[j] > 0) || inoutfile->fcounters[j] == 0) 
-                tmp_file.fcounters[j] = infile->fcounters[j];
-            else
-                tmp_file.fcounters[j] = inoutfile->fcounters[j];
-        }
+    /* 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,
+        DARSHAN_PNETCDF_MOD,
+        sizeof(struct darshan_stdio_file),
+        NULL);
+
+    if(!file_rec)
+    {
+        darshan_delete_record_ref(&(stdio_runtime->rec_id_hash),
+            &rec_id, sizeof(darshan_record_id));
+        free(rec_ref);
+        return(NULL);
+    }
 
-        /* max */
-        for(j=STDIO_F_OPEN_END_TIMESTAMP; j<=STDIO_F_READ_END_TIMESTAMP; j++)
-        {
-            if(infile->fcounters[j] > inoutfile->fcounters[j])
-                tmp_file.fcounters[j] = infile->fcounters[j];
-            else
-                tmp_file.fcounters[j] = inoutfile->fcounters[j];
-        }
+    /* registering this file record was successful, so initialize some fields */
+    file_rec->base_rec.id = rec_id;
+    file_rec->base_rec.rank = my_rank;
+    rec_ref->file_rec = file_rec;
+    stdio_runtime->file_rec_count++;
 
-        /* update pointers */
-        *inoutfile = tmp_file;
-        inoutfile++;
-        infile++;
-    }
+    return(rec_ref);
 
-    return;
 }
 
-static void stdio_shutdown()
+static void stdio_cleanup_runtime()
 {
-    struct stdio_file_runtime_ref *ref, *tmp;
+    darshan_clear_record_refs(&(stdio_runtime->stream_hash), 0);
+    darshan_clear_record_refs(&(stdio_runtime->rec_id_hash), 1);
 
-    assert(stdio_runtime);
-
-    HASH_ITER(hlink, stdio_runtime->stream_hash, ref, tmp)
-    {
-        HASH_DELETE(hlink, stdio_runtime->stream_hash, ref);
-        free(ref);
-    }
-
-    HASH_CLEAR(hlink, stdio_runtime->file_hash); /* these entries are freed all at once below */
-
-    free(stdio_runtime->file_runtime_array);
-    free(stdio_runtime->file_record_array);
     free(stdio_runtime);
     stdio_runtime = NULL;
-    instrumentation_disabled = 0;
-    
+
     return;
 }
 


=====================================
darshan-stdio-log-format.h
=====================================
--- a/darshan-stdio-log-format.h
+++ b/darshan-stdio-log-format.h
@@ -80,10 +80,9 @@ enum darshan_stdio_f_indices
  *      - integer I/O counters (operation counts, I/O sizes, etc.)
  *      - floating point I/O counters (timestamps, cumulative timers, etc.)
  */
-struct darshan_stdio_record
+struct darshan_stdio_file
 {
-    darshan_record_id f_id;
-    int64_t rank;
+    struct darshan_base_record base_rec;
     int64_t counters[STDIO_NUM_INDICES];
     double fcounters[STDIO_F_NUM_INDICES];
 };



View it on GitLab: https://xgitlab.cels.anl.gov/darshan/darshan/commit/ad6ea64f7f18b00e2c778b002ed4fe7731711b32
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/darshan-commits/attachments/20160623/0c67605f/attachment-0001.html>


More information about the Darshan-commits mailing list