aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2011-11-29 11:05:37 +0100
committerLukas Larsson <[email protected]>2011-12-02 10:39:38 +0100
commit1bbf8cee44b8836d66d289cc0b5b314ed83de821 (patch)
tree6d7ab44fd0d11c33f885816ddb12dfbc785f4540
parent27faa34693f35b6aa41fa67cbfe365bd082a5757 (diff)
downloadotp-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.c72
-rw-r--r--erts/emulator/drivers/common/erl_efile.h2
-rw-r--r--erts/emulator/drivers/unix/unix_efile.c14
-rw-r--r--erts/preloaded/src/prim_file.erl13
-rw-r--r--lib/kernel/doc/src/file.xml25
-rw-r--r--lib/kernel/src/file.erl15
-rw-r--r--lib/kernel/test/sendfile_SUITE.erl42
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),