iodine 0.6.5 → 0.7.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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +4 -4
  4. data/SPEC-Websocket-Draft.md +3 -6
  5. data/bin/mustache.rb +128 -0
  6. data/examples/test_template.mustache +16 -0
  7. data/ext/iodine/fio.c +9397 -0
  8. data/ext/iodine/fio.h +4723 -0
  9. data/ext/iodine/fio_ary.h +353 -54
  10. data/ext/iodine/fio_cli.c +351 -361
  11. data/ext/iodine/fio_cli.h +84 -105
  12. data/ext/iodine/fio_hashmap.h +70 -16
  13. data/ext/iodine/fio_json_parser.h +35 -24
  14. data/ext/iodine/fio_siphash.c +104 -4
  15. data/ext/iodine/fio_siphash.h +18 -2
  16. data/ext/iodine/fio_str.h +1218 -0
  17. data/ext/iodine/fio_tmpfile.h +1 -1
  18. data/ext/iodine/fiobj.h +13 -8
  19. data/ext/iodine/fiobj4sock.h +6 -8
  20. data/ext/iodine/fiobj_ary.c +107 -17
  21. data/ext/iodine/fiobj_ary.h +36 -4
  22. data/ext/iodine/fiobj_data.c +146 -127
  23. data/ext/iodine/fiobj_data.h +25 -23
  24. data/ext/iodine/fiobj_hash.c +7 -7
  25. data/ext/iodine/fiobj_hash.h +6 -5
  26. data/ext/iodine/fiobj_json.c +20 -17
  27. data/ext/iodine/fiobj_json.h +5 -5
  28. data/ext/iodine/fiobj_mem.h +71 -0
  29. data/ext/iodine/fiobj_mustache.c +310 -0
  30. data/ext/iodine/fiobj_mustache.h +40 -0
  31. data/ext/iodine/fiobj_numbers.c +199 -94
  32. data/ext/iodine/fiobj_numbers.h +7 -7
  33. data/ext/iodine/fiobj_str.c +142 -333
  34. data/ext/iodine/fiobj_str.h +65 -55
  35. data/ext/iodine/fiobject.c +49 -11
  36. data/ext/iodine/fiobject.h +40 -39
  37. data/ext/iodine/http.c +382 -190
  38. data/ext/iodine/http.h +124 -80
  39. data/ext/iodine/http1.c +99 -127
  40. data/ext/iodine/http1.h +5 -5
  41. data/ext/iodine/http1_parser.c +3 -2
  42. data/ext/iodine/http1_parser.h +2 -2
  43. data/ext/iodine/http_internal.c +14 -12
  44. data/ext/iodine/http_internal.h +25 -19
  45. data/ext/iodine/iodine.c +37 -18
  46. data/ext/iodine/iodine.h +4 -0
  47. data/ext/iodine/iodine_caller.c +9 -2
  48. data/ext/iodine/iodine_caller.h +2 -0
  49. data/ext/iodine/iodine_connection.c +82 -117
  50. data/ext/iodine/iodine_defer.c +57 -50
  51. data/ext/iodine/iodine_defer.h +0 -1
  52. data/ext/iodine/iodine_fiobj2rb.h +4 -2
  53. data/ext/iodine/iodine_helpers.c +4 -4
  54. data/ext/iodine/iodine_http.c +25 -32
  55. data/ext/iodine/iodine_json.c +2 -1
  56. data/ext/iodine/iodine_mustache.c +423 -0
  57. data/ext/iodine/iodine_mustache.h +6 -0
  58. data/ext/iodine/iodine_pubsub.c +48 -153
  59. data/ext/iodine/iodine_pubsub.h +5 -4
  60. data/ext/iodine/iodine_rack_io.c +7 -5
  61. data/ext/iodine/iodine_store.c +16 -13
  62. data/ext/iodine/iodine_tcp.c +26 -34
  63. data/ext/iodine/mustache_parser.h +1085 -0
  64. data/ext/iodine/redis_engine.c +740 -646
  65. data/ext/iodine/redis_engine.h +13 -15
  66. data/ext/iodine/resp_parser.h +11 -5
  67. data/ext/iodine/websocket_parser.h +13 -13
  68. data/ext/iodine/websockets.c +240 -393
  69. data/ext/iodine/websockets.h +52 -113
  70. data/lib/iodine.rb +1 -1
  71. data/lib/iodine/mustache.rb +140 -0
  72. data/lib/iodine/version.rb +1 -1
  73. metadata +15 -28
  74. data/ext/iodine/defer.c +0 -566
  75. data/ext/iodine/defer.h +0 -148
  76. data/ext/iodine/evio.c +0 -26
  77. data/ext/iodine/evio.h +0 -161
  78. data/ext/iodine/evio_callbacks.c +0 -26
  79. data/ext/iodine/evio_epoll.c +0 -251
  80. data/ext/iodine/evio_kqueue.c +0 -194
  81. data/ext/iodine/facil.c +0 -2325
  82. data/ext/iodine/facil.h +0 -616
  83. data/ext/iodine/fio_base64.c +0 -277
  84. data/ext/iodine/fio_base64.h +0 -71
  85. data/ext/iodine/fio_llist.h +0 -257
  86. data/ext/iodine/fio_mem.c +0 -675
  87. data/ext/iodine/fio_mem.h +0 -143
  88. data/ext/iodine/fio_random.c +0 -248
  89. data/ext/iodine/fio_random.h +0 -45
  90. data/ext/iodine/fio_sha1.c +0 -362
  91. data/ext/iodine/fio_sha1.h +0 -107
  92. data/ext/iodine/fio_sha2.c +0 -842
  93. data/ext/iodine/fio_sha2.h +0 -169
  94. data/ext/iodine/pubsub.c +0 -867
  95. data/ext/iodine/pubsub.h +0 -221
  96. data/ext/iodine/sock.c +0 -1366
  97. data/ext/iodine/sock.h +0 -566
  98. data/ext/iodine/spnlock.inc +0 -111
@@ -5,7 +5,7 @@ License: MIT
5
5
  #ifndef H_HTTP1_H
6
6
  #define H_HTTP1_H
7
7
 
8
- #include "http.h"
8
+ #include <http.h>
9
9
 
10
10
  #ifndef HTTP1_READ_BUFFER
11
11
  /**
@@ -17,13 +17,13 @@ License: MIT
17
17
 
18
18
  /** Creates an HTTP1 protocol object and handles any unread data in the buffer
19
19
  * (if any). */
20
- protocol_s *http1_new(uintptr_t uuid, http_settings_s *settings,
21
- void *unread_data, size_t unread_length);
20
+ fio_protocol_s *http1_new(uintptr_t uuid, http_settings_s *settings,
21
+ void *unread_data, size_t unread_length);
22
22
 
23
23
  /** Manually destroys the HTTP1 protocol object. */
24
- void http1_destroy(protocol_s *);
24
+ void http1_destroy(fio_protocol_s *);
25
25
 
26
26
  /** returns the HTTP/1.1 protocol's VTable. */
27
- void * http1_vtable(void);
27
+ void *http1_vtable(void);
28
28
 
29
29
  #endif
@@ -8,7 +8,8 @@ Feel free to copy, use and enjoy according to the license provided.
8
8
  #define __GNU_SOURCE
9
9
  #endif
10
10
 
11
- #include "http1_parser.h"
11
+ #include <http1_parser.h>
12
+
12
13
  #include <ctype.h>
13
14
  #include <stdio.h>
14
15
  #include <string.h>
@@ -357,7 +358,7 @@ inline static int consume_body(struct http1_fio_parser_args_s *args,
357
358
  /* *****************************************************************************
358
359
  HTTP/1.1 parsre function
359
360
  ***************************************************************************** */
360
- #ifdef DEBUG
361
+ #if DEBUG
361
362
  #include <assert.h>
362
363
  #else
363
364
  #define DEBUG 0
@@ -57,7 +57,7 @@ typedef struct http1_parser_s {
57
57
  /**
58
58
  * Available options for the parsing function.
59
59
  *
60
- * Callbacks should return 0 unless an error occured.
60
+ * Callbacks should return 0 unless an error occurred.
61
61
  */
62
62
  struct http1_fio_parser_args_s {
63
63
  /** REQUIRED: the parser object that manages the parser's state. */
@@ -90,7 +90,7 @@ struct http1_fio_parser_args_s {
90
90
  /** called when a body chunk is parsed. */
91
91
  int (*const on_body_chunk)(http1_parser_s *parser, char *data,
92
92
  size_t data_len);
93
- /** called when a protocol error occured. */
93
+ /** called when a protocol error occurred. */
94
94
  int (*const on_error)(http1_parser_s *parser);
95
95
  };
96
96
 
@@ -4,11 +4,9 @@ License: MIT
4
4
 
5
5
  Feel free to copy, use and enjoy according to the license provided.
6
6
  */
7
- #include "http_internal.h"
7
+ #include <http_internal.h>
8
8
 
9
- #include "fio_mem.h"
10
-
11
- #include "http1.h"
9
+ #include <http1.h>
12
10
 
13
11
  /* *****************************************************************************
14
12
  Internal Request / Response Handlers
@@ -45,7 +43,7 @@ void http_on_request_handler______internal(http_s *h,
45
43
  HTTP_HVALUE_SSE_MIME))
46
44
  goto eventsource;
47
45
  if (settings->public_folder) {
48
- fio_cstr_s path_str = fiobj_obj2cstr(h->path);
46
+ fio_str_info_s path_str = fiobj_obj2cstr(h->path);
49
47
  if (!http_sendfile2(h, settings->public_folder,
50
48
  settings->public_folder_length, path_str.data,
51
49
  path_str.len)) {
@@ -58,7 +56,7 @@ void http_on_request_handler______internal(http_s *h,
58
56
  upgrade:
59
57
  if (1) {
60
58
  fiobj_dup(t); /* allow upgrade name access after http_finish */
61
- fio_cstr_s val = fiobj_obj2cstr(t);
59
+ fio_str_info_s val = fiobj_obj2cstr(t);
62
60
  if (val.data[0] == 'h' && val.data[1] == '2') {
63
61
  http_send_error(h, 400);
64
62
  } else {
@@ -82,7 +80,7 @@ void http_on_response_handler______internal(http_s *h,
82
80
  settings->on_response(h);
83
81
  return;
84
82
  } else {
85
- fio_cstr_s val = fiobj_obj2cstr(t);
83
+ fio_str_info_s val = fiobj_obj2cstr(t);
86
84
  settings->on_upgrade(h, val.data, val.len);
87
85
  }
88
86
  }
@@ -94,12 +92,12 @@ Internal helpers
94
92
  int http_send_error2(size_t error, intptr_t uuid, http_settings_s *settings) {
95
93
  if (!uuid || !settings || !error)
96
94
  return -1;
97
- protocol_s *pr = http1_new(uuid, settings, NULL, 0);
95
+ fio_protocol_s *pr = http1_new(uuid, settings, NULL, 0);
98
96
  http_s *r = fio_malloc(sizeof(*r));
99
97
  HTTP_ASSERT(pr, "Couldn't allocate response object for error report.")
100
- http_s_new(r, (http_protocol_s *)pr, http1_vtable());
98
+ http_s_new(r, (http_fio_protocol_s *)pr, http1_vtable());
101
99
  int ret = http_send_error(r, error);
102
- sock_close(uuid);
100
+ fio_close(uuid);
103
101
  return ret;
104
102
  }
105
103
 
@@ -138,7 +136,8 @@ FIOBJ HTTP_HVALUE_WS_UPGRADE;
138
136
  FIOBJ HTTP_HVALUE_WS_VERSION;
139
137
  FIOBJ HTTP_HVALUE_SSE_MIME;
140
138
 
141
- void http_lib_cleanup(void) {
139
+ static void http_lib_cleanup(void *ignr) {
140
+ (void)ignr;
142
141
  http_mimetype_clear();
143
142
  #define HTTPLIB_RESET(x) \
144
143
  fiobj_free(x); \
@@ -180,6 +179,7 @@ void http_lib_cleanup(void) {
180
179
  void http_lib_init(void) {
181
180
  if (HTTP_HEADER_ACCEPT_RANGES)
182
181
  return;
182
+ fio_state_callback_add(FIO_CALL_AT_EXIT, http_lib_cleanup, NULL);
183
183
  HTTP_HEADER_ACCEPT = fiobj_str_new("accept", 6);
184
184
  HTTP_HEADER_ACCEPT_RANGES = fiobj_str_new("accept-ranges", 13);
185
185
  HTTP_HEADER_CACHE_CONTROL = fiobj_str_new("cache-control", 13);
@@ -244,7 +244,7 @@ void http_lib_init(void) {
244
244
 
245
245
  #define REGISTER_MIME(ext, type) \
246
246
  http_mimetype_register(ext, sizeof(ext) - 1, \
247
- fiobj_str_static(type, sizeof(type) - 1))
247
+ fiobj_str_new(type, sizeof(type) - 1))
248
248
 
249
249
  REGISTER_MIME("123", "application/vnd.lotus-1-2-3");
250
250
  REGISTER_MIME("3dml", "text/vnd.in3d.3dml");
@@ -671,6 +671,7 @@ void http_lib_init(void) {
671
671
  REGISTER_MIME("maker", "application/vnd.framemaker");
672
672
  REGISTER_MIME("man", "text/troff");
673
673
  REGISTER_MIME("mar", "application/octet-stream");
674
+ REGISTER_MIME("markdown", "text/markdown");
674
675
  REGISTER_MIME("mathml", "application/mathml+xml");
675
676
  REGISTER_MIME("mb", "application/mathematica");
676
677
  REGISTER_MIME("mbk", "application/vnd.mobius.mbk");
@@ -678,6 +679,7 @@ void http_lib_init(void) {
678
679
  REGISTER_MIME("mc1", "application/vnd.medcalcdata");
679
680
  REGISTER_MIME("mcd", "application/vnd.mcd");
680
681
  REGISTER_MIME("mcurl", "text/vnd.curl.mcurl");
682
+ REGISTER_MIME("md", "text/markdown");
681
683
  REGISTER_MIME("mdb", "application/x-msaccess");
682
684
  REGISTER_MIME("mdi", "image/vnd.ms-modi");
683
685
  REGISTER_MIME("me", "text/troff");
@@ -7,22 +7,25 @@ Feel free to copy, use and enjoy according to the license provided.
7
7
  #ifndef H_HTTP_INTERNAL_H
8
8
  #define H_HTTP_INTERNAL_H
9
9
 
10
- #include "spnlock.inc"
10
+ #define FIO_INCLUDE_LINKED_LIST
11
+ #include <fio.h>
11
12
 
12
- #include "fio_llist.h"
13
- #include "http.h"
14
- #include "pubsub.h"
13
+ #include <http.h>
15
14
 
16
- #include "fiobj4sock.h"
15
+ #include <fiobj4sock.h>
17
16
 
18
17
  #include <arpa/inet.h>
19
18
  #include <errno.h>
20
19
 
20
+ /* *****************************************************************************
21
+ Library initialization
22
+ ***************************************************************************** */
23
+ void http_lib_init(void);
21
24
  /* *****************************************************************************
22
25
  Types
23
26
  ***************************************************************************** */
24
27
 
25
- typedef struct http_protocol_s http_protocol_s;
28
+ typedef struct http_fio_protocol_s http_fio_protocol_s;
26
29
  typedef struct http_vtable_s http_vtable_s;
27
30
 
28
31
  struct http_vtable_s {
@@ -39,16 +42,16 @@ struct http_vtable_s {
39
42
  int (*const http_push_data)(http_s *h, void *data, uintptr_t length,
40
43
  FIOBJ mime_type);
41
44
  /** Upgrades a connection to Websockets. */
42
- int (*const http2websocket)(websocket_settings_s *arg);
45
+ int (*const http2websocket)(http_s *h, websocket_settings_s *arg);
43
46
  /** Push for files. */
44
47
  int (*const http_push_file)(http_s *h, FIOBJ filename, FIOBJ mime_type);
45
48
  /** Pauses the request / response handling. */
46
- void (*http_on_pause)(http_s *, http_protocol_s *);
49
+ void (*http_on_pause)(http_s *, http_fio_protocol_s *);
47
50
 
48
51
  /** Resumes a request / response handling. */
49
- void (*http_on_resume)(http_s *, http_protocol_s *);
52
+ void (*http_on_resume)(http_s *, http_fio_protocol_s *);
50
53
  /** hijacks the socket aaway from the protocol. */
51
- intptr_t (*http_hijack)(http_s *h, fio_cstr_s *leftover);
54
+ intptr_t (*http_hijack)(http_s *h, fio_str_info_s *leftover);
52
55
 
53
56
  /** Upgrades an HTTP connection to an EventSource (SSE) connection. */
54
57
  int (*http_upgrade2sse)(http_s *h, http_sse_s *sse);
@@ -58,13 +61,13 @@ struct http_vtable_s {
58
61
  int (*http_sse_close)(http_sse_s *sse);
59
62
  };
60
63
 
61
- struct http_protocol_s {
62
- protocol_s protocol; /* facil.io protocol */
64
+ struct http_fio_protocol_s {
65
+ fio_protocol_s protocol; /* facil.io protocol */
63
66
  intptr_t uuid; /* socket uuid */
64
67
  http_settings_s *settings; /* pointer to HTTP settings */
65
68
  };
66
69
 
67
- #define http2protocol(h) ((http_protocol_s *)h->private_data.flag)
70
+ #define http2protocol(h) ((http_fio_protocol_s *)h->private_data.flag)
68
71
 
69
72
  /* *****************************************************************************
70
73
  Constants that shouldn't be accessed by the users (`fiobj_dup` required).
@@ -90,7 +93,7 @@ extern FIOBJ HTTP_HVALUE_WS_VERSION;
90
93
  HTTP request/response object management
91
94
  ***************************************************************************** */
92
95
 
93
- static inline void http_s_new(http_s *h, http_protocol_s *owner,
96
+ static inline void http_s_new(http_s *h, http_fio_protocol_s *owner,
94
97
  http_vtable_s *vtbl) {
95
98
  *h = (http_s){
96
99
  .private_data =
@@ -100,7 +103,7 @@ static inline void http_s_new(http_s *h, http_protocol_s *owner,
100
103
  .out_headers = fiobj_hash_new(),
101
104
  },
102
105
  .headers = fiobj_hash_new(),
103
- .received_at = facil_last_tick(),
106
+ .received_at = fio_last_tick(),
104
107
  .status = 200,
105
108
  };
106
109
  }
@@ -128,7 +131,8 @@ static inline void http_s_destroy(http_s *h, uint8_t log) {
128
131
 
129
132
  static inline void http_s_clear(http_s *h, uint8_t log) {
130
133
  http_s_destroy(h, log);
131
- http_s_new(h, (http_protocol_s *)h->private_data.flag, h->private_data.vtbl);
134
+ http_s_new(h, (http_fio_protocol_s *)h->private_data.flag,
135
+ h->private_data.vtbl);
132
136
  }
133
137
 
134
138
  /** tests handle validity */
@@ -157,7 +161,7 @@ typedef struct http_sse_internal_s {
157
161
  http_vtable_s *vtable; /* the protocol's vtable */
158
162
  uintptr_t id; /* the SSE identifier */
159
163
  fio_ls_s subscriptions; /* Subscription List */
160
- spn_lock_i lock; /* Subscription List lock */
164
+ fio_lock_i lock; /* Subscription List lock */
161
165
  size_t ref; /* reference count */
162
166
  } http_sse_internal_s;
163
167
 
@@ -173,7 +177,7 @@ static inline void http_sse_init(http_sse_internal_s *sse, intptr_t uuid,
173
177
  }
174
178
 
175
179
  static inline void http_sse_try_free(http_sse_internal_s *sse) {
176
- if (spn_sub(&sse->ref, 1))
180
+ if (fio_atomic_sub(&sse->ref, 1))
177
181
  return;
178
182
  free(sse);
179
183
  }
@@ -181,8 +185,10 @@ static inline void http_sse_try_free(http_sse_internal_s *sse) {
181
185
  static inline void http_sse_destroy(http_sse_internal_s *sse) {
182
186
  while (fio_ls_any(&sse->subscriptions)) {
183
187
  void *sub = fio_ls_pop(&sse->subscriptions);
184
- pubsub_unsubscribe(sub);
188
+ fio_unsubscribe(sub);
185
189
  }
190
+ if (sse->sse.on_close)
191
+ sse->sse.on_close(&sse->sse);
186
192
  sse->uuid = -1;
187
193
  http_sse_try_free(sse);
188
194
  }
@@ -2,7 +2,8 @@
2
2
 
3
3
  #include <ruby/version.h>
4
4
 
5
- #include "facil.h"
5
+ #define FIO_INCLUDE_LINKED_LIST
6
+ #include "fio.h"
6
7
  /* *****************************************************************************
7
8
  OS specific patches
8
9
  ***************************************************************************** */
@@ -31,10 +32,8 @@ static ID call_id;
31
32
  /* *****************************************************************************
32
33
  Idling
33
34
  ***************************************************************************** */
34
- #include "fio_llist.h"
35
- #include "spnlock.inc"
36
35
 
37
- static spn_lock_i iodine_on_idle_lock = SPN_LOCK_INIT;
36
+ static fio_lock_i iodine_on_idle_lock = FIO_LOCK_INIT;
38
37
  static fio_ls_s iodine_on_idle_list = FIO_LS_INIT(iodine_on_idle_list);
39
38
 
40
39
  static void iodine_perform_deferred(void *block, void *ignr) {
@@ -57,21 +56,22 @@ VALUE iodine_sched_on_idle(VALUE self) {
57
56
  rb_need_block();
58
57
  VALUE block = rb_block_proc();
59
58
  IodineStore.add(block);
60
- spn_lock(&iodine_on_idle_lock);
59
+ fio_lock(&iodine_on_idle_lock);
61
60
  fio_ls_push(&iodine_on_idle_list, (void *)block);
62
- spn_unlock(&iodine_on_idle_lock);
61
+ fio_unlock(&iodine_on_idle_lock);
63
62
  return block;
64
63
  (void)self;
65
64
  }
66
65
 
67
- static void iodine_on_idle(void) {
68
- spn_lock(&iodine_on_idle_lock);
66
+ static void iodine_on_idle(void *arg) {
67
+ (void)arg;
68
+ fio_lock(&iodine_on_idle_lock);
69
69
  while (fio_ls_any(&iodine_on_idle_list)) {
70
70
  VALUE block = (VALUE)fio_ls_shift(&iodine_on_idle_list);
71
- defer(iodine_perform_deferred, (void *)block, NULL);
71
+ fio_defer(iodine_perform_deferred, (void *)block, NULL);
72
72
  IodineStore.remove(block);
73
73
  }
74
- spn_unlock(&iodine_on_idle_lock);
74
+ fio_unlock(&iodine_on_idle_lock);
75
75
  }
76
76
 
77
77
  /* *****************************************************************************
@@ -85,8 +85,7 @@ typedef struct {
85
85
 
86
86
  static void *iodine_run_outside_GVL(void *params_) {
87
87
  iodine_start_params_s *params = params_;
88
- facil_run(.threads = params->threads, .processes = params->workers,
89
- .on_idle = iodine_on_idle, .on_finish = iodine_defer_on_finish);
88
+ fio_start(.threads = params->threads, .workers = params->workers);
90
89
  return NULL;
91
90
  }
92
91
 
@@ -166,14 +165,14 @@ static VALUE iodine_workers_set(VALUE self, VALUE val) {
166
165
  static void iodine_print_startup_message(iodine_start_params_s params) {
167
166
  VALUE iodine_version = rb_const_get(IodineModule, rb_intern("VERSION"));
168
167
  VALUE ruby_version = rb_const_get(IodineModule, rb_intern("RUBY_VERSION"));
169
- facil_expected_concurrency(&params.threads, &params.workers);
168
+ fio_expected_concurrency(&params.threads, &params.workers);
170
169
  fprintf(stderr,
171
170
  "\nStarting up Iodine:\n"
172
- " * Ruby v.%s\n * Iodine v.%s\n"
171
+ " * Iodine %s\n * Ruby %s\n * facil.io " FIO_VERSION_STRING " (%s)\n"
173
172
  " * %d Workers X %d Threads per worker.\n"
174
173
  "\n",
175
- StringValueCStr(ruby_version), StringValueCStr(iodine_version),
176
- params.workers, params.threads);
174
+ StringValueCStr(iodine_version), StringValueCStr(ruby_version),
175
+ fio_engine(), params.workers, params.threads);
177
176
  (void)params;
178
177
  }
179
178
 
@@ -193,19 +192,32 @@ static void iodine_print_startup_message(iodine_start_params_s params) {
193
192
  *
194
193
  */
195
194
  static VALUE iodine_start(VALUE self) {
196
- if (facil_is_running()) {
195
+ if (fio_is_running()) {
197
196
  rb_raise(rb_eRuntimeError, "Iodine already running!");
198
197
  }
198
+ IodineCaller.set_GVL(1);
199
199
  VALUE threads_rb = iodine_threads_get(self);
200
200
  VALUE workers_rb = iodine_workers_get(self);
201
201
  iodine_start_params_s params = {
202
- .threads = NUM2SHORT(threads_rb), .workers = NUM2SHORT(workers_rb),
202
+ .threads = NUM2SHORT(threads_rb),
203
+ .workers = NUM2SHORT(workers_rb),
203
204
  };
204
205
  iodine_print_startup_message(params);
205
206
  IodineCaller.leaveGVL(iodine_run_outside_GVL, &params);
206
207
  return self;
207
208
  }
208
209
 
210
+ /**
211
+ * This will stop the iodine server, shutting it down.
212
+ *
213
+ * If called within a worker process (rather than the root/master process), this
214
+ * will cause a hot-restart for the worker.
215
+ */
216
+ static VALUE iodine_stop(VALUE self) {
217
+ fio_stop();
218
+ return self;
219
+ }
220
+
209
221
  /* *****************************************************************************
210
222
  Ruby loads the library and invokes the Init_<lib_name> function...
211
223
 
@@ -230,6 +242,7 @@ void Init_iodine(void) {
230
242
  rb_define_module_function(IodineModule, "workers", iodine_workers_get, 0);
231
243
  rb_define_module_function(IodineModule, "workers=", iodine_workers_set, 1);
232
244
  rb_define_module_function(IodineModule, "start", iodine_start, 0);
245
+ rb_define_module_function(IodineModule, "stop", iodine_stop, 0);
233
246
  rb_define_module_function(IodineModule, "on_idle", iodine_sched_on_idle, 0);
234
247
 
235
248
  // initialize Object storage for GC protection
@@ -250,10 +263,16 @@ void Init_iodine(void) {
250
263
  // initialize JSON helpers
251
264
  iodine_init_json();
252
265
 
266
+ // initialize Mustache engine
267
+ iodine_init_mustache();
268
+
253
269
  // initialize Rack helpers and IO
254
270
  iodine_init_helpers();
255
271
  IodineRackIO.init();
256
272
 
257
273
  // initialize Pub/Sub extension (for Engines)
258
274
  iodine_pubsub_init();
275
+
276
+ // register idle and finish callbacks
277
+ fio_state_callback_add(FIO_CALL_ON_IDLE, iodine_on_idle, NULL);
259
278
  }
@@ -9,6 +9,7 @@
9
9
  #include "iodine_helpers.h"
10
10
  #include "iodine_http.h"
11
11
  #include "iodine_json.h"
12
+ #include "iodine_mustache.h"
12
13
  #include "iodine_pubsub.h"
13
14
  #include "iodine_rack_io.h"
14
15
  #include "iodine_store.h"
@@ -20,4 +21,7 @@ Constants
20
21
  extern VALUE IodineModule;
21
22
  extern VALUE IodineBaseModule;
22
23
 
24
+ #define IODINE_RSTRINFO(rstr) \
25
+ ((fio_str_info_s){.len = RSTRING_LEN(rstr), .data = RSTRING_PTR(rstr)})
26
+
23
27
  #endif
@@ -1,6 +1,7 @@
1
1
  #include "iodine_caller.h"
2
2
 
3
3
  #include <ruby/thread.h>
4
+ #include <string.h>
4
5
 
5
6
  static __thread volatile uint8_t iodine_GVL_state;
6
7
 
@@ -91,7 +92,10 @@ static void *iodine_leaveGVL(void *(*func)(void *), void *arg) {
91
92
  /** Calls a Ruby method on a given object, protecting against exceptions. */
92
93
  static VALUE iodine_call(VALUE obj, ID method) {
93
94
  iodine_rb_task_s task = {
94
- .obj = obj, .argc = 0, .argv = NULL, .method = method,
95
+ .obj = obj,
96
+ .argc = 0,
97
+ .argv = NULL,
98
+ .method = method,
95
99
  };
96
100
  void *rv = iodine_enterGVL(iodine_protect_ruby_call, &task);
97
101
  return (VALUE)rv;
@@ -100,7 +104,10 @@ static VALUE iodine_call(VALUE obj, ID method) {
100
104
  /** Calls a Ruby method on a given object, protecting against exceptions. */
101
105
  static VALUE iodine_call2(VALUE obj, ID method, int argc, VALUE *argv) {
102
106
  iodine_rb_task_s task = {
103
- .obj = obj, .argc = argc, .argv = argv, .method = method,
107
+ .obj = obj,
108
+ .argc = argc,
109
+ .argv = argv,
110
+ .method = method,
104
111
  };
105
112
  void *rv = iodine_enterGVL(iodine_protect_ruby_call, &task);
106
113
  return (VALUE)rv;