Skip to content

Commit

Permalink
Use file:sendfile/5 if available
Browse files Browse the repository at this point in the history
  • Loading branch information
Tuncer Ayaz authored and vinoski committed Feb 27, 2012
1 parent 7464efc commit 4113a99
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 45 deletions.
2 changes: 1 addition & 1 deletion c_src/Makefile
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ else
PRIV_FILES= ../priv/lib/setuid_drv.$(DLL) $(EPAM) PRIV_FILES= ../priv/lib/setuid_drv.$(DLL) $(EPAM)
endif endif


ifeq ($(HAVE_SENDFILE),true) ifeq ($(HAVE_YAWS_SENDFILE),true)
PRIV_FILES += ../priv/lib/yaws_sendfile_drv.$(DLL) PRIV_FILES += ../priv/lib/yaws_sendfile_drv.$(DLL)
endif endif


Expand Down
4 changes: 2 additions & 2 deletions c_src/yaws_sendfile_drv.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* author: vinoski@ieee.org */ /* author: vinoski@ieee.org */
/* Created : 09 Nov 2008 by Steve Vinoski <vinoski@ieee.org> */ /* Created : 09 Nov 2008 by Steve Vinoski <vinoski@ieee.org> */


#ifdef HAVE_SENDFILE #ifdef HAVE_YAWS_SENDFILE


#include <errno.h> #include <errno.h>
#include <stdint.h> #include <stdint.h>
Expand Down Expand Up @@ -328,4 +328,4 @@ DRIVER_INIT(yaws_sendfile_drv)


#error "yaws_sendfile_drv not supported on this platform" #error "yaws_sendfile_drv not supported on this platform"


#endif /* HAVE_SENDFILE */ #endif /* HAVE_YAWS_SENDFILE */
18 changes: 12 additions & 6 deletions configure.in
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ dnl in /usr/include/pam... I'm too sick of M4 at this very moment to write
dnl a test that searches for the files, so hard coded for now... dnl a test that searches for the files, so hard coded for now...
dnl or use --with-extrainclude=.... dnl or use --with-extrainclude=....
CFLAGS="$CFLAGS -I/usr/include/security" CFLAGS="$CFLAGS -I/usr/include/security"
HAVE_SENDFILE=false HAVE_YAWS_SENDFILE=false


case "$host_os" in case "$host_os" in
*linux*) *linux*)
Expand Down Expand Up @@ -242,7 +242,7 @@ case "$host_os" in
AC_SUBST(LD_SHARED) AC_SUBST(LD_SHARED)
FPIC=-fpic FPIC=-fpic
AC_SUBST(FPIC) AC_SUBST(FPIC)
HAVE_SENDFILE=true HAVE_YAWS_SENDFILE=true
;; ;;


*solaris*) *solaris*)
Expand All @@ -259,7 +259,7 @@ case "$host_os" in
AC_DEFINE(BSD) AC_DEFINE(BSD)
case "$host_os" in case "$host_os" in
freebsd*) freebsd*)
HAVE_SENDFILE=true HAVE_YAWS_SENDFILE=true
;; ;;
bsdi*) bsdi*)
BSDI=bsdi BSDI=bsdi
Expand All @@ -274,7 +274,7 @@ case "$host_os" in
;; ;;
*darwin*) *darwin*)
AC_LANG(C) AC_LANG(C)
AC_CHECK_LIB([c],[sendfile],[HAVE_SENDFILE=true]) AC_CHECK_LIB([c],[sendfile],[HAVE_YAWS_SENDFILE=true])
case "$host_os" in case "$host_os" in
darwin1?*) darwin1?*)
AC_LANG(Erlang) AC_LANG(Erlang)
Expand Down Expand Up @@ -316,8 +316,14 @@ case "$host_os" in
esac esac


AC_ARG_ENABLE(sendfile, AS_HELP_STRING([--disable-sendfile], [disables use of sendfile system call]), AC_ARG_ENABLE(sendfile, AS_HELP_STRING([--disable-sendfile], [disables use of sendfile system call]),
[ test "$enableval" = no && HAVE_SENDFILE=false ]) [ test "$enableval" = no && HAVE_YAWS_SENDFILE=false ])
AC_SUBST(HAVE_SENDFILE) file_sendfile=`"${ERL}" -noshell -eval 'io:format("~p~n",[[erlang:function_exported(file, sendfile, 5)]]), erlang:halt().' | tail -1`
if [ "$file_sendfile" = true ] ; then
HAVE_YAWS_SENDFILE=false
AC_MSG_NOTICE(found file:sendfile/5)
fi
AC_SUBST(HAVE_YAWS_SENDFILE)

