[Darshan-commits] [Darshan] branch, dev-modular, updated. 7fdf26f08dfc4528bcf7397f3786ad96a2d6cbd2

Service Account git at mcs.anl.gov
Fri Feb 6 14:19:07 CST 2015


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".

The branch, dev-modular has been updated
       via  7fdf26f08dfc4528bcf7397f3786ad96a2d6cbd2 (commit)
       via  3d963df90711b53b02beeb649bfaf0a363d83328 (commit)
       via  2936261cb3ad0146fac92846fff70e4c62a4fa75 (commit)
      from  a0e8f8a87a9113013ae4460c32fa49b8257a0459 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 7fdf26f08dfc4528bcf7397f3786ad96a2d6cbd2
Author: Shane Snyder <ssnyder at mcs.anl.gov>
Date:   Fri Feb 6 14:17:51 2015 -0600

    First cut at logutils and posix parser

commit 3d963df90711b53b02beeb649bfaf0a363d83328
Author: Shane Snyder <ssnyder at mcs.anl.gov>
Date:   Fri Feb 6 14:17:22 2015 -0600

    additions to log format

commit 2936261cb3ad0146fac92846fff70e4c62a4fa75
Author: Shane Snyder <ssnyder at mcs.anl.gov>
Date:   Fri Feb 6 14:16:24 2015 -0600

    more refactoring runtime side

-----------------------------------------------------------------------

Summary of changes:
 darshan-log-format.h                |  129 ++++++-
 darshan-runtime/lib/darshan-core.c  |  242 ++++++-----
 darshan-runtime/lib/darshan-posix.c |  120 -----
 darshan-util/darshan-logutils.c     |  861 +++++++----------------------------
 darshan-util/darshan-logutils.h     |   23 +-
 darshan-util/darshan-posix-parser.c |  121 +++++
 6 files changed, 543 insertions(+), 953 deletions(-)
 create mode 100644 darshan-util/darshan-posix-parser.c


Diff of changes:
diff --git a/darshan-log-format.h b/darshan-log-format.h
index 4777b1b..d377fb5 100644
--- a/darshan-log-format.h
+++ b/darshan-log-format.h
@@ -32,6 +32,12 @@
 
 typedef uint64_t darshan_record_id;
 
+enum darshan_comp_type
+{
+    DARSHAN_GZ_COMP,
+    DARSHAN_BZ2_COMP,
+};
+
 struct darshan_header
 {
     char version_string[8];
@@ -44,7 +50,6 @@ struct darshan_record
 {
     char* name;
     darshan_record_id id;
-    //int64_t rank; /* TODO: maybe rank doesn't go here ? */
 };
 
 /* statistics for the job as a whole */
@@ -59,4 +64,126 @@ struct darshan_job
     char metadata[DARSHAN_JOB_METADATA_LEN]; /* TODO: what is this? */
 };
 
+/*** POSIX MODULE DATA STRUCTURES START */
+
+/* TODO: where do these file record structs go? */
+/* TODO: DARSHAN_* OR CP_* */
+enum darshan_posix_indices
+{
+    CP_POSIX_READS,              /* count of posix reads */
+    CP_POSIX_WRITES,             /* count of posix writes */
+    CP_POSIX_OPENS,              /* count of posix opens */
+    CP_POSIX_SEEKS,              /* count of posix seeks */
+    CP_POSIX_STATS,              /* count of posix stat/lstat/fstats */
+    CP_POSIX_MMAPS,              /* count of posix mmaps */
+    CP_POSIX_FREADS,
+    CP_POSIX_FWRITES,
+    CP_POSIX_FOPENS,
+    CP_POSIX_FSEEKS,
+    CP_POSIX_FSYNCS,
+    CP_POSIX_FDSYNCS,
+    CP_MODE,                      /* mode of file */
+    CP_BYTES_READ,                /* total bytes read */
+    CP_BYTES_WRITTEN,             /* total bytes written */
+    CP_MAX_BYTE_READ,             /* highest offset byte read */
+    CP_MAX_BYTE_WRITTEN,          /* highest offset byte written */
+    CP_CONSEC_READS,              /* count of consecutive reads */
+    CP_CONSEC_WRITES,             /* count of consecutive writes */
+    CP_SEQ_READS,                 /* count of sequential reads */
+    CP_SEQ_WRITES,                /* count of sequential writes */
+    CP_RW_SWITCHES,               /* number of times switched between read and write */
+    CP_MEM_NOT_ALIGNED,           /* count of accesses not mem aligned */
+    CP_MEM_ALIGNMENT,             /* mem alignment in bytes */
+    CP_FILE_NOT_ALIGNED,          /* count of accesses not file aligned */
+    CP_FILE_ALIGNMENT,            /* file alignment in bytes */
+    CP_MAX_READ_TIME_SIZE,
+    CP_MAX_WRITE_TIME_SIZE,
+    /* buckets */
+    CP_SIZE_READ_0_100,           /* count of posix read size ranges */
+    CP_SIZE_READ_100_1K,
+    CP_SIZE_READ_1K_10K,
+    CP_SIZE_READ_10K_100K,
+    CP_SIZE_READ_100K_1M,
+    CP_SIZE_READ_1M_4M,
+    CP_SIZE_READ_4M_10M,
+    CP_SIZE_READ_10M_100M,
+    CP_SIZE_READ_100M_1G,
+    CP_SIZE_READ_1G_PLUS,
+    /* buckets */
+    CP_SIZE_WRITE_0_100,          /* count of posix write size ranges */
+    CP_SIZE_WRITE_100_1K,
+    CP_SIZE_WRITE_1K_10K,
+    CP_SIZE_WRITE_10K_100K,
+    CP_SIZE_WRITE_100K_1M,
+    CP_SIZE_WRITE_1M_4M,
+    CP_SIZE_WRITE_4M_10M,
+    CP_SIZE_WRITE_10M_100M,
+    CP_SIZE_WRITE_100M_1G,
+    CP_SIZE_WRITE_1G_PLUS,
+    /* counters */
+    CP_STRIDE1_STRIDE,             /* the four most frequently appearing strides */
+    CP_STRIDE2_STRIDE,
+    CP_STRIDE3_STRIDE,
+    CP_STRIDE4_STRIDE,
+    CP_STRIDE1_COUNT,              /* count of each of the most frequent strides */
+    CP_STRIDE2_COUNT,
+    CP_STRIDE3_COUNT,
+    CP_STRIDE4_COUNT,
+    CP_ACCESS1_ACCESS,             /* the four most frequently appearing access sizes */
+    CP_ACCESS2_ACCESS,
+    CP_ACCESS3_ACCESS,
+    CP_ACCESS4_ACCESS,
+    CP_ACCESS1_COUNT,              /* count of each of the most frequent access sizes */
+    CP_ACCESS2_COUNT,
+    CP_ACCESS3_COUNT,
+    CP_ACCESS4_COUNT,
+    CP_DEVICE,                     /* device id reported by stat */
+    CP_SIZE_AT_OPEN,
+    CP_FASTEST_RANK,
+    CP_FASTEST_RANK_BYTES,
+    CP_SLOWEST_RANK,
+    CP_SLOWEST_RANK_BYTES,
+
+    CP_NUM_INDICES,
+};
+
+/* floating point statistics */
+enum darshan_f_posix_indices
+{
+    /* NOTE: adjust cp_normalize_timestamps() function if any TIMESTAMPS are
+     * added or modified in this list
+     */
+    CP_F_OPEN_TIMESTAMP = 0,    /* timestamp of first open */
+    CP_F_READ_START_TIMESTAMP,  /* timestamp of first read */
+    CP_F_WRITE_START_TIMESTAMP, /* timestamp of first write */
+    CP_F_CLOSE_TIMESTAMP,       /* timestamp of last close */
+    CP_F_READ_END_TIMESTAMP,    /* timestamp of last read */
+    CP_F_WRITE_END_TIMESTAMP,   /* timestamp of last write */
+    CP_F_POSIX_READ_TIME,       /* cumulative posix read time */
+    CP_F_POSIX_WRITE_TIME,      /* cumulative posix write time */
+    CP_F_POSIX_META_TIME,       /* cumulative posix meta time */
+    CP_F_MAX_READ_TIME,
+    CP_F_MAX_WRITE_TIME,
+    /* Total I/O and meta time consumed by fastest and slowest ranks, 
+     * reported in either MPI or POSIX time depending on how the file 
+     * was accessed.
+     */
+    CP_F_FASTEST_RANK_TIME,
+    CP_F_SLOWEST_RANK_TIME,
+    CP_F_VARIANCE_RANK_TIME,
+    CP_F_VARIANCE_RANK_BYTES,
+
+    CP_F_NUM_INDICES,
+};
+
+struct darshan_posix_file
+{
+    darshan_record_id f_id;
+    int64_t rank;
+    int64_t counters[CP_NUM_INDICES];
+    double fcounters[CP_F_NUM_INDICES];
+};
+
+/*** POSIX MODULE DATA STRUCTURES END */
+
 #endif /* __DARSHAN_LOG_FORMAT_H */
diff --git a/darshan-runtime/lib/darshan-core.c b/darshan-runtime/lib/darshan-core.c
index 60232c7..93d7823 100644
--- a/darshan-runtime/lib/darshan-core.c
+++ b/darshan-runtime/lib/darshan-core.c
@@ -47,8 +47,13 @@ static void darshan_log_record_hints_and_ver(
     struct darshan_core_runtime* job);
 static int darshan_get_shared_record_ids(
     struct darshan_core_runtime *job, darshan_record_id *shared_recs);
