gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] branch master updated (f2f1d659 -> 41eb046c


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated (f2f1d659 -> 41eb046c)
Date: Sun, 01 Oct 2017 23:53:39 +0200

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from f2f1d659 Improved 5ac497e212525a12209a3c1007a129ae85055cf7
     new 6f646947 Added support for sendfile() on FreeBSD
     new 41eb046c Implemented usage of readahead buffer for sendfile() on 
FreeBSD 11 and later

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 configure.ac                |  41 ++++++++++++++
 src/microhttpd/connection.c | 129 +++++++++++++++++++++++++++++++++++++-------
 src/microhttpd/connection.h |   9 ++++
 src/microhttpd/daemon.c     |   3 ++
 src/microhttpd/internal.h   |   4 +-
 5 files changed, 166 insertions(+), 20 deletions(-)

diff --git a/configure.ac b/configure.ac
index e4b6f48e..507062c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1267,6 +1267,47 @@ ssize_t sendfile(int, int, off_t*, size_t);
   [AC_MSG_RESULT([[no]])
   ]
 )
+AS_VAR_IF([[found_sendfile]], [["no"]],
+  [
+   AC_MSG_CHECKING([[for FreeBSD-style sendfile(2)]])
+   AC_LINK_IFELSE(
+     [AC_LANG_PROGRAM(
+       [[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+static void empty_func(void)
+{
+/* Check for declaration */
+  (void)sendfile;
+}
+/* Declare again to check form match */
+int sendfile(int, int, off_t, size_t,
+             struct sf_hdtr*, off_t*, int);
+       ]],
+       [[
+         int fd1=0, fd2=1;
+         off_t o = 0;
+         size_t s = 5;
+         off_t r1;
+         int r2;
+         r2 = sendfile (fd1, fd2, o, s, (void*)0, &r1, 0);
+         if (r2)
+           empty_func();
+       ]]
+      )
+     ],
+     [
+       AC_DEFINE([HAVE_FREEBSD_SENDFILE], [1], [Define to 1 if you have 
FreeBSD-style sendfile(2).])
+       found_sendfile="yes, FreeBSD-style"
+       AC_MSG_RESULT([[yes]])
+     ],
+     [AC_MSG_RESULT([[no]])
+     ]
+   )
+  ]
+)
 
 # optional: have error messages ?
 AC_MSG_CHECKING([[whether to generate error messages]])
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index fbe9f9d3..c33d484a 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -39,6 +39,11 @@
 #ifdef HAVE_LINUX_SENDFILE
 #include <sys/sendfile.h>
 #endif /* HAVE_LINUX_SENDFILE */
+#ifdef HAVE_FREEBSD_SENDFILE
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#endif /* HAVE_FREEBSD_SENDFILE */
 #ifdef HTTPS_SUPPORT
 #include "connection_https.h"
 #endif /* HTTPS_SUPPORT */
@@ -113,6 +118,54 @@
 
 
 /**
+ * sendfile() chuck size
+ */
+#define MHD_SENFILE_CHUNK_         (0x20000)
+
+/**
+ * sendfile() chuck size for thread-per-connection
+ */
+#define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
+
+#ifdef HAVE_FREEBSD_SENDFILE
+#ifdef SF_FLAGS
+/**
+ * FreeBSD sendfile() flags
+ */
+static int freebsd_sendfile_flags_;
+
+/**
+ * FreeBSD sendfile() flags for thread-per-connection
+ */
+static int freebsd_sendfile_flags_thd_p_c_;
+#endif /* SF_FLAGS */
+/**
+ * Initialises static variables
+ */
+void
+MHD_conn_init_static_ (void)
+{
+/* FreeBSD 11 and later allow to specify read-ahead size
+ * and handles SF_NODISKIO differently.
+ * SF_FLAGS defined only on FreeBSD 11 and later. */
+#ifdef SF_FLAGS
+  long sys_page_size = sysconf (_SC_PAGESIZE);
+  if (0 > sys_page_size)
+    { /* Failed to get page size. */
+      freebsd_sendfile_flags_ = SF_NODISKIO;
+      freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
+    }
+  else
+    {
+      freebsd_sendfile_flags_ =
+          SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_ / sys_page_size), 
SF_NODISKIO);
+      freebsd_sendfile_flags_thd_p_c_ =
+          SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size), 
SF_NODISKIO);
+    }
+#endif /* SF_FLAGS */
+}
+#endif /* HAVE_FREEBSD_SENDFILE */
+/**
  * Callback for receiving data from the socket.
  *
  * @param connection the MHD connection structure
@@ -219,7 +272,7 @@ send_param_adapter (struct MHD_Connection *connection,
 }
 
 
-#ifdef HAVE_LINUX_SENDFILE
+#if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_FREEBSD_SENDFILE)
 /**
  * Function for sending responses backed by file FD.
  *
@@ -234,13 +287,24 @@ sendfile_adapter (struct MHD_Connection *connection)
   uint64_t left;
   uint64_t offsetu64;
 #ifndef HAVE_SENDFILE64
+  const uint64_t max_off_t = (uint64_t)OFF_T_MAX;
+#else  /* HAVE_SENDFILE64 */
+  const uint64_t max_off_t = (uint64_t)OFF64_T_MAX;
+#endif /* HAVE_SENDFILE64 */
+#ifdef HAVE_LINUX_SENDFILE
+#ifndef HAVE_SENDFILE64
   off_t offset;
 #else  /* HAVE_SENDFILE64 */
   off64_t offset;
 #endif /* HAVE_SENDFILE64 */