YTOP=`pwd` YTOP=`pwd`
AC_SUBST(YTOP) AC_SUBST(YTOP)
AC_OUTPUT(include.mk) AC_OUTPUT(include.mk)
Expand Down
6 changes: 3 additions & 3 deletions include.mk.in
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ DEFAULT_CHARSET=@DEFAULT_CHARSET@
EPAM = @EPAM@ EPAM = @EPAM@
EXTRAINCLUDE = @EXTRAINCLUDE@ EXTRAINCLUDE = @EXTRAINCLUDE@
ERLBINDIR = @ERLBINDIR@ ERLBINDIR = @ERLBINDIR@
HAVE_SENDFILE = @HAVE_SENDFILE@ HAVE_YAWS_SENDFILE = @HAVE_YAWS_SENDFILE@
BITS_SUPPORT = @BITS_SUPPORT@ BITS_SUPPORT = @BITS_SUPPORT@


ifdef debug ifdef debug
Expand All @@ -43,8 +43,8 @@ endif


CC=@CC@ CC=@CC@
CFLAGS=@CFLAGS@ CFLAGS=@CFLAGS@
ifeq ($(HAVE_SENDFILE),true) ifeq ($(HAVE_YAWS_SENDFILE),true)
CFLAGS += -DHAVE_SENDFILE CFLAGS += -DHAVE_YAWS_SENDFILE
endif endif
LINKER=@LINKER@ LINKER=@LINKER@
LDFLAGS=@LDFLAGS@ LDFLAGS=@LDFLAGS@
Expand Down
13 changes: 8 additions & 5 deletions rebar.config
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@
{plugins, [rebar_reltool_link]}. {plugins, [rebar_reltool_link]}.
{sub_dirs, ["rel"]}. {sub_dirs, ["rel"]}.


{erl_opts, [{platform_define, {erl_opts, [%% OTP R11 - R15A -> yaws_sendfile_drv or compat_send
"(linux|freebsd|darwin)", 'HAVE_SENDFILE'}, {platform_define,
"R1([1-4]|5A).*(linux|freebsd|darwin)", 'HAVE_YAWS_SENDFILE'},
{platform_define, "R1([1-4]|5A).*", 'NO_FILE_SENDFILE'},
no_debug_info, no_debug_info,
{src_dirs, ["src", "examples/src"]}, {src_dirs, ["src", "examples/src"]},
warnings_as_errors]}. warnings_as_errors]}.


{port_envs, [{"CFLAGS", "$CFLAGS -g -O3 -Wall -I/usr/include/security"}, {port_envs, [{"CFLAGS", "$CFLAGS -g -O3 -Wall -I/usr/include/security"},
{"(linux|freebsd|dragonfly|solaris|darwin)", {"R1([1-4]|5A).*(linux|freebsd|darwin)",
"DRV_CFLAGS", "$DRV_CFLAGS -DHAVE_SENDFILE"}]}. "DRV_CFLAGS", "$DRV_CFLAGS -DHAVE_YAWS_SENDFILE"}]}.


{port_specs, [{"priv/lib/epam.so", ["c_src/epam.c"]}, {port_specs, [{"priv/lib/epam.so", ["c_src/epam.c"]},
{"priv/lib/setuid_drv.so", ["c_src/setuid_drv.c"]}, {"priv/lib/setuid_drv.so", ["c_src/setuid_drv.c"]},
{"priv/lib/yaws_sendfile_drv.so", {"R1([1-4]|5A).*(linux|freebsd|darwin)",
"priv/lib/yaws_sendfile_drv.so",
["c_src/yaws_sendfile_drv.c", "c_src/hashtable.c"]}]}. ["c_src/yaws_sendfile_drv.c", "c_src/hashtable.c"]}]}.


