folly: AsyncIO: add debuging helper
authorLucian Grijincu <lucian@fb.com>
Fri, 22 Feb 2013 18:36:01 +0000 (10:36 -0800)
committerJordan DeLong <jdelong@fb.com>
Tue, 19 Mar 2013 00:07:46 +0000 (17:07 -0700)
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

folly/experimental/io/AsyncIO.cpp
folly/experimental/io/AsyncIO.h

index d064affc9176796e861bd1afecd3b08077704693..16473e7f00af3a8c416860ecff12cdafbbd91ddc 100644 (file)
 
 #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
 
index 3c84ebb0c4f2be331669ffb88b379fdfb8fbbfc3..0421796995dce193aa28e4082a3b294c179d894c 100644 (file)
@@ -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.
  */