Compare commits

...
93 Commits
Author SHA1 Message Date
Unbit 7108ee1ba0 improved xclient 2013-06-22 11:50:45 +02:00
Unbit cf8e68f7a0 another attempt to fix xclient 2013-06-22 11:18:25 +02:00
Unbit a9510c2209 fixed xclient 2013-06-22 10:51:17 +02:00
Unbit b2be5943a8 added router_xmldir plugin 2013-06-21 06:54:05 +02:00
Unbit 8f19fe292e added --add-cache-item 2013-06-20 15:12:48 +02:00
Unbit d3e7668d0a better clang detection 2013-06-20 11:00:05 +02:00
Unbit 88e67a74e5 fixed #321 2013-06-20 08:59:18 +02:00
Roberta Giordano 7fecda1a23 fixed #324 2013-06-20 06:15:35 +02:00
unbit 56b6fa88f9 Merge pull request #323 from jbert/master
Fix infinite loop in psgi/coroae
2013-06-19 07:47:52 -07:00
John Berthels e847cfe4bc fix infinite loop in coroae/psgi
Perl PSGI app infinite loops since f20213ff10

Looking at that change, other loop termination conditions are '<= UWSGI_OK'.
Using gdb to inspect the app while looping shows thats ->request is returning
UWSGI_OK in this case. However, the numeric value of this is zero, so we
never exit the for(;;) loop.

Cargo culting loop escape conditions from core/async.c (or gevent/gevent.c)
fixes the inf loop for psgi/coroae.
2013-06-19 15:27:31 +01:00
Roberta Giordano 1a854ae3ba varios osx build workaround 2013-06-19 07:14:54 +02:00
unbit c75180bf95 Create logo_uWSGI.svg 2013-06-17 10:26:59 +02:00
Unbit d496450b84 added seturi and setpathinfo routing actions 2013-06-16 07:52:59 +02:00
Unbit d2636ed133 better compiler detection 2013-06-16 07:13:19 +02:00
unbit 59de0c2085 Merge pull request #317 from anaconda/fix-gcc-darwin-llvm
Fix GCC on Darwin for Python 3.
2013-06-15 22:11:11 -07:00
anaconda 4b7df29bd1 Fix GCC on Darwin for Python 3.
distutils.sysconfig.get_config_var('CC') returns the compiler used to
build Python, which may be not installed on the system where uWSGI is
being built.