{pre_hooks, [{compile, "./scripts/rebar-pre-script"}, {pre_hooks, [{compile, "./scripts/rebar-pre-script"},
Expand Down
3 changes: 2 additions & 1 deletion scripts/rebar-pre-script
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ if [ -n "$need_mime" ]; then
fi fi


if [ ! -f yaws_configure.hrl ]; then if [ ! -f yaws_configure.hrl ]; then
echo '%% rebar sets HAVE_SENDFILE in erlc command line' > yaws_configure.hrl echo '%% rebar sets HAVE_YAWS_SENDFILE in erlc command line' \
> yaws_configure.hrl
[ $? -eq 0 ] || fail [ $? -eq 0 ] || fail
fi fi
tmpgen=`mktemp /tmp/${script}.XXXXXX` || fail tmpgen=`mktemp /tmp/${script}.XXXXXX` || fail
Expand Down
4 changes: 2 additions & 2 deletions src/Makefile
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ yaws_generated.erl: yaws_generated.template ../vsn.mk
../scripts/gen-yaws-generated true > yaws_generated.erl ../scripts/gen-yaws-generated true > yaws_generated.erl


yaws_configure.hrl: ../vsn.mk ../include.mk yaws_configure.hrl: ../vsn.mk ../include.mk
if [ $(HAVE_SENDFILE) = "true" ]; then \ if [ $(HAVE_YAWS_SENDFILE) = "true" ]; then \
echo "-define(HAVE_SENDFILE, true)." > yaws_configure.hrl; \ echo "-define(HAVE_YAWS_SENDFILE, true)." > yaws_configure.hrl; \
else touch yaws_configure.hrl; fi else touch yaws_configure.hrl; fi




Expand Down
85 changes: 61 additions & 24 deletions src/yaws_sendfile.erl
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -11,23 +11,70 @@


-include("yaws_configure.hrl"). -include("yaws_configure.hrl").
-include("../include/yaws.hrl"). -include("../include/yaws.hrl").
-include_lib("kernel/include/file.hrl").


-ifdef(HAVE_SENDFILE). -ifndef(HAVE_YAWS_SENDFILE).
-ifndef(NO_FILE_SENDFILE).
-define(HAVE_FILE_SENDFILE, 1).
-endif.
-endif.



-ifdef(HAVE_YAWS_SENDFILE).
-behavior(gen_server). -behavior(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
code_change/3]). code_change/3]).

-include_lib("kernel/include/file.hrl").

-endif. -endif.


send(Out, Filename) -> send(Out, Filename) ->
send(Out, Filename, 0, all). send(Out, Filename, 0, all).
send(Out, Filename, Offset) -> send(Out, Filename, Offset) ->
send(Out, Filename, Offset, all). send(Out, Filename, Offset, all).


-ifdef(HAVE_SENDFILE). bytes_to_transfer(Filename, Offset, Count) ->
case Count of
all ->
case file:read_file_info(Filename) of
{ok, #file_info{size = Size}} ->
Size - Offset;
Error ->
Error
end;
Count when is_integer(Count) ->
Count;
_ ->
{error, badarg}
end.

-ifdef(HAVE_FILE_SENDFILE). %% OTP >= R15B; use file:sendfile/5

enabled() ->
true.
send(Out, Filename, Offset, Count) ->
Count1 = bytes_to_transfer(Filename, Offset, Count),
case Count1 of
{error, _}=Error1 ->
Error1;
_ ->
case file:open(Filename, [raw, read, binary]) of
{ok, RawFile} ->
Res = file:sendfile(RawFile, Out, Offset, Count1, []),
ok = file:close(RawFile),
Res;
Error2 ->
Error2
end
end.
start_link() ->
ignore.
start() ->
ignore.
stop() ->
ok.

-else.

-ifdef(HAVE_YAWS_SENDFILE).


start_link() -> start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
Expand All @@ -39,28 +86,16 @@ enabled() ->
true. true.


send(Out, Filename, Offset, Count) -> send(Out, Filename, Offset, Count) ->
Count1 = case Count of Count1 = bytes_to_transfer(Filename, Offset, Count),
all ->
case file:read_file_info(Filename) of
{ok, #file_info{size = Size}} ->
Size - Offset;
Error ->
Error
end;
Count when is_integer(Count) ->
Count;
_ ->
{error, badarg}
end,
case Count1 of case Count1 of
{error, _}=Error2 -> {error, _}=Error ->
Error2; Error;
_ -> _ ->
case prim_inet:getfd(Out) of case prim_inet:getfd(Out) of
{ok, SocketFd} -> {ok, SocketFd} ->
do_send(Out, SocketFd, Filename, Offset, Count1); do_send(Out, SocketFd, Filename, Offset, Count1);
Error3 -> Error2 ->
Error3 Error2
end end
end. end.


Expand Down Expand Up @@ -149,14 +184,14 @@ do_send(Out, SocketFd, Filename, Offset, Count) ->


enabled() -> enabled() ->
false. false.
send(Out, Filename, Offset, Count) ->
compat_send(Out, Filename, Offset, Count).
start_link() -> start_link() ->
ignore. ignore.
start() -> start() ->
ignore. ignore.
stop() -> stop() ->
ok. ok.
send(Out, Filename, Offset, Count) ->
compat_send(Out, Filename, Offset, Count).


-endif. -endif.


Expand Down Expand Up @@ -203,3 +238,5 @@ loop_send(Fd, ChunkSize, {ok, Bin}, Out, Count) ->
end; end;
loop_send(_Fd, _, Err, _,_) -> loop_send(_Fd, _, Err, _,_) ->
Err. Err.

-endif.
2 changes: 1 addition & 1 deletion win32/include.mk
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ DEFAULT_CHARSET=
EPAM = ../priv/epam EPAM = ../priv/epam
EXTRAINCLUDE = EXTRAINCLUDE =
ERLBINDIR = /usr/lib/erlang/bin ERLBINDIR = /usr/lib/erlang/bin
HAVE_SENDFILE = true HAVE_YAWS_SENDFILE = true


ifdef debug ifdef debug
ERLC_FLAGS+=-Ddebug ERLC_FLAGS+=-Ddebug
Expand Down

0 comments on commit 4113a99

Please sign in to comment.