Commit 9bfc7b65 authored by Shane Snyder's avatar Shane Snyder

add record_ref interface to darshan-common

This interface provides some convenience functions for mapping
opaque record identifiers (could be a filename, file descriptor,
or any other type of file handle) to a corresponding runtime
structure referencing the actual file record. This runtime
structure should at least contain a pointer to the actual file
record, and can also persist arbitrary state for this record.
parent bfde9eb7
......@@ -157,6 +157,36 @@ struct darshan_variance_dt
* darshan-common functions for darshan modules *
***********************************************/
void *darshan_lookup_record_ref(
void *hash_head,
void *handle,
size_t handle_sz);
int darshan_add_record_ref(
void **hash_head,
void *handle,
size_t handle_sz,
void *rec_ref_p);
void *darshan_delete_record_ref(
void **hash_head,
void *handle,
size_t handle_sz);
void darshan_clear_record_refs(
void **hash_head,
int free_flag);
void darshan_iter_record_refs(
void *hash_head,
void (*iter_action)(void *));
darshan_record_id darshan_record_id_from_path(
const char *path);
darshan_record_id darshan_record_id_from_name(
const char *name);
/* darshan_clean_file_path()
*
* Allocate a new string that contains a new cleaned-up version of
......
......@@ -118,7 +118,7 @@ void darshan_core_unregister_module(
*
*/
darshan_record_id darshan_core_gen_record_id(
char *name);
const char *name);
/* darshan_core_register_record()
*
......@@ -136,7 +136,7 @@ darshan_record_id darshan_core_gen_record_id(
*/
void *darshan_core_register_record(
darshan_record_id rec_id,
char *name,
const char *name,
darshan_module_id mod_id,
int rec_len,
int *file_alignment);
......
......@@ -15,11 +15,122 @@
#include <search.h>
#include <assert.h>
#include "uthash.h"
#include "darshan.h"
static int darshan_common_val_compare(const void* a_p, const void* b_p);
static void darshan_common_val_walker(const void* nodep, const VISIT which,
const int depth);
struct darshan_record_ref_tracker
{
void *rec_ref_p;
UT_hash_handle hlink;
};
void *darshan_lookup_record_ref(void *hash_head, void *handle, size_t handle_sz)
{
struct darshan_record_ref_tracker *ref_tracker;
struct darshan_record_ref_tracker *ref_tracker_head =
(struct darshan_record_ref_tracker *)hash_head;
HASH_FIND(hlink, ref_tracker_head, handle, handle_sz, ref_tracker);
if(ref_tracker)
return(ref_tracker->rec_ref_p);
else
return(NULL);
}
int darshan_add_record_ref(void **hash_head, void *handle, size_t handle_sz,
void *rec_ref_p)
{
struct darshan_record_ref_tracker *ref_tracker;
struct darshan_record_ref_tracker *ref_tracker_head =
*(struct darshan_record_ref_tracker **)hash_head;
void *handle_p;
ref_tracker = malloc(sizeof(*ref_tracker) + handle_sz);
if(!ref_tracker)
return(0);
memset(ref_tracker, 0, sizeof(*ref_tracker) + handle_sz);
ref_tracker->rec_ref_p = rec_ref_p;
handle_p = (char *)ref_tracker + sizeof(*ref_tracker);
memcpy(handle_p, handle, handle_sz);
HASH_ADD_KEYPTR(hlink, ref_tracker_head, handle_p, handle_sz, ref_tracker);
*hash_head = ref_tracker_head;
return(1);
}
void *darshan_delete_record_ref(void **hash_head, void *handle, size_t handle_sz)
{
struct darshan_record_ref_tracker *ref_tracker;
struct darshan_record_ref_tracker *ref_tracker_head =
*(struct darshan_record_ref_tracker **)hash_head;
void *rec_ref_p;
HASH_FIND(hlink, ref_tracker_head, handle, handle_sz, ref_tracker);
if(!ref_tracker)
return(NULL);
HASH_DELETE(hlink, ref_tracker_head, ref_tracker);
*hash_head = ref_tracker_head;
rec_ref_p = ref_tracker->rec_ref_p;
free(ref_tracker);
return(rec_ref_p);
}
void darshan_clear_record_refs(void **hash_head, int free_flag)
{
struct darshan_record_ref_tracker *ref_tracker, *tmp;
struct darshan_record_ref_tracker *ref_tracker_head =
*(struct darshan_record_ref_tracker **)hash_head;
HASH_ITER(hlink, ref_tracker_head, ref_tracker, tmp)
{
HASH_DELETE(hlink, ref_tracker_head, ref_tracker);
if(free_flag)
free(ref_tracker->rec_ref_p);
free(ref_tracker);
}
*hash_head = ref_tracker_head;
return;
}
void darshan_iter_record_refs(void *hash_head, void (*iter_action)(void *))
{
struct darshan_record_ref_tracker *ref_tracker, *tmp;
struct darshan_record_ref_tracker *ref_tracker_head =
(struct darshan_record_ref_tracker *)hash_head;
HASH_ITER(hlink, ref_tracker_head, ref_tracker, tmp)
{
iter_action(ref_tracker->rec_ref_p);
}
return;
}
darshan_record_id darshan_record_id_from_path(const char *path)
{
char *newpath = NULL;
darshan_record_id rec_id;
newpath = darshan_clean_file_path(path);
if(!newpath)
newpath = (char *)path;
rec_id = darshan_record_id_from_name(newpath);
if(newpath != path)
free(newpath);
return(rec_id);
}
darshan_record_id darshan_record_id_from_name(const char *name)
{
return(darshan_core_gen_record_id(name));
}
char* darshan_clean_file_path(const char* path)
{
......@@ -82,6 +193,37 @@ char* darshan_clean_file_path(const char* path)
static int64_t* walker_val_p = NULL;
static int64_t* walker_cnt_p = NULL;
static void darshan_common_val_walker(const void *nodep, const VISIT which,
const int depth)
{
struct darshan_common_val_counter* counter;
switch (which)
{
case postorder:
case leaf:
counter = *(struct darshan_common_val_counter**)nodep;
DARSHAN_COMMON_VAL_COUNTER_INC(walker_val_p, walker_cnt_p,
counter->val, counter->freq, 0);
default:
break;
}
return;
}
static int darshan_common_val_compare(const void *a_p, const void *b_p)
{
const struct darshan_common_val_counter* a = a_p;
const struct darshan_common_val_counter* b = b_p;
if(a->val < b->val)
return(-1);
if(a->val > b->val)
return(1);
return(0);
}
void darshan_common_val_counter(void **common_val_root, int *common_val_count,
int64_t val, int64_t *common_val_p, int64_t *common_cnt_p)
{
......@@ -146,37 +288,6 @@ void darshan_walk_common_vals(void *common_val_root, int64_t *val_p,
return;
}
static void darshan_common_val_walker(const void *nodep, const VISIT which,
const int depth)
{
struct darshan_common_val_counter* counter;
switch (which)
{
case postorder:
case leaf:
counter = *(struct darshan_common_val_counter**)nodep;
DARSHAN_COMMON_VAL_COUNTER_INC(walker_val_p, walker_cnt_p,
counter->val, counter->freq, 0);
default:
break;
}
return;
}
static int darshan_common_val_compare(const void *a_p, const void *b_p)
{
const struct darshan_common_val_counter* a = a_p;
const struct darshan_common_val_counter* b = b_p;
if(a->val < b->val)
return(-1);
if(a->val > b->val)
return(1);
return(0);
}
void darshan_variance_reduce(void *invec, void *inoutvec, int *len,
MPI_Datatype *dt)
{
......
......@@ -95,7 +95,7 @@ static void darshan_get_exe_and_mounts(
struct darshan_core_runtime *core, int argc, char **argv);
static void darshan_add_name_record_ref(
struct darshan_core_runtime *core, darshan_record_id rec_id,
char *name, darshan_module_id mod_id);
const char *name, darshan_module_id mod_id);
static int darshan_block_size_from_path(
const char *path);
static void darshan_get_user_name(
......@@ -1222,7 +1222,7 @@ static void darshan_get_logfile_name(char* logfile_name, int jobid, struct tm* s
}
static void darshan_add_name_record_ref(struct darshan_core_runtime *core,
darshan_record_id rec_id, char *name, darshan_module_id mod_id)
darshan_record_id rec_id, const char *name, darshan_module_id mod_id)
{
struct darshan_core_name_record_ref *ref;
int record_size = sizeof(darshan_record_id) + strlen(name) + 1;
......@@ -1778,7 +1778,7 @@ void darshan_core_unregister_module(
}
darshan_record_id darshan_core_gen_record_id(
char *name)
const char *name)
{
/* hash the input name to get a unique id for this record */
return darshan_hash((unsigned char *)name, strlen(name), 0);
......@@ -1786,7 +1786,7 @@ darshan_record_id darshan_core_gen_record_id(
void *darshan_core_register_record(
darshan_record_id rec_id,
char *name,
const char *name,
darshan_module_id mod_id,
int rec_len,
int *file_alignment)
......
......@@ -26,7 +26,6 @@
#include <aio.h>
#include <pthread.h>
#include "uthash.h"
#include "utlist.h"
#include "darshan.h"
......@@ -91,32 +90,9 @@ struct posix_aio_tracker
struct posix_aio_tracker* next;
};
/* The posix_file_runtime structure maintains necessary runtime metadata
* for the POSIX file record (darshan_posix_file structure, defined in
* darshan-posix-log-format.h) pointed to by 'file_record'. This metadata
* assists with the instrumenting of specific statistics in the file record.
* 'hlink' is a hash table link structure used to add/remove this record
* from the hash table of POSIX file records for this process.
*
* RATIONALE: the POSIX module needs to track some stateful, volatile
* information about each open file (like the current file offset, most recent
* access time, etc.) to aid in instrumentation, but this information can't be
* stored in the darshan_posix_file struct because we don't want it to appear in
* the final darshan log file. We therefore associate a posix_file_runtime
* struct with each darshan_posix_file struct in order to track this information.
*
* NOTE: There is a one-to-one mapping of posix_file_runtime structs to
* darshan_posix_file structs.
*
* NOTE: The posix_file_runtime struct contains a pointer to a darshan_posix_file
* struct (see the *file_record member) rather than simply embedding an entire
* darshan_posix_file struct. This is done so that all of the darshan_posix_file
* structs can be kept contiguous in memory as a single array to simplify
* reduction, compression, and storage.
*/
struct posix_file_runtime
struct posix_file_record_ref
{
struct darshan_posix_file* file_record;
struct darshan_posix_file* file_rec;
int64_t offset;
int64_t last_byte_read;
int64_t last_byte_written;
......@@ -129,47 +105,13 @@ struct posix_file_runtime
void* stride_root;
int stride_count;
struct posix_aio_tracker* aio_list;
UT_hash_handle hlink;
};
/* The posix_file_runtime_ref structure is used to associate a POSIX
* file descriptor with an already existing POSIX file record. This is
* necessary as many POSIX I/O functions take only an input file descriptor,
* but POSIX file records are indexed by their full file paths (i.e., darshan
* record identifiers for POSIX files are created by hashing the file path).
* In other words, this structure is necessary as it allows us to look up a
* file record either by a pathname (posix_file_runtime) or by POSIX file
* descriptor (posix_file_runtime_ref), depending on which parameters are
* available. This structure includes another hash table link, since separate
* hashes are maintained for posix_file_runtime structures and posix_file_runtime_ref
* structures.
*
* RATIONALE: In theory the fd information could be included in the
* posix_file_runtime struct rather than in a separate structure here. The
* reason we don't do that is because the same file could be opened multiple
* times by a given process with different file descriptors and thus
* simulataneously referenced using different file descriptors. This practice is
* not common, but we must support it.
*
* NOTE: there are potentially multiple posix_file_runtime_ref structures
* referring to a single posix_file_runtime structure. Most of the time there is
* only one, however.
*/
struct posix_file_runtime_ref
{
struct posix_file_runtime* file;
int fd;
UT_hash_handle hlink;
};
/* The posix_runtime structure maintains necessary state for storing
* POSIX file records and for coordinating with darshan-core at
* shutdown time.
*/
struct posix_runtime
{
struct posix_file_runtime* file_hash;
struct posix_file_runtime_ref* fd_hash;
void *rec_id_hash;
void *fd_hash;
int file_rec_count;
};
static struct posix_runtime *posix_runtime = NULL;
......@@ -178,175 +120,194 @@ static int instrumentation_disabled = 0;
static int my_rank = -1;
static int darshan_mem_alignment = 1;
static void posix_runtime_initialize(void);
static struct posix_file_runtime* posix_file_by_name(const char *name);
static struct posix_file_runtime* posix_file_by_name_setfd(const char* name, int fd);
static struct posix_file_runtime* posix_file_by_fd(int fd);
static void posix_file_close_fd(int fd);
static void posix_aio_tracker_add(int fd, void *aiocbp);
static struct posix_aio_tracker* posix_aio_tracker_del(int fd, void *aiocbp);
static int posix_record_compare(const void* a, const void* b);
static void posix_record_reduction_op(void* infile_v, void* inoutfile_v,
int *len, MPI_Datatype *datatype);
static void posix_shared_record_variance(MPI_Comm mod_comm,
struct darshan_posix_file *inrec_array, struct darshan_posix_file *outrec_array,
int shared_rec_count);
static void posix_begin_shutdown(void);
static void posix_get_output_data(MPI_Comm mod_comm, darshan_record_id *shared_recs,
static void posix_runtime_initialize(
void);
static struct posix_file_record_ref *posix_track_new_file_record(
darshan_record_id rec_id, const char *path);
static void posix_aio_tracker_add(
int fd, void *aiocbp);
static struct posix_aio_tracker* posix_aio_tracker_del(
int fd, void *aiocbp);
static int posix_record_compare(
const void* a, const void* b);
static void posix_record_reduction_op(
void* infile_v, void* inoutfile_v, int *len, MPI_Datatype *datatype);
static void posix_shared_record_variance(
MPI_Comm mod_comm, struct darshan_posix_file *inrec_array,
struct darshan_posix_file *outrec_array, int shared_rec_count);
static void posix_begin_shutdown(
void);
static void posix_get_output_data(
MPI_Comm mod_comm, darshan_record_id *shared_recs,
int shared_rec_count, void **posix_buf, int *posix_buf_sz);
static void posix_shutdown(void);
static void posix_shutdown(
void);
#define POSIX_LOCK() pthread_mutex_lock(&posix_runtime_mutex)
#define POSIX_UNLOCK() pthread_mutex_unlock(&posix_runtime_mutex)
#define POSIX_RECORD_OPEN(__ret, __path, __mode, __stream_flag, __tm1, __tm2) do { \
struct posix_file_runtime* file; \
struct posix_file_record_ref *rec_ref; \
darshan_record_id rec_id; \
if(__ret < 0) break; \
if(!posix_runtime || instrumentation_disabled) break; /* XXX: PREMABLE??? */\
if(darshan_core_excluded_path(__path)) break; \
file = posix_file_by_name_setfd(__path, __ret); \
if(!file) break; \
rec_id = darshan_record_id_from_path(__path); \
rec_ref = darshan_lookup_record_ref(posix_runtime->rec_id_hash, &rec_id, sizeof(darshan_record_id)); \
if(!rec_ref) { \
rec_ref = posix_track_new_file_record(rec_id, __path); \
if(!rec_ref) break; \
} \
if(darshan_add_record_ref(&(posix_runtime->fd_hash), &__ret, sizeof(int), rec_ref) == 0) break; \
if(__mode) \
file->file_record->counters[POSIX_MODE] = __mode; \
file->offset = 0; \
file->last_byte_written = 0; \
file->last_byte_read = 0; \
rec_ref->file_rec->counters[POSIX_MODE] = __mode; \
rec_ref->offset = 0; \
rec_ref->last_byte_written = 0; \
rec_ref->last_byte_read = 0; \
if(__stream_flag)\
file->file_record->counters[POSIX_FOPENS] += 1; \
rec_ref->file_rec->counters[POSIX_FOPENS] += 1; \
else \
file->file_record->counters[POSIX_OPENS] += 1; \
if(file->file_record->fcounters[POSIX_F_OPEN_TIMESTAMP] == 0) \
file->file_record->fcounters[POSIX_F_OPEN_TIMESTAMP] = __tm1; \
DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[POSIX_F_META_TIME], \
__tm1, __tm2, file->last_meta_end); \
rec_ref->file_rec->counters[POSIX_OPENS] += 1; \
if(rec_ref->file_rec->fcounters[POSIX_F_OPEN_TIMESTAMP] == 0) \
rec_ref->file_rec->fcounters[POSIX_F_OPEN_TIMESTAMP] = __tm1; \
DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[POSIX_F_META_TIME], \
__tm1, __tm2, rec_ref->last_meta_end); \
} while(0)
#define POSIX_RECORD_READ(__ret, __fd, __pread_flag, __pread_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
#define POSIX_RECORD_READ(__ret, __fd, __pread_flag, __pread_offset, __aligned, __stream_flag, __tm1, __tm2) do { \
struct posix_file_record_ref* rec_ref; \
size_t stride; \
int64_t this_offset; \
struct posix_file_runtime* file; \
int64_t file_alignment; \
double __elapsed = __tm2-__tm1; \
if(__ret < 0) break; \
file = posix_file_by_fd(__fd); \
if(!file) break; \
if(!posix_runtime || instrumentation_disabled) break; /* XXX: PREMABLE??? */\
rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &(__fd), sizeof(int)); \
if(!rec_ref) break; \
if(__pread_flag) \
this_offset = __pread_offset; \
else \
this_offset = file->offset; \
if(this_offset > file->last_byte_read) \
file->file_record->counters[POSIX_SEQ_READS] += 1; \
if(this_offset == (file->last_byte_read + 1)) \
file->file_record->counters[POSIX_CONSEC_READS] += 1; \
if(this_offset > 0 && this_offset > file->last_byte_read \
&& file->last_byte_read != 0) \
stride = this_offset - file->last_byte_read - 1; \
this_offset = rec_ref->offset; \
if(this_offset > rec_ref->last_byte_read) \
rec_ref->file_rec->counters[POSIX_SEQ_READS] += 1; \
if(this_offset == (rec_ref->last_byte_read + 1)) \
rec_ref->file_rec->counters[POSIX_CONSEC_READS] += 1; \
if(this_offset > 0 && this_offset > rec_ref->last_byte_read \
&& rec_ref->last_byte_read != 0) \
stride = this_offset - rec_ref->last_byte_read - 1; \
else \
stride = 0; \
file->last_byte_read = this_offset + __ret - 1; \
file->offset = this_offset + __ret; \
if(file->file_record->counters[POSIX_MAX_BYTE_READ] < (this_offset + __ret - 1)) \
file->file_record->counters[POSIX_MAX_BYTE_READ] = (this_offset + __ret - 1); \
file->file_record->counters[POSIX_BYTES_READ] += __ret; \
rec_ref->last_byte_read = this_offset + __ret - 1; \
rec_ref->offset = this_offset + __ret; \
if(rec_ref->file_rec->counters[POSIX_MAX_BYTE_READ] < (this_offset + __ret - 1)) \
rec_ref->file_rec->counters[POSIX_MAX_BYTE_READ] = (this_offset + __ret - 1); \
rec_ref->file_rec->counters[POSIX_BYTES_READ] += __ret; \
if(__stream_flag) \
file->file_record->counters[POSIX_FREADS] += 1; \
rec_ref->file_rec->counters[POSIX_FREADS] += 1; \
else \
file->file_record->counters[POSIX_READS] += 1; \
DARSHAN_BUCKET_INC(&(file->file_record->counters[POSIX_SIZE_READ_0_100]), __ret); \
darshan_common_val_counter(&file->access_root, &file->access_count, __ret, \
&(file->file_record->counters[POSIX_ACCESS1_ACCESS]), \
&(file->file_record->counters[POSIX_ACCESS1_COUNT])); \
darshan_common_val_counter(&file->stride_root, &file->stride_count, stride, \
&(file->file_record->counters[POSIX_STRIDE1_STRIDE]), \
&(file->file_record->counters[POSIX_STRIDE1_COUNT])); \
rec_ref->file_rec->counters[POSIX_READS] += 1; \
DARSHAN_BUCKET_INC(&(rec_ref->file_rec->counters[POSIX_SIZE_READ_0_100]), __ret); \
darshan_common_val_counter(&rec_ref->access_root, &rec_ref->access_count, __ret, \
&(rec_ref->file_rec->counters[POSIX_ACCESS1_ACCESS]), \
&(rec_ref->file_rec->counters[POSIX_ACCESS1_COUNT])); \
darshan_common_val_counter(&rec_ref->stride_root, &rec_ref->stride_count, stride, \
&(rec_ref->file_rec->counters[POSIX_STRIDE1_STRIDE]), \
&(rec_ref->file_rec->counters[POSIX_STRIDE1_COUNT])); \
if(!__aligned) \
file->file_record->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
file_alignment = file->file_record->counters[POSIX_FILE_ALIGNMENT]; \
rec_ref->file_rec->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
file_alignment = rec_ref->file_rec->counters[POSIX_FILE_ALIGNMENT]; \
if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
file->file_record->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
if(file->last_io_type == DARSHAN_IO_WRITE) \
file->file_record->counters[POSIX_RW_SWITCHES] += 1; \
file->last_io_type = DARSHAN_IO_READ; \
if(file->file_record->fcounters[POSIX_F_READ_START_TIMESTAMP] == 0) \
file->file_record->fcounters[POSIX_F_READ_START_TIMESTAMP] = __tm1; \
file->file_record->fcounters[POSIX_F_READ_END_TIMESTAMP] = __tm2; \
if(file->file_record->fcounters[POSIX_F_MAX_READ_TIME] < __elapsed) { \
file->file_record->fcounters[POSIX_F_MAX_READ_TIME] = __elapsed; \
file->file_record->counters[POSIX_MAX_READ_TIME_SIZE] = __ret; } \
DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[POSIX_F_READ_TIME], \
__tm1, __tm2, file->last_read_end); \
rec_ref->file_rec->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
if(rec_ref->last_io_type == DARSHAN_IO_WRITE) \
rec_ref->file_rec->counters[POSIX_RW_SWITCHES] += 1; \
rec_ref->last_io_type = DARSHAN_IO_READ; \
if(rec_ref->file_rec->fcounters[POSIX_F_READ_START_TIMESTAMP] == 0) \
rec_ref->file_rec->fcounters[POSIX_F_READ_START_TIMESTAMP] = __tm1; \
rec_ref->file_rec->fcounters[POSIX_F_READ_END_TIMESTAMP] = __tm2; \
if(rec_ref->file_rec->fcounters[POSIX_F_MAX_READ_TIME] < __elapsed) { \
rec_ref->file_rec->fcounters[POSIX_F_MAX_READ_TIME] = __elapsed; \
rec_ref->file_rec->counters[POSIX_MAX_READ_TIME_SIZE] = __ret; } \
DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[POSIX_F_READ_TIME], \
__tm1, __tm2, rec_ref->last_read_end); \
} while(0)
#define POSIX_RECORD_WRITE(__ret, __fd, __pwrite_flag, __pwrite_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
#define POSIX_RECORD_WRITE(__ret, __fd, __pwrite_flag, __pwrite_offset, __aligned, __stream_flag, __tm1, __tm2) do { \
struct posix_file_record_ref* rec_ref; \
size_t stride; \
int64_t this_offset; \
struct posix_file_runtime* file; \
int64_t file_alignment; \
double __elapsed = __tm2-__tm1; \
if(__ret < 0) break; \
file = posix_file_by_fd(__fd); \
if(!file) break; \
if(!posix_runtime || instrumentation_disabled) break; /* XXX: PREMABLE??? */\
rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &__fd, sizeof(int)); \
if(!rec_ref) break; \
if(__pwrite_flag) \
this_offset = __pwrite_offset; \
else \
this_offset = file->offset; \
if(this_offset > file->last_byte_written) \
file->file_record->counters[POSIX_SEQ_WRITES] += 1; \
if(this_offset == (file->last_byte_written + 1)) \
file->file_record->counters[POSIX_CONSEC_WRITES] += 1; \
if(this_offset > 0 && this_offset > file->last_byte_written \
&& file->last_byte_written != 0) \
stride = this_offset - file->last_byte_written - 1; \
this_offset = rec_ref->offset; \
if(this_offset > rec_ref->last_byte_written) \
rec_ref->file_rec->counters[POSIX_SEQ_WRITES] += 1; \
if(this_offset == (rec_ref->last_byte_written + 1)) \
rec_ref->file_rec->counters[POSIX_CONSEC_WRITES] += 1; \
if(this_offset > 0 && this_offset > rec_ref->last_byte_written \
&& rec_ref->last_byte_written != 0) \
stride = this_offset - rec_ref->last_byte_written - 1; \
else \
stride = 0; \
file->last_byte_written = this_offset + __ret - 1; \
file->offset = this_offset + __ret; \
if(file->file_record->counters[POSIX_MAX_BYTE_WRITTEN] < (this_offset + __ret - 1)) \
file->file_record->counters[POSIX_MAX_BYTE_WRITTEN] = (this_offset + __ret - 1); \
file->file_record->counters[POSIX_BYTES_WRITTEN] += __ret; \
rec_ref->last_byte_written = this_offset + __ret - 1; \
rec_ref->offset = this_offset + __ret; \
if(rec_ref->file_rec->counters[POSIX_MAX_BYTE_WRITTEN] < (this_offset + __ret - 1)) \
rec_ref->file_rec->counters[POSIX_MAX_BYTE_WRITTEN] = (this_offset + __ret - 1); \
rec_ref->file_rec->counters[POSIX_BYTES_WRITTEN] += __ret; \
if(__stream_flag) \
file->file_record->counters[POSIX_FWRITES] += 1; \
rec_ref->file_rec->counters[POSIX_FWRITES] += 1; \
else \
file->file_record->counters[POSIX_WRITES] += 1; \
DARSHAN_BUCKET_INC(&(file->file_record->counters[POSIX_SIZE_WRITE_0_100]), __ret); \
darshan_common_val_counter(&file->access_root, &file->access_count, __ret, \
&(file->file_record->counters[POSIX_ACCESS1_ACCESS]), \
&(file->file_record->counters[POSIX_ACCESS1_COUNT])); \
darshan_common_val_counter(&file->stride_root, &file->stride_count, stride, \
&(file->file_record->counters[POSIX_STRIDE1_STRIDE]), \
&(file->file_record->counters[POSIX_STRIDE1_COUNT])); \
rec_ref->file_rec->counters[POSIX_WRITES] += 1; \
DARSHAN_BUCKET_INC(&(rec_ref->file_rec->counters[POSIX_SIZE_WRITE_0_100]), __ret); \
darshan_common_val_counter(&rec_ref->access_root, &rec_ref->access_count, __ret, \
&(rec_ref->file_rec->counters[POSIX_ACCESS1_ACCESS]), \
&(rec_ref->file_rec->counters[POSIX_ACCESS1_COUNT])); \
darshan_common_val_counter(&rec_ref->stride_root, &rec_ref->stride_count, stride, \
&(rec_ref->file_rec->counters[POSIX_STRIDE1_STRIDE]), \
&(rec_ref->file_rec->counters[POSIX_STRIDE1_COUNT])); \
if(!__aligned) \
file->file_record->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
file_alignment = file->file_record->counters[POSIX_FILE_ALIGNMENT]; \
rec_ref->file_rec->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
file_alignment = rec_ref->file_rec->counters[POSIX_FILE_ALIGNMENT]; \
if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
file->file_record->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
if(file->last_io_type == DARSHAN_IO_READ) \
file->file_record->counters[POSIX_RW_SWITCHES] += 1; \
file->last_io_type = DARSHAN_IO_WRITE; \
if(file->file_record->fcounters[POSIX_F_WRITE_START_TIMESTAMP] == 0) \
file->file_record->fcounters[POSIX_F_WRITE_START_TIMESTAMP] = __tm1; \
file->file_record->fcounters[POSIX_F_WRITE_END_TIMESTAMP] = __tm2; \
if(file->file_record->fcounters[POSIX_F_MAX_WRITE_TIME] < __elapsed) { \
file->file_record->fcounters[POSIX_F_MAX_WRITE_TIME] = __elapsed; \
file->file_record->counters[POSIX_MAX_WRITE_TIME_SIZE] = __ret; } \
DARSHAN_TIMER_INC_NO_OVERLAP(file->file_record->fcounters[POSIX_F_WRITE_TIME], \
__tm1, __tm2, file->last_write_end); \
rec_ref->file_rec->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
if(rec_ref->last_io_type == DARSHAN_IO_READ) \
rec_ref->file_rec->counters[POSIX_RW_SWITCHES] += 1; \
rec_ref->last_io_type = DARSHAN_IO_WRITE; \
if(rec_ref->file_rec->fcounters[POSIX_F_WRITE_START_TIMESTAMP] == 0) \
rec_ref->file_rec->fcounters[POSIX_F_WRITE_START_TIMESTAMP] = __tm1; \
rec_ref->file_rec->fcounters[POSIX_F_WRITE_END_TIMESTAMP] = __tm2; \
if(rec_ref->file_rec->fcounters[POSIX_F_MAX_WRITE_TIME] < __elapsed) { \
rec_ref->file_rec->fcounters[POSIX_F_MAX_WRITE_TIME] = __elapsed; \
rec_ref->file_rec->counters[POSIX_MAX_WRITE_TIME_SIZE] = __ret; } \
DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[POSIX_F_WRITE_TIME], \
__tm1, __tm2, rec_ref->last_write_end); \
} while(0)
#define POSIX_LOOKUP_RECORD_STAT(__path, __statbuf, __tm1, __tm2) do { \
struct posix_file_runtime* file; \
struct posix_file_record_ref* rec_ref; \
darshan_record_id rec_id; \
if(!posix_runtime || instrumentation_disabled) break; /* XXX: PREMABLE??? */\
if(darshan_core_excluded_path(__path)) break; \
file = posix_file_by_name(__path); \
if(file) \
{ \
POSIX_RECORD_STAT(file, __statbuf, __tm1, __tm2); \
rec_id = darshan_record_id_from_path(__path); \
rec_ref = darshan_lookup_record_ref(posix_runtime->rec_id_hash, &rec_id, sizeof(darshan_record_id)); \
if(!rec_ref) { \
rec_ref = posix_track_new_file_record(rec_id, __path); \
} \
if(rec_ref) { \
POSIX_RECORD_STAT(rec_ref, __statbuf, __tm1, __tm2); \
} \
} while(0)
#define POSIX_RECORD_STAT(__file, __statbuf, __tm1, __tm2) do { \
(__file)->file_record->counters[POSIX_STATS] += 1; \
DARSHAN_TIMER_INC_NO_OVERLAP((__file)->file_record->fcounters[POSIX_F_META_TIME], \
__tm1, __tm2, (__file)->last_meta_end); \
#define POSIX_RECORD_STAT(__rec_ref, __statbuf, __tm1, __tm2) do { \
(__rec_ref)->file_rec->counters[POSIX_STATS] += 1; \
DARSHAN_TIMER_INC_NO_OVERLAP((__rec_ref)->file_rec->fcounters[POSIX_F_META_TIME], \
__tm1, __tm2, (__rec_ref)->last_meta_end); \
} while(0)
......@@ -776,6 +737,7 @@ size_t DARSHAN_DECL(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t ret;
int aligned_flag = 0;
int fd;
double tm1, tm2;
MAP_OR_FAIL(fread);
......@@ -788,15 +750,14 @@ size_t DARSHAN_DECL(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
POSIX_LOCK();
posix_runtime_initialize();
fd = fileno(stream);
if(ret > 0)
{
POSIX_RECORD_READ(size*ret, fileno(stream), 0, 0,
aligned_flag, 1, tm1, tm2);
POSIX_RECORD_READ(size*ret, fd, 0, 0, aligned_flag, 1, tm1, tm2);
}
else
{
POSIX_RECORD_READ(ret, fileno(stream), 0, 0,
aligned_flag, 1, tm1, tm2);
POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, 1, tm1, tm2);
}
POSIX_UNLOCK();
......@@ -807,6 +768,7 @@ size_t DARSHAN_DECL(fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *st
{
size_t ret;
int aligned_flag = 0;
int fd;
double tm1, tm2;
MAP_OR_FAIL(fwrite);
......@@ -819,15 +781,14 @@ size_t DARSHAN_DECL(fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *st