diff options
author | Lukas Larsson <[email protected]> | 2011-11-29 11:05:37 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2011-12-02 10:39:38 +0100 |
commit | 1bbf8cee44b8836d66d289cc0b5b314ed83de821 (patch) | |
tree | 6d7ab44fd0d11c33f885816ddb12dfbc785f4540 | |
parent | 27faa34693f35b6aa41fa67cbfe365bd082a5757 (diff) | |
download | otp-1bbf8cee44b8836d66d289cc0b5b314ed83de821.tar.gz otp-1bbf8cee44b8836d66d289cc0b5b314ed83de821.tar.bz2 otp-1bbf8cee44b8836d66d289cc0b5b314ed83de821.zip |
Remove header/trailer support
Since the API for headers/trailers seem to be very awkward to
work with when using non-blocking io the feature is dropped
for now. See unix_efile.c for more details.
-rw-r--r-- | erts/emulator/drivers/common/efile_drv.c | 72 | ||||
-rw-r--r-- | erts/emulator/drivers/common/erl_efile.h | 2 | ||||
-rw-r--r-- | erts/emulator/drivers/unix/unix_efile.c | 14 | ||||
-rw-r--r-- | erts/preloaded/src/prim_file.erl | 13 | ||||
-rw-r--r-- | lib/kernel/doc/src/file.xml | 25 | ||||
-rw-r--r-- | lib/kernel/src/file.erl | 15 | ||||
-rw-r--r-- | lib/kernel/test/sendfile_SUITE.erl | 42 |
7 files changed, 32 insertions, 151 deletions
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 7eaafd5af1..5c52b99348 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -431,8 +431,6 @@ struct t_data off_t offset; Uint64 nbytes; Uint64 written; - short flags; - struct t_sendfile_hdtl *hdtl; } sendfile; #endif /* HAVE_SENDFILE */ } c; @@ -521,9 +519,6 @@ static void *ef_safe_realloc(void *op, Uint s) !0) \ : 0) -/* int EV_GET_SYSIOVEC(ErlIoVec *ev, Uint32, int *cnt, SysIOVec **target, int *pp, int *qp) */ -#define EV_GET_SYSIOVEC ev_get_sysiovec - #if 0 @@ -935,43 +930,6 @@ static int reply_eof(file_descriptor *desc) { driver_output2(desc->port, &c, 1, NULL, 0); return 0; } - -static int ev_get_sysiovec(ErlIOVec *ev, Uint32 len, int *cnt, SysIOVec **target, int *pp, int *qp) { - int tmp_p = *pp, tmp_q = *qp, tmp_len = len, i; - SysIOVec *tmp_target; - while (tmp_len != 0) { - if (tmp_len + tmp_p > ev->iov[tmp_q].iov_len) { - - tmp_len -= ev->iov[tmp_q].iov_len - tmp_p; - tmp_q++; - tmp_p = 0; - if (tmp_q == ev->vsize) - return 0; - } else break; - } - *cnt = tmp_q - *qp + 1; - tmp_target = EF_SAFE_ALLOC(sizeof(SysIOVec)* (*cnt)); - *target = tmp_target; - for (i = 0; i < *cnt; i++) { - tmp_target[i].iov_base = ev->iov[*qp].iov_base+*pp; - if (len + *pp <= ev->iov[*qp].iov_len) { - tmp_target[i].iov_len = len; - if (len + *pp == ev->iov[*qp].iov_len) { - *pp = 0; - (*qp)++; - } else - *pp += len; - } else { - tmp_target[i].iov_len = ev->iov[*qp].iov_len - *pp; - len -= ev->iov[*qp].iov_len - *pp; - *pp = 0; - (*qp)++; - } - } - return 1; -} - - static void invoke_name(void *data, int (*f)(Efile_error *, char *)) { @@ -1781,7 +1739,7 @@ static void invoke_sendfile(void *data) int result = 0; d->again = 0; - result = efile_sendfile(&d->errInfo, fd, out_fd, &d->c.sendfile.offset, &nbytes, &d->c.sendfile.hdtl); + result = efile_sendfile(&d->errInfo, fd, out_fd, &d->c.sendfile.offset, &nbytes, NULL); d->c.sendfile.written += nbytes; @@ -3426,14 +3384,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { Uint64 nbytes; char flags; - /* DestFD:32, Offset:64, Bytes:64, - ChunkSize:64, - (get_bit(Nodiskio)):1, - (get_bit(MNowait)):1, - (get_bit(Sync)):1,0:5, - (encode_hdtl(Headers))/binary, - (encode_hdtl(Trailers))/binary */ - if (ev->size < 1 + 1 + 5 * sizeof(Uint32) + sizeof(char) + if (ev->size < 1 + 7 * sizeof(Uint32) + sizeof(char) || !EV_GET_UINT32(ev, &out_fd, &p, &q) || !EV_GET_CHAR(ev, &flags, &p, &q) || !EV_GET_UINT32(ev, &offsetH, &p, &q) @@ -3446,6 +3397,12 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } + if (hd_len != 0 || tl_len != 0 || flags != 0) { + // We do not allow header, trailers and/or flags right now + reply_posix_error(desc, EINVAL); + goto done; + } + d = EF_SAFE_ALLOC(sizeof(struct t_data)); d->fd = desc->fd; d->command = command; @@ -3454,7 +3411,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->level = 2; d->c.sendfile.out_fd = (int) out_fd; - d->c.sendfile.flags = (int) flags; d->c.sendfile.written = 0; #if SIZEOF_OFF_T == 4 @@ -3468,18 +3424,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #endif d->c.sendfile.nbytes = nbytes; - if (hd_len == 0 && tl_len == 0) - d->c.sendfile.hdtl = NULL; - else { - d->c.sendfile.hdtl = EF_SAFE_ALLOC(sizeof(struct t_sendfile_hdtl)); - if (!EV_GET_SYSIOVEC(ev, hd_len, &d->c.sendfile.hdtl->hdr_cnt, &d->c.sendfile.hdtl->headers, &p, &q) - || !EV_GET_SYSIOVEC(ev, tl_len, &d->c.sendfile.hdtl->trl_cnt, &d->c.sendfile.hdtl->trailers, &p, &q)) { - EF_FREE(d->c.sendfile.hdtl); - EF_FREE(d); - reply_posix_error(desc, EINVAL); - goto done; - } - } if (sys_info.async_threads != 0) { SET_BLOCKING(d->c.sendfile.out_fd); diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h index b73fb35120..349ab0e17b 100644 --- a/erts/emulator/drivers/common/erl_efile.h +++ b/erts/emulator/drivers/common/erl_efile.h @@ -177,5 +177,5 @@ int efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, Sint64 length, int advise); #ifdef HAVE_SENDFILE int efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, - off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl **hdtl); + off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl *hdtl); #endif /* HAVE_SENDFILE */ diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 138c550fdd..72911641d3 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -1471,9 +1471,21 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, #ifdef HAVE_SENDFILE #define SENDFILE_CHUNK_SIZE ((1 << 30) -1) +/* + * sendfile: The implementation of the sendfile system call varies + * a lot on different *nix platforms so to make the api similar in all + * we have to emulate some things in linux and play with variables on + * bsd/darwin. + * + * It could be possible to implement header/trailer in sendfile, though + * you would have to emulate it in linux and on BSD/Darwin some complex + * calculations have to be made when using a non blocking socket to figure + * out how much of the header/file/trailer was sent in each command. + */ + int efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, - off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl** hdtl) + off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl* hdtl) { Uint64 written = 0; #if defined(__linux__) || (defined(__sun) && defined(__SVR4)) diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl index 6f35162feb..7316e0be99 100644 --- a/erts/preloaded/src/prim_file.erl +++ b/erts/preloaded/src/prim_file.erl @@ -545,7 +545,7 @@ write_file(_, _) -> %sendfile(_,_,_,_,_,_,_,_,_,_) -> % {error, enotsup}; sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}}, - Dest, Offset, Bytes, _ChunkSize, _Headers, _Trailers, + Dest, Offset, Bytes, _ChunkSize, Headers, Trailers, _Nodiskio, _MNowait, _Sync) -> case erlang:port_get_data(Dest) of Data when Data == inet_tcp; Data == inet6_tcp -> @@ -555,8 +555,9 @@ sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}}, 0:8, Offset:64/unsigned, Bytes:64/unsigned, - 0:32/unsigned, - 0:32/unsigned>>]) + (iolist_size(Headers)):32/unsigned, + (iolist_size(Trailers)):32/unsigned>>, + Headers,Trailers]) after ok = inet:lock_socket(Dest,false) end; @@ -564,12 +565,6 @@ sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}}, {error,badarg} end. -get_bit(true) -> - 1; -get_bit(false) -> - 0. - - %%%----------------------------------------------------------------- %%% Functions operating on files without handle to the file. ?DRV. diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 7fcc354176..c6a1f25dd9 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -1602,35 +1602,10 @@ 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 diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 19eaa7bfcc..0b0f91d86a 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -106,10 +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, pos_integer()} | - {headers, Hdrs :: list(iodata())} | - {trailers, Tlrs :: list(iodata())} | - sf_nodiskio | sf_mnowait | sf_sync. +-type sendfile_option() :: {chunk_size, non_neg_integer()}. %%%----------------------------------------------------------------- %%% General functions @@ -1144,11 +1141,11 @@ sendfile(File, Sock, Offset, Bytes, Opts) -> ?MAX_CHUNK_SIZE; true -> ChunkSize0 end, - Headers = proplists:get_value(headers, Opts, []), - Trailers = proplists:get_value(trailers, Opts, []), - sendfile(File, Sock, Offset, Bytes, ChunkSize, Headers, Trailers, - lists:member(sf_nodiskio,Opts),lists:member(sf_mnowait,Opts), - lists:member(sf_sync,Opts)). + %% Support for headers, trailers and options has been removed because the + %% Darwin and BSD API for using it does not play nice with + %% non-blocking sockets. See unix_efile.c for more info. + sendfile(File, Sock, Offset, Bytes, ChunkSize, [], [], + false,false,false). %% sendfile/2 -spec sendfile(Filename, Socket) -> diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl index cddb783fe7..5312508918 100644 --- a/lib/kernel/test/sendfile_SUITE.erl +++ b/lib/kernel/test/sendfile_SUITE.erl @@ -27,7 +27,6 @@ all() -> [t_sendfile_small ,t_sendfile_big -% ,t_sendfile_hdtl ,t_sendfile_partial ,t_sendfile_offset ,t_sendfile_sendafter @@ -130,47 +129,6 @@ t_sendfile_offset(Config) -> ok = sendfile_send(Send). -t_sendfile_hdtl(Config) -> - Filename = proplists:get_value(small_file, Config), - FileOpts = proplists:get_value(file_opts, Config, []), - - Send = fun(Sock, Headers, Trailers, HdtlSize) -> - {Size, Data} = sendfile_file_info(Filename), - {ok,D} = file:open(Filename,[read|FileOpts]), - AllSize = Size+HdtlSize, - {ok, AllSize} = file:sendfile( - D, Sock,0,0, - [{headers,Headers}, - {trailers,Trailers}]), - file:close(D), - Data - end, - - SendHdTl = fun(Sock) -> - Headers = [<<"header1">>,<<0:(1024*8)>>,"header2"], - Trailers = [<<"trailer1">>,"trailer2"], - D = Send(Sock,Headers,Trailers, - iolist_size([Headers,Trailers])), - iolist_to_binary([Headers,D,Trailers]) - end, - ok = sendfile_send(SendHdTl), - - SendHd = fun(Sock) -> - Headers = [<<"header1">>,"header2"], - D = Send(Sock,Headers,undefined, - iolist_size([Headers])), - iolist_to_binary([Headers,D]) - end, - ok = sendfile_send(SendHd), - - SendTl = fun(Sock) -> - Trailers = [<<"trailer1">>,"trailer2"], - D = Send(Sock,undefined,Trailers, - iolist_size([Trailers])), - iolist_to_binary([D,Trailers]) - end, - ok = sendfile_send(SendTl). - t_sendfile_sendafter(Config) -> Filename = proplists:get_value(small_file, Config), |