-static int darshan_write_record_map(
-    struct darshan_core_runtime *job, MPI_File log_fh, darshan_record_id *share_recs);
+static int darshan_log_write_header(
+    MPI_File log_fh, int mod_count, int64_t rec_off, int64_t psx_off);
+static int darshan_log_write_record_map(
+    MPI_File log_fh, struct darshan_core_runtime *job,
+    darshan_record_id *shared_recs, MPI_Offset *off);
+static int darshan_log_coll_append(MPI_File log_fh, MPI_Offset *off,
+    void *buf, int count);
 
 #define DARSHAN_CORE_LOCK() pthread_mutex_lock(&darshan_core_mutex)
 #define DARSHAN_CORE_UNLOCK() pthread_mutex_unlock(&darshan_core_mutex)
@@ -207,6 +212,7 @@ static void darshan_core_shutdown()
     double end_log_time;
     long offset;
     MPI_File log_fh;
+    MPI_Offset my_off = 0;
     MPI_Info info;
     MPI_Status status;
 
@@ -347,8 +353,10 @@ static void darshan_core_shutdown()
         }
     }
 
+    /* TODO: ensuing error checking...does MPI ensure collective I/O functions return the same error
+     * globally, or do I always need to allreduce????? */
+
     /* get a list of records which are shared across all processes */
-    /* TODO: do we store rank with the name map? */
     ret = darshan_get_shared_record_ids(final_job, shared_recs);
 
     /* error out if unable to determine shared file records */
@@ -366,9 +374,6 @@ static void darshan_core_shutdown()
 
     }
 
-    /* TODO: ensuing error checking...does MPI ensure collective I/O functions return the same error
-     * globally, or do I always need to allreduce????? */
-
     /* open the darshan log file for writing */
     ret = DARSHAN_MPI_CALL(PMPI_File_open)(MPI_COMM_WORLD, logfile_name,
         MPI_MODE_CREATE | MPI_MODE_WRONLY | MPI_MODE_EXCL, info, &log_fh);
@@ -394,30 +399,30 @@ static void darshan_core_shutdown()
         return;
     }
 
-    /* reserve space at beginning of darshan log for uncompressed header using seek */
-    /* NOTE: the header includes the the darshan job struct and the module indices map */
-    MPI_Offset header_end = sizeof(struct darshan_job);
-    /* header_end += (); TODO: how much do i leave for the indices map? */
-    ret = DARSHAN_MPI_CALL(PMPI_File_seek)(log_fh, header_end, MPI_SEEK_SET);
-    if(ret != MPI_SUCCESS)
+
+    if(my_rank == 0)
     {
-        if(my_rank == 0)
+        my_off = sizeof(struct darshan_header);
+        my_off += 2 * sizeof(int64_t); /* FIXME account for changes to index map */
+
+        ret = DARSHAN_MPI_CALL(PMPI_File_write_at)(log_fh, my_off, &final_job->log_job,
+                sizeof(struct darshan_job), MPI_BYTE, &status);
+        if(ret != MPI_SUCCESS)
         {
             int msg_len;
             char msg[MPI_MAX_ERROR_STRING] = {0};
 
             MPI_Error_string(ret, msg, &msg_len);
-            fprintf(stderr, "darshan library warning: unable to seek in log file %s: %s\n",
-                logfile_name, msg);
-            unlink(logfile_name);
+            fprintf(stderr, "darshan library warning: unable to write job data to log file %s: %s\n",
+                    logfile_name, msg);
         }
-        free(logfile_name);
-        darshan_core_cleanup(final_job);
-        return;
+
+        my_off += sizeof(struct darshan_job);
     }
 
+    int64_t rec_off = my_off; /* TODO: get rid of this hack */
     /* write the record name->id map to the log file */
-    ret = darshan_write_record_map(final_job, log_fh, shared_recs);
+    ret = darshan_log_write_record_map(log_fh, final_job, shared_recs, &my_off);
 
     DARSHAN_MPI_CALL(PMPI_Allreduce)(&ret, &all_ret, 1, MPI_INT,
         MPI_LOR, MPI_COMM_WORLD);
@@ -432,11 +437,12 @@ static void darshan_core_shutdown()
         darshan_core_cleanup(final_job);
         return;
     }
+    int64_t psx_off = my_off; /* TODO: get rid of this hack */
 
     /* loop over globally used darshan modules and:
      *      - get final output buffer
      *      - compress (zlib) provided output buffer
-     *      - write compressed buffer to log file
+     *      - append compressed buffer to log file
      *      - shutdown the module
      */
     for(i = 0; i < DARSHAN_MAX_MODS; i++)
@@ -445,9 +451,6 @@ static void darshan_core_shutdown()
         MPI_Comm mod_comm;
         void* mod_buf = NULL;
         int mod_buf_size = 0;
-        void* comp_buf = NULL;
-        long comp_buf_size = 0;
-        long scan_offset = 0;
 
         if(!global_mod_use_count[i])
             continue;
@@ -469,64 +472,11 @@ static void darshan_core_shutdown()
             this_mod->mod_funcs.get_output_data(mod_comm, &mod_buf, &mod_buf_size);
         }
 
-        if(mod_buf_size > 0)
+        /* append module data buffer to the darshan log file */
+        ret = darshan_log_coll_append(log_fh, &my_off, mod_buf, mod_buf_size);
+        if(ret < 0)
         {
-            /* TODO generic compression */
-            comp_buf = mod_buf;
-            comp_buf_size = mod_buf_size;
-        }
-
-        /* get current file size on rank 0 so we can calculate offset correctly */
-        scan_offset = comp_buf_size;
-        if(my_rank == 0)
-        {
-            MPI_Offset tmp_off;
-            
-            ret = MPI_File_get_size(log_fh, &tmp_off);
-            if(ret != MPI_SUCCESS)
-            {
-                int msg_len;
-                char msg[MPI_MAX_ERROR_STRING] = {0};
-
-                MPI_Error_string(ret, msg, &msg_len);
-                fprintf(stderr, "darshan library warning: unable to write module data to log file %s: %s\n",
-                        logfile_name, msg);
-                DARSHAN_MPI_CALL(PMPI_File_close)(&log_fh);
-                unlink(logfile_name);
-                free(logfile_name);
-                darshan_core_cleanup(final_job);
-                return;
-            }
-            scan_offset += tmp_off;
-        }
-
-        /* figure out everyone's offset using scan */
-        DARSHAN_MPI_CALL(PMPI_Scan)(&scan_offset, &offset, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
-        offset -= comp_buf_size;
-
-        /* collectively write out each rank's contributing data (maybe nothing) */
-        ret = DARSHAN_MPI_CALL(PMPI_File_write_at_all)(log_fh, offset, comp_buf,
-            comp_buf_size, MPI_BYTE, &status);
-
-        /* error out if unable to write */
-        DARSHAN_MPI_CALL(PMPI_Allreduce)(&ret, &all_ret, 1, MPI_INT,
-            MPI_LOR, MPI_COMM_WORLD);
-        if(all_ret != 0)
-        {
-            DARSHAN_MPI_CALL(PMPI_File_close)(&log_fh);
-            if(my_rank == 0)
-            {
-                int msg_len;
-                char msg[MPI_MAX_ERROR_STRING] = {0};
-
-                MPI_Error_string(ret, msg, &msg_len);
-                fprintf(stderr, "darshan library warning: unable to write module data to log file %s: %s\n",
-                        logfile_name, msg);
-                unlink(logfile_name);
-            }
-            free(logfile_name);
-            darshan_core_cleanup(final_job);
-            return;
+            /* TODO: */
         }
 
         /* shutdown module if registered locally */
@@ -539,25 +489,10 @@ static void darshan_core_shutdown()
         MPI_Comm_free(&mod_comm);
     }
 
-    /* TODO: is this still right? -- write the job info on rank 0 */
+    /* rank 0 is responsible for writing the log header and index map */
     if(my_rank == 0)
     {
-        /* TODO: we want to send log_job, and offsets map */
-        ret = DARSHAN_MPI_CALL(PMPI_File_write_at)(log_fh, 0, &(final_job->log_job),
-            sizeof(struct darshan_job), MPI_BYTE, &status);
-        if(ret != MPI_SUCCESS)
-        {
-            int msg_len;
-            char msg[MPI_MAX_ERROR_STRING] = {0};
-
-            MPI_Error_string(ret, msg, &msg_len);
-            fprintf(stderr, "darshan library warning: unable to write job data to log file %s: %s\n",
-                    logfile_name, msg);
-            unlink(logfile_name);
-            free(logfile_name);
-            darshan_core_cleanup(final_job);
-            return;
-        }
+        ret = darshan_log_write_header(log_fh, 1, rec_off, psx_off);
     }
 
     DARSHAN_MPI_CALL(PMPI_File_close)(&log_fh);
@@ -823,7 +758,7 @@ static int darshan_get_shared_record_ids(struct darshan_core_runtime *job,
         MPI_BYTE, 0, MPI_COMM_WORLD);
     if(ret != 0)
     {
-        return -1;
+        return(-1);
     }
 
     /* everyone looks to see if they opened the same records as root */
@@ -845,7 +780,7 @@ static int darshan_get_shared_record_ids(struct darshan_core_runtime *job,
         DARSHAN_CORE_MAX_RECORDS, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
     if(ret != 0)
     {
-        return -1;
+        return(-1);
     }
 
     ndx = 0;
@@ -857,14 +792,58 @@ static int darshan_get_shared_record_ids(struct darshan_core_runtime *job,
         }
     }
 
