diff options
-rw-r--r-- | lib/kernel/doc/src/file.xml | 66 | ||||
-rw-r--r-- | lib/kernel/src/file.erl | 18 |
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} -> |