示例#1
0
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(&notificationEvent_,
            getNotificationRecvFD(),
            EV_READ | EV_PERSIST,
            TNonblockingIOThread::notifyHandler,
            this);

  // Attach to the base
  event_base_set(eventBase_, &notificationEvent_);

  // Add the event and start up the server
  if (-1 == event_add(&notificationEvent_, 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;
}