bool TNonblockingIOThread::notify(TNonblockingServer::TConnection* conn) { THRIFT_SOCKET fd = getNotificationSendFD(); if (fd < 0) { return false; } const int kSize = sizeof(conn); if (send(fd, const_cast_sockopt(&conn), kSize, 0) != kSize) { return false; } return true; }
bool TNonblockingIOThread::notify(TNonblockingServer::TConnection* conn) { THRIFT_SOCKET fd = getNotificationSendFD(); if (fd < 0) { return false; } fd_set wfds, efds; long ret = -1; long kSize = sizeof(conn); const char* pos = reinterpret_cast<const char*>(&conn); while (kSize > 0) { FD_ZERO(&wfds); FD_ZERO(&efds); FD_SET(fd, &wfds); FD_SET(fd, &efds); ret = select(static_cast<int>(fd + 1), NULL, &wfds, &efds, NULL); if (ret < 0) { return false; } else if (ret == 0) { continue; } if (FD_ISSET(fd, &efds)) { ::THRIFT_CLOSESOCKET(fd); return false; } if (FD_ISSET(fd, &wfds)) { ret = send(fd, pos, kSize, 0); if (ret < 0) { if (errno == EAGAIN) { continue; } ::THRIFT_CLOSESOCKET(fd); return false; } kSize -= ret; pos += ret; } } return true; }
void TNonblockingIOThread::createNotificationPipe() { if(evutil_socketpair(AF_LOCAL, SOCK_STREAM, 0, notificationPipeFDs_) == -1) { GlobalOutput.perror("TNonblockingServer::createNotificationPipe ", EVUTIL_SOCKET_ERROR()); throw TException("can't create notification pipe"); } if(evutil_make_socket_nonblocking(notificationPipeFDs_[0])<0 || evutil_make_socket_nonblocking(notificationPipeFDs_[1])<0) { ::close(notificationPipeFDs_[0]); ::close(notificationPipeFDs_[1]); throw TException("TNonblockingServer::createNotificationPipe() O_NONBLOCK"); } for (int i = 0; i < 2; ++i) { #if LIBEVENT_VERSION_NUMBER < 0x02000000 int flags; if ((flags = fcntl(notificationPipeFDs_[i], F_GETFD, 0)) < 0 || fcntl(notificationPipeFDs_[i], F_SETFD, flags | FD_CLOEXEC) < 0) { #else if (evutil_make_socket_closeonexec(notificationPipeFDs_[i]) < 0) { #endif ::close(notificationPipeFDs_[0]); ::close(notificationPipeFDs_[1]); throw TException("TNonblockingServer::createNotificationPipe() " "FD_CLOEXEC"); } } } /** * Register the core libevent events onto the proper base. */ void TNonblockingIOThread::registerEvents() { if (listenSocket_ >= 0) { // Register the server event event_set(&serverEvent_, listenSocket_, EV_READ | EV_PERSIST, TNonblockingIOThread::listenHandler, server_); event_base_set(eventBase_, &serverEvent_); // Add the event and start up the server if (-1 == event_add(&serverEvent_, 0)) { throw TException("TNonblockingServer::serve(): " "event_add() failed on server listen event"); } GlobalOutput.printf("TNonblocking: IO thread #%d registered for listen.", number_); } createNotificationPipe(); // Create an event to be notified when a task finishes event_set(¬ificationEvent_, getNotificationRecvFD(), EV_READ | EV_PERSIST, TNonblockingIOThread::notifyHandler, this); // Attach to the base event_base_set(eventBase_, ¬ificationEvent_); // Add the event and start up the server if (-1 == event_add(¬ificationEvent_, 0)) { throw TException("TNonblockingServer::serve(): " "event_add() failed on task-done notification event"); } GlobalOutput.printf("TNonblocking: IO thread #%d registered for notify.", number_); } bool TNonblockingIOThread::notify(TNonblockingServer::TConnection* conn) { int fd = getNotificationSendFD(); if (fd < 0) { return false; } const int kSize = sizeof(conn); if (send(fd, const_cast_sockopt(&conn), kSize, 0) != kSize) { return false; } return true; }