+#endif /* HAVE_LINUX_SENDFILE */
+#ifdef HAVE_FREEBSD_SENDFILE
+  off_t sent_bytes;
+  int flags = 0;
+#endif
   const bool used_thr_p_c = (0 != (connection->daemon->options & 
MHD_USE_THREAD_PER_CONNECTION));
-  const size_t chunk_size = used_thr_p_c ? 0x200000 : 0x20000;
-  size_t send_size;
+  const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ : 
MHD_SENFILE_CHUNK_;
+  size_t send_size = 0;
   mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender);
 
   offsetu64 = connection->response_write_position + 
connection->response->fd_off;
@@ -248,23 +312,19 @@ sendfile_adapter (struct MHD_Connection *connection)
   /* Do not allow system to stick sending on single fast connection:
    * use 128KiB chunks (2MiB for thread-per-connection). */
   send_size = (left > chunk_size) ? chunk_size : (size_t) left;
-#ifndef HAVE_SENDFILE64
-  if ((uint64_t)OFF_T_MAX < offsetu64)
+  if (max_off_t < offsetu64)
     { /* Retry to send with standard 'send()'. */
       connection->resp_sender = MHD_resp_sender_std;
       return MHD_ERR_AGAIN_;
     }
+#ifdef HAVE_LINUX_SENDFILE
+#ifndef HAVE_SENDFILE64
   offset = (off_t) offsetu64;
   ret = sendfile (connection->socket_fd,
                   file_fd,
                   &offset,
                   send_size);
 #else  /* HAVE_SENDFILE64 */
-  if ((uint64_t)OFF64_T_MAX < offsetu64)
-    { /* Retry to send with standard 'send()'. */
-      connection->resp_sender = MHD_resp_sender_std;
-      return MHD_ERR_AGAIN_;
-    }
   offset = (off64_t) offsetu64;
   ret = sendfile64 (connection->socket_fd,
                     file_fd,
@@ -299,9 +359,42 @@ sendfile_adapter (struct MHD_Connection *connection)
   else if (send_size > (size_t)ret)
         connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
 #endif /* EPOLL_SUPPORT */
+#elif defined(HAVE_FREEBSD_SENDFILE)
+#ifdef SF_FLAGS
+  flags = used_thr_p_c ?
+      freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
+#endif /* SF_FLAGS */
+  if (0 != sendfile (file_fd,
+                     connection->socket_fd,
+                     (off_t) offsetu64,
+                     send_size,
+                     NULL,
+                     &sent_bytes,
+                     flags))
+    {
+      const int err = MHD_socket_get_error_();
+      if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
+          MHD_SCKT_ERR_IS_EINTR_(err) ||
+          EBUSY == err)
+        {
+          mhd_assert (SSIZE_MAX >= sent_bytes);
+          if (0 != sent_bytes)
+            return (ssize_t)sent_bytes;
+
+          return MHD_ERR_AGAIN_;
+        }
+      /* Some unrecoverable error. Possibly file FD is not suitable
+       * for sendfile(). Retry with standard send(). */
+      connection->resp_sender = MHD_resp_sender_std;
+      return MHD_ERR_AGAIN_;
+    }
+  mhd_assert (0 < sent_bytes);
+  mhd_assert (SSIZE_MAX >= sent_bytes);
+  ret = (ssize_t)sent_bytes;
+#endif /* HAVE_FREEBSD_SENDFILE */
   return ret;
 }
