Exemplo n.º 1
0
/*
 *  appSetup(argc, argv);
 *
 *    Perform all the setup for this application include setting up
 *    required modules, parsing options, etc.  This function should be
 *    passed the same arguments that were passed into main().
 *
 *    Returns to the caller if all setup succeeds.  If anything fails,
 *    this function will cause the application to exit with a FAILURE
 *    exit status.
 */
static void
appSetup(
    int                 argc,
    char              **argv)
{
    SILK_FEATURES_DEFINE_STRUCT(features);
    unsigned int optctx_flags;
    sk_file_header_t *silk_hdr;
    int logmask;
    int rv;

    /* verify same number of options and help strings */
    assert((sizeof(appHelp)/sizeof(char *)) ==
           (sizeof(appOptions)/sizeof(struct option)));

    /* register the application */
    skAppRegister(argv[0]);
    skAppVerifyFeatures(&features, NULL);
    skOptionsSetUsageCallback(&appUsageLong);

    optctx_flags = (SK_OPTIONS_CTX_INPUT_BINARY | SK_OPTIONS_CTX_XARGS);

    /* register the options */
    if (skOptionsCtxCreate(&optctx, optctx_flags)
        || skOptionsCtxOptionsRegister(optctx)
        || skOptionsRegister(appOptions, &appOptionsHandler, NULL)
        || skOptionsNotesRegister(NULL)
        || skCompMethodOptionsRegister(&comp_method))
    {
        skAppPrintErr("Unable to register options");
        exit(EXIT_FAILURE);
    }

    /* enable the logger */
    sklogSetup(0);
    sklogSetDestination("stderr");
    sklogSetStampFunction(&logprefix);

    /* register the teardown handler */
    if (atexit(appTeardown) < 0) {
        skAppPrintErr("Unable to register appTeardown() with atexit()");
        appTeardown();
        exit(EXIT_FAILURE);
    }

    /* parse the options */
    rv = skOptionsCtxOptionsParse(optctx, argc, argv);
    if (rv < 0) {
        skAppUsage();           /* never returns */
    }

    if ('\0' == log_destination[0]) {
        strncpy(log_destination, LOG_DESTINATION_DEFAULT,
                sizeof(log_destination));
    } else {
        sklogSetLevel("debug");
    }
    sklogSetDestination(log_destination);

    /* default output is "stdout" */
    if (!silk_output) {
        if ((rv =skStreamCreate(&silk_output,SK_IO_WRITE,SK_CONTENT_SILK_FLOW))
            || (rv = skStreamBind(silk_output, "-")))
        {
            skStreamPrintLastErr(silk_output, rv, &skAppPrintErr);
            exit(EXIT_FAILURE);
        }
    }

    /* get the header */
    silk_hdr = skStreamGetSilkHeader(silk_output);

    /* open the output */
    if ((rv = skHeaderSetCompressionMethod(silk_hdr, comp_method))
        || (rv = skOptionsNotesAddToStream(silk_output))
        || (rv = skHeaderAddInvocation(silk_hdr, 1, argc, argv))
        || (rv = skStreamOpen(silk_output))
        || (rv = skStreamWriteSilkHeader(silk_output)))
    {
        skStreamPrintLastErr(silk_output, rv, &skAppPrintErr);
        exit(EXIT_FAILURE);
    }

    if (skpcSetup()) {
        exit(EXIT_FAILURE);
    }
    if (skpcProbeCreate(&probe, PROBE_ENUM_NETFLOW_V5)) {
        exit(EXIT_FAILURE);
    }
    skpcProbeSetName(probe, skAppName());
    skpcProbeSetFileSource(probe, "/dev/null");
    if (parseLogFlags(log_flags)) {
        exit(EXIT_FAILURE);
    }
    if (skpcProbeVerify(probe, 0)) {
        exit(EXIT_FAILURE);
    }

    /* set level to "warning" to avoid the "Started logging" message */
    logmask = sklogGetMask();
    sklogSetLevel("warning");
    sklogOpen();
    sklogSetMask(logmask);

    return;                     /* OK */
}
Exemplo n.º 2
0
/*
 *  sortRandom();
 *
 *    Don't make any assumptions about the input.  Store the input
 *    records in a large buffer, and sort those in-core records once
 *    all records are processed or the buffer is full.  If the buffer
 *    fills up, store the sorted records into temporary files.  Once
 *    all records are read, use mergeFiles() above to merge-sort the
 *    temporary files.
 *
 *    Exits the application if an error occurs.
 */
static void
sortRandom(
    void)
{
    int temp_file_idx = -1;
    skstream_t *input_rwios = NULL; /* input stream */
    uint8_t *record_buffer = NULL;  /* Region of memory for records */
    uint8_t *cur_node = NULL;       /* Ptr into record_buffer */
    uint8_t *next_node = NULL;      /* Ptr into record_buffer */
    uint32_t buffer_max_recs;       /* max buffer size (in number of recs) */
    uint32_t buffer_recs;           /* current buffer size (# records) */
    uint32_t buffer_chunk_recs;     /* how to grow from current to max buf */
    uint32_t num_chunks;            /* how quickly to grow buffer */
    uint32_t record_count = 0;      /* Number of records read */
    int rv;

    /* Determine the maximum number of records that will fit into the
     * buffer if it grows the maximum size */
    buffer_max_recs = buffer_size / NODE_SIZE;
    TRACEMSG((("buffer_size = %" PRIu64
               "\nnode_size = %" PRIu32
               "\nbuffer_max_recs = %" PRIu32),
              buffer_size, NODE_SIZE, buffer_max_recs));

    /* We will grow to the maximum size in chunks */
    num_chunks = NUM_CHUNKS;
    if (num_chunks <= 0) {
        num_chunks = 1;
    }

    /* Attempt to allocate the initial chunk.  If we fail, increment
     * the number of chunks---which will decrease the amount we
     * attempt to allocate at once---and try again. */
    for (;;) {
        buffer_chunk_recs = buffer_max_recs / num_chunks;
        TRACEMSG((("num_chunks = %" PRIu32
                   "\nbuffer_chunk_recs = %" PRIu32),
                  num_chunks, buffer_chunk_recs));

        record_buffer = (uint8_t*)malloc(NODE_SIZE * buffer_chunk_recs);
        if (record_buffer) {
            /* malloc was successful */
            break;
        } else if (buffer_chunk_recs < MIN_IN_CORE_RECORDS) {
            /* give up at this point */
            skAppPrintErr("Error allocating space for %d records",
                          MIN_IN_CORE_RECORDS);
            appExit(EXIT_FAILURE);
        } else {
            /* reduce the amount we allocate at once by increasing the
             * number of chunks and try again */
            TRACEMSG(("malloc() failed"));
            ++num_chunks;
        }
    }

    buffer_recs = buffer_chunk_recs;
    TRACEMSG((("buffer_recs = %" PRIu32), buffer_recs));

    /* open first file */
    rv = appNextInput(&input_rwios);
    if (rv < 0) {
        free(record_buffer);
        appExit(EXIT_FAILURE);
    }

    record_count = 0;
    cur_node = record_buffer;
    while (input_rwios != NULL) {
        /* read record */
        if ((rv = skStreamReadRecord(input_rwios, (rwRec*)cur_node))
            != SKSTREAM_OK)
        {
            if (rv != SKSTREAM_ERR_EOF) {
                skStreamPrintLastErr(input_rwios, rv, &skAppPrintErr);
            }
            /* end of file: close current and open next */
            skStreamDestroy(&input_rwios);
            rv = appNextInput(&input_rwios);
            if (rv < 0) {
                free(record_buffer);
                appExit(EXIT_FAILURE);
            }
            continue;
        }

        ++record_count;
        cur_node += NODE_SIZE;

        if (record_count == buffer_recs) {
            /* Filled the current buffer */

            /* If buffer not at max size, see if we can grow it */
            if (buffer_recs < buffer_max_recs) {
                uint8_t *old_buf = record_buffer;

                /* add a chunk of records.  if we are near the max,
                 * set the size to the max */
                buffer_recs += buffer_chunk_recs;
                if (buffer_recs + buffer_chunk_recs > buffer_max_recs) {
                    buffer_recs = buffer_max_recs;
                }
                TRACEMSG((("Buffer full---attempt to grow to %" PRIu32
                           " records, %" PRIu32 " bytes"),
                          buffer_recs, NODE_SIZE * buffer_recs));

                /* attempt to grow */
                record_buffer = (uint8_t*)realloc(record_buffer,
                                                  NODE_SIZE * buffer_recs);
                if (record_buffer) {
                    /* Success, make certain cur_node points into the
                     * new buffer */
                    cur_node = (record_buffer + (record_count * NODE_SIZE));
                } else {
                    /* Unable to grow it */
                    TRACEMSG(("realloc() failed"));
                    record_buffer = old_buf;
                    buffer_max_recs = buffer_recs = record_count;
                }
            }

            /* Either buffer at maximum size or attempt to grow it
             * failed. */
            if (record_count == buffer_max_recs) {
                /* Sort */
                skQSort(record_buffer, record_count, NODE_SIZE, &rwrecCompare);

                /* Write to temp file */
                if (skTempFileWriteBufferStream(
                        tmpctx, &temp_file_idx,
                        record_buffer, NODE_SIZE, record_count))
                {
                    skAppPrintSyserror(
                        "Error writing sorted buffer to temporary file");
                    free(record_buffer);
                    appExit(EXIT_FAILURE);
                }

                /* Reset record buffer to 'empty' */
                record_count = 0;
                cur_node = record_buffer;
            }
        }
    }

    /* Sort (and maybe store) last batch of records */
    if (record_count > 0) {
        skQSort(record_buffer, record_count, NODE_SIZE, &rwrecCompare);

        if (temp_file_idx >= 0) {
            /* Write last batch to temp file */
            if (skTempFileWriteBufferStream(
                    tmpctx, &temp_file_idx,
                    record_buffer, NODE_SIZE, record_count))
            {
                skAppPrintSyserror(
                    "Error writing sorted buffer to temporary file");
                free(record_buffer);
                appExit(EXIT_FAILURE);
            }
        }
    }

    /* Generate the output */

    if (record_count == 0 && temp_file_idx == -1) {
        /* No records were read at all; write the header to the output
         * file */
        rv = skStreamWriteSilkHeader(out_rwios);
        if (0 != rv) {
            skStreamPrintLastErr(out_rwios, rv, &skAppPrintErr);
        }
    } else if (temp_file_idx == -1) {
        /* No temp files written, just output batch of records */
        uint32_t c;

        TRACEMSG((("Writing %" PRIu32 " records to '%s'"),
                  record_count, skStreamGetPathname(out_rwios)));
        /* get first two records from the sorted buffer */
        cur_node = record_buffer;
        next_node = record_buffer + NODE_SIZE;
        for (c = 1; c < record_count; ++c, next_node += NODE_SIZE) {
            if (0 != rwrecCompare(cur_node, next_node)) {
                /* records differ. print earlier record */
                rv = skStreamWriteRecord(out_rwios, (rwRec*)cur_node);
                if (0 != rv) {
                    skStreamPrintLastErr(out_rwios, rv, &skAppPrintErr);
                    if (SKSTREAM_ERROR_IS_FATAL(rv)) {
                        free(record_buffer);
                        appExit(EXIT_FAILURE);
                    }
                }
                cur_node = next_node;
            }
            /* else records are duplicates: ignore latter record */
        }
        /* print remaining record */
        rv = skStreamWriteRecord(out_rwios, (rwRec*)cur_node);
        if (0 != rv) {
            skStreamPrintLastErr(out_rwios, rv, &skAppPrintErr);
            if (SKSTREAM_ERROR_IS_FATAL(rv)) {
                free(record_buffer);
                appExit(EXIT_FAILURE);
            }
        }
    } else {
        /* no longer have a need for the record buffer */
        free(record_buffer);
        record_buffer = NULL;

        /* now merge all the temp files */
        mergeFiles(temp_file_idx);
    }

    if (record_buffer) {
        free(record_buffer);
    }
}