nyara 0.0.1.pre.8 → 0.0.1.pre.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/nyara +17 -0
- data/changes +12 -0
- data/copying +10 -0
- data/ext/event.c +78 -68
- data/ext/extconf.rb +7 -0
- data/ext/inc/epoll.h +12 -20
- data/ext/inc/kqueue.h +8 -18
- data/ext/nyara.c +17 -2
- data/ext/nyara.h +7 -3
- data/ext/request.c +35 -7
- data/ext/request.h +3 -0
- data/ext/request_parse.c +26 -7
- data/ext/url_encoded.c +22 -11
- data/lib/nyara/command.rb +79 -0
- data/lib/nyara/config.rb +88 -26
- data/lib/nyara/controller.rb +175 -110
- data/lib/nyara/cookie.rb +2 -2
- data/lib/nyara/flash.rb +3 -2
- data/lib/nyara/hashes/config_hash.rb +18 -5
- data/lib/nyara/hashes/header_hash.rb +3 -2
- data/lib/nyara/hashes/param_hash.rb +2 -0
- data/lib/nyara/mime_types.rb +1 -0
- data/lib/nyara/nyara.rb +47 -25
- data/lib/nyara/part.rb +85 -39
- data/lib/nyara/request.rb +21 -4
- data/lib/nyara/route.rb +167 -8
- data/lib/nyara/session.rb +29 -22
- data/lib/nyara/templates/Gemfile +4 -0
- data/lib/nyara/templates/Rakefile +1 -0
- data/lib/nyara/templates/config/boot.rb +0 -0
- data/lib/nyara/templates/config/database.yml +28 -0
- data/lib/nyara/templates/config/development.rb +0 -0
- data/lib/nyara/templates/config/production.rb +0 -0
- data/lib/nyara/templates/config/session.key +1 -0
- data/lib/nyara/templates/config/test.rb +0 -0
- data/lib/nyara/templates/public/robot.txt +0 -0
- data/lib/nyara/templates/spec/spec_helper.rb +0 -0
- data/lib/nyara/test.rb +14 -11
- data/lib/nyara/view.rb +16 -9
- data/nyara.gemspec +18 -5
- data/rakefile +8 -2
- data/readme.md +26 -15
- data/spec/apps/connect.rb +1 -0
- data/spec/command_spec.rb +46 -0
- data/spec/config_spec.rb +14 -4
- data/spec/controller_spec.rb +24 -0
- data/spec/ext_route_spec.rb +3 -3
- data/spec/flash_spec.rb +0 -4
- data/spec/integration_spec.rb +63 -2
- data/spec/{part_spec.rb → multipart_spec.rb} +18 -0
- data/spec/raw_requests/multipart +20 -0
- data/spec/request_delegate_spec.rb +4 -0
- data/spec/request_spec.rb +8 -0
- data/spec/{route_entry_spec.rb → route_spec.rb} +58 -3
- data/spec/session_spec.rb +4 -4
- data/spec/spec_helper.rb +14 -7
- data/tools/hello.rb +21 -3
- metadata +42 -10
- data/lib/nyara/route_entry.rb +0 -111
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abcd7918ded6547e4edadb0746742a854f3c216b
|
4
|
+
data.tar.gz: 8dfaf81082c63b6e117bfc6836210d3d6f8f9aa8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00c038fe5d84059b5452c8f445e0680c95f05a81be846c73a481efe0fd1a2d50433f3511b04453187983e6fd491940c7033229757d10d5da52c91fd508c332e8
|
7
|
+
data.tar.gz: 8a49ba878195450a06fe361c3d0ac57697c89f508b2c8f4ba5bb0e5a0acbcd8ff2f287cf59f38d63df4633af17c055b98ea1d6d02623318a81098b55a8b4b7b1
|
data/bin/nyara
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative "../lib/nyara/nyara"
|
3
|
+
|
4
|
+
args = ARGV.dup
|
5
|
+
task_name = args.shift || 'help'
|
6
|
+
|
7
|
+
|
8
|
+
case task_name
|
9
|
+
when 'help'
|
10
|
+
Nyara::Command.help
|
11
|
+
when '-h'
|
12
|
+
Nyara::Command.help
|
13
|
+
when '-v'
|
14
|
+
Nyara::Command.version
|
15
|
+
when 'new'
|
16
|
+
Nyara::Command.new_project(*args)
|
17
|
+
end
|
data/changes
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
2013-07-13 add bin script `nyara`
|
2
|
+
2013-07-10 add before filter
|
3
|
+
2013-07-06 add worker signal management
|
4
|
+
2013-07-05 add static file controller
|
5
|
+
Config: remove setter helpers, add path helers
|
6
|
+
2013-07-03 add multipart request parsing
|
7
|
+
2013-07-01 add flash helper
|
8
|
+
2013-06-30 add Nyara::Test::Response for test to parse response
|
9
|
+
2013-06-27 compatibility fixes for versions of GCC and Ruby
|
10
|
+
2013-06-26 patch TCPSocket so client libraries in Ruby won't stuck
|
11
|
+
add sleep helper
|
12
|
+
2013-06-22 add changes and copying
|
data/copying
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
Copyright (c) 2013, Zete Lui
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
7
|
+
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
8
|
+
- Neither the name of the *Nyara* nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
9
|
+
|
10
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/ext/event.c
CHANGED
@@ -7,23 +7,14 @@
|
|
7
7
|
#include <errno.h>
|
8
8
|
#include <stdint.h>
|
9
9
|
#include <unistd.h>
|
10
|
+
#include <ruby/st.h>
|
10
11
|
|
11
|
-
#ifndef rb_obj_hide
|
12
|
-
extern VALUE rb_obj_hide(VALUE obj);
|
13
|
-
extern VALUE rb_obj_reveal(VALUE obj, VALUE klass);
|
14
|
-
#endif
|
15
|
-
|
16
|
-
#define ETYPE_CAN_ACCEPT 0
|
17
|
-
#define ETYPE_HANDLE_REQUEST 1
|
18
|
-
#define ETYPE_CONNECT 2
|
19
12
|
#define MAX_E 1024
|
20
|
-
static void loop_body(
|
13
|
+
static void loop_body(VALUE rid);
|
21
14
|
static void loop_check();
|
22
15
|
static int qfd = 0;
|
23
|
-
|
24
|
-
|
25
|
-
static char received_data[MAX_RECEIVE_DATA];
|
26
|
-
extern http_parser_settings nyara_request_parse_settings;
|
16
|
+
static int tcp_server_fd = 0;
|
17
|
+
static st_table* handled_rids; // {rid => nil} for current round
|
27
18
|
|
28
19
|
#ifdef HAVE_KQUEUE
|
29
20
|
#include "inc/kqueue.h"
|
@@ -31,15 +22,27 @@ extern http_parser_settings nyara_request_parse_settings;
|
|
31
22
|
#include "inc/epoll.h"
|
32
23
|
#endif
|
33
24
|
|
34
|
-
|
35
|
-
|
36
|
-
|
25
|
+
#ifndef rb_obj_hide
|
26
|
+
extern VALUE rb_obj_hide(VALUE obj);
|
27
|
+
extern VALUE rb_obj_reveal(VALUE obj, VALUE klass);
|
28
|
+
#endif
|
29
|
+
|
30
|
+
#define MAX_RECEIVE_DATA 65536 * 2
|
31
|
+
static char received_data[MAX_RECEIVE_DATA];
|
32
|
+
extern http_parser_settings nyara_request_parse_settings;
|
33
|
+
|
34
|
+
static VALUE rid_request_map; // {rid(FIXNUM) => request}
|
35
|
+
static VALUE to_resume_requests; // [request], for current round
|
36
|
+
|
37
|
+
static VALUE sym_accept;
|
38
|
+
|
39
|
+
// Fiber.yield
|
37
40
|
static VALUE sym_term_close;
|
38
41
|
static VALUE sym_writing;
|
39
42
|
static VALUE sym_reading;
|
40
43
|
static VALUE sym_sleep;
|
44
|
+
|
41
45
|
static Request* curr_request;
|
42
|
-
static VALUE to_resume_actions;
|
43
46
|
static bool graceful_quit = false;
|
44
47
|
|
45
48
|
static VALUE _fiber_func(VALUE _, VALUE args) {
|
@@ -82,8 +85,7 @@ static void _handle_request(VALUE request) {
|
|
82
85
|
if (errno != EAGAIN && errno != EWOULDBLOCK) {
|
83
86
|
// this can happen when 2 events are fetched, and first event closes the fd, then second event fails
|
84
87
|
if (p->fd) {
|
85
|
-
|
86
|
-
p->fd = 0;
|
88
|
+
nyara_detach_rid(p->rid);
|
87
89
|
}
|
88
90
|
return;
|
89
91
|
}
|
@@ -100,6 +102,7 @@ static void _handle_request(VALUE request) {
|
|
100
102
|
// ensure action
|
101
103
|
if (p->fiber == Qnil) {
|
102
104
|
volatile RouteResult result = nyara_lookup_route(p->method, p->path, p->accept);
|
105
|
+
nyara_summary_request(p->method, p->path, result.controller);
|
103
106
|
if (RTEST(result.controller)) {
|
104
107
|
rb_ary_push(result.args, rb_class_new_instance(1, &(p->self), result.controller));
|
105
108
|
// result.args is on stack, no need to worry gc
|
@@ -117,8 +120,7 @@ static void _handle_request(VALUE request) {
|
|
117
120
|
not_found_len = strlen(not_found);
|
118
121
|
}
|
119
122
|
nyara_send_data(p->fd, not_found, not_found_len);
|
120
|
-
|
121
|
-
p->fd = 0;
|
123
|
+
nyara_detach_rid(p->rid);
|
122
124
|
return;
|
123
125
|
}
|
124
126
|
}
|
@@ -127,31 +129,26 @@ static void _handle_request(VALUE request) {
|
|
127
129
|
}
|
128
130
|
|
129
131
|
// platform independent, invoked by LOOP_E()
|
130
|
-
static void loop_body(
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
break;
|
132
|
+
static void loop_body(VALUE rid) {
|
133
|
+
if (rid == sym_accept) {
|
134
|
+
int cfd = accept(tcp_server_fd, NULL, NULL);
|
135
|
+
if (cfd > 0) {
|
136
|
+
nyara_set_nonblock(cfd);
|
137
|
+
Request* p = nyara_request_new(cfd);
|
138
|
+
rb_hash_aset(rid_request_map, p->rid, p->self);
|
139
|
+
ADD_E(cfd, p->rid);
|
139
140
|
}
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
rb_hash_aset(fd_request_map, key, request);
|
146
|
-
}
|
147
|
-
_handle_request(request);
|
148
|
-
break;
|
141
|
+
} else {
|
142
|
+
// epoll_wait can return multiple results on a same request,
|
143
|
+
// and this request may be closed at previous round.
|
144
|
+
if (st_lookup(handled_rids, rid, NULL)) {
|
145
|
+
return;
|
149
146
|
}
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
147
|
+
st_insert(handled_rids, rid, Qnil);
|
148
|
+
|
149
|
+
VALUE request = rb_hash_aref(rid_request_map, rid);
|
150
|
+
if (request != Qnil) {
|
151
|
+
_handle_request(request);
|
155
152
|
}
|
156
153
|
}
|
157
154
|
}
|
@@ -161,52 +158,59 @@ static void loop_check() {
|
|
161
158
|
rb_thread_schedule();
|
162
159
|
|
163
160
|
// wakeup actions which finished sleeping
|
164
|
-
long len = RARRAY_LEN(
|
161
|
+
long len = RARRAY_LEN(to_resume_requests);
|
165
162
|
if (len) {
|
166
|
-
VALUE* ptr = RARRAY_PTR(
|
163
|
+
VALUE* ptr = RARRAY_PTR(to_resume_requests);
|
167
164
|
for (long i = 0; i < len; i++) {
|
168
165
|
VALUE request = ptr[i];
|
169
166
|
Request* p;
|
170
167
|
Data_Get_Struct(request, Request, p);
|
171
168
|
|
172
169
|
p->sleeping = false;
|
173
|
-
if (!rb_fiber_alive_p(p->fiber)) {
|
170
|
+
if (!rb_fiber_alive_p(p->fiber) || !p->fd) { // do not wake dead requests
|
174
171
|
continue;
|
175
172
|
}
|
176
173
|
|
177
174
|
_resume_action(p);
|
178
175
|
if (qfd) {
|
176
|
+
// printf("%s\n", "no way!");
|
177
|
+
// _Exit(1);
|
179
178
|
VALUE* v_fds = RARRAY_PTR(p->watched_fds);
|
180
179
|
long v_fds_len = RARRAY_LEN(p->watched_fds);
|
181
180
|
for (long i = 0; i < v_fds_len; i++) {
|
182
|
-
ADD_E(FIX2INT(v_fds[i]),
|
181
|
+
ADD_E(FIX2INT(v_fds[i]), p->rid);
|
183
182
|
}
|
184
|
-
ADD_E(p->fd,
|
183
|
+
ADD_E(p->fd, p->rid);
|
185
184
|
} else {
|
186
185
|
// we are in a test, no queue
|
187
186
|
}
|
188
187
|
}
|
188
|
+
|
189
|
+
rb_ary_clear(to_resume_requests);
|
189
190
|
}
|
190
191
|
|
191
192
|
if (graceful_quit) {
|
192
|
-
if (RTEST(rb_funcall(
|
193
|
+
if (RTEST(rb_funcall(rid_request_map, rb_intern("empty?"), 0))) {
|
193
194
|
_Exit(0);
|
194
195
|
}
|
195
196
|
}
|
196
197
|
}
|
197
198
|
|
198
|
-
void
|
199
|
-
VALUE request = rb_hash_delete(
|
199
|
+
void nyara_detach_rid(VALUE rid) {
|
200
|
+
VALUE request = rb_hash_delete(rid_request_map, rid);
|
200
201
|
if (request != Qnil) {
|
201
202
|
Request* p;
|
202
203
|
Data_Get_Struct(request, Request, p);
|
203
204
|
VALUE* watched = RARRAY_PTR(p->watched_fds);
|
204
205
|
long watched_len = RARRAY_LEN(p->watched_fds);
|
205
206
|
for (long i = 0; i < watched_len; i++) {
|
206
|
-
|
207
|
+
close(NUM2INT(watched[i]));
|
208
|
+
}
|
209
|
+
if (p->fd) {
|
210
|
+
close(p->fd);
|
211
|
+
p->fd = 0;
|
207
212
|
}
|
208
213
|
}
|
209
|
-
close(fd);
|
210
214
|
}
|
211
215
|
|
212
216
|
static VALUE ext_init_queue(VALUE _) {
|
@@ -216,9 +220,9 @@ static VALUE ext_init_queue(VALUE _) {
|
|
216
220
|
|
217
221
|
// run queue loop with server_fd
|
218
222
|
static VALUE ext_run_queue(VALUE _, VALUE v_server_fd) {
|
219
|
-
|
220
|
-
nyara_set_nonblock(
|
221
|
-
ADD_E(
|
223
|
+
tcp_server_fd = FIX2INT(v_server_fd);
|
224
|
+
nyara_set_nonblock(tcp_server_fd);
|
225
|
+
ADD_E(tcp_server_fd, sym_accept);
|
222
226
|
|
223
227
|
LOOP_E();
|
224
228
|
return Qnil;
|
@@ -255,7 +259,7 @@ static VALUE ext_request_sleep(VALUE _, VALUE request) {
|
|
255
259
|
// NOTE this will be executed in another thread, resuming fiber in a non-main thread will stuck
|
256
260
|
static VALUE ext_request_wakeup(VALUE _, VALUE request) {
|
257
261
|
// NOTE should not use curr_request
|
258
|
-
rb_ary_push(
|
262
|
+
rb_ary_push(to_resume_requests, request);
|
259
263
|
return Qnil;
|
260
264
|
}
|
261
265
|
|
@@ -267,9 +271,15 @@ static VALUE ext_set_nonblock(VALUE _, VALUE v_fd) {
|
|
267
271
|
|
268
272
|
static VALUE ext_fd_watch(VALUE _, VALUE v_fd) {
|
269
273
|
int fd = NUM2INT(v_fd);
|
270
|
-
rb_hash_aset(watch_request_map, v_fd, curr_request->self);
|
271
274
|
rb_ary_push(curr_request->watched_fds, v_fd);
|
272
|
-
ADD_E(fd,
|
275
|
+
ADD_E(fd, curr_request->rid);
|
276
|
+
return Qnil;
|
277
|
+
}
|
278
|
+
|
279
|
+
static VALUE ext_fd_unwatch(VALUE _, VALUE v_fd) {
|
280
|
+
int fd = NUM2INT(v_fd);
|
281
|
+
rb_ary_delete(curr_request->watched_fds, v_fd);
|
282
|
+
DEL_E(fd);
|
273
283
|
return Qnil;
|
274
284
|
}
|
275
285
|
|
@@ -367,19 +377,18 @@ static VALUE ext_handle_request(VALUE _, VALUE request) {
|
|
367
377
|
}
|
368
378
|
|
369
379
|
void Init_event(VALUE ext) {
|
370
|
-
|
371
|
-
rb_gc_register_mark_object(
|
372
|
-
|
373
|
-
|
374
|
-
|
380
|
+
rid_request_map = rb_hash_new();
|
381
|
+
rb_gc_register_mark_object(rid_request_map);
|
382
|
+
handled_rids = st_init_numtable();
|
383
|
+
to_resume_requests = rb_ary_new();
|
384
|
+
rb_gc_register_mark_object(to_resume_requests);
|
385
|
+
|
386
|
+
sym_accept = ID2SYM(rb_intern("accept"));
|
375
387
|
sym_term_close = ID2SYM(rb_intern("term_close"));
|
376
388
|
sym_writing = ID2SYM(rb_intern("writing"));
|
377
389
|
sym_reading = ID2SYM(rb_intern("reading"));
|
378
390
|
sym_sleep = ID2SYM(rb_intern("sleep"));
|
379
391
|
|
380
|
-
to_resume_actions = rb_ary_new();
|
381
|
-
rb_gc_register_mark_object(to_resume_actions);
|
382
|
-
|
383
392
|
rb_define_singleton_method(ext, "init_queue", ext_init_queue, 0);
|
384
393
|
rb_define_singleton_method(ext, "run_queue", ext_run_queue, 1);
|
385
394
|
rb_define_singleton_method(ext, "graceful_quit", ext_graceful_quit, 1);
|
@@ -390,6 +399,7 @@ void Init_event(VALUE ext) {
|
|
390
399
|
// fd operations
|
391
400
|
rb_define_singleton_method(ext, "set_nonblock", ext_set_nonblock, 1);
|
392
401
|
rb_define_singleton_method(ext, "fd_watch", ext_fd_watch, 1);
|
402
|
+
rb_define_singleton_method(ext, "fd_unwatch", ext_fd_unwatch, 1);
|
393
403
|
rb_define_singleton_method(ext, "fd_send", ext_fd_send, 3);
|
394
404
|
rb_define_singleton_method(ext, "fd_recv", ext_fd_recv, 3);
|
395
405
|
|
data/ext/extconf.rb
CHANGED
@@ -19,6 +19,13 @@ def tweak_cflags
|
|
19
19
|
puts "To enable debug: make xflags='-DDEBUG -O0'"
|
20
20
|
end
|
21
21
|
|
22
|
+
# for debugging low versions of gcc
|
23
|
+
def use_gcc42
|
24
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = `which gcc-4.2`.strip
|
25
|
+
RbConfig::MAKEFILE_CONFIG['CXX'] = `which g++-4.2`.strip
|
26
|
+
end
|
27
|
+
# use_gcc42
|
28
|
+
|
22
29
|
have_kqueue = (have_header("sys/event.h") and have_header("sys/queue.h"))
|
23
30
|
have_epoll = have_func('epoll_create', 'sys/epoll.h')
|
24
31
|
abort('no kqueue nor epoll') if !have_kqueue and !have_epoll
|
data/ext/inc/epoll.h
CHANGED
@@ -6,35 +6,24 @@
|
|
6
6
|
|
7
7
|
static struct epoll_event qevents[MAX_E];
|
8
8
|
|
9
|
-
static void ADD_E(int fd,
|
9
|
+
static void ADD_E(int fd, VALUE rid) {
|
10
10
|
struct epoll_event e;
|
11
11
|
// not using edge trigger flag EPOLLET
|
12
12
|
// because edge trigger only fire once when fd is readable/writable
|
13
13
|
// but the event may not be consumed in our handler
|
14
14
|
e.events = EPOLLIN | EPOLLOUT;
|
15
|
-
e.data.u64 = (
|
15
|
+
e.data.u64 = (uint64_t)rid;
|
16
16
|
|
17
|
-
// todo timeout
|
18
|
-
# ifdef NDEBUG
|
19
|
-
epoll_ctl(qfd, EPOLL_CTL_ADD, fd, &e);
|
20
|
-
# else
|
21
17
|
if (epoll_ctl(qfd, EPOLL_CTL_ADD, fd, &e))
|
22
|
-
|
23
|
-
# endif
|
18
|
+
rb_sys_fail("epoll_ctl(2) - EPOLL_CTL_ADD");
|
24
19
|
}
|
25
20
|
|
26
21
|
// NOTE either epoll or kqueue removes the event watch from queue when fd closed
|
27
22
|
static void DEL_E(int fd) {
|
28
23
|
struct epoll_event e;
|
29
24
|
e.events = EPOLLIN | EPOLLOUT;
|
30
|
-
e.data.ptr = NULL;
|
31
|
-
|
32
|
-
# ifdef NDEBUG
|
33
|
-
epoll_ctl(qfd, EPOLL_CTL_DEL, fd, &e);
|
34
|
-
# else
|
35
25
|
if (epoll_ctl(qfd, EPOLL_CTL_DEL, fd, &e))
|
36
|
-
|
37
|
-
# endif
|
26
|
+
rb_sys_fail("epoll_ctl(2) - EPOLL_CTL_DEL");
|
38
27
|
}
|
39
28
|
|
40
29
|
static void INIT_E() {
|
@@ -48,13 +37,16 @@ static void LOOP_E() {
|
|
48
37
|
while (1) {
|
49
38
|
// heart beat of 0.1 sec, allow ruby signal interrupts to be inserted
|
50
39
|
int sz = epoll_wait(qfd, qevents, MAX_E, 100);
|
40
|
+
st_clear(handled_rids);
|
51
41
|
|
52
42
|
for (int i = 0; i < sz; i++) {
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
43
|
+
VALUE rid = (VALUE)qevents[i].data.u64;
|
44
|
+
if (qevents[i].events & (EPOLLHUP | EPOLLERR)) {
|
45
|
+
nyara_detach_rid(rid);
|
46
|
+
} else if (qevents[i].events & (EPOLLIN | EPOLLOUT)) {
|
47
|
+
loop_body(rid);
|
48
|
+
} else if (qevents[i].events & EPOLLRDHUP) {
|
49
|
+
// do sth?
|
58
50
|
}
|
59
51
|
}
|
60
52
|
loop_check();
|
data/ext/inc/kqueue.h
CHANGED
@@ -10,32 +10,22 @@
|
|
10
10
|
# include <sys/queue.h>
|
11
11
|
#endif
|
12
12
|
|
13
|
-
#define MAX_E 1024
|
14
|
-
static int qfd;
|
15
13
|
static struct kevent qevents[MAX_E];
|
16
14
|
|
17
|
-
static void ADD_E(int fd,
|
15
|
+
static void ADD_E(int fd, VALUE rid) {
|
18
16
|
struct kevent e;
|
19
17
|
// without EV_CLEAR, it is level-triggered
|
20
18
|
// http://www.cs.helsinki.fi/linux/linux-kernel/2001-38/0547.html
|
21
|
-
EV_SET(&e, fd, EVFILT_READ | EVFILT_WRITE, EV_ADD, 0, 0, (void*)
|
22
|
-
# ifdef NDEBUG
|
23
|
-
kevent(qfd, &e, 1, NULL, 0, NULL);
|
24
|
-
# else
|
19
|
+
EV_SET(&e, fd, EVFILT_READ | EVFILT_WRITE, EV_ADD, 0, 0, (void*)rid);
|
25
20
|
if (kevent(qfd, &e, 1, NULL, 0, NULL))
|
26
|
-
|
27
|
-
# endif
|
21
|
+
rb_sys_fail("kevent(2) - EV_ADD");
|
28
22
|
}
|
29
23
|
|
30
24
|
static void DEL_E_WITH_FILTER(int fd, int filter) {
|
31
25
|
struct kevent e;
|
32
26
|
EV_SET(&e, fd, filter, EV_DELETE, 0, 0, NULL);
|
33
|
-
# ifdef NDEBUG
|
34
|
-
kevent(qfd, &e, 1, NULL, 0, NULL);
|
35
|
-
# else
|
36
27
|
if (kevent(qfd, &e, 1, NULL, 0, NULL))
|
37
|
-
|
38
|
-
# endif
|
28
|
+
rb_sys_fail("kevent(2) - EV_DELETE");
|
39
29
|
}
|
40
30
|
|
41
31
|
static void DEL_E(int fd) {
|
@@ -55,21 +45,21 @@ static void LOOP_E() {
|
|
55
45
|
// EV_DELETE, EV_RECEIPT, EV_ONESHOT,
|
56
46
|
// EV_CLEAR, EV_EOF, EV_ERROR);
|
57
47
|
|
58
|
-
struct timespec ts = {0, 1000 * 1000 * 100};
|
48
|
+
static struct timespec ts = {0, 1000 * 1000 * 100};
|
59
49
|
while (1) {
|
60
50
|
// heart beat of 0.1 sec, allow ruby signal interrupts to be inserted
|
61
51
|
int sz = kevent(qfd, NULL, 0, qevents, MAX_E, &ts);
|
52
|
+
st_clear(handled_rids);
|
62
53
|
|
63
54
|
for (int i = 0; i < sz; i++) {
|
64
|
-
int fd = (int)qevents[i].ident;
|
65
55
|
if (qevents[i].flags & EV_EOF) {
|
56
|
+
int fd = (int)qevents[i].ident;
|
66
57
|
// EV_EOF is set if the read side of the socket is shutdown
|
67
58
|
// the event can keep flipping back to consume cpu if we don't remove it
|
68
59
|
DEL_E_WITH_FILTER(fd, qevents[i].filter);
|
69
60
|
}
|
70
61
|
if (qevents[i].filter & (EVFILT_READ | EVFILT_WRITE)) {
|
71
|
-
loop_body(
|
72
|
-
break;
|
62
|
+
loop_body((VALUE)qevents[i].udata);
|
73
63
|
}
|
74
64
|
}
|
75
65
|
loop_check();
|
data/ext/nyara.c
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
#include <sys/fcntl.h>
|
8
8
|
|
9
9
|
rb_encoding* u8_encoding;
|
10
|
+
static VALUE nyara;
|
10
11
|
|
11
12
|
void nyara_set_nonblock(int fd) {
|
12
13
|
int flags;
|
@@ -30,11 +31,24 @@ static void set_fd_limit(int nofiles) {
|
|
30
31
|
}
|
31
32
|
}
|
32
33
|
|
34
|
+
static bool summary_request = false;
|
35
|
+
void nyara_summary_request(int method, VALUE path, VALUE controller) {
|
36
|
+
if (summary_request) {
|
37
|
+
rb_funcall(nyara, rb_intern("summary_request"), 3, INT2NUM(method), path, controller);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
// set whether should log summary of request
|
42
|
+
static VALUE ext_summary_request(VALUE _, VALUE toggle) {
|
43
|
+
summary_request = RTEST(toggle);
|
44
|
+
return toggle;
|
45
|
+
}
|
46
|
+
|
33
47
|
void Init_nyara() {
|
34
48
|
u8_encoding = rb_utf8_encoding();
|
35
49
|
set_fd_limit(20000);
|
36
50
|
|
37
|
-
|
51
|
+
nyara = rb_define_module("Nyara");
|
38
52
|
# include "inc/version.inc"
|
39
53
|
rb_const_set(nyara, rb_intern("VERSION"), rb_enc_str_new(NYARA_VERSION, strlen(NYARA_VERSION), u8_encoding));
|
40
54
|
|
@@ -66,10 +80,11 @@ void Init_nyara() {
|
|
66
80
|
OBJ_FREEZE(status_map);
|
67
81
|
|
68
82
|
VALUE ext = rb_define_module_under(nyara, "Ext");
|
83
|
+
rb_define_singleton_method(ext, "summary_request", ext_summary_request, 1);
|
69
84
|
Init_accept(ext);
|
70
85
|
Init_mime(ext);
|
71
86
|
Init_request(nyara, ext);
|
72
|
-
Init_request_parse(nyara);
|
87
|
+
Init_request_parse(nyara, ext);
|
73
88
|
Init_test_response(nyara);
|
74
89
|
Init_event(ext);
|
75
90
|
Init_route(nyara, ext);
|
data/ext/nyara.h
CHANGED
@@ -9,19 +9,22 @@
|
|
9
9
|
#undef NDEBUG
|
10
10
|
#endif
|
11
11
|
|
12
|
+
#define nyara_inspect(value) do {\
|
13
|
+
volatile VALUE _xx = rb_inspect(value);\
|
14
|
+
printf("%s: %.*s\n", __func__, (int)RSTRING_LEN(_xx), RSTRING_PTR(_xx));\
|
15
|
+
} while(0)
|
12
16
|
|
13
17
|
/* event.c */
|
14
18
|
void Init_event(VALUE ext);
|
15
|
-
void
|
19
|
+
void nyara_detach_rid(VALUE rid);
|
16
20
|
|
17
21
|
|
18
22
|
/* request_parse.c */
|
19
|
-
void Init_request_parse(VALUE nyara);
|
23
|
+
void Init_request_parse(VALUE nyara, VALUE ext);
|
20
24
|
|
21
25
|
|
22
26
|
/* request.c */
|
23
27
|
void Init_request(VALUE nyara, VALUE ext);
|
24
|
-
VALUE nyara_request_new(int fd);
|
25
28
|
void nyara_request_init_env(VALUE request);
|
26
29
|
void nyara_request_term_close(VALUE request);
|
27
30
|
bool nyara_send_data(int fd, const char* s, long len);
|
@@ -75,4 +78,5 @@ extern RouteResult nyara_lookup_route(enum http_method method_num, VALUE vpath,
|
|
75
78
|
|
76
79
|
/* nyara.c */
|
77
80
|
void nyara_set_nonblock(int fd);
|
81
|
+
void nyara_summary_request(int method, VALUE path, VALUE controller);
|
78
82
|
extern rb_encoding* u8_encoding;
|