iodine 0.4.19 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/CHANGELOG.md +22 -0
  4. data/LIMITS.md +19 -9
  5. data/README.md +92 -77
  6. data/SPEC-PubSub-Draft.md +113 -0
  7. data/SPEC-Websocket-Draft.md +127 -143
  8. data/bin/http-hello +0 -1
  9. data/bin/raw-rbhttp +1 -1
  10. data/bin/raw_broadcast +8 -10
  11. data/bin/updated api +2 -2
  12. data/bin/ws-broadcast +2 -4
  13. data/bin/ws-echo +2 -2
  14. data/examples/config.ru +13 -13
  15. data/examples/echo.ru +5 -6
  16. data/examples/hello.ru +2 -3
  17. data/examples/info.md +316 -0
  18. data/examples/pubsub_engine.ru +81 -0
  19. data/examples/redis.ru +9 -9
  20. data/examples/shootout.ru +45 -11
  21. data/ext/iodine/defer.c +194 -297
  22. data/ext/iodine/defer.h +61 -53
  23. data/ext/iodine/evio.c +0 -260
  24. data/ext/iodine/evio.h +50 -22
  25. data/ext/iodine/evio_callbacks.c +26 -0
  26. data/ext/iodine/evio_epoll.c +251 -0
  27. data/ext/iodine/evio_kqueue.c +193 -0
  28. data/ext/iodine/extconf.rb +1 -1
  29. data/ext/iodine/facil.c +1420 -542
  30. data/ext/iodine/facil.h +151 -64
  31. data/ext/iodine/fio_ary.h +418 -0
  32. data/ext/iodine/{base64.c → fio_base64.c} +33 -24
  33. data/ext/iodine/{base64.h → fio_base64.h} +6 -7
  34. data/ext/iodine/{fio_cli_helper.c → fio_cli.c} +77 -58
  35. data/ext/iodine/{fio_cli_helper.h → fio_cli.h} +9 -4
  36. data/ext/iodine/fio_hashmap.h +759 -0
  37. data/ext/iodine/fio_json_parser.h +651 -0
  38. data/ext/iodine/fio_llist.h +257 -0
  39. data/ext/iodine/fio_mem.c +672 -0
  40. data/ext/iodine/fio_mem.h +140 -0
  41. data/ext/iodine/fio_random.c +248 -0
  42. data/ext/iodine/{random.h → fio_random.h} +11 -14
  43. data/ext/iodine/{sha1.c → fio_sha1.c} +28 -24
  44. data/ext/iodine/{sha1.h → fio_sha1.h} +38 -16
  45. data/ext/iodine/{sha2.c → fio_sha2.c} +66 -49
  46. data/ext/iodine/{sha2.h → fio_sha2.h} +57 -26
  47. data/ext/iodine/{fiobj_internal.c → fio_siphash.c} +9 -90
  48. data/ext/iodine/fio_siphash.h +18 -0
  49. data/ext/iodine/fio_tmpfile.h +38 -0
  50. data/ext/iodine/fiobj.h +24 -7
  51. data/ext/iodine/fiobj4sock.h +23 -0
  52. data/ext/iodine/fiobj_ary.c +143 -226
  53. data/ext/iodine/fiobj_ary.h +17 -16
  54. data/ext/iodine/fiobj_data.c +1160 -0
  55. data/ext/iodine/fiobj_data.h +164 -0
  56. data/ext/iodine/fiobj_hash.c +298 -406
  57. data/ext/iodine/fiobj_hash.h +101 -54
  58. data/ext/iodine/fiobj_json.c +478 -601
  59. data/ext/iodine/fiobj_json.h +34 -9
  60. data/ext/iodine/fiobj_numbers.c +383 -51
  61. data/ext/iodine/fiobj_numbers.h +87 -11
  62. data/ext/iodine/fiobj_str.c +423 -184
  63. data/ext/iodine/fiobj_str.h +81 -32
  64. data/ext/iodine/fiobject.c +273 -522
  65. data/ext/iodine/fiobject.h +477 -112
  66. data/ext/iodine/http.c +2243 -83
  67. data/ext/iodine/http.h +842 -121
  68. data/ext/iodine/http1.c +810 -385
  69. data/ext/iodine/http1.h +16 -39
  70. data/ext/iodine/http1_parser.c +146 -74
  71. data/ext/iodine/http1_parser.h +15 -4
  72. data/ext/iodine/http_internal.c +1258 -0
  73. data/ext/iodine/http_internal.h +226 -0
  74. data/ext/iodine/http_mime_parser.h +341 -0
  75. data/ext/iodine/iodine.c +86 -68
  76. data/ext/iodine/iodine.h +26 -11
  77. data/ext/iodine/iodine_helpers.c +8 -7
  78. data/ext/iodine/iodine_http.c +487 -324
  79. data/ext/iodine/iodine_json.c +304 -0
  80. data/ext/iodine/iodine_json.h +6 -0
  81. data/ext/iodine/iodine_protocol.c +107 -45
  82. data/ext/iodine/iodine_pubsub.c +526 -225
  83. data/ext/iodine/iodine_pubsub.h +10 -0
  84. data/ext/iodine/iodine_websockets.c +268 -510
  85. data/ext/iodine/iodine_websockets.h +2 -4
  86. data/ext/iodine/pubsub.c +726 -432
  87. data/ext/iodine/pubsub.h +85 -103
  88. data/ext/iodine/rb-call.c +4 -4
  89. data/ext/iodine/rb-defer.c +46 -22
  90. data/ext/iodine/rb-fiobj2rb.h +117 -0
  91. data/ext/iodine/rb-rack-io.c +73 -238
  92. data/ext/iodine/rb-rack-io.h +2 -2
  93. data/ext/iodine/rb-registry.c +35 -93
  94. data/ext/iodine/rb-registry.h +1 -0
  95. data/ext/iodine/redis_engine.c +742 -304
  96. data/ext/iodine/redis_engine.h +42 -39
  97. data/ext/iodine/resp_parser.h +311 -0
  98. data/ext/iodine/sock.c +627 -490
  99. data/ext/iodine/sock.h +345 -297
  100. data/ext/iodine/spnlock.inc +15 -4
  101. data/ext/iodine/websocket_parser.h +16 -20
  102. data/ext/iodine/websockets.c +188 -257
  103. data/ext/iodine/websockets.h +24 -133
  104. data/lib/iodine.rb +52 -7
  105. data/lib/iodine/cli.rb +6 -24
  106. data/lib/iodine/json.rb +40 -0
  107. data/lib/iodine/version.rb +1 -1
  108. data/lib/iodine/websocket.rb +5 -3
  109. data/lib/rack/handler/iodine.rb +58 -13
  110. metadata +38 -48
  111. data/bin/ws-shootout +0 -107
  112. data/examples/broadcast.ru +0 -56
  113. data/ext/iodine/bscrypt-common.h +0 -116
  114. data/ext/iodine/bscrypt.h +0 -49
  115. data/ext/iodine/fio2resp.c +0 -60
  116. data/ext/iodine/fio2resp.h +0 -51
  117. data/ext/iodine/fio_dict.c +0 -446
  118. data/ext/iodine/fio_dict.h +0 -99
  119. data/ext/iodine/fio_hash_table.h +0 -370
  120. data/ext/iodine/fio_list.h +0 -111
  121. data/ext/iodine/fiobj_internal.h +0 -280
  122. data/ext/iodine/fiobj_primitives.c +0 -131
  123. data/ext/iodine/fiobj_primitives.h +0 -55
  124. data/ext/iodine/fiobj_sym.c +0 -135
  125. data/ext/iodine/fiobj_sym.h +0 -60
  126. data/ext/iodine/hex.c +0 -124
  127. data/ext/iodine/hex.h +0 -70
  128. data/ext/iodine/http1_request.c +0 -81
  129. data/ext/iodine/http1_request.h +0 -58
  130. data/ext/iodine/http1_response.c +0 -417
  131. data/ext/iodine/http1_response.h +0 -95
  132. data/ext/iodine/http_request.c +0 -111
  133. data/ext/iodine/http_request.h +0 -102
  134. data/ext/iodine/http_response.c +0 -1703
  135. data/ext/iodine/http_response.h +0 -250
  136. data/ext/iodine/misc.c +0 -182
  137. data/ext/iodine/misc.h +0 -74
  138. data/ext/iodine/random.c +0 -208
  139. data/ext/iodine/redis_connection.c +0 -278
  140. data/ext/iodine/redis_connection.h +0 -86
  141. data/ext/iodine/resp.c +0 -842
  142. data/ext/iodine/resp.h +0 -261
  143. data/ext/iodine/siphash.c +0 -154
  144. data/ext/iodine/siphash.h +0 -22
  145. data/ext/iodine/xor-crypt.c +0 -193
  146. data/ext/iodine/xor-crypt.h +0 -107
