darshan-logutils.c 23.9 KB
Newer Older
1
/*
Shane Snyder's avatar
Shane Snyder committed
2 3 4
 * Copyright (C) 2015 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
5 6
 */

7
#define _GNU_SOURCE
8
#include "darshan-util-config.h"
9 10
#include <stdio.h>
#include <string.h>
11
#include <assert.h>
12
#include <stdlib.h>
13
#include <unistd.h>
14
#include <inttypes.h>
15 16 17
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
18
#include <errno.h>
19

20 21
#include "darshan-logutils.h"

22 23
/* TODO: for log reads, we need to make sure the header has been read prior */

24 25
static int darshan_log_seek(darshan_fd fd, off_t offset);
static int darshan_log_read(darshan_fd fd, void *buf, int len);
26
static int darshan_log_write(darshan_fd fd, void *buf, int len);
27 28
static int darshan_decompress_buf(char* comp_buf, int comp_buf_sz,
    char* decomp_buf, int* inout_decomp_buf_sz);
29 30 31 32

/* TODO: can we make this s.t. we don't care about ordering (i.e., X macro it ) */
struct darshan_mod_logutil_funcs *mod_logutils[DARSHAN_MAX_MODS] =
{
33
    NULL,               /* NULL */
34
    &posix_logutils,    /* POSIX */
35 36 37
    &mpiio_logutils,    /* MPI-IO */
    &hdf5_logutils,     /* HDF5 */
    &pnetcdf_logutils,  /* PNETCDF */
38 39 40 41 42 43 44 45 46 47 48 49
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL
};
50 51 52 53 54 55 56

/* darshan_log_open()
 *
 * open a darshan log file for reading/writing
 *
 * returns 0 on success, -1 on failure
 */
57
darshan_fd darshan_log_open(const char *name, const char *mode)
58
{
59
    int o_flags;
60
    darshan_fd tmp_fd;
61

62
    /* we only allow "w" or "r" modes, nothing fancy */
63 64 65
    assert(strlen(mode) == 1);
    assert(mode[0] == 'r' || mode[0] == 'w');

66 67 68 69 70 71 72 73 74 75 76 77
    if(mode[0] == 'r')
    {
        o_flags = O_RDONLY;
    }
    else if (mode[0] == 'w')
    {
        /* when writing, we create the log file making sure not to overwrite
         * an existing log
         */
        o_flags = O_WRONLY | O_CREAT | O_EXCL;
    }

78
    tmp_fd = malloc(sizeof(*tmp_fd));
79 80 81 82
    if(!tmp_fd)
        return(NULL);
    memset(tmp_fd, 0, sizeof(*tmp_fd));

83 84
    tmp_fd->fildes = open(name, o_flags);
    if(tmp_fd->fildes < 0)
85
    {
86
        perror("darshan_log_open: ");
87
        free(tmp_fd);
88
        tmp_fd = NULL;
89
    }
90 91

    return(tmp_fd);
92 93
}

94 95 96 97
/* 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
98
 * NOTE: this is the only portion of the darshan log which is uncompressed
99 100 101 102
 *
 * returns 0 on success, -1 on failure
 */
