From 250a556b1e3eb8486ec294f94d3b918c9ac91542 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 2 Dec 2011 17:13:49 +0100 Subject: Make solaris use sendfilev sendfilev is a richer API which allows us to do non blocking TCP on solaris. The normal sendfile API seems to have some issue with non blocking sockets and the return value of sendfile. --- erts/configure.in | 4 +++- erts/emulator/drivers/common/erl_efile.h | 5 +++++ erts/emulator/drivers/unix/unix_efile.c | 24 +++++++++++++++++++++++- lib/kernel/test/sendfile_SUITE.erl | 13 ++++++------- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/erts/configure.in b/erts/configure.in index 548e4cc9d5..e937184f62 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -1697,7 +1697,9 @@ case $host_os in AC_CHECK_FUNCS([sendfile]) ;; solaris*) - AC_SEARCH_LIBS(sendfile, sendfile, AC_DEFINE(HAVE_SENDFILE, 1)) + AC_SEARCH_LIBS(sendfilev, sendfile, + AC_DEFINE([HAVE_SENDFILEV],[1], + [Define to 1 if you have the `sendfilev' function.])) ;; win32) LIBS="$LIBS -lmswsock" diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h index 349ab0e17b..ed8910a8b8 100644 --- a/erts/emulator/drivers/common/erl_efile.h +++ b/erts/emulator/drivers/common/erl_efile.h @@ -67,6 +67,11 @@ #define FILENAMES_16BIT 1 #endif +// We use sendfilev if it exist on solaris +#if !defined(HAVE_SENDFILE) && defined(HAVE_SENDFILEV) +#define HAVE_SENDFILE +#endif + /* * An handle to an open directory. To be cast to the correct type * in the system-dependent directory functions. diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 72911641d3..2b68334ad7 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -1488,7 +1488,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl* hdtl) { Uint64 written = 0; -#if defined(__linux__) || (defined(__sun) && defined(__SVR4)) +#if defined(__linux__) ssize_t retval; do { // check if *nbytes is 0 or greater than the largest size_t @@ -1503,6 +1503,28 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, } while (retval != -1 && retval == SENDFILE_CHUNK_SIZE); *nbytes = written; return check_error(retval == -1 ? -1 : 0, errInfo); +#elif defined(__sun) && defined(__SVR4) && defined(HAVE_SENDFILEV) + ssize_t retval; + size_t len; + sendfilevec_t fdrec; + fdrec.sfv_fd = in_fd; + fdrec.sfv_flag = SFV_NOWAIT; + do { + fdrec.sfv_off = *offset; + len = 0; + if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) + fdrec.sfv_len = SENDFILE_CHUNK_SIZE; + else + fdrec.sfv_len = *nbytes; + retval = sendfilev(out_fd, &fdrec, 1, &len); + if (retval != -1 || errno == EAGAIN || errno == EINTR) { + *offset += len; + *nbytes -= len; + written += len; + } + } while (len == SENDFILE_CHUNK_SIZE); + *nbytes = written; + return check_error(retval == -1 ? -1 : 0, errInfo); #elif defined(DARWIN) int retval; off_t len; diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl index 04af16a6b9..1b5119c684 100644 --- a/lib/kernel/test/sendfile_SUITE.erl +++ b/lib/kernel/test/sendfile_SUITE.erl @@ -99,7 +99,7 @@ t_sendfile_big(Config) when is_list(Config) -> Size end, - ok = sendfile_send("localhost", Send, 0). + ok = sendfile_send({127,0,0,1}, Send, 0). t_sendfile_partial(Config) -> Filename = proplists:get_value(small_file, Config), @@ -185,14 +185,14 @@ t_sendfile_sendduring(Config) -> {ok, #file_info{size = Size}} = file:read_file_info(Filename), spawn_link(fun() -> - timer:sleep(10), + timer:sleep(50), ok = gen_tcp:send(Sock, <<2>>) end), {ok, Size} = file:sendfile(Filename, Sock), Size+1 end, - ok = sendfile_send("localhost", Send, 0). + ok = sendfile_send({127,0,0,1}, Send, 0). t_sendfile_recvduring(Config) -> Filename = proplists:get_value(big_file, Config), @@ -201,7 +201,7 @@ t_sendfile_recvduring(Config) -> {ok, #file_info{size = Size}} = file:read_file_info(Filename), spawn_link(fun() -> - timer:sleep(10), + timer:sleep(50), ok = gen_tcp:send(Sock, <<1>>), {ok,<<1>>} = gen_tcp:recv(Sock, 1) end), @@ -210,11 +210,11 @@ t_sendfile_recvduring(Config) -> Size+1 end, - ok = sendfile_send("localhost", Send, 0). + ok = sendfile_send({127,0,0,1}, Send, 0). %% TODO: consolidate tests and reduce code sendfile_send(Send) -> - sendfile_send("localhost",Send). + sendfile_send({127,0,0,1},Send). sendfile_send(Host, Send) -> sendfile_send(Host, Send, []). sendfile_send(Host, Send, Orig) -> @@ -245,7 +245,6 @@ sendfile_server(ClientPid, Orig) -> gen_tcp:send(Sock, <<1>>). -define(SENDFILE_TIMEOUT, 10000). -%% f(),{ok, S} = gen_tcp:connect("localhost",7890,[binary]),file:sendfile("/ldisk/lukas/otp/sendfiletest.dat",S). sendfile_do_recv(Sock, Bs) -> receive {tcp, Sock, B} -> -- cgit v1.2.3