@@ -51,198 +51,64 @@ close must never be called on the input stream.
51
51
  Core data / helpers
52
52
  */
53
53
 
54
- static VALUE rRackStrIO;
55
- static VALUE rRackFileIO;
54
+ static VALUE rRackIO;
56
55
 
57
- static ID pos_id;
58
- static ID end_id;
59
56
  static ID env_id;
60
57
  static ID io_id;
61
58
 
62
59
  static VALUE TCPSOCKET_CLASS;
63
60
  static ID for_fd_id;
64
61
 
65
- #define set_uuid(object, request) \
66
- rb_ivar_set((object), iodine_fd_var_id, ULONG2NUM((request)->fd))
62
+ #define set_handle(object, handle) \
63
+ rb_ivar_set((object), iodine_fd_var_id, ULL2NUM((uintptr_t)handle))
67
64
 
68
- inline static intptr_t get_uuid(VALUE obj) {
65
+ inline static http_s *get_handle(VALUE obj) {
69
66
  VALUE i = rb_ivar_get(obj, iodine_fd_var_id);
70
- return (intptr_t)FIX2ULONG(i);
71
- }
72
-
73
- #define set_pos(object, pos) rb_ivar_set((object), pos_id, ULONG2NUM(pos))
74
-
75
- inline static size_t get_pos(VALUE obj) {
76
- VALUE i = rb_ivar_get(obj, pos_id);
77
- return (size_t)FIX2ULONG(i);
78
- }
79
-
80
- inline static size_t get_end(VALUE obj) {
81
- VALUE i = rb_ivar_get(obj, end_id);
82
- return (size_t)FIX2ULONG(i);
67
+ return (http_s *)FIX2ULONG(i);
83
68
  }
84
69
 
85
70
  /* *****************************************************************************
86
- StrIO API
71
+ IO API
87
72
  */
88
73
 
89
- // a macro helper to get the server pointer embeded in an object
90
- inline static char *get_str(VALUE obj) {
91
- VALUE i = rb_ivar_get(obj, io_id);
92
- return (char *)FIX2ULONG(i);
93
- }
94
-
95
- /**
96
- Gets returns a line. this is okay for small lines,
97
- but shouldn't really be used.
98
-
99
- Limited to ~ 1Mb of a line length.
100
- */
101
- static VALUE strio_gets(VALUE self) {
102
- char *str = get_str(self);
103
- size_t pos = get_pos(self);
104
- size_t end = get_end(self);
105
- if (str == NULL || pos == end)
106
- return Qnil;
107
- size_t pos_e = pos;
108
-
109
- while ((pos_e < end) && str[pos_e] != '\n')
110
- pos_e++;
111
- set_pos(self, pos_e + 1);
112
- return rb_enc_str_new(str + pos, pos_e - pos, IodineBinaryEncoding);
113
- }
114
-
115
- // Reads data from the IO, according to the Rack specifications for `#read`.
116
- static VALUE strio_read(int argc, VALUE *argv, VALUE self) {
117
- char *str = get_str(self);
118
- size_t pos = get_pos(self);
119
- size_t end = get_end(self);
120
- VALUE buffer = Qnil;
121
- char ret_nil = 0;
122
- ssize_t len = 0;
123
- // get the buffer object if given
124
- if (argc == 2) {
125
- Check_Type(argv[1], T_STRING);
126
- buffer = argv[1];
127
- }
128
- // get the length object, if given
129
- if (argc > 0 && argv[0] != Qnil) {
130
- Check_Type(argv[0], T_FIXNUM);
131
- len = FIX2LONG(argv[0]);
132
- if (len < 0)
133
- rb_raise(rb_eRangeError, "length should be bigger then 0.");
134
- ret_nil = 1;
135
- }
136
- // return if we're at the EOF.
137
- if (str == NULL)
138
- goto no_data;
139
- // calculate length if it wasn't specified.
140
- if (len == 0) {
141
- // make sure we're not reading more then we have (string buffer)
142
- len = end - pos;
143
- // set position for future reads
144
- set_pos(self, end);
145
- if (len == 0)
146
- goto no_data;
147
- } else {
148
- // set position for future reads
149
- set_pos(self, pos + len);
150
- }
151
- if (len + pos > end)
152
- len = end - pos;
153
- // create the buffer if we don't have one.
154
- if (buffer == Qnil) {
155
- buffer = rb_str_buf_new(len);
156
- // make sure the buffer is binary encoded.
157
- rb_enc_associate(buffer, IodineBinaryEncoding);
158
- } else {
159
- // make sure the buffer is binary encoded.
160
- rb_enc_associate(buffer, IodineBinaryEncoding);
161
- if (rb_str_capacity(buffer) < (size_t)len)
162
- rb_str_resize(buffer, len);
163
- }
164
- // read the data.
165
- memcpy(RSTRING_PTR(buffer), str + pos, len);
166
- rb_str_set_len(buffer, len);
167
- return buffer;
168
- no_data:
169
- if (ret_nil)
170
- return Qnil;
171
- else
172
- return rb_str_buf_new(0);
173
- }
174
-
175
- // Does nothing - this is controlled by the server.
176
- static VALUE strio_close(VALUE self) {
177
- (void)self;
178
- return Qnil;
74
+ static inline FIOBJ get_data(VALUE self) {
75
+ VALUE i = rb_ivar_get(self, io_id);
76
+ return (FIOBJ)FIX2ULONG(i);
179
77
  }
180
78
 
181
- // Rewinds the IO, so that it is read from the begining.
182
79
  static VALUE rio_rewind(VALUE self) {
183
- set_pos(self, 0);
184
- return self;
185
- }
186
-
187
- // Passes each line of the input to the block. This should be avoided.
188
- static VALUE strio_each(VALUE self) {
189
- rb_need_block();
190
- rio_rewind(self);
191
- VALUE str = Qnil;
192
- while ((str = strio_gets(self)) != Qnil) {
193
- rb_yield(str);
194
- }
195
- return self;
196
- }
197
-
198
- /* *****************************************************************************
199
- TempFileIO API
200
- */
201
-
202
- // a macro helper to get the server pointer embeded in an object
203
- inline static int get_tmpfile(VALUE obj) {
204
- VALUE i = rb_ivar_get(obj, io_id);
205
- return (int)FIX2INT(i);
80
+ FIOBJ io = get_data(self);
81
+ if (!FIOBJ_TYPE_IS(io, FIOBJ_T_DATA))
82
+ return Qnil;
83
+ fiobj_data_seek(io, 0);
84
+ return INT2NUM(0);
206
85
  }
207
-
208
86
  /**
209
87
  Gets returns a line. this is okay for small lines,
210
88
  but shouldn't really be used.
211
89
 
212
90
  Limited to ~ 1Mb of a line length.
213
91
  */
214
- static VALUE tfio_gets(VALUE self) {
215
- int fd = get_tmpfile(self);
216
- size_t pos = get_pos(self);
217
- size_t end = get_end(self);
218
- if (pos == end)
92
+ static VALUE rio_gets(VALUE self) {
93
+ FIOBJ io = get_data(self);
94
+ if (!FIOBJ_TYPE_IS(io, FIOBJ_T_DATA))
219
95
  return Qnil;
220
- size_t pos_e = pos;
221
- char c;
222
- int ret;
223
- VALUE buffer;
224
-
225
- do {
226
- ret = pread(fd, &c, 1, pos_e);
227
- } while (ret > 0 && c != '\n' && (++pos_e < end));
228
- set_pos(self, pos_e + 1);
229
- if (pos > pos_e) {
230
- buffer = rb_str_buf_new(pos_e - pos);
96
+ fio_cstr_s line = fiobj_data_gets(io);
97
+ if (line.len) {
98
+ VALUE buffer = rb_str_new(line.data, line.len);
231
99
  // make sure the buffer is binary encoded.
232
100
  rb_enc_associate(buffer, IodineBinaryEncoding);
233
- if (pread(fd, RSTRING_PTR(buffer), pos_e - pos, pos) < 0)
234
- return Qnil;
235
- rb_str_set_len(buffer, pos_e - pos);
236
101
  return buffer;
237
102
  }
238
103
  return Qnil;
239
104
  }
240
105
 
241
106
  // Reads data from the IO, according to the Rack specifications for `#read`.
242
- static VALUE tfio_read(int argc, VALUE *argv, VALUE self) {
243
- int fd = get_tmpfile(self);
244
- size_t pos = get_pos(self);
245
- size_t end = get_end(self);
107
+ static VALUE rio_read(int argc, VALUE *argv, VALUE self) {
108
+ FIOBJ io = get_data(self);
109
+ if (!FIOBJ_TYPE_IS(io, FIOBJ_T_DATA))
110
+ return Qnil;
111
+
246
112
  VALUE buffer = Qnil;
247
113
  char ret_nil = 0;
248
114
  ssize_t len = 0;
@@ -257,43 +123,27 @@ static VALUE tfio_read(int argc, VALUE *argv, VALUE self) {
257
123
  len = FIX2LONG(argv[0]);
258
124
  if (len < 0)
259
125
  rb_raise(rb_eRangeError, "length should be bigger then 0.");
126
+ if (len == 0)
127
+ return rb_str_buf_new(0);
260
128
  ret_nil = 1;
261
129
  }
262
130
  // return if we're at the EOF.
263
- if (pos == end)
264
- goto no_data;
265
- // calculate length if it wasn't specified.
266
- if (len == 0) {
267
- // make sure we're not reading more then we have
268
- len = end - pos;
269
- // set position for future reads
270
- set_pos(self, end);
271
- if (len == 0)
272
- goto no_data;
273
- } else {
274
- // set position for future reads
275
- set_pos(self, pos + len);
276
- }
277
- // limit read to what we have
278
- if (len + pos > end)
279
- len = end - pos;
280
- // create the buffer if we don't have one.
281
- if (buffer == Qnil) {
282
- buffer = rb_str_buf_new(len);
283
- // make sure the buffer is binary encoded.
284
- rb_enc_associate(buffer, IodineBinaryEncoding);
285
- } else {
286
- // make sure the buffer is binary encoded.
287
- rb_enc_associate(buffer, IodineBinaryEncoding);
288
- if (rb_str_capacity(buffer) < (size_t)len)
289
- rb_str_resize(buffer, len);
131
+ fio_cstr_s buf = fiobj_data_read(io, len);
132
+ if (buf.len) {
133
+ // create the buffer if we don't have one.
134
+ if (buffer == Qnil) {
135
+ // make sure the buffer is binary encoded.
136
+ buffer = rb_enc_str_new(buf.data, buf.len, IodineBinaryEncoding);
137
+ } else {
138
+ // make sure the buffer is binary encoded.
139
+ rb_enc_associate(buffer, IodineBinaryEncoding);
140
+ if (rb_str_capacity(buffer) < (size_t)buf.len)
141
+ rb_str_resize(buffer, buf.len);
142
+ memcpy(RSTRING_PTR(buffer), buf.data, buf.len);
143
+ rb_str_set_len(buffer, buf.len);
144
+ }
145
+ return buffer;
290
146
  }
291
- // read the data.
292
- if (pread(fd, RSTRING_PTR(buffer), len, pos) <= 0)
293
- goto no_data;
294
- rb_str_set_len(buffer, len);
295
- return buffer;
296
- no_data:
297
147
  if (ret_nil)
298
148
  return Qnil;
299
149
  else
@@ -301,17 +151,20 @@ no_data:
301
151
  }
302
152
 
303
153
  // Does nothing - this is controlled by the server.
304
- static VALUE tfio_close(VALUE self) {
154
+ static VALUE rio_close(VALUE self) {
155
+ FIOBJ io = get_data(self);
156
+ fiobj_free(io);
157
+ rb_ivar_set(self, io_id, INT2NUM(0));
305
158
  (void)self;
306
159
  return Qnil;
307
160
  }
308
161
 
309
162
  // Passes each line of the input to the block. This should be avoided.
310
- static VALUE tfio_each(VALUE self) {
163
+ static VALUE rio_each(VALUE self) {
311
164
  rb_need_block();
312
165
  rio_rewind(self);
313
166
  VALUE str = Qnil;
314
- while ((str = tfio_gets(self)) != Qnil) {
167
+ while ((str = rio_gets(self)) != Qnil) {
315
168
  rb_yield(str);
316
169
  }
317
170
  return self;
@@ -329,17 +182,21 @@ extern VALUE IODINE_R_HIJACK_IO; // for Rack: rack.hijack_io
329
182
  static VALUE rio_get_io(int argc, VALUE *argv, VALUE self) {
330
183
  if (TCPSOCKET_CLASS == Qnil)
331
184
  return Qfalse;
332
- intptr_t fduuid = get_uuid(self);
333
- // hijack the IO object
334
- VALUE fd = INT2FIX(sock_uuid2fd(fduuid));
335
185
  VALUE env = rb_ivar_get(self, env_id);
336
- // make sure we're not repeating ourselves
337
- VALUE new_io = rb_hash_aref(env, IODINE_R_HIJACK_IO);
338
- if (new_io != Qnil)
339
- return new_io;
186
+ http_s *h = get_handle(self);
187
+ if (h == NULL) {
188
+ /* we're repeating ourselves, aren't we? */
189
+ VALUE io = rb_hash_aref(env, IODINE_R_HIJACK_IO);
190
+ return io;
191
+ }
192
+ // mark update
193
+ set_handle(self, NULL);
194
+ // hijack the IO object
195
+ intptr_t uuid = http_hijack(h, NULL);
196
+ VALUE fd = INT2FIX(sock_uuid2fd(uuid));
340
197
  // VALUE new_io = how the fuck do we create a new IO from the fd?
341
- new_io = RubyCaller.call2(TCPSOCKET_CLASS, for_fd_id, 1,
342
- &fd); // TCPSocket.for_fd(fd) ... cool...
198
+ VALUE new_io = RubyCaller.call2(TCPSOCKET_CLASS, for_fd_id, 1,
199
+ &fd); // TCPSocket.for_fd(fd) ... cool...
343
200
  rb_hash_aset(env, IODINE_R_HIJACK_IO, new_io);
344
201
  if (argc)
345
202
  rb_hash_aset(env, IODINE_R_HIJACK_CB, *argv);
@@ -351,53 +208,31 @@ C land API
351
208
  */
352
209
 
353
210
  // new object
354
- static VALUE new_rack_io(http_request_s *request, VALUE env) {
355
- VALUE rack_io;
356
- if (request->body_file > 0) {
357
- rack_io = rb_funcall2(rRackFileIO, iodine_new_func_id, 0, NULL);
358
- rb_ivar_set(rack_io, io_id, ULONG2NUM(request->body_file));
359
- lseek(request->body_file, 0, SEEK_SET);
360
- } else {
361
- rack_io = rb_funcall2(rRackStrIO, iodine_new_func_id, 0, NULL);
362
- rb_ivar_set(rack_io, io_id, ULONG2NUM(((intptr_t)request->body_str)));
363
- // fprintf(stderr, "rack body IO (%lu, %p):%.*s\n", request->content_length,
364
- // request->body_str, (int)request->content_length,
365
- // request->body_str);
366
- }
367
- set_uuid(rack_io, request);
368
- set_pos(rack_io, 0);
369
- rb_ivar_set(rack_io, end_id, ULONG2NUM(request->content_length));
211
+ static VALUE new_rack_io(http_s *h, VALUE env) {
212
+ VALUE rack_io = rb_funcall2(rRackIO, iodine_new_func_id, 0, NULL);
213
+ rb_ivar_set(rack_io, io_id, ULL2NUM(h->body));
214
+ set_handle(rack_io, h);
370
215
  rb_ivar_set(rack_io, env_id, env);
371
-
372
216
  return rack_io;
373
217
  }
374
218
 
375
219
  // initialize library
376
220
  static void init_rack_io(void) {
377
- rRackStrIO = rb_define_class_under(IodineBase, "RackStrIO", rb_cObject);
378
- rRackFileIO = rb_define_class_under(IodineBase, "RackTmpFileIO", rb_cObject);
221
+ rRackIO = rb_define_class_under(IodineBase, "RackIO", rb_cObject);
379
222
 
380
- pos_id = rb_intern("pos");
381
- end_id = rb_intern("io_end");
382
223
  io_id = rb_intern("rack_io");
383
224
  env_id = rb_intern("env");
384
225
  for_fd_id = rb_intern("for_fd");
385
226
 
386
227
  TCPSOCKET_CLASS = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
387
228
  // IO methods
388
- rb_define_method(rRackStrIO, "rewind", rio_rewind, 0);
389
- rb_define_method(rRackStrIO, "gets", strio_gets, 0);
390
- rb_define_method(rRackStrIO, "read", strio_read, -1);
391
- rb_define_method(rRackStrIO, "close", strio_close, 0);
392
- rb_define_method(rRackStrIO, "each", strio_each, 0);
393
- rb_define_method(rRackStrIO, "_hijack", rio_get_io, -1);
394
-
395
- rb_define_method(rRackFileIO, "rewind", rio_rewind, 0);
396
- rb_define_method(rRackFileIO, "gets", tfio_gets, 0);
397
- rb_define_method(rRackFileIO, "read", tfio_read, -1);
398
- rb_define_method(rRackFileIO, "close", tfio_close, 0);
399
- rb_define_method(rRackFileIO, "each", tfio_each, 0);
400
- rb_define_method(rRackFileIO, "_hijack", rio_get_io, -1);
229
+
230
+ rb_define_method(rRackIO, "rewind", rio_rewind, 0);
231
+ rb_define_method(rRackIO, "gets", rio_gets, 0);
232
+ rb_define_method(rRackIO, "read", rio_read, -1);
233
+ rb_define_method(rRackIO, "close", rio_close, 0);
234
+ rb_define_method(rRackIO, "each", rio_each, 0);
235
+ rb_define_method(rRackIO, "_hijack", rio_get_io, -1);
401
236
  }
402
237
 
403
238
  ////////////////////////////////////////////////////////////////////////////
@@ -9,10 +9,10 @@ Feel free to copy, use and enjoy according to the license provided.
9
9
 
10
10
  #include <ruby.h>
11
11
 
12
- #include "http_request.h"
12
+ #include "http.h"
13
13
 
14
14
  extern struct IodineRackIO {
15
- VALUE (*create)(http_request_s *request, VALUE env);
15
+ VALUE (*create)(http_s *h, VALUE env);
16
16
  void (*init)(void);
17
17
  } IodineRackIO;
18
18
 
@@ -9,81 +9,38 @@ Feel free to copy, use and enjoy according to the license provided.
9
9
 
10
10
  #include "spnlock.inc"
11
11
 
12
- #include "fio_hash_table.h"
13
- #include <signal.h>
12
+ #define FIO_OVERRIDE_MALLOC 1
13
+ #include "fio_mem.h"
14
14
 
15
- // #define RUBY_REG_DBG
16
- #ifndef REGISTRY_POOL_SIZE
17
- #define REGISTRY_POOL_SIZE 1024
18
- #endif
15
+ #include "fio_hashmap.h"
16
+ #include <signal.h>
19
17
 
20
18
  #ifndef RUBY_REG_DBG
21
19
  #define RUBY_REG_DBG 0
22
20
  #endif
23
21
 
24
- typedef struct {
25
- union {
26
- fio_list_s pool;
27
- fio_ht_node_s node;
28
- };
29
- VALUE obj;
30
- volatile uint64_t ref;
31
- } obj_s;
32
-
33
22
  // the registry state keeper
34
23
  static struct {
35
- obj_s pool_mem[REGISTRY_POOL_SIZE];
36
- fio_list_s pool;
37
- fio_ht_s store;
24
+ fio_hash_s store;
38
25
  VALUE owner;
39
26
  spn_lock_i lock;
40
- } registry = {.pool = FIO_LIST_INIT_STATIC(registry.pool),
41
- .store = FIO_HASH_TABLE_STATIC(registry.store),
42
- .owner = 0,
43
- .lock = SPN_LOCK_INIT};
27
+ } registry = {.store = {.capa = 0}, .owner = 0, .lock = SPN_LOCK_INIT};
44
28
 
45
29
  #define try_lock_registry() spn_trylock(&registry.lock)
46
30
  #define unlock_registry() spn_unlock(&registry.lock)
47
31
  #define lock_registry() spn_lock(&registry.lock)
48
32
 
49
- inline static void free_node(obj_s *to_free) {
50
- if (to_free >= registry.pool_mem &&
51
- (intptr_t)to_free <= (intptr_t)(&registry.pool))
52
- fio_list_push(obj_s, pool, registry.pool, to_free);
53
- else
54
- free(to_free);
55
- }
56
-
57
33
  /** adds an object to the registry or increases it's reference count. */
58
34
  static VALUE register_object(VALUE ruby_obj) {
59
35
  if (!ruby_obj || ruby_obj == Qnil || ruby_obj == Qfalse)
60
36
  return 0;
61
37
  lock_registry();
62
- obj_s *obj = (void *)fio_ht_find(&registry.store, (uint64_t)ruby_obj);
63
- if (obj) {
64
- obj = fio_node2obj(obj_s, node, obj);
38
+ uintptr_t count = (uintptr_t)fio_hash_find(&registry.store, ruby_obj);
65
39
  #if RUBY_REG_DBG == 1
66
- fprintf(stderr, "Ruby Registry: register %p ref: %" PRIu64 " + 1\n",
67
- (void *)ruby_obj, obj->ref);
40
+ fprintf(stderr, "Ruby Registry: register %p ref: %" PRIu64 " + 1\n",
41
+ (void *)ruby_obj, (uint64_t)count);
68
42
  #endif
69
- goto exists;
70
- }
71
- #if RUBY_REG_DBG == 1
72
- fprintf(stderr, "Ruby Registry: register %p\n", (void *)ruby_obj);
73
- #endif
74
- obj = fio_list_pop(obj_s, pool, registry.pool);
75
- if (!obj)
76
- obj = malloc(sizeof(obj_s));
77
- if (!obj) {
78
- perror("No Memory!");
79
- kill(0, SIGINT);
80
- exit(1);
81
- }
82
- *obj = (obj_s){.obj = ruby_obj};
83
- fio_ht_add(&registry.store, &obj->node, (uint64_t)ruby_obj);
84
- exists:
85
- spn_add(&obj->ref, 1);
86
-
43
+ fio_hash_insert(&registry.store, (uint64_t)ruby_obj, (void *)(count + 1));
87
44
  unlock_registry();
88
45
  return ruby_obj;
89
46
  }
@@ -93,30 +50,15 @@ static void unregister_object(VALUE ruby_obj) {
93
50
  if (!ruby_obj || ruby_obj == Qnil)
94
51
  return;
95
52
  lock_registry();
96
- obj_s *obj = (void *)fio_ht_find(&registry.store, (uint64_t)ruby_obj);
97
- if (!obj) {
53
+ uintptr_t count = (uintptr_t)fio_hash_find(&registry.store, ruby_obj);
98
54
  #if RUBY_REG_DBG == 1
99
- fprintf(stderr, "Ruby Registry: unregister - NOT FOUND %p\n",
100
- (void *)ruby_obj);
55
+ fprintf(stderr, "Ruby Registry: unregister %p ref: %" PRIu64 " - 1\n",
56
+ (void *)ruby_obj, (uint64_t)count);
101
57
  #endif
102
- goto finish;
58
+ if (count) {
59
+ fio_hash_insert(&registry.store, (uint64_t)ruby_obj, (void *)(count - 1));
103
60
  }
104
- obj = fio_node2obj(obj_s, node, obj);
105
- if (spn_sub(&obj->ref, 1)) {
106
- unlock_registry();
107
- #if RUBY_REG_DBG == 1
108
- fprintf(stderr, "Ruby Registry: unregistered %p ref: %" PRIu64 " \n",
109
- (void *)ruby_obj, obj->ref);
110
- #endif
111
- return;
112
- }
113
- fio_ht_remove(&obj->node);
114
- free_node(obj);
115
- finish:
116
61
  unlock_registry();
117
- #if RUBY_REG_DBG == 1
118
- fprintf(stderr, "Ruby Registry: unregistered %p\n", (void *)ruby_obj);
119
- #endif
120
62
  }
121
63
 
122
64
  /* a callback for the GC (marking active objects) */
@@ -126,8 +68,12 @@ static void registry_mark(void *ignore) {
126
68
  Registry.print();
127
69
  #endif
128
70
  lock_registry();
129
- obj_s *obj;
130
- fio_ht_for_each(obj_s, node, obj, registry.store) rb_gc_mark(obj->obj);
71
+ fio_hash_compact(&registry.store);
72
+ FIO_HASH_FOR_LOOP(&registry.store, pos) {
73
+ if (pos->obj) {
74
+ rb_gc_mark((VALUE)pos->key);
75
+ }
76
+ }
131
77
  unlock_registry();
132
78
  }
133
79
 
@@ -138,13 +84,9 @@ static void registry_clear(void *ignore) {
138
84
  fprintf(stderr, "Ruby Registry: Clear!!!\n");
139
85
  #endif
140
86
  lock_registry();
141
- obj_s *obj;
142
- fio_ht_for_each(obj_s, node, obj, registry.store) {
143
- fio_ht_remove(&obj->node);
144
- rb_gc_mark(obj->obj);
145
- }
87
+ fio_hash_free(&registry.store);
146
88
  registry.owner = 0;
147
- fio_ht_free(&registry.store);
89
+ registry.store = (fio_hash_s){.capa = 0};
148
90
  unlock_registry();
149
91
  }
150
92
 
@@ -172,29 +114,28 @@ static void init(VALUE owner) {
172
114
  VALUE r_registry =
173
115
  TypedData_Wrap_Struct(rReferences, &my_registry_type_struct, &registry);
174
116
  rb_ivar_set(owner, rb_intern("registry"), r_registry);
175
- // initialize memory pool
176
- for (size_t i = 0; i < REGISTRY_POOL_SIZE; i++) {
177
- fio_list_push(obj_s, pool, registry.pool, &registry.pool_mem[i]);
178
- }
179
117
  finish:
180
118
  unlock_registry();
181
119
  }
182
120
 
121
+ static void registry_on_fork(void) { unlock_registry(); }
122
+
183
123
  /* print data, for testing */
184
124
  static void print(void) {
185
125
  lock_registry();
186
126
  fprintf(stderr, "Registry owner is %lu\n", registry.owner);
187
- obj_s *obj;
188
- uint64_t index = 0;
189
- fio_ht_for_each(obj_s, node, obj, registry.store) {
190
- fprintf(stderr, "[%" PRIu64 " ] => %" PRIu64 " X obj %p type %d at %p\n",
191
- index++, obj->ref, (void *)obj->obj, TYPE(obj->obj), (void *)obj);
127
+ uintptr_t index = 0;
128
+ FIO_HASH_FOR_LOOP(&registry.store, pos) {
129
+ if (pos->obj) {
130
+ fprintf(stderr, "[%" PRIuPTR " ] => %" PRIuPTR " X obj %p type %d\n",
131
+ index++, (uintptr_t)pos->obj, (void *)pos->key, TYPE(pos->key));
132
+ }
192
133
  }
193
- fprintf(stderr, "Total of %" PRIu64 " registered objects being marked\n",
134
+ fprintf(stderr, "Total of %" PRIuPTR " registered objects being marked\n",
194
135
  index);
195
136
  fprintf(stderr,
196
- "Registry uses %" PRIu64 " Hash bins for %" PRIu64 " objects\n",
197
- registry.store.bin_count, registry.store.count);
137
+ "Registry uses %" PRIuPTR " Hash bins for %" PRIuPTR " objects\n",
138
+ registry.store.capa, registry.store.count);
198
139
  unlock_registry();
199
140
  }
200
141
 
@@ -205,4 +146,5 @@ struct ___RegistryClass___ Registry = {
205
146
  .remove = unregister_object,
206
147
  .add = register_object,
207
148
  .print = print,
149
+ .on_fork = registry_on_fork,
208
150
  };