int darshan_log_getheader(darshan_fd fd, struct darshan_header *header)
103
{
104
    int i;
105
    int ret;
106

107
    ret = darshan_log_seek(fd, 0);
108
    if(ret < 0)
109 110
    {
        fprintf(stderr, "Error: unable to seek in darshan log file.\n");
111
        return(-1);
112
    }
113

114
    /* read uncompressed header from log file */
115
    ret = darshan_log_read(fd, header, sizeof(*header));
116
    if(ret != sizeof(*header))
117
    {
118
        fprintf(stderr, "Error: failed to read darshan log file header.\n");
119 120 121
        return(-1);
    }

122 123
    /* save the version string */
    strncpy(fd->version, header->version_string, 8);
124

125
    if(header->magic_nr == DARSHAN_MAGIC_NR)
126
    {
127
        /* no byte swapping needed, this file is in host format already */
128 129 130 131 132 133
        fd->swap_flag = 0;
    }
    else
    {
        /* try byte swapping */
        DARSHAN_BSWAP64(&header->magic_nr);
134
        if(header->magic_nr == DARSHAN_MAGIC_NR)
135 136
        {
            fd->swap_flag = 1;
137 138 139 140

            /* swap the log map variables in the header */
            DARSHAN_BSWAP64(&header->rec_map.off);
            DARSHAN_BSWAP64(&header->rec_map.len);
141
            for(i = 0; i < DARSHAN_MAX_MODS; i++)
142 143 144 145
            {
                DARSHAN_BSWAP64(&header->mod_map[i].off);
                DARSHAN_BSWAP64(&header->mod_map[i].len);
            }
146 147 148 149 150 151 152
        }
        else
        {
            /* otherwise this file is just broken */
            fprintf(stderr, "Error: bad magic number in darshan log file.\n");
            return(-1);
        }
153 154
    }

155
    /* save the mapping of data within log file to this file descriptor */
156 157
    fd->job_map.off = sizeof(struct darshan_header);
    fd->job_map.len = header->rec_map.off - fd->job_map.off;
158 159
    memcpy(&fd->rec_map, &header->rec_map, sizeof(struct darshan_log_map));
    memcpy(&fd->mod_map, &header->mod_map, DARSHAN_MAX_MODS * sizeof(struct darshan_log_map));
160 161

    return(0);
162
}
163

164
#if 0
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
/* darshan_log_putheader()
 *
 * write a darshan header to log file
 *
 * returns 0 on success, -1 on failure
 */
int darshan_log_putheader(darshan_fd fd, struct darshan_header *header)
{
    int ret;

    ret = darshan_log_seek(fd, 0);
    if(ret < 0)
    {
        fprintf(stderr, "Error: unable to seek in darshan log file.\n");
        return(-1);
    }

    /* write header to file */
    ret = darshan_log_write(fd, header, sizeof(*header));
    if(ret != sizeof(*header))
    {
        fprintf(stderr, "Error: failed to write Darshan log file header.\n");
        return(-1);
    }

    /* copy the mapping information to the file descriptor */
    memcpy(&fd->rec_map, &header->rec_map, sizeof(struct darshan_log_map));
    memcpy(&fd->mod_map, &header->mod_map, DARSHAN_MAX_MODS * sizeof(struct darshan_log_map));

    return(0);
}
196
#endif
197

198
/* darshan_log_getjob()
199 200
 *
 * read job level metadata from the darshan log file
201
 *
202
 * returns 0 on success, -1 on failure
203
 */
204
int darshan_log_getjob(darshan_fd fd, struct darshan_job *job)
205
{
206 207 208
    char *comp_buf;
    char job_buf[DARSHAN_JOB_RECORD_SIZE] = {0};
    int job_buf_sz = DARSHAN_JOB_RECORD_SIZE;
209
    int ret;
210

211 212 213 214 215 216
    /* allocate buffer to store compressed job info */
    comp_buf = malloc(fd->job_map.len);
    if(!comp_buf)
        return(-1);

    ret = darshan_log_seek(fd, fd->job_map.off);
217
    if(ret < 0)
218
    {
219
        fprintf(stderr, "Error: unable to seek in darshan log file.\n");
220
        free(comp_buf);
221
        return(-1);
222 223
    }

224 225 226
    /* read the compressed job data from the log file */
    ret = darshan_log_read(fd, comp_buf, fd->job_map.len);
    if(ret != fd->job_map.len)
227
    {
228
        fprintf(stderr, "Error: failed to read darshan log file job data.\n");
229 230 231 232 233 234 235 236 237 238
        free(comp_buf);
        return(-1);
    }

    /* decompress the job data */
    ret = darshan_decompress_buf(comp_buf, fd->job_map.len, job_buf, &job_buf_sz);
    if(ret < 0)
    {
        fprintf(stderr, "Error: failed to decompress darshan job data.\n");
        free(comp_buf);
239 240
        return(-1);
    }
241 242 243 244
    assert(job_buf_sz == DARSHAN_JOB_RECORD_SIZE);
    free(comp_buf);

    memcpy(job, job_buf, sizeof(*job));
245

246
    if(fd->swap_flag)
247
    {
248 249 250 251 252 253
        /* swap bytes if necessary */
        DARSHAN_BSWAP64(&job->uid);
        DARSHAN_BSWAP64(&job->start_time);
        DARSHAN_BSWAP64(&job->end_time);
        DARSHAN_BSWAP64(&job->nprocs);
        DARSHAN_BSWAP64(&job->jobid);
254 255
    }

256 257 258 259 260 261 262
    /* save trailing exe & mount information, so it can be retrieved later */
    if(!fd->exe_mnt_data)
        fd->exe_mnt_data = malloc(DARSHAN_EXE_LEN+1);
    if(!fd->exe_mnt_data)
        return(-1);
    memcpy(fd->exe_mnt_data, &job_buf[sizeof(*job)], DARSHAN_EXE_LEN+1);

263 264 265
    return(0);
}

