aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/kernel/doc/src/file.xml66
-rw-r--r--lib/kernel/src/file.erl18
2 files changed, 66 insertions, 18 deletions
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index 78bf0aff45..7fcc354176 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -149,6 +149,9 @@
<datatype>
<name name="mode"/>
</datatype>
+ <datatype>
+ <name name="sendfile_option"/>
+ </datatype>
</datatypes>
<funcs>
@@ -1574,25 +1577,70 @@
</desc>
</func>
<func>
- <name name="sendfile" arity="4"/>
+ <name name="sendfile" arity="2"/>
<fsummary>send a file to a socket</fsummary>
<desc>
- <p>Sends <c>Bytes</c> in from the file
- referenced by <c>IoDevice</c> beginning at <c>Offset</c> to
- <c>Socket</c>.
+ <p>Sends the file <c>Filename</c> to <c>Socket</c>.
Returns <c>{ok, BytesSent}</c> if successful,
otherwise <c>{error, Reason}</c>.</p>
- <p>Available on Linux, FreeBSD, DragonflyBSD, Solaris, Darwin and Windows</p>
</desc>
</func>
<func>
- <name name="sendfile" arity="2"/>
+ <name name="sendfile" arity="5"/>
<fsummary>send a file to a socket</fsummary>
<desc>
- <p>Sends the file <c>Filename</c> to <c>Socket</c>.
+ <p>Sends <c>Bytes</c> from the file
+ referenced by <c>RawFile</c> beginning at <c>Offset</c> to
+ <c>Socket</c>.
Returns <c>{ok, BytesSent}</c> if successful,
- otherwise <c>{error, Reason}</c>.</p>
- <p>Available on Linux, FreeBSD, DragonflyBSD, Solaris, Darwin and Windows</p>
+ otherwise <c>{error, Reason}</c>. If <c>Bytes</c> is set to
+ 0 all data after the given <c>Offset</c> is sent.</p>
+ <p>The file used must be opened using the raw flag, and the process
+ calling sendfile must be the controlling process of the socket.
+ See <seealso marker="gen_tcp#controlling_process-2">gen_tcp:controlling_process/2</seealso></p>
+ <p>If the OS used does not support sendfile, an Erlang fallback
+ using file:read and gen_tcp:send is used.</p>
+ <p>The option list can contain the following options:
+ <taglist>
+ <tag><c>headers</c></tag>
+ <item>A list containing data which is to be sent before
+ the file is sent. If <c>headers</c> is used, <c>Bytes</c> specifies
+ the total bytes in the header and/or file to be sent. If
+ <c>Bytes</c> is set to 0, the all headers, the file and
+ possible trailers will be sent. </item>
+ <tag><c>trailers</c></tag>
+ <item>A list containing data which is to be after before
+ the file is sent. All the <c>trailers</c> will be sent after the
+ file is sent, no matter what <c>Bytes</c> is set to. </item>
+ <tag><c>chunk_size</c></tag>
+ <item>The chunk size used by the erlang fallback to send
+ data. If using the fallback, this should be set to a value
+ which comfortably fits in the systems memory. Default is 20 MB.</item>
+ <tag><c>sf_nodiskio</c></tag>
+ <item>This flag causes any sendfile() call which would
+ block on disk I/O to instead return EBUSY. Busy servers may bene-
+ fit by transferring requests that would block to a separate I/O
+ worker thread.</item>
+ <tag><c>sf_mnowait</c></tag>
+ <item>Do not wait for some kernel resource to become avail-
+ able, in particular, mbuf and sf_buf. The flag does not make the
+ sendfile() syscall truly non-blocking, since other resources are
+ still allocated in a blocking fashion.</item>
+ <tag><c>sf_sync</c></tag>
+ <item>sendfile sleeps until the network stack no longer refer-
+ ences the VM pages of the file, making subsequent modifications to
+ it safe. Please note that this is not a guarantee that the data
+ has actually been sent.</item>
+ </taglist>
+ </p>
+ <p>On operating systems with thread support, it is recommended to use
+ async threads. See the command line flag
+ <c>+A</c> in <seealso marker="erts:erl">erl(1)</seealso>. If it is not
+ possible to use async threads for sendfile, it is recommended to use
+ a relatively small value for the send buffer on the socket. Otherwise
+ the Erlang VM might loose some of its soft realtime guarantees.
+ Which size to use depends on the OS/hardware and the requirements
+ of the application.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index ef1d20b53b..19eaa7bfcc 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -106,7 +106,7 @@
-type date_time() :: calendar:datetime().
-type posix_file_advise() :: 'normal' | 'sequential' | 'random'
| 'no_reuse' | 'will_need' | 'dont_need'.
--type sendfile_option() :: {chunk_size, non_neg_integer()} |
+-type sendfile_option() :: {chunk_size, pos_integer()} |
{headers, Hdrs :: list(iodata())} |
{trailers, Tlrs :: list(iodata())} |
sf_nodiskio | sf_mnowait | sf_sync.
@@ -1126,10 +1126,10 @@ change_time(Name, Atime, Mtime)
-define(MAX_CHUNK_SIZE, (1 bsl 20)*20). %% 20 MB, has to fit in primary memory
--spec sendfile(File, Sock, Offset, Bytes, Opts) ->
+-spec sendfile(RawFile, Socket, Offset, Bytes, Opts) ->
{'ok', non_neg_integer()} | {'error', inet:posix() | badarg | not_owner} when
- File :: file:fd(),
- Sock :: inet:socket(),
+ RawFile :: file:fd(),
+ Socket :: inet:socket(),
Offset :: non_neg_integer(),
Bytes :: non_neg_integer(),
Opts :: [sendfile_option()].
@@ -1151,12 +1151,12 @@ sendfile(File, Sock, Offset, Bytes, Opts) ->
lists:member(sf_sync,Opts)).
%% sendfile/2
--spec sendfile(File, Sock) ->
+-spec sendfile(Filename, Socket) ->
{'ok', non_neg_integer()} | {'error', inet:posix() | badarg | not_owner}
- when File :: file:name(),
- Sock :: inet:socket().
-sendfile(File, Sock) ->
- case file:open(File, [read, raw, binary]) of
+ when Filename :: file:name(),
+ Socket :: inet:socket().
+sendfile(Filename, Sock) ->
+ case file:open(Filename, [read, raw, binary]) of
{error, Reason} ->
{error, Reason};
{ok, Fd} ->