예제 #1
0
pthread_t setup_listener(config_t *config) {
    pthread_t server_tid= 0;

    socketize(config->argv[0], s_listen, IPPROTO_UDP, RELAY_CONN_IS_INBOUND, "listener" );

    /* must open the socket BEFORE we create the worker pool */
    open_socket(s_listen, DO_BIND|DO_REUSEADDR|DO_EPOLLFD, 0, config->server_socket_rcvbuf);

    /* create worker pool /after/ we open the socket, otherwise we
     * might leak worker threads. */

    if (s_listen->proto == IPPROTO_UDP)
        spawn(&server_tid, udp_server, s_listen, PTHREAD_CREATE_JOINABLE);
    else
        spawn(&server_tid, tcp_server, s_listen, PTHREAD_CREATE_JOINABLE);

    return server_tid;
}
예제 #2
0
/* initialize a worker safely */
socket_worker_t *socket_worker_create(const char *arg, const config_t * config)
{
    socket_worker_t *worker = calloc_or_fatal(sizeof(*worker));
    disk_writer_t *disk_writer = calloc_or_fatal(sizeof(disk_writer_t));

    if (worker == NULL || disk_writer == NULL)
        return NULL;

    int create_err;

    worker->base.config = config;
    worker->base.arg = strdup(arg);

    worker->exists = 1;

    if (!socketize(arg, &worker->base.output_socket, IPPROTO_TCP, RELAY_CONN_IS_OUTBOUND, "worker")) {
        FATAL("Failed to socketize worker");
        return NULL;
    }

    worker->disk_writer = disk_writer;

    disk_writer->base.config = config;
    disk_writer->counters = &worker->counters;
    disk_writer->recents = &worker->recents;
    disk_writer->totals = &worker->totals;

#define DECAY_1MIN 60
#define DECAY_5MIN (5 * DECAY_1MIN)
#define DECAY_15MIN (15 * DECAY_1MIN)

    rates_init(&worker->rates[0], DECAY_1MIN);
    rates_init(&worker->rates[1], DECAY_5MIN);
    rates_init(&worker->rates[2], DECAY_15MIN);

    LOCK_INIT(&worker->lock);

    /* setup spill_path */
    int wrote = snprintf(disk_writer->spill_path, PATH_MAX, "%s/event_relay.%s", config->spill_root,
                         worker->base.output_socket.arg_clean);
    if (wrote < 0 || wrote >= PATH_MAX) {
        FATAL("Failed to construct spill_path %s", disk_writer->spill_path);
        return NULL;
    }

    /* Create the disk_writer before we create the main worker.
     * We do this because the disk_writer only consumes things
     * that have been handled by the main worker, and vice versa
     * when the main worker fails to send then it might want to give
     * the item to the disk worker. If we did it the other way round
     * we might have something to assign to the disk worker but no
     * disk worker to assign it to.
     */
    create_err = pthread_create(&disk_writer->base.tid, NULL, disk_writer_thread, disk_writer);
    if (create_err) {
        FATAL("Failed to create disk worker, pthread error: %d", create_err);
        return NULL;
    }

    /* and finally create the thread */
    create_err = pthread_create(&worker->base.tid, NULL, socket_worker_thread, worker);
    if (create_err) {
        int join_err;

        /* we died, so shut down our "pet" disk worker, and then exit with a message */
        RELAY_ATOMIC_OR(disk_writer->base.stopping, WORKER_STOPPING);

        /* have to handle failure of the shutdown too */
        join_err = pthread_join(disk_writer->base.tid, NULL);

        if (join_err) {
            FATAL
                ("Failed to create socket worker, pthread error: %d, and also failed to join disk worker, pthread error: %d",
                 create_err, join_err);
        } else {
            FATAL("Failed to create socket worker, pthread error: %d, disk worker shut down ok", create_err);
        }
        return NULL;
    }

    /* return the worker */
    return worker;
}