-#endif /* HAVE_LINUX_SENDFILE */
+#endif /* HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE */
 
 
 /**
@@ -933,13 +1026,13 @@ try_ready_normal_body (struct MHD_Connection *connection)
        (response->data_size + response->data_start >
        connection->response_write_position) )
     return MHD_YES; /* response already ready */
-#if defined(HAVE_LINUX_SENDFILE)
+#if defined(HAVE_LINUX_SENDFILE) || defined (HAVE_FREEBSD_SENDFILE)
   if (MHD_resp_sender_sendfile == connection->resp_sender)
     {
       /* will use sendfile, no need to bother response crc */
       return MHD_YES;
     }
-#endif
+#endif /* HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE */
 
   ret = response->crc (response->crc_cls,
                        connection->response_write_position,
@@ -2875,15 +2968,15 @@ MHD_connection_handle_write (struct MHD_Connection 
*connection)
               /* mutex was already unlocked by try_ready_normal_body */
               return;
             }
-#if defined(HAVE_LINUX_SENDFILE)
+#if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_FREEBSD_SENDFILE)
           if (MHD_resp_sender_sendfile == connection->resp_sender)
             {
               ret = sendfile_adapter (connection);
             }
           else
-#else  /* ! HAVE_LINUX_SENDFILE */
+#else  /* ! (HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE) */
           if (1)
-#endif /* ! HAVE_LINUX_SENDFILE */
+#endif /* ! (HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE) */
             {
               data_write_offset = connection->response_write_position
                                   - response->data_start;
@@ -3819,13 +3912,13 @@ MHD_queue_response (struct MHD_Connection *connection,
   MHD_increment_response_rc (response);
   connection->response = response;
   connection->responseCode = status_code;
-#if defined(HAVE_LINUX_SENDFILE)
+#if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_FREEBSD_SENDFILE)
   if ( (response->fd == -1) ||
        (0 != (connection->daemon->options & MHD_USE_TLS)) )
     connection->resp_sender = MHD_resp_sender_std;
   else
     connection->resp_sender = MHD_resp_sender_sendfile;
-#endif /* HAVE_LINUX_SENDFILE */
+#endif /* HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE */
 
   if ( ( (NULL != connection->method) &&
          (MHD_str_equal_caseless_ (connection->method,
diff --git a/src/microhttpd/connection.h b/src/microhttpd/connection.h
index 37e4d550..a9df9998 100644
--- a/src/microhttpd/connection.h
+++ b/src/microhttpd/connection.h
@@ -62,6 +62,15 @@
 #define MHD_ERR_INVAL_ (-3078)
 
 
+#ifdef HAVE_FREEBSD_SENDFILE
+/**
+ * Initialises static variables
+ */
+void
+MHD_conn_init_static_ (void);
+#endif /* HAVE_FREEBSD_SENDFILE */
+
+
 /**
  * Set callbacks for this connection to those for HTTP.
  *
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 3bf151bb..8a9c74e7 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -6702,6 +6702,9 @@ MHD_init(void)
   gnutls_global_init ();
 #endif /* HTTPS_SUPPORT */
   MHD_monotonic_sec_counter_init();
+#ifdef HAVE_FREEBSD_SENDFILE
+  MHD_conn_init_static_ ();
+#endif /* HAVE_FREEBSD_SENDFILE */
 }
 
 
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index f82a122c..25a24588 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -806,13 +806,13 @@ struct MHD_Connection
    */
   uint64_t response_write_position;
 
-#if defined(HAVE_LINUX_SENDFILE)
+#if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_FREEBSD_SENDFILE)
   enum MHD_resp_sender_
   {
     MHD_resp_sender_std = 0,
     MHD_resp_sender_sendfile
   } resp_sender;
-#endif /* HAVE_LINUX_SENDFILE */
+#endif /* HAVE_LINUX_SENDFILE || HAVE_FREEBSD_SENDFILE */
 
   /**
    * Position in the 100 CONTINUE message that

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]