-    return 0;
+    return(0);
+}
+
+static int darshan_log_write_header(MPI_File log_fh, int mod_count,
+    int64_t rec_off, int64_t psx_off)
+{
+    struct darshan_header base_hdr;
+    unsigned char *hdr_buf;
+    unsigned char *tmp_p;
+    int hdr_size;
+    MPI_Status status;
+    int i;
+    int ret;
+
+    /* set the fields of the darshan header */
+    strcpy(base_hdr.version_string, CP_VERSION);
+    base_hdr.magic_nr = CP_MAGIC_NR;
+    base_hdr.comp_type = DARSHAN_GZ_COMP;
+    base_hdr.mod_count = mod_count;
+
+    hdr_size = sizeof(struct darshan_header) + (2 * sizeof(int64_t)); /* TODO: */
+    hdr_buf = malloc(hdr_size);
+    if(!hdr_buf)
+    {
+        return(-1);
+    }
+
+    /* pack the header in buffer for writing */
+    tmp_p = hdr_buf;
+    *((struct darshan_header *)tmp_p) = base_hdr;
+    tmp_p += sizeof(struct darshan_header);
+
+    /* TODO: we need to have a way of identifying different modules in index map */
+    *((int64_t *)tmp_p) = rec_off;
+    tmp_p += sizeof(int64_t);
+    *((int64_t *)tmp_p) = psx_off;
+
+    ret = DARSHAN_MPI_CALL(PMPI_File_write_at)(log_fh, 0, hdr_buf, hdr_size,
+        MPI_BYTE, &status);
+    if(ret < 0)
+    {
+        return(-1);
+    }
+
+    return(0);
 }
 
 /* NOTE: the map written to file may contain duplicate id->name entries if a
  *       record is opened by multiple ranks, but not all ranks
  */
