Skip to content
This repository has been archived by the owner on Sep 13, 2024. It is now read-only.

Commit

Permalink
uGreen fd async waiting support
Browse files Browse the repository at this point in the history
  • Loading branch information
roberto@sirius committed Mar 31, 2010
1 parent 474860c commit bdab4dc
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 11 deletions.
22 changes: 16 additions & 6 deletions async.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,12 +279,22 @@ struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *uwsgi, int fd, int
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;

for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd && wsgi_req->async_waiting_fd_type == etype) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
if (etype != -1) {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd && wsgi_req->async_waiting_fd_type == etype) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}
else {
for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_waiting_fd == fd) {
return wsgi_req ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
}
}

return NULL ;

Expand Down
41 changes: 41 additions & 0 deletions tests/iobound_green.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import uwsgi
import socket
import errno

def send_request(env, client):

client.setblocking(1)

client.send(b"GET /intl/it_it/images/logo.gif HTTP/1.0\r\n")
client.send(b"Host: www.google.it\r\n\r\n")

uwsgi.green_schedule()

while 1:
uwsgi.green_wait_fdread(client.fileno(), 10)
buf = client.recv(4096)
if len(buf) == 0:
break
else:
yield buf


def application(env, start_response):

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)

c = s.connect_ex(('74.125.77.104', 80))
if c == errno.EINPROGRESS:
uwsgi.green_wait_fdwrite(s.fileno(), 10)
for r in send_request(env, s):
yield r
elif c == errno.EISCONN:
for r in send_request(env, s):
yield r
else:
uwsgi.green_schedule()
start_response( '500 Internal Server Error', [ ('Content-Type', 'text/html')])
yield "Internal Server Error"

s.close()
71 changes: 66 additions & 5 deletions ugreen.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,22 @@
TODO
io and sleep management
io, timeout and sleep management
*/

#include "uwsgi.h"

#define UGREEN_DEFAULT_STACKSIZE 128*1024
#define UGREEN_DEFAULT_STACKSIZE 256*1024

extern struct uwsgi_server uwsgi;


static int u_green_blocking(struct uwsgi_server *uwsgi) {
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests ;
int i ;

for(i=0;i<uwsgi->async;i++) {
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (wsgi_req->async_status != UWSGI_ACCEPTING && wsgi_req->async_waiting_fd == -1) {
return 0 ;
}
wsgi_req = next_wsgi_req(uwsgi, wsgi_req) ;
Expand Down Expand Up @@ -65,6 +64,25 @@ inline static void u_green_schedule_to_req(struct uwsgi_server *uwsgi, struct ws
tstate->frame = py_current_frame ;
}

static void u_green_wait_for_fd(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, int fd, int etype, int timeout) {

if (fd < 0) return;

if (async_add(uwsgi->async_queue, fd, etype)) return ;

wsgi_req->async_waiting_fd = fd ;
wsgi_req->async_waiting_fd_type = etype;
wsgi_req->async_timeout = timeout ;

u_green_schedule_to_main(uwsgi, wsgi_req->async_id);

async_del(uwsgi->async_queue, wsgi_req->async_waiting_fd, wsgi_req->async_waiting_fd_type);

wsgi_req->async_waiting_fd = -1;
wsgi_req->async_timeout = 0 ;
}


PyObject *py_uwsgi_green_schedule(PyObject * self, PyObject * args) {

struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
Expand All @@ -76,8 +94,42 @@ PyObject *py_uwsgi_green_schedule(PyObject * self, PyObject * args) {

}

PyObject *py_uwsgi_green_wait_fdread(PyObject * self, PyObject * args) {

struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
int fd,timeout;

if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}

u_green_wait_for_fd(&uwsgi, wsgi_req, fd, ASYNC_IN, timeout);

Py_INCREF(Py_True);
return Py_True;
}

PyObject *py_uwsgi_green_wait_fdwrite(PyObject * self, PyObject * args) {

struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
int fd,timeout;

if (!PyArg_ParseTuple(args, "i|i", &fd, &timeout)) {
return NULL;
}

u_green_wait_for_fd(&uwsgi, wsgi_req, fd, ASYNC_OUT, timeout);

Py_INCREF(Py_True);
return Py_True;
}



PyMethodDef uwsgi_green_methods[] = {
{"green_schedule", py_uwsgi_green_schedule, METH_VARARGS, ""},
{"green_wait_fdread", py_uwsgi_green_wait_fdread, METH_VARARGS, ""},
{"green_wait_fdwrite", py_uwsgi_green_wait_fdwrite, METH_VARARGS, ""},
{ NULL, NULL }
};

Expand Down Expand Up @@ -218,12 +270,21 @@ void u_green_loop(struct uwsgi_server *uwsgi) {
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
else {
wsgi_req = find_wsgi_req_by_fd(uwsgi, uwsgi->async_events[i].ASYNC_FD, -1);
if (wsgi_req) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
else {
async_del(uwsgi->async_queue, uwsgi->async_events[i].ASYNC_FD, uwsgi->async_events[i].ASYNC_EV);
}
}

}

cycle:
wsgi_req = find_wsgi_req_by_id(uwsgi, current) ;
if (wsgi_req->async_status != UWSGI_ACCEPTING) {
if (wsgi_req->async_status != UWSGI_ACCEPTING && wsgi_req->async_waiting_fd == -1) {
u_green_schedule_to_req(uwsgi, wsgi_req);
}
current++;
Expand Down
33 changes: 33 additions & 0 deletions uwsgiconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
UGREEN=True
STACKLESS=False
PLUGINS = []
UNBIT=False
UWSGI_BIN_NAME = 'uwsgi'
GCC='gcc'

Expand Down Expand Up @@ -101,6 +102,31 @@ def build_uwsgi(bin_name):
bin_name = './' + bin_name
print("*** uWSGI is ready, launch it with %s ***" % bin_name)

def unbit_setup():
global XML, SNMP, SCTP, ERLANG, SPOOLER
global EMBEDDED, UDP, MULTICAST, THREADING
global SENDFILE, PROFILER, NAGIOS, PROXY

global UWSGI_BIN_NAME

XML=False
SNMP=False
SCTP=False
ERLANG=False
UDP=False
MULTICAST=False
NAGIOS=False
PROXY=False

EMBEDDED=True
SPOOLER=True
THREADING=True
SENDFILE=True
PROFILER=True

UNBIT=True
UWSGI_BIN_NAME='/usr/share/unbit/uwsgi26'


def parse_vars():

Expand Down Expand Up @@ -211,6 +237,9 @@ def parse_vars():
cflags.append("-DUWSGI_SPOOLER")
gcc_list.append('spooler')

if UNBIT:
cflags.append("-DUWSGI_UNBIT")

def build_plugin(path):
path = path.rstrip('/')

Expand Down Expand Up @@ -255,6 +284,10 @@ def build_plugin(path):
elif cmd == '--build':
parse_vars()
build_uwsgi(UWSGI_BIN_NAME)
elif cmd == '--unbit':
unbit_setup()
parse_vars()
build_uwsgi(UWSGI_BIN_NAME)
elif cmd == '--plugin':
parse_vars()
build_plugin(sys.argv[2])
Expand Down

0 comments on commit bdab4dc

Please sign in to comment.