mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-03 15:38:36 +00:00
added support for (working, high-performance) static file offloading in linux
This commit is contained in:
+1
-1
@@ -1910,7 +1910,7 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
wsgi_req->header_cnt += 2;
|
||||
|
||||
// Ok, the file must be transferred from uWSGI
|
||||
if (!wsgi_req->socket->can_offload) {
|
||||
if (wsgi_req->socket->can_offload) {
|
||||
if (!uwsgi_offload_request_do(wsgi_req, real_filename, st->st_size)) goto done;
|
||||
}
|
||||
|
||||
|
||||
+95
-1
@@ -13,6 +13,10 @@ int uwsgi_offload_request_do(struct wsgi_request *wsgi_req, char *filename, size
|
||||
// avoid closing the connection
|
||||
wsgi_req->fd_closed = 1;
|
||||
|
||||
#ifdef TCP_CORK
|
||||
// enable CORK mode (if available)
|
||||
#endif
|
||||
|
||||
// fill offload request
|
||||
struct uwsgi_offload_request uor;
|
||||
uor.fd = open(filename, O_RDONLY | O_NONBLOCK);
|
||||
@@ -24,6 +28,8 @@ int uwsgi_offload_request_do(struct wsgi_request *wsgi_req, char *filename, size
|
||||
uor.pos = 0;
|
||||
uor.len = len;
|
||||
uor.written = 0;
|
||||
uor.prev = NULL;
|
||||
uor.next = NULL;
|
||||
|
||||
if (write(uwsgi.offload_thread->pipe[0], &uor, sizeof(struct uwsgi_offload_request)) != sizeof(struct uwsgi_offload_request)) {
|
||||
goto error2;
|
||||
@@ -38,6 +44,59 @@ error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_offload_close(struct uwsgi_offload_request *uor) {
|
||||
// close the socket and the file descriptor
|
||||
close(uor->s);
|
||||
close(uor->fd);
|
||||
// remove the structure from the linked list;
|
||||
struct uwsgi_offload_request *prev = uor->prev;
|
||||
struct uwsgi_offload_request *next = uor->next;
|
||||
|
||||
if (uor == uwsgi.offload_requests_head) {
|
||||
uwsgi.offload_requests_head = next;
|
||||
}
|
||||
|
||||
if (uor == uwsgi.offload_requests_tail) {
|
||||
uwsgi.offload_requests_tail = prev;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next->prev = prev;
|
||||
}
|
||||
|
||||
free(uor);
|
||||
}
|
||||
|
||||
static void uwsgi_offload_append(struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uwsgi.offload_requests_head) {
|
||||
uwsgi.offload_requests_head = uor;
|
||||
}
|
||||
|
||||
if (uwsgi.offload_requests_tail) {
|
||||
uwsgi.offload_requests_tail->next = uor;
|
||||
uor->prev = uwsgi.offload_requests_tail;
|
||||
}
|
||||
|
||||
uwsgi.offload_requests_tail = uor;
|
||||
}
|
||||
|
||||
static struct uwsgi_offload_request *uwsgi_offload_get_by_socket(int s) {
|
||||
struct uwsgi_offload_request *uor = uwsgi.offload_requests_head;
|
||||
while(uor) {
|
||||
if (uor->s == s) {
|
||||
return uor;
|
||||
}
|
||||
uor = uor->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
int i;
|
||||
@@ -46,7 +105,42 @@ static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
|
||||
for(;;) {
|
||||
int nevents = event_queue_wait_multi(ut->queue, -1, events, uwsgi.static_offload_to_thread);
|
||||
for (i=0;i<nevents;i++) {
|
||||
//int interesting_fd = event_queue_interesting_fd(events, i);
|
||||
int interesting_fd = event_queue_interesting_fd(events, i);
|
||||
if (interesting_fd == uwsgi.offload_thread->pipe[1]) {
|
||||
struct uwsgi_offload_request *uor = uwsgi_malloc(sizeof(struct uwsgi_offload_request));
|
||||
ssize_t len = read(uwsgi.offload_thread->pipe[1], uor, sizeof(struct uwsgi_offload_request));
|
||||
if (len != sizeof(struct uwsgi_offload_request)) {
|
||||
uwsgi_error("read()");
|
||||
free(uor);
|
||||
continue;
|
||||
}
|
||||
// start monitoring socket for write
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s) < 0) {
|
||||
free(uor);
|
||||
continue;
|
||||
}
|
||||
uwsgi_offload_append(uor);
|
||||
continue;
|
||||
}
|
||||
// ok check for socket writability
|
||||
struct uwsgi_offload_request *uor = uwsgi_offload_get_by_socket(interesting_fd);
|
||||
if (!uor) continue;
|
||||
// sendfile() in chunks (128k is a good size...)
|
||||
#if defined(__linux__)
|
||||
ssize_t len = sendfile(uor->s, uor->fd, &uor->pos, 128*1024);
|
||||
if (len > 0) {
|
||||
uor->written += len;
|
||||
if (uor->written >= uor->len) {
|
||||
uwsgi_offload_close(uor);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (len < 0) {
|
||||
if (errno == EAGAIN) continue;
|
||||
uwsgi_error("sendfile()");
|
||||
}
|
||||
uwsgi_offload_close(uor);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -1751,7 +1751,8 @@ setup_proto:
|
||||
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
|
||||
uwsgi_sock->proto_sendfile = NULL;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
uwsgi_sock->can_offload = 1;
|
||||
if (uwsgi.static_offload_to_thread)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
|
||||
if (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi")) {
|
||||
@@ -1780,7 +1781,8 @@ setup_proto:
|
||||
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
|
||||
uwsgi_sock->proto_sendfile = NULL;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
uwsgi_sock->can_offload = 1;
|
||||
if (uwsgi.static_offload_to_thread)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
|
||||
@@ -2599,6 +2599,14 @@ next2:
|
||||
// set default wsgi_req (for loading apps);
|
||||
uwsgi.wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[0].req;
|
||||
|
||||
if (uwsgi.static_offload_to_thread) {
|
||||
uwsgi.offload_thread = uwsgi_offload_thread_start();
|
||||
if (!uwsgi.offload_thread) {
|
||||
uwsgi_log("unable to offload static file serving !!!\n");
|
||||
uwsgi.static_offload_to_thread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// must be run before running apps
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
|
||||
@@ -1491,6 +1491,9 @@ struct uwsgi_server {
|
||||
int check_static_docroot;
|
||||
int static_offload_to_thread;
|
||||
struct uwsgi_thread *offload_thread;
|
||||
// linked list for offloaded requests
|
||||
struct uwsgi_offload_request *offload_requests_head;
|
||||
struct uwsgi_offload_request *offload_requests_tail;
|
||||
|
||||
char *daemonize;
|
||||
char *daemonize2;
|
||||
@@ -3325,6 +3328,8 @@ struct uwsgi_offload_request {
|
||||
off_t pos;
|
||||
size_t len;
|
||||
size_t written;
|
||||
struct uwsgi_offload_request *prev;
|
||||
struct uwsgi_offload_request *next;
|
||||
};
|
||||
|
||||
struct uwsgi_thread *uwsgi_offload_thread_start(void);
|
||||
|
||||
Reference in New Issue
Block a user