Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

folly: AsyncIO: add debuging helper

Summary: Change State to enum class, and add debugging helper to AsyncIOOp and AsyncIO.

Test Plan: n/a

Reviewed By: philipp@fb.com

FB internal diff: D715676
  • Loading branch information...
commit 88b49f3e6b5592135a756d02e1b8dbb78631ecf5 1 parent feca2a7
@luciang luciang authored jdelong committed
Showing with 101 additions and 13 deletions.
  1. +95 −12 folly/experimental/io/AsyncIO.cpp
  2. +6 −1 folly/experimental/io/AsyncIO.h
View
107 folly/experimental/io/AsyncIO.cpp
@@ -16,12 +16,15 @@
#include "folly/experimental/io/AsyncIO.h"
+#include <unistd.h>
#include <cerrno>
+#include <string>
#include <boost/intrusive/parent_from_member.hpp>
#include <glog/logging.h>
#include "folly/Exception.h"
+#include "folly/Format.h"
#include "folly/Likely.h"
#include "folly/String.h"
#include "folly/eventfd.h"
@@ -30,31 +33,31 @@ namespace folly {
AsyncIOOp::AsyncIOOp(NotificationCallback cb)
: cb_(std::move(cb)),
- state_(UNINITIALIZED),
+ state_(State::UNINITIALIZED),
result_(-EINVAL) {
memset(&iocb_, 0, sizeof(iocb_));
}
void AsyncIOOp::reset(NotificationCallback cb) {
- CHECK_NE(state_, PENDING);
+ CHECK_NE(state_, State::PENDING);
cb_ = std::move(cb);
- state_ = UNINITIALIZED;
+ state_ = State::UNINITIALIZED;
result_ = -EINVAL;
memset(&iocb_, 0, sizeof(iocb_));
}
AsyncIOOp::~AsyncIOOp() {
- CHECK_NE(state_, PENDING);
+ CHECK_NE(state_, State::PENDING);
}
void AsyncIOOp::start() {
- DCHECK_EQ(state_, INITIALIZED);
- state_ = PENDING;
+ DCHECK_EQ(state_, State::INITIALIZED);
+ state_ = State::PENDING;
}
void AsyncIOOp::complete(ssize_t result) {
- DCHECK_EQ(state_, PENDING);
- state_ = COMPLETED;
+ DCHECK_EQ(state_, State::PENDING);
+ state_ = State::COMPLETED;
result_ = result;
if (cb_) {
cb_(this);
@@ -62,7 +65,7 @@ void AsyncIOOp::complete(ssize_t result) {
}
ssize_t AsyncIOOp::result() const {
- CHECK_EQ(state_, COMPLETED);
+ CHECK_EQ(state_, State::COMPLETED);
return result_;
}
@@ -95,8 +98,8 @@ void AsyncIOOp::pwritev(int fd, const iovec* iov, int iovcnt, off_t start) {
}
void AsyncIOOp::init() {
- CHECK_EQ(state_, UNINITIALIZED);
- state_ = INITIALIZED;
+ CHECK_EQ(state_, State::UNINITIALIZED);
+ state_ = State::INITIALIZED;
}
AsyncIO::AsyncIO(size_t capacity, PollMode pollMode)
@@ -133,7 +136,7 @@ void AsyncIO::initializeContext() {
}
void AsyncIO::submit(Op* op) {
- CHECK_EQ(op->state(), Op::INITIALIZED);
+ CHECK_EQ(op->state(), Op::State::INITIALIZED);
CHECK_LT(pending_, capacity_) << "too many pending requests";
initializeContext(); // on demand
iocb* cb = &op->iocb_;
@@ -243,5 +246,85 @@ void AsyncIOQueue::maybeDequeue() {
}
}
+// debugging helpers:
+
+namespace {
+
+#define X(c) case c: return #c
+
+const char* asyncIoOpStateToString(AsyncIOOp::State state) {
+ switch (state) {
+ X(AsyncIOOp::State::UNINITIALIZED);
+ X(AsyncIOOp::State::INITIALIZED);
+ X(AsyncIOOp::State::PENDING);
+ X(AsyncIOOp::State::COMPLETED);
+ }
+ return "<INVALID AsyncIOOp::State>";
+}
+
+const char* iocbCmdToString(short int cmd_short) {
+ io_iocb_cmd cmd = static_cast<io_iocb_cmd>(cmd_short);
+ switch (cmd) {
+ X(IO_CMD_PREAD);
+ X(IO_CMD_PWRITE);
+ X(IO_CMD_FSYNC);
+ X(IO_CMD_FDSYNC);
+ X(IO_CMD_POLL);
+ X(IO_CMD_NOOP);
+ X(IO_CMD_PREADV);
+ X(IO_CMD_PWRITEV);
+ };
+ return "<INVALID io_iocb_cmd>";
+}
+
+#undef X
+
+std::string fd2name(int fd) {
+ std::string path = folly::to<std::string>("/proc/self/fd/", fd);
+ char link[PATH_MAX];
+ const ssize_t length =
+ std::max<ssize_t>(readlink(path.c_str(), link, PATH_MAX), 0);
+ return path.assign(link, length);
+}
+
+std::ostream& operator<<(std::ostream& os, const iocb& cb) {
+ os << folly::format(
+ "data={}, key={}, opcode={}, reqprio={}, fd={}, f={}, ",
+ cb.data, cb.key, iocbCmdToString(cb.aio_lio_opcode),
+ cb.aio_reqprio, cb.aio_fildes, fd2name(cb.aio_fildes));
+
+ switch (cb.aio_lio_opcode) {
+ case IO_CMD_PREAD:
+ case IO_CMD_PWRITE:
+ os << folly::format("buf={}, off={}, size={}, ",
+ cb.u.c.buf, cb.u.c.nbytes, cb.u.c.offset);
+ default:
+ os << "[TODO: write debug string for "
+ << iocbCmdToString(cb.aio_lio_opcode) << "] ";
+ }
+
+ return os;
+}
+
+} // anonymous namespace
+
+std::ostream& operator<<(std::ostream& os, const AsyncIOOp& op) {
+ os << "{" << op.state_ << ", ";
+
+ if (op.state_ != AsyncIOOp::State::UNINITIALIZED) {
+ os << op.iocb_;
+ }
+
+ if (op.state_ == AsyncIOOp::State::COMPLETED) {
+ os << "result=" << op.result_ << ", ";
+ }
+
+ return os << "}";
+}
+
+std::ostream& operator<<(std::ostream& os, AsyncIOOp::State state) {
+ return os << asyncIoOpStateToString(state);
+}
+
} // namespace folly
View
7 folly/experimental/io/AsyncIO.h
@@ -24,6 +24,7 @@
#include <cstdint>
#include <deque>
#include <functional>
+#include <ostream>
#include <utility>
#include <vector>
@@ -42,6 +43,7 @@ namespace folly {
*/
class AsyncIOOp : private boost::noncopyable {
friend class AsyncIO;
+ friend std::ostream& operator<<(std::ostream& stream, const AsyncIOOp& o);
public:
typedef std::function<void(AsyncIOOp*)> NotificationCallback;
@@ -51,7 +53,7 @@ class AsyncIOOp : private boost::noncopyable {
// There would be a cancel() method here if Linux AIO actually implemented
// it. But let's not get your hopes up.
- enum State {
+ enum class State {
UNINITIALIZED,
INITIALIZED,
PENDING,
@@ -108,6 +110,9 @@ class AsyncIOOp : private boost::noncopyable {
ssize_t result_;
};
+std::ostream& operator<<(std::ostream& stream, const AsyncIOOp& o);
+std::ostream& operator<<(std::ostream& stream, AsyncIOOp::State state);
+
/**
* C++ interface around Linux Async IO.
*/
Please sign in to comment.
Something went wrong with that request. Please try again.