diff options
author | Emil Renner Berthing <esmil@mailme.dk> | 2013-01-09 13:42:03 +0100 |
---|---|---|
committer | Emil Renner Berthing <esmil@mailme.dk> | 2013-01-09 21:50:00 +0100 |
commit | f8d493d6411d1538960ec19cb3b6aa67542c7d95 (patch) | |
tree | a96a65048abdc2887bed3d190b1eaf962464e65e | |
parent | 12c0a611cdf15bf8f86d870af5fa97881a457b0a (diff) | |
download | lem-f8d493d6411d1538960ec19cb3b6aa67542c7d95.tar.gz lem-f8d493d6411d1538960ec19cb3b6aa67542c7d95.tar.xz lem-f8d493d6411d1538960ec19cb3b6aa67542c7d95.zip |
io: allow simultaneous sendfile on the same file
-rw-r--r-- | lem/io/file.c | 5 | ||||
-rw-r--r-- | lem/io/stream.c | 79 |
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); |