-static int darshan_write_record_map(struct darshan_core_runtime *job, MPI_File log_fh,
-    darshan_record_id *shared_recs)
+static int darshan_log_write_record_map(MPI_File log_fh, struct darshan_core_runtime *job,
+    darshan_record_id *shared_recs, MPI_Offset *off)
 {
     int i;
     int ret;
@@ -897,9 +876,10 @@ static int darshan_write_record_map(struct darshan_core_runtime *job, MPI_File l
     map_buf = malloc(map_buf_sz);
     if(!map_buf)
     {
-        return -1;
+        return(-1);
     }
 
+    /* serialize the record map into a buffer for writing */
     map_buf_off = map_buf;
     HASH_ITER(hlink, job->rec_hash, ref, tmp)
     {
@@ -918,7 +898,7 @@ static int darshan_write_record_map(struct darshan_core_runtime *job, MPI_File l
             if(!tmp_buf)
             {
                 free(map_buf);
-                return -1;
+                return(-1);
             }
 
             memcpy(tmp_buf, map_buf, old_buf_sz);
@@ -943,23 +923,55 @@ static int darshan_write_record_map(struct darshan_core_runtime *job, MPI_File l
     if(map_buf_off > map_buf)
     {
         /* we have records to contribute to the collective write of the record map */
-        ret = DARSHAN_MPI_CALL(PMPI_File_write_all)(log_fh, map_buf, (map_buf_off - map_buf),
-            MPI_BYTE, &status);
+        ret = darshan_log_coll_append(log_fh, off, map_buf, (map_buf_off-map_buf));
     }
     else
     {
         /* we have no data to write, but participate in the collective anyway */
-        ret = DARSHAN_MPI_CALL(PMPI_File_write_all)(log_fh, NULL, 0,
-            MPI_BYTE, &status);
-    }
-    if(ret != MPI_SUCCESS)
-    {
-        return -1;
+        ret = darshan_log_coll_append(log_fh, off, NULL, 0);
     }
 
     free(map_buf);
 
-    return 0;
+    if(ret < 0)
+        return(-1);
+
+    return(0);
+}
+
+/* NOTE: This function assumes that rank 0 passes in the log file offset
+ *       to start appending at, so the caller must make sure rank 0
+ *       has this info. After returning from this function, it is
+ *       guaranteed all ranks will have the ending log file offset.
+ */
+static int darshan_log_coll_append(MPI_File log_fh, MPI_Offset *off,
+    void *buf, int count)
+{
+    MPI_Offset send_off, my_off;
+    MPI_Status status;
+    int ret;
+
+    /* figure out where everyone is writing */
+    send_off = count;
+    if(my_rank == 0)
+        send_off += *off; /* rank 0 knows the beginning offset */
+
+    DARSHAN_MPI_CALL(PMPI_Scan)(&send_off, &my_off, 1, MPI_OFFSET,
+        MPI_SUM, MPI_COMM_WORLD);
+    /* scan in inclusive; subtract local size back out */
+    my_off -= count;
+
+    /* perform the collective write */
+    ret = DARSHAN_MPI_CALL(PMPI_File_write_at_all)(log_fh, my_off, buf,
+        count, MPI_BYTE, &status);
+    if(ret < 0)
+        return(-1);
+
+    *off = my_off + count;
+    /* broadcast the final offset so everyone knows */
+    DARSHAN_MPI_CALL(PMPI_Bcast)(off, 1, MPI_OFFSET, (nprocs-1), MPI_COMM_WORLD);
+
+    return(0);
 }
 
 /* ********************************************************* */
@@ -1052,6 +1064,8 @@ void darshan_core_lookup_record_id(
 
     DARSHAN_CORE_UNLOCK();
 
+    printf("New Darshan record: %s (%"PRIu64")\n", (char *)name, tmp_id);
+
     *id = tmp_id;
     return;
 }
diff --git a/darshan-runtime/lib/darshan-posix.c b/darshan-runtime/lib/darshan-posix.c
index 7ba3ad3..9136d37 100644
--- a/darshan-runtime/lib/darshan-posix.c
+++ b/darshan-runtime/lib/darshan-posix.c
@@ -44,127 +44,8 @@ typedef int64_t off64_t;
 
 #define MAP_OR_FAIL(func)
 
-/* TODO: where do these file record structs go? (some needed for darshan-util) */
-/* TODO: DARSHAN_* OR CP_* */
-
 #define POSIX_MOD_NAME "POSIX"
 
-enum darshan_posix_indices
-{
-    CP_POSIX_READS,              /* count of posix reads */
-    CP_POSIX_WRITES,             /* count of posix writes */
-    CP_POSIX_OPENS,              /* count of posix opens */
-    CP_POSIX_SEEKS,              /* count of posix seeks */
-    CP_POSIX_STATS,              /* count of posix stat/lstat/fstats */
-    CP_POSIX_MMAPS,              /* count of posix mmaps */
-    CP_POSIX_FREADS,
-    CP_POSIX_FWRITES,
-    CP_POSIX_FOPENS,
-    CP_POSIX_FSEEKS,
-    CP_POSIX_FSYNCS,
-    CP_POSIX_FDSYNCS,
-    CP_MODE,                      /* mode of file */
-    CP_BYTES_READ,                /* total bytes read */
-    CP_BYTES_WRITTEN,             /* total bytes written */
-    CP_MAX_BYTE_READ,             /* highest offset byte read */
-    CP_MAX_BYTE_WRITTEN,          /* highest offset byte written */
-    CP_CONSEC_READS,              /* count of consecutive reads */
-    CP_CONSEC_WRITES,             /* count of consecutive writes */
-    CP_SEQ_READS,                 /* count of sequential reads */
-    CP_SEQ_WRITES,                /* count of sequential writes */
-    CP_RW_SWITCHES,               /* number of times switched between read and write */
-    CP_MEM_NOT_ALIGNED,           /* count of accesses not mem aligned */
-    CP_MEM_ALIGNMENT,             /* mem alignment in bytes */
-    CP_FILE_NOT_ALIGNED,          /* count of accesses not file aligned */
-    CP_FILE_ALIGNMENT,            /* file alignment in bytes */
-    CP_MAX_READ_TIME_SIZE,
-    CP_MAX_WRITE_TIME_SIZE,
-    /* buckets */
-    CP_SIZE_READ_0_100,           /* count of posix read size ranges */
-    CP_SIZE_READ_100_1K,
-    CP_SIZE_READ_1K_10K,
-    CP_SIZE_READ_10K_100K,
-    CP_SIZE_READ_100K_1M,
-    CP_SIZE_READ_1M_4M,
-    CP_SIZE_READ_4M_10M,
-    CP_SIZE_READ_10M_100M,
-    CP_SIZE_READ_100M_1G,
-    CP_SIZE_READ_1G_PLUS,
-    /* buckets */
-    CP_SIZE_WRITE_0_100,          /* count of posix write size ranges */
-    CP_SIZE_WRITE_100_1K,
-    CP_SIZE_WRITE_1K_10K,
-    CP_SIZE_WRITE_10K_100K,
-    CP_SIZE_WRITE_100K_1M,
-    CP_SIZE_WRITE_1M_4M,
-    CP_SIZE_WRITE_4M_10M,
-    CP_SIZE_WRITE_10M_100M,
-    CP_SIZE_WRITE_100M_1G,
-    CP_SIZE_WRITE_1G_PLUS,
-    /* counters */
-    CP_STRIDE1_STRIDE,             /* the four most frequently appearing strides */
-    CP_STRIDE2_STRIDE,
-    CP_STRIDE3_STRIDE,
-    CP_STRIDE4_STRIDE,
-    CP_STRIDE1_COUNT,              /* count of each of the most frequent strides */
-    CP_STRIDE2_COUNT,
-    CP_STRIDE3_COUNT,
-    CP_STRIDE4_COUNT,
-    CP_ACCESS1_ACCESS,             /* the four most frequently appearing access sizes */
-    CP_ACCESS2_ACCESS,
-    CP_ACCESS3_ACCESS,
-    CP_ACCESS4_ACCESS,
-    CP_ACCESS1_COUNT,              /* count of each of the most frequent access sizes */
-    CP_ACCESS2_COUNT,
-    CP_ACCESS3_COUNT,
-    CP_ACCESS4_COUNT,
-    CP_DEVICE,                     /* device id reported by stat */
-    CP_SIZE_AT_OPEN,
-    CP_FASTEST_RANK,
-    CP_FASTEST_RANK_BYTES,
-    CP_SLOWEST_RANK,
-    CP_SLOWEST_RANK_BYTES,
-
-    CP_NUM_INDICES,
-};
-
-/* floating point statistics */
-enum darshan_f_posix_indices
-{
-    /* NOTE: adjust cp_normalize_timestamps() function if any TIMESTAMPS are
-     * added or modified in this list
-     */
-    CP_F_OPEN_TIMESTAMP = 0,    /* timestamp of first open */
-    CP_F_READ_START_TIMESTAMP,  /* timestamp of first read */
-    CP_F_WRITE_START_TIMESTAMP, /* timestamp of first write */
-    CP_F_CLOSE_TIMESTAMP,       /* timestamp of last close */
-    CP_F_READ_END_TIMESTAMP,    /* timestamp of last read */
-    CP_F_WRITE_END_TIMESTAMP,   /* timestamp of last write */
-    CP_F_POSIX_READ_TIME,       /* cumulative posix read time */
-    CP_F_POSIX_WRITE_TIME,      /* cumulative posix write time */
-    CP_F_POSIX_META_TIME,       /* cumulative posix meta time */
-    CP_F_MAX_READ_TIME,
-    CP_F_MAX_WRITE_TIME,
-    /* Total I/O and meta time consumed by fastest and slowest ranks, 
-     * reported in either MPI or POSIX time depending on how the file 
-     * was accessed.
-     */
-    CP_F_FASTEST_RANK_TIME,     
-    CP_F_SLOWEST_RANK_TIME,
-    CP_F_VARIANCE_RANK_TIME,
-    CP_F_VARIANCE_RANK_BYTES,
-
-    CP_F_NUM_INDICES,
-};
-
-struct darshan_posix_file
-{
-    darshan_record_id f_id;
-    int64_t rank;
-    int64_t counters[CP_NUM_INDICES];
-    double fcounters[CP_F_NUM_INDICES];
-};
-
 struct posix_runtime_file
 {
     struct darshan_posix_file* file_record;
@@ -191,7 +72,6 @@ struct posix_runtime
 static struct posix_runtime *posix_runtime = NULL;
 static pthread_mutex_t posix_runtime_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
 static int my_rank = -1;
-static int darshan_mem_alignment = 1;
 
 /* these are paths that we will not trace */
 static char* exclusions[] = {
diff --git a/darshan-util/darshan-logutils.c b/darshan-util/darshan-logutils.c
index 9f01aa7..76fe85e 100644
--- a/darshan-util/darshan-logutils.c
+++ b/darshan-util/darshan-logutils.c
@@ -14,6 +14,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <errno.h>
 
 #include <zlib.h>
 #ifdef HAVE_LIBBZ2
@@ -30,15 +31,24 @@ struct darshan_fd_s
     int swap_flag;
     char version[8];
     char* name;
-    /* TODO: ultimately store indices here */
+    int mod_count;
+    int64_t job_off;
+    int64_t rec_off;
+    int64_t mod_off;
+    int64_t end_off;
 };
 
 static int darshan_log_seek(darshan_fd fd, off_t offset);
 static int darshan_log_read(darshan_fd fd, void *buf, int len);
 static int darshan_log_write(darshan_fd fd, void *buf, int len);
-//static const char* darshan_log_error(darshan_fd fd, int* errnum);
 
-/* a rather crude API for accessing raw binary darshan files */
+
+/* darshan_log_open()
+ *
+ * open a darshan log file for reading/writing
+ *
+ * returns 0 on success, -1 on failure
+ */
 darshan_fd darshan_log_open(const char *name, const char *mode)
 {
     int o_flags;
@@ -78,11 +88,20 @@ darshan_fd darshan_log_open(const char *name, const char *mode)
     return(tmp_fd);
 }
 
-int darshan_log_getheader(darshan_fd file, struct darshan_header *header)
+/* darshan_log_getheader()
+ *
+ * read the header of the darshan log and set internal data structures
+ * NOTE: this function must be called before reading other portions of the log
+ *
+ * returns 0 on success, -1 on failure
+ */
+int darshan_log_getheader(darshan_fd fd, struct darshan_header *header)
 {
+    struct stat sbuf;
+    int64_t ndx_buf[2];
     int ret;
 
-    ret = darshan_log_seek(file, 0);
+    ret = darshan_log_seek(fd, 0);
     if(ret < 0)
     {
         fprintf(stderr, "Error: unable to seek in darshan log file.\n");
@@ -90,46 +109,68 @@ int darshan_log_getheader(darshan_fd file, struct darshan_header *header)
     }
 
     /* read header from log file */
-    ret = darshan_log_read(file, header, sizeof(*header));
+    ret = darshan_log_read(fd, header, sizeof(*header));
     if(ret < sizeof(*header))
     {
         fprintf(stderr, "Error: invalid darshan log file (failed to read header).\n");
         return(-1);
     }
 
-    /* save the version string -- this can be used to support multiple log versions */
-    strncpy(file->version, header->version_string, 8);
+    /* save the version string */
+    strncpy(fd->version, header->version_string, 8);
 
     if(header->magic_nr == CP_MAGIC_NR)
     {
         /* no byte swapping needed, this file is in host format already */
-        file->swap_flag = 0;
-        return(0);
+        fd->swap_flag = 0;
+    }
+    else
+    {
+        /* try byte swapping */
+        DARSHAN_BSWAP64(&header->magic_nr);
+        if(header->magic_nr == CP_MAGIC_NR)
+        {
+            fd->swap_flag = 1;
+        }
+        else
+        {
+            /* otherwise this file is just broken */
+            fprintf(stderr, "Error: bad magic number in darshan log file.\n");
+            return(-1);
+        }
     }
 
-    /* try byte swapping */
-    DARSHAN_BSWAP64(&header->magic_nr);
-    if(header->magic_nr == CP_MAGIC_NR)
+    /* read index map from log file */
+    ret = darshan_log_read(fd, ndx_buf, (2*sizeof(int64_t)));
+    if(ret < (2 * sizeof(int64_t)))
     {
-        file->swap_flag = 1;
-        return(0);
+        fprintf(stderr, "Error: invalid darshan log file (failed to read header indexes).\n");
+        return(-1);
     }
 
-    /* otherwise this file is just broken */
-    fprintf(stderr, "Error: bad magic number in darshan log file.\n");
-    return(-1);
+    /* fill index info into darshan file descriptor */
+    fd->job_off = sizeof(struct darshan_header) + (2 * sizeof(int64_t)); /* TODO: */
+    fd->rec_off = ndx_buf[0];
+    fd->mod_off = ndx_buf[1];
+
+    /* use stat to get log file size -- used to help index the log */
+    fstat(fd->pf, &sbuf);
+    fd->end_off = sbuf.st_size;
+
+    return(0);
 }
 
 /* darshan_log_getjob()
  *
+ * read job level metadata from the darshan log file
+ *
  * returns 0 on success, -1 on failure
  */
-int darshan_log_getjob(darshan_fd file, struct darshan_job *job)
+int darshan_log_getjob(darshan_fd fd, struct darshan_job *job)
 {
     int ret;
-    char buffer[DARSHAN_JOB_METADATA_LEN];
 
-    ret = darshan_log_seek(file, sizeof(struct darshan_header));
+    ret = darshan_log_seek(fd, fd->job_off);
     if(ret < 0)
     {
         fprintf(stderr, "Error: unable to seek in darshan log file.\n");
@@ -137,14 +178,14 @@ int darshan_log_getjob(darshan_fd file, struct darshan_job *job)
     }
 
     /* read the job data from the log file */
-    ret = darshan_log_read(file, job, sizeof(*job));
+    ret = darshan_log_read(fd, job, sizeof(*job));
     if(ret < sizeof(*job))
     {
         fprintf(stderr, "Error: invalid darshan log file (failed to read job data).\n");
         return(-1);
     }
 
-    if(file->swap_flag)
+    if(fd->swap_flag)
     {
         /* swap bytes if necessary */
         DARSHAN_BSWAP64(&job->uid);
@@ -157,540 +198,117 @@ int darshan_log_getjob(darshan_fd file, struct darshan_job *job)
     return(0);
 }
 
-int darshan_log_getmap(darshan_fd file, unsigned char **map_buf)
+/* darshan_log_getjob()
+ *
+ * read job level metadata from the darshan log file
+ *
+ * returns 0 on success, -1 on failure
+ */
+int darshan_log_getmap(darshan_fd fd, struct darshan_record_ref **map)
 {
+    int map_size;
+    unsigned char *map_buf;
+    unsigned char *buf_ptr;
+    darshan_record_id *rec_id_ptr;
+    uint32_t *path_len_ptr;
+    char *path_ptr;
+    struct darshan_record_ref *ref;
     int ret;
-    struct stat sbuf;
-    int map_buf_size;
 
-    ret = darshan_log_seek(file, sizeof(struct darshan_header) + CP_JOB_RECORD_SIZE);
+    ret = darshan_log_seek(fd, fd->rec_off);
     if(ret < 0)
     {
         fprintf(stderr, "Error: unable to seek in darshan log file.\n");
         return(ret);
     }
 
-    /* TODO: use indices map rather than stat to determine offsets */
     /* allocate a buffer to store the (serialized) darshan record map */
-    /* NOTE: caller's responsibility to free this allocated map buffer */
-    fstat(file->pf, &sbuf);
-    map_buf_size = sbuf.st_size - (sizeof(struct darshan_header) + CP_JOB_RECORD_SIZE);
-    *map_buf = malloc(map_buf_size);
-    if(!(*map_buf))
+    map_size = fd->mod_off - fd->rec_off;
+    map_buf = malloc(map_size);
+    if(!map_buf)
         return(-1);
 
     /* read the record map from the log file */
-    ret = darshan_log_read(file, *map_buf, map_buf_size);
-    if(ret < map_buf_size)
+    ret = darshan_log_read(fd, map_buf, map_size);
+    if(ret < map_size)
     {
         fprintf(stderr, "Error: invalid darshan log file (failed to read record map).\n");
+        free(map_buf);
         return(-1);
     }
 
-    if(file->swap_flag)
+    buf_ptr = map_buf;
+    while(buf_ptr < (map_buf + map_size))
     {
-        /* we need to sort out endianness issues before passing back the serialized buffer */
+        /* get pointers for each field of this darshan record */
         /* NOTE: darshan record map serialization method: 
          *          ... darshan_record_id | (uint32_t) path_len | path ...
          */
-        unsigned char *buf_ptr = *map_buf;
-        darshan_record_id *rec_id_ptr;
-        uint32_t *path_len_ptr;
-
-        while(buf_ptr < (*map_buf + map_buf_size))
+        rec_id_ptr = (darshan_record_id *)buf_ptr;
+        buf_ptr += sizeof(darshan_record_id);
+        path_len_ptr = (uint32_t *)buf_ptr;
+        buf_ptr += sizeof(uint32_t);
+        path_ptr = (char *)buf_ptr;
+        buf_ptr += *path_len_ptr;
+
+        ref = malloc(sizeof(*ref));
+        if(!ref)
         {
-            rec_id_ptr = (darshan_record_id *)buf_ptr;
-            buf_ptr += sizeof(darshan_record_id);
-            path_len_ptr = (uint32_t *)buf_ptr;
-            buf_ptr += sizeof(uint32_t);
-            buf_ptr += *path_len_ptr;
-
-            DARSHAN_BSWAP64(rec_id_ptr);
-            DARSHAN_BSWAP32(path_len_ptr);
+            free(map_buf);
+            return(-1);
         }
-    }
-
-    return(0);
-}
-
-/* TODO: implement */
-/* TODO: could this could be used in darshan-runtime? do we refactor so we aren't maintaining in 2 spots? */
-int darshan_log_build_map(unsigned char *map_buf, int map_buf_size, some_struct *rec_hash)
-{
-    unsigned char *buf_ptr;
-
-    return(0);
-}
-
-/* TODO: implement */
-/* TODO: could this could be used in darshan-runtime? do we refactor so we aren't maintaining in 2 spots? */
-int darshan_log_destroy_map()
-{
-    return(0);
-}
-
-#if 0
-/* darshan_log_getfile()
- *
- * return 1 if file record found, 0 on eof, and -1 on error
- */
-int darshan_log_getfile(darshan_fd fd, struct darshan_job *job, struct darshan_file *file)
-{
-    int ret;
-
-    ret = getfile_internal(fd, job, file);
-
-    return(ret);
-}
-
-int darshan_log_getexe(darshan_fd fd, char *buf)
-{
-    int ret;
-    char* newline;
-
-    ret = darshan_log_seek(fd, fd->job_struct_size);
-    if(ret < 0)
-        return(ret);
-
-    ret = darshan_log_read(fd, buf, (fd->COMPAT_CP_EXE_LEN + 1));
-    if (ret < (fd->COMPAT_CP_EXE_LEN + 1))
-    {
-        perror("darshan_log_read");
-        return(-1);
-    }
-
-    /* this call is only supposed to return the exe string, but starting in
-     * log format 1.23 there could be a table of mount entry information
-     * after the exe.  Look for newline character and truncate there.
-     */
-    newline = strchr(buf, '\n');
-    if(newline)
-        *newline = '\0';
-
-    return (0);
-}
-#endif
-
-void darshan_log_close(darshan_fd file)
-{
-    if(file->pf)
-        close(file->pf);
-
-    free(file->name);
-    free(file);
-}
-
-#if 0
-/* darshan_log_print_version_warnings()
- *
- * Print summary of any problems with the detected log format
- */
-void darshan_log_print_version_warnings(struct darshan_job *job)
-{
-    if(strcmp(job->version_string, "2.05") == 0)
-    {
-        /* current version */
-        return;
-    }
-
-    if(strcmp(job->version_string, "2.04") == 0)
-    {
-        printf("# WARNING: version 2.04 log format has the following limitations:\n");
-        printf("# - CP_F_SLOWEST_RANK_TIME and CP_F_FASTEST_RANK_TIME only report elapsed time at the POSIX level.\n");
-        return;
-    }
-
-    if(strcmp(job->version_string, "2.03") == 0)
-    {
-        /* no meaningful change to interpretation of log file, 2.03 just
-         * increased the header space available for annotations.
-         */
-        printf("# WARNING: version 2.03 log format has the following limitations:\n");
-        printf("# - CP_F_SLOWEST_RANK_TIME and CP_F_FASTEST_RANK_TIME only report elapsed time at the POSIX level.\n");
-        return;
-    }
-
-    if(strcmp(job->version_string, "2.02") == 0)
-    {
-        printf("# WARNING: version 2.01 log format has the following limitations:\n");
-        printf("# - *_TIMESTAMP fields are not normalized relative to MPI_Init() time.\n");
-        printf("# - CP_F_SLOWEST_RANK_TIME and CP_F_FASTEST_RANK_TIME only report elapsed time at the POSIX level.\n");
-        return;
-    }
-
-    if(strcmp(job->version_string, "2.01") == 0)
-    {
-        printf("# WARNING: version 2.01 log format has the following limitations:\n");
-        printf("# - *_TIMESTAMP fields are not normalized relative to MPI_Init() time.\n");
-        printf("# - inaccurate statistics in some multi-threaded cases.\n");
-        printf("# - CP_F_SLOWEST_RANK_TIME and CP_F_FASTEST_RANK_TIME only report elapsed time at the POSIX level.\n");
-        return;
-    }
-
-    if(strcmp(job->version_string, "2.00") == 0)
-    {
-        printf("# WARNING: version 2.00 log format has the following limitations:\n");
-        printf("# - *_TIMESTAMP fields are not normalized relative to MPI_Init() time.\n");
-        printf("# - inaccurate statistics in some multi-threaded cases.\n");
-        printf("# - CP_F_SLOWEST_RANK_TIME and CP_F_FASTEST_RANK_TIME only report elapsed time at the POSIX level.\n");
-        return;
-    }
- 
-    if(strcmp(job->version_string, "1.24") == 0)
-    {
-        printf("# WARNING: version 1.24 log format does not support the following parameters:\n");
-        printf("#   CP_FASTEST_RANK\n");
-        printf("#   CP_FASTEST_RANK_BYTES\n");
-        printf("#   CP_SLOWEST_RANK\n");
-        printf("#   CP_SLOWEST_RANK_BYTES\n");
-        printf("#   CP_F_FASTEST_RANK_TIME\n");
-        printf("#   CP_F_SLOWEST_RANK_TIME\n");
-        printf("#   CP_F_VARIANCE_RANK_TIME\n");
-        printf("#   CP_F_VARIANCE_RANK_BYTES\n");
-        printf("# WARNING: version 1.24 log format has the following limitations:\n");
-        printf("# - *_TIMESTAMP fields are not normalized relative to MPI_Init() time.\n");
-        printf("# - does not store the job id in the file.\n");
-        printf("# - inaccurate statistics in some multi-threaded cases.\n");
-        printf("# - CP_F_SLOWEST_RANK_TIME and CP_F_FASTEST_RANK_TIME only report elapsed time at the POSIX level.\n");
-        return;
-    }
-    
-    if(strcmp(job->version_string, "1.23") == 0)
-    {
-        printf("# WARNING: version 1.23 log format does not support the following parameters:\n");
-        printf("#   CP_FASTEST_RANK\n");
-        printf("#   CP_FASTEST_RANK_BYTES\n");
-        printf("#   CP_SLOWEST_RANK\n");
-        printf("#   CP_SLOWEST_RANK_BYTES\n");
-        printf("#   CP_F_FASTEST_RANK_TIME\n");
-        printf("#   CP_F_SLOWEST_RANK_TIME\n");
-        printf("#   CP_F_VARIANCE_RANK_TIME\n");
-        printf("#   CP_F_VARIANCE_RANK_BYTES\n");
-        printf("# WARNING: version 1.23 log format has the following limitations:\n");
-        printf("# - *_TIMESTAMP fields are not normalized relative to MPI_Init() time.\n");
-        printf("# - may have incorrect mount point mappings for files with rank > 0.\n");
-        printf("# - does not store the job id in the file.\n");
-        printf("# - inaccurate statistics in some multi-threaded cases.\n");
-        printf("# - CP_F_SLOWEST_RANK_TIME and CP_F_FASTEST_RANK_TIME only report elapsed time at the POSIX level.\n");
-        return;
-    }
-
-    if(strcmp(job->version_string, "1.22") == 0)
-    {
-        printf("# WARNING: version 1.22 log format does not support the following parameters:\n");
-        printf("#   CP_DEVICE\n");
-        printf("#   CP_SIZE_AT_OPEN\n");
-        printf("#   CP_FASTEST_RANK\n");
-        printf("#   CP_FASTEST_RANK_BYTES\n");
-        printf("#   CP_SLOWEST_RANK\n");
-        printf("#   CP_SLOWEST_RANK_BYTES\n");
-        printf("#   CP_F_FASTEST_RANK_TIME\n");
-        printf("#   CP_F_SLOWEST_RANK_TIME\n");
-        printf("#   CP_F_VARIANCE_RANK_TIME\n");
-        printf("#   CP_F_VARIANCE_RANK_BYTES\n");
-        printf("# WARNING: version 1.22 log format has the following limitations:\n");
-        printf("# - *_TIMESTAMP fields are not normalized relative to MPI_Init() time.\n");
-        printf("# - does not record mounted file systems, mount points, or fs types.\n");
-        printf("# - attributes syncs to cumulative metadata time, rather than cumulative write time.\n");
-        printf("# - does not store the job id in the file.\n");
-        printf("# - inaccurate statistics in some multi-threaded cases.\n");
-        printf("# - CP_F_SLOWEST_RANK_TIME and CP_F_FASTEST_RANK_TIME only report elapsed time at the POSIX level.\n");
-        return;
-    }
-
-    if(strcmp(job->version_string, "1.21") == 0)
-    {
-        printf("# WARNING: version 1.21 log format does not support the following parameters:\n");
-        printf("#   CP_INDEP_NC_OPENS\n");
-        printf("#   CP_COLL_NC_OPENS\n");
-        printf("#   CP_HDF5_OPENS\n");
-        printf("#   CP_MAX_READ_TIME_SIZE\n");
-        printf("#   CP_MAX_WRITE_TIME_SIZE\n");
-        printf("#   CP_DEVICE\n");
-        printf("#   CP_SIZE_AT_OPEN\n");
-        printf("#   CP_F_MAX_READ_TIME\n");
-        printf("#   CP_F_MAX_WRITE_TIME\n");
-        printf("#   CP_FASTEST_RANK\n");
-        printf("#   CP_FASTEST_RANK_BYTES\n");
-        printf("#   CP_SLOWEST_RANK\n");
-        printf("#   CP_SLOWEST_RANK_BYTES\n");
-        printf("#   CP_F_FASTEST_RANK_TIME\n");
-        printf("#   CP_F_SLOWEST_RANK_TIME\n");
-        printf("#   CP_F_VARIANCE_RANK_TIME\n");
-        printf("#   CP_F_VARIANCE_RANK_BYTES\n");
-        printf("# WARNING: version 1.21 log format has the following limitations:\n");
-        printf("# - *_TIMESTAMP fields are not normalized relative to MPI_Init() time.\n");
-        printf("# - does not record mounted file systems, mount points, or fs types.\n");
-        printf("# - attributes syncs to cumulative metadata time, rather than cumulative write time.\n");
-        printf("# - does not store the job id in the file.\n");
-        printf("# - inaccurate statistics in some multi-threaded cases.\n");
-        printf("# - CP_F_SLOWEST_RANK_TIME and CP_F_FASTEST_RANK_TIME only report elapsed time at the POSIX level.\n");
-        return;
-    }
-
-    fprintf(stderr, "Error: version %s not supported by parser.\n",
-        job->version_string);
-    return;
-}
-
-/* shift_missing_1_21()
- *
- * translates indices to account for counters that weren't present in log
- * format 1.21
- */
-/*******************************
- * version 1.21 to 2.00 differences 
- * - added:
- *   - CP_INDEP_NC_OPENS
- *   - CP_COLL_NC_OPENS
- *   - CP_HDF5_OPENS
- *   - CP_MAX_READ_TIME_SIZE
- *   - CP_MAX_WRITE_TIME_SIZE
- *   - CP_DEVICE
- *   - CP_SIZE_AT_OPEN
- *   - CP_FASTEST_RANK
- *   - CP_FASTEST_RANK_BYTES
- *   - CP_SLOWEST_RANK
- *   - CP_SLOWEST_RANK_BYTES
- *   - CP_F_MAX_READ_TIME
- *   - CP_F_MAX_WRITE_TIME
- *   - CP_F_FASTEST_RANK_TIME
- *   - CP_F_SLOWEST_RANK_TIME
- *   - CP_F_VARIANCE_RANK_TIME
- *   - CP_F_VARIANCE_RANK_BYTES
- * - changed params:
- *   - CP_FILE_RECORD_SIZE: 1184 to 1328
- *   - CP_NUM_INDICES: 133 to 144
- *   - CP_F_NUM_INDICES: 12 to 18
- */
-static void shift_missing_1_21(struct darshan_file* file)
-{
-    int c_index = 0;
-    int missing_counters[] = {
-        CP_INDEP_NC_OPENS,
-        CP_COLL_NC_OPENS,
-        CP_HDF5_OPENS,
-        CP_MAX_READ_TIME_SIZE,
-        CP_MAX_WRITE_TIME_SIZE,
-        CP_DEVICE,
-        CP_SIZE_AT_OPEN,
-        CP_FASTEST_RANK,
-        CP_FASTEST_RANK_BYTES,
-        CP_SLOWEST_RANK,
-        CP_SLOWEST_RANK_BYTES,
-        -1};
-    int missing_f_counters[] = {
-        CP_F_MAX_READ_TIME,
-        CP_F_MAX_WRITE_TIME,
-        CP_F_FASTEST_RANK_TIME,
-        CP_F_SLOWEST_RANK_TIME,
-        CP_F_VARIANCE_RANK_TIME,
-        CP_F_VARIANCE_RANK_BYTES,
-        -1};
-
-    c_index = 0;
-    while(missing_counters[c_index] != -1)
-    {
-        int missing_counter = missing_counters[c_index];
-        c_index++;
-        if(missing_counter < (CP_NUM_INDICES - 1))
+        ref->rec.name = malloc(*path_len_ptr + 1);
+        if(!ref->rec.name)
         {
-            /* shift down */
-            memmove(&file->counters[missing_counter+1],
-                &file->counters[missing_counter],
-                (CP_NUM_INDICES-missing_counter-1)*sizeof(int64_t));
+            free(map_buf);
+            free(ref);
+            return(-1);
         }
-        /* zero out missing counter */
-        file->counters[missing_counter] = 0;
-    }
 
-    c_index = 0;
-    while(missing_f_counters[c_index] != -1)
-    {
-        int missing_counter = missing_f_counters[c_index];
-        c_index++;
-        if(missing_counter < (CP_F_NUM_INDICES - 1))
+        if(fd->swap_flag)
         {
-            /* shift down */
-            memmove(&file->fcounters[missing_counter+1],
-                &file->fcounters[missing_counter],
-                (CP_F_NUM_INDICES-missing_counter-1)*sizeof(double));
+            /* we need to sort out endianness issues before deserializing */
+            DARSHAN_BSWAP64(rec_id_ptr);
+            DARSHAN_BSWAP32(path_len_ptr);
         }
-        /* zero out missing counter */
-        file->fcounters[missing_counter] = 0;
-    }
 
-    return;
-}
+        /* set the fields for this record */
+        ref->rec.id = *rec_id_ptr;
+        memcpy(ref->rec.name, path_ptr, *path_len_ptr);
+        ref->rec.name[*path_len_ptr] = '\0';
 
-/* shift_missing_1_22()
- *
- * translates indices to account for counters that weren't present in log
- * format 1.22
- */
-/*******************************
- * version 1.22 to 2.00 differences
- *
- * - added:
- *   - CP_DEVICE
- *   - CP_SIZE_AT_OPEN
- *   - CP_FASTEST_RANK
- *   - CP_FASTEST_RANK_BYTES
- *   - CP_SLOWEST_RANK
- *   - CP_SLOWEST_RANK_BYTES
- *   - CP_F_FASTEST_RANK_TIME
- *   - CP_F_SLOWEST_RANK_TIME
- *   - CP_F_VARIANCE_RANK_TIME
- *   - CP_F_VARIANCE_RANK_BYTES
- * - changed params:
- *   - CP_FILE_RECORD_SIZE: 1240 to 1328
- *   - CP_NUM_INDICES: 138 to 144
- *   - CP_F_NUM_INDICES: 14 to 18
- */
-static void shift_missing_1_22(struct darshan_file* file)
-{
-    int c_index = 0;
-    int missing_counters[] = {
-        CP_DEVICE,
-        CP_SIZE_AT_OPEN,
-        CP_FASTEST_RANK,
-        CP_FASTEST_RANK_BYTES,
-        CP_SLOWEST_RANK,
-        CP_SLOWEST_RANK_BYTES,
-        -1};
-    int missing_f_counters[] = {
-        CP_F_FASTEST_RANK_TIME,
-        CP_F_SLOWEST_RANK_TIME,
-        CP_F_VARIANCE_RANK_TIME,
-        CP_F_VARIANCE_RANK_BYTES,
-        -1};
-
-    c_index = 0;
-    while(missing_counters[c_index] != -1)
-    {
-        int missing_counter = missing_counters[c_index];
-        c_index++;
-        if(missing_counter < (CP_NUM_INDICES - 1))
-        {
-            /* shift down */
-            memmove(&file->counters[missing_counter+1],
-                &file->counters[missing_counter],
-                (CP_NUM_INDICES-missing_counter-1)*sizeof(int64_t));
-        }
-        /* zero out missing counter */
-        file->counters[missing_counter] = 0;
+        /* add this record to the hash */
+        HASH_ADD(hlink, *map, rec.id, sizeof(darshan_record_id), ref);
     }
 
-    c_index = 0;
-    while(missing_f_counters[c_index] != -1)
-    {
-        int missing_counter = missing_f_counters[c_index];
-        c_index++;
-        if(missing_counter < (CP_F_NUM_INDICES - 1))
-        {
-            /* shift down */
-            memmove(&file->fcounters[missing_counter+1],
-                &file->fcounters[missing_counter],
-                (CP_F_NUM_INDICES-missing_counter-1)*sizeof(double));
-        }
-        /* zero out missing counter */
-        file->fcounters[missing_counter] = 0;
-    }
+    free(map_buf);
 
-    return;
+    return(0);
 }
 
-/* shift_missing_1_24()
- *
- * translates indices to account for counters that weren't present in log
- * format 1.24
- */
-/*******************************
- * version 1.24 to 2.00 differences
- *
- * - added:
- *   - CP_FASTEST_RANK
- *   - CP_FASTEST_RANK_BYTES
- *   - CP_SLOWEST_RANK
- *   - CP_SLOWEST_RANK_BYTES
- *   - CP_F_FASTEST_RANK_TIME
- *   - CP_F_SLOWEST_RANK_TIME
- *   - CP_F_VARIANCE_RANK_TIME
- *   - CP_F_VARIANCE_RANK_BYTES
- * - changed params:
- *   - CP_FILE_RECORD_SIZE: ? to 1328
- *   - CP_NUM_INDICES: 140 to 144
- *   - CP_F_NUM_INDICES: 14 to 18
+/* TODO: hardcoded for posix -- what can we do generally?
+ *       different function for each module and a way to map to this function?
  */
-static void shift_missing_1_24(struct darshan_file* file)
-{
-    int c_index = 0;
-    int missing_counters[] = {
-        CP_FASTEST_RANK,
-        CP_FASTEST_RANK_BYTES,
-        CP_SLOWEST_RANK,
-        CP_SLOWEST_RANK_BYTES,
-        -1};
-    int missing_f_counters[] = {
-        CP_F_FASTEST_RANK_TIME,
-        CP_F_SLOWEST_RANK_TIME,
-        CP_F_VARIANCE_RANK_TIME,
-        CP_F_VARIANCE_RANK_BYTES,
-        -1};
-
-    c_index = 0;
-    while(missing_counters[c_index] != -1)
-    {
-        int missing_counter = missing_counters[c_index];
-        c_index++;
-        if(missing_counter < (CP_NUM_INDICES - 1))
-        {
-            /* shift down */
-            memmove(&file->counters[missing_counter+1],
-                &file->counters[missing_counter],
-                (CP_NUM_INDICES-missing_counter-1)*sizeof(int64_t));
-        }
-        /* zero out missing counter */
-        file->counters[missing_counter] = 0;
-    }
-
-    c_index = 0;
-    while(missing_f_counters[c_index] != -1)
-    {
-        int missing_counter = missing_f_counters[c_index];
-        c_index++;
-        if(missing_counter < (CP_F_NUM_INDICES - 1))
-        {
-            /* shift down */
-            memmove(&file->fcounters[missing_counter+1],
-                &file->fcounters[missing_counter],
-                (CP_F_NUM_INDICES-missing_counter-1)*sizeof(double));
-        }
-        /* zero out missing counter */
-        file->fcounters[missing_counter] = 0;
-    }
-
-    return;
-}
-
-static int getfile_internal_204(darshan_fd fd, struct darshan_job *job, 
-    struct darshan_file *file)
+int darshan_log_getfile(darshan_fd fd, struct darshan_posix_file *file)
 {
     int ret;
     const char* err_string;
     int i;
 
-    if(fd->pos < CP_JOB_RECORD_SIZE)
+    if(fd->pos < fd->mod_off)
     {
-        ret = darshan_log_seek(fd, CP_JOB_RECORD_SIZE);
+        ret = darshan_log_seek(fd, fd->mod_off);
         if(ret < 0)
+        {
+            fprintf(stderr, "Error: unable to seek in darshan log file.\n");
             return(ret);
+        }
     }
 
     /* reset file record, so that diff compares against a zero'd out record
      * if file is missing
      */
-    memset(file, 0, sizeof(&file));
+    memset(file, 0, sizeof(*file));
 
     ret = darshan_log_read(fd, file, sizeof(*file));
     if(ret == sizeof(*file))
@@ -699,7 +317,7 @@ static int getfile_internal_204(darshan_fd fd, struct darshan_job *job,
         if(fd->swap_flag)
         {
             /* swap bytes if necessary */
-            DARSHAN_BSWAP64(&file->hash);
+            DARSHAN_BSWAP64(&file->f_id);
             DARSHAN_BSWAP64(&file->rank);
             for(i=0; i<CP_NUM_INDICES; i++)
                 DARSHAN_BSWAP64(&file->counters[i]);
@@ -724,198 +342,57 @@ static int getfile_internal_204(darshan_fd fd, struct darshan_job *job,
     }
 
     /* all other errors */
-    err_string = darshan_log_error(fd, &ret);
+    err_string = strerror(errno);
     fprintf(stderr, "Error: %s\n", err_string);
     return(-1);
 }
 
-static int getfile_internal_200(darshan_fd fd, struct darshan_job *job, 
-    struct darshan_file *file)
+#if 0
+int darshan_log_getexe(darshan_fd fd, char *buf)
 {
     int ret;
-    const char* err_string;
-    int i;
-
-    if(fd->pos < CP_JOB_RECORD_SIZE_200)
-    {
-        ret = darshan_log_seek(fd, CP_JOB_RECORD_SIZE_200);
-        if(ret < 0)
-            return(ret);
-    }
-
-    /* reset file record, so that diff compares against a zero'd out record
-     * if file is missing
-     */
-    memset(file, 0, sizeof(&file));
-
-    ret = darshan_log_read(fd, file, sizeof(*file));
-    if(ret == sizeof(*file))
-    {
-        /* got exactly one, correct size record */
-        if(fd->swap_flag)
-        {
-            /* swap bytes if necessary */
-            DARSHAN_BSWAP64(&file->hash);
-            DARSHAN_BSWAP64(&file->rank);
-            for(i=0; i<CP_NUM_INDICES; i++)
-                DARSHAN_BSWAP64(&file->counters[i]);
-            for(i=0; i<CP_F_NUM_INDICES; i++)
-                DARSHAN_BSWAP64(&file->fcounters[i]);
-        }
-        return(1);
-    }
+    char* newline;
 
+    ret = darshan_log_seek(fd, fd->job_struct_size);
+    if(ret < 0)
+        return(ret);
 
-    if(ret > 0)
+    ret = darshan_log_read(fd, buf, (fd->COMPAT_CP_EXE_LEN + 1));
+    if (ret < (fd->COMPAT_CP_EXE_LEN + 1))
     {
-        /* got a short read */
-        fprintf(stderr, "Error: invalid file record (too small)\n");
+        perror("darshan_log_read");
         return(-1);
     }
 
-    if(ret == 0)
-    {
-        /* hit end of file */
-        return(0);
-    }
-
-    /* all other errors */
-    err_string = darshan_log_error(fd, &ret);
-    fprintf(stderr, "Error: %s\n", err_string);
-    return(-1);
-}
-
-static int getfile_internal_124(darshan_fd fd, struct darshan_job *job, 
-    struct darshan_file *file)
-{
-    int ret;
-
-    ret = getfile_internal_1x(fd, job, file, 140, 14);
-    if(ret <= 0)
-        return(ret);
-
-    shift_missing_1_24(file);
-
-    return(1);
-}
-
-static int getfile_internal_122(darshan_fd fd, struct darshan_job *job, 
-    struct darshan_file *file)
-{
-    int ret;
-
-    ret = getfile_internal_1x(fd, job, file, 138, 14);
-    if(ret <= 0)
-        return(ret);
-
-    shift_missing_1_22(file);
+    /* this call is only supposed to return the exe string, but starting in
+     * log format 1.23 there could be a table of mount entry information
+     * after the exe.  Look for newline character and truncate there.
+     */
+    newline = strchr(buf, '\n');
+    if(newline)
+        *newline = '\0';
 
-    return(1);
+    return (0);
 }
+#endif
 
-static int getfile_internal_121(darshan_fd fd, struct darshan_job *job, 
-    struct darshan_file *file)
+/* darshan_log_close()
+ *
+ * close an open darshan file descriptor
+ *
+ * returns 0 on success, -1 on failure
+ */
+void darshan_log_close(darshan_fd fd)
 {
-    int ret;
-
-    ret = getfile_internal_1x(fd, job, file, 133, 12);
-    if(ret <= 0)
-        return(ret);
-
-    shift_missing_1_21(file);
+    if(fd->pf)
+        close(fd->pf);
 
-    return(1);
+    free(fd->name);
+    free(fd);
 }
 
-static int getfile_internal_1x(darshan_fd fd, struct darshan_job *job, 
-    struct darshan_file *file, int n_counters, int n_fcounters)
-{
-    char* buffer;
-    int ret;
-    const char* err_string;
-    int i;
-    uint64_t hash;
-    int32_t rank;
-    int64_t* counters;
-    double* fcounters;
-    char* name_suffix;
-    int FILE_SIZE_1x = (32 + n_counters*8 + n_fcounters*8);
-
-    memset(file, 0, sizeof(*file));
-
-    /* set file pointer if this is the first file record; otherwise pick up
-     * where we left off last time
-     */
-    if(fd->pos < CP_JOB_RECORD_SIZE_1x)
-    {
-        ret = darshan_log_seek(fd, CP_JOB_RECORD_SIZE_1x);
-        if(ret < 0)
-            return(ret);
-    }
-    
-    /* space for file struct, int64 array, and double array */
-    buffer = (char*)malloc(FILE_SIZE_1x);
-    if(!buffer)
-    {
-        return(-1);
-    }
-
-    ret = darshan_log_read(fd, buffer, FILE_SIZE_1x);
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-    if(ret > 0 && ret < FILE_SIZE_1x)
-    {
-        /* got a short read */
-        fprintf(stderr, "Error: invalid file record (too small)\n");
-        free(buffer);
-        return(-1);
-    }
-    else if(ret == 0)
-    {
-        /* hit end of file */
-        free(buffer);
-        return(0);
-    }
-    else if(ret <= 0)
-    {
-        /* all other errors */
-        err_string = darshan_log_error(fd, &ret);
-        fprintf(stderr, "Error: %s\n", err_string);
-        free(buffer);
-        return(-1);
-    }
-
-    /* got exactly one, correct size record */
-    hash = *((int64_t*)&buffer[0]);
-    rank = *((int32_t*)&buffer[8]);
-    counters = ((int64_t*)&buffer[16]);
-    fcounters = ((double*)&buffer[16 + n_counters*8]);
-    name_suffix = &buffer[16 + n_counters*8 + n_fcounters*8];
-
-
-    if(fd->swap_flag)
-    {
-        /* swap bytes if necessary */
-        DARSHAN_BSWAP64(&hash);
-        DARSHAN_BSWAP32(&rank);
-        for(i=0; i<n_counters; i++)
-            DARSHAN_BSWAP64(&counters[i]);
-        for(i=0; i<n_fcounters; i++)
-            DARSHAN_BSWAP64(&fcounters[i]);
-    }
-
-    /* assign into new format */
-    file->hash = hash;
-    file->rank += rank;
-    memcpy(file->counters, counters, n_counters*8);
-    memcpy(file->fcounters, fcounters, n_fcounters*8);
-    memcpy(file->name_suffix, name_suffix, 12);
-
-    free(buffer);
-    return(1);
-}
-#endif
-
-/* ** SDS ** */
 /* return amount written on success, -1 on failure.
  */
 static int darshan_log_write(darshan_fd fd, void* buf, int len)
@@ -933,7 +410,6 @@ static int darshan_log_write(darshan_fd fd, void* buf, int len)
     return(-1);
 }
 
-/* ** SDS ** */
 /* return amount read on success, 0 on EOF, -1 on failure.
  */
 static int darshan_log_read(darshan_fd fd, void* buf, int len)
@@ -951,35 +427,12 @@ static int darshan_log_read(darshan_fd fd, void* buf, int len)
     return(-1);
 }
 
-#if 0
-static const char* darshan_log_error(darshan_fd fd, int* errnum)
-{
-    if(fd->gzf)
-    {
-        return(gzerror(fd->gzf, errnum));
-    }
-
-#ifdef HAVE_LIBBZ2
-    if(fd->bzf)
-    {
-        return(BZ2_bzerror(fd->bzf, errnum));
-    }
-#endif
-
-    *errnum = 0;
-    return(NULL);
-}
-#endif
-
-/* ** SDS ** */
 /* return 0 on successful seek to offset, -1 on failure.
  */
 static int darshan_log_seek(darshan_fd fd, off_t offset)
 {
     off_t ret_off;
 
-    /* TODO: need to look at each use case here -- do I have everything right? */
-
     if(fd->pos == offset)
         return(0);
 
diff --git a/darshan-util/darshan-logutils.h b/darshan-util/darshan-logutils.h
index 2bbc5a9..82043d8 100644
--- a/darshan-util/darshan-logutils.h
+++ b/darshan-util/darshan-logutils.h
@@ -5,39 +5,34 @@
 
 #ifndef __DARSHAN_LOG_UTILS_H
 #define __DARSHAN_LOG_UTILS_H
+
 #include <darshan-log-format.h>
+#include "uthash-1.9.2/src/uthash.h"
 
 typedef struct darshan_fd_s* darshan_fd;
 
+struct darshan_record_ref
+{
+    struct darshan_record rec;
+    UT_hash_handle hlink;
+};
+
 darshan_fd darshan_log_open(const char *name, const char* mode);
 int darshan_log_getheader(darshan_fd file, struct darshan_header *header);
 int darshan_log_getjob(darshan_fd file, struct darshan_job *job);
-int darshan_log_getmap(darshan_fd file, unsigned char **map_buf);
-int darshan_log_build_map(unsigned char *map_buf);
-int darshan_log_destroy_map(void);
+int darshan_log_getmap(darshan_fd file, struct darshan_record_ref **map);
 #if 0
-int darshan_log_putjob(darshan_fd file, struct darshan_job *job);
 int darshan_log_getfile(darshan_fd fd, 
     struct darshan_job* job, 
     struct darshan_file *file);
-int darshan_log_putfile(darshan_fd fd, 
-    struct darshan_job* job, 
-    struct darshan_file *file);
 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,
     int64_t** devs,
     char*** mnt_pts,
     char*** fs_types,
     int* count);
-int darshan_log_putmounts(darshan_fd fd,
-    int64_t* devs,
-    char** mnt_pts,
-    char** fs_types,
-    int count);
 #endif
 void darshan_log_close(darshan_fd file);
-//void darshan_log_print_version_warnings(struct darshan_job *job);
 
 /* convenience macros for printing out counters */
 #define CP_PRINT_HEADER() printf("#<rank>\t<file>\t<counter>\t<value>\t<name suffix>\t<mount pt>\t<fs type>\n")
diff --git a/darshan-util/darshan-posix-parser.c b/darshan-util/darshan-posix-parser.c
new file mode 100644
index 0000000..9240f04
--- /dev/null
+++ b/darshan-util/darshan-posix-parser.c
@@ -0,0 +1,121 @@
+/*
+ *  (C) 2009 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <zlib.h>
+#include <time.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include "darshan-logutils.h"
+#include "uthash-1.9.2/src/uthash.h"
+
+int main(int argc, char **argv)
+{
+    int ret;
+    char *filename;
+    darshan_fd file;
+    struct darshan_header header;
+    struct darshan_job job;
+    struct darshan_record_ref *rec_map = NULL;
+    struct darshan_record_ref *ref, *tmp;
+    struct darshan_posix_file next_rec;
+
+    assert(argc == 2);
+    filename = argv[1];
+
+    struct stat sbuf;
+    stat(filename, &sbuf);
+
+    printf("\nDarshan log file size: %"PRId64"\n", sbuf.st_size);
+    printf("size of header: %"PRId64"\n", sizeof(struct darshan_header));
+    printf("size of index map: %"PRId64"\n", 2*sizeof(int64_t));
+    printf("size of job data: %"PRId64"\n", sizeof(struct darshan_job));
+
+    file = darshan_log_open(filename, "r");
+    if(!file)
+    {
+        fprintf(stderr, "darshan_log_open() failed to open %s\n.", filename);
+        return(-1);
+    }
+
+    /* read the log header */
+    ret = darshan_log_getheader(file, &header);
+    if(ret < 0)
+    {
+        fprintf(stderr, "darshan_log_getheader() failed to read log header.\n");
+        darshan_log_close(file);
+        return(-1);
+    }
+
+    printf("\n*** HEADER DATA ***\n");
+    printf("\tver=%s\n\tmagic_nr=%"PRId64"\n\tcomp_type=%d\n\tmod_count=%d\n",
+        header.version_string, header.magic_nr, header.comp_type, header.mod_count);    
+
+    /* read job info */
+    ret = darshan_log_getjob(file, &job);
+    if(ret < 0)
+    {
+        fprintf(stderr, "darshan_log_getjob() failed to read job data.\n");
+        darshan_log_close(file);
+        return(-1);
+    }
+
+    printf("\n*** JOB DATA ***\n");
+    printf(
+        "\tuid=%"PRId64"\n\tstart_time=%"PRId64"\n\tend_time=%"PRId64"\n\tnprocs=%"PRId64"\n\tjobid=%"PRId64"\n",
+        job.uid, job.start_time, job.end_time, job.nprocs, job.jobid);    
+
+    /* read record map */
+    ret = darshan_log_getmap(file, &rec_map);
+    if(ret < 0)
+    {
+        fprintf(stderr, "darshan_log_getmap() failed to read record map.\n");
+        darshan_log_close(file);
+        return(-1);
+    }
+
+    /* try to retrieve first record (may not exist) */
+    ret = darshan_log_getfile(file, &next_rec);
+    if(ret < 0)
+    {
+        fprintf(stderr, "Error: failed to parse log file.\n");
+        fflush(stderr);
+        return(-1);
+    }
+    if(ret == 0)
+    {
+        /* it looks like the app didn't open any files */
+        printf("# no files opened.\n");
+        darshan_log_close(file);
+        return(0);
+    }
+
+    /* iterate the posix file records stored in the darshan log */
+    printf("\n*** FILE RECORD DATA ***\n");
+    int i = 0;
+    do{
+        struct darshan_record_ref *ref;
+
+        /* get the pathname for this record */
+        HASH_FIND(hlink, rec_map, &next_rec.f_id, sizeof(darshan_record_id), ref);
+        assert(ref);
+
+        printf("\tRecord %d: id=%"PRIu64" (path=%s, rank=%"PRId64")\n",
+            i, next_rec.f_id, ref->rec.name, next_rec.rank);
+
+        i++;
+    } while((ret = darshan_log_getfile(file, &next_rec)) == 1);
+
+    darshan_log_close(file);
+
+    return(0);
+}


hooks/post-receive
--



More information about the Darshan-commits mailing list