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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nyara +17 -0
  3. data/changes +12 -0
  4. data/copying +10 -0
  5. data/ext/event.c +78 -68
  6. data/ext/extconf.rb +7 -0
  7. data/ext/inc/epoll.h +12 -20
  8. data/ext/inc/kqueue.h +8 -18
  9. data/ext/nyara.c +17 -2
  10. data/ext/nyara.h +7 -3
  11. data/ext/request.c +35 -7
  12. data/ext/request.h +3 -0
  13. data/ext/request_parse.c +26 -7
  14. data/ext/url_encoded.c +22 -11
  15. data/lib/nyara/command.rb +79 -0
  16. data/lib/nyara/config.rb +88 -26
  17. data/lib/nyara/controller.rb +175 -110
  18. data/lib/nyara/cookie.rb +2 -2
  19. data/lib/nyara/flash.rb +3 -2
  20. data/lib/nyara/hashes/config_hash.rb +18 -5
  21. data/lib/nyara/hashes/header_hash.rb +3 -2
  22. data/lib/nyara/hashes/param_hash.rb +2 -0
  23. data/lib/nyara/mime_types.rb +1 -0
  24. data/lib/nyara/nyara.rb +47 -25
  25. data/lib/nyara/part.rb +85 -39
  26. data/lib/nyara/request.rb +21 -4
  27. data/lib/nyara/route.rb +167 -8
  28. data/lib/nyara/session.rb +29 -22
  29. data/lib/nyara/templates/Gemfile +4 -0
  30. data/lib/nyara/templates/Rakefile +1 -0
  31. data/lib/nyara/templates/config/boot.rb +0 -0
  32. data/lib/nyara/templates/config/database.yml +28 -0
  33. data/lib/nyara/templates/config/development.rb +0 -0
  34. data/lib/nyara/templates/config/production.rb +0 -0
  35. data/lib/nyara/templates/config/session.key +1 -0
  36. data/lib/nyara/templates/config/test.rb +0 -0
  37. data/lib/nyara/templates/public/robot.txt +0 -0
  38. data/lib/nyara/templates/spec/spec_helper.rb +0 -0
  39. data/lib/nyara/test.rb +14 -11
  40. data/lib/nyara/view.rb +16 -9
  41. data/nyara.gemspec +18 -5
  42. data/rakefile +8 -2
  43. data/readme.md +26 -15
  44. data/spec/apps/connect.rb +1 -0
  45. data/spec/command_spec.rb +46 -0
  46. data/spec/config_spec.rb +14 -4
  47. data/spec/controller_spec.rb +24 -0
  48. data/spec/ext_route_spec.rb +3 -3
  49. data/spec/flash_spec.rb +0 -4
  50. data/spec/integration_spec.rb +63 -2
  51. data/spec/{part_spec.rb → multipart_spec.rb} +18 -0
  52. data/spec/raw_requests/multipart +20 -0
  53. data/spec/request_delegate_spec.rb +4 -0
  54. data/spec/request_spec.rb +8 -0
  55. data/spec/{route_entry_spec.rb → route_spec.rb} +58 -3
  56. data/spec/session_spec.rb +4 -4
  57. data/spec/spec_helper.rb +14 -7
  58. data/tools/hello.rb +21 -3
  59. metadata +42 -10
  60. data/lib/nyara/route_entry.rb +0 -111
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1464261ce5d4ec90868a68278e81de0124568897
4
- data.tar.gz: 566342b6927ac0fc3f5607580a0863d18b9be432
3
+ metadata.gz: abcd7918ded6547e4edadb0746742a854f3c216b
4
+ data.tar.gz: 8dfaf81082c63b6e117bfc6836210d3d6f8f9aa8
5
5
  SHA512:
6
- metadata.gz: c322de1bd85993df20041bd8535800751abdf4b4c8152b7ed4899a0430aed90d4552a97f21839267376f78bac18cc254fd395e9124cc071db8e4b3575ba6537c
7
- data.tar.gz: e7c16bb717db1c131069d361087a8d97e96b1282d93d002582aa10cd0bcff01741eedefa0d43ab65c18c9ec480e1c214d3f03218c4569a1bb3786194c43c46e8
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(int fd, int etype);
13
+ static void loop_body(VALUE rid);
21
14
  static void loop_check();
22
15
  static int qfd = 0;
23
-
24
- #define MAX_RECEIVE_DATA 65536 * 2
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
- static VALUE fd_request_map;
35
- static VALUE watch_request_map;
36
- static ID id_not_found;
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
- nyara_detach_fd(p->fd);
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
- nyara_detach_fd(p->fd);
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(int fd, int etype) {
131
- switch (etype) {
132
- case ETYPE_CAN_ACCEPT: {
133
- int cfd = accept(fd, NULL, NULL);
134
- if (cfd > 0) {
135
- nyara_set_nonblock(cfd);
136
- ADD_E(cfd, ETYPE_HANDLE_REQUEST);
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
- case ETYPE_HANDLE_REQUEST: {
141
- VALUE key = INT2FIX(fd);
142
- volatile VALUE request = rb_hash_aref(fd_request_map, key);
143
- if (request == Qnil) {
144
- request = nyara_request_new(fd);
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
- case ETYPE_CONNECT: {
151
- VALUE request = rb_hash_aref(watch_request_map, INT2FIX(fd));
152
- if (request != Qnil) {
153
- _handle_request(request);
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(to_resume_actions);
161
+ long len = RARRAY_LEN(to_resume_requests);
165
162
  if (len) {
166
- VALUE* ptr = RARRAY_PTR(to_resume_actions);
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]), ETYPE_CONNECT);
181
+ ADD_E(FIX2INT(v_fds[i]), p->rid);
183
182
  }
184
- ADD_E(p->fd, ETYPE_HANDLE_REQUEST);
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(fd_request_map, rb_intern("empty?"), 0))) {
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 nyara_detach_fd(int fd) {
199
- VALUE request = rb_hash_delete(fd_request_map, INT2FIX(fd));
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
- rb_hash_delete(watch_request_map, watched[i]);
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
- int fd = FIX2INT(v_server_fd);
220
- nyara_set_nonblock(fd);
221
- ADD_E(fd, ETYPE_CAN_ACCEPT);
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(to_resume_actions, request);
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, ETYPE_CONNECT);
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
- fd_request_map = rb_hash_new();
371
- rb_gc_register_mark_object(fd_request_map);
372
- watch_request_map = rb_hash_new();
373
- rb_gc_register_mark_object(watch_request_map);
374
- id_not_found = rb_intern("not_found");
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, uint64_t etype) {
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 = (etype << 32) | (uint64_t)fd;
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
- printf("%s: %s\n", __func__, strerror(errno));
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
- printf("%s: %s\n", __func__, strerror(errno));
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
- if (qevents[i].events & (EPOLLIN | EPOLLOUT)) {
54
- int fd = (int)(qevents[i].data.u64 & 0xFFFFFFFF);
55
- int etype = (int)(qevents[i].data.u64 >> 32);
56
- loop_body(fd, etype);
57
- break;
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, uint64_t etype) {
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*)etype);
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
- printf("%s: %s\n", __func__, strerror(errno));
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
- printf("%s: %s\n", __func__, strerror(errno));
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(fd, (int)qevents[i].udata);
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
- VALUE nyara = rb_define_module("Nyara");
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 nyara_detach_fd(int fd);
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;