266
#if 0
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
/* darshan_log_putjob()
 *
 * write job level metadat to darshan log file
 *
 * returns 0 on success, -1 on failure
 */
int darshan_log_putjob(darshan_fd fd, struct darshan_job *job)
{
    struct darshan_job job_copy;
    int len;
    int ret;

    ret = darshan_log_seek(fd, sizeof(struct darshan_header));
    if(ret < 0)
    {
        fprintf(stderr, "Error: unable to seek in darshan log file.\n");
        return(-1);
    }

    memset(&job_copy, 0, sizeof(*job));
    memcpy(&job_copy, job, sizeof(*job));

    /* check for newline in existing metadata, add if needed */
    len = strlen(job_copy.metadata);
    if(len > 0 && len < DARSHAN_JOB_METADATA_LEN)
    {
        if(job_copy.metadata[len-1] != '\n')
        {
            job_copy.metadata[len] = '\n';
            job_copy.metadata[len+1] = '\0';
        }
    }

    /* write job data to file */
    ret = darshan_log_write(fd, job, sizeof(*job));
    if(ret != sizeof(*job))
    {
        fprintf(stderr, "Error: failed to write darshan log file job data.\n");
        return(-1);
    }

    return(0);
}
310
#endif
311 312 313 314 315 316 317

/* darshan_log_getexe()
 *
 * reads the application exe name from darshan log file
 * 
 * returns 0 on success, -1 on failure 
 */
318 319 320
int darshan_log_getexe(darshan_fd fd, char *buf)
{
    char *newline;
321
    int ret;
322

323 324
    /* if the exe/mount data has not been saved yet, read in the job info */
    if(!fd->exe_mnt_data)
325
    {
326 327
        struct darshan_job job;
        ret = darshan_log_getjob(fd, &job);
328

329 330
        if(ret < 0 || !fd->exe_mnt_data)
            return(-1);
331
    }
332

333 334 335 336
    /* exe string is located before the first line break */
    newline = strchr(fd->exe_mnt_data, '\n');

    /* copy over the exe string */
337
    if(newline)
338
        memcpy(buf, fd->exe_mnt_data, (newline - fd->exe_mnt_data));
339 340 341 342

    return (0);
}

343
#if 0
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
/* darshan_log_putexe()
 *
 * wrties the application exe name to darshan log file
 *
 * returns 0 on success, -1 on failure 
 */
int darshan_log_putexe(darshan_fd fd, char *buf)
{
    int tmp_off = sizeof(struct darshan_header) + sizeof(struct darshan_job);
    int len;
    int ret;

    ret = darshan_log_seek(fd, tmp_off);
    if(ret < 0)
    {
        fprintf(stderr, "Error: unable to seek in darshan log file.\n");
        return(-1);
    }

    len = strlen(buf);

    ret = darshan_log_write(fd, buf, len);
    if(ret != len)
    {
        fprintf(stderr, "Error: failed to write exe string to darshan log file.\n");
        return(-1);
    }

    return(0);
}
374
#endif
375

376 377
/* darshan_log_getmounts()
 * 
378
 * retrieves mount table information from the log. Note that mnt_pts and
379
 * fs_types are arrays that will be allocated by the function and must be
380 381 382
 * freed by the caller. count will indicate the size of the arrays
 *
 * returns 0 on success, -1 on failure
383
 */
