sendfile async implementation, still broken on BSD

This commit is contained in:
roberto@sirius
2010-03-21 14:38:26 +01:00
parent 9852b2fa62
commit a18bc5f148
8 changed files with 167 additions and 125 deletions
+17
View File
@@ -4,6 +4,9 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
PyObject *pychunk ;
ssize_t wsize ;
#ifdef UWSGI_SENDFILE
ssize_t sf_len = 0 ;
#endif
// return or yield ?
if (PyString_Check(wsgi_req->async_result)) {
@@ -16,6 +19,20 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
goto clear;
}
if (wsgi_req->sendfile_fd != -1) {
sf_len = uwsgi_sendfile(uwsgi, wsgi_req);
if (sf_len < 1) goto clear;
wsgi_req->response_size += sf_len ;
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
if (wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
return UWSGI_AGAIN;
}
}
#endif
goto clear;
}
// ok its a yield
if (!wsgi_req->async_placeholder) {
wsgi_req->async_placeholder = PyObject_GetIter(wsgi_req->async_result);
+94
View File
@@ -0,0 +1,94 @@
#ifdef UWSGI_SENDFILE
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
if (!PyArg_ParseTuple(args, "Oi:uwsgi_sendfile", &uwsgi.wsgi_req->async_sendfile, &uwsgi.wsgi_req->sendfile_fd_chunk)) {
return NULL;
}
#ifdef PYTHREE
uwsgi.wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(uwsgi.wsgi_req->async_sendfile);
#else
if (PyFile_Check(uwsgi.wsgi_req->async_sendfile)) {
uwsgi.wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(uwsgi.wsgi_req->async_sendfile);
}
#endif
return PyTuple_New(0);
}
ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
off_t rlen;
int fd = wsgi_req->sendfile_fd ;
int sockfd = wsgi_req->poll.fd ;
struct stat stat_buf;
if (!wsgi_req->sendfile_fd_size) {
if (fstat(fd, &stat_buf)) {
perror("fstat()");
return 0;
}
else {
wsgi_req->sendfile_fd_size = stat_buf.st_size;
}
}
if (wsgi_req->sendfile_fd_size) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
if (sendfile(fd, sockfd, 0, 0, NULL, &wsgi_req->sendfile_fd_size, 0)) {
perror("sendfile()");
}
#elif __APPLE__
if (sendfile(fd, sockfd, 0, &rlen, NULL, 0)) {
perror("sendfile()");
}
#elif defined(__linux__) || defined(__sun__)
if (uwsgi->async > 1) {
return sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_chunk);
}
else {
return sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_size);
}
#else
ssize_t i = 0;
char *no_sendfile_buf[4096];
ssize_t jlen = 0;
rlen = 0;
i = 0;
while (i < rlen) {
jlen = read(fd, no_sendfile_buf, 4096);
if (jlen <= 0) {
perror("read()");
break;
}
i += jlen;
jlen = write(sockfd, no_sendfile_buf, jlen);
if (jlen <= 0) {
perror("write()");
break;
}
rlen += jlen;
}
return rlen;
#endif
}
return 0;
}
#endif
+18
View File
@@ -0,0 +1,18 @@
import sys
import mimetypes
basedir = sys.argv[1]
mimetypes.init()
def application(environ, start_response):
print environ['PATH_INFO']
filename = basedir + environ['PATH_INFO']
(content_type, encoding) = mimetypes.guess_type(filename)
if not content_type:
content_type = 'text/plain'
start_response('200 OK', [('Content-Type', content_type)])
fd = open(filename,'r')
yield environ['wsgi.file_wrapper'](fd, 32*1024)
+18 -3
View File
@@ -1,5 +1,20 @@
import sys
content_type = 'image/png'
filename = 'logo_uWSGI.png'
try:
filename = sys.argv[1]
except:
pass
try:
content_type = sys.argv[2]
except:
pass
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'image/png')])
fd = open('logo_uWSGI.png','r')
yield environ['wsgi.file_wrapper'](fd, 4096)
start_response('200 OK', [('Content-Type', content_type)])
fd = open(filename,'r')
yield environ['wsgi.file_wrapper'](fd, 32*1024)
+4 -30
View File
@@ -44,6 +44,10 @@ static const char *app_slash = "/";
extern char **environ;
#ifdef UWSGI_SENDFILE
PyMethodDef uwsgi_sendfile_method[] = {{"uwsgi_sendfile", py_uwsgi_sendfile, METH_VARARGS, ""}};
#endif
int find_worker_id(pid_t pid) {
int i;
for (i = 1; i <= uwsgi.numproc; i++) {
@@ -438,38 +442,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
return Py_None;
}
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
//PyObject *zero ;
uwsgi.py_sendfile = PyTuple_GetItem(args, 0);
#ifdef PYTHREE
if ((uwsgi.wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(uwsgi.py_sendfile)) >= 0) {
Py_INCREF(uwsgi.py_sendfile);
}
#else
if (PyFile_Check(uwsgi.py_sendfile)) {
//zero = PyFile_Name(uwsgi.py_sendfile) ;
//fprintf(stderr,"->serving %s as static file...", PyString_AsString(zero));
uwsgi.wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(uwsgi.py_sendfile);
Py_INCREF(uwsgi.py_sendfile);
}
#endif
return PyTuple_New(0);
}
#endif
PyMethodDef uwsgi_spit_method[] = { {"uwsgi_spit", py_uwsgi_spit, METH_VARARGS, ""} };
PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARGS, ""} };
#ifdef UWSGI_SENDFILE
PyMethodDef uwsgi_sendfile_method[] = { {"uwsgi_sendfile", py_uwsgi_sendfile, METH_VARARGS, ""}};
#endif
#ifdef UWSGI_ASYNC
PyMethodDef uwsgi_eventfd_read_method[] = { {"uwsgi_eventfd_read", py_eventfd_read, METH_VARARGS, ""}};
PyMethodDef uwsgi_eventfd_write_method[] = { {"uwsgi_eventfd_write", py_eventfd_write, METH_VARARGS, ""}};
@@ -1670,7 +1645,6 @@ int main(int argc, char *argv[], char *envp[]) {
if (uwsgi.async > 1) {
current_async_timeout = async_get_timeout(&uwsgi) ;
fprintf(stderr,"sleeping for %d secs\n", current_async_timeout);
uwsgi.async_nevents = async_wait(uwsgi.async_queue, uwsgi.async_events, uwsgi.async, uwsgi.async_running, current_async_timeout);
async_expire_timeouts(&uwsgi);
+10 -2
View File
@@ -274,12 +274,15 @@ struct __attribute__ ((packed)) wsgi_request {
#endif
int sendfile_fd;
size_t sendfile_fd_chunk;
size_t sendfile_fd_size;
off_t sendfile_fd_pos;
uint16_t var_cnt;
uint16_t header_cnt;
int status;
int response_size;
size_t response_size;
int headers_size;
int async_id;
@@ -297,6 +300,7 @@ struct __attribute__ ((packed)) wsgi_request {
void *async_placeholder;
void *async_environ;
void *async_post;
void *async_sendfile;
// buffer MUST BE THE LAST VAR !!!
char buffer;
@@ -417,7 +421,6 @@ struct uwsgi_server {
int single_interpreter;
int py_optimize;
PyObject *py_sendfile;
PyObject *embedded_dict;
PyObject *embedded_args;
PyObject *fastfuncslist;
@@ -669,3 +672,8 @@ void async_expire_timeouts(struct uwsgi_server *);
int manage_python_response(struct uwsgi_server *, struct wsgi_request *);
int uwsgi_python_call(struct uwsgi_server *, struct wsgi_request *, PyObject *, PyObject *);
PyObject *python_call(PyObject *, PyObject *);
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *) ;
ssize_t uwsgi_sendfile(struct uwsgi_server *, struct wsgi_request *);
#endif
+1
View File
@@ -142,6 +142,7 @@ def parse_vars():
if SENDFILE:
cflags.append("-DUWSGI_SENDFILE")
gcc_list.append('sendfile')
if XML:
xmlconf = spcall('xml2-config --libs')
+5 -90
View File
@@ -1,7 +1,5 @@
#include "uwsgi.h"
static int uwsgi_sendfile(struct uwsgi_server *, int, int);
int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
int i;
@@ -219,34 +217,14 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
if (wsgi_req->async_result) {
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd > -1) {
wsgi_req->response_size = uwsgi_sendfile(uwsgi, wsgi_req->sendfile_fd, wsgi_req->poll.fd);
if (wsgi_req->async_environ) {
PyDict_Clear(wsgi_req->async_environ);
}
if (wsgi_req->async_post) {
fclose(wsgi_req->async_post);
}
Py_DECREF(wsgi_req->async_result);
}
else {
#endif
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
//fprintf(stderr,"WSGI CYCLE\n");
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
#ifdef UWSGI_ASYNC
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#endif
if (uwsgi->async > 1) {
return UWSGI_AGAIN;
}
#ifdef UWSGI_SENDFILE
}
#endif
}
}
@@ -268,66 +246,3 @@ void uwsgi_after_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *w
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
#ifdef UWSGI_SENDFILE
static int uwsgi_sendfile(struct uwsgi_server *uwsgi, int fd, int sockfd) {
off_t rlen;
#ifdef __sun__
struct stat stat_buf;
if (fstat(fd, &stat_buf)) {
perror("fstat()");
return 0;
}
else {
rlen = stat_buf.st_size;
}
#else
rlen = lseek(fd, 0, SEEK_END);
#endif
if (rlen > 0) {
lseek(fd, 0, SEEK_SET);
#if !defined(__linux__) && !defined(__sun__)
#if defined(__FreeBSD__) || defined(__DragonFly__)
if (sendfile(fd, sockfd, 0, 0, NULL, &rlen, 0)) {
perror("sendfile()");
}
#elif __APPLE__
if (sendfile(fd, sockfd, 0, &rlen, NULL, 0)) {
perror("sendfile()");
}
#else
ssize_t i = 0;
char *no_sendfile_buf[4096];
ssize_t jlen = 0;
rlen = 0;
i = 0;
while (i < rlen) {
jlen = read(fd, no_sendfile_buf, 4096);
if (jlen <= 0) {
perror("read()");
break;
}
i += jlen;
jlen = write(sockfd, no_sendfile_buf, jlen);
if (jlen <= 0) {
perror("write()");
break;
}
rlen += jlen;
}
#endif
#else
off_t sf_ot = 0;
rlen = sendfile(sockfd, fd, &sf_ot, rlen);
#endif
}
Py_DECREF(uwsgi->py_sendfile);
return rlen;
}
#endif