Example #1
0
void AsyncPipeWriter::handleWrite() {
  DestructorGuard dg(this);
  assert(!queue_.empty());
  do {
    auto& front = queue_.front();
    folly::IOBufQueue& curQueue = front.first;
    DCHECK(!curQueue.empty());
    // someday, support writev.  The logic for partial writes is a bit complex
    const IOBuf* head = curQueue.front();
    CHECK(head->length());
#if _WIN32
    // On Windows you can't call write on a socket.
    ssize_t rc = folly::fileutil_detail::wrapNoInt(
        send_internal, fd_, head->data(), head->length());
#else
    ssize_t rc = folly::writeNoInt(fd_.toFd(), head->data(), head->length());
#endif
    if (rc < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
        // pipe is full
        VLOG(5) << "write blocked";
        registerHandler(EventHandler::WRITE);
        return;
      } else {
        failAllWrites(AsyncSocketException(
            AsyncSocketException::INTERNAL_ERROR, "write failed", errno));
        closeNow();
        return;
      }
    } else if (rc == 0) {
      registerHandler(EventHandler::WRITE);
      return;
    }
    curQueue.trimStart(size_t(rc));
    if (curQueue.empty()) {
      auto cb = front.second;
      queue_.pop_front();
      if (cb) {
        cb->writeSuccess();
      }
    } else {
      VLOG(5) << "partial write blocked";
    }
  } while (!queue_.empty());

  if (closeOnEmpty_) {
    closeNow();
  } else {
    unregisterHandler();
  }
}
Example #2
0
// Low level interface
void Cpp2Channel::sendMessage(SendCallback* callback,
                              std::unique_ptr<folly::IOBuf>&& buf) {
    // Callback may be null.
    assert(buf);

    if (!transport_->good()) {
        VLOG(5) << "Channel is !good() in sendMessage";
        // Callback must be last thing in sendMessage, or use guard
        if (callback) {
            callback->messageSendError(
                folly::make_exception_wrapper<TTransportException>(
                    "Channel is !good()"));
        }
        return;
    }

    std::vector<SendCallback*> cbs;
    if (callback) {
        callback->sendQueued();
        cbs.push_back(callback);
    }
    sendCallbacks_.push_back(std::move(cbs));

    DestructorGuard dg(this);

    auto future = pipeline_->write(std::move(buf));
    future.then([this,dg](folly::Try<void>&& t) {
        if (t.withException<TTransportException>(
        [&](const TTransportException& ex) {
        writeError(0, ex);
        }) ||
        t.withException<std::exception>(
        [&](const std::exception& ex) {
            writeError(0, TTransportException(ex.what()));
        })) {
            return;
        }
        else {
            writeSuccess();
        }
    });
}