Esempio n. 1
0
/*
 * Initializes the thread subsystem, creating various worker threads.
 *
 * nthreads  Number of worker event handler threads to spawn
 * main_base Event base for main thread
 */
void thread_init(int nthr, struct event_base *main_base,
                 void (*dispatcher_callback)(evutil_socket_t, short, void *)) {
    int i;
    nthreads = nthr + 1;

    cqi_freelist = NULL;

    cb_mutex_initialize(&conn_lock);
    cb_mutex_initialize(&cqi_freelist_lock);
    cb_mutex_initialize(&init_lock);
    cb_cond_initialize(&init_cond);

    threads = calloc(nthreads, sizeof(LIBEVENT_THREAD));
    if (! threads) {
        settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL,
                                        "Can't allocate thread descriptors: %s",
                                        strerror(errno));
        exit(1);
    }
    thread_ids = calloc(nthreads, sizeof(cb_thread_t));
    if (! thread_ids) {
        settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL,
                                        "Can't allocate thread descriptors: %s",
                                        strerror(errno));
        exit(1);
    }

    setup_dispatcher(main_base, dispatcher_callback);

    for (i = 0; i < nthreads; i++) {
        if (!create_notification_pipe(&threads[i])) {
            exit(1);
        }
        threads[i].index = i;

        setup_thread(&threads[i]);
    }

    /* Create threads after we've done all the libevent setup. */
    for (i = 0; i < nthreads; i++) {
        create_worker(worker_libevent, &threads[i], &thread_ids[i]);
        threads[i].thread_id = thread_ids[i];
    }

    /* Wait for all the threads to set themselves up before returning. */
    cb_mutex_enter(&init_lock);
    while (init_count < nthreads) {
        cb_cond_wait(&init_cond, &init_lock);
    }
    cb_mutex_exit(&init_lock);
}
Esempio n. 2
0
topkeys_t *topkeys_init(int max_keys) {
    static struct hash_ops my_hash_ops;
    topkeys_t *tk = calloc(sizeof(topkeys_t), 1);
    if (tk == NULL) {
        return NULL;
    }

    my_hash_ops.hashfunc = genhash_string_hash;
    my_hash_ops.hasheq = my_hash_eq;
    my_hash_ops.dupKey = NULL;
    my_hash_ops.dupValue = NULL;
    my_hash_ops.freeKey = NULL;
    my_hash_ops.freeValue = NULL;

    cb_mutex_initialize(&tk->mutex);
    tk->max_keys = max_keys;
    tk->list.next = &tk->list;
    tk->list.prev = &tk->list;

    tk->hash = genhash_init(max_keys, my_hash_ops);
    if (tk->hash == NULL) {
        return NULL;
    }

    return tk;
}
Esempio n. 3
0
/*
 * Set up a thread's information.
 */
static void setup_thread(LIBEVENT_THREAD *me) {
    me->type = GENERAL;
    me->base = event_base_new();
    if (! me->base) {
        settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL,
                                        "Can't allocate event base\n");
        exit(1);
    }

    /* Listen for notifications from other threads */
    event_set(&me->notify_event, me->notify[0],
              EV_READ | EV_PERSIST,
              thread_libevent_process, me);
    event_base_set(me->base, &me->notify_event);

    if (event_add(&me->notify_event, 0) == -1) {
        settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL,
                                        "Can't monitor libevent notify pipe\n");
        exit(1);
    }

    me->new_conn_queue = malloc(sizeof(struct conn_queue));
    if (me->new_conn_queue == NULL) {
        settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL,
                                        "Failed to allocate memory for connection queue");
        exit(EXIT_FAILURE);
    }
    cq_init(me->new_conn_queue);

    cb_mutex_initialize(&me->mutex);

    // Initialize threads' sub-document parser / handler
    me->subdoc_op = subdoc_op_alloc();
}
Esempio n. 4
0
cache_t* cache_create(const char *name, size_t bufsize, size_t align,
                      cache_constructor_t* constructor,
                      cache_destructor_t* destructor) {
    cache_t* ret = calloc(1, sizeof(cache_t));
    char* nm = strdup(name);
    void** ptr = calloc(initial_pool_size, bufsize);
    if (ret == NULL || nm == NULL || ptr == NULL) {
        free(ret);
        free(nm);
        free(ptr);
        return NULL;
    }
    cb_mutex_initialize(&ret->mutex);
    ret->name = nm;
    ret->ptr = ptr;
    ret->freetotal = initial_pool_size;
    ret->constructor = constructor;
    ret->destructor = destructor;

#ifndef NDEBUG
    ret->bufsize = bufsize + 2 * sizeof(redzone_pattern);
#else
    ret->bufsize = bufsize;
#endif
    (void)align;

    return ret;
}
Esempio n. 5
0
File: work.c Progetto: membase/moxi
/** The "work_collect" abstraction helps to make scatter/gather easier
 *  when using work queue's.  The main caller uses work_collect_init()
 *  to initialize the work_collect tracking data structure.  The
 *  work_collect structure is then scattered across worker threads
 *  (such as by using work_send()).  The main thread then calls
 *  work_collect_wait() to wait for N responses.  A worker thread
 *  invokes work_collect_one() when it's finished with its assigned
 *  work and has one response to contribute.  When N responses have
 *  been counted, work_collect_wait() returns control back to the
 *  main caller.
 */
