2017-10-11 01:45:00 +03:00
|
|
|
/*
|
2019-06-20 02:58:25 +03:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2017-10-11 01:45:00 +03:00
|
|
|
*
|
2019-06-20 02:58:25 +03:00
|
|
|
* This software may be used and distributed according to the terms of the
|
|
|
|
* GNU General Public License version 2.
|
2017-10-11 01:45:00 +03:00
|
|
|
*/
|
2019-10-11 15:26:59 +03:00
|
|
|
|
2017-10-11 01:45:00 +03:00
|
|
|
#include "eden/fs/utils/IoFuture.h"
|
|
|
|
|
|
|
|
#include <folly/futures/Future.h>
|
|
|
|
#include <folly/futures/Promise.h>
|
|
|
|
#include <folly/io/async/AsyncTimeout.h>
|
|
|
|
#include <folly/io/async/EventHandler.h>
|
2020-11-11 03:29:24 +03:00
|
|
|
#include <folly/logging/xlog.h>
|
2017-10-11 01:45:00 +03:00
|
|
|
|
|
|
|
using folly::EventBase;
|
|
|
|
using folly::Promise;
|
|
|
|
using std::make_unique;
|
|
|
|
|
|
|
|
namespace facebook {
|
|
|
|
namespace eden {
|
|
|
|
|
|
|
|
IoFuture::IoFuture(folly::EventBase* eventBase, int socket)
|
2019-02-23 21:44:41 +03:00
|
|
|
: EventHandler{eventBase, folly::NetworkSocket::fromFd(socket)},
|
2017-10-11 01:45:00 +03:00
|
|
|
AsyncTimeout{eventBase},
|
|
|
|
promise_{Promise<int>::makeEmpty()} {}
|
|
|
|
|
|
|
|
folly::Future<int> IoFuture::wait(
|
|
|
|
int eventFlags,
|
|
|
|
folly::TimeoutManager::timeout_type timeout) {
|
|
|
|
// wait() may be called multiple times.
|
|
|
|
// If someone is calling wait() again before the previous wait() finished,
|
|
|
|
// fail the previously returned future with an exception indicating that the
|
|
|
|
// I/O wait was canceled.
|
|
|
|
if (!promise_.isFulfilled()) {
|
|
|
|
promise_.setException(std::system_error(
|
2018-03-20 23:31:16 +03:00
|
|
|
ECANCELED, std::generic_category(), "I/O wait canceled"));
|
2017-10-11 01:45:00 +03:00
|
|
|
}
|
|
|
|
promise_ = Promise<int>{};
|
|
|
|
|
|
|
|
// We do not support using the EventHandler::PERSIST flag.
|
|
|
|
// folly::Future objects are one-shot, so it doesn't make sense to repeatedly
|
|
|
|
// wait for I/O to be ready using a Future.
|
2020-11-11 03:29:24 +03:00
|
|
|
XCHECK(!(eventFlags & EventHandler::PERSIST));
|
2017-10-11 01:45:00 +03:00
|
|
|
|
|
|
|
auto future = promise_.getFuture();
|
|
|
|
|
|
|
|
// Register a timeout in case the remote side does not send
|
|
|
|
// credentials soon.
|
|
|
|
if (!scheduleTimeout(timeout)) {
|
|
|
|
promise_.setException(std::system_error(
|
2018-03-20 23:31:16 +03:00
|
|
|
EIO, std::generic_category(), "error registering for socket I/O"));
|
2017-10-11 01:45:00 +03:00
|
|
|
return future;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register for the requested I/O event
|
|
|
|
if (!registerHandler(eventFlags)) {
|
|
|
|
promise_.setException(std::system_error(
|
2018-03-20 23:31:16 +03:00
|
|
|
EIO, std::generic_category(), "error registering for socket I/O"));
|
2017-10-11 01:45:00 +03:00
|
|
|
return future;
|
|
|
|
}
|
|
|
|
|
|
|
|
return future;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IoFuture::handlerReady(uint16_t events) noexcept {
|
|
|
|
cancelTimeout();
|
|
|
|
promise_.setValue(events);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IoFuture::timeoutExpired() noexcept {
|
|
|
|
unregisterHandler();
|
|
|
|
promise_.setException(std::system_error(
|
2018-03-20 23:31:16 +03:00
|
|
|
ETIMEDOUT, std::generic_category(), "timed out waiting for socket I/O"));
|
2017-10-11 01:45:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
folly::Future<int> waitForIO(
|
|
|
|
EventBase* eventBase,
|
|
|
|
int socket,
|
|
|
|
int eventFlags,
|
|
|
|
folly::TimeoutManager::timeout_type timeout) {
|
|
|
|
return folly::makeFutureWith([&] {
|
|
|
|
auto ioFuture = make_unique<IoFuture>(eventBase, socket);
|
|
|
|
auto f = ioFuture.get();
|
|
|
|
return f->wait(eventFlags, timeout).ensure([iof = std::move(ioFuture)] {});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace eden
|
|
|
|
} // namespace facebook
|