In my case, I grabbed Python 3.3.2 from python.org: it was apparently
compiled with 'gcc-4.2', but my system only has 'gcc' (symlink) and
'llvm-gcc-4.2'.  This change tries to detect this situation (only on
Darwin) and sets GCC to 'llvm-' + compiler returned by sysconfig.
2013-06-16 01:59:48 +02:00
unbit b099ba6a29 Merge pull request #316 from anaconda/spool-decorator-call
Implement __call__ for @spool* decorators.
2013-06-15 07:09:51 -07:00
anaconda 164069e194 Implement __call__ for @spool* decorators.
Also removed duplicate code.
2013-06-15 15:05:39 +02:00
Unbit b3e4ff8613 cosmetic fix for fastcgi 2013-06-15 14:37:50 +02:00
Unbit 3eb5ec3543 better fastcgi handling 2013-06-15 14:36:18 +02:00
unbit c3c698a615 Update uwsgi.conf 2013-06-15 15:09:22 +03:00
Unbit ac6d2f3e83 rack api functions are now static 2013-06-15 11:55:48 +02:00
Unbit d1f1b8a43a another tests cleanup 2013-06-15 08:03:34 +02:00
Unbit 85586a621c the official API list is now in uwsgi-docs 2013-06-15 08:01:53 +02:00
Unbit 1a384a334f remove mercurial files 2013-06-15 08:00:16 +02:00
Unbit 8901afded5 moved lanunchd examples to contrib 2013-06-15 07:59:27 +02:00
Roberta Giordano ab12703a11 added new set_user_harakiri to python,pypy,perl and ruby 2013-06-15 07:04:53 +02:00
Roberta Giordano 9992b4c964 improved set_user_harakiri to support mules and spoolers 2013-06-15 06:50:10 +02:00
unbit 9a2dbd08cd Merge pull request #315 from prymitive/curl_bug
fix curl crashing master on slow dns responses
2013-06-14 06:48:03 -07:00
Łukasz Mierzwa 5f92a00b71 fix curl crashing master on slow dns responses 2013-06-14 09:24:00 +02:00
Unbit 7bd9d51217 added mule support to pypy 2013-06-12 16:39:10 +02:00
unbit 80c649aa40 Create emperor.conf 2013-06-11 13:47:34 +03:00
Unbit 6c8fe2cc53 improved ready_fd call 2013-06-10 23:01:19 +02:00
Unbit dcc7167d75 added uwsgi[lq] routing var 2013-06-10 02:48:52 +02:00
Unbit e3a52e4039 added --use-abort 2013-06-09 23:14:52 +02:00
Unbit 498f6162f7 fixed debug 2013-06-09 23:00:22 +02:00
Unbit 33d85d3670 added coroae build profile 2013-06-09 22:58:18 +02:00
Unbit afbf5b9633 fixed typo doc 2013-06-09 22:54:42 +02:00
Unbit a8505be6c0 standardized uwsgi.disconnect() 2013-06-09 22:47:44 +02:00
Unbit 4a07632569 uwsgi.add_cron does not return a value 2013-06-09 22:35:52 +02:00
Unbit d4f0589c39 fixed uwsgi.fd_ready() 2013-06-09 22:22:59 +02:00
Roberta Giordano a9989d46fc set default lock to 0 in pypy uwsgi.lock/uwsgi.unlock 2013-06-10 06:08:15 +02:00
Unbit 99cf598c0c added chunked input support to pypy 2013-06-09 08:47:50 +02:00
Unbit a6af22b8f0 ported websockets api to pypy 2013-06-09 08:35:12 +02:00
Unbit 0961d61a88 added chunked async support 2013-06-09 08:06:45 +02:00
Unbit 7b76a2d749 first test for chunked input 2013-06-09 03:25:46 +02:00
Unbit b516f1d3ec added --chunked-input-limit and --chunked-input-timeout 2013-06-09 03:06:12 +02:00
Unbit 8fdef7a1f9 added chunked input api 2013-06-09 03:02:16 +02:00
Unbit 10258db4ae removed python 3 need for 'imp' module 2013-06-08 23:36:49 +02:00
unbit 621c9523cf fixed python3 compilation and added UWSGI_INCLUDES 2013-06-09 07:01:34 +02:00
Unbit c415adab28 added setmethod routing action 2013-06-08 01:05:44 +02:00
Unbit 7fef1048b3 added pypy greenlet contrib module 2013-06-07 10:15:25 +02:00
Unbit 1e7aaeeeed fix harakiri routing 2013-06-07 09:11:54 +02:00
Unbit c5b4564001 added 2 example of continulets 2013-06-06 18:16:01 +02:00
Unbit a9127c8d79 added support for pypy uwsgi.async_sleep 2013-06-06 17:25:03 +02:00
Unbit a0f7a5c70f added support for pypy continulets 2013-06-06 17:17:51 +02:00
Unbit ecf3cae35b use ffi.string instead of ffi.buffer in pypy 2013-06-06 16:05:20 +02:00
Unbit d553bc8014 let's start with 1.9.13 2013-06-06 15:49:51 +02:00
Unbit a1553d3632 removed debug print from pypy_setup.py 2013-06-06 14:54:39 +02:00
Unbit bb42ae1b4a fixed cron and alarm in pypy_setup.py 2013-06-06 14:16:38 +02:00
Unbit 61ac2efe0e added user_lock/unlock to new pypy setup 2013-06-06 14:15:02 +02:00
Unbit 1c0a3ec413 refactored the pypy plugin to make best use of cffi and to avoid the need of helpers 2013-06-06 14:10:34 +02:00
Unbit 8b7e93385b missing newline in --cflags 2013-06-06 11:27:14 +02:00
Unbit c742624054 added uwsgi_get_cflags() 2013-06-06 11:25:17 +02:00
Unbit 8011f0615d added --dot-h infrastructure 2013-06-06 11:18:25 +02:00
Unbit 8096b2198f fixed --print-sym and embed uwsgi.h in the server binary 2013-06-06 10:06:40 +02:00
Unbit 3556bd5283 removed PTRACE check, was an old stupid attempt 2013-06-06 09:42:08 +02:00
Unbit 26710694af fixed #306 2013-06-05 15:19:21 +02:00
Unbit 0f397eeb55 fixed #305 2013-06-05 11:14:47 +02:00
Unbit bf929398a9 updated gemspec for 1.9.12 2013-06-05 09:19:57 +02:00
Unbit 4f8a0f753e added router_hash and extended support for memcached and redis 2013-06-05 06:26:39 +02:00
Unbit 7db5da9566 fixed support for newer cygwin 2013-06-04 17:13:18 +02:00
Unbit 4d1389805c added redis router code 2013-06-04 13:20:47 +02:00
Unbit ee87e2b946 memcached and redis routers are now builtin by default 2013-06-04 13:07:51 +02:00
Unbit 6356d78768 completed memcachedstore 2013-06-04 12:04:42 +02:00
Unbit afdf7e740e prepare for memcachedstore 2013-06-04 11:40:19 +02:00
Unbit 51ce3ddf78 added offloading to memcached internal router 2013-06-04 11:18:02 +02:00
Unbit 192186056e added pipe offload engine 2013-06-04 10:34:19 +02:00
Unbit 336a7febd7 prepate for 1.9.12 2013-06-03 15:35:17 +02:00
Unbit 63e73d1b73 added --touch-signal 2013-06-03 11:15:39 +02:00
Unbit a02ab9a723 automatically search for 'application' method in jwsgi 2013-06-03 06:33:48 +02:00
Unbit 95f15ab9dd added a note for python logger 2013-06-02 19:20:35 +02:00
Unbit 5d0ea0066a fixed fastcgi body read 2013-06-02 12:52:13 +02:00
Unbit 9ff6b2da9b improved tmp file generation and first implementation of offload transformation 2013-06-02 11:12:28 +02:00
Roberta Giordano 6ac7e27847 added seek() support to jvm input 2013-06-01 19:53:29 +02:00
Roberta Giordano 4ed1c5e747 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-06-01 19:42:29 +02:00
Roberta Giordano bae3bc096f added readLine featute to jvm input 2013-06-01 19:42:11 +02:00
unbit 9d73683de2 Merge pull request #298 from prymitive/csfix
try to escape json
2013-06-01 08:15:19 -07:00
Roberta Giordano f5fec0ab71 added support for jvm list and uwsgi.opt 2013-06-01 16:32:39 +02:00
Łukasz Mierzwa 9909ab10c4 try to escape json 2013-06-01 15:53:35 +02:00
Roberta Giordano 65cff01fee implemented non-static JWSGI apps 2013-06-01 12:20:19 +02:00
unbit 10190a3012 Merge pull request #301 from jimfunk/master
Fix signed/unsigned comparison in emperor_amqp plugin
2013-05-31 21:56:23 -07:00
James Oakley 79ab696f4e Fix signed/unsigned comparison 2013-05-31 13:24:49 -07:00
70 changed files with 2963 additions and 444 deletions
-4
View File
@@ -1,4 +0,0 @@
syntax: glob
*.o
*.pyc
-58
View File
@@ -1,58 +0,0 @@
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
3c70927335856883283fe4db448e092cecc0ccdb 1.0
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
+1 -1
View File
@@ -16,7 +16,7 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash
as_shared_library = false
locking = auto
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = psgi,coroae
inherit = base
+1
View File
@@ -1,3 +1,4 @@
[uwsgi]
main_plugin = python,gevent
inherit = base
debug = false
+61
View File
@@ -0,0 +1,61 @@
"""
Greenlets support
simply --pypy-exec this file to enable PyPy's greenlet mode
Example:
uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi werkzeug.testapp:test_app --pypy-exec contrib/pypy/uwsgi_pypy_greenlets.py --async 8
"""
import greenlet
uwsgi_pypy_greenlets = {}
def uwsgi_pypy_greenlet_wrapper():
lib.async_schedule_to_req_green()
@ffi.callback("void()")
def uwsgi_pypy_greenlet_schedule():
id = lib.uwsgi.wsgi_req.async_id
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
# generate a new greenlet
if not lib.uwsgi.wsgi_req.suspended:
uwsgi_pypy_greenlets[id] = greenlet.greenlet(uwsgi_pypy_greenlet_wrapper)
lib.uwsgi.wsgi_req.suspended = 1
# this is called in the main stack
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
# let's switch
uwsgi_pypy_greenlets[id].switch()
# back to the main stack
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(ffi.NULL)
@ffi.callback("void(struct wsgi_request *)")
def uwsgi_pypy_greenlet_switch(wsgi_req):
id = wsgi_req.async_id
modifier1 = wsgi_req.uh.modifier1;
# this is called in the current greenlet
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(wsgi_req)
uwsgi_pypy_main_greenlet.switch()
# back to the greenlet
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(wsgi_req)
# update current running greenlet
lib.uwsgi.wsgi_req = wsgi_req
if lib.uwsgi.async <= 1:
raise Exception("pypy greenlets require async mode !!!")
lib.uwsgi.schedule_to_main = uwsgi_pypy_greenlet_switch
lib.uwsgi.schedule_to_req = uwsgi_pypy_greenlet_schedule
uwsgi_pypy_main_greenlet = greenlet.getcurrent()
+15
View File
@@ -0,0 +1,15 @@
# uWSGI - Emperor
#
description "uWSGI Emperor"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
env VASSALS=/etc/uwsgi
exec $BINPATH --emperor $VASSALS --logto $LOGTO
+2 -3
View File
@@ -11,7 +11,6 @@ respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --no-orphans avoid workers without master
# --die-on-term could be a good idea
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
# --die-on-term is upstart friendly
exec $BINPATH --die-on-term --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
+9
View File
@@ -206,7 +206,11 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
}
static int async_wait_fd_read(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_read(wsgi_req, fd, timeout)) {
return -1;
}
@@ -222,6 +226,8 @@ static int async_wait_fd_read(int fd, int timeout) {
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
wsgi_req->async_ready_fd = 0;
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now() + timeout, wsgi_req);
}
@@ -265,6 +271,9 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
static int async_wait_fd_write(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_write(wsgi_req, fd, timeout)) {
return -1;
}
+37
View File
@@ -171,6 +171,41 @@ static void cache_sync_hook(char *k, uint16_t kl, char *v, uint16_t vl, void *da
}
}
static void uwsgi_cache_add_items(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uwsgi.add_cache_item;
while(usl) {
char *space = strchr(usl->value, ' ');
char *key = usl->value;
uint16_t key_len = usl->len;
if (space) {
// need to skip ?
if (uwsgi_strncmp(uc->name, uc->name_len, usl->value, space-usl->value)) {
goto next;
}
key = space+1;
key_len = usl->len - ((space-usl->value)+1);
}
char *value = strchr(key, '=');
if (!value) {
uwsgi_log("[cache] unable to store item %s\n", usl->value);
goto next;
}
key_len = value - key;
value++;
uint64_t len = (usl->value + usl->len) - value;
uwsgi_wlock(uc->lock);
if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) {
uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
else {
uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name);
}
uwsgi_rwunlock(uc->lock);
next:
usl = usl->next;
}
}
static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
struct uwsgi_string_list *usl = uwsgi.load_file_in_cache;
@@ -341,6 +376,8 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
uwsgi_cache_load_files(uc);
uwsgi_cache_add_items(uc);
}
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
+159
View File
@@ -0,0 +1,159 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
Chunked input implementation
--chunked-input-limit <bytes> (default 1MB)
--chunked-input-timeout <s> (default --socket-timeout)
chunk = uwsgi.chunked_read([timeout])
timeout = -1 (wait forever)
timeout = 0 (default)
*/
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
if (timeout == 0) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
int ret = -1;
for(;;) {
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
if (rlen > 0) return rlen;
if (rlen == 0) return -1;
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
if (nb) return -1;
goto wait;
}
uwsgi_error("uwsgi_chunked_input_recv()");
return -1;
}
wait:
ret = uwsgi.wait_read_hook(wsgi_req->fd, timeout);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
if (rlen > 0) return rlen;
if (rlen <= 0) return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_chunked_input_recv()");
}
return -1;
}
return -1;
}
static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
size_t i;
int found = 0;
for(i=0;i<wsgi_req->chunked_input_buf->pos;i++) {
if (found) {
if (wsgi_req->chunked_input_buf->buf[i] == '\n') {
// strtoul will stop at \r
size_t num = strtoul(wsgi_req->chunked_input_buf->buf, NULL, 16);
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, i+1)) return -1;
return num;
}
return -1;
}
if ((wsgi_req->chunked_input_buf->buf[i] >= '0' && wsgi_req->chunked_input_buf->buf[i] <= '9') ||
(wsgi_req->chunked_input_buf->buf[i] >= 'a' && wsgi_req->chunked_input_buf->buf[i] <= 'z') ||
(wsgi_req->chunked_input_buf->buf[i] >= 'A' && wsgi_req->chunked_input_buf->buf[i] <= 'Z')) continue;
if (wsgi_req->chunked_input_buf->buf[i] == '\r') { found = 1; continue; }
return -1;
}
return -2;
}
/*
0 -> waiting for \r\n
1 -> waiting for whole body
*/
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
char *ret;
if (!wsgi_req->chunked_input_buf) {
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
}
// the whole chunk stream has been consumed
if (wsgi_req->chunked_input_complete) {
*len = 0;
return wsgi_req->chunked_input_buf->buf;
}
for(;;) {
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
if (uwsgi_buffer_fix(wsgi_req->chunked_input_buf, uwsgi.page_size)) return NULL;
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
if (rlen <= 0) return NULL;
// update buffer position
wsgi_req->chunked_input_buf->pos += rlen;
if (wsgi_req->chunked_input_need > 0) {
if ((size_t)rlen > wsgi_req->chunked_input_need) {
wsgi_req->chunked_input_need = 0;
}
else {
wsgi_req->chunked_input_need -= rlen;
}
}
}
if (wsgi_req->chunked_input_need > 0) continue;
// ok we have a frame, let's parse it
if (wsgi_req->chunked_input_buf->pos > 0) {
switch(wsgi_req->chunked_input_parser_status) {
case 0:
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
if (wsgi_req->chunked_input_chunk_len == -2) {
break;
}
else if (wsgi_req->chunked_input_chunk_len < 0) {
return NULL;
}
else if (wsgi_req->chunked_input_chunk_len == 0) {
*len = 0;
wsgi_req->chunked_input_complete = 1;
return wsgi_req->chunked_input_buf->buf;
}
// if here the buffer has been already decapitated
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
wsgi_req->chunked_input_parser_status = 1;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
ret = wsgi_req->chunked_input_buf->buf;
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
return ret;
case 1:
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
ret = wsgi_req->chunked_input_buf->buf;
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
wsgi_req->chunked_input_parser_status = 0;
return ret;
}
}
}
}
+1
View File
@@ -0,0 +1 @@
int main() {}
+3
View File
@@ -169,6 +169,9 @@ void uwsgi_init_default() {
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
uwsgi_websockets_init();
// 1 MB default limit
uwsgi.chunked_input_limit = 1024*1024;
}
void uwsgi_setup_reload() {
+19
View File
@@ -1078,3 +1078,22 @@ void uwsgi_add_safe_fd(int fd) {
uwsgi.safe_fds[uwsgi.safe_fds_cnt] = fd;
uwsgi.safe_fds_cnt++;
}
int uwsgi_is_again() {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
return 1;
}
return 0;
}
void uwsgi_disconnect(struct wsgi_request *wsgi_req) {
if (wsgi_req->socket) {
wsgi_req->socket->proto_close(wsgi_req);
}
wsgi_req->fd_closed = 1;
}
int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
return -1;
}
+18
View File
@@ -485,6 +485,18 @@ int master_loop(char **argv, char **environ) {
usl = usl->next;
}
uwsgi_check_touches(uwsgi.touch_exec);
// update signal touches
usl = uwsgi.touch_signal;
while(usl) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
usl->len = strlen(usl->value);
usl->custom_ptr = space + 1;
}
usl = usl->next;
}
uwsgi_check_touches(uwsgi.touch_signal);
// setup cheaper algos (can be stacked)
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
@@ -769,6 +781,12 @@ int master_loop(char **argv, char **environ) {
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
}
}
touched = uwsgi_check_touches(uwsgi.touch_signal);
if (touched) {
uint8_t signum = atoi(touched);
uwsgi_route_signal(signum);
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
}
}
continue;
+13
View File
@@ -197,6 +197,14 @@ void uwsgi_master_check_mules_deadline() {
uwsgi.mules[i].harakiri = 0;
}
}
// user harakiri
if (uwsgi.mules[i].user_harakiri > 0) {
if (uwsgi.mules[i].user_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
kill(uwsgi.mules[i].pid, SIGKILL);
uwsgi.mules[i].user_harakiri = 0;
}
}
}
}
@@ -208,6 +216,11 @@ void uwsgi_master_check_spoolers_deadline() {
kill(uspool->pid, SIGKILL);
uspool->harakiri = 0;
}
if (uspool->user_harakiri > 0 && uspool->user_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
kill(uspool->pid, SIGKILL);
uspool->user_harakiri = 0;
}
uspool = uspool->next;
}
}
+16 -2
View File
@@ -696,8 +696,17 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
while (ud) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
// allocate 2x the size of original command
// in case we need to escape all chars
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
escape_json(ud->command, strlen(ud->command), cmd);
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
free(cmd);
goto end;
}
free(cmd);
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) (ud->pid < 0) ? 0 : ud->pid))
goto end;
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
@@ -1106,8 +1115,13 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
goto end;
if (uwsgi_stats_keyval_comma(us, "command", ucron->command))
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
escape_json(ucron->command, strlen(ucron->command), cmd);
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
free(cmd);
goto end;
}
free(cmd);
if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique))
goto end;
+92 -2
View File
@@ -58,6 +58,22 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
return 0;
}
/*
pipe offload engine:
fd -> the file descriptor to read from
len -> amount of data to transfer
*/
static int u_offload_pipe_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (uor->fd < 0 || !uor->len) {
return -1;
}
return 0;
}
/*
memory offload engine:
@@ -66,7 +82,7 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
*/
int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
static int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->buf || !uor->len) {
return -1;
@@ -83,7 +99,7 @@ int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload
*/
int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
static int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->name) {
return -1;
@@ -343,6 +359,71 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
}
/*
pipe offloading
status:
0 -> waiting for data on fd
1 -> waiting for write to s
*/
static int u_offload_pipe_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
ssize_t rlen;
// setup
if (fd == -1) {
event_queue_add_fd_read(ut->queue, uor->fd);
return 0;
}
switch(uor->status) {
// read event from fd
case 0:
if (!uor->buf) {
uor->buf = uwsgi_malloc(4096);
}
rlen = read(uor->fd, uor->buf, 4096);
if (rlen > 0) {
uor->to_write = rlen;
uor->pos = 0;
if (event_queue_del_fd(ut->queue, uor->fd, event_queue_read())) return -1;
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
uor->status = 1;
return 0;
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_pipe_do() -> read()");
}
return -1;
// write event on s
case 1:
rlen = write(uor->s, uor->buf + uor->pos, uor->to_write);
if (rlen > 0) {
uor->to_write -= rlen;
uor->pos += rlen;
if (uor->to_write == 0) {
if (event_queue_del_fd(ut->queue, uor->s, event_queue_write())) return -1;
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
uor->status = 0;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_pipe_do() -> write()");
}
return -1;
default:
break;
}
return -1;
}
/*
the offload task starts soon after the call to connect()
@@ -541,6 +622,7 @@ void uwsgi_offload_engines_register_all() {
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do);
uwsgi.offload_engine_pipe = uwsgi_offload_register_engine("pipe", u_offload_pipe_prepare, u_offload_pipe_do);
}
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
@@ -566,3 +648,11 @@ int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, si
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_pipe_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_pipe, &uor, wsgi_req, 1);
uor.fd = fd;
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
+2 -2
View File
@@ -478,9 +478,9 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
int upload_progress_fd = -1;
char *upload_progress_filename = NULL;
wsgi_req->post_file = tmpfile();
wsgi_req->post_file = uwsgi_tmpfile();
if (!wsgi_req->post_file) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/tmpfile()");
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
return -1;
}
+80 -1
View File
@@ -564,7 +564,7 @@ static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsg
if (route->custom > 0) {
set_user_harakiri(route->custom);
}
return UWSGI_ROUTE_CONTINUE;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_harakiri(struct uwsgi_route *ur, char *arg) {
@@ -889,6 +889,77 @@ static int uwsgi_router_setscriptname(struct uwsgi_route *ur, char *arg) {
return 0;
}
// setmethod route
static int uwsgi_router_setmethod_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "REQUEST_METHOD", 14, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->method = ptr;
wsgi_req->method_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setmethod(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setmethod_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// seturi route
static int uwsgi_router_seturi_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "REQUEST_URI", 11, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->uri = ptr;
wsgi_req->uri_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_seturi_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setpathinfo route
static int uwsgi_router_setpathinfo_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->path_info = ptr;
wsgi_req->path_info_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setpathinfo_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setuser route
static int uwsgi_router_setuser_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -1389,6 +1460,11 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
*vallen = strlen(ret);
}
else if (!uwsgi_strncmp(key, keylen, "lq", 2)) {
ret = uwsgi_num2str(uwsgi.shared->load);
*vallen = strlen(ret);
}
return ret;
}
@@ -1514,6 +1590,9 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("sethome", uwsgi_router_sethome);
uwsgi_register_router("setfile", uwsgi_router_setfile);
uwsgi_register_router("setscriptname", uwsgi_router_setscriptname);
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
uwsgi_register_router("seturi", uwsgi_router_seturi);
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
+36
View File
@@ -37,3 +37,39 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
#endif
}
/*
simple non blocking sendfile implementation
(generally used as fallback)
*/
int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
wsgi_req->write_pos = 0;
for(;;) {
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_simple_sendfile()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) {
wsgi_req->write_errors++;
return -1;
}
if (ret == 0) {
uwsgi_log("uwsgi_simple_sendfile() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
return 0;
}
+10 -5
View File
@@ -82,6 +82,8 @@ int uwsgi_apply_final_transformations(struct wsgi_request *wsgi_req) {
found_nostream = 1;
}
else {
// stop the chain if no chunk is available
if (!ut->chunk) return 0;
t_buf = ut->chunk->buf;
t_len = ut->chunk->pos;
goto next;
@@ -132,6 +134,12 @@ void uwsgi_free_transformations(struct wsgi_request *wsgi_req) {
if (current_ut->chunk) {
uwsgi_buffer_destroy(current_ut->chunk);
}
if (current_ut->ub) {
uwsgi_buffer_destroy(current_ut->ub);
}
if (current_ut->fd > -1) {
close(current_ut->fd);
}
ut = ut->next;
free(current_ut);
}
@@ -144,12 +152,9 @@ struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_
ut = ut->next;
}
ut = uwsgi_malloc(sizeof(struct uwsgi_transformation));
ut = uwsgi_calloc(sizeof(struct uwsgi_transformation));
ut->func = func;
ut->is_final = 0;
ut->next = NULL;
ut->chunk = NULL;
ut->can_stream = 0;
ut->fd = -1;
ut->data = data;
if (old_ut) {
+83 -22
View File
@@ -71,11 +71,30 @@ void set_user_harakiri(int sec) {
uwsgi_log("!!! unable to set user harakiri without the master process !!!\n");
return;
}
// a 0 seconds value, reset the timer
if (sec == 0) {
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].user_harakiri = 0;
}
else if (uwsgi.i_am_a_spooler) {
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
uspool->user_harakiri = 0;
}
else {
uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
}
}
else {
uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].user_harakiri = uwsgi_now() + sec;
}
else if (uwsgi.i_am_a_spooler) {
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
uspool->user_harakiri = uwsgi_now() + sec;
}
else {
uwsgi.workers[uwsgi.mywid].user_harakiri = uwsgi_now() + sec;
}
}
}
@@ -708,6 +727,11 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
free(ptr);
}
// free chunked input
if (wsgi_req->chunked_input_buf) {
uwsgi_buffer_destroy(wsgi_req->chunked_input_buf);
}
// free websocket engine
if (wsgi_req->websocket_buf) {
uwsgi_buffer_destroy(wsgi_req->websocket_buf);
@@ -1147,7 +1171,6 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
int i;
struct stat st;
int found;
int free_appname = 0;
char *app_name = key;
uint16_t app_name_len = key_len;
@@ -1162,13 +1185,20 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
}
if (uwsgi.vhost) {
app_name = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
char *vhost_name = uwsgi_concat3n(wsgi_req->host, wsgi_req->host_len, "|",1, wsgi_req->script_name, wsgi_req->script_name_len);
app_name_len = wsgi_req->host_len + 1 + wsgi_req->script_name_len;
app_name = uwsgi_req_append(wsgi_req, "UWSGI_APPID", 11, vhost_name, app_name_len);
free(vhost_name);
if (!app_name) {
uwsgi_log("unable to add UWSGI_APPID to the uwsgi buffer, consider increasing it\n");
return -1;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("VirtualHost KEY=%.*s\n", wsgi_req->appid_len, wsgi_req->appid);
uwsgi_debug("VirtualHost KEY=%.*s\n", app_name_len, app_name);
#endif
free_appname = 1;
}
wsgi_req->appid = app_name;
wsgi_req->appid_len = app_name_len;
}
}
@@ -1203,18 +1233,11 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
}
}
}
if (modifier1 == -1) {
if (free_appname) free(app_name);
return i;
}
if (modifier1 == uwsgi_apps[i].modifier1) {
if (free_appname) free(app_name);
return i;
}
if (modifier1 == -1) return i;
if (modifier1 == uwsgi_apps[i].modifier1) return i;
}
}
if (free_appname) free(app_name);
return -1;
}
@@ -1952,7 +1975,7 @@ int uwsgi_list_has_str(char *list, char *str) {
return 0;
}
char hex2num(char *str) {
static char hex2num(char *str) {
char val = 0;
@@ -3065,6 +3088,36 @@ void escape_shell_arg(char *src, size_t len, char *dst) {
*ptr++ = 0;
}
void escape_json(char *src, size_t len, char *dst) {
size_t i;
char *ptr = dst;
for (i = 0; i < len; i++) {
if (src[i] == '\t') {
*ptr++ = '\\';
*ptr++ = 't';
}
else if (src[i] == '\n') {
*ptr++ = '\\';
*ptr++ = 'n';
}
else if (src[i] == '\r') {
*ptr++ = '\\';
*ptr++ = 'r';
}
else if (src[i] == '"') {
*ptr++ = '\\';
*ptr++ = '"';
}
else {
*ptr++ = src[i];
}
}
*ptr++ = 0;
}
void http_url_decode(char *buf, uint16_t * len, char *dst) {
uint16_t i;
@@ -3221,14 +3274,22 @@ char *uwsgi_chomp(char *str) {
return str;
}
char *uwsgi_tmpname(char *base, char *id) {
char *template = uwsgi_concat3(base, "/", id);
if (mkstemp(template) < 0) {
free(template);
return NULL;
int uwsgi_tmpfd() {
char *tmpdir = getenv("TMPDIR");
if (!tmpdir) {
tmpdir = "/tmp";
}
char *template = uwsgi_concat2(tmpdir, "/uwsgiXXXXXX");
int fd = mkstemp(template);
unlink(template);
free(template);
return fd;
}
return template;
FILE *uwsgi_tmpfile() {
int fd = uwsgi_tmpfd();
if (fd < 0) return NULL;
return fdopen(fd, "w+");
}
int uwsgi_file_to_string_list(char *filename, struct uwsgi_string_list **list) {
+70 -14
View File
@@ -236,6 +236,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"cache-sync", required_argument, 0, "copy the whole content of another uWSGI cache server on server startup", uwsgi_opt_set_str, &uwsgi.cache_sync, 0},
{"cache-use-last-modified", no_argument, 0, "update last_modified_at timestamp on every cache item modification (default is disabled)", uwsgi_opt_true, &uwsgi.cache_use_last_modified, 0},
{"add-cache-item", required_argument, 0, "add an item in the cache", uwsgi_opt_add_string_list, &uwsgi.add_cache_item, 0},
{"load-file-in-cache", required_argument, 0, "load a static file in the cache", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache, 0},
#ifdef UWSGI_ZLIB
{"load-file-in-cache-gzip", required_argument, 0, "load a static file in the cache with gzip compression", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache_gzip, 0},
@@ -349,6 +350,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"touch-logrotate", required_argument, 0, "trigger logrotation if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logrotate, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"touch-logreopen", required_argument, 0, "trigger log reopen if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logreopen, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"touch-exec", required_argument, 0, "run command when the specified file is modified/touched (syntax: file command)", uwsgi_opt_add_string_list, &uwsgi.touch_exec, UWSGI_OPT_MASTER},
{"touch-signal", required_argument, 0, "signal when the specified file is modified/touched (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.touch_signal, UWSGI_OPT_MASTER},
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
@@ -459,6 +461,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"log-route", required_argument, 0, "log to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_route, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"log-req-route", required_argument, 0, "log requests to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_req_route, UWSGI_OPT_REQ_LOG_MASTER},
#endif
{"use-abort", no_argument, 0, "call abort() on segfault/fpe, could be useful for generating a core dump", uwsgi_opt_true, &uwsgi.use_abort, 0},
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
@@ -579,6 +584,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"websockets-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
{"websocket-max-size", required_argument, 0, "set the max allowed size of websocket messages (in Kbytes, default 1024)", uwsgi_opt_set_64bit, &uwsgi.websockets_max_size, 0},
{"chunked-input-limit", required_argument, 0, "set the max size of a chunked input part (default 1MB, in bytes)", uwsgi_opt_set_64bit, &uwsgi.chunked_input_limit, 0},
{"chunked-input-timeout", required_argument, 0, "set default timeout for chunked input", uwsgi_opt_set_int, &uwsgi.chunked_input_timeout, 0},
{"clock", required_argument, 0, "set a clock source", uwsgi_opt_set_str, &uwsgi.requested_clock, 0},
{"clock-list", no_argument, 0, "list enabled clocks", uwsgi_opt_true, &uwsgi.clock_list, 0},
@@ -693,6 +701,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config, 0},
{"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL, 0},
{"cflags", no_argument, 0, "report uWSGI CFLAGS (useful for building external plugins)", uwsgi_opt_cflags, NULL, UWSGI_OPT_IMMEDIATE},
{"dot-h", no_argument, 0, "dump the uwsgi.h used for building the core (useful for building external plugins)", uwsgi_opt_dot_h, NULL, UWSGI_OPT_IMMEDIATE},
{"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
{0, 0, 0, 0, 0, 0, 0}
};
@@ -1527,6 +1536,8 @@ void uwsgi_segfault(int signum) {
uwsgi_log("!!! uWSGI process %d got Segmentation Fault !!!\n", (int) getpid());
uwsgi_backtrace(uwsgi.backtrace_depth);
if (uwsgi.use_abort) abort();
// restore default handler to generate core
signal(signum, SIG_DFL);
kill(getpid(), signum);
@@ -1540,6 +1551,8 @@ void uwsgi_fpe(int signum) {
uwsgi_log("!!! uWSGI process %d got Floating Point Exception !!!\n", (int) getpid());
uwsgi_backtrace(uwsgi.backtrace_depth);
if (uwsgi.use_abort) abort();
// restore default handler to generate core
signal(signum, SIG_DFL);
kill(getpid(), signum);
@@ -3386,7 +3399,9 @@ void uwsgi_opt_set_16bit(char *opt, char *value, void *key) {
uint16_t *ptr = (uint16_t *) key;
if (value) {
*ptr = (strtoul(value, NULL, 10));
unsigned long n = strtoul(value, NULL, 10);
if (n > 65535) n = 65535;
*ptr = n;
}
else {
*ptr = 1;
@@ -4057,20 +4072,61 @@ void uwsgi_opt_flock_wait(char *opt, char *filename, void *none) {
// report CFLAGS used for compiling the server
// use that values to build external plugins
void uwsgi_opt_cflags(char *opt, char *filename, void *foobar) {
size_t len = sizeof(UWSGI_CFLAGS);
char *src = UWSGI_CFLAGS;
char *ptr = uwsgi_malloc(len / 2);
char *base = ptr;
size_t i;
unsigned int u;
for (i = 0; i < len; i += 2) {
sscanf(src + i, "%2x", &u);
*ptr++ = (char) u;
}
fprintf(stdout, "%.*s\n", (int) len / 2, base);
fprintf(stdout, "%s\n", uwsgi_get_cflags());
exit(0);
}
char *uwsgi_get_cflags() {
size_t len = sizeof(UWSGI_CFLAGS);
char *src = UWSGI_CFLAGS;
char *ptr = uwsgi_malloc((len / 2) + 1);
char *base = ptr;
size_t i;
unsigned int u;
for (i = 0; i < len; i += 2) {
sscanf(src + i, "%2x", &u);
*ptr++ = (char) u;
}
*ptr ++= 0;
return base;
}
// report uwsgi.h used for compiling the server
// use that values to build external plugins
extern char *uwsgi_dot_h;
char *uwsgi_get_dot_h() {
char *src = uwsgi_dot_h;
size_t len = strlen(src);
char *ptr = uwsgi_malloc(len / 2);
char *base = ptr;
size_t i;
unsigned int u;
for (i = 0; i < len; i += 2) {
sscanf(src + i, "%2x", &u);
*ptr++ = (char) u;
}
#ifdef UWSGI_ZLIB
struct uwsgi_buffer *ub = uwsgi_zlib_decompress(base, ptr-base);
if (!ub) {
free(base);
return "";
}
// add final null byte
uwsgi_buffer_append(ub, "\0", 1);
free(base);
// base is the final blob
base = ub->buf;
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
#endif
return base;
}
void uwsgi_opt_dot_h(char *opt, char *filename, void *foobar) {
fprintf(stdout, "%s\n", uwsgi_get_dot_h());
exit(0);
}
void uwsgi_opt_connect_and_read(char *opt, char *address, void *foobar) {
char buf[8192];
@@ -4107,9 +4163,9 @@ void uwsgi_opt_extract(char *opt, char *address, void *foobar) {
}
void uwsgi_print_sym(char *opt, char *symbol, void *foobar) {
char *sym = dlsym(RTLD_DEFAULT, symbol);
char **sym = dlsym(RTLD_DEFAULT, symbol);
if (sym) {
uwsgi_log("%s", sym);
uwsgi_log("%s", *sym);
exit(0);
}
+32
View File
@@ -408,3 +408,35 @@ int uwsgi_simple_wait_write_hook(int fd, int timeout) {
return ret;
}
/*
simplified write to client
(generally used as fallback)
*/
int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
wsgi_req->write_pos = 0;
for(;;) {
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_simple_write()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) { wsgi_req->write_errors++; return -1;}
if (ret == 0) {
uwsgi_log("uwsgi_simple_write() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
return 0;
}
+56
View File
@@ -2,6 +2,8 @@
char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
extern struct uwsgi_server uwsgi;
char *uwsgi_gzip_chunk(z_stream *z, uint32_t *crc32, char *buf, size_t len, size_t *dlen) {
uwsgi_crc32(crc32, buf, len);
return uwsgi_deflate(z, buf, len, dlen);
@@ -38,6 +40,45 @@ end:
return ub;
}
struct uwsgi_buffer *uwsgi_zlib_decompress(char *buf, size_t len) {
z_stream z;
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
if (inflateInit(&z) != Z_OK) {
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
unsigned char out[8192];
z.next_in = (unsigned char *)buf;
z.avail_in = len;
z.next_out = out;
do {
z.avail_out = 8192;
z.next_out = out;
int ret = inflate(&z, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
uwsgi_buffer_destroy(ub);
ub = NULL;
goto end;
}
if (uwsgi_buffer_append(ub, (char *)out, 8192 - z.avail_out)) {
uwsgi_buffer_destroy(ub);
ub = NULL;
goto end;
}
}
while (z.avail_out == 0);
end:
inflateEnd(&z);
return ub;
}
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
z->zfree = Z_NULL;
@@ -54,6 +95,21 @@ int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
return 0;
}
int uwsgi_inflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
z->zfree = Z_NULL;
z->opaque = Z_NULL;
if (inflateInit2(z, 16+MAX_WBITS) != Z_OK) {
return -1;
}
if (dict && dict_len) {
if (inflateSetDictionary(z, (Bytef *) dict, dict_len) != Z_OK) {
return -1;
}
}
return 0;
}
int uwsgi_gzip_prepare(z_stream *z, char *dict, size_t dict_len, uint32_t *crc32) {
uwsgi_crc32(crc32, NULL, 0);
if (uwsgi_deflate_init(z, NULL, 0)) return -1;
+52
View File
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="768px" height="272.667px" viewBox="0 0 768 272.667" enable-background="new 0 0 768 272.667" xml:space="preserve">
<g>
<path fill="#AEC84D" d="M170.667,41.334"/>
<path fill="#AEC84D" d="M46.167,106.667v92.5c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34l0.062-140h-34
l-0.062,86.5c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.167-89H46.167z"/>
<polygon fill="#141215" points="227,250.334 241,250.334 286.667,137.334 332.333,250.001 346.333,250.001 403,41.334
368.667,32.667 334.333,161.667 293.667,60.001 279.333,60.001 240,160.667 204.667,32.667 170.667,41.334 "/>
<path fill="#141215" d="M402,203c0,0,8.667,26.001,23,35.334s38.666,12.999,50.333,12.666s71.001-1.333,71.667-56.333
c5-28-19.333-48.334-26-52.334s-28.334-18-45.667-23s-34.334-16-35.667-24.666s0.001-34,37.334-34.334
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334s-13.333-19-55.333-18.666
c-42,0.332-66.666,17.666-68.333,47.666s4.666,44,35.333,62.666c19,10.334,39.001,12.667,59.667,28.334
c14.333,11.667,11.334,25.001,11,30.667s-7.334,21.666-36.334,20.333S441,209.668,439,206.334s-9-17-9-17L402,203z"/>
<rect x="710.667" y="36.334" fill="#141215" width="35.333" height="211.333"/>
<path fill="#141215" d="M636.333,135.001v27.666h27.333v56c0,0-8.334,5.001-26.667,4.334s-47.332,1.666-49.666-81.667
s37.334-80.667,42-80.667s28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667s-12.334-50.333-67-47.666
c-54.666,2.666-75.666,30.999-78.666,102c-3,71,21.999,117.334,81.666,115s64-7.334,64-7.334l-0.083-107.583L636.333,135.001z"/>
<g>
<circle fill="#AEC84D" cx="521.333" cy="71.001" r="11.667"/>
<circle fill="#252326" cx="521.333" cy="71.001" r="3.5"/>
</g>
<g>
<path fill="none" d="M81.147,185.163L81,106.667H46.167v90.88C56.139,192.016,68.027,187.752,81.147,185.163z"/>
<path fill="none" d="M171.729,106.667h-34l-0.057,78.023c12.606,2.254,24.141,6.043,34.017,11.019L171.729,106.667z"/>
<path opacity="0.1" fill="#FFFFFF" d="M46.167,199.167c0,0-0.667,52.667,48.5,51.5c7.667-0.333,36,1,43-21c0-0.5,0,17,0,17h34
l0.023-50.958c-9.876-4.976-21.411-8.765-34.017-11.019l-0.006,8.477c0,0,1,31-28,29.5s-28.5-27-28.5-27l-0.02-10.504
c-13.12,2.589-25.008,6.853-34.98,12.384V199.167z"/>
</g>
<g>
<path fill="none" d="M342.89,129.517l-8.557,32.15l-13.896-34.738c-22.89-2.918-44.071-6.524-63.071-10.708L240,160.667
l-14.526-52.621c-16.399-4.896-30.286-10.312-41.175-16.132L227,250.334h14l45.667-113l45.667,112.667h14l31.898-117.459
C366.127,131.707,354.33,130.695,342.89,129.517z"/>
<path opacity="0.1" fill="#FFFFFF" d="M403,41.334l-34.333-8.667l-25.776,96.85c11.44,1.178,23.237,2.19,35.341,3.025L403,41.334z
"/>
<path opacity="0.1" fill="#FFFFFF" d="M204.667,32.667l-34,8.667l13.633,50.58c10.889,5.82,24.775,11.236,41.175,16.132
L204.667,32.667z"/>
<path opacity="0.1" fill="#FFFFFF" d="M293.667,60.001h-14.333l-21.967,56.22c19,4.185,40.182,7.79,63.071,10.708L293.667,60.001z
"/>
</g>
<path opacity="0.1" fill="#FFFFFF" d="M474.333,33.001c-42,0.332-66.666,17.666-68.333,47.666
c-1.409,25.351,2.897,39.276,22.77,54.247c10.646,0.275,21.452,0.419,32.396,0.419c15.9,0,31.514-0.299,46.756-0.872
c-9.466-5.486-21.856-12.032-32.589-15.128c-17.333-5-34.334-16-35.667-24.666s0.001-34,37.334-34.334
c26,2.668,27,13.668,31,19.668l7,14.332l28.666-13.332c0,0-11.334-27-14-29.334S516.333,32.667,474.333,33.001z"/>
<path opacity="0.1" fill="#FFFFFF" d="M631,33.001c-53.87,2.627-75.047,30.182-78.522,98.93c11.947-0.916,23.576-2.007,34.838-3.26
c1.845-70.377,37.603-68.004,42.019-68.004c4.666,0,28,0.334,40,33.334C669.667,94.334,698,80.667,698,80.667
S685.666,30.334,631,33.001z"/>
<path opacity="0.1" fill="#FFFFFF" d="M710.667,103.59c14.42-5.033,26.342-10.521,35.333-16.36V36.334h-35.333V103.59z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

+1
View File
@@ -229,6 +229,7 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
curl_easy_setopt(curl, CURLOPT_POST, 1L);
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
char *opts = uwsgi_str(uacc->arg);
+1
View File
@@ -154,6 +154,7 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
curl_easy_setopt(curl, CURLOPT_POST, 1L);
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
char *opts = uwsgi_str(uacc->arg);
+2 -2
View File
@@ -23,13 +23,13 @@
}\
peer->out_pos += len;
#define cr_write_buf(peer, buf, f) write(peer->fd, buf + buf##_pos, buf->pos - buf##_pos);\
#define cr_write_buf(peer, ubuf, f) write(peer->fd, ubuf->buf + ubuf##_pos, ubuf->pos - ubuf##_pos);\
if (len < 0) {\
cr_try_again;\
uwsgi_cr_error(peer, f);\
return -1;\
}\
buf##_pos += len;
ubuf##_pos += len;
#define cr_write_complete(peer) peer->out_pos == peer->out->pos
+1 -1
View File
@@ -161,7 +161,7 @@ request:
#endif
for(;;) {
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req)) {
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
goto end;
}
wsgi_req->switches++;
+2 -1
View File
@@ -453,7 +453,8 @@ static int amqp_wait_connection_tune(int fd) {
static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
char *ptr = (char *) fh;
ssize_t len = 0, rlen;
size_t len = 0;
ssize_t rlen;
while(len < 7) {
rlen = recv(fd, ptr, 7-len, 0);
+5
View File
@@ -25,6 +25,7 @@ struct uwsgi_jvm {
jclass input_stream_class;
jclass file_class;
jclass hashmap_class;
jclass list_class;
jclass set_class;
jclass iterator_class;
@@ -63,6 +64,10 @@ jmethodID uwsgi_jvm_get_static_method_id_quiet(jclass, char *, char *);
jobject uwsgi_jvm_str(char *, size_t);
jobject uwsgi_jvm_hashmap(void);
int uwsgi_jvm_hashmap_put(jobject, jobject, jobject);
int uwsgi_jvm_hashmap_has(jobject, jobject);
jobject uwsgi_jvm_list(void);
int uwsgi_jvm_list_add(jobject, jobject);
jobject uwsgi_jvm_call_object(jobject, jmethodID, ...);
jobject uwsgi_jvm_call_object_static(jclass, jmethodID, ...);
+120
View File
@@ -215,15 +215,42 @@ JNIEXPORT jint JNICALL uwsgi_jvm_request_body_read_bytearray(JNIEnv *env, jobjec
return rlen;
}
JNIEXPORT jint JNICALL uwsgi_jvm_request_body_readline_bytearray(JNIEnv *env, jobject o, jobject b) {
struct wsgi_request *wsgi_req = current_wsgi_req();
ssize_t rlen = 0;
size_t len = uwsgi_jvm_array_len(b);
char *chunk = uwsgi_request_body_readline(wsgi_req, len, &rlen);
if (!chunk) {
uwsgi_jvm_throw_io("error reading request body");
return -1;
}
if (chunk == uwsgi.empty) {
return -1;
}
char *buf = (char *) (*ujvm_env)->GetByteArrayElements(ujvm_env, b, JNI_FALSE);
if (!buf) return -1;
memcpy(buf, chunk, rlen);
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, b, (jbyte *) buf, 0);
return rlen;
}
JNIEXPORT jint JNICALL uwsgi_jvm_request_body_available(JNIEnv *env, jobject o) {
struct wsgi_request *wsgi_req = current_wsgi_req();
return (jint) (wsgi_req->post_cl - wsgi_req->post_pos);
}
JNIEXPORT void JNICALL uwsgi_jvm_request_body_seek(JNIEnv *env, jobject o, jint pos) {
struct wsgi_request *wsgi_req = current_wsgi_req();
uwsgi_request_body_seek(wsgi_req, pos);
}
static JNINativeMethod uwsgi_jvm_request_body_methods[] = {
{"read", "()I", (void *) &uwsgi_jvm_request_body_read},
{"read", "([B)I", (void *) &uwsgi_jvm_request_body_read_bytearray},
{"readLine", "([B)I", (void *) &uwsgi_jvm_request_body_readline_bytearray},
{"available", "()I", (void *) &uwsgi_jvm_request_body_available},
{"seek", "(I)V", (void *) &uwsgi_jvm_request_body_seek},
};
static struct uwsgi_option uwsgi_jvm_options[] = {
@@ -684,6 +711,23 @@ void uwsgi_jvm_local_unref(jobject obj) {
(*ujvm_env)->DeleteLocalRef(ujvm_env, obj);
}
jobject uwsgi_jvm_list() {
// optimization
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.list_class, "<init>", "()V");
if (!mid) return NULL;
}
jobject ll = (*ujvm_env)->NewObject(ujvm_env, ujvm.list_class, mid);
if (uwsgi_jvm_exception()) {
return NULL;
}
return ll;
}
jobject uwsgi_jvm_hashmap() {
// optimization
static jmethodID mid = 0;
@@ -712,6 +756,18 @@ int uwsgi_jvm_hashmap_put(jobject hm, jobject key, jobject value) {
return uwsgi_jvm_call(hm, mid, key, value);
}
int uwsgi_jvm_list_add(jobject ll, jobject value) {
// optimization
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.list_class, "add", "(Ljava/lang/Object;)Z");
if (!mid) return -1;
}
return uwsgi_jvm_call(ll, mid, value);
}
jobject uwsgi_jvm_hashmap_get(jobject hm, jobject key) {
// optimization
static jmethodID mid = 0;
@@ -724,6 +780,21 @@ jobject uwsgi_jvm_hashmap_get(jobject hm, jobject key) {
return uwsgi_jvm_call_object(hm, mid, key);
}
int uwsgi_jvm_hashmap_has(jobject hm, jobject key) {
// optimization
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.hashmap_class, "containsKey", "(Ljava/lang/Object;)Z");
if (!mid) return 0;
}
if (uwsgi_jvm_call_bool(hm, mid, key)) {
return 1;
}
return 0;
}
jobject uwsgi_jvm_iterator(jobject set) {
// optimization
static jmethodID mid = 0;
@@ -1010,6 +1081,9 @@ static void uwsgi_jvm_create(void) {
ujvm.hashmap_class = uwsgi_jvm_class("java/util/HashMap");
if (!ujvm.hashmap_class) exit(1);
ujvm.list_class = uwsgi_jvm_class("java/util/ArrayList");
if (!ujvm.list_class) exit(1);
ujvm.set_class = uwsgi_jvm_class("java/util/Set");
if (!ujvm.set_class) exit(1);
@@ -1026,6 +1100,52 @@ static void uwsgi_jvm_create(void) {
if (!uwsgi_class) {
exit(1);
}
/*
start filling uwsgi.opt
*/
jfieldID opt_fid = (*ujvm_env)->GetStaticFieldID(ujvm_env, uwsgi_class, "opt", "Ljava/util/HashMap;");
if (uwsgi_jvm_exception()) {
exit(1);
}
jobject opt_hm = uwsgi_jvm_hashmap();
int j;
for (j = 0; j < uwsgi.exported_opts_cnt; j++) {
jstring j_opt_key = uwsgi_jvm_str(uwsgi.exported_opts[j]->key, 0);
if (uwsgi_jvm_hashmap_has(opt_hm, (jobject) j_opt_key)) {
jobject j_opt_value = uwsgi_jvm_hashmap_get(opt_hm, (jobject) j_opt_key);
if (uwsgi_jvm_object_is_instance(j_opt_value, ujvm.list_class)) {
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_list_add(j_opt_value, (jobject) 1);
}
else {
uwsgi_jvm_list_add(j_opt_value, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
}
}
else {
jobject ll = uwsgi_jvm_list();
uwsgi_jvm_list_add(ll, j_opt_value);
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_list_add(ll, (jobject) 1);
}
else {
uwsgi_jvm_list_add(ll, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
}
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, ll);
}
}
else {
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, (jobject) 1);
}
else {
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
}
}
}
(*ujvm_env)->SetStaticObjectField(ujvm_env, uwsgi_class, opt_fid, opt_hm);
(*ujvm_env)->RegisterNatives(ujvm_env, uwsgi_class, uwsgi_jvm_api_methods, sizeof(uwsgi_jvm_api_methods)/sizeof(uwsgi_jvm_api_methods[0]));
if (uwsgi_jvm_exception()) {
exit(1);
+5
View File
@@ -1,11 +1,16 @@
import java.io.*;
import java.util.*;
public class uwsgi {
static HashMap<String,Object> opt;
public static class RequestBody extends InputStream {
public native int read();
public native int read(byte[] b);
public native int readLine(byte[] b);
public native int available();
public native void seek(int pos);
}
public interface SignalHandler {
+33 -10
View File
@@ -9,6 +9,7 @@ struct uwsgi_jwsgi {
char *app;
jmethodID app_mid;
jclass app_class;
jobject app_instance;
} ujwsgi;
static struct uwsgi_option uwsgi_jwsgi_options[] = {
@@ -20,7 +21,16 @@ static int uwsgi_jwsgi_add_request_item(jobject hm, char *key, uint16_t key_len,
jobject j_key = uwsgi_jvm_str(key, key_len);
if (!j_key) return -1;
jobject j_value = uwsgi_jvm_str(value, value_len);
jobject j_value = NULL;
// avoid clobbering vars
if (value_len > 0) {
j_value = uwsgi_jvm_str(value, value_len);
}
else {
char *tmp = uwsgi_str("");
j_value = uwsgi_jvm_str(tmp, 0);
free(tmp);
}
if (!j_value) {
uwsgi_jvm_local_unref(j_value);
return -1;
@@ -72,7 +82,12 @@ static int uwsgi_jwsgi_request(struct wsgi_request *wsgi_req) {
if (uwsgi_jwsgi_add_request_input(hm, "jwsgi.input", 11)) goto end;
response = uwsgi_jvm_call_object_static(ujwsgi.app_class, ujwsgi.app_mid, hm);
if (!ujwsgi.app_instance) {
response = uwsgi_jvm_call_object_static(ujwsgi.app_class, ujwsgi.app_mid, hm);
}
else {
response = uwsgi_jvm_call_object(ujwsgi.app_instance, ujwsgi.app_mid, hm);
}
if (!response) goto end;
if (uwsgi_jvm_array_len(response) != 3) {
@@ -135,23 +150,31 @@ static int uwsgi_jwsgi_setup() {
char *app = uwsgi_str(ujwsgi.app);
char *method = "application";
char *colon = strchr(app, ':');
if (!colon) {
uwsgi_log("invalid JWSGI app definition, must be class:method\n");
exit(1);
if (colon) {
*colon = 0;
method = colon + 1;
}
*colon = 0;
ujwsgi.app_class = uwsgi_jvm_class(app);
if (!ujwsgi.app_class) {
exit(1);
}
ujwsgi.app_mid = uwsgi_jvm_get_static_method_id(ujwsgi.app_class, colon+1, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
if (!ujwsgi.app_mid) {
exit(1);
ujwsgi.app_mid = uwsgi_jvm_get_static_method_id_quiet(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
jmethodID mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, "<init>", "()V");
if (uwsgi_jvm_exception() || !mid) exit(1);
ujwsgi.app_instance = (*ujvm_env)->NewObject(ujvm_env, ujwsgi.app_class, mid);
if (uwsgi_jvm_exception() || !ujwsgi.app_instance) {
exit(1);
}
ujwsgi.app_mid = uwsgi_jvm_get_method_id(ujwsgi.app_class, method, "(Ljava/util/HashMap;)[Ljava/lang/Object;");
if (uwsgi_jvm_exception() || !ujwsgi.app_mid) {
exit(1);
}
}
uwsgi_log("JWSGI app \"%s\" loaded\n", ujwsgi.app);
+5
View File
@@ -0,0 +1,5 @@
#include <uwsgi.h>
struct uwsgi_plugin objc_gc_plugin = {
.name = "objc_gc",
};
+5
View File
@@ -0,0 +1,5 @@
NAME="objc_gc"
CFLAGS=["-fobjc-gc"]
LDFLAGS=[]
LIBS=[]
GCC_LIST=['objc_gc.m']
+12
View File
@@ -81,6 +81,16 @@ XS(XS_signal) {
XSRETURN_UNDEF;
}
XS(XS_set_user_harakiri) {
dXSARGS;
psgi_check_args(1);
set_user_harakiri( SvIV(ST(0)) );
XSRETURN_UNDEF;
}
XS(XS_reload) {
dXSARGS;
@@ -549,5 +559,7 @@ void init_perl_embedded_module() {
psgi_xs(add_timer);
psgi_xs(add_rb_timer);
psgi_xs(set_user_harakiri);
}
+15 -41
View File
@@ -41,47 +41,6 @@ void (*uwsgi_pypy_post_fork_hook)(void);
extern struct uwsgi_server uwsgi;
struct uwsgi_plugin pypy_plugin;
int uwsgi_pypy_helper_masterpid() {
if (uwsgi.master_process) {
return uwsgi.workers[0].pid;
}
return 0;
}
int uwsgi_pypy_helper_worker_id() {
return uwsgi.mywid;
}
int uwsgi_pypy_helper_mule_id() {
return uwsgi.muleid;
}
void uwsgi_pypy_helper_signal(int signum) {
uwsgi_signal_send(uwsgi.signal_socket, signum);
}
struct uwsgi_opt **uwsgi_pypy_helper_opts(int *n) {
*n = uwsgi.exported_opts_cnt;
return uwsgi.exported_opts;
}
char *uwsgi_pypy_helper_version() {
return UWSGI_VERSION;
}
int uwsgi_pypy_helper_register_signal(int signum, char *kind, void *handler) {
return uwsgi_register_signal(signum, kind, handler, pypy_plugin.modifier1);
}
int uwsgi_pypy_helper_register_rpc(char *name, int argc, void *func) {
return uwsgi_register_rpc(name, &pypy_plugin, argc, func);
}
struct iovec *uwsgi_pypy_helper_environ(struct wsgi_request *wsgi_req, uint16_t *len) {
*len = wsgi_req->var_cnt;
return wsgi_req->hvec;
}
static int uwsgi_pypy_init() {
size_t rlen = 0;
@@ -342,6 +301,20 @@ static void uwsgi_pypy_onload() {
#endif
}
static int uwsgi_pypy_mule(char *opt) {
if (uwsgi_endswith(opt, ".py")) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(opt, &rlen, 1, NULL);
pypy_execute_source(buffer);
free(buffer);
return 1;
}
return 0;
}
struct uwsgi_plugin pypy_plugin = {
.name = "pypy",
.modifier1 = 0,
@@ -357,4 +330,5 @@ struct uwsgi_plugin pypy_plugin = {
.enable_threads = uwsgi_pypy_enable_threads,
.rpc = uwsgi_pypy_rpc,
.post_fork = uwsgi_pypy_post_fork,
.mule = uwsgi_pypy_mule,
};
+508 -72
View File
@@ -14,69 +14,230 @@ import cffi
# this is a list holding object we do not want to be freed (like callback and handlers)
uwsgi_gc = []
# the main ffi
ffi = cffi.FFI()
defines = '''
# the hooks we need to patch
hooks = '''
void free(void *);
ssize_t read(int, void *, size_t);
ssize_t write(int, const void *, size_t);
int close(int);
void (*uwsgi_pypy_hook_loader)(char *);
void (*uwsgi_pypy_hook_file_loader)(char *);
void (*uwsgi_pypy_hook_pythonpath)(char *);
void (*uwsgi_pypy_hook_request)(void *, int);
void (*uwsgi_pypy_hook_request)(struct wsgi_request *);
void (*uwsgi_pypy_post_fork_hook)(void);
'''
# here we load CFLAGS and uwsgi.h from the binary
defines0 = '''
char *uwsgi_get_cflags();
char *uwsgi_get_dot_h();
'''
ffi.cdef(defines0)
lib0 = ffi.verify(defines0)
# this is ugly, we should find a better approach
# basically it build a list of #define from binary CFLAGS
uwsgi_cdef = []
uwsgi_defines = []
uwsgi_cflags = ffi.string(lib0.uwsgi_get_cflags()).split()
for cflag in uwsgi_cflags:
if cflag.startswith('-D'):
line = cflag[2:]
if '=' in line:
(key, value) = line.split('=', 1)
uwsgi_cdef.append('#define %s ...' % key)
uwsgi_defines.append('#define %s %s' % (key, value.replace('\\"','"').replace('""','"')))
else:
uwsgi_cdef.append('#define %s ...' % line)
uwsgi_defines.append('#define %s 1' % line)
uwsgi_dot_h = ffi.string(lib0.uwsgi_get_dot_h())
# uwsgi definitions
cdefines = '''
%s
struct iovec {
char *iov_base;
uint64_t iov_len;
void *iov_base;
size_t iov_len;
...;
};
struct uwsgi_header {
uint8_t modifier1;
...;
};
struct wsgi_request {
int fd;
int async_id;
uint16_t var_cnt;
struct iovec *hvec;
int async_ready_fd;
int async_last_ready_fd;
int suspended;
struct uwsgi_header *uh;
...;
};
struct uwsgi_opt {
char *key;
char *value;
int configured;
char *key;
char *value;
...;
};
struct uwsgi_worker {
int id;
int pid;
uint64_t requests;
uint64_t delta_requests;
uint64_t signals;
int cheaped;
int suspended;
int sig;
uint8_t signum;
uint64_t running_time;
uint64_t avg_response_time;
uint64_t tx;
...;
};
struct uwsgi_plugin {
uint8_t modifier1;
void (*suspend) (struct wsgi_request *);
void (*resume) (struct wsgi_request *);
...;
};
struct uwsgi_buffer {
char *buf;
size_t pos;
...;
};
struct uwsgi_server {
char hostname[];
int mywid;
int muleid;
int master_process;
struct uwsgi_opt **exported_opts;
int exported_opts_cnt;
struct uwsgi_worker *workers;
int signal_socket;
int numproc;
int async;
void (*schedule_to_main) (struct wsgi_request *);
void (*schedule_to_req) (void);
struct wsgi_request *(*current_wsgi_req) (void);
struct wsgi_request *wsgi_req;
struct uwsgi_plugin *p[];
...;
};
struct uwsgi_server uwsgi;
struct uwsgi_plugin *pypy_plugin;
const char *uwsgi_pypy_version;
char *uwsgi_binary_path();
void uwsgi_set_processname(char *);
void uwsgi_alarm_trigger(char *, char *, uint64_t);
int uwsgi_signal_registered(uint8_t);
int uwsgi_response_write_body_do(void *, char *, uint64_t);
int uwsgi_response_sendfile_do_can_close(void *, int, uint64_t, uint64_t, int);
int uwsgi_response_prepare_headers(void *, char *, uint16_t);
int uwsgi_response_add_header(void *, char *, uint16_t, char *, uint16_t);
char *uwsgi_request_body_read(void *, uint64_t, int64_t *);
char *uwsgi_request_body_readline(void *, uint64_t, int64_t *);
int uwsgi_response_prepare_headers(struct wsgi_request *, char *, size_t);
int uwsgi_response_add_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
int uwsgi_response_write_body_do(struct wsgi_request *, char *, size_t);
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *, int, size_t, size_t, int);
struct iovec *uwsgi_pypy_helper_environ(void *, uint16_t *);
char *uwsgi_request_body_read(struct wsgi_request *, ssize_t , ssize_t *);
char *uwsgi_request_body_readline(struct wsgi_request *, ssize_t, ssize_t *);
char *uwsgi_pypy_helper_version();
int uwsgi_pypy_helper_register_signal(int, char *, void *);
int uwsgi_pypy_helper_register_rpc(char *, int, void *);
void uwsgi_pypy_helper_signal(int);
struct uwsgi_opt** uwsgi_pypy_helper_opts(int *);
int uwsgi_pypy_helper_masterpid();
int uwsgi_pypy_helper_worker_id();
int uwsgi_pypy_helper_mule_id();
void uwsgi_buffer_destroy(struct uwsgi_buffer *);
int uwsgi_is_again();
int uwsgi_register_rpc(char *, struct uwsgi_plugin *, uint8_t, void *);
int uwsgi_register_signal(uint8_t, char *, void *, uint8_t);
char *uwsgi_cache_magic_get(char *, uint64_t, uint64_t *, uint64_t *, char *);
int uwsgi_cache_magic_set(char *, uint64_t, char *, uint64_t, uint64_t, uint64_t, char *);
int uwsgi_cache_magic_del(char *, uint64_t, char *);
int uwsgi_add_timer(uint8_t, int);
int uwsgi_add_rb_timer(uint8_t, int, int);
int uwsgi_add_file_monitor(uint8_t, char *);
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);
void uwsgi_set_processname(char *);
int uwsgi_signal_send(int, uint8_t);
uint64_t uwsgi_worker_exceptions(int);
int uwsgi_worker_is_busy(int);
char *uwsgi_cache_magic_get(char *, uint16_t, uint64_t *, uint64_t *, char *);
int uwsgi_cache_magic_set(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t, char *);
int uwsgi_cache_magic_del(char *, uint16_t, char *);
int uwsgi_cache_magic_exists(char *, uint16_t, char *);
int uwsgi_cache_magic_clear(char *);
int uwsgi_add_file_monitor(uint8_t, char *);
int uwsgi_add_timer(uint8_t, int);
int uwsgi_signal_add_rb_timer(uint8_t, int, int);
int uwsgi_user_lock(int);
int uwsgi_user_unlock(int);
'''
int uwsgi_signal_registered(uint8_t);
ffi = cffi.FFI()
ffi.cdef(defines)
lib = ffi.verify(defines)
int uwsgi_signal_add_cron(uint8_t, int, int, int, int, int);
void uwsgi_alarm_trigger(char *, char *, size_t);
void async_schedule_to_req_green(void);
void async_add_timeout(struct wsgi_request *, int);
int async_add_fd_write(struct wsgi_request *, int, int);
int async_add_fd_read(struct wsgi_request *, int, int);
int uwsgi_connect(char *, int, int);
int uwsgi_websocket_handshake(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
int uwsgi_websocket_send(struct wsgi_request *, char *, size_t);
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *);
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *);
char *uwsgi_chunked_read(struct wsgi_request *, size_t *, int, int);
void uwsgi_disconnect(struct wsgi_request *);
int uwsgi_ready_fd(struct wsgi_request *);
void set_user_harakiri(int);
%s
''' % ('\n'.join(uwsgi_cdef), hooks)
cverify = '''
%s
const char *uwsgi_pypy_version = UWSGI_VERSION;
%s
extern struct uwsgi_server uwsgi;
extern struct uwsgi_plugin *pypy_plugin;
%s
''' % ('\n'.join(uwsgi_defines), uwsgi_dot_h, hooks)
ffi.cdef(cdefines)
lib = ffi.verify(cverify)
libc = ffi.dlopen(None)
"""
this is a global object point the the WSGI callable
it sucks, i will fix it in the near future...
@@ -115,7 +276,7 @@ def uwsgi_pypy_file_loader(filename):
wsgi_application = getattr(mod, c)
"""
.post_fork_hokk
.post_fork_hook
"""
@ffi.callback("void()")
def uwsgi_pypy_post_fork_hook():
@@ -180,7 +341,7 @@ class WSGIinput(object):
raise IOError("error waiting for wsgi.input")
def getline(self, hint=0):
rlen = ffi.new('int64_t*')
rlen = ffi.new('ssize_t*')
chunk = lib.uwsgi_request_body_readline(self.wsgi_req, hint, rlen)
if chunk != ffi.NULL:
return ffi.string(chunk, rlen[0])
@@ -213,8 +374,9 @@ class WSGIinput(object):
"""
the WSGI request handler
"""
@ffi.callback("void(void *, int)")
def uwsgi_pypy_wsgi_handler(wsgi_req, core):
@ffi.callback("void(struct wsgi_request *)")
def uwsgi_pypy_wsgi_handler(wsgi_req):
import uwsgi
global wsgi_application
def writer(data):
@@ -229,10 +391,9 @@ def uwsgi_pypy_wsgi_handler(wsgi_req, core):
return writer
environ = {}
nv = ffi.new("uint16_t*")
iov = lib.uwsgi_pypy_helper_environ(wsgi_req, nv)
for i in range(0, nv[0], 2):
environ[ffi.string(iov[i].iov_base, iov[i].iov_len)] = ffi.string(iov[i+1].iov_base, iov[i+1].iov_len)
iov = wsgi_req.hvec
for i in range(0, wsgi_req.var_cnt, 2):
environ[ffi.string(ffi.cast("char*", iov[i].iov_base), iov[i].iov_len)] = ffi.string(ffi.cast("char*", iov[i+1].iov_base), iov[i+1].iov_len)
environ['wsgi.version'] = (1, 0)
scheme = 'http'
@@ -247,7 +408,8 @@ def uwsgi_pypy_wsgi_handler(wsgi_req, core):
environ['wsgi.multithread'] = True
environ['wsgi.multiprocess'] = True
environ['uwsgi.core'] = core
environ['uwsgi.core'] = wsgi_req.async_id
environ['uwsgi.node'] = uwsgi.hostname
response = wsgi_application(environ, start_response)
if type(response) is str:
@@ -281,13 +443,13 @@ Here we define the "uwsgi" virtual module
uwsgi = imp.new_module('uwsgi')
sys.modules['uwsgi'] = uwsgi
uwsgi.version = ffi.string(lib.uwsgi_pypy_helper_version())
uwsgi.version = ffi.string(lib.uwsgi_pypy_version)
uwsgi.hostname = ffi.string(lib.uwsgi.hostname)
def uwsgi_pypy_uwsgi_register_signal(signum, kind, handler):
cb = ffi.callback('void(int)', handler)
uwsgi_gc.append(cb)
if lib.uwsgi_pypy_helper_register_signal(signum, ffi.new("char[]", kind), cb) < 0:
if lib.uwsgi_register_signal(signum, ffi.new("char[]", kind), cb, lib.pypy_plugin.modifier1) < 0:
raise Exception("unable to register signal %d" % signum)
uwsgi.register_signal = uwsgi_pypy_uwsgi_register_signal
@@ -311,7 +473,7 @@ def uwsgi_pypy_uwsgi_register_rpc(name, func, argc=0):
rpc_func = uwsgi_pypy_RPC(func)
cb = ffi.callback("int(int, char*[], int[], char*)", rpc_func)
uwsgi_gc.append(cb)
if lib.uwsgi_pypy_helper_register_rpc(ffi.new("char[]", name), argc, cb) < 0:
if lib.uwsgi_register_rpc(ffi.new("char[]", name), lib.pypy_plugin, argc, cb) < 0:
raise Exception("unable to register rpc func %s" % name)
uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc
@@ -350,9 +512,7 @@ def uwsgi_pypy_call(func, *args):
return uwsgi_pypy_rpc(node, func, *args)
uwsgi.call = uwsgi_pypy_call
def uwsgi_pypy_uwsgi_signal(signum):
lib.uwsgi_pypy_helper_signal(signum)
uwsgi.signal = uwsgi_pypy_uwsgi_signal
uwsgi.signal = lambda x: lib.uwsgi_signal_send(lib.uwsgi.signal_socket, x)
def uwsgi_pypy_uwsgi_cache_get(key, cache=ffi.NULL):
@@ -387,7 +547,7 @@ def uwsgi_pypy_uwsgi_add_timer(signum, secs):
uwsgi.add_timer = uwsgi_pypy_uwsgi_add_timer
def uwsgi_pypy_uwsgi_add_rb_timer(signum, secs):
if lib.uwsgi_add_rb_timer(signum, secs, 0) < 0:
if lib.uwsgi_signal_add_rb_timer(signum, secs, 0) < 0:
raise Exception("unable to register redblack timer")
uwsgi.add_rb_timer = uwsgi_pypy_uwsgi_add_rb_timer
@@ -397,27 +557,25 @@ def uwsgi_pypy_uwsgi_add_file_monitor(signum, filename):
raise Exception("unable to register file monitor")
uwsgi.add_file_monitor = uwsgi_pypy_uwsgi_add_file_monitor
def uwsgi_pypy_lock(num):
def uwsgi_pypy_lock(num=0):
if lib.uwsgi_user_lock(num) < 0:
raise Exception("invalid lock")
uwsgi.lock = uwsgi_pypy_lock
def uwsgi_pypy_unlock(num):
def uwsgi_pypy_unlock(num=0):
if lib.uwsgi_user_unlock(num) < 0:
raise Exception("invalid lock")
uwsgi.unlock = uwsgi_pypy_unlock
def uwsgi_pypy_masterpid():
return lib.uwsgi_pypy_helper_masterpid()
if lib.uwsgi.master_process:
return lib.uwsgi.workers[0].pid
return 0
uwsgi.masterpid = uwsgi_pypy_masterpid
def uwsgi_pypy_worker_id():
return lib.uwsgi_pypy_helper_worker_id()
uwsgi.worker_id = uwsgi_pypy_worker_id
uwsgi.worker_id = lambda: lib.uwsgi.mywid
def uwsgi_pypy_mule_id():
return lib.uwsgi_pypy_helper_mule_id()
uwsgi.mule_id = uwsgi_pypy_mule_id
uwsgi.mule_id = lambda: lib.uwsgi.muleid
def uwsgi_pypy_signal_registered(signum):
if lib.uwsgi_signal_registered(signum) > 0:
@@ -429,28 +587,24 @@ def uwsgi_pypy_alarm(alarm, msg):
lib.uwsgi_alarm_trigger(ffi.new('char[]', alarm), ffi.new('char[]', msg), len(msg))
uwsgi.alarm = uwsgi_pypy_alarm
def uwsgi_pypy_setprocname(name):
lib.uwsgi_set_processname(ffi.new('char[]',name))
uwsgi.setprocname = uwsgi_pypy_setprocname
uwsgi.setprocname = lambda name: lib.uwsgi_set_processname(ffi.new('char[]', name))
def uwsgi_pypy_add_cron(signum, minute, hour, day, month, week):
if lib.uwsgi_signal_add_cron(signum, minute, hour, day, month, week) < 0:
raise Exception("unable to register cron")
return True
uwsgi.add_cron = uwsgi_pypy_add_cron
"""
populate uwsgi.opt
"""
uwsgi.opt = {}
n_opts = ffi.new('int*')
u_opts = lib.uwsgi_pypy_helper_opts(n_opts)
for i in range(0, n_opts[0]):
k = ffi.string(u_opts[i].key)
if u_opts[i].value == ffi.NULL:
for i in range(0, lib.uwsgi.exported_opts_cnt):
uo = lib.uwsgi.exported_opts[i]
k = ffi.string(uo.key)
if uo.value == ffi.NULL:
v = True
else:
v = ffi.string(u_opts[i].value)
v = ffi.string(uo.value)
if k in uwsgi.opt:
if type(uwsgi.opt[k]) is list:
uwsgi.opt[k].append(v)
@@ -459,5 +613,287 @@ for i in range(0, n_opts[0]):
else:
uwsgi.opt[k] = v
def uwsgi_pypy_current_wsgi_req():
wsgi_req = lib.uwsgi.current_wsgi_req()
if wsgi_req == ffi.NULL:
raise Exception("unable to get current wsgi_request, check your setup !!!")
return wsgi_req
"""
uwsgi.suspend()
"""
def uwsgi_pypy_suspend():
wsgi_req = uwsgi_pypy_current_wsgi_req()
if lib.uwsgi.schedule_to_main:
lib.uwsgi.schedule_to_main(wsgi_req);
uwsgi.suspend = uwsgi_pypy_suspend
"""
uwsgi.workers()
"""
def uwsgi_pypy_workers():
workers = []
for i in range(1, lib.uwsgi.numproc+1):
worker = {}
worker['id'] = lib.uwsgi.workers[i].id
worker['pid'] = lib.uwsgi.workers[i].pid
worker['requests'] = lib.uwsgi.workers[i].requests
worker['delta_requests'] = lib.uwsgi.workers[i].delta_requests
worker['signals'] = lib.uwsgi.workers[i].signals
worker['exceptions'] = lib.uwsgi_worker_exceptions(i);
worker['apps'] = []
if lib.uwsgi.workers[i].cheaped:
worker['status'] == 'cheap'
elif lib.uwsgi.workers[i].suspended and not lib.uwsgi_worker_is_busy(i):
worker['status'] == 'pause'
else:
if lib.uwsgi.workers[i].sig:
worker['status'] = 'sig%d' % lib.uwsgi.workers[i].signum
elif lib.uwsgi_worker_is_busy(i):
worker['status'] = 'busy'
else:
worker['status'] = 'idle'
worker['running_time'] = lib.uwsgi.workers[i].running_time
worker['avg_rt'] = lib.uwsgi.workers[i].avg_response_time
worker['tx'] = lib.uwsgi.workers[i].tx
workers.append(worker)
return workers
uwsgi.workers = uwsgi_pypy_workers
"""
uwsgi.async_sleep(timeout)
"""
def uwsgi_pypy_async_sleep(timeout):
if timeout > 0:
wsgi_req = uwsgi_pypy_current_wsgi_req();
lib.async_add_timeout(wsgi_req, timeout);
uwsgi.async_sleep = uwsgi_pypy_async_sleep
"""
uwsgi.async_connect(addr)
"""
def uwsgi_pypy_async_connect(addr):
fd = lib.uwsgi_connect(ffi.new('char[]', addr), 0, 1)
if fd < 0:
raise Exception("unable to connect to %s" % addr)
return fd
uwsgi.async_connect = uwsgi_pypy_async_connect
uwsgi.connection_fd = lambda: uwsgi_pypy_current_wsgi_req().fd
"""
uwsgi.wait_fd_read(fd, timeout=0)
"""
def uwsgi_pypy_wait_fd_read(fd, timeout=0):
wsgi_req = uwsgi_pypy_current_wsgi_req();
if lib.async_add_fd_read(wsgi_req, fd, timeout) < 0:
raise Exception("unable to add fd %d to the event queue" % fd)
uwsgi.wait_fd_read = uwsgi_pypy_wait_fd_read
"""
uwsgi.wait_fd_write(fd, timeout=0)
"""
def uwsgi_pypy_wait_fd_write(fd, timeout=0):
wsgi_req = uwsgi_pypy_current_wsgi_req();
if lib.async_add_fd_write(wsgi_req, fd, timeout) < 0:
raise Exception("unable to add fd %d to the event queue" % fd)
uwsgi.wait_fd_write = uwsgi_pypy_wait_fd_write
"""
uwsgi.ready_fd()
"""
def uwsgi_pypy_ready_fd():
wsgi_req = uwsgi_pypy_current_wsgi_req();
return lib.uwsgi_ready_fd(wsgi_req)
uwsgi.ready_fd = uwsgi_pypy_ready_fd
"""
uwsgi.send(fd=None,data)
"""
def uwsgi_pypy_send(*args):
if len(args) == 0:
raise ValueError("uwsgi.send() takes at least 1 argument")
elif len(args) == 1:
wsgi_req = uwsgi_pypy_current_wsgi_req();
fd = wsgi_req.fd
data = args[0]
else:
fd = args[0]
data = args[1]
rlen = libc.write(fd, data, len(data))
if rlen <= 0:
raise IOError("unable to send data")
return rlen
uwsgi.send = uwsgi_pypy_send
"""
uwsgi.recv(fd=None,len)
"""
def uwsgi_pypy_recv(*args):
if len(args) == 0:
raise ValueError("uwsgi.recv() takes at least 1 argument")
elif len(args) == 1:
wsgi_req = uwsgi_pypy_current_wsgi_req();
fd = wsgi_req.fd
l = args[0]
else:
fd = args[0]
l = args[1]
data = ffi.new('char[%d]' % l)
rlen = libc.read(fd, data, l)
if rlen <= 0:
raise IOError("unable to receive data")
return ffi.string(data[0:rlen])
uwsgi.recv = uwsgi_pypy_recv
"""
uwsgi.close(fd)
"""
uwsgi.close = lambda fd: lib.close(fd)
"""
uwsgi.disconnect()
"""
uwsgi.disconnect = lambda: lib.uwsgi_disconnect(uwsgi_pypy_current_wsgi_req())
"""
uwsgi.websocket_recv()
"""
def uwsgi_pypy_websocket_recv():
wsgi_req = uwsgi_pypy_current_wsgi_req();
ub = lib.uwsgi_websocket_recv(wsgi_req);
if ub == ffi.NULL:
raise IOError("unable to receive websocket message")
ret = ffi.string(ub.buf, ub.pos)
lib.uwsgi_buffer_destroy(ub)
return ret
uwsgi.websocket_recv = uwsgi_pypy_websocket_recv
"""
uwsgi.websocket_recv_nb()
"""
def uwsgi_pypy_websocket_recv_nb():
wsgi_req = uwsgi_pypy_current_wsgi_req();
ub = lib.uwsgi_websocket_recv_nb(wsgi_req);
if ub == ffi.NULL:
raise IOError("unable to receive websocket message")
ret = ffi.string(ub.buf, ub.pos)
lib.uwsgi_buffer_destroy(ub)
return ret
uwsgi.websocket_recv_nb = uwsgi_pypy_websocket_recv_nb
"""
uwsgi.websocket_handshake(key, origin)
"""
def uwsgi_pypy_websocket_handshake(key, origin=''):
wsgi_req = uwsgi_pypy_current_wsgi_req();
if lib.uwsgi_websocket_handshake(wsgi_req, ffi.new('char[]', key), len(key), ffi.new('char[]',origin), len(origin)) < 0:
raise IOError("unable to complete websocket handshake")
uwsgi.websocket_handshake = uwsgi_pypy_websocket_handshake
"""
uwsgi.websocket_send(msg)
"""
def uwsgi_pypy_websocket_send(msg):
wsgi_req = uwsgi_pypy_current_wsgi_req();
if lib.uwsgi_websocket_send(wsgi_req, ffi.new('char[]', msg), len(msg)) < 0:
raise IOError("unable to send websocket message")
uwsgi.websocket_send = uwsgi_pypy_websocket_send
"""
uwsgi.chunked_read(timeout=0)
"""
def uwsgi_pypy_chunked_read(timeout=0):
wsgi_req = uwsgi_pypy_current_wsgi_req();
rlen = ffi.new("size_t*")
chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, timeout, 0)
if chunk == ffi.NULL:
raise IOError("unable to receive chunked part")
return ffi.string(chunk, rlen[0])
uwsgi.chunked_read = uwsgi_pypy_chunked_read
"""
uwsgi.chunked_read_nb()
"""
def uwsgi_pypy_chunked_read_nb():
wsgi_req = uwsgi_pypy_current_wsgi_req();
rlen = ffi.new("size_t*")
chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, 0, 1)
if chunk == ffi.NULL:
if lib.uwsgi_is_again() > 0:
return None
raise IOError("unable to receive chunked part")
return ffi.string(chunk, rlen[0])
uwsgi.chunked_read_nb = uwsgi_pypy_chunked_read_nb
"""
uwsgi.set_user_harakiri(sec)
"""
uwsgi.set_user_harakiri = lambda x: lib.set_user_harakiri(x)
print "Initialized PyPy with Python", sys.version
print "PyPy Home:", sys.prefix
"""
Continulets support
"""
# this is the dictionary of continulets (one per-core)
uwsgi_pypy_continulets = {}
def uwsgi_pypy_continulet_wrapper(cont):
lib.async_schedule_to_req_green()
@ffi.callback("void()")
def uwsgi_pypy_continulet_schedule():
id = lib.uwsgi.wsgi_req.async_id
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
# generate a new continulet
if not lib.uwsgi.wsgi_req.suspended:
from _continuation import continulet
uwsgi_pypy_continulets[id] = continulet(uwsgi_pypy_continulet_wrapper)
lib.uwsgi.wsgi_req.suspended = 1
# this is called in the main stack
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
# let's switch
uwsgi_pypy_continulets[id].switch()
# back to the main stack
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(ffi.NULL)
@ffi.callback("void(struct wsgi_request *)")
def uwsgi_pypy_continulet_switch(wsgi_req):
id = wsgi_req.async_id
modifier1 = wsgi_req.uh.modifier1;
# this is called in the current continulet
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(wsgi_req)
uwsgi_pypy_continulets[id].switch()
# back to the continulet
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(wsgi_req)
# update current running continulet
lib.uwsgi.wsgi_req = wsgi_req
def uwsgi_pypy_setup_continulets():
if lib.uwsgi.async <= 1:
raise Exception("pypy continulets require async mode !!!")
lib.uwsgi.schedule_to_main = uwsgi_pypy_continulet_switch
lib.uwsgi.schedule_to_req = uwsgi_pypy_continulet_schedule
print "*** PyPy Continulets engine loaded ***"
+6 -1
View File
@@ -1756,7 +1756,12 @@ void uwsgi_python_harakiri(int wid) {
}
}
/*
# you can use this logger to offload logging to python
# be sure to configure it to not log to stderr otherwise you will generate a loop
import logging
logging.basicConfig(filename='/tmp/pippo.log')
*/
ssize_t uwsgi_python_logger(struct uwsgi_logger *ul, char *message, size_t len) {
if (!Py_IsInitialized()) return -1;
+48 -9
View File
@@ -1063,6 +1063,42 @@ PyObject *py_uwsgi_websocket_send(PyObject * self, PyObject * args) {
return Py_None;
}
PyObject *py_uwsgi_chunked_read(PyObject * self, PyObject * args) {
int timeout = 0;
if (!PyArg_ParseTuple(args, "|i:chunked_read", &timeout)) {
return NULL;
}
size_t len = 0;
struct wsgi_request *wsgi_req = py_current_wsgi_req();
UWSGI_RELEASE_GIL
char *chunk = uwsgi_chunked_read(wsgi_req, &len, timeout, 0);
UWSGI_GET_GIL
if (!chunk) {
return PyErr_Format(PyExc_IOError, "unable to receive chunked part");
}
return PyString_FromStringAndSize(chunk, len);
}
PyObject *py_uwsgi_chunked_read_nb(PyObject * self, PyObject * args) {
size_t len = 0;
struct wsgi_request *wsgi_req = py_current_wsgi_req();
UWSGI_RELEASE_GIL
char *chunk = uwsgi_chunked_read(wsgi_req, &len, 0, 1);
UWSGI_GET_GIL
if (!chunk) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
Py_INCREF(Py_None);
return Py_None;
}
return PyErr_Format(PyExc_IOError, "unable to receive chunked part");
}
return PyString_FromStringAndSize(chunk, len);
}
PyObject *py_uwsgi_websocket_recv(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
UWSGI_RELEASE_GIL
@@ -2234,17 +2270,15 @@ PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
#ifdef UWSGI_DEBUG
uwsgi_log("disconnecting worker %d (pid :%d) from session...\n", uwsgi.mywid, uwsgi.mypid);
#endif
uwsgi_disconnect(wsgi_req);
if (wsgi_req->socket) {
wsgi_req->socket->proto_close(wsgi_req);
}
wsgi_req->fd_closed = 1;
Py_INCREF(Py_None);
return Py_None;
}
Py_INCREF(Py_True);
return Py_True;
PyObject *py_uwsgi_ready_fd(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
return PyInt_FromLong(uwsgi_ready_fd(wsgi_req));
}
PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
@@ -2484,6 +2518,11 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"websocket_send", py_uwsgi_websocket_send, METH_VARARGS, ""},
{"websocket_handshake", py_uwsgi_websocket_handshake, METH_VARARGS, ""},
{"chunked_read", py_uwsgi_chunked_read, METH_VARARGS, ""},
{"chunked_read_nb", py_uwsgi_chunked_read_nb, METH_VARARGS, ""},
{"ready_fd", py_uwsgi_ready_fd, METH_VARARGS, ""},
{NULL, NULL},
};
+60 -51
View File
@@ -7,7 +7,7 @@ extern struct uwsgi_plugin rack_plugin;
#define uwsgi_rack_api(x, y, z) rb_define_module_function(rb_uwsgi_embedded, x, y, z)
VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
static VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
Check_Type(rbmessage, T_STRING);
char *message = RSTRING_PTR(rbmessage);
@@ -26,7 +26,14 @@ VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
return Qnil;
}
VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
static VALUE rack_uwsgi_user_harakiri(VALUE *class, VALUE sec) {
Check_Type(sec, T_FIXNUM);
set_user_harakiri(NUM2INT(sec));
return Qnil;
}
static VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
Check_Type(msg, T_STRING);
@@ -35,7 +42,7 @@ VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
return Qnil;
}
VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
static VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
if (uwsgi.i_am_a_spooler) {
return Qtrue;
}
@@ -43,7 +50,7 @@ VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
}
#ifdef UWSGI_SSL
VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
static VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
Check_Type(legion_name, T_STRING);
if (uwsgi_legion_i_am_the_lord(RSTRING_PTR(legion_name))) {
return Qtrue;
@@ -54,7 +61,7 @@ VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
static VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
Check_Type(rbname, T_STRING);
char *name = RSTRING_PTR(rbname);
@@ -63,7 +70,7 @@ VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
return Qnil;
}
VALUE rack_uwsgi_mem(VALUE *class) {
static VALUE rack_uwsgi_mem(VALUE *class) {
uint64_t rss=0, vsz = 0;
VALUE ml = rb_ary_new2(2);
@@ -77,23 +84,23 @@ VALUE rack_uwsgi_mem(VALUE *class) {
}
VALUE rack_uwsgi_request_id(VALUE *class) {
static VALUE rack_uwsgi_request_id(VALUE *class) {
return ULONG2NUM(uwsgi.workers[uwsgi.mywid].requests);
}
VALUE rack_uwsgi_worker_id(VALUE *class) {
static VALUE rack_uwsgi_worker_id(VALUE *class) {
return INT2NUM(uwsgi.mywid);
}
VALUE rack_uwsgi_mule_id(VALUE *class) {
static VALUE rack_uwsgi_mule_id(VALUE *class) {
return INT2NUM(uwsgi.muleid);
}
VALUE rack_uwsgi_logsize(VALUE *class) {
static VALUE rack_uwsgi_logsize(VALUE *class) {
return ULONG2NUM(uwsgi.shared->logsize);
}
VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
int fd = -1;
int mule_id = -1;
@@ -151,7 +158,7 @@ VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
static int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
Check_Type(key, T_SYMBOL);
ID key_id = SYM2ID(key);
const char *key_name = rb_id2name(key_id);
@@ -172,7 +179,7 @@ int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
return 0;
}
VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
int manage_signals = 1;
int manage_farms = 1;
@@ -228,7 +235,7 @@ VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
}
VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
int lock_num = 0;
@@ -246,7 +253,7 @@ VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
return Qnil;
}
VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
int lock_num = 0;
@@ -268,7 +275,7 @@ VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
VALUE rack_uwsgi_cache_set(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_set(int argc, VALUE *argv, VALUE *class) {
if (argc < 2) goto error;
@@ -304,7 +311,7 @@ error:
}
VALUE rack_uwsgi_cache_update(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_update(int argc, VALUE *argv, VALUE *class) {
if (argc < 2) goto error;
@@ -341,7 +348,7 @@ error:
}
VALUE rack_uwsgi_cache_set_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_set_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_set(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to set value in uWSGI cache");
@@ -349,7 +356,7 @@ VALUE rack_uwsgi_cache_set_exc(int argc, VALUE *argv, VALUE *class) {
return ret;
}
VALUE rack_uwsgi_cache_update_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_update_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_update(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to update value in uWSGI cache");
@@ -357,7 +364,7 @@ VALUE rack_uwsgi_cache_update_exc(int argc, VALUE *argv, VALUE *class) {
return ret;
}
VALUE rack_uwsgi_cache_del(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_del(int argc, VALUE *argv, VALUE *class) {
if (argc == 0) goto error;
@@ -383,7 +390,7 @@ error:
return Qnil;
}
VALUE rack_uwsgi_cache_del_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_del_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_del(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to delete object from uWSGI cache");
@@ -393,7 +400,7 @@ VALUE rack_uwsgi_cache_del_exc(int argc, VALUE *argv, VALUE *class) {
VALUE rack_uwsgi_cache_exists(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_exists(int argc, VALUE *argv, VALUE *class) {
if (argc == 0) goto error;
@@ -421,7 +428,7 @@ error:
VALUE rack_uwsgi_cache_clear(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_clear(int argc, VALUE *argv, VALUE *class) {
char *cache = NULL;
@@ -437,7 +444,7 @@ VALUE rack_uwsgi_cache_clear(int argc, VALUE *argv, VALUE *class) {
return Qnil;
}
VALUE rack_uwsgi_cache_clear_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_clear_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_clear(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to clear the uWSGI cache");
@@ -447,7 +454,7 @@ VALUE rack_uwsgi_cache_clear_exc(int argc, VALUE *argv, VALUE *class) {
VALUE rack_uwsgi_cache_get(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_get(int argc, VALUE *argv, VALUE *class) {
if (argc == 0) goto error;
@@ -477,7 +484,7 @@ error:
}
VALUE rack_uwsgi_cache_get_exc(int argc, VALUE *argv, VALUE *class) {
static VALUE rack_uwsgi_cache_get_exc(int argc, VALUE *argv, VALUE *class) {
VALUE ret = rack_uwsgi_cache_get(argc, argv, class);
if (ret == Qnil) {
rb_raise(rb_eRuntimeError, "unable to get value from uWSGI cache");
@@ -488,7 +495,7 @@ VALUE rack_uwsgi_cache_get_exc(int argc, VALUE *argv, VALUE *class) {
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
static VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(rbmin, T_FIXNUM);
@@ -514,7 +521,7 @@ VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhou
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
static VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(secs, T_FIXNUM);
@@ -532,7 +539,7 @@ VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
static VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(secs, T_FIXNUM);
@@ -550,7 +557,7 @@ VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
}
VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) {
static VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) {
Check_Type(alarm, T_STRING);
Check_Type(msg, T_STRING);
@@ -560,7 +567,7 @@ VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) {
return Qnil;
}
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
static VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
Check_Type(rbsignum, T_FIXNUM);
Check_Type(rbfilename, T_STRING);
@@ -577,7 +584,7 @@ VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename
}
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
static VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
Check_Type(arg1, T_FIXNUM);
Check_Type(arg2, T_FIXNUM);
@@ -595,7 +602,7 @@ VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
return Qtrue;
}
VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
static VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
Check_Type(arg1, T_FIXNUM);
Check_Type(arg2, T_FIXNUM);
@@ -612,7 +619,7 @@ VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
return Qtrue;
}
VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
static VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
Check_Type(arg, T_STRING);
@@ -622,7 +629,7 @@ VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
}
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
static VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
Check_Type(arg, T_FIXNUM);
@@ -636,7 +643,7 @@ VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
return Qtrue;
}
VALUE uwsgi_ruby_masterpid(VALUE *class) {
static VALUE uwsgi_ruby_masterpid(VALUE *class) {
if (uwsgi.master_process) {
return INT2NUM(uwsgi.workers[0].pid);
@@ -644,7 +651,7 @@ VALUE uwsgi_ruby_masterpid(VALUE *class) {
return INT2NUM(0);
}
VALUE uwsgi_ruby_suspend(VALUE *class) {
static VALUE uwsgi_ruby_suspend(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -655,7 +662,7 @@ VALUE uwsgi_ruby_suspend(VALUE *class) {
}
VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
static VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
int wait_for_specific_signal = 0;
@@ -687,7 +694,7 @@ VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
return Qnil;
}
VALUE uwsgi_ruby_signal_received(VALUE *class) {
static VALUE uwsgi_ruby_signal_received(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -695,7 +702,7 @@ VALUE uwsgi_ruby_signal_received(VALUE *class) {
}
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
static VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
Check_Type(signum, T_FIXNUM);
@@ -708,7 +715,7 @@ VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
return Qfalse;
}
VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
static VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
char *node = NULL, *func;
uint16_t size = 0;
@@ -759,7 +766,7 @@ clear:
return Qnil;
}
VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
static VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
int rb_argc = 0;
@@ -785,7 +792,7 @@ clear:
return Qtrue;
}
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
static VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
Check_Type(signum, T_FIXNUM);
Check_Type(sigkind, T_STRING);
@@ -805,7 +812,7 @@ VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALU
}
VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
static VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
if (argc < 1) {
rb_raise(rb_eRuntimeError, "you have to specify a signum");
@@ -872,7 +879,7 @@ int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
}
VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
static VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
char spool_filename[1024];
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -926,10 +933,10 @@ VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
rb_hash_foreach(args, rack_uwsgi_build_spool, (VALUE) argv);
if (numprio) {
priority = uwsgi_num2str(numprio);
priority = uwsgi_num2str((int)numprio);
}
int ret = spool_request(uwsgi.spoolers, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, argv[0] - spool_buffer, priority, at, body, body_len);
int ret = spool_request(uwsgi.spoolers, spool_filename, (int)(uwsgi.workers[0].requests + 1), wsgi_req->async_id, spool_buffer, (int)(argv[0] - spool_buffer), priority, at, body, body_len);
if (priority) {
free(priority);
@@ -950,7 +957,7 @@ VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
}
VALUE uwsgi_ruby_websocket_handshake(int argc, VALUE *argv, VALUE *class) {
static VALUE uwsgi_ruby_websocket_handshake(int argc, VALUE *argv, VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -978,7 +985,7 @@ VALUE uwsgi_ruby_websocket_handshake(int argc, VALUE *argv, VALUE *class) {
return Qnil;
}
VALUE uwsgi_ruby_websocket_send(VALUE *class, VALUE *msg) {
static VALUE uwsgi_ruby_websocket_send(VALUE *class, VALUE *msg) {
Check_Type(msg, T_STRING);
char *message = RSTRING_PTR(msg);
size_t message_len = RSTRING_LEN(msg);
@@ -989,7 +996,7 @@ VALUE uwsgi_ruby_websocket_send(VALUE *class, VALUE *msg) {
return Qnil;
}
VALUE uwsgi_ruby_websocket_recv(VALUE *class) {
static VALUE uwsgi_ruby_websocket_recv(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_buffer *ub = uwsgi_websocket_recv(wsgi_req);
@@ -1003,7 +1010,7 @@ VALUE uwsgi_ruby_websocket_recv(VALUE *class) {
}
VALUE uwsgi_ruby_websocket_recv_nb(VALUE *class) {
static VALUE uwsgi_ruby_websocket_recv_nb(VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_buffer *ub = uwsgi_websocket_recv_nb(wsgi_req);
@@ -1069,6 +1076,8 @@ void uwsgi_rack_init_api() {
uwsgi_rack_api("set_warning_message", rack_uwsgi_warning, 1);
uwsgi_rack_api("set_user_harakiri", rack_uwsgi_user_harakiri, 1);
uwsgi_rack_api("rpc", uwsgi_ruby_do_rpc, -1);
+4 -4
View File
@@ -141,13 +141,13 @@ static struct uwsgi_buffer *uwsgi_ruby_backtrace(struct wsgi_request *wsgi_req)
// ok let's start the C dance to parse the backtrace
char *colon = strchr(bt, ':');
if (!colon) continue;
filename = uwsgi_concat2n(bt, colon-bt, "", 0);
filename = uwsgi_concat2n(bt, (int) (colon-bt), "", 0);
uint16_t filename_len = colon-bt;
colon++; if (*colon == 0) goto error;
char *lineno_ptr = colon;
colon = strchr(lineno_ptr, ':');
if (!colon) goto error;
int64_t lineno = uwsgi_str_num(lineno_ptr, colon-lineno_ptr);
int64_t lineno = uwsgi_str_num(lineno_ptr, (int) (colon-lineno_ptr));
colon++; if (*colon == 0) goto error;
colon = strchr(lineno_ptr, '`');
if (!colon) goto error;
@@ -155,7 +155,7 @@ static struct uwsgi_buffer *uwsgi_ruby_backtrace(struct wsgi_request *wsgi_req)
char *function_ptr = colon;
char *function_end = strchr(function_ptr, '\'');
if (!function_end) goto error;
function = uwsgi_concat2n(function_ptr, function_end-function_ptr, "", 0);
function = uwsgi_concat2n(function_ptr, (int) (function_end-function_ptr), "", 0);
uint16_t function_len = function_end-function_ptr;
if (uwsgi_buffer_u16le(ub, filename_len)) goto error;
@@ -312,7 +312,7 @@ VALUE init_rack_app(VALUE);
VALUE rack_call_rpc_handler(VALUE args) {
VALUE rpc_args = rb_ary_entry(args, 1);
return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args));
return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), (int) RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args));
}
+6 -4
View File
@@ -112,13 +112,15 @@ static ssize_t rr_xclient_write(struct corerouter_peer *peer) {
if (!len) return 0;
if (cr_write_complete_buf(peer, rr->xclient)) {
if (peer->session->main_peer->out) {
if (peer->session->main_peer->out_pos > 0) {
// (eventually) send previous data
peer->last_hook_read = rr_instance_read;
cr_write_to_main(peer, rr_write);
}
else {
// reset to standard behaviour
cr_reset_hooks(peer);
peer->in->pos = 0;
cr_reset_hooks_and_read(peer, rr_instance_read);
}
}
@@ -140,10 +142,10 @@ static ssize_t rr_xclient_read(struct corerouter_peer *peer) {
return -1;
}
// banner received (skip it, will be sent later)
size_t remains = peer->in->pos - (len - (i+1));
size_t remains = len - (i+1);
if (remains > 0) {
peer->session->main_peer->out = peer->in;
peer->session->main_peer->out_pos = remains;
peer->session->main_peer->out_pos = (peer->in->pos - remains) ;
}
cr_write_to_backend(peer, rr_xclient_write);
return len;
-1
View File
@@ -193,7 +193,6 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_
if (wsgi_req->socket->can_offload && !ur->custom && !urcc->no_offload) {
if (!uwsgi_offload_request_memory_do(wsgi_req, value, valsize)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->status = 202;
return UWSGI_ROUTE_BREAK;
}
}
+146
View File
@@ -0,0 +1,146 @@
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
extern struct uwsgi_server uwsgi;
/*
by Unbit
syntax:
route = /^foobar1(.*)/ hash:key=foo$1poo,algo=murmur2,var=MYHASH,items=node1;node2;node3
*/
struct uwsgi_router_hash_conf {
char *key;
size_t key_len;
char *var;
size_t var_len;
char *algo;
char *items;
size_t items_len;
};
static int uwsgi_routing_func_hash(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_hash_conf *urhc = (struct uwsgi_router_hash_conf *) ur->data2;
struct uwsgi_hash_algo *uha = uwsgi_hash_algo_get(urhc->algo);
if (!uha) {
uwsgi_log("[uwsgi-hash-router] unable to find hash algo \"%s\"\n", urhc->algo);
return UWSGI_ROUTE_BREAK;
}
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urhc->key, urhc->key_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uint32_t h = uha->func(ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
// now count the number of items
uint32_t items = 1;
size_t i, ilen = urhc->items_len;
for(i=0;i<ilen;i++) {
if (urhc->items[i] == ';') items++;
}
// skip last semicolon
if (urhc->items[ilen-1] == ';') items--;
uint32_t hashed_result = h % items;
uint32_t found = 0;
char *value = urhc->items;
uint16_t vallen = 0;
for(i=0;i<ilen;i++) {
if (!value) {
value = urhc->items + i;
}
if (urhc->items[i] == ';') {
if (found == hashed_result) {
vallen = (urhc->items+i) - value;
break;
}
value = NULL;
found++;
}
}
if (vallen == 0) {
// first item
if (hashed_result == 0) {
value = urhc->items;
vallen = urhc->items_len;
}
// last item
else {
vallen = (urhc->items + urhc->items_len) - value;
}
}
if (!vallen) {
uwsgi_log("[uwsgi-hash-router] BUG !!! unable to hash items\n");
return UWSGI_ROUTE_BREAK;
}
if (!uwsgi_req_append(wsgi_req, urhc->var, urhc->var_len, value, vallen)) {
uwsgi_log("[uwsgi-hash-router] unable to append hash var to the request\n");
return UWSGI_ROUTE_BREAK;
}
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_hash(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_hash;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_hash_conf *urhc = uwsgi_calloc(sizeof(struct uwsgi_router_hash_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"key", &urhc->key,
"var", &urhc->var,
"algo", &urhc->algo,
"items", &urhc->items,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (!urhc->key || !urhc->var || !urhc->items) {
uwsgi_log("invalid route syntax: you need to specify a hash key, a var and a set of items\n");
exit(1);
}
urhc->key_len = strlen(urhc->key);
urhc->var_len = strlen(urhc->var);
urhc->items_len = strlen(urhc->items);
if (!urhc->algo) urhc->algo = "djb33x";
ur->data2 = urhc;
return 0;
}
static void router_hash_register() {
uwsgi_register_router("hash", uwsgi_router_hash);
}
struct uwsgi_plugin router_hash_plugin = {
.name = "router_hash",
.on_load = router_hash_register,
};
#else
struct uwsgi_plugin router_hash_plugin = {
.name = "router_hash",
};
#endif
+6
View File
@@ -0,0 +1,6 @@
NAME='router_hash'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['router_hash']
+174 -33
View File
@@ -1,20 +1,24 @@
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
#define MEMCACHED_BUFSIZE 8192
extern struct uwsgi_server uwsgi;
/*
memcached internal router
memcached internal router and transformation
route = /^foobar1(.*)/ memcached:addr=127.0.0.1:11211,key=foo$1poo,type=body
route = /^foobar1(.*)/ memcached:addr=127.0.0.1:11211,key=foo$1poo
route = /^foobar1(.*)/ memcachedstore:addr=127.0.0.1:11211,key=foo$1poo
*/
struct uwsgi_router_memcached_conf {
char *addr;
size_t addr_len;
char *key;
size_t key_len;
@@ -22,12 +26,19 @@ struct uwsgi_router_memcached_conf {
char *content_type;
size_t content_type_len;
// 0 -> full, 1 -> body
char *type;
int type_num;
char *no_offload;
char *expires;
};
// this is allocated for each transformation
struct uwsgi_transformation_memcached_conf {
struct uwsgi_buffer *addr;
struct uwsgi_buffer *key;
char *expires;
};
static size_t memcached_firstline_parse(char *buf, size_t len) {
// check for "VALUE x 0 0"
if (len < 11) return 0;
@@ -48,6 +59,86 @@ static size_t memcached_firstline_parse(char *buf, size_t len) {
}
}
// store an item in memcached
static void memcached_store(char *addr, struct uwsgi_buffer *key, struct uwsgi_buffer *value, char *expires) {
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
int fd = uwsgi_connect(addr, 0, 1);
if (fd < 0) return;
// wait for connection
int ret = uwsgi.wait_write_hook(fd, timeout);
if (ret <= 0) goto end;
// build the request
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
if (uwsgi_buffer_append(ub, "set ", 4)) goto end2;
if (uwsgi_buffer_append(ub, key->buf, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, " 0 " , 3)) goto end2;
if (uwsgi_buffer_append(ub, expires, strlen(expires))) goto end2;
if (uwsgi_buffer_append(ub, " " , 1)) goto end2;
if (uwsgi_buffer_num64(ub, value->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto end2;
if (uwsgi_write_true_nb(fd, value->buf, value->pos, timeout)) goto end2;
if (uwsgi_write_true_nb(fd, "\r\n", 2, timeout)) goto end2;
// we are not interested in command result... (ugly but it works)
end2:
uwsgi_buffer_destroy(ub);
end:
close(fd);
}
static int transform_memcached(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
struct uwsgi_transformation_memcached_conf *utmc = (struct uwsgi_transformation_memcached_conf *) ut->data;
struct uwsgi_buffer *ub = ut->chunk;
// store only successfull response
if (wsgi_req->write_errors == 0 && wsgi_req->status == 200 && ub->pos > 0) {
memcached_store(utmc->addr->buf, utmc->key, ub, utmc->expires);
}
// free resources
uwsgi_buffer_destroy(utmc->key);
uwsgi_buffer_destroy(utmc->addr);
free(utmc);
return 0;
}
// be tolerant on errors
static int uwsgi_routing_func_memcached_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_memcached_conf *urmc = (struct uwsgi_router_memcached_conf *) ur->data2;
struct uwsgi_transformation_memcached_conf *utmc = uwsgi_calloc(sizeof(struct uwsgi_transformation_memcached_conf));
// build key and name
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
utmc->key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->key, urmc->key_len);
if (!utmc->key) goto error;
utmc->addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->addr, urmc->addr_len);
if (!utmc->addr) goto error;
utmc->expires = urmc->expires;
uwsgi_add_transformation(wsgi_req, transform_memcached, utmc);
return UWSGI_ROUTE_NEXT;
error:
if (utmc->key) uwsgi_buffer_destroy(utmc->key);
if (utmc->addr) uwsgi_buffer_destroy(utmc->addr);
free(utmc);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
// this is the buffer for the memcached response
char buf[MEMCACHED_BUFSIZE];
@@ -62,13 +153,24 @@ static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uw
struct uwsgi_buffer *ub_key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->key, urmc->key_len);
if (!ub_key) return UWSGI_ROUTE_BREAK;
int fd = uwsgi_connect(urmc->addr, 0, 1);
if (fd < 0) { uwsgi_buffer_destroy(ub_key) ; goto end; }
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->addr, urmc->addr_len);
if (!ub_addr) {
uwsgi_buffer_destroy(ub_key);
return UWSGI_ROUTE_BREAK;
}
int fd = uwsgi_connect(ub_addr->buf, 0, 1);
if (fd < 0) {
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
goto end;
}
// wait for connection;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
uwsgi_buffer_destroy(ub_key) ;
uwsgi_buffer_destroy(ub_addr);
close(fd);
goto end;
}
@@ -77,11 +179,13 @@ static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uw
char *cmd = uwsgi_concat3n("get ", 4, ub_key->buf, ub_key->pos, "\r\n", 2);
if (uwsgi_write_true_nb(fd, cmd, 6+ub_key->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
free(cmd);
close(fd);
goto end;
}
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
free(cmd);
// ok, start reading the response...
@@ -130,26 +234,34 @@ read:
goto end;
}
if (urmc->type_num == 1) {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) { close(fd); goto end; }
if (uwsgi_response_add_content_type(wsgi_req, urmc->content_type, urmc->content_type_len)) { close(fd); goto end; }
if (uwsgi_response_add_content_length(wsgi_req, response_size)) { close(fd); goto end; }
}
// from now on, every error will trigger a BREAK...
// send headers
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
if (uwsgi_response_add_content_type(wsgi_req, urmc->content_type, urmc->content_type_len)) goto error;
if (uwsgi_response_add_content_length(wsgi_req, response_size)) goto error;
// the first chunk could already contains part of the body
size_t remains = pos-(found+2);
if (remains >= response_size) {
uwsgi_response_write_body_do(wsgi_req, buf+found+2, response_size);
close(fd);
goto end;
goto done;
}
// send what we have
if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) {
close(fd);
goto end;
}
if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) goto error;
// and now start reading til the output is consumed
response_size -= remains;
// try to offload via the pipe engine
if (wsgi_req->socket->can_offload && !ur->custom && !urmc->no_offload) {
if (!uwsgi_offload_request_pipe_do(wsgi_req, fd, response_size)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
return UWSGI_ROUTE_BREAK;
}
}
while(response_size > 0) {
ssize_t len = read(fd, buf, UMIN(MEMCACHED_BUFSIZE, response_size));
if (len > 0) goto write;
@@ -165,23 +277,22 @@ wait2:
}
goto error;
write:
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) {
goto error;
}
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) goto error;
response_size -= len;
}
done:
close(fd);
if (ur->custom)
return UWSGI_ROUTE_NEXT;
return UWSGI_ROUTE_BREAK;
error:
close(fd);
return UWSGI_ROUTE_BREAK;
end:
if (ur->custom)
return UWSGI_ROUTE_NEXT;
return UWSGI_ROUTE_BREAK;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_memcached(struct uwsgi_route *ur, char *args) {
@@ -193,27 +304,23 @@ static int uwsgi_router_memcached(struct uwsgi_route *ur, char *args) {
"addr", &urmc->addr,
"key", &urmc->key,
"content_type", &urmc->content_type,
"type", &urmc->type, NULL)) {
"no_offload", &urmc->no_offload,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (!urmc->key || !urmc->addr) {
uwsgi_log("invalid route syntax: you need to specify a memcached address and key pattern\n");
exit(1);
return -1;
}
urmc->key_len = strlen(urmc->key);
urmc->addr_len = strlen(urmc->addr);
if (!urmc->type) urmc->type = "full";
if (!urmc->content_type) urmc->content_type = "text/html";
urmc->content_type_len = strlen(urmc->content_type);
if (!strcmp(urmc->type, "body")) {
urmc->type_num = 1;
}
ur->data2 = urmc;
return 0;
}
@@ -224,12 +331,46 @@ static int uwsgi_router_memcached_continue(struct uwsgi_route *ur, char *args) {
return 0;
}
static int uwsgi_router_memcached_store(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_memcached_store;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_memcached_conf *urmc = uwsgi_calloc(sizeof(struct uwsgi_router_memcached_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"addr", &urmc->addr,
"key", &urmc->key,
"expires", &urmc->expires, NULL)) {
uwsgi_log("invalid memcachedstore route syntax: %s\n", args);
return -1;
}
if (!urmc->key || !urmc->addr) {
uwsgi_log("invalid memcachedstore route syntax: you need to specify an address and a key\n");
return -1;
}
urmc->key_len = strlen(urmc->key);
urmc->addr_len = strlen(urmc->addr);
if (!urmc->expires) urmc->expires = "0";
ur->data2 = urmc;
return 0;
}
static void router_memcached_register() {
uwsgi_register_router("memcached", uwsgi_router_memcached);
uwsgi_register_router("memcached-continue", uwsgi_router_memcached_continue);
uwsgi_register_router("memcachedstore", uwsgi_router_memcached_store);
uwsgi_register_router("memcached-store", uwsgi_router_memcached_store);
}
#endif
struct uwsgi_plugin router_memcached_plugin = {
.name = "router_memcached",
#ifdef UWSGI_ROUTING
.on_load = router_memcached_register,
#endif
};
+374
View File
@@ -0,0 +1,374 @@
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
#define REDIS_BUFSIZE 8192
extern struct uwsgi_server uwsgi;
/*
redis internal router and transformation
route = /^foobar1(.*)/ redis:addr=127.0.0.1:11211,key=foo$1poo
route = /^foobar1(.*)/ redisstore:addr=127.0.0.1:11211,key=foo$1poo
*/
struct uwsgi_router_redis_conf {
char *addr;
size_t addr_len;
char *key;
size_t key_len;
char *content_type;
size_t content_type_len;
char *no_offload;
char *expires;
};
// this is allocated for each transformation
struct uwsgi_transformation_redis_conf {
struct uwsgi_buffer *addr;
struct uwsgi_buffer *key;
char *expires;
};
static size_t redis_firstline_parse(char *buf, size_t len) {
// check for "$0"
if (len < 2) return 0;
if (buf[0] != '$') return 0;
if (buf[1] == '-') return 0;
return uwsgi_str_num(buf + 1, len - 1);
}
// store an item in redis
static void redis_store(char *addr, struct uwsgi_buffer *key, struct uwsgi_buffer *value, char *expires) {
int timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
int fd = uwsgi_connect(addr, 0, 1);
if (fd < 0) return;
// wait for connection
int ret = uwsgi.wait_write_hook(fd, timeout);
if (ret <= 0) goto end;
// build the request
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
if (uwsgi_buffer_append(ub, "*3\r\n$3\r\nSET\r\n$", 14)) goto end2;
if (uwsgi_buffer_num64(ub, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_buffer_append(ub, key->buf, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n$" , 3)) goto end2;
if (uwsgi_buffer_num64(ub, value->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto end2;
if (uwsgi_write_true_nb(fd, value->buf, value->pos, timeout)) goto end2;
ub->pos = 0;
if (strcmp(expires, "0")) {
if (uwsgi_buffer_append(ub, "\r\n*3\r\n$6\r\nEXPIRE\r\n$" , 19)) goto end2;
if (uwsgi_buffer_num64(ub, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_buffer_append(ub, key->buf, key->pos)) goto end2;
if (uwsgi_buffer_append(ub, "\r\n$" , 3)) goto end2;
if (uwsgi_buffer_num64(ub, strlen(expires))) goto end2;
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_buffer_append(ub, expires, strlen(expires))) goto end2;
}
if (uwsgi_buffer_append(ub, "\r\n" , 2)) goto end2;
if (uwsgi_write_true_nb(fd, ub->buf, ub->pos, timeout)) goto end2;
// we are not interested in command result... (ugly but it works)
end2:
uwsgi_buffer_destroy(ub);
end:
close(fd);
}
static int transform_redis(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
struct uwsgi_transformation_redis_conf *utrc = (struct uwsgi_transformation_redis_conf *) ut->data;
struct uwsgi_buffer *ub = ut->chunk;
// store only successfull response
if (wsgi_req->write_errors == 0 && wsgi_req->status == 200 && ub->pos > 0) {
redis_store(utrc->addr->buf, utrc->key, ub, utrc->expires);
}
// free resources
uwsgi_buffer_destroy(utrc->key);
uwsgi_buffer_destroy(utrc->addr);
free(utrc);
return 0;
}
// be tolerant on errors
static int uwsgi_routing_func_redis_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_redis_conf *urrc = (struct uwsgi_router_redis_conf *) ur->data2;
struct uwsgi_transformation_redis_conf *utrc = uwsgi_calloc(sizeof(struct uwsgi_transformation_redis_conf));
// build key and name
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
utrc->key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->key, urrc->key_len);
if (!utrc->key) goto error;
utrc->addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->addr, urrc->addr_len);
if (!utrc->addr) goto error;
utrc->expires = urrc->expires;
uwsgi_add_transformation(wsgi_req, transform_redis, utrc);
return UWSGI_ROUTE_NEXT;
error:
if (utrc->key) uwsgi_buffer_destroy(utrc->key);
if (utrc->addr) uwsgi_buffer_destroy(utrc->addr);
free(utrc);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_routing_func_redis(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
// this is the buffer for the redis response
char buf[REDIS_BUFSIZE];
size_t i;
char last_char = 0;
struct uwsgi_router_redis_conf *urrc = (struct uwsgi_router_redis_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->key, urrc->key_len);
if (!ub_key) return UWSGI_ROUTE_BREAK;
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urrc->addr, urrc->addr_len);
if (!ub_addr) {
uwsgi_buffer_destroy(ub_key);
return UWSGI_ROUTE_BREAK;
}
int fd = uwsgi_connect(ub_addr->buf, 0, 1);
if (fd < 0) {
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
goto end;
}
// wait for connection;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
uwsgi_buffer_destroy(ub_key) ;
uwsgi_buffer_destroy(ub_addr);
close(fd);
goto end;
}
// build the request and send it
char *cmd = uwsgi_concat3n("get ", 4, ub_key->buf, ub_key->pos, "\r\n", 2);
if (uwsgi_write_true_nb(fd, cmd, 6+ub_key->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
free(cmd);
close(fd);
goto end;
}
uwsgi_buffer_destroy(ub_key);
uwsgi_buffer_destroy(ub_addr);
free(cmd);
// ok, start reading the response...
// first we need to get a full line;
size_t found = 0;
size_t pos = 0;
for(;;) {
ssize_t len = read(fd, buf + pos, REDIS_BUFSIZE - pos);
if (len > 0) {
pos += len;
goto read;
}
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
}
close(fd);
goto end;
wait:
ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
// when we have a chunk try to read the first line
if (ret > 0) {
len = read(fd, buf + pos, REDIS_BUFSIZE - pos);
if (len > 0) {
pos += len;
goto read;
}
}
close(fd);
goto end;
read:
for(i=0;i<pos;i++) {
if (last_char == '\r' && buf[i] == '\n') {
found = i-1;
break;
}
last_char = buf[i];
}
if (found) break;
}
// ok parse the first line
size_t response_size = redis_firstline_parse(buf, found);
if (response_size == 0) {
close(fd);
goto end;
}
// from now on, every error will trigger a BREAK...
// send headers
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
if (uwsgi_response_add_content_type(wsgi_req, urrc->content_type, urrc->content_type_len)) goto error;
if (uwsgi_response_add_content_length(wsgi_req, response_size)) goto error;
// the first chunk could already contains part of the body
size_t remains = pos-(found+2);
if (remains >= response_size) {
uwsgi_response_write_body_do(wsgi_req, buf+found+2, response_size);
goto done;
}
// send what we have
if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) goto error;
// and now start reading til the output is consumed
response_size -= remains;
// try to offload via the pipe engine
if (wsgi_req->socket->can_offload && !ur->custom && !urrc->no_offload) {
if (!uwsgi_offload_request_pipe_do(wsgi_req, fd, response_size)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
return UWSGI_ROUTE_BREAK;
}
}
while(response_size > 0) {
ssize_t len = read(fd, buf, UMIN(REDIS_BUFSIZE, response_size));
if (len > 0) goto write;
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2;
}
goto error;
wait2:
ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret > 0) {
len = read(fd, buf, UMIN(REDIS_BUFSIZE, response_size));
if (len > 0) goto write;
}
goto error;
write:
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) goto error;
response_size -= len;
}
done:
close(fd);
if (ur->custom)
return UWSGI_ROUTE_NEXT;
return UWSGI_ROUTE_BREAK;
error:
close(fd);
return UWSGI_ROUTE_BREAK;
end:
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_redis(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_redis;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_redis_conf *urrc = uwsgi_calloc(sizeof(struct uwsgi_router_redis_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"addr", &urrc->addr,
"key", &urrc->key,
"content_type", &urrc->content_type,
"no_offload", &urrc->no_offload,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (!urrc->key || !urrc->addr) {
uwsgi_log("invalid route syntax: you need to specify a redis address and key pattern\n");
return -1;
}
urrc->key_len = strlen(urrc->key);
urrc->addr_len = strlen(urrc->addr);
if (!urrc->content_type) urrc->content_type = "text/html";
urrc->content_type_len = strlen(urrc->content_type);
ur->data2 = urrc;
return 0;
}
static int uwsgi_router_redis_continue(struct uwsgi_route *ur, char *args) {
uwsgi_router_redis(ur, args);
ur->custom = 1;
return 0;
}
static int uwsgi_router_redis_store(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_redis_store;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_redis_conf *urrc = uwsgi_calloc(sizeof(struct uwsgi_router_redis_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"addr", &urrc->addr,
"key", &urrc->key,
"expires", &urrc->expires, NULL)) {
uwsgi_log("invalid redisstore route syntax: %s\n", args);
return -1;
}
if (!urrc->key || !urrc->addr) {
uwsgi_log("invalid redisstore route syntax: you need to specify an address and a key\n");
return -1;
}
urrc->key_len = strlen(urrc->key);
urrc->addr_len = strlen(urrc->addr);
if (!urrc->expires) urrc->expires = "0";
ur->data2 = urrc;
return 0;
}
static void router_redis_register() {
uwsgi_register_router("redis", uwsgi_router_redis);
uwsgi_register_router("redis-continue", uwsgi_router_redis_continue);
uwsgi_register_router("redisstore", uwsgi_router_redis_store);
uwsgi_register_router("redis-store", uwsgi_router_redis_store);
}
#endif
struct uwsgi_plugin router_redis_plugin = {
.name = "router_redis",
#ifdef UWSGI_ROUTING
.on_load = router_redis_register,
#endif
};
+6
View File
@@ -0,0 +1,6 @@
NAME='router_redis'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['router_redis']
+75
View File
@@ -0,0 +1,75 @@
#include <uwsgi.h>
#ifndef UWSGI_XML_LIBXML2
#error you need a libxml2-enabled build of uWSGI to use the router_xmldir plugin
#endif
#include <libxml/tree.h>
static int uwsgi_routing_func_xmldir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
struct dirent **tasklist;
int n = scandir(ub->buf, &tasklist, 0, versionsort);
uwsgi_buffer_destroy(ub);
if (n < 0) return UWSGI_ROUTE_BREAK;
int i;
xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
xmlNode *rtree = xmlNewNode(NULL, BAD_CAST "tree");
xmlDocSetRootElement(rdoc, rtree);
for(i=0;i<n;i++) {
if (tasklist[i]->d_name[0] == '.') goto next;
switch (tasklist[i]->d_type) {
case DT_DIR:
xmlNewTextChild(rtree, NULL, BAD_CAST "directory", BAD_CAST tasklist[i]->d_name);
break;
case DT_LNK:
xmlNewTextChild(rtree, NULL, BAD_CAST "link", BAD_CAST tasklist[i]->d_name);
break;
case DT_REG:
xmlNewTextChild(rtree, NULL, BAD_CAST "file", BAD_CAST tasklist[i]->d_name);
break;
default:
xmlNewTextChild(rtree, NULL, BAD_CAST "unknown", BAD_CAST tasklist[i]->d_name);
break;
}
next:
free(tasklist[i]);
}
free(tasklist);
xmlChar *xmlbuf;
int xlen = 0;
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6);
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
xmlFreeDoc(rdoc);
xmlFree(xmlbuf);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_xmldir(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_xmldir;
ur->data = args;
ur->data_len = strlen(args);
return 0;
}
static void router_xmldir_register() {
uwsgi_register_router("xmldir", uwsgi_router_xmldir);
}
struct uwsgi_plugin router_xmldir_plugin = {
.name = "router_xmldir",
.on_load = router_xmldir_register,
};
+5
View File
@@ -0,0 +1,5 @@
NAME='router_xmldir'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['router_xmldir']
+138
View File
@@ -0,0 +1,138 @@
#include <uwsgi.h>
#if defined(UWSGI_ROUTING)
/*
offload transformation
each chunk is buffered to the transformation custom buffer
if the buffer grows higher than the specified limit, the response will be buffered to disk
on final the memory (or the tmpfile) will be offloaded
even if we are talking about buffering, this is a streaming transformation
as we need to hold control on memory usage
"offload" MUST BE the last transformation in the chain. Hellish things will happen otherwise...
*/
static int transform_offload(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
if (ut->is_final) {
struct uwsgi_transformation *orig_ut = (struct uwsgi_transformation *) ut->data;
// sendfile offload
if (orig_ut->fd > -1) {
if (!uwsgi_offload_request_sendfile_do(wsgi_req, orig_ut->fd, orig_ut->len)) {
// the fd will be closed by the offload engine
orig_ut->fd = -1;
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->response_size += orig_ut->len;
return 0;
}
// fallback to non-offloaded write
if (uwsgi_simple_sendfile(wsgi_req, orig_ut->fd, 0, orig_ut->len)) {
return -1;
}
wsgi_req->response_size += orig_ut->len;
return 0;
}
// memory offload
if (orig_ut->ub) {
if (!uwsgi_offload_request_memory_do(wsgi_req, orig_ut->ub->buf, orig_ut->ub->pos)) {
// memory will be freed by the offload engine
orig_ut->ub->buf = NULL;
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->response_size += orig_ut->ub->pos;
return 0;
}
// fallback to non-offloaded write
if (uwsgi_simple_write(wsgi_req, orig_ut->ub->buf, orig_ut->ub->pos)) {
return -1;
}
wsgi_req->response_size += orig_ut->ub->pos;
return -1;
}
return 0;
}
// check if we need to start buffering to disk
if (ut->fd == -1 && ut->len + ut->chunk->pos > ut->custom64) {
ut->fd = uwsgi_tmpfd();
if (ut->fd < 0) return -1;
// save already buffered data
if (ut->ub) {
ssize_t wlen = write(ut->fd, ut->ub->buf, ut->ub->pos);
if (wlen != (ssize_t) ut->ub->pos) {
uwsgi_error("transform_offload/write()");
return -1;
}
}
}
// if fd > -1, append to file
if (ut->fd > -1) {
ssize_t wlen = write(ut->fd, ut->chunk->buf, ut->chunk->pos);
if (wlen != (ssize_t) ut->chunk->pos) {
uwsgi_error("transform_offload/write()");
return -1;
}
ut->len += wlen;
goto done;
}
// buffer to memory
if (!ut->ub) {
ut->ub = uwsgi_buffer_new(ut->chunk->pos);
}
// append the chunk to the custom buffer
if (uwsgi_buffer_append(ut->ub, ut->chunk->buf, ut->chunk->pos)) return -1;
ut->len += ut->chunk->pos;
done:
// reset the chunk !!!
ut->chunk->pos = 0;
return 0;
}
static int uwsgi_routing_func_offload(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
if (!wsgi_req->socket->can_offload) {
uwsgi_log("unable to use the offload transformation without offload threads !!!\n");
return UWSGI_ROUTE_BREAK;
}
struct uwsgi_transformation *ut = uwsgi_add_transformation(wsgi_req, transform_offload, NULL);
ut->can_stream = 1;
ut->custom64 = ur->custom;
// add a "final" transformation to add the trailing chunk
ut = uwsgi_add_transformation(wsgi_req, transform_offload, ut);
ut->is_final = 1;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_offload(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_offload;
if (args[0] == 0) {
// 1 MB limit
ur->custom = 1024 * 1024;
}
else {
ur->custom = strtoul(args, NULL, 10);
}
return 0;
}
static void router_offload_register(void) {
uwsgi_register_router("offload", uwsgi_router_offload);
}
struct uwsgi_plugin transformation_offload_plugin = {
.name = "transformation_offload",
.on_load = router_offload_register,
};
#else
struct uwsgi_plugin transformation_offload_plugin = {
.name = "transformation_offload",
};
#endif
@@ -0,0 +1,6 @@
NAME='transformation_offload'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['offload']
+18 -2
View File
@@ -150,11 +150,17 @@ parse:
ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf, size_t len) {
int has_read = 0;
if (wsgi_req->proto_parser_remains > 0) {
size_t remains = UMIN(wsgi_req->proto_parser_remains, len);
memcpy(buf, wsgi_req->proto_parser_remains_buf, remains);
wsgi_req->proto_parser_remains -= remains;
wsgi_req->proto_parser_remains_buf += remains;
// we consumed all of the body, we can safely move the memory
if (wsgi_req->proto_parser_remains == 0 && wsgi_req->proto_parser_move) {
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_move, wsgi_req->proto_parser_pos);
wsgi_req->proto_parser_move = 0;
}
return remains;
}
@@ -176,7 +182,14 @@ ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf,
// copy remaining
wsgi_req->proto_parser_remains = fcgi_len - remains;
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf + sizeof(struct fcgi_record) + remains;
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
// we consumed all of the body, we can safely move the memory
if (wsgi_req->proto_parser_remains == 0) {
memmove(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_buf + fcgi_all_len, wsgi_req->proto_parser_pos - fcgi_all_len);
}
else {
// postpone memory move
wsgi_req->proto_parser_move = fcgi_all_len;
}
wsgi_req->proto_parser_pos -= fcgi_all_len;
return remains;
}
@@ -192,12 +205,15 @@ ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *wsgi_req, char *buf,
wsgi_req->proto_parser_buf = tmp_buf;
wsgi_req->proto_parser_buf_size += fcgi_all_len - (wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
}
goto gather;
if (!has_read) goto gather;
errno = EAGAIN;
return -1;
}
else {
gather:
rlen = read(wsgi_req->fd, wsgi_req->proto_parser_buf + wsgi_req->proto_parser_pos, wsgi_req->proto_parser_buf_size - wsgi_req->proto_parser_pos);
if (rlen > 0) {
has_read = 1;
wsgi_req->proto_parser_pos += rlen;
continue;
}
+40
View File
@@ -0,0 +1,40 @@
"""
simplified test for continulet without checking for partial writes
to enable continulets you only need to call uwsgi_pypy_setup_continulets() soon after startup:
uwsgi --pypy-wsgi-file t/pypy/t_continulet1.py --http-socket :9090 --pypy-home /opt/pypy --pypy-eval "uwsgi_pypy_setup_continulets()" --async 8
"""
import uwsgi
def application(e, sr):
sr('200 OK', [('Content-Type','text/plain')])
# call suspend 10 times and yield some value
for i in range(0,10):
print i
uwsgi.suspend()
yield str(i)
# connect to a memcached server
fd = uwsgi.async_connect('127.0.0.1:11211')
try:
# start waiting for socket availability (4 seconds max)
uwsgi.wait_fd_write(fd, 4)
# suspend execution 'til event
uwsgi.suspend()
uwsgi.send(fd, "get /foobar\r\n")
# now wait for memcached response
uwsgi.wait_fd_read(fd, 4)
uwsgi.suspend()
# read the response
data = uwsgi.recv(fd, 4096)
# return to the client
yield data
finally:
uwsgi.close(fd)
print "sleeping for 3 seconds..."
uwsgi.async_sleep(3)
uwsgi.suspend()
yield "done"
+47
View File
@@ -0,0 +1,47 @@
"""
safer test for continulet with partial writes check
to enable continulets you only need to call uwsgi_pypy_setup_continulets() soon after startup:
uwsgi --pypy-wsgi-file t/pypy/t_continulet2.py --http-socket :9090 --pypy-home /opt/pypy --pypy-eval "uwsgi_pypy_setup_continulets()" --async 8
"""
import uwsgi
def application(e, sr):
sr('200 OK', [('Content-Type','text/plain')])
# suspend 10 times and yield a value
for i in range(1,10):
print i
uwsgi.suspend()
yield str(i)
# connect to a memcached server
fd = uwsgi.async_connect('127.0.0.1:11211')
try:
command = "get /foobar\r\n"
remains = len(command)
while remains > 0:
# start waiting for socket availability (4 seconds max)
uwsgi.wait_fd_write(fd, 4)
# suspend execution 'til event
uwsgi.suspend()
pos = len(command) - remains
written = uwsgi.send(fd, command[pos:])
remains -= written
# now wait for memcached response
uwsgi.wait_fd_read(fd, 4)
uwsgi.suspend()
# read a chunk of data
data = uwsgi.recv(fd, 4096)
# .. and yield it
yield data
finally:
# always ensure sockets are closed
uwsgi.close(fd)
print "sleeping for 3 seconds..."
uwsgi.async_sleep(3)
uwsgi.suspend()
yield "done"
+14
View File
@@ -0,0 +1,14 @@
import socket
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
(addr, port) = sys.argv[1].split(':')
s.connect((addr, int(port)))
s.send("POST /send HTTP/1.1\r\n")
s.send("Transfer-Encoding: chunked\r\n\r\n")
while True:
msg = raw_input("msg >> ")
s.send("%X\r\n%s\r\n" % (len(msg), msg))
+81
View File
@@ -0,0 +1,81 @@
#!./uwsgi --http-socket :9090 --async 100 ...
# same chat example but using uwsgi async api
# for pypy + continulets just run:
# uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi-file tests/websockets_chat_async.py --pypy-eval "uwsgi_pypy_setup_continulets()" --async 100
import uwsgi
import time
import redis
def application(env, sr):
ws_scheme = 'ws'
if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
ws_scheme = 'wss'
if env['PATH_INFO'] == '/':
sr('200 OK', [('Content-Type','text/html')])
return """
<html>
<head>
<script language="Javascript">
var s = new WebSocket("%s://%s/foobar/");
s.onopen = function() {
alert("connected !!!");
s.send("ciao");
};
s.onmessage = function(e) {
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
};
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
function invia() {
var value = document.getElementById('testo').value;
s.send(value);
}
</script>
</head>
<body>
<h1>WebSocket</h1>
<input type="text" id="testo"/>
<input type="button" value="invia" onClick="invia();"/>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
</body>
</html>
""" % (ws_scheme, env['HTTP_HOST'])
elif env['PATH_INFO'] == '/favicon.ico':
return ""
elif env['PATH_INFO'] == '/foobar/':
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
print "websockets..."
r = redis.StrictRedis(host='localhost', port=6379, db=0)
channel = r.pubsub()
channel.subscribe('foobar')
websocket_fd = uwsgi.connection_fd()
redis_fd = channel.connection._sock.fileno()
while True:
uwsgi.wait_fd_read(websocket_fd)
uwsgi.wait_fd_read(redis_fd)
uwsgi.suspend()
fd = uwsgi.ready_fd()
if fd > -1:
if fd == websocket_fd:
msg = uwsgi.websocket_recv_nb()
if msg:
r.publish('foobar', msg)
elif fd == redis_fd:
msg = channel.parse_response()
# only interested in user messages
if msg[0] == 'message':
uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
+1 -1
View File
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
s.name = 'uwsgi'
s.license = 'GPL-2'
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
s.date = '2013-05-26'
s.date = '2013-06-05'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+42 -6
View File
@@ -218,11 +218,6 @@ extern "C" {
#include <sys/prctl.h>
#include <linux/limits.h>
#include <sys/mount.h>
#ifdef UWSGI_PTRACE
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/reg.h>
#endif
extern int pivot_root(const char *new_root, const char *put_old);
#endif
@@ -278,7 +273,9 @@ extern int pivot_root(const char *new_root, const char *put_old);
#endif
#if defined(__HAIKU__) || defined(__CYGWIN__)
#ifndef WAIT_ANY
#define WAIT_ANY (-1)
#endif
#define PRIO_MAX 20
#endif
@@ -1048,6 +1045,7 @@ struct uwsgi_spooler {
uint64_t tasks;
struct uwsgi_lock_item *lock;
time_t harakiri;
time_t user_harakiri;
int mode;
@@ -1220,6 +1218,10 @@ struct uwsgi_transformation {
uint8_t flushed;
void *data;
uint64_t round;
int fd;
struct uwsgi_buffer *ub;
uint64_t len;
uint64_t custom64;
struct uwsgi_transformation *next;
};
@@ -1398,6 +1400,7 @@ struct wsgi_request {
int headers_hvec;
uint64_t proto_parser_pos;
uint64_t proto_parser_move;
int64_t proto_parser_status;
void *proto_parser_buf;
uint64_t proto_parser_buf_size;
@@ -1426,6 +1429,12 @@ struct wsgi_request {
time_t websocket_last_pong;
int websocket_closed;
struct uwsgi_buffer *chunked_input_buf;
uint8_t chunked_input_parser_status;
ssize_t chunked_input_chunk_len;
size_t chunked_input_need;
uint8_t chunked_input_complete;
uint64_t stream_id;
// avoid routing loops
@@ -1870,6 +1879,8 @@ struct uwsgi_server {
struct uwsgi_regexp_list *log_req_route;
#endif
int use_abort;
int alarm_freq;
uint64_t alarm_msg_size;
struct uwsgi_string_list *alarm_list;
@@ -1945,6 +1956,7 @@ struct uwsgi_server {
struct uwsgi_offload_engine *offload_engine_sendfile;
struct uwsgi_offload_engine *offload_engine_transfer;
struct uwsgi_offload_engine *offload_engine_memory;
struct uwsgi_offload_engine *offload_engine_pipe;
int offload_threads;
int offload_threads_events;
struct uwsgi_thread **offload_thread;
@@ -1995,6 +2007,7 @@ struct uwsgi_server {
struct uwsgi_string_list *touch_logrotate;
struct uwsgi_string_list *touch_logreopen;
struct uwsgi_string_list *touch_exec;
struct uwsgi_string_list *touch_signal;
int propagate_touch;
@@ -2237,6 +2250,7 @@ struct uwsgi_server {
size_t lock_size;
size_t rwlock_size;
struct uwsgi_string_list *add_cache_item;
struct uwsgi_string_list *load_file_in_cache;
#ifdef UWSGI_ZLIB
struct uwsgi_string_list *load_file_in_cache_gzip;
@@ -2339,6 +2353,9 @@ struct uwsgi_server {
int websockets_pong_tolerance;
uint64_t websockets_max_size;
int chunked_input_timeout;
uint64_t chunked_input_limit;
int (*wait_write_hook) (int, int);
int (*wait_read_hook) (int, int);
@@ -2568,6 +2585,7 @@ struct uwsgi_mule {
uint8_t signum;
time_t harakiri;
time_t user_harakiri;
char name[0xff];
};
@@ -3227,6 +3245,7 @@ struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *, char *);
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int, char *);
void escape_shell_arg(char *, size_t, char *);
void escape_json(char *, size_t, char *);
void *uwsgi_malloc_shared(size_t);
void *uwsgi_calloc_shared(size_t);
@@ -3355,7 +3374,8 @@ void uwsgi_opt_set_cap(char *, char *, void *);
void uwsgi_opt_set_unshare(char *, char *, void *);
#endif
char *uwsgi_tmpname(char *, char *);
int uwsgi_tmpfd();
FILE *uwsgi_tmpfile();
#ifdef UWSGI_ROUTING
struct uwsgi_router *uwsgi_register_router(char *, int (*)(struct uwsgi_route *, char *));
@@ -3490,9 +3510,13 @@ char *uwsgi_substitute(char *, char *, char *);
void uwsgi_opt_add_custom_option(char *, char *, void *);
void uwsgi_opt_cflags(char *, char *, void *);
void uwsgi_opt_dot_h(char *, char *, void *);
void uwsgi_opt_connect_and_read(char *, char *, void *);
void uwsgi_opt_extract(char *, char *, void *);
char *uwsgi_get_dot_h();
char *uwsgi_get_cflags();
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *, char *, size_t);
void trigger_harakiri(int);
@@ -3770,6 +3794,10 @@ struct uwsgi_thread *uwsgi_offload_thread_start(void);
int uwsgi_offload_request_sendfile_do(struct wsgi_request *, int, size_t);
int uwsgi_offload_request_net_do(struct wsgi_request *, char *, struct uwsgi_buffer *);
int uwsgi_offload_request_memory_do(struct wsgi_request *, char *, size_t);
int uwsgi_offload_request_pipe_do(struct wsgi_request *, int, size_t);
int uwsgi_simple_sendfile(struct wsgi_request *, int, size_t, size_t);
int uwsgi_simple_write(struct wsgi_request *, char *, size_t);
void uwsgi_subscription_set_algo(char *);
@@ -3852,6 +3880,8 @@ int uwsgi_websocket_send(struct wsgi_request *, char *, size_t);
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *);
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *);
char *uwsgi_chunked_read(struct wsgi_request *, size_t *, int, int);
uint16_t uwsgi_be16(char *);
uint32_t uwsgi_be32(char *);
uint64_t uwsgi_be64(char *);
@@ -3995,9 +4025,11 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *);
#ifdef UWSGI_ZLIB
#include <zlib.h>
int uwsgi_deflate_init(z_stream *, char *, size_t);
int uwsgi_inflate_init(z_stream *, char *, size_t);
char *uwsgi_deflate(z_stream *, char *, size_t, size_t *);
void uwsgi_crc32(uint32_t *, char *, size_t);
struct uwsgi_buffer *uwsgi_gzip(char *, size_t);
struct uwsgi_buffer *uwsgi_zlib_decompress(char *, size_t);
int uwsgi_gzip_fix(z_stream *, uint32_t, struct uwsgi_buffer *, size_t);
char *uwsgi_gzip_chunk(z_stream *, uint32_t *, char *, size_t, size_t *);
int uwsgi_gzip_prepare(z_stream *, char *, size_t, uint32_t *);
@@ -4040,6 +4072,10 @@ void uwsgi_takeover(void);
char *uwsgi_binary_path(void);
int uwsgi_is_again();
void uwsgi_disconnect(struct wsgi_request *);
int uwsgi_ready_fd(struct wsgi_request *);
void uwsgi_check_emperor(void);
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
-55
View File
@@ -1,55 +0,0 @@
send_message()
send_multi_message()
reload()
workers()
masterpid()
total_requests()
getoption(id)
get_option(id)
setoption(id, value)
set_option(id, value)
sorry_i_need_to_block()
request_id()
worker_id()
log(message)
disconnect()
grunt()
load_plugin()
lock()
unlock()
send()
cl()
req_fd()
signal(num)
sendfile()
set_warning_message()
mem()
has_hook()
logsize()
send_multicast_message
cluster_nodes
cluster_best_node
async_sleep
async_connect
async_send_message
green_schedule
suspend
wait_fd_read(fd, [timeout])
wait_fd_write(fd, timeout)
is_connected()
send
recv()
recv_block
recv_frame
close
parsefile
sharedarea_read
sharedarea_write
sharedarea_readbyte
sharedarea_writebyte
sharedarea_readlong
sharedarea_writelong
sharedarea_inclong
register_signal(num, targer, handler)
register_rpc(name, func[,args])
rpc(node, name[,args,...])
+61 -12
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.11'
uwsgi_version = '1.9.13'
import os
import re
@@ -25,13 +25,17 @@ try:
import ConfigParser
except:
import configparser as ConfigParser
from imp import reload
GCC = os.environ.get('CC', sysconfig.get_config_var('CC'))
if not GCC:
GCC = 'gcc'
CPP = os.environ.get('CPP', 'cpp')
def get_preprocessor():
if 'clang' in GCC:
return 'clang -xc core/clang_fake.c'
return 'cpp'
CPP = os.environ.get('CPP', get_preprocessor())
try:
CPUCOUNT = int(os.environ.get('CPUCOUNT', -1))
@@ -245,11 +249,11 @@ def build_uwsgi(uc, print_only=False):
print("detected CPU cores: %d" % CPUCOUNT)
print("configured CFLAGS: %s" % ' '.join(cflags))
try:
uwsgi_cflags = ' '.join(cflags).encode('hex')
except:
if sys.version_info[0] >= 3:
import binascii
uwsgi_cflags = binascii.b2a_hex(' '.join(cflags).encode('ascii')).decode('ascii')
else:
uwsgi_cflags = ' '.join(cflags).encode('hex')
last_cflags_ts = 0
@@ -267,6 +271,27 @@ def build_uwsgi(uc, print_only=False):
ulc.write(uwsgi_cflags)
ulc.close()
# embed uwsgi.h in the server binary. It increases the binary size, but will be very useful
# for various tricks (like cffi integration)
# if possibile, the blob is compressed
if sys.version_info[0] >= 3:
uwsgi_dot_h_content = open('uwsgi.h', 'rb').read()
else:
uwsgi_dot_h_content = open('uwsgi.h').read()
if report['zlib']:
import zlib
# maximum level of compression
uwsgi_dot_h_content = zlib.compress(uwsgi_dot_h_content, 9)
if sys.version_info[0] >= 3:
import binascii
uwsgi_dot_h = binascii.b2a_hex(uwsgi_dot_h_content).decode('ascii')
else:
uwsgi_dot_h = uwsgi_dot_h_content.encode('hex')
open('core/dot_h.c', 'w').write('char *uwsgi_dot_h = "%s";\n' % uwsgi_dot_h);
gcc_list.append('core/dot_h')
cflags.append('-DUWSGI_CFLAGS=\\"%s\\"' % uwsgi_cflags)
cflags.append('-DUWSGI_BUILD_DATE="\\"%s\\""' % time.strftime("%d %B %Y %H:%M:%S"))
@@ -317,6 +342,13 @@ def build_uwsgi(uc, print_only=False):
except:
pass
if GCC in ('clang',):
try:
p_cflags.remove('-fno-fast-math')
p_cflags.remove('-ggdb3')
except:
pass
try:
p_cflags.remove('-Wdeclaration-after-statement')
except:
@@ -456,6 +488,8 @@ def open_profile(filename):
class uConf(object):
def __init__(self, filename, mute=False):
global GCC
self.config = ConfigParser.ConfigParser()
if not mute:
print("using profile: %s" % filename)
@@ -476,7 +510,7 @@ class uConf(object):
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks',
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions', 'core/config',
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron',
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events',
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/chunked',
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini',
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/transformations', 'core/uwsgi']
# add protocols
@@ -487,6 +521,10 @@ class uConf(object):
self.gcc_list.append('proto/scgi')
self.include_path = []
if 'UWSGI_INCLUDES' in os.environ:
self.include_path += os.environ['UWSGI_INCLUDES'].split(',')
self.cflags = ['-O2', '-I.', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split() + self.get('cflags','').split()
report['kernel'] = uwsgi_os
@@ -504,11 +542,13 @@ class uConf(object):
if uwsgi_os == 'GNU':
self.cflags.append('-D__HURD__')
try:
gcc_version = str(spcall("%s -dumpversion" % GCC))
except:
print("*** you need a c compiler to build uWSGI ***")
sys.exit(1)
gcc_version = spcall("%s -dumpversion" % GCC)
if not gcc_version and GCC.startswith('gcc'):
if uwsgi_os == 'Darwin':
GCC = 'llvm-' + GCC
else:
GCC = 'gcc'
gcc_version = spcall("%s -dumpversion" % GCC)
try:
add_it = False
@@ -655,6 +695,8 @@ class uConf(object):
if uwsgi_os == 'Darwin':
self.cflags.append('-mmacosx-version-min=10.5')
if GCC in ('clang',):
self.libs.remove('-rdynamic')
# compile extras
extras = self.get('extras', None)
@@ -1197,6 +1239,13 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
except:
pass
if GCC in ('clang',):
try:
p_cflags.remove('-fno-fast-math')
p_cflags.remove('-ggdb3')
except:
pass
if uwsgi_os.startswith('CYGWIN'):
try:
p_cflags.remove('-fstack-protector')
+19 -24
View File
@@ -1,4 +1,3 @@
import uwsgi
import sys
from threading import Thread
@@ -7,6 +6,7 @@ try:
except:
import pickle
import uwsgi
if uwsgi.masterpid() == 0:
raise Exception(
@@ -45,48 +45,43 @@ class postfork(object):
postfork_chain.append(f)
class spool(object):
class spoolraw(object):
def spool(self, *args, **kwargs):
def __call__(self, *args, **kwargs):
arguments = self.base_dict
arguments['ud_spool_ret'] = str(uwsgi.SPOOL_OK)
if len(args) > 0:
arguments.update(args[0])
if kwargs:
arguments.update(kwargs)
return uwsgi.spool(arguments)
# For backward compatibility (uWSGI < 1.9.13)
def spool(self, *args, **kwargs):
return self.__class__.__call__(self, *args, **kwargs)
def __init__(self, f):
if not 'spooler' in uwsgi.opt:
raise Exception(
"you have to enable the uWSGI spooler to use @spool decorator")
"you have to enable the uWSGI spooler to use @%s decorator" % self.__class__.__name__)
self.f = f
spooler_functions[f.__name__] = self.f
self.f.spool = self.spool
spooler_functions[self.f.__name__] = self.f
# For backward compatibility (uWSGI < 1.9.13)
self.f.spool = self.__call__
self.base_dict = {'ud_spool_func': self.f.__name__}
class spoolforever(spool):
class spool(spoolraw):
def spool(self, *args, **kwargs):
arguments = self.base_dict
arguments['ud_spool_ret'] = str(uwsgi.SPOOL_RETRY)
if len(args) > 0:
arguments.update(args[0])
if kwargs:
arguments.update(kwargs)
return uwsgi.spool(arguments)
def __call__(self, *args, **kwargs):
self.base_dict['ud_spool_ret'] = str(uwsgi.SPOOL_OK)
return spoolraw.__call__(self, *args, **kwargs)
class spoolraw(spool):
class spoolforever(spoolraw):
def spool(self, *args, **kwargs):
arguments = self.base_dict
if len(args) > 0:
arguments.update(args[0])
if kwargs:
arguments.update(kwargs)
return uwsgi.spool(arguments)
def __call__(self, *args, **kwargs):
self.base_dict['ud_spool_ret'] = str(uwsgi.SPOOL_RETRY)
return spoolraw.__call__(self, *args, **kwargs)
class mulefunc(object):