staprun/stap_merge.c - systemtap

Functions defined

Macros defined

Source code

/*
* stap_merge.c - systemtap merge program
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) Red Hat Inc, 2005-2007
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

static void usage (char *prog)
{
    fprintf(stderr, "%s [-v] [-o output_filename] input_files ...\n", prog);
    exit(-1);
}

#define TIMESTAMP_SIZE (sizeof(int))
#define NR_CPUS 256

int main (int argc, char *argv[])
{
    char *buf, *outfile_name = NULL;
    int c, i, j, rc, dropped=0;
    long count=0, min, num[NR_CPUS] = { 0 };
    FILE *ofp = NULL;
    FILE *fp[NR_CPUS] = { 0 };
    int ncpus, len, verbose = 0;
    int bufsize = 65536;

    buf = malloc(bufsize);
    if (buf == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        exit(-2);
    }

    while ((c = getopt (argc, argv, "vo:")) != EOF)  {
        switch (c) {
        case 'v':
            verbose = 1;
            break;
        case 'o':
            outfile_name = optarg;
            break;
        default:
            usage(argv[0]);
        }
    }

    if (optind == argc)
        usage (argv[0]);

    i = 0;
    while (optind < argc) {
        fp[i] = fopen(argv[optind++], "r");
        if (!fp[i]) {
            fprintf(stderr, "error opening file %s.\n", argv[optind - 1]);
            return -1;
        }
        if (fread (buf, TIMESTAMP_SIZE, 1, fp[i]))
            num[i] = *((int *)buf);
        else
            num[i] = 0;
        i++;
    }
    ncpus = i;

    if (!outfile_name)
        ofp = stdout;
    else {
        ofp = fopen(outfile_name, "w");
        if (!ofp) {
            fprintf(stderr, "ERROR: couldn't open output file %s: errcode = %s\n",
                outfile_name, strerror(errno));
            return -1;
        }
    }

    do {
        min = num[0];
        j = 0;
        for (i = 1; i < ncpus; i++) {
            if (min == 0 || (num[i] && num[i] < min)) {
                min = num[i];
                j = i;
            }
        }

        if (fread(&len, sizeof(int), 1, fp[j])) {
            if (verbose)
                fprintf(stdout, "[CPU:%d, seq=%ld, length=%d]\n", j, min, len);
            if (len > bufsize) {
                bufsize = len;
                if (verbose) fprintf(stderr, "reallocating %d bytes\n", bufsize);
                buf = realloc(buf, bufsize);
                if (buf == NULL) {
                    fprintf(stderr, "Memory allocation failed.\n");
                    exit(-2);
                }
            }
            if ((rc = fread(buf, len, 1, fp[j])) <= 0 ) {
                fprintf(stderr, "fread error: got %d\n", rc);
                exit(-3);
            }
            if ((rc = fwrite(buf, len, 1, ofp)) <= 0 ) {
                fprintf(stderr, "fread error: got %d\n", rc);
                exit(-3);
            }
        }

        if (min && ++count != min) {
            fprintf(stderr, "got %ld. expected %ld\n", min, count);
            dropped += min - count ;
            count = min;
        }

        if (fread (buf, TIMESTAMP_SIZE, 1, fp[j]))
            num[j] = *((int *)buf);
        else
            num[j] = 0;
    } while (min);

    for (i = 0; i < ncpus; i++)
        fclose (fp[i]);
    fclose (ofp);
    printf ("sequence had %d drops\n", dropped);
    return 0;
}