384
int darshan_log_getmounts(darshan_fd fd, char*** mnt_pts,
385 386 387 388
    char*** fs_types, int* count)
{
    char *pos;
    int array_index = 0;
389
    int ret;
390

391 392
    /* if the exe/mount data has not been saved yet, read in the job info */
    if(!fd->exe_mnt_data)
393
    {
394 395
        struct darshan_job job;
        ret = darshan_log_getjob(fd, &job);
396

397 398
        if(ret < 0 || !fd->exe_mnt_data)
            return(-1);
399
    }
400

401
    /* count entries */
402
    *count = 0;
403
    pos = fd->exe_mnt_data;
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
    while((pos = strchr(pos, '\n')) != NULL)
    {
        pos++;
        (*count)++;
    }

    if(*count == 0)
    {
        /* no mount entries present */
        return(0);
    }

    /* allocate output arrays */
    *mnt_pts = malloc((*count)*sizeof(char*));
    assert(*mnt_pts);
    *fs_types = malloc((*count)*sizeof(char*));
    assert(*fs_types);

    /* work backwards through the table and parse each line (except for
     * first, which holds command line information)
     */
425
    while((pos = strrchr(fd->exe_mnt_data, '\n')) != NULL)
426 427
    {
        /* overestimate string lengths */
428
        (*mnt_pts)[array_index] = malloc(DARSHAN_EXE_LEN);
429
        assert((*mnt_pts)[array_index]);
430
        (*fs_types)[array_index] = malloc(DARSHAN_EXE_LEN);
431 432
        assert((*fs_types)[array_index]);

433 434 435
        ret = sscanf(++pos, "%s\t%s", (*fs_types)[array_index],
            (*mnt_pts)[array_index]);
        if(ret != 2)
436
        {
437
            fprintf(stderr, "Error: poorly formatted mount table in darshan log file.\n");
438 439 440 441 442 443 444
            return(-1);
        }
        pos--;
        *pos = '\0';
        array_index++;
    }

445 446 447
    return(0);
}

448
#if 0
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
/* darshan_log_putmounts()
 *
 * writes mount information to the darshan log file
 * NOTE: this function call should follow immediately after the call
 * to darshan_log_putexe(), as it assumes the darshan log file pointer
 * is pointing to the offset immediately following the exe string
 *
 * returns 0 on success, -1 on failure
 */
int darshan_log_putmounts(darshan_fd fd, char** mnt_pts, char** fs_types, int count)
{
    int i;
    char line[1024];
    int ret;

    /* write each mount entry to file */
    for(i=count-1; i>=0; i--)
    {
        sprintf(line, "\n%s\t%s", fs_types[i], mnt_pts[i]);
        ret = darshan_log_write(fd, line, strlen(line));
        if (ret != strlen(line))
        {
            fprintf(stderr, "Error: failed to write darshan log mount entry.\n");
            return(-1);
        }
    }

    /* seek ahead to end of exe region, will be zero filled */
    ret = darshan_log_seek(fd, DARSHAN_JOB_RECORD_SIZE);
    if (ret < 0)
    {
        fprintf(stderr, "Error: unable to seek forward in darshan log file.\n");
        return(-1);
    }

    return(0);
}
486
#endif
487

488
/* darshan_log_gethash()
489
 *
490
 * read the hash of records from the darshan log file
491 492 493
 *
 * returns 0 on success, -1 on failure
 */
