mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-06-16 02:15:48 +00:00
sendfile async implementation, still broken on BSD
This commit is contained in:
@@ -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
@@ -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
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user