You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by an...@apache.org on 2018/05/23 21:36:48 UTC

[04/10] mesos git commit: Windows: Added overlapped support to `os::write`.

Windows: Added overlapped support to `os::write`.

Added overlapped handle support to `os::write`. Now, `os::write` will do
a blocking write no matter the handle type. Also, `os::write_async` will
do an overlapped write on an overlapped handle.

Review: https://reviews.apache.org/r/66956/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/bd4a8008
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/bd4a8008
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/bd4a8008

Branch: refs/heads/master
Commit: bd4a8008e0eb1a286e9c45a8ff6cf4cf1792ad6c
Parents: 5cdd29f
Author: Akash Gupta <ak...@hotmail.com>
Authored: Wed May 23 14:01:17 2018 -0700
Committer: Andrew Schwartzmeyer <an...@schwartzmeyer.com>
Committed: Wed May 23 14:01:17 2018 -0700

----------------------------------------------------------------------
 .../stout/include/stout/os/windows/write.hpp    | 92 ++++++++++++++++++--
 1 file changed, 87 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/bd4a8008/3rdparty/stout/include/stout/os/windows/write.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/os/windows/write.hpp b/3rdparty/stout/include/stout/os/windows/write.hpp
index 295c031..232218e 100644
--- a/3rdparty/stout/include/stout/os/windows/write.hpp
+++ b/3rdparty/stout/include/stout/os/windows/write.hpp
@@ -18,23 +18,105 @@
 #include <stout/unreachable.hpp>
 #include <stout/windows.hpp>
 
+#include <stout/internal/windows/overlapped.hpp>
+
 #include <stout/os/int_fd.hpp>
 #include <stout/os/socket.hpp>
 
 namespace os {
 
+// Asynchronous write on a overlapped int_fd. Returns `Error` on fatal errors,
+// `None()` on a successful pending IO operation or number of bytes written on
+// a successful IO operation that finished immediately.
+inline Result<size_t> write_async(
+    const int_fd& fd,
+    const void* data,
+    size_t size,
+    OVERLAPPED* overlapped)
+{
+  CHECK_LE(size, UINT_MAX);
+
+  switch (fd.type()) {
+    case WindowsFD::Type::HANDLE: {
+      DWORD bytes;
+      const bool success =
+        ::WriteFile(fd, data, static_cast<DWORD>(size), &bytes, overlapped);
+
+      return ::internal::windows::process_async_io_result(success, bytes);
+    }
+    case WindowsFD::Type::SOCKET: {
+      static_assert(
+          std::is_same<OVERLAPPED, WSAOVERLAPPED>::value,
+          "Expected `WSAOVERLAPPED` to be of type `OVERLAPPED`.");
+
+      // Note that it's okay to allocate this on the stack, since the WinSock
+      // providers must copy the WSABUF to their internal buffers. See
+      // https://msdn.microsoft.com/en-us/library/windows/desktop/ms741688(v=vs.85).aspx // NOLINT(whitespace/line_length)
+      WSABUF buf = {
+        static_cast<u_long>(size),
+        static_cast<char*>(const_cast<void*>(data))
+      };
+
+      DWORD bytes;
+      const int result =
+        ::WSASend(fd, &buf, 1, &bytes, 0, overlapped, nullptr);
+
+      return ::internal::windows::process_async_io_result(result == 0, bytes);
+    }
+  }
+
+  UNREACHABLE();
+}
+
+
 inline ssize_t write(const int_fd& fd, const void* data, size_t size)
 {
   CHECK_LE(size, INT_MAX);
 
   switch (fd.type()) {
     case WindowsFD::Type::HANDLE: {
+      // Handle non-overlapped case. We just use the regular `WriteFile` since
+      // seekable overlapped files require an offset, which we don't track.
+      if (!fd.is_overlapped()) {
+        DWORD bytes;
+        const BOOL result =
+          ::WriteFile(fd, data, static_cast<DWORD>(size), &bytes, nullptr);
+
+        if (result == FALSE) {
+          // Indicates an error, but we can't return a `WindowsError`.
+          return -1;
+        }
+
+        return static_cast<ssize_t>(bytes);
+      }
+
+      // Asynchronous handle, we can use the `write_async` function
+      // and then wait on the overlapped object for a synchronous write.
+      Try<OVERLAPPED> overlapped_ =
+        ::internal::windows::init_overlapped_for_sync_io();
+
+      if (overlapped_.isError()) {
+        return -1;
+      }
+
+      OVERLAPPED overlapped = overlapped_.get();
+      Result<size_t> result = write_async(fd, data, size, &overlapped);
+
+      if (result.isError()) {
+        return -1;
+      }
+
+      if (result.isSome()) {
+        return result.get();
+      }
+
+      // IO is pending, so wait for the overlapped object.
       DWORD bytes;
-      // TODO(andschwa): Handle overlapped I/O.
-      const BOOL result =
-        ::WriteFile(fd, data, static_cast<DWORD>(size), &bytes, nullptr);
-      if (result == FALSE) {
-        return -1; // Indicates an error, but we can't return a `WindowsError`.
+      const BOOL wait_success =
+        ::GetOverlappedResult(fd, &overlapped, &bytes, TRUE);
+
+      if (wait_success == FALSE) {
+        return -1;
       }
 
       return static_cast<ssize_t>(bytes);