494
int darshan_log_gethash(darshan_fd fd, struct darshan_record_ref **hash)
495
{
496
    char *comp_buf;
497
    char *hash_buf;
498
    int hash_buf_sz;
499
    char *buf_ptr;
500 501 502 503
    darshan_record_id *rec_id_ptr;
    uint32_t *path_len_ptr;
    char *path_ptr;
    struct darshan_record_ref *ref;
504 505
    int ret;

506 507 508 509 510 511 512 513 514 515
    /* allocate buffers to store compressed and decompressed record
     * hash data
     */
    comp_buf = malloc(fd->rec_map.len);
    hash_buf = malloc(DARSHAN_DEF_COMP_BUF_SZ);
    if(!comp_buf || !hash_buf)
        return(-1);
    hash_buf_sz = DARSHAN_DEF_COMP_BUF_SZ;
    memset(hash_buf, 0, DARSHAN_DEF_COMP_BUF_SZ);

516
    ret = darshan_log_seek(fd, fd->rec_map.off);
517
    if(ret < 0)
518 519
    {
        fprintf(stderr, "Error: unable to seek in darshan log file.\n");
520
        free(comp_buf);
521
        return(-1);
522
    }
523

524
    /* read the record hash from the log file */
525
    ret = darshan_log_read(fd, comp_buf, fd->rec_map.len);
526
    if(ret != fd->rec_map.len)
527
    {
528
        fprintf(stderr, "Error: failed to read record hash from darshan log file.\n");
529 530 531 532 533 534 535 536 537 538 539
        free(comp_buf);
        return(-1);
    }

    /* decompress the record hash buffer */
    ret = darshan_decompress_buf(comp_buf, fd->rec_map.len,
        hash_buf, &hash_buf_sz);
    if(ret < 0)
    {
        fprintf(stderr, "Error: unable to decompress darshan job data.\n");
        free(comp_buf);
540 541
        return(-1);
    }
542
    free(comp_buf);
543

544
    buf_ptr = hash_buf;
545
    while(buf_ptr < (hash_buf + hash_buf_sz))
546
    {
547
        /* get pointers for each field of this darshan record */
548
        /* NOTE: darshan record hash serialization method: 
549 550
         *          ... darshan_record_id | (uint32_t) path_len | path ...
         */
551 552 553 554 555 556 557 558
        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;

        if(fd->swap_flag)
559
        {
560 561 562
            /* we need to sort out endianness issues before deserializing */
            DARSHAN_BSWAP64(rec_id_ptr);
            DARSHAN_BSWAP32(path_len_ptr);
563 564
        }

565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
        HASH_FIND(hlink, *hash, rec_id_ptr, sizeof(darshan_record_id), ref);
        if(!ref)
        {
            ref = malloc(sizeof(*ref));
            if(!ref)
            {
                return(-1);
            }
            ref->rec.name = malloc(*path_len_ptr + 1);
            if(!ref->rec.name)
            {
                free(ref);
                return(-1);
            }

            /* 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';
584

585 586 587
            /* add this record to the hash */
            HASH_ADD(hlink, *hash, rec.id, sizeof(darshan_record_id), ref);
        }
588 589
    }

590
    free(hash_buf);
591 592 593
    return(0);
}

594
#if 0
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
/* darshan_log_puthash()
 *
 * writes the hash table of records to the darshan log file
 *
 * returns 0 on success, -1 on failure
 */
int darshan_log_puthash(darshan_fd fd, struct darshan_record_ref *hash)
{
    size_t hash_buf_sz;
    char *hash_buf;
    char *hash_buf_off;
    struct darshan_record_ref *ref, *tmp;
    uint32_t name_len;
    size_t record_sz;
    int ret;

    ret = darshan_log_seek(fd, fd->rec_map.off);
    if(ret < 0)
    {
        fprintf(stderr, "Error: unable to seek in darshan log file.\n");
        return(-1);
    }

    /* allocate a buffer to store 2 MiB worth of record data */
    /* NOTE: this buffer may be reallocated if estimate is too small */
    hash_buf_sz = 2 * 1024 * 1024;
    hash_buf = malloc(hash_buf_sz);
    if(!hash_buf)
    {
        return(-1);
    }

    /* serialize the record hash into a buffer for writing */
    hash_buf_off = hash_buf;
    HASH_ITER(hlink, hash, ref, tmp)
    {
        name_len = strlen(ref->rec.name);
        record_sz = sizeof(darshan_record_id) + sizeof(uint32_t) + name_len;
        /* make sure there is room in the buffer for this record */
        if((hash_buf_off + record_sz) > (hash_buf + hash_buf_sz))
        {
            char *tmp_buf;
            size_t old_buf_sz;

            /* if no room, reallocate the hash buffer at twice the current size */
            old_buf_sz = hash_buf_off - hash_buf;
            hash_buf_sz *= 2;
            tmp_buf = malloc(hash_buf_sz);
            if(!tmp_buf)
            {
                free(hash_buf);
                return(-1);
            }

            memcpy(tmp_buf, hash_buf, old_buf_sz);
            free(hash_buf);
            hash_buf = tmp_buf;
            hash_buf_off = hash_buf + old_buf_sz;
        }

        /* now serialize the record into the hash buffer.
         * NOTE: darshan record hash serialization method: 
         *          ... darshan_record_id | (uint32_t) path_len | path ...
         */
        *((darshan_record_id *)hash_buf_off) = ref->rec.id;
        hash_buf_off += sizeof(darshan_record_id);
        *((uint32_t *)hash_buf_off) = name_len;
        hash_buf_off += sizeof(uint32_t);
        memcpy(hash_buf_off, ref->rec.name, name_len);
        hash_buf_off += name_len;
    }

    /* collectively write out the record hash to the darshan log */
    hash_buf_sz = hash_buf_off - hash_buf;

    /* write the record hash to file */
    ret = darshan_log_write(fd, hash_buf, hash_buf_sz);
    if(ret != hash_buf_sz)
    {
        fprintf(stderr, "Error: failed to write record hash to darshan log file.\n");
        return(-1);
    }

    free(hash_buf);

    return(0);
}
682
#endif
683 684 685

