Commit b543e7eb authored by Matthieu Dorier's avatar Matthieu Dorier
Browse files

adding initial files

parents
COPYRIGHT
The following is a notice of limited availability of the code, and disclaimer
which must be included in the prologue of the code and in all source listings
of the code.
Copyright Notice
+ 2015 University of Chicago
Permission is hereby granted to use, reproduce, prepare derivative works, and
to redistribute to others. This software was authored by:
Mathematics and Computer Science Division
Argonne National Laboratory, Argonne IL 60439
GOVERNMENT LICENSE
Portions of this material resulted from work developed under a U.S.
Government Contract and are subject to the following license: the Government
is granted for itself and others acting on its behalf a paid-up, nonexclusive,
irrevocable worldwide license in this computer software to reproduce, prepare
derivative works, and perform publicly and display publicly.
DISCLAIMER
This computer code material was prepared, in part, as an account of work
sponsored by an agency of the United States Government. Neither the United
States, nor the University of Chicago, nor any of their employees, makes any
warranty express or implied, or assumes any legal liability or responsibility
for the accuracy, completeness, or usefulness of any information, apparatus,
product, or process disclosed, or represents that its use would not infringe
privately owned rights.
Darshan-Ruby is a binding to the Darshan-util library.
Darshan is a lightweight I/O characterization tool that transparently
captures I/O access pattern information from HPC applications.
Darshan can be used to tune applications for increased scientific
productivity or to gain insight into trends in large-scale computing
systems.
Please see the
[Darshan web page](http://www.mcs.anl.gov/research/projects/darshan)
for more in-depth news and documentation about Darshan.
Darshan-Ruby is designed to support Darshan 3.0.0 and above.
NOTE: this source is not necessary to install Darshan-Ruby, as
Darshan-Ruby is available as a ruby gem on rubygems.org.
HOW TO INSTALL:
Darshan must be installed with bzip2 support. Assuming the path to
Darshan is "path/to/darshan", install Darshan-Ruby can be done as
follows:
gem install darshan-ruby -- --with-darshan-dir=path/to/darshan
Gem::Specification.new do |s|
s.name = 'darshan-ruby'
s.version = '3.0.0'
s.date = '2015-10-12'
s.summary = "Ruby binding to Darshan"
s.description = "Ruby binding to ANL's Darshan library for HPC I/O tracing and analysis"
s.authors = ["Matthieu Dorier"]
s.email = 'mdorier@anl.gov'
s.files = ["lib/darshan.rb",
"ext/darshan/darshan-ruby.c", "ext/darshan/darshan-ruby.h",
"ext/darshan/bgq-module.c", "ext/darshan/bgq-module.h",
"ext/darshan/hdf5-module.c", "ext/darshan/hdf5-module.h",
"ext/darshan/mpiio-module.c", "ext/darshan/mpiio-module.h",
"ext/darshan/pnetcdf-module.c", "ext/darshan/pnetcdf-module.h",
"ext/darshan/posix-module.c", "ext/darshan/posix-module.h",
"ext/darshan/extconf.rb"]
s.require_paths = [ 'lib', 'ext' ]
s.extensions = %w[ext/darshan/extconf.rb]
s.homepage = 'http://www.mcs.anl.gov/research/projects/darshan/'
s.license = 'GOVERNMENT LICENSE'
s.rubyforge_project = "nowarning"
end
/*
* Copyright (C) 2015 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#include "darshan-ruby.h"
extern VALUE cDarshanRecord;
extern VALUE mDarshan;
VALUE cDarshanBGQRecord;
VALUE mDarshanBGQ;
static VALUE Darshan3rb_bgq_get_rank(VALUE self)
{
struct darshan_bgq_record* c_record = NULL;
Data_Get_Struct(self,struct darshan_fd_s,c_record);
if(c_record) return LL2NUM(c_record->rank);
else return Qnil;
}
static VALUE Darshan3rb_bgq_get_alignment(VALUE self)
{
struct darshan_bgq_record* c_record = NULL;
Data_Get_Struct(self,struct darshan_fd_s,c_record);
if(c_record) return INT2NUM(c_record->alignment);
else return Qnil;
}
static VALUE Darshan3rb_bgq_get_counter(VALUE self, VALUE index)
{
struct darshan_bgq_record* c_record = NULL;
Data_Get_Struct(self,struct darshan_fd_s,c_record);
int i = NUM2INT(index);
if((i < 0) || (c_record == NULL)) return Qnil;
if(i < BGQ_NUM_INDICES) return LL2NUM(c_record->counters[i]);
if(i < BGQ_NUM_INDICES+BGQ_F_NUM_INDICES) return rb_float_new(c_record->fcounters[i-BGQ_NUM_INDICES]);
else return Qnil;
}
void Darshan3rb_init_bgq()
{
mDarshanBGQ = rb_define_module_under(mDarshan,"BGQ");
VALUE cnames = rb_ary_new2(BGQ_NUM_INDICES+BGQ_F_NUM_INDICES);
int i;
for(i=0; i < BGQ_NUM_INDICES; i++) {
rb_ary_store(cnames,i,rb_str_new2(bgq_counter_names[i]));
rb_define_const(mDarshanBGQ,bgq_counter_names[i],INT2NUM(i));
}
for(i=0; i < BGQ_F_NUM_INDICES; i++) {
int j = i+BGQ_NUM_INDICES;
rb_ary_store(cnames,j,rb_str_new2(bgq_f_counter_names[i]));
rb_define_const(mDarshanBGQ,bgq_f_counter_names[i],INT2NUM(j));
}
rb_define_const(mDarshanBGQ,"NAMES",cnames);
cDarshanBGQRecord = rb_define_class_under(mDarshanBGQ,"Record",cDarshanRecord);
rb_define_method(cDarshanBGQRecord,"rank",Darshan3rb_bgq_get_rank,0);
rb_define_method(cDarshanBGQRecord,"counter",Darshan3rb_bgq_get_counter,1);
rb_define_method(cDarshanBGQRecord,"alignment",Darshan3rb_bgq_get_alignment,0);
}
VALUE Darshan3rb_get_bgq_record(darshan_fd fd, darshan_record_id* rec_id)
{
struct darshan_bgq_record* c_record = (struct darshan_bgq_record*)malloc(sizeof(struct darshan_bgq_record));
int r = mod_logutils[DARSHAN_BGQ_MOD]->log_get_record(fd, (char*)c_record, rec_id);
if(r != 1) return Qnil;
VALUE rb_record = Data_Wrap_Struct(cDarshanBGQRecord, NULL , free, c_record);
return rb_record;
}
/*
* Copyright (C) 2015 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#include <ruby.h>
void Darshan3rb_init_bgq();
VALUE Darshan3rb_get_bgq_record(darshan_fd fd, darshan_record_id* rec_id);
/*
* (C) 2009 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#include "darshan-ruby.h"
VALUE mDarshan; // Darshan module in Ruby
VALUE cDarshanException;// Darshan::Exception class
VALUE cDarshanLogFile; // Darshan::LogFile class
VALUE cDarshanRecord; // Darshan::Record class
VALUE cDarshanModule; // Darshan::Module class
VALUE cDarshanHash; // Darshan::Hash class
/* Within: Darshan module
* Opens a log file using its name.
* Returns an instance of Darshan::LogFile on sucess, nil on failure.
*/
static VALUE rb_darshan_open(VALUE self, VALUE name)
{
const char* c_name = rb_string_value_cstr(&name);
darshan_fd fd = darshan_log_open(c_name);
char buffer[DARSHAN_JOB_METADATA_LEN];
if(fd != NULL) {
VALUE res = Data_Wrap_Struct(cDarshanLogFile, NULL ,NULL, fd);
// set the name of the file
rb_iv_set(res, "@name", name);//rb_str_new2(fd->name));
// get the job struct
struct darshan_job job;
int err = darshan_log_getjob(fd,&job);
if(err < 0) return Qnil;
// set the version number
rb_iv_set(res,"@version", rb_str_new2(fd->version));
// set the uid
rb_iv_set(res,"@uid", LL2NUM(job.uid));
// set the start time
rb_iv_set(res,"@start_time", LL2NUM(job.start_time));
// set the end time
rb_iv_set(res,"@end_time", LL2NUM(job.end_time));
// set the job id
rb_iv_set(res,"@job_id", LL2NUM(job.jobid));
// set the number of processes
rb_iv_set(res,"@nprocs", LL2NUM(job.nprocs));
// set the metadata
VALUE metadata = rb_hash_new();
char *token;
char *save;
for(token=strtok_r(job.metadata, "\n", &save);
token != NULL;
token=strtok_r(NULL, "\n", &save)) {
char *key;
char *value;
strcpy(buffer, token);
key = buffer;
value = index(buffer, '=');
if(!value) continue;
value[0] = '\0';
value++;
rb_hash_aset(metadata, rb_str_new2(key), rb_str_new2(value));
}
rb_iv_set(res,"@metadata", metadata);
// set the executable name
char exe[DARSHAN_EXE_LEN+2];
err = darshan_log_getexe(fd, exe);
if(err < 0) return Qnil;
rb_iv_set(res,"@exe", rb_str_new2(exe));
rb_iv_set(res,"@partial", fd->partial_flag ? Qtrue : Qfalse);
rb_iv_set(res,"@current_module", INT2NUM(-1));
// set the list of mount points
char** mnt_pts = NULL;
char** fs_types = NULL;
int count = 0;
err = darshan_log_getmounts(fd,&mnt_pts,&fs_types,&count);
if(err < 0) {
return Qnil;
}
VALUE path = ID2SYM(rb_intern("path"));
VALUE type = ID2SYM(rb_intern("type"));
VALUE mp = rb_ary_new2(count);
int i;
for(i=0; i<count; i++) {
VALUE hash = rb_hash_new();
rb_hash_aset(hash,path,rb_str_new2(mnt_pts[i]));
rb_hash_aset(hash,type,rb_str_new2(fs_types[i]));
rb_ary_store(mp,i,hash);
if(mnt_pts != NULL && mnt_pts[i] != NULL)
free(mnt_pts[i]);
if(fs_types != NULL && fs_types[i] != NULL)
free(fs_types[i]);
}
if(mnt_pts != NULL) free(mnt_pts);
if(fs_types != NULL) free(fs_types);
rb_iv_set(res,"@mount_points", mp);
// get the hash
struct darshan_record_ref *rec_hash = NULL;
err = darshan_log_gethash(fd, &rec_hash);
if(err < 0) {
return Qnil;
}
VALUE rb_hash = Data_Wrap_Struct(cDarshanHash, NULL ,NULL, rec_hash);
rb_iv_set(res,"@hash",rb_hash);
return res;
} else {
return Qnil;
}
}
/* Within: Darshan module
* Closes a file (instance of Darshan::LogFile)
* Returns true on success, false on failure.
*/
static VALUE rb_darshan_close(VALUE self, VALUE fd)
{
darshan_fd c_fd = NULL;
Data_Get_Struct(fd,struct darshan_fd_s,c_fd);
if(c_fd != NULL) {
darshan_log_close(c_fd);
return Qtrue;
} else {
return Qfalse;
}
}
/* Within: Darshan::Module LogFile class
* Returns the next Darshan::Module entry from the log file,
* or nil if there is no more modules to read.
*/
static VALUE rb_darshan_next_module(VALUE self)
{
darshan_fd fd = NULL;
Data_Get_Struct(self,struct darshan_fd_s, fd);
if(fd == NULL) return Qnil;
int i = NUM2INT(rb_iv_get(self,"@current_module"));
i +=1;
while(fd->mod_map[i].len == 0 && i < DARSHAN_MAX_MODS) i++;
if(i >= DARSHAN_MAX_MODS || (!mod_logutils[i])) {
rb_iv_set(self,"@current_module",INT2NUM(i));
return Qnil;
}
// Creat a Darshan::Module object
VALUE argv[0];
VALUE res = rb_class_new_instance(0, argv, cDarshanModule);
VALUE name = rb_str_new2(darshan_module_names[i]);
VALUE length = LL2NUM(fd->mod_map[i].len);
rb_iv_set(res,"@name", name);
rb_iv_set(res,"@length", length);
rb_iv_set(res,"@fd",self);
rb_iv_set(res,"@index", INT2NUM(i));
rb_iv_set(self,"@current_module",INT2NUM(i));
return res;
}
/* Within: Darshan::Module class
* Returns the next Darshan::Record entry from the module,
* or nil if there is no more such an entry.
*/
static VALUE rb_darshan_next_record(VALUE self)
{
// get the index of the module to access its functions
int i = NUM2INT(rb_iv_get(self,"@index"));
// get the parent log file descriptor
VALUE rfd = rb_iv_get(self,"@fd");
darshan_fd fd = NULL;
Data_Get_Struct(rfd,struct darshan_fd_s, fd);
if(fd == NULL) return Qnil;
VALUE rbhash = rb_iv_get(rfd,"@hash");
struct darshan_record_ref* rec_hash = NULL;
Data_Get_Struct(rbhash,struct darshan_record_ref, rec_hash);
if(rec_hash == NULL) return Qnil;
darshan_record_id rec_id;
VALUE res = Qnil;
switch(i) {
case DARSHAN_NULL_MOD:
res = Qnil;
break;
case DARSHAN_POSIX_MOD:
res = Darshan3rb_get_posix_record(fd,&rec_id);
break;
case DARSHAN_MPIIO_MOD:
res = Darshan3rb_get_mpiio_record(fd,&rec_id);
break;
case DARSHAN_HDF5_MOD:
res = Darshan3rb_get_hdf5_record(fd,&rec_id);
break;
case DARSHAN_PNETCDF_MOD:
res = Darshan3rb_get_pnetcdf_record(fd,&rec_id);
break;
case DARSHAN_BGQ_MOD:
res = Darshan3rb_get_bgq_record(fd,&rec_id);
break;
}
if(res == Qnil) return Qnil;
struct darshan_record_ref* ref;
HASH_FIND(hlink, rec_hash, &rec_id, sizeof(darshan_record_id), ref);
rb_iv_set(res,"@name",rb_str_new2(ref->rec.name));
return res;
}
/* Initialize the Darshan Ruby library
*/
void Init_Darshan3rb() {
mDarshan = rb_define_module("Darshan");
cDarshanLogFile = rb_define_class_under(mDarshan,"LogFile", rb_cObject);
cDarshanException = rb_define_class_under(mDarshan,"Exception", rb_cObject);
cDarshanModule = rb_define_class_under(mDarshan,"Module", rb_cObject);
cDarshanRecord = rb_define_class_under(mDarshan,"Record", rb_cObject);
cDarshanHash = rb_define_class_under(mDarshan,"Hash", rb_cObject);
rb_define_module_function(mDarshan,"open", rb_darshan_open, 1);
rb_define_module_function(mDarshan,"close", rb_darshan_close, 1);
rb_define_const(mDarshan,"VERSION",rb_str_new2(DARSHAN_LOG_VERSION));
Darshan3rb_init_posix();
Darshan3rb_init_mpiio();
Darshan3rb_init_hdf5();
Darshan3rb_init_pnetcdf();
Darshan3rb_init_bgq();
rb_define_method(cDarshanLogFile,"next_module",
rb_darshan_next_module,0);
rb_define_method(cDarshanModule,"next_record",
rb_darshan_next_record,0);
}
/*
* (C) 2009 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#ifndef DARSHAN_RUBY_H
#define DARSHAN_RUBY_H
#include <ruby.h>
#define DARSHAN_CONFIG_H "darshan-util-config.h"
#include <darshan-logutils.h>
#include "posix-module.h"
#include "mpiio-module.h"
#include "hdf5-module.h"
#include "pnetcdf-module.h"
#include "bgq-module.h"
#endif
#
# (C) 2015 by Argonne National Laboratory.
# See COPYRIGHT in top-level directory.
#
require 'mkmf'
dir_config('darshan')
dir_config('z')
dir_config('bz2')
if(not have_header('darshan-log-format.h'))
$stderr << "Error, could not find darshan-log-format.h\n"
$stderr << "Please use --with-darshan-dir=...\n"
abort "Missing darshan-log-format.h"
end
if(not have_library('z'))
$stderr << "Error, could not locate zlib.\n"
abort "Missing zlib"
end
if(not have_library('bz2'))
$stderr << "Error, could not locate libbz2.\n"
abort "Missing bz2"
end
if(not have_library('darshan-util'))
$stderr << "Error, could not locate libdarshan-util.a\n"
$stderr << "Please use --with-darshan-dir=...\n"
abort "Missing libdarshan-util.a"
end
create_makefile("Darshan3rb")
/*
* Copyright (C) 2015 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#include "darshan-ruby.h"
extern VALUE cDarshanRecord;
extern VALUE mDarshan;
VALUE cDarshanHDF5Record;
VALUE mDarshanHDF5;
static VALUE Darshan3rb_hdf5_get_rank(VALUE self)
{
struct darshan_hdf5_file* c_record = NULL;
Data_Get_Struct(self,struct darshan_fd_s,c_record);
if(c_record) return LL2NUM(c_record->rank);
else return Qnil;
}
static VALUE Darshan3rb_hdf5_get_counter(VALUE self, VALUE index)
{
struct darshan_hdf5_file* c_record = NULL;
Data_Get_Struct(self,struct darshan_fd_s,c_record);
int i = NUM2INT(index);
if((i < 0) || (c_record == NULL)) return Qnil;
if(i < HDF5_NUM_INDICES) return LL2NUM(c_record->counters[i]);
if(i < HDF5_NUM_INDICES+HDF5_F_NUM_INDICES) return rb_float_new(c_record->fcounters[i-HDF5_NUM_INDICES]);
else return Qnil;
}
void Darshan3rb_init_hdf5()
{
mDarshanHDF5 = rb_define_module_under(mDarshan,"HDF5");
VALUE cnames = rb_ary_new2(HDF5_NUM_INDICES+HDF5_F_NUM_INDICES);
int i;
for(i=0; i < HDF5_NUM_INDICES; i++) {
rb_ary_store(cnames,i,rb_str_new2(hdf5_counter_names[i]));
rb_define_const(mDarshanHDF5,hdf5_counter_names[i],INT2NUM(i));
}
for(i=0; i < HDF5_F_NUM_INDICES; i++) {
int j = i+HDF5_NUM_INDICES;
rb_ary_store(cnames,j,rb_str_new2(hdf5_f_counter_names[i]));
rb_define_const(mDarshanHDF5,hdf5_f_counter_names[i],INT2NUM(j));
}
rb_define_const(mDarshanHDF5,"NAMES",cnames);
cDarshanHDF5Record = rb_define_class_under(mDarshanHDF5,"Record",cDarshanRecord);
rb_define_method(cDarshanHDF5Record,"rank",Darshan3rb_hdf5_get_rank,0);
rb_define_method(cDarshanHDF5Record,"counter",Darshan3rb_hdf5_get_counter,1);
}
VALUE Darshan3rb_get_hdf5_record(darshan_fd fd, darshan_record_id* rec_id)
{
struct darshan_hdf5_file* c_record = (struct darshan_hdf5_file*)malloc(sizeof(struct darshan_hdf5_file));
int r = mod_logutils[DARSHAN_HDF5_MOD]->log_get_record(fd, (char*)c_record, rec_id);
if(r != 1) return Qnil;
VALUE rb_record = Data_Wrap_Struct(cDarshanHDF5Record, NULL , free, c_record);
return rb_record;
}
/*
* Copyright (C) 2015 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#include <ruby.h>
void Darshan3rb_init_hdf5();
VALUE Darshan3rb_get_hdf5_record(darshan_fd fd, darshan_record_id* rec_id);
/*
* Copyright (C) 2015 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#include "darshan-ruby.h"
extern VALUE cDarshanRecord;
extern VALUE mDarshan;
VALUE cDarshanMPIIORecord;
VALUE mDarshanMPIIO;
static VALUE Darshan3rb_mpiio_get_rank(VALUE self)
{
struct darshan_mpiio_file* c_record = NULL;
Data_Get_Struct(self,struct darshan_fd_s,c_record);
if(c_record) return LL2NUM(c_record->rank);
else return Qnil;
}
static VALUE Darshan3rb_mpiio_get_counter(VALUE self, VALUE index)
{
struct darshan_mpiio_file* c_record = NULL;
Data_Get_Struct(self,struct darshan_fd_s,c_record);
int i = NUM2INT(index);
if((i < 0) || (c_record == NULL)) return Qnil;
if(i < MPIIO_NUM_INDICES) return LL2NUM(c_record->counters[i]);
if(i < MPIIO_NUM_INDICES+MPIIO_F_NUM_INDICES) return rb_float_new(c_record->fcounters[i-MPIIO_NUM_INDICES]);
else return Qnil;
}
void Darshan3rb_init_mpiio()
{
mDarshanMPIIO = rb_define_module_under(mDarshan,"MPIIO");
VALUE cnames = rb_ary_new2(MPIIO_NUM_INDICES+MPIIO_F_NUM_INDICES);
int i;
for(i=0; i < MPIIO_NUM_INDICES; i++) {
rb_ary_store(cnames,i,rb_str_new2(mpiio_counter_names[i]));
rb_define_const(mDarshanMPIIO,mpiio_counter_names[i],INT2NUM(i));
}
for(i=0; i < MPIIO_F_NUM_INDICES; i++) {
int j = i+MPIIO_NUM_INDICES;
rb_ary_store(cnames,j,rb_str_new2(mpiio_f_counter_names[i]));
rb_define_const(mDarshanMPIIO,mpiio_f_counter_names[i],INT2NUM(j));
}
rb_define_const(mDarshanMPIIO,"NAMES",cnames);
cDarshanMPIIORecord = rb_define_class_under(mDarshanMPIIO,"Record",cDarshanRecord);
rb_define_method(cDarshanMPIIORecord,"rank",Darshan3rb_mpiio_get_rank,0);
rb_define_method(cDarshanMPIIORecord,"counter",Darshan3rb_mpiio_get_counter,1);
}
VALUE Darshan3rb_get_mpiio_record(darshan_fd fd, darshan_record_id* rec_id)