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:50 UTC

[06/10] mesos git commit: Windows: Added async version of `os::sendfile`.

Windows: Added async version of `os::sendfile`.

Split the original `os::sendfile` implementation into an asynchronous
`os::sendfile_async`function and a synchronous `os::sendfile`
function. The synchronous version simply calls the asynchronous
version and waits.

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


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

Branch: refs/heads/master
Commit: 20beb52afa8b698f87013f5fd56adaf4c9e4f824
Parents: 028bb60
Author: Akash Gupta <ak...@hotmail.com>
Authored: Wed May 23 14:03:46 2018 -0700
Committer: Andrew Schwartzmeyer <an...@schwartzmeyer.com>
Committed: Wed May 23 14:07:47 2018 -0700

----------------------------------------------------------------------
 .../stout/include/stout/os/windows/sendfile.hpp | 80 +++++++++++++++-----
 1 file changed, 61 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/20beb52a/3rdparty/stout/include/stout/os/windows/sendfile.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/os/windows/sendfile.hpp b/3rdparty/stout/include/stout/os/windows/sendfile.hpp
index 594d9c7..2c08bb7 100644
--- a/3rdparty/stout/include/stout/os/windows/sendfile.hpp
+++ b/3rdparty/stout/include/stout/os/windows/sendfile.hpp
@@ -14,40 +14,82 @@
 #define __STOUT_OS_WINDOWS_SENDFILE_HPP__
 
 #include <stout/error.hpp>
+#include <stout/result.hpp>
 #include <stout/try.hpp>
 #include <stout/windows.hpp> // For `winioctl.h`.
 
+#include <stout/internal/windows/overlapped.hpp>
+
 #include <stout/os/int_fd.hpp>
 
 namespace os {
 
+inline Result<size_t> sendfile_async(
+    const int_fd& s, const int_fd& fd, size_t length, OVERLAPPED* overlapped)
+{
+  // `::TransmitFile` can only send `INT_MAX - 1` bytes.
+  CHECK_LE(length, INT_MAX - 1);
+
+  const BOOL result = ::TransmitFile(
+      s,                          // Sending socket.
+      fd,                         // File to be sent.
+      static_cast<DWORD>(length), // Number of bytes to be sent from the file.
+      0,                          // Bytes per send. 0 chooses system default.
+      overlapped,                 // Overlapped object with file offset.
+      nullptr,                    // Data before and after file send.
+      0);                         // Flags.
+
+  const WindowsError error;
+  if (result == FALSE &&
+      (error.code == WSA_IO_PENDING || error.code == ERROR_IO_PENDING)) {
+    return None();
+  }
+
+  if (result == FALSE) {
+    return error;
+  }
+
+  return length;
+}
+
 // Returns the amount of bytes written from the input file
 // descriptor to the output socket.
 // On error, `Try<ssize_t, SocketError>` contains the error.
 inline Try<ssize_t, SocketError> sendfile(
     const int_fd& s, const int_fd& fd, off_t offset, size_t length)
 {
+  if (offset < 0) {
+    return SocketError(WSAEINVAL);
+  }
+
   // NOTE: We convert the `offset` here to avoid potential data loss
   // in the type casting and bitshifting below.
-  uint64_t offset_ = offset;
-
-  OVERLAPPED from = {
-    0,
-    0,
-    {static_cast<DWORD>(offset_), static_cast<DWORD>(offset_ >> 32)},
-    nullptr};
-
-  CHECK_LE(length, MAXDWORD);
-  if (::TransmitFile(s, fd, static_cast<DWORD>(length), 0, &from, nullptr, 0) ==
-        FALSE &&
-      (::WSAGetLastError() == WSA_IO_PENDING ||
-       ::WSAGetLastError() == ERROR_IO_PENDING)) {
-    DWORD sent = 0;
-    DWORD flags = 0;
-
-    if (::WSAGetOverlappedResult(s, &from, &sent, TRUE, &flags) == TRUE) {
-      return sent;
-    }
+  const uint64_t offset_ = offset;
+
+  const Try<OVERLAPPED> from_ =
+    ::internal::windows::init_overlapped_for_sync_io();
+
+  if (from_.isError()) {
+    return SocketError(from_.error());
+  }
+
+  OVERLAPPED from = from_.get();
+  from.Offset = static_cast<DWORD>(offset_);
+  from.OffsetHigh = static_cast<DWORD>(offset_ >> 32);
+
+  const Result<size_t> result = sendfile_async(s, fd, length, &from);
+  if (result.isError()) {
+    return SocketError(result.error());
+  }
+
+  if (result.isSome()) {
+    return result.get();
+  }
+
+  DWORD sent = 0;
+  DWORD flags = 0;
+  if (::WSAGetOverlappedResult(s, &from, &sent, TRUE, &flags) == TRUE) {
+    return sent;
   }
 
   return SocketError();