/* darshan_log_getmod()
 *
686
 * returns 1 on successful read of module data, 0 on no data, -1 on failure
687 688
 */
int darshan_log_getmod(darshan_fd fd, darshan_module_id mod_id,
689
    void *mod_buf, int *mod_buf_sz)
690
{
691
    char *comp_buf;
692
    int ret;
693

694
    if(mod_id < 0 || mod_id >= DARSHAN_MAX_MODS)
695
    {
696 697
        fprintf(stderr, "Error: invalid Darshan module id.\n");
        return(-1);
698 699
    }

700 701 702 703 704
    if(fd->mod_map[mod_id].len == 0)
        return(0); /* no data corresponding to this mod_id */

    comp_buf = malloc(fd->mod_map[mod_id].len);
    if(!comp_buf)
705
        return(-1);
706 707 708 709 710 711 712

    ret = darshan_log_seek(fd, fd->mod_map[mod_id].off);
    if(ret < 0)
    {
        fprintf(stderr, "Error: unable to seek in darshan log file.\n");
        free(comp_buf);
        return(ret);
713 714
    }

715 716 717
    /* read this module's data from the log file */
    ret = darshan_log_read(fd, comp_buf, fd->mod_map[mod_id].len);
    if(ret != fd->mod_map[mod_id].len)
718
    {
719
        fprintf(stderr,
720
            "Error: failed to read module %s data from darshan log file.\n",
721
            darshan_module_names[mod_id]);
722
        free(comp_buf);
723 724 725
        return(-1);
    }

726 727 728 729 730 731 732 733 734 735 736 737
    /* decompress this module's data */
    ret = darshan_decompress_buf(comp_buf, fd->mod_map[mod_id].len,
        mod_buf, mod_buf_sz);
    if(ret < 0)
    {
        fprintf(stderr, "Error: unable to decompress module %s data.\n",
            darshan_module_names[mod_id]);
        free(comp_buf);
        return(-1);
    }
    free(comp_buf);

738
    return(1);
739 740
}

741
#if 0
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
/* darshan_log_putmod()
 *
 * write a chunk of module data to the darshan log file
 *
 * returns 0 on success, -1 on failure
 */
int darshan_log_putmod(darshan_fd fd, darshan_module_id mod_id,
    void *mod_buf, int mod_buf_sz)
{
    int mod_buf_end = fd->mod_map[mod_id].off + fd->mod_map[mod_id].len;
    int ret;

    if(!fd->mod_map[mod_id].len)
    {
        fprintf(stderr, "Error: attempting to write data for empty module.\n");
        return(-1);
    }

    /* only seek to start of module data if current log file position 
     * is not within the given mod_id's range. This allows one to
     * repeatedly call this function and put chunks of a module's
     * data piecemeal.
     */
    if((fd->pos < fd->mod_map[mod_id].off) || (fd->pos > mod_buf_end))
    {
        ret = darshan_log_seek(fd, fd->mod_map[mod_id].off);
        if(ret < 0)
        {
            fprintf(stderr, "Error: unable to seek in darshan log file.\n");
            return(-1);
        }
    }

    /* if the given data violates stored mapping info, error out */
    if(mod_buf_sz > (mod_buf_end - fd->pos))
    {
        fprintf(stderr, "Error: module data write violates stored mapping information.\n");
        return(-1);
    }

    /* write the module chunk to the log file */
    ret = darshan_log_write(fd, mod_buf, mod_buf_sz);
    if(ret != mod_buf_sz)
    {
        fprintf(stderr,
            "Error: failed to write module %s data to darshan log file.\n",
            darshan_module_names[mod_id]);
        return(-1);
    }

    return(0);
}
794
#endif 
795

