void threads_shutdown(void) { int ii; for (ii = 0; ii < nthreads; ++ii) { notify_thread(&threads[ii]); cb_join_thread(thread_ids[ii]); } }
void threads_shutdown(void) { for (int ii = 0; ii < nthreads; ++ii) { notify_thread(&threads[ii]); pthread_join(thread_ids[ii], NULL); } for (int ii = 0; ii < nthreads; ++ii) { safe_close(threads[ii].notify[0]); safe_close(threads[ii].notify[1]); } }
/* * Dispatches a new connection to another thread. This is only ever called * from the main thread, either during initialization (for UDP) or because * of an incoming connection. */ void dispatch_conn_new(SOCKET sfd, STATE_FUNC init_state, int event_flags, int read_buffer_size, enum network_transport transport) { CQ_ITEM *item = cqi_new(); int tid = (last_thread + 1) % settings.num_threads; LIBEVENT_THREAD *thread = threads + tid; last_thread = tid; item->sfd = sfd; item->init_state = init_state; item->event_flags = event_flags; item->read_buffer_size = read_buffer_size; item->transport = transport; cq_push(thread->new_conn_queue, item); MEMCACHED_CONN_DISPATCH(sfd, (uintptr_t)thread->thread_id); notify_thread(thread); }
void threads_shutdown(void) { for (int ii = 0; ii < nthreads; ++ii) { notify_thread(&threads[ii]); pthread_join(thread_ids[ii], NULL); } for (int ii = 0; ii < nthreads; ++ii) { safe_close(threads[ii].notify[0]); safe_close(threads[ii].notify[1]); cache_destroy(threads[ii].suffix_cache); event_base_free(threads[ii].base); CQ_ITEM *it; while ((it = cq_pop(threads[ii].new_conn_queue)) != NULL) { cqi_free(it); } free(threads[ii].new_conn_queue); } free(thread_ids); free(threads); }
void notify_io_complete(const void *cookie, ENGINE_ERROR_CODE status) { struct conn *conn = (struct conn *)cookie; assert(conn); LIBEVENT_THREAD *thr = conn->thread; assert(thr); settings.extensions.logger->log(EXTENSION_LOG_DEBUG, NULL, "Got notify from %d, status %x\n", conn->sfd, status); LOCK_THREAD(thr); conn->aiostat = status; int notify = add_conn_to_pending_io_list(conn); UNLOCK_THREAD(thr); /* kick the thread in the butt */ if (notify) { notify_thread(thr); } }
void notify_dispatcher(void) { notify_thread(&dispatcher_thread); }
void notify_io_complete(const void *cookie, ENGINE_ERROR_CODE status) { if (cookie == NULL) { settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL, "notify_io_complete called without a valid cookie (status %x)\n", status); return ; } struct conn *conn = (struct conn *)cookie; settings.extensions.logger->log(EXTENSION_LOG_DEBUG, NULL, "Got notify from %d, status %x\n", conn->sfd, status); /* ** TROND: ** I changed the logic for the tap connections so that the core ** issues the ON_DISCONNECT call to the engine instead of trying ** to close the connection. Then it let's the engine have a grace ** period to call notify_io_complete if not it will go ahead and ** kill it. ** */ if (status == ENGINE_DISCONNECT && conn->thread == tap_thread) { LOCK_THREAD(conn->thread); /** Remove the connection from both of the lists */ conn->thread->pending_io = list_remove(conn->thread->pending_io, conn); conn->thread->pending_close = list_remove(conn->thread->pending_close, conn); if (conn->state == conn_pending_close || conn->state == conn_immediate_close) { if (conn->refcount == 1) { settings.extensions.logger->log(EXTENSION_LOG_DEBUG, NULL, "Complete shutdown of %p", conn); conn_set_state(conn, conn_immediate_close); enlist_conn(conn, &conn->thread->pending_close); } else { settings.extensions.logger->log(EXTENSION_LOG_DEBUG, NULL, "Keep on waiting for shutdown of %p", conn); } } else { settings.extensions.logger->log(EXTENSION_LOG_DEBUG, NULL, "Engine requested shutdown of %p", conn); conn_set_state(conn, conn_closing); enlist_conn(conn, &conn->thread->pending_io); } if (!is_thread_me(conn->thread)) { /* kick the thread in the butt */ notify_thread(conn->thread); } UNLOCK_THREAD(conn->thread); return; } /* ** There may be a race condition between the engine calling this ** function and the core closing the connection. ** Let's lock the connection structure (this might not be the ** correct one) and re-evaluate. */ LIBEVENT_THREAD *thr = conn->thread; if (thr == NULL || (conn->state == conn_closing || conn->state == conn_pending_close || conn->state == conn_immediate_close)) { return; } int notify = 0; LOCK_THREAD(thr); if (thr != conn->thread || !conn->ewouldblock) { // Ignore UNLOCK_THREAD(thr); return; } conn->aiostat = status; /* Move the connection to the closing state if the engine * wants it to be disconnected */ if (status == ENGINE_DISCONNECT) { conn->state = conn_closing; notify = 1; thr->pending_io = list_remove(thr->pending_io, conn); if (number_of_pending(conn, thr->pending_close) == 0) { enlist_conn(conn, &thr->pending_close); } } else { if (number_of_pending(conn, thr->pending_io) + number_of_pending(conn, thr->pending_close) == 0) { if (thr->pending_io == NULL) { notify = 1; } enlist_conn(conn, &thr->pending_io); } } UNLOCK_THREAD(thr); /* kick the thread in the butt */ if (notify) { notify_thread(thr); } }