-
Notifications
You must be signed in to change notification settings - Fork 267
/
yaws_sendfile_compat.erl
109 lines (96 loc) · 2.83 KB
/
yaws_sendfile_compat.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
%%% File : yaws_sendfile_compat.erl
%%% Author : Claes Wikstrom, klacke@hyber.org
%%% Description : Conditional OS dependent call to sendfile
%%% Created : Sat Dec 20 20:00:11 CET 2008
-module(yaws_sendfile_compat).
-export([start_link/0, init/1, stop/0, send/2, send/3, send/4, enabled/0]).
-include_lib("kernel/include/file.hrl").
-include("yaws_configure.hrl").
-include("../include/yaws.hrl").
%% will be true for MacOsX, FreeBSD, Linux
-ifdef(HAVE_SENDFILE).
enabled() ->
true.
start_link() ->
yaws_sendfile:start_link().
stop() ->
yaws_sendfile:stop().
init(ShLib) ->
yaws_sendfile:init(ShLib).
send(Out, FileName) ->
case yaws_sendfile:send(Out, FileName) of
{error, eoverflow} ->
compat_send(Out, FileName, 0, all);
Other ->
Other
end.
send(Out, FileName, Offset) ->
case yaws_sendfile:send(Out, FileName, Offset) of
{error, eoverflow} ->
compat_send(Out, FileName, Offset, all);
Other ->
Other
end.
send(Out, FileName, Offset, Count) ->
case yaws_sendfile:send(Out, FileName, Offset, Count) of
{error, eoverflow} ->
compat_send(Out, FileName, Offset, Count);
Other ->
Other
end.
-else.
%% Emulate sendfile, this is true for win32, qnx, solaris. OpenBSD,NetBSD I
%% still don't know
enabled() ->
false.
start_link() ->
ignore.
stop() ->
ok.
init(_) ->
ok.
send(Out, Filename) ->
send(Out, Filename, 0, all).
send(Out, Filename, Offset) ->
send(Out, Filename, Offset, all).
send(Out, Filename, Offset, Count) ->
compat_send(Out, Filename, Offset, Count).
-endif.
compat_send(Out, Filename, Offset, Count) ->
case file:open(Filename, [read, binary, raw]) of
{ok, Fd} ->
file:position(Fd, {bof, Offset}),
ChunkSize = (get(gc))#gconf.large_file_chunk_size,
Ret = loop_send(Fd, ChunkSize, file:read(Fd, ChunkSize), Out, Count),
file:close(Fd),
Ret;
Err ->
Err
end.
loop_send(Fd, ChunkSize, {ok, Bin}, Out, all) ->
case gen_tcp:send(Out, Bin) of
ok ->
loop_send(Fd, ChunkSize, file:read(Fd, ChunkSize), Out, all);
Err ->
Err
end;
loop_send(_Fd, _ChunkSize, eof, _Out, _) ->
ok;
loop_send(Fd, ChunkSize, {ok, Bin}, Out, Count) ->
Sz = size(Bin),
if Sz < Count ->
case gen_tcp:send(Out, Bin) of
ok ->
loop_send(Fd, ChunkSize, file:read(Fd, ChunkSize),
Out, Count-Sz);
Err ->
Err
end;
Sz == Count ->
gen_tcp:send(Out, Bin);
Sz > Count ->
<<Deliver:Count/binary , _/binary>> = Bin,
gen_tcp:send(Out, Deliver)
end;
loop_send(_Fd, _, Err, _,_) ->
Err.