796 797 798 799 800 801 802
/* darshan_log_close()
 *
 * close an open darshan file descriptor
 *
 * returns 0 on success, -1 on failure
 */
void darshan_log_close(darshan_fd fd)
803
{
804 805 806 807 808
    if(fd->fildes)
        close(fd->fildes);

    if(fd->exe_mnt_data)
        free(fd->exe_mnt_data);
809

810
    free(fd);
811 812

    return;
813 814
}

815
/* **************************************************** */
816

817 818 819 820
/* return 0 on successful seek to offset, -1 on failure.
 */
static int darshan_log_seek(darshan_fd fd, off_t offset)
{
821
    off_t ret_off;
822 823 824 825

    if(fd->pos == offset)
        return(0);

826 827
    ret_off = lseek(fd->fildes, offset, SEEK_SET);
    if(ret_off == offset)
828
    {
829 830
        fd->pos = offset;
        return(0);
831 832 833 834 835
    }

    return(-1);
}

836
/* return amount read on success, 0 on EOF, -1 on failure.
837
 */
838
static int darshan_log_read(darshan_fd fd, void* buf, int len)
839 840 841
{
    int ret;

842 843 844 845
    /* read data from the log file using the given map */
    ret = read(fd->fildes, buf, len);
    if(ret > 0)
        fd->pos += ret;
846

847
    return(ret);
848 849
}

850
/* return amount written on success, -1 on failure.
851
 */
852
static int darshan_log_write(darshan_fd fd, void* buf, int len)
853 854 855
{
    int ret;

856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
    ret = write(fd->fildes, buf, len);
    if(ret > 0)
        fd->pos += ret;

    return(ret);
}

/* return 0 on successful decompression, -1 on failure
 */
static int darshan_decompress_buf(char* comp_buf, int comp_buf_sz,
    char* decomp_buf, int* inout_decomp_buf_sz)
{
    int ret;
    int total_out = 0;
    z_stream tmp_stream;

    memset(&tmp_stream, 0, sizeof(tmp_stream));
    tmp_stream.zalloc = Z_NULL;
    tmp_stream.zfree = Z_NULL;
    tmp_stream.opaque = Z_NULL;
    tmp_stream.next_in = (unsigned char*)comp_buf;
    tmp_stream.avail_in = comp_buf_sz;
    tmp_stream.next_out = (unsigned char*)decomp_buf;
    tmp_stream.avail_out = *inout_decomp_buf_sz;

    /* initialize the zlib decompression parameters */
    /* TODO: check these parameters? */
    //ret = inflateInit2(&tmp_stream, 31);
    ret = inflateInit(&tmp_stream);
    if(ret != Z_OK)
886
    {
887
        return(-1);
888 889
    }

890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925
    /* while we have not finished consuming all of the compressed input data */
    while(tmp_stream.avail_in)
    {
        if(tmp_stream.avail_out == 0)
        {
            /* We ran out of buffer space for compression.  In theory,
             * we could just alloc more space, but probably just easier
             * to bump up the default size of the output buffer.
             */
            inflateEnd(&tmp_stream);
            return(-1);
        }

        /* decompress data */
        ret = inflate(&tmp_stream, Z_FINISH);
        if(ret != Z_STREAM_END)
        {
            inflateEnd(&tmp_stream);
            return(-1);
        }

        total_out += tmp_stream.total_out;
        if(tmp_stream.avail_in)
            inflateReset(&tmp_stream);
    }
    inflateEnd(&tmp_stream);

    *inout_decomp_buf_sz = total_out;
    return(0);
}

static int darshan_compress_buf(char* decomp_buf, int decomp_buf_sz,
    char* comp_buf, int* inout_comp_buf_sz)
{

    return(0);
926
}
927 928 929 930 931 932 933 934 935

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ts=8 sts=4 sw=4 expandtab
 */