<html lang='en'>
<head>
<meta content='text/html; charset=utf-8' http-equiv='Content-Type'>
<title>
GitLab
</title>
</meta>
</head>
<style>
  img {
    max-width: 100%;
    height: auto;
  }
  p.details {
    font-style:italic;
    color:#777
  }
  .footer p {
    font-size:small;
    color:#777
  }
  pre.commit-message {
    white-space: pre-wrap;
  }
  .file-stats a {
    text-decoration: none;
  }
  .file-stats .new-file {
    color: #090;
  }
  .file-stats .deleted-file {
    color: #B00;
  }
</style>
<body>
<div class='content'>
<h3>Shane Snyder pushed to branch mmap-dev at <a href="https://xgitlab.cels.anl.gov/darshan/darshan">darshan / darshan</a></h3>
<h4>
Commits:
</h4>
<ul>
<li>
<strong><a href="https://xgitlab.cels.anl.gov/darshan/darshan/commit/cc498bfadbe820d8e22ce7d94c57a2f062ea0088">cc498bfa</a></strong>
<div>
<span>by Shane Snyder</span>
<i>at 2016-01-14T16:16:55Z</i>
</div>
<pre class='commit-message'>minor reorganization of some runtime code</pre>
</li>
<li>
<strong><a href="https://xgitlab.cels.anl.gov/darshan/darshan/commit/b989ffe4326ac4b8b6e9376a3c69fce7763459bb">b989ffe4</a></strong>
<div>
<span>by Shane Snyder</span>
<i>at 2016-01-14T16:20:15Z</i>
</div>
<pre class='commit-message'>integrate new darshan-diff util in mmap branch</pre>
</li>
</ul>
<h4>7 changed files:</h4>
<ul>
<li class='file-stats'>
<a href='#diff-0'>
darshan-runtime/darshan-core.h
</a>
</li>
<li class='file-stats'>
<a href='#diff-1'>
darshan-runtime/lib/darshan-core.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-2'>
darshan-runtime/lib/darshan-posix.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-3'>
darshan-util/Makefile.in
</a>
</li>
<li class='file-stats'>
<a href='#diff-4'>
darshan-util/darshan-diff.c
</a>
</li>
<li class='file-stats'>
<a href='#diff-5'>
darshan-util/darshan-logutils.h
</a>
</li>
<li class='file-stats'>
<a href='#diff-6'>
darshan-util/darshan-posix-logutils.c
</a>
</li>
</ul>
<h4>Changes:</h4>
<li id='diff-0'>
<a href='https://xgitlab.cels.anl.gov/darshan/darshan/compare/80c07c27781a9680cfa7c001badc2ebe53e6dd00...b989ffe4326ac4b8b6e9376a3c69fce7763459bb#diff-0'>
<strong>
darshan-runtime/darshan-core.h
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/darshan-runtime/darshan-core.h
</span><span style="color: #000000;background-color: #ddffdd">+++ b/darshan-runtime/darshan-core.h
</span><span style="color: #aaaaaa">@@ -10,6 +10,7 @@
</span> #include <unistd.h>
 #include <sys/types.h>
 #include <stdint.h>
<span style="color: #000000;background-color: #ddffdd">+#include <limits.h>
</span> 
 #include "uthash.h"
 #include "darshan-log-format.h"
<span style="color: #aaaaaa">@@ -50,8 +51,8 @@ struct darshan_core_runtime
</span>     void *log_rec_p;
     void *log_mod_p;
 
<span style="color: #000000;background-color: #ddffdd">+    char mmap_log_name[PATH_MAX];
</span>     struct darshan_core_record_ref *rec_hash;
<span style="color: #000000;background-color: #ffdddd">-    int rec_hash_sz;
</span>     int rec_hash_cnt;
     struct darshan_core_module* mod_array[DARSHAN_MAX_MODS];
     char comp_buf[DARSHAN_COMP_BUF_SIZE]; /* TODO: why is this allocated statically? only used in shutdown */
</code></pre>

<br>
</li>
<li id='diff-1'>
<a href='https://xgitlab.cels.anl.gov/darshan/darshan/compare/80c07c27781a9680cfa7c001badc2ebe53e6dd00...b989ffe4326ac4b8b6e9376a3c69fce7763459bb#diff-1'>
<strong>
darshan-runtime/lib/darshan-core.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/darshan-runtime/lib/darshan-core.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/darshan-runtime/lib/darshan-core.c
</span><span style="color: #aaaaaa">@@ -124,7 +124,6 @@ void darshan_core_initialize(int argc, char **argv)
</span>     struct darshan_core_runtime *init_core = NULL;
     int internal_timing_flag = 0;
     double init_start, init_time, init_max;
<span style="color: #000000;background-color: #ffdddd">-    char mmap_log_name[PATH_MAX];
</span>     int mmap_fd;
     int mmap_size;
     int sys_page_size;
<span style="color: #aaaaaa">@@ -171,6 +170,26 @@ void darshan_core_initialize(int argc, char **argv)
</span>             darshan_mem_alignment = 1;
         }
 
<span style="color: #000000;background-color: #ddffdd">+        /* Use DARSHAN_JOBID_OVERRIDE for the env var for __DARSHAN_JOBID */
+        envstr = getenv(DARSHAN_JOBID_OVERRIDE);
+        if(!envstr)
+        {
+            envstr = __DARSHAN_JOBID;
+        }
+
+        /* find a job id */
+        jobid_str = getenv(envstr);
+        if(jobid_str)
+        {
+            /* in cobalt we can find it in env var */
+            ret = sscanf(jobid_str, "%d", &jobid);
+        }
+        if(!jobid_str || ret != 1)
+        {
+            /* use pid as fall back */
+            jobid = getpid();
+        }
+
</span>         /* allocate structure to track darshan core runtime information */
         init_core = malloc(sizeof(*init_core));
         if(init_core)
<span style="color: #aaaaaa">@@ -178,26 +197,6 @@ void darshan_core_initialize(int argc, char **argv)
</span>             memset(init_core, 0, sizeof(*init_core));
             init_core->wtime_offset = DARSHAN_MPI_CALL(PMPI_Wtime)();
 
<span style="color: #000000;background-color: #ffdddd">-            /* Use DARSHAN_JOBID_OVERRIDE for the env var for __DARSHAN_JOBID */
-            envstr = getenv(DARSHAN_JOBID_OVERRIDE);
-            if(!envstr)
-            {
-                envstr = __DARSHAN_JOBID;
-            }
</span>-
<span style="color: #000000;background-color: #ffdddd">-            /* find a job id */
-            jobid_str = getenv(envstr);
-            if(jobid_str)
-            {
-                /* in cobalt we can find it in env var */
-                ret = sscanf(jobid_str, "%d", &jobid);
-            }
-            if(!jobid_str || ret != 1)
-            {
-                /* use pid as fall back */
-                jobid = getpid();
-            }
</span>-
             sys_page_size = sysconf(_SC_PAGESIZE);
             assert(sys_page_size > 0);
 
<span style="color: #aaaaaa">@@ -210,15 +209,15 @@ void darshan_core_initialize(int argc, char **argv)
</span>             /* construct a unique temporary log file name for this process
              * to write mmap log data to
              */
<span style="color: #000000;background-color: #ffdddd">-            snprintf(mmap_log_name, PATH_MAX, "/tmp/darshan_job%d.%d",
</span><span style="color: #000000;background-color: #ddffdd">+            snprintf(init_core->mmap_log_name, PATH_MAX, "/tmp/darshan_job%d.%d",
</span>                 jobid, my_rank);
 
             /* create the temporary mmapped darshan log */
<span style="color: #000000;background-color: #ffdddd">-            mmap_fd = open(mmap_log_name, O_CREAT|O_RDWR|O_EXCL , 0644);
</span><span style="color: #000000;background-color: #ddffdd">+            mmap_fd = open(init_core->mmap_log_name, O_CREAT|O_RDWR|O_EXCL , 0644);
</span>             if(mmap_fd < 0)
             {
                 fprintf(stderr, "darshan library warning: "
<span style="color: #000000;background-color: #ffdddd">-                    "unable to create darshan log file %s\n", mmap_log_name);
</span><span style="color: #000000;background-color: #ddffdd">+                    "unable to create darshan log file %s\n", init_core->mmap_log_name);
</span>                 free(init_core);
                 return;
             }
<span style="color: #aaaaaa">@@ -229,10 +228,10 @@ void darshan_core_initialize(int argc, char **argv)
</span>             if(ret < 0)
             {
                 fprintf(stderr, "darshan library warning: "
<span style="color: #000000;background-color: #ffdddd">-                    "unable to allocate darshan log file %s\n", mmap_log_name);
</span><span style="color: #000000;background-color: #ddffdd">+                    "unable to allocate darshan log file %s\n", init_core->mmap_log_name);
</span>                 free(init_core);
                 close(mmap_fd);
<span style="color: #000000;background-color: #ffdddd">-                unlink(mmap_log_name);
</span><span style="color: #000000;background-color: #ddffdd">+                unlink(init_core->mmap_log_name);
</span>                 return;
             }
 
<span style="color: #aaaaaa">@@ -243,10 +242,10 @@ void darshan_core_initialize(int argc, char **argv)
</span>             if(mmap_p == MAP_FAILED)
             {
                 fprintf(stderr, "darshan library warning: "
<span style="color: #000000;background-color: #ffdddd">-                    "unable to mmap darshan log file %s\n", mmap_log_name);
</span><span style="color: #000000;background-color: #ddffdd">+                    "unable to mmap darshan log file %s\n", init_core->mmap_log_name);
</span>                 free(init_core);
                 close(mmap_fd);
<span style="color: #000000;background-color: #ffdddd">-                unlink(mmap_log_name);
</span><span style="color: #000000;background-color: #ddffdd">+                unlink(init_core->mmap_log_name);
</span>                 return;
             }
 
<span style="color: #aaaaaa">@@ -713,7 +712,8 @@ void darshan_core_shutdown()
</span>         }
     }
 
<span style="color: #000000;background-color: #ffdddd">-    /* TODO: remove temporary log files after successfully creating darshan log */
</span><span style="color: #000000;background-color: #ddffdd">+    /* remove the temporary mmap log files */
+    unlink(final_core->mmap_log_name);
</span> 
     free(logfile_name);
     darshan_core_cleanup(final_core);
<span style="color: #aaaaaa">@@ -996,7 +996,7 @@ static void darshan_add_record_hashref(struct darshan_core_runtime *core,
</span> {
     int record_size = sizeof(darshan_record_id) + strlen(name) + 1;
 
<span style="color: #000000;background-color: #ffdddd">-    if((record_size + core->rec_hash_sz) > DARSHAN_RECORD_BUF_SIZE)
</span><span style="color: #000000;background-color: #ddffdd">+    if((record_size + core->log_hdr_p->rec_map.len) > DARSHAN_RECORD_BUF_SIZE)
</span>         return;
 
     *ref = malloc(sizeof(**ref));
<span style="color: #aaaaaa">@@ -1013,7 +1013,7 @@ static void darshan_add_record_hashref(struct darshan_core_runtime *core,
</span> #endif
         {
             /* store the rec id and full file path in record hash buffer */
<span style="color: #000000;background-color: #ffdddd">-            void *tmp_p = (char *)core->log_rec_p + core->rec_hash_sz;
</span><span style="color: #000000;background-color: #ddffdd">+            void *tmp_p = (char *)core->log_rec_p + core->log_hdr_p->rec_map.len;
</span>             *(darshan_record_id *)tmp_p = id;
 
             /* set the name pointer for this record to point to the
<span style="color: #aaaaaa">@@ -1031,7 +1031,6 @@ static void darshan_add_record_hashref(struct darshan_core_runtime *core,
</span>         /* TODO: look at HASH_ADD_KEYPTR, use same strategy (big contig pool) for non-mmap darshan */
         HASH_ADD(hlink, core->rec_hash, id, sizeof(darshan_record_id), (*ref));
         core->rec_hash_cnt++;
<span style="color: #000000;background-color: #ffdddd">-        core->rec_hash_sz += record_size;
</span>         core->log_hdr_p->rec_map.len += record_size;
     }
 
<span style="color: #aaaaaa">@@ -1454,7 +1453,7 @@ static int darshan_log_write_record_hash(MPI_File log_fh, struct darshan_core_ru
</span> 
     /* collectively write out the record hash to the darshan log */
     ret = darshan_log_append_all(log_fh, core, core->log_rec_p,
<span style="color: #000000;background-color: #ffdddd">-        core->rec_hash_sz, inout_off);
</span><span style="color: #000000;background-color: #ddffdd">+        core->log_hdr_p->rec_map.len, inout_off);
</span> 
     return(ret);
 }
</code></pre>

<br>
</li>
<li id='diff-2'>
<a href='https://xgitlab.cels.anl.gov/darshan/darshan/compare/80c07c27781a9680cfa7c001badc2ebe53e6dd00...b989ffe4326ac4b8b6e9376a3c69fce7763459bb#diff-2'>
<strong>
darshan-runtime/lib/darshan-posix.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/darshan-runtime/lib/darshan-posix.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/darshan-runtime/lib/darshan-posix.c
</span><span style="color: #aaaaaa">@@ -1714,6 +1714,8 @@ static struct posix_file_runtime* posix_file_by_name(const char *name)
</span>         return(file);
     }
 
<span style="color: #000000;background-color: #ddffdd">+    /* TODO: what happens when there are no more records? */
+
</span>     /* no existing record, assign a new file record from the global array */
     file = &(posix_runtime->file_runtime_array[posix_runtime->file_array_ndx]);
     file->file_record = &(posix_runtime->file_record_array[posix_runtime->file_array_ndx]);
</code></pre>

<br>
</li>
<li id='diff-3'>
<a href='https://xgitlab.cels.anl.gov/darshan/darshan/compare/80c07c27781a9680cfa7c001badc2ebe53e6dd00...b989ffe4326ac4b8b6e9376a3c69fce7763459bb#diff-3'>
<strong>
darshan-util/Makefile.in
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/darshan-util/Makefile.in
</span><span style="color: #000000;background-color: #ddffdd">+++ b/darshan-util/Makefile.in
</span><span style="color: #aaaaaa">@@ -1,4 +1,4 @@
</span>-all: libdarshan-util.a darshan-null-logutils.o darshan-analyzer darshan-convert darshan-parser darshan-stitch-logs jenkins-hash-gen
<span style="color: #000000;background-color: #ddffdd">+all: libdarshan-util.a darshan-null-logutils.o darshan-analyzer darshan-convert darshan-diff darshan-parser darshan-stitch-logs jenkins-hash-gen
</span> 
 DESTDIR =
 srcdir = @srcdir@
<span style="color: #aaaaaa">@@ -98,10 +98,8 @@ darshan-analyzer: darshan-analyzer.c darshan-logutils.h $(DARSHAN_LOG_FORMAT) $(
</span> darshan-convert: darshan-convert.c darshan-logutils.h $(DARSHAN_LOG_FORMAT) libdarshan-util.a lookup3.o | uthash-1.9.2
        $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
 
-#darshan-diff: darshan-diff.o $(DARSHAN_LOG_FORMAT) darshan-logutils.o darshan-logutils.h
-#      $(CC) $(CFLAGS)  $(LDFLAGS) $< darshan-logutils.o -o $@ $(LIBS)
-#darshan-diff.o: darshan-diff.c
-#      $(CC) $(CFLAGS) -c  $< -o $@
<span style="color: #000000;background-color: #ddffdd">+darshan-diff: darshan-diff.c darshan-logutils.h $(DARSHAN_LOG_FORMAT) $(DARSHAN_MOD_LOGUTIL_HEADERS) $(DARSHAN_MOD_LOG_FORMATS) libdarshan-util.a | uthash-1.9.2
+       $(CC) $(CFLAGS) $(LDFLAGS) $< libdarshan-util.a -o $@ $(LIBS) 
</span> 
 darshan-parser: darshan-parser.c darshan-logutils.h $(DARSHAN_LOG_FORMAT) $(DARSHAN_MOD_LOGUTIL_HEADERS) $(DARSHAN_MOD_LOG_FORMATS) libdarshan-util.a | uthash-1.9.2
        $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) 
</code></pre>

<br>
</li>
<li id='diff-4'>
<a href='https://xgitlab.cels.anl.gov/darshan/darshan/compare/80c07c27781a9680cfa7c001badc2ebe53e6dd00...b989ffe4326ac4b8b6e9376a3c69fce7763459bb#diff-4'>
<strong>
darshan-util/darshan-diff.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/darshan-util/darshan-diff.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/darshan-util/darshan-diff.c
</span><span style="color: #aaaaaa">@@ -1,149 +1,472 @@
</span> /*
<span style="color: #000000;background-color: #ffdddd">- *  (C) 2009 by Argonne National Laboratory.
- *      See COPYRIGHT in top-level directory.
</span><span style="color: #000000;background-color: #ddffdd">+ * Copyright (C) 2015 University of Chicago.
+ * See COPYRIGHT notice in top-level directory.
+ *
</span>  */
 
 #include <stdio.h>
-#include <zlib.h>
-#include <string.h>
-#include "darshan-log-format.h"
<span style="color: #000000;background-color: #ddffdd">+#include <stdlib.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <assert.h>
+
</span> #include "darshan-logutils.h"
<span style="color: #000000;background-color: #ddffdd">+#include "uthash-1.9.2/src/uthash.h"
+
+#define DEF_MOD_BUF_SIZE 1024 /* 1 KiB is enough for all current mod records ... */
</span> 
<span style="color: #000000;background-color: #ddffdd">+struct darshan_mod_record_ref
+{
+    int rank;
+    char mod_dat[DEF_MOD_BUF_SIZE];
+    struct darshan_mod_record_ref *prev;
+    struct darshan_mod_record_ref *next;
+};
+
+struct darshan_file_record_ref
+{
+    darshan_record_id rec_id;
+    struct darshan_mod_record_ref *mod_recs[DARSHAN_MAX_MODS];
+    UT_hash_handle hlink;
+};
</span> 
-/* utility functions just for darshan-diff */
<span style="color: #000000;background-color: #ddffdd">+static int darshan_build_global_record_hash(
+    darshan_fd fd, struct darshan_file_record_ref **rec_hash);
</span> 
-static void cd_print_str(char * prefix, char * arg1, char *arg2)
<span style="color: #000000;background-color: #ddffdd">+static void print_str_diff(char *prefix, char *arg1, char *arg2)
</span> {
     printf("- %s %s\n", prefix, arg1);
     printf("+ %s %s\n", prefix, arg2);
<span style="color: #000000;background-color: #ddffdd">+    return;
</span> }
-static void cd_print_int(char * prefix, int arg1, int arg2)
-{
<span style="color: #000000;background-color: #ffdddd">-    printf("- %s %d\n", prefix, arg1);
-    printf("+ %s %d\n", prefix, arg2);
</span>-}
-static void cd_print_int64(char * prefix, int64_t arg1, int64_t arg2)
<span style="color: #000000;background-color: #ddffdd">+
+static void print_int64_diff(char *prefix, int64_t arg1, int64_t arg2)
</span> {
     printf("- %s %" PRId64 "\n", prefix, arg1);
     printf("+ %s %" PRId64 "\n", prefix, arg2);
<span style="color: #000000;background-color: #ddffdd">+    return;
</span> }
 
-
-int main(int argc, char ** argv)
<span style="color: #000000;background-color: #ddffdd">+int main(int argc, char *argv[])
</span> {
<span style="color: #000000;background-color: #ddffdd">+    char *logfile1, *logfile2;
</span>     darshan_fd file1, file2;
     struct darshan_job job1, job2;
<span style="color: #000000;background-color: #ffdddd">-    struct darshan_file cp_file1, cp_file2;
</span>     char exe1[4096], exe2[4096];
<span style="color: #000000;background-color: #ffdddd">-    int i, ret1,ret2;
</span><span style="color: #000000;background-color: #ddffdd">+    struct darshan_record_ref *name_hash1 = NULL, *name_hash2 = NULL;
+    struct darshan_record_ref *name_ref1, *name_ref2;
+    struct darshan_file_record_ref *rec_hash1 = NULL, *rec_hash2 = NULL;
+    struct darshan_file_record_ref *rec_ref1, *rec_ref2, *rec_tmp;
+    struct darshan_mod_record_ref *mod_rec1, *mod_rec2;
+    void *mod_buf1, *mod_buf2;
+    struct darshan_base_record *base_rec1, *base_rec2;
+    char *file_name1, *file_name2;
+    int i;
+    int ret;
</span> 
<span style="color: #000000;background-color: #ffdddd">-    if (argc != 3)
</span><span style="color: #000000;background-color: #ddffdd">+    if(argc != 3)
</span>     {
<span style="color: #000000;background-color: #ffdddd">-        fprintf(stderr, "Usage: %s <file1> <file2>\n", argv[0]);
</span><span style="color: #000000;background-color: #ddffdd">+        fprintf(stderr, "Usage: darshan-diff <logfile1> <logfile2>\n");
</span>         return(-1);
     }
 
<span style="color: #000000;background-color: #ffdddd">-    file1 = darshan_log_open(argv[1], "r");
-    if(!file1) {
-        fprintf(stderr, "darshan_log_open() failed to open %s\n.", argv[1]);
</span><span style="color: #000000;background-color: #ddffdd">+    logfile1 = argv[1];
+    logfile2 = argv[2];
+
+    file1 = darshan_log_open(logfile1);
+    if(!file1)
+    {
+        fprintf(stderr, "Error: unable to open darshan log file %s.\n", logfile1);
</span>         return(-1);
     }
<span style="color: #000000;background-color: #ffdddd">-    file2 = darshan_log_open(argv[2], "r");
-    if(!file2) {
-        fprintf(stderr, "darshan_log_open() failed to open %s\n.", argv[2]);
</span><span style="color: #000000;background-color: #ddffdd">+
+    file2 = darshan_log_open(logfile2);
+    if(!file2)
+    {
+        darshan_log_close(file1);
+        fprintf(stderr, "Error: unable to open darshan log file %s.\n", logfile2);
</span>         return(-1);
     }
 
<span style="color: #000000;background-color: #ffdddd">-    if (darshan_log_getjob(file1, &job1))
</span><span style="color: #000000;background-color: #ddffdd">+    /* get job data for each log file */
+    ret = darshan_log_getjob(file1, &job1);
+    if(ret < 0)
</span>     {
         darshan_log_close(file1);
<span style="color: #000000;background-color: #ddffdd">+        darshan_log_close(file2);
+        fprintf(stderr, "Error: unable to read job info for darshan log file %s.\n", logfile1);
</span>         return(-1);
     }
<span style="color: #000000;background-color: #ffdddd">-    if (darshan_log_getjob(file2, &job2))
</span><span style="color: #000000;background-color: #ddffdd">+
+    ret = darshan_log_getjob(file2, &job2);
+    if(ret < 0)
</span>     {
<span style="color: #000000;background-color: #ddffdd">+        darshan_log_close(file1);
</span>         darshan_log_close(file2);
<span style="color: #000000;background-color: #ddffdd">+        fprintf(stderr, "Error: unable to read job info for darshan log file %s.\n", logfile2);
</span>         return(-1);
     }
 
<span style="color: #000000;background-color: #ffdddd">-    if (darshan_log_getexe(file1, exe1))
</span><span style="color: #000000;background-color: #ddffdd">+    /* get exe string for each log file */
+    ret = darshan_log_getexe(file1, exe1);
+    if(ret < 0)
</span>     {
         darshan_log_close(file1);
<span style="color: #000000;background-color: #ddffdd">+        darshan_log_close(file2);
+        fprintf(stderr, "Error: unable to read exe for darshan log file %s.\n", logfile1);
</span>         return(-1);
     }
<span style="color: #000000;background-color: #ffdddd">-    if (darshan_log_getexe(file2, exe2))
</span><span style="color: #000000;background-color: #ddffdd">+
+    ret = darshan_log_getexe(file2, exe2);
+    if(ret < 0)
</span>     {
<span style="color: #000000;background-color: #ddffdd">+        darshan_log_close(file1);
</span>         darshan_log_close(file2);
<span style="color: #000000;background-color: #ddffdd">+        fprintf(stderr, "Error: unable to read exe for darshan log file %s.\n", logfile2);
</span>         return(-1);
     }
 
<span style="color: #000000;background-color: #ffdddd">-    if (strcmp(exe1, exe2)) 
-        cd_print_str("# exe: ", exe1, exe2);
</span><span style="color: #000000;background-color: #ddffdd">+    /* print diff of exe and job data */
+    if (strcmp(exe1, exe2))
+        print_str_diff("# exe: ", exe1, exe2);
</span> 
     if (job1.uid != job2.uid)
<span style="color: #000000;background-color: #ffdddd">-        cd_print_int("# uid:", job1.uid, job2.uid);
</span><span style="color: #000000;background-color: #ddffdd">+        print_int64_diff("# uid:", job1.uid, job2.uid);
</span>     if (job1.start_time != job2.start_time)
<span style="color: #000000;background-color: #ffdddd">-        cd_print_int64("# start_time:", 
-                (int64_t)job1.start_time, (int64_t)job2.start_time);
-    if (job1.end_time!= job2.end_time)
-        cd_print_int64("# end_time:", 
-                (int64_t)job1.end_time,(int64_t)job2.end_time);
-    if (job1.nprocs!= job2.nprocs)
-        cd_print_int("# nprocs:", job1.nprocs, job2.nprocs);
</span><span style="color: #000000;background-color: #ddffdd">+        print_int64_diff("# start_time:", job1.start_time, job2.start_time);
+    if (job1.end_time != job2.end_time)
+        print_int64_diff("# end_time:", job1.end_time, job2.end_time);
+    if (job1.nprocs != job2.nprocs)
+        print_int64_diff("# nprocs:", job1.nprocs, job2.nprocs);
</span>     if ((job1.end_time-job1.start_time) != (job2.end_time - job2.start_time))
<span style="color: #000000;background-color: #ffdddd">-        cd_print_int64("# run time:", 
-                (int64_t)(job1.end_time - job1.start_time +1),
</span><span style="color: #000000;background-color: #ddffdd">+        print_int64_diff("# run time:",
+                (int64_t)(job1.end_time - job1.start_time + 1),
</span>                 (int64_t)(job2.end_time - job2.start_time + 1));
 
<span style="color: #000000;background-color: #ffdddd">-    /* if for some reason no files were accessed, then we'll have to fix-up the
-     * buffers in the while loop */
</span>-
<span style="color: #000000;background-color: #ffdddd">-    do {
-        ret1 = darshan_log_getfile(file1, &job1, &cp_file1);
</span>-  if (ret1 < 0) 
-       {
-               perror("darshan_log_getfile");
-               darshan_log_close(file1);
-               return(-1);
-       }
<span style="color: #000000;background-color: #ffdddd">-        ret2 = darshan_log_getfile(file2, &job2, &cp_file2);
</span>-  if (ret2 < 0) 
-       {
-               perror("darshan_log_getfile");
-               darshan_log_close(file2);
-               return(-1);
-       }
-
<span style="color: #000000;background-color: #ffdddd">-        for(i=0; i<CP_NUM_INDICES; i++) {
-            if (cp_file1.counters[i] != cp_file2.counters[i]) {
</span>-          printf("- ");
-               printf("%" PRId64 "\t%" PRIu64 "\t%s\t%" PRId64 "\t...%s\n",
-                       cp_file1.rank, cp_file1.hash, darshan_names[i], 
-                       cp_file1.counters[i], cp_file1.name_suffix);
-               printf("+ ");
-               printf("%" PRId64 "\t%" PRIu64 "\t%s\t%" PRId64 "\t...%s\n",
-                       cp_file2.rank, cp_file2.hash, darshan_names[i], 
-                       cp_file2.counters[i], cp_file2.name_suffix);
<span style="color: #000000;background-color: #ddffdd">+    /* get hash of record ids to file names for each log */
+    ret = darshan_log_gethash(file1, &name_hash1);
+    if(ret < 0)
+    {
+        darshan_log_close(file1);
+        darshan_log_close(file2);
+        fprintf(stderr, "Error: unable to read record hash for darshan log file %s.\n", logfile1);
+        return(-1);
+    }
+
+    ret = darshan_log_gethash(file2, &name_hash2);
+    if(ret < 0)
+    {
+        darshan_log_close(file1);
+        darshan_log_close(file2);
+        fprintf(stderr, "Error: unable to read record hash for darshan log file %s.\n", logfile2);
+        return(-1);
+    }
+
+    /* build hash tables of all records opened by all modules for each darshan log file */
+    ret = darshan_build_global_record_hash(file1, &rec_hash1);
+    if(ret < 0)
+    {
+        fprintf(stderr, "Error: unable to build record hash for darshan log file %s.\n", logfile1);
+        darshan_log_close(file1);
+        darshan_log_close(file2);
+        return(-1);
+    }
+
+    ret = darshan_build_global_record_hash(file2, &rec_hash2);
+    if(ret < 0)
+    {
+        fprintf(stderr, "Error: unable to build record hash for darshan log file %s.\n", logfile2);
+        darshan_log_close(file1);
+        darshan_log_close(file2);
+        return(-1);
+    }
+
+    /* iterate records for the first log file and correlate/diff with records from
+     * the second log file
+     */
+    HASH_ITER(hlink, rec_hash1, rec_ref1, rec_tmp)
+    {
+        printf("\n");
+
+        /* search hash2 for this record */
+        HASH_FIND(hlink, rec_hash2, &(rec_ref1->rec_id), sizeof(darshan_record_id), rec_ref2);
+
+        for(i = 0; i < DARSHAN_MAX_MODS; i++)
+        {
+#if 0
+            /* TODO: skip modules that don't have the same format version, for now */
+            if(rec_ref1->mod_recs[i] && rec_ref2 && rec_ref2->mod_recs[i] &&
+                (file1->mod_ver[i] != file2->mod_ver[i]))
+            {
+                fprintf(stderr, "Warning: skipping %s module data due to incompatible"
+                    "version numbers (file1=%d, file2=%d).\n",
+                    darshan_module_names[i], file1->mod_ver[i], file2->mod_ver[i]);
+                continue;
</span>             }
<span style="color: #000000;background-color: #ffdddd">-        }
-        for(i=0; i<CP_F_NUM_INDICES; i++) {
-            if (cp_file1.fcounters[i] != cp_file2.fcounters[i]) {
</span>-          printf("- ");
-               printf("%" PRId64 "\t%" PRIu64 "\t%s\t%f\t...%s\n",
-                       cp_file1.rank, cp_file1.hash, darshan_f_names[i], 
-                       cp_file1.fcounters[i], cp_file1.name_suffix);
-               printf("+ ");
-               printf("%" PRId64 "\t%" PRIu64 "\t%s\t%f\t...%s\n",
-                       cp_file2.rank, cp_file2.hash, darshan_f_names[i], 
-                       cp_file2.fcounters[i], cp_file2.name_suffix);
<span style="color: #000000;background-color: #ddffdd">+#endif
+
+            while(1)
+            {
+                mod_rec1 = rec_ref1->mod_recs[i];
+                if(rec_ref2)
+                    mod_rec2 = rec_ref2->mod_recs[i];
+                else
+                    mod_rec2 = NULL;
+
+                if(mod_rec1 == NULL)
+                    mod_buf1 = NULL;
+                else
+                    mod_buf1 = mod_rec1->mod_dat;
+                if(mod_rec2 == NULL)
+                    mod_buf2 = NULL;
+                else
+                    mod_buf2 = mod_rec2->mod_dat;
+
+                base_rec1 = (struct darshan_base_record *)mod_buf1;
+                base_rec2 = (struct darshan_base_record *)mod_buf2;
+
+                if(!base_rec1 && !base_rec2)
+                {
+                    /* break out if there are no more records for this module */
+                    break;
+                }
+                else if(base_rec1 && base_rec2)
+                {
+                    /* make sure if we have module records for this darshan record
+                     * from both log files, that we are performing the diff rank-by-rank
+                     * (i.e., we diff rank 1 records together, rank 2 records together,
+                     * and so on)
+                     */
+                    if(base_rec1->rank < base_rec2->rank)
+                        mod_buf2 = NULL;
+                    else if(base_rec1->rank > base_rec2->rank)
+                        mod_buf1 = NULL;
+                }
+
+                /* get corresponding file name for each record */
+                if(mod_buf1)
+                {
+                    HASH_FIND(hlink, name_hash1, &(base_rec1->f_id),
+                        sizeof(darshan_record_id), name_ref1);
+                    assert(name_ref1);
+                    file_name1 = name_ref1->name;
+                }
+                if(mod_buf2)
+                {
+                    HASH_FIND(hlink, name_hash2, &(base_rec2->f_id),
+                        sizeof(darshan_record_id), name_ref2);
+                    assert(name_ref2);
+                    file_name2 = name_ref2->name;
+                }
+
+                mod_logutils[i]->log_print_diff(mod_buf1, file_name1, mod_buf2, file_name2);
+
+                /* remove records which we have diffed already */
+                if(mod_buf1)
+                {
+                    if(mod_rec1->next == mod_rec1)
+                    {
+                        rec_ref1->mod_recs[i] = NULL;
+                    }
+                    else
+                    {
+                        mod_rec1->prev->next = mod_rec1->next;
+                        mod_rec1->next->prev = mod_rec1->prev;
+                        rec_ref1->mod_recs[i] = mod_rec1->next;
+                    }
+                    free(mod_rec1);
+                }
+                if(mod_buf2)
+                {
+                    if(mod_rec2->next == mod_rec2)
+                    {
+                        rec_ref2->mod_recs[i] = NULL;
+                    }
+                    else
+                    {
+                        mod_rec2->prev->next = mod_rec2->next;
+                        mod_rec2->next->prev = mod_rec2->prev;
+                        rec_ref2->mod_recs[i] = mod_rec2->next;
+                    }
+                    free(mod_rec2);
+                }
</span>             }
         }
 
<span style="color: #000000;background-color: #ddffdd">+        HASH_DELETE(hlink, rec_hash1, rec_ref1);
+        free(rec_ref1);
+        if(rec_ref2)
+        {
+            HASH_DELETE(hlink, rec_hash2, rec_ref2);
+            free(rec_ref2);
+        }
+    }
</span> 
<span style="color: #000000;background-color: #ffdddd">-    } while (ret1 == 1 || ret2 == 1);
</span><span style="color: #000000;background-color: #ddffdd">+    /* iterate any remaning records from the 2nd log file and print the diff output --
+     * NOTE: that these records do not have corresponding records in the first log file
+     */
+    HASH_ITER(hlink, rec_hash2, rec_ref2, rec_tmp)
+    {
+        printf("\n");
+
+        for(i = 0; i < DARSHAN_MAX_MODS; i++)
+        {
+            while(rec_ref2->mod_recs[i])
+            {
+                mod_rec2 = rec_ref2->mod_recs[i];
+                base_rec2 = (struct darshan_base_record *)mod_rec2->mod_dat;
+
+                HASH_FIND(hlink, name_hash2, &(base_rec2->f_id),
+                    sizeof(darshan_record_id), name_ref2);
+                assert(name_ref2);
+                file_name2 = name_ref2->name;
</span> 
<span style="color: #000000;background-color: #ddffdd">+                mod_logutils[i]->log_print_diff(NULL, NULL, mod_rec2->mod_dat, file_name2);
+                
+                /* remove the record we just diffed */
+                if(mod_rec2->next == mod_rec2)
+                {
+                    rec_ref2->mod_recs[i] = NULL;
+                }
+                else
+                {
+                    mod_rec2->prev->next = mod_rec2->next;
+                    mod_rec2->next->prev = mod_rec2->prev;
+                    rec_ref2->mod_recs[i] = mod_rec2->next;
+                }
+                free(mod_rec2);
+            }
+        }
+
+        HASH_DELETE(hlink, rec_hash2, rec_ref2);
+        free(rec_ref2);
+    }
+
+    HASH_ITER(hlink, name_hash1, name_ref1, name_ref2)
+    {
+        HASH_DELETE(hlink, name_hash1, name_ref1);
+        free(name_ref1->name);
+        free(name_ref1);
+    }
+    HASH_ITER(hlink, name_hash2, name_ref2, name_ref1)
+    {
+        HASH_DELETE(hlink, name_hash2, name_ref2);
+        free(name_ref2->name);
+        free(name_ref2);
+    }
</span> 
     darshan_log_close(file1);
     darshan_log_close(file2);
<span style="color: #000000;background-color: #ddffdd">+
+    return(0);
+}
+
+static int darshan_build_global_record_hash(
+    darshan_fd fd, struct darshan_file_record_ref **rec_hash)
+{
+    struct darshan_mod_record_ref *mod_rec;
+    struct darshan_file_record_ref *file_rec;
+    darshan_record_id tmp_rec_id;
+    struct darshan_base_record *base_rec;
+    int i;
+    int ret;
+
+    /* iterate over all modules in each log file, adding records to the
+     * appropriate hash table
+     */
+    for(i = 0; i < DARSHAN_MAX_MODS; i++)
+    {
+        while(1)
+        {
+            if(!mod_logutils[i]) break;
+
+            mod_rec = malloc(sizeof(struct darshan_mod_record_ref));
+            assert(mod_rec);
+            memset(mod_rec, 0, sizeof(struct darshan_mod_record_ref));
+
+            ret = mod_logutils[i]->log_get_record(fd, mod_rec->mod_dat);
+            if(ret < 0)
+            {
+                fprintf(stderr, "Error: unable to read module %s data from log file.\n",
+                    darshan_module_names[i]);
+                free(mod_rec);
+                return(-1);
+            }
+            else if(ret == 0)
+            {
+                free(mod_rec);
+                break;
+            }
+            else
+            {
+                base_rec = (struct darshan_base_record *)mod_rec->mod_dat;
+                mod_rec->rank = base_rec->rank;
+
+                HASH_FIND(hlink, *rec_hash, &tmp_rec_id, sizeof(darshan_record_id), file_rec);
+                if(!file_rec)
+                {
+                    /* there is no entry in the global hash table of darshan records
+                     * for this log file, so create one and add it.
+                     */
+                    file_rec = malloc(sizeof(struct darshan_file_record_ref));
+                    assert(file_rec);
+
+                    memset(file_rec, 0, sizeof(struct darshan_file_record_ref));
+                    file_rec->rec_id = tmp_rec_id;
+                    HASH_ADD(hlink, *rec_hash, rec_id, sizeof(darshan_record_id), file_rec);
+
+                }
+
+                /* add new record into the linked list of this module's records */
+                if(file_rec->mod_recs[i])
+                {
+                    /* there is already an initialized linked list for this module */
+
+                    /* we start at the end of the list and work backwards to insert this
+                     * record (the list is sorted according to increasing ranks, and in
+                     * general, darshan log records are sorted according to increasing
+                     * ranks, as well)
+                     */
+                    struct darshan_mod_record_ref *tmp_mod_rec = file_rec->mod_recs[i]->prev;
+                    while(1)
+                    {
+                        if(mod_rec->rank > tmp_mod_rec->rank)
+                        {
+                            /* insert new module record after this record */
+                            mod_rec->prev = tmp_mod_rec;
+                            mod_rec->next = tmp_mod_rec->next;
+                            tmp_mod_rec->next->prev = mod_rec;
+                            tmp_mod_rec->next = mod_rec;
+                            break;
+                        }
+                        else if(mod_rec->rank < tmp_mod_rec->rank)
+                        {
+                            /* insert new module record before this record */
+                            mod_rec->prev = tmp_mod_rec->prev;
+                            mod_rec->next = tmp_mod_rec;
+                            tmp_mod_rec->prev->next = mod_rec;
+                            tmp_mod_rec->prev = mod_rec;
+                            if(file_rec->mod_recs[i] == mod_rec->next)
+                                file_rec->mod_recs[i] = mod_rec;
+                            break;
+                        }
+
+                        tmp_mod_rec = tmp_mod_rec->prev;
+                        assert(tmp_mod_rec != file_rec->mod_recs[i]);
+                    }
+                }
+                else
+                {
+                    /* there are currently no records for this module, so just
+                     * initialize a new linked list
+                     */
+                    mod_rec->prev = mod_rec->next = mod_rec;
+                    file_rec->mod_recs[i] = mod_rec;
+                }
+            }
+        }
+    }
+
</span>     return(0);
 }
 
</code></pre>

<br>
</li>
<li id='diff-5'>
<a href='https://xgitlab.cels.anl.gov/darshan/darshan/compare/80c07c27781a9680cfa7c001badc2ebe53e6dd00...b989ffe4326ac4b8b6e9376a3c69fce7763459bb#diff-5'>
<strong>
darshan-util/darshan-logutils.h
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/darshan-util/darshan-logutils.h
</span><span style="color: #000000;background-color: #ddffdd">+++ b/darshan-util/darshan-logutils.h
</span><span style="color: #aaaaaa">@@ -81,6 +81,13 @@ struct darshan_mod_logutil_funcs
</span>         void *agg_rec,
         int init_flag
     );
<span style="color: #000000;background-color: #ddffdd">+        /* print a text diff of 2 module I/O records */
+    void (*log_print_diff)(
+        void *rec1,
+        char *name1,
+        void *rec2,
+        char *name2
+    );
</span> };
 
 extern struct darshan_mod_logutil_funcs *mod_logutils[];
</code></pre>

<br>
</li>
<li id='diff-6'>
<a href='https://xgitlab.cels.anl.gov/darshan/darshan/compare/80c07c27781a9680cfa7c001badc2ebe53e6dd00...b989ffe4326ac4b8b6e9376a3c69fce7763459bb#diff-6'>
<strong>
darshan-util/darshan-posix-logutils.c
</strong>
</a>
<hr>
<pre class="highlight"><code><span style="color: #000000;background-color: #ffdddd">--- a/darshan-util/darshan-posix-logutils.c
</span><span style="color: #000000;background-color: #ddffdd">+++ b/darshan-util/darshan-posix-logutils.c
</span><span style="color: #aaaaaa">@@ -35,13 +35,16 @@ static int darshan_log_put_posix_file(darshan_fd fd, void* posix_buf);
</span> static void darshan_log_print_posix_file(void *file_rec,
     char *file_name, char *mnt_pt, char *fs_type);
 static void darshan_log_agg_posix_files(void *rec, void *agg_rec, int init_flag);
<span style="color: #000000;background-color: #ddffdd">+static void darshan_log_print_posix_file_diff(void *file_rec1, char *file_name1,
+    void *file_rec2, char *file_name2);
</span> 
 struct darshan_mod_logutil_funcs posix_logutils =
 {
     .log_get_record = &darshan_log_get_posix_file,
     .log_put_record = &darshan_log_put_posix_file,
     .log_print_record = &darshan_log_print_posix_file,
<span style="color: #000000;background-color: #ffdddd">-    .log_agg_records = &darshan_log_agg_posix_files
</span><span style="color: #000000;background-color: #ddffdd">+    .log_agg_records = &darshan_log_agg_posix_files,
+    .log_print_diff = &darshan_log_print_posix_file_diff
</span> };
 
 static int darshan_log_get_posix_file(darshan_fd fd, void* posix_buf)
<span style="color: #aaaaaa">@@ -297,6 +300,78 @@ static void darshan_log_agg_posix_files(void *rec, void *agg_rec, int init_flag)
</span>     return;
 }
 
<span style="color: #000000;background-color: #ddffdd">+static void darshan_log_print_posix_file_diff(void *file_rec1, char *file_name1,
+    void *file_rec2, char *file_name2)
+{
+    struct darshan_posix_file *file1 = (struct darshan_posix_file *)file_rec1;
+    struct darshan_posix_file *file2 = (struct darshan_posix_file *)file_rec2;
+    int i;
+
+    /* NOTE: we assume that both input records are the same module format version */
+
+    for(i=0; i<POSIX_NUM_INDICES; i++)
+    {
+        if(!file2)
+        {
+            printf("- ");
+            DARSHAN_COUNTER_PRINT(darshan_module_names[DARSHAN_POSIX_MOD],
+                file1->base_rec.rank, file1->base_rec.id, posix_counter_names[i],
+                file1->counters[i], file_name1, "", "");
+
+        }
+        else if(!file1)
+        {
+            printf("+ ");
+            DARSHAN_COUNTER_PRINT(darshan_module_names[DARSHAN_POSIX_MOD],
+                file2->base_rec.rank, file2->base_rec.id, posix_counter_names[i],
+                file2->counters[i], file_name2, "", "");
+        }
+        else if(file1->counters[i] != file2->counters[i])
+        {
+            printf("- ");
+            DARSHAN_COUNTER_PRINT(darshan_module_names[DARSHAN_POSIX_MOD],
+                file1->base_rec.rank, file1->base_rec.id, posix_counter_names[i],
+                file1->counters[i], file_name1, "", "");
+            printf("+ ");
+            DARSHAN_COUNTER_PRINT(darshan_module_names[DARSHAN_POSIX_MOD],
+                file2->base_rec.rank, file2->base_rec.id, posix_counter_names[i],
+                file2->counters[i], file_name2, "", "");
+        }
+    }
+
+    for(i=0; i<POSIX_F_NUM_INDICES; i++)
+    {
+        if(!file2)
+        {
+            printf("- ");
+            DARSHAN_F_COUNTER_PRINT(darshan_module_names[DARSHAN_POSIX_MOD],
+                file1->base_rec.rank, file1->base_rec.id, posix_f_counter_names[i],
+                file1->fcounters[i], file_name1, "", "");
+
+        }
+        else if(!file1)
+        {
+            printf("+ ");
+            DARSHAN_F_COUNTER_PRINT(darshan_module_names[DARSHAN_POSIX_MOD],
+                file2->base_rec.rank, file2->base_rec.id, posix_f_counter_names[i],
+                file2->fcounters[i], file_name2, "", "");
+        }
+        else if(file1->fcounters[i] != file2->fcounters[i])
+        {
+            printf("- ");
+            DARSHAN_F_COUNTER_PRINT(darshan_module_names[DARSHAN_POSIX_MOD],
+                file1->base_rec.rank, file1->base_rec.id, posix_f_counter_names[i],
+                file1->fcounters[i], file_name1, "", "");
+            printf("+ ");
+            DARSHAN_F_COUNTER_PRINT(darshan_module_names[DARSHAN_POSIX_MOD],
+                file2->base_rec.rank, file2->base_rec.id, posix_f_counter_names[i],
+                file2->fcounters[i], file_name2, "", "");
+        }
+    }
+
+    return;
+}
+
</span> /*
  * Local variables:
  *  c-indent-level: 4
</code></pre>

<br>
</li>

</div>
<div class='footer' style='margin-top: 10px;'>
<p>

<br>
<a href="https://xgitlab.cels.anl.gov/darshan/darshan/compare/80c07c27781a9680cfa7c001badc2ebe53e6dd00...b989ffe4326ac4b8b6e9376a3c69fce7763459bb">View it on GitLab</a>
<script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","action":{"@type":"ViewAction","name":["merge_requests","issues","commit"],"url":"https://xgitlab.cels.anl.gov/darshan/darshan/compare/80c07c27781a9680cfa7c001badc2ebe53e6dd00...b989ffe4326ac4b8b6e9376a3c69fce7763459bb"}}</script>
</p>
</div>
</body>
</html>