summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmil Renner Berthing <esmil@mailme.dk>2013-01-09 13:42:03 +0100
committerEmil Renner Berthing <esmil@mailme.dk>2013-01-09 21:50:00 +0100
commitf8d493d6411d1538960ec19cb3b6aa67542c7d95 (patch)
treea96a65048abdc2887bed3d190b1eaf962464e65e
parent12c0a611cdf15bf8f86d870af5fa97881a457b0a (diff)
downloadlem-f8d493d6411d1538960ec19cb3b6aa67542c7d95.tar.gz
lem-f8d493d6411d1538960ec19cb3b6aa67542c7d95.tar.xz
lem-f8d493d6411d1538960ec19cb3b6aa67542c7d95.zip
io: allow simultaneous sendfile on the same file
-rw-r--r--lem/io/file.c5
-rw-r--r--lem/io/stream.c79
2 files changed, 44 insertions, 40 deletions
diff --git a/lem/io/file.c b/lem/io/file.c
index 043c1b9..e9bb3d0 100644
--- a/lem/io/file.c
+++ b/lem/io/file.c
@@ -41,11 +41,6 @@ struct file {
off_t len;
short type;
} lock;
- struct {
- struct stream *stream;
- off_t size;
- off_t offset;
- } sendfile;
};
struct lem_inputbuf buf;
};
diff --git a/lem/io/stream.c b/lem/io/stream.c
index 7acccdc..80a3f65 100644
--- a/lem/io/stream.c
+++ b/lem/io/stream.c
@@ -310,15 +310,24 @@ stream_uncork(lua_State *T)
return stream_setcork(T, 0);
}
+struct sfhandle {
+ struct lem_async a;
+ struct stream *s;
+ off_t size;
+ off_t offset;
+ int fd;
+ int ret;
+};
+
static void
stream_sendfile_work(struct lem_async *a)
{
- struct file *f = (struct file *)a;
- struct stream *s = f->sendfile.stream;
+ struct sfhandle *sf = (struct sfhandle *)a;
+ struct stream *s = sf->s;
/* make socket blocking */
if (fcntl(s->w.fd, F_SETFL, 0)) {
- f->ret = errno;
+ sf->ret = errno;
close(s->w.fd);
s->r.fd = s->w.fd = -1;
return;
@@ -326,40 +335,40 @@ stream_sendfile_work(struct lem_async *a)
#ifdef __FreeBSD__
off_t written;
- int ret = sendfile(f->fd, s->w.fd,
- f->sendfile.offset, f->sendfile.size,
+ int ret = sendfile(sf->fd, s->w.fd,
+ sf->offset, sf->size,
NULL, &written, SF_SYNC);
if (ret == 0) {
- f->ret = 0;
- f->sendfile.size = written;
+ sf->ret = 0;
+ sf->size = written;
} else
- f->ret = errno;
+ sf->ret = errno;
lem_debug("wrote = %ld bytes", written);
#else
#ifdef __APPLE__
- int ret = sendfile(f->fd, s->w.fd,
- f->sendfile.offset, &f->sendfile.size,
+ int ret = sendfile(sf->fd, s->w.fd,
+ sf->offset, &sf->size,
NULL, 0);
if (ret == 0)
- f->ret = 0;
+ sf->ret = 0;
else
- f->ret = errno;
- lem_debug("wrote = %lld bytes", f->sendfile.size);
+ sf->ret = errno;
+ lem_debug("wrote = %lld bytes", sf->size);
#else
- ssize_t ret = sendfile(s->w.fd, f->fd,
- &f->sendfile.offset, f->sendfile.size);
+ ssize_t ret = sendfile(s->w.fd, sf->fd,
+ &sf->offset, sf->size);
if (ret >= 0) {
- f->ret = 0;
- f->sendfile.size = ret;
+ sf->ret = 0;
+ sf->size = ret;
} else
- f->ret = errno;
+ sf->ret = errno;
lem_debug("wrote = %ld bytes", ret);
#endif
#endif
/* make socket non-blocking again */
if (fcntl(s->w.fd, F_SETFL, O_NONBLOCK)) {
- f->ret = errno;
+ sf->ret = errno;
close(s->w.fd);
s->r.fd = s->w.fd = -1;
return;
@@ -369,19 +378,20 @@ stream_sendfile_work(struct lem_async *a)
static void
stream_sendfile_reap(struct lem_async *a)
{
- struct file *f = (struct file *)a;
- struct stream *s = f->sendfile.stream;
- lua_State *T = f->a.T;
+ struct sfhandle *sf = (struct sfhandle *)a;
+ struct stream *s = sf->s;
+ lua_State *T = sf->a.T;
int ret;
- if (f->ret == 0) {
- lua_pushnumber(T, f->sendfile.size);
+ if (sf->ret == 0) {
+ lua_pushnumber(T, sf->size);
ret = 1;
} else {
- ret = io_strerror(T, f->ret);
+ ret = io_strerror(T, sf->ret);
}
- f->a.T = NULL;
+ free(sf);
+
s->w.data = NULL;
lem_queue(T, ret);
}
@@ -393,6 +403,7 @@ stream_sendfile(lua_State *T)
struct file *f;
off_t size;
off_t offset;
+ struct sfhandle *sf;
luaL_checktype(T, 1, LUA_TUSERDATA);
luaL_checktype(T, 2, LUA_TUSERDATA);
@@ -411,17 +422,15 @@ stream_sendfile(lua_State *T)
lua_pushliteral(T, "file closed");
return 2;
}
- if (f->a.T != NULL) {
- lua_pushnil(T);
- lua_pushliteral(T, "file busy");
- return 2;
- }
s->w.data = T;
- f->sendfile.stream = s;
- f->sendfile.size = size;
- f->sendfile.offset = offset;
- lem_async_do(&f->a, T, stream_sendfile_work, stream_sendfile_reap);
+
+ sf = lem_xmalloc(sizeof(struct sfhandle));
+ sf->s = s;
+ sf->size = size;
+ sf->offset = offset;
+ sf->fd = f->fd;
+ lem_async_do(&sf->a, T, stream_sendfile_work, stream_sendfile_reap);
lua_settop(T, 2);
return lua_yield(T, 2);