diff --git a/server/core/dcb.cc b/server/core/dcb.cc index fc0a4ba28..20dd6bdfc 100644 --- a/server/core/dcb.cc +++ b/server/core/dcb.cc @@ -3512,3 +3512,145 @@ dcb_session_check(DCB *dcb, const char *function) return false; } } + +int poll_add_dcb(DCB *dcb) +{ + int rc = -1; + dcb_state_t old_state = dcb->state; + dcb_state_t new_state; + uint32_t events = 0; + + CHK_DCB(dcb); + +#ifdef EPOLLRDHUP + events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLHUP | EPOLLET; +#else + events = EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLET; +#endif + + /*< + * Choose new state according to the role of dcb. + */ + if (dcb->dcb_role == DCB_ROLE_CLIENT_HANDLER || dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER) + { + new_state = DCB_STATE_POLLING; + } + else + { + ss_dassert(dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER); + new_state = DCB_STATE_LISTENING; + } + /* + * Check DCB current state seems sensible + */ + if (DCB_STATE_DISCONNECTED == dcb->state + || DCB_STATE_ZOMBIE == dcb->state + || DCB_STATE_UNDEFINED == dcb->state) + { + MXS_ERROR("%lu [poll_add_dcb] Error : existing state of dcb %p " + "is %s, but this should be impossible, crashing.", + pthread_self(), + dcb, + STRDCBSTATE(dcb->state)); + raise(SIGABRT); + } + if (DCB_STATE_POLLING == dcb->state + || DCB_STATE_LISTENING == dcb->state) + { + MXS_ERROR("%lu [poll_add_dcb] Error : existing state of dcb %p " + "is %s, but this is probably an error, not crashing.", + pthread_self(), + dcb, + STRDCBSTATE(dcb->state)); + } + dcb->state = new_state; + + /* + * The only possible failure that will not cause a crash is + * running out of system resources. + */ + int worker_id = 0; + + if (dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER) + { + worker_id = MXS_WORKER_ALL; + } + else if (dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER) + { + worker_id = dcb->session->client_dcb->poll.thread.id; + } + else + { + worker_id = MXS_WORKER_ANY; + } + + rc = poll_add_fd_to_worker(worker_id, dcb->fd, events, (MXS_POLL_DATA*)dcb); + + if (0 == rc) + { + dcb_add_to_list(dcb); + + MXS_DEBUG("%lu [poll_add_dcb] Added dcb %p in state %s to poll set.", + pthread_self(), + dcb, + STRDCBSTATE(dcb->state)); + } + else + { + dcb->state = old_state; + } + return rc; +} + +int poll_remove_dcb(DCB *dcb) +{ + int dcbfd, rc = 0; + struct epoll_event ev; + CHK_DCB(dcb); + + /*< It is possible that dcb has already been removed from the set */ + if (dcb->state == DCB_STATE_NOPOLLING || + dcb->state == DCB_STATE_ZOMBIE) + { + return 0; + } + if (DCB_STATE_POLLING != dcb->state + && DCB_STATE_LISTENING != dcb->state) + { + MXS_ERROR("%lu [poll_remove_dcb] Error : existing state of dcb %p " + "is %s, but this is probably an error, not crashing.", + pthread_self(), + dcb, + STRDCBSTATE(dcb->state)); + } + /*< + * Set state to NOPOLLING and remove dcb from poll set. + */ + dcb->state = DCB_STATE_NOPOLLING; + + /** + * Only positive fds can be removed from epoll set. + * Cloned DCBs can have a state of DCB_STATE_POLLING but are not in + * the epoll set and do not have a valid file descriptor. Hence the + * only action for them is already done - the change of state to + * DCB_STATE_NOPOLLING. + */ + dcbfd = dcb->fd; + + if (dcbfd > 0) + { + int worker_id; + + if (dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER) + { + worker_id = MXS_WORKER_ALL; + } + else + { + worker_id = dcb->poll.thread.id; + } + + rc = poll_remove_fd_from_worker(worker_id, dcbfd); + } + return rc; +} diff --git a/server/core/poll.cc b/server/core/poll.cc index 71d4cb860..89236b0e7 100644 --- a/server/core/poll.cc +++ b/server/core/poll.cc @@ -420,148 +420,6 @@ int poll_remove_fd_from_worker(int wid, int fd) return rc; } -int poll_add_dcb(DCB *dcb) -{ - int rc = -1; - dcb_state_t old_state = dcb->state; - dcb_state_t new_state; - uint32_t events = 0; - - CHK_DCB(dcb); - -#ifdef EPOLLRDHUP - events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLHUP | EPOLLET; -#else - events = EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLET; -#endif - - /*< - * Choose new state according to the role of dcb. - */ - if (dcb->dcb_role == DCB_ROLE_CLIENT_HANDLER || dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER) - { - new_state = DCB_STATE_POLLING; - } - else - { - ss_dassert(dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER); - new_state = DCB_STATE_LISTENING; - } - /* - * Check DCB current state seems sensible - */ - if (DCB_STATE_DISCONNECTED == dcb->state - || DCB_STATE_ZOMBIE == dcb->state - || DCB_STATE_UNDEFINED == dcb->state) - { - MXS_ERROR("%lu [poll_add_dcb] Error : existing state of dcb %p " - "is %s, but this should be impossible, crashing.", - pthread_self(), - dcb, - STRDCBSTATE(dcb->state)); - raise(SIGABRT); - } - if (DCB_STATE_POLLING == dcb->state - || DCB_STATE_LISTENING == dcb->state) - { - MXS_ERROR("%lu [poll_add_dcb] Error : existing state of dcb %p " - "is %s, but this is probably an error, not crashing.", - pthread_self(), - dcb, - STRDCBSTATE(dcb->state)); - } - dcb->state = new_state; - - /* - * The only possible failure that will not cause a crash is - * running out of system resources. - */ - int worker_id = 0; - - if (dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER) - { - worker_id = MXS_WORKER_ALL; - } - else if (dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER) - { - worker_id = dcb->session->client_dcb->poll.thread.id; - } - else - { - worker_id = (unsigned int)atomic_add(&next_epoll_fd, 1) % n_threads; - } - - rc = poll_add_fd_to_worker(worker_id, dcb->fd, events, (MXS_POLL_DATA*)dcb); - - if (0 == rc) - { - dcb_add_to_list(dcb); - - MXS_DEBUG("%lu [poll_add_dcb] Added dcb %p in state %s to poll set.", - pthread_self(), - dcb, - STRDCBSTATE(dcb->state)); - } - else - { - dcb->state = old_state; - } - return rc; -} - -int poll_remove_dcb(DCB *dcb) -{ - int dcbfd, rc = 0; - struct epoll_event ev; - CHK_DCB(dcb); - - /*< It is possible that dcb has already been removed from the set */ - if (dcb->state == DCB_STATE_NOPOLLING || - dcb->state == DCB_STATE_ZOMBIE) - { - return 0; - } - if (DCB_STATE_POLLING != dcb->state - && DCB_STATE_LISTENING != dcb->state) - { - MXS_ERROR("%lu [poll_remove_dcb] Error : existing state of dcb %p " - "is %s, but this is probably an error, not crashing.", - pthread_self(), - dcb, - STRDCBSTATE(dcb->state)); - } - /*< - * Set state to NOPOLLING and remove dcb from poll set. - */ - dcb->state = DCB_STATE_NOPOLLING; - - /** - * Only positive fds can be removed from epoll set. - * Cloned DCBs can have a state of DCB_STATE_POLLING but are not in - * the epoll set and do not have a valid file descriptor. Hence the - * only action for them is already done - the change of state to - * DCB_STATE_NOPOLLING. - */ - dcbfd = dcb->fd; - - if (dcbfd > 0) - { - int worker_id; - - if (dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER) - { - worker_id = MXS_WORKER_ALL; - } - else - { - worker_id = dcb->poll.thread.id; - } - - rc = poll_remove_fd_from_worker(worker_id, dcbfd); - } - return rc; -} - /** * Check error returns from epoll_ctl. Most result in a crash since they * are "impossible". Adding when already present is assumed non-fatal.