int work_collect_init(work_collect *c, int count, void *data) {
    cb_assert(c);

    memset(c, 0, sizeof(work_collect));

    c->count = count;
    c->data  = data;
    cb_mutex_initialize(&c->collect_lock);
    cb_cond_initialize(&c->collect_cond);

    return 0;
}
Esempio n. 6
0
File: work.c Progetto: membase/moxi
/** A work queue is a mechanism to allow thread-to-thread
 *  communication in a libevent-based, multithreaded system.
 *
 *  One thread can send work to another thread.  The receiving thread
 *  should be libevent-based, with a processing loop handled by
 *  libevent.
 *
 *  Use work_queue_init() to initialize a work_queue structure,
 *  where the work_queue structure memory is owned by the caller.
 *
 *  Returns true on success.
 */
bool work_queue_init(work_queue *m, struct event_base *event_base) {
    cb_assert(m != NULL);

    memset(m, 0, sizeof(work_queue));

    cb_mutex_initialize(&m->work_lock);

    m->work_head = NULL;
    m->work_tail = NULL;

    m->num_items = 0;
    m->tot_sends = 0;
    m->tot_recvs = 0;

    m->event_base = event_base;
    cb_assert(m->event_base != NULL);

    if (!create_notification_pipe(m)) {
        return false;
    }

    event_set(&m->event, m->recv_fd,
              EV_READ | EV_PERSIST, work_recv, m);
    event_base_set(m->event_base, &m->event);

    if (event_add(&m->event, 0) == 0) {
#ifdef WORK_DEBUG
            moxi_log_write("work_queue_init %x %x %x %d %d %u %llu\n",
                    (int) pthread_self(),
                    (int) m,
                    (int) m->event_base,
                    m->send_fd,
                    m->recv_fd,
                    m->work_head != NULL,
                    m->tot_sends);
#endif

        return true;
    }

#ifdef WORK_DEBUG
    moxi_log_write("work_queue_init error\n");
#endif

    return false;
}
Esempio n. 7
0
void mcache_init(mcache *m, bool multithreaded,
                 mcache_funcs *funcs, bool key_alloc) {
    assert(m);
    assert(funcs);

    m->funcs       = funcs;
    m->key_alloc   = key_alloc;
    m->map         = NULL;
    m->max         = 0;
    m->lru_head    = NULL;
    m->lru_tail    = NULL;
    m->oldest_live = 0;

    if (multithreaded) {
        m->lock = malloc(sizeof(cb_mutex_t));
        if (m->lock != NULL) {
            cb_mutex_initialize(m->lock);
        }
    } else {
        m->lock = NULL;
    }

    mcache_reset_stats(m);
}
Esempio n. 8
0
/*
 * Initializes a connection queue.
 */
static void cq_init(CQ *cq) {
    cb_mutex_initialize(&cq->lock);
    cb_cond_initialize(&cq->cond);
    cq->head = NULL;
    cq->tail = NULL;
}