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
@@ -1,616 +0,0 @@
1
- /*
2
- Copyright: Boaz Segev, 2016-2017
3
- License: MIT
4
-
5
- Feel free to copy, use and enjoy according to the license provided.
6
- */
7
- #ifndef H_FACIL_H
8
- /**
9
- "facil.h" is the main header for the facil.io server platform.
10
- */
11
- #define H_FACIL_H
12
- #define FACIL_VERSION_MAJOR 0
13
- #define FACIL_VERSION_MINOR 6
14
- #define FACIL_VERSION_PATCH 4
15
-
16
- #ifndef FACIL_PRINT_STATE
17
- /**
18
- * When FACIL_PRINT_STATE is set to 1, facil.io will print out common messages
19
- * regarding the server state (start / finish / listen messages).
20
- */
21
- #define FACIL_PRINT_STATE 1
22
- #endif
23
-
24
- #ifndef FACIL_CPU_CORES_LIMIT
25
- /**
26
- * If facil.io detects more CPU cores than the number of cores stated in the
27
- * FACIL_CPU_CORES_LIMIT, it will assume an error and cap the number of cores
28
- * detected to the assigned limit.
29
- *
30
- * This is only relevant to automated values, when running facil.io with zero
31
- * threads and processes, which invokes a large matrix of workers and threads
32
- * (see {facil_run})
33
- *
34
- * The default auto-detection cap is set at 8 cores. The number is arbitrary
35
- * (historically the number 7 was used after testing `malloc` race conditions on
36
- * a MacBook Pro).
37
- *
38
- * The does NOT effect manually set (non-zero) worker/thread values.
39
- */
40
- #define FACIL_CPU_CORES_LIMIT 8
41
- #endif
42
-
43
- #ifndef FIO_DEDICATED_SYSTEM
44
- /**
45
- * If FIO_DEDICATED_SYSTEM is false, threads will be used (mostly) for
46
- * non-prallel concurrency (protection against slow user code / high load) and
47
- * processes will be used for parallelism. Otherwise, both threads and processes
48
- * will be used for prallel concurrency (at the expense of increased polling).
49
- *
50
- * If FIO_DEDICATED_SYSTEM is true, facil.io assumes that the whole system is at
51
- * it's service and that no other process is using the CPU cores.
52
- *
53
- * Accordingly, facil.io will poll the IO more often in an attempt to activate
54
- * the threads and utilize all the cores whenever events occur.
55
- *
56
- * My tests show that the non-polling approach is faster, but it may be system
57
- * specific.
58
- */
59
- #define FIO_DEDICATED_SYSTEM 0
60
- #endif
61
-
62
- #ifndef FACIL_DISABLE_HOT_RESTART
63
- /**
64
- * Disables the hot restart reaction to the SIGUSR1 signal
65
- *
66
- * The hot restart will attempt to shut down all workers, and spawn new workers,
67
- * cleaning up any data cached by any of the workers.
68
- *
69
- * It's quite useless unless the workers are running their own VMs which are
70
- * initialized in the listening socket's `on_start` callback.
71
- */
72
- #define FACIL_DISABLE_HOT_RESTART 0
73
- #endif
74
-
75
- /* *****************************************************************************
76
- Required facil libraries
77
- ***************************************************************************** */
78
- #include "defer.h"
79
- #include "fiobj.h"
80
- #include "sock.h"
81
-
82
- /* support C++ */
83
- #ifdef __cplusplus
84
- extern "C" {
85
- #endif
86
-
87
- /* *****************************************************************************
88
- Core object types
89
- ***************************************************************************** */
90
-
91
- typedef struct FacilIOProtocol protocol_s;
92
- /**************************************************************************/ /**
93
- * The Protocol
94
-
95
- The Protocol struct defines the callbacks used for the connection and sets it's
96
- behaviour. The Protocol struct is part of facil.io's core design.
97
-
98
- For concurrency reasons, a protocol instance SHOULD be unique to each
99
- connections. Different connections shouldn't share a single protocol object
100
- (callbacks and data can obviously be shared).
101
-
102
- All the callbacks recieve a unique connection ID (a localized UUID) that can be
103
- converted to the original file descriptor when in need.
104
-
105
- This allows facil.io to prevent old connection handles from sending data
106
- to new connections after a file descriptor is "recycled" by the OS.
107
- */
108
- struct FacilIOProtocol {
109
- /**
110
- * A string to identify the protocol's service (i.e. "http").
111
- *
112
- * The string should be a global constant, only a pointer comparison will be
113
- * used (not `strcmp`).
114
- */
115
- const char *service;
116
- /** Called when a data is available, but will not run concurrently */
117
- void (*on_data)(intptr_t uuid, protocol_s *protocol);
118
- /** called when the socket is ready to be written to. */
119
- void (*on_ready)(intptr_t uuid, protocol_s *protocol);
120
- /**
121
- * Called when the server is shutting down, immediately before closing the
122
- * connection.
123
- *
124
- * The callback runs within a {FIO_PR_LOCK_TASK} lock, so it will never run
125
- * concurrently wil {on_data} or other connection specific tasks.
126
- */
127
- void (*on_shutdown)(intptr_t uuid, protocol_s *protocol);
128
- /** Called when the connection was closed, but will not run concurrently */
129
- void (*on_close)(intptr_t uuid, protocol_s *protocol);
130
- /** called when a connection's timeout was reached */
131
- void (*ping)(intptr_t uuid, protocol_s *protocol);
132
- /** private metadata used by facil. */
133
- size_t rsv;
134
- };
135
-
136
- /**************************************************************************/ /**
137
- * Listening to Incoming Connections
138
-
139
- Listenning to incoming connections is pretty straight forward.
140
-
141
- After a new connection is accepted, the `on_open` callback is called. `on_open`
142
- should allocate the new connection's protocol and retuen it's address.
143
-
144
- The protocol's `on_close` callback is expected to handle the cleanup.
145
-
146
- These settings will be used to setup listening sockets.
147
-
148
- i.e.
149
-
150
- ```c
151
- // A callback to be called whenever data is available on the socket
152
- static void echo_on_data(intptr_t uuid,
153
- protocol_s *prt
154
- ) {
155
- (void)prt; // we can ignore the unused argument
156
- // echo buffer
157
- char buffer[1024] = {'E', 'c', 'h', 'o', ':', ' '};
158
- ssize_t len;
159
- // Read to the buffer, starting after the "Echo: "
160
- while ((len = sock_read(uuid, buffer + 6, 1018)) > 0) {
161
- // Write back the message
162
- sock_write(uuid, buffer, len + 6);
163
- // Handle goodbye
164
- if ((buffer[6] | 32) == 'b' && (buffer[7] | 32) == 'y' &&
165
- (buffer[8] | 32) == 'e') {
166
- sock_write(uuid, "Goodbye.\n", 9);
167
- sock_close(uuid);
168
- return;
169
- }
170
- }
171
- }
172
-
173
- // A callback called whenever a timeout is reach
174
- static void echo_ping(intptr_t uuid, protocol_s *prt) {
175
- (void)prt; // we can ignore the unused argument
176
- sock_write(uuid, "Server: Are you there?\n", 23);
177
- }
178
-
179
- // A callback called if the server is shutting down...
180
- // ... while the connection is still open
181
- static void echo_on_shutdown(intptr_t uuid, protocol_s *prt) {
182
- (void)prt; // we can ignore the unused argument
183
- sock_write(uuid, "Echo server shutting down\nGoodbye.\n", 35);
184
- }
185
-
186
- // A callback called for new connections
187
- static protocol_s *echo_on_open(intptr_t uuid, void *udata) {
188
- (void)udata; // ignore this
189
- // Protocol objects MUST always be dynamically allocated.
190
- protocol_s *echo_proto = malloc(sizeof(*echo_proto));
191
- *echo_proto = (protocol_s){
192
- .service = "echo",
193
- .on_data = echo_on_data,
194
- .on_shutdown = echo_on_shutdown,
195
- .on_close = (void (*)(protocol_s *))free, // simply free when done
196
- .ping = echo_ping};
197
-
198
- sock_write(uuid, "Echo Service: Welcome\n", 22);
199
- facil_set_timeout(uuid, 5);
200
- return echo_proto;
201
- }
202
-
203
- int main() {
204
- // Setup a listening socket
205
- if (facil_listen(.port = "8888", .on_open = echo_on_open)) {
206
- perror("No listening socket available on port 8888");
207
- exit(-1);
208
- }
209
- // Run the server and hang until a stop signal is received.
210
- facil_run(.threads = 4, .processes = 1);
211
- }
212
-
213
- ```
214
- */
215
- struct facil_listen_args {
216
- /**
217
- * Called whenever a new connection is accepted.
218
- *
219
- * Should either call `facil_attach` or close the connection.
220
- */
221
- void (*on_open)(intptr_t fduuid, void *udata);
222
- /** The network service / port. Defaults to "3000". */
223
- const char *port;
224
- /** The socket binding address. Defaults to the recommended NULL. */
225
- const char *address;
226
- /** Opaque user data. */
227
- void *udata;
228
- /**
229
- * Called when the server starts (or a worker process is respawned), allowing
230
- * for further initialization, such as timed event scheduling or VM
231
- * initialization.
232
- *
233
- * This will be called seperately for every worker process whenever it is
234
- * spawned.
235
- */
236
- void (*on_start)(intptr_t uuid, void *udata);
237
- /**
238
- * Called when the server is done, usable for cleanup.
239
- *
240
- * This will be called seperately for every process. */
241
- void (*on_finish)(intptr_t uuid, void *udata);
242
- };
243
-
244
- /** Schedule a network service on a listening socket. */
245
- int facil_listen(struct facil_listen_args args);
246
-
247
- /**
248
- * Schedule a network service on a listening socket.
249
- *
250
- * See the `struct facil_listen_args` details for any possible named arguments.
251
- */
252
- #define facil_listen(...) facil_listen((struct facil_listen_args){__VA_ARGS__})
253
-
254
- /* *****************************************************************************
255
- Connecting to remote servers as a client
256
- ***************************************************************************** */
257
-
258
- /**
259
- Named arguments for the `server_connect` function, that allows non-blocking
260
- connections to be established.
261
- */
262
- struct facil_connect_args {
263
- /** The address of the server we are connecting to. */
264
- char *address;
265
- /** The port on the server we are connecting to. */
266
- char *port;
267
- /**
268
- * The `on_connect` callback should return a pointer to a protocol object
269
- * that will handle any connection related events.
270
- *
271
- * Should either call `facil_attach` or close the connection.
272
- */
273
- void (*on_connect)(intptr_t uuid, void *udata);
274
- /**
275
- * The `on_fail` is called when a socket fails to connect. The old sock UUID
276
- * is passed along.
277
- */
278
- void (*on_fail)(intptr_t uuid, void *udata);
279
- /** Opaque user data. */
280
- void *udata;
281
- /** A non-system timeout after which connection is assumed to have failed. */
282
- uint8_t timeout;
283
- };
284
-
285
- /**
286
- Creates a client connection (in addition or instead of the server).
287
-
288
- See the `struct facil_listen_args` details for any possible named arguments.
289
-
290
- * `.address` should be the address of the server.
291
-
292
- * `.port` the server's port.
293
-
294
- * `.udata`opaque user data.
295
-
296
- * `.on_connect` called once a connection was established.
297
-
298
- Should return a pointer to a `protocol_s` object, to handle connection
299
- callbacks.
300
-
301
- * `.on_fail` called if a connection failed to establish.
302
-
303
- (experimental: untested)
304
- */
305
- intptr_t facil_connect(struct facil_connect_args);
306
- #define facil_connect(...) \
307
- facil_connect((struct facil_connect_args){__VA_ARGS__})
308
-
309
- /* *****************************************************************************
310
- Core API
311
- ***************************************************************************** */
312
-
313
- struct facil_run_args {
314
- /**
315
- * The number of threads to run in the thread pool. Has "smart" defaults.
316
- *
317
- *
318
- * A positive value will indicate a set number of threads (or processes).
319
- *
320
- * Zeros and negative values are fun and include an interesting shorthand:
321
- *
322
- * * Negative values indicate a fraction of the number of CPU cores. i.e.
323
- * -2 will normally indicate "half" (1/2) the number of cores.
324
- *
325
- * * If the other option (i.e. `.processes` when setting `.threads`) is zero,
326
- * it will be automatically updated to reflect the option's absolute value.
327
- * i.e.:
328
- * if .threads == -2 and .processes == 0,
329
- * than facil.io will run 2 processes with (cores/2) threads per process.
330
- */
331
- int16_t threads;
332
- /** The number of processes to run (including this one). See `threads`. */
333
- int16_t processes;
334
- /** called if the event loop in cycled with no pending events. */
335
- void (*on_idle)(void);
336
- /** called when the server is done, to clean up any leftovers. */
337
- void (*on_finish)(void);
338
- };
339
-
340
- /**
341
- * Starts the facil.io event loop. This function will return after facil.io is
342
- * done (after shutdown).
343
- *
344
- * See the `struct facil_run_args` details for any possible named arguments.
345
- */
346
- void facil_run(struct facil_run_args args);
347
- #define facil_run(...) facil_run((struct facil_run_args){__VA_ARGS__})
348
-
349
- /**
350
- * Returns the number of expected threads / processes to be used by facil.io.
351
- *
352
- * The pointers should start with valid values that match the expected threads /
353
- * processes values passed to `facil_run`.
354
- *
355
- * The data in the pointers will be overwritten with the result.
356
- */
357
- void facil_expected_concurrency(int16_t *threads, int16_t *processes);
358
-
359
- /**
360
- * returns true (1) if the facil.io engine is already running.
361
- */
362
- int facil_is_running(void);
363
-
364
- /**
365
- OVERRIDE THIS to replace the default `fork` implementation or to inject hooks
366
- into the forking function.
367
-
368
- Behaves like the system's `fork`.
369
- */
370
- int facil_fork(void);
371
-
372
- /**
373
- * Attaches (or updates) a protocol object to a socket UUID.
374
- *
375
- * The new protocol object can be NULL, which will detach ("hijack"), the
376
- * socket.
377
- *
378
- * The old protocol's `on_close` (if any) will be scheduled.
379
- *
380
- * Returns -1 on error and 0 on success.
381
- *
382
- * On error, the new protocol's `on_close` callback will be called.
383
- */
384
- int facil_attach(intptr_t uuid, protocol_s *protocol);
385
-
386
- /**
387
- * Attaches (or updates) a LOCKED protocol object to a socket UUID.
388
- *
389
- * The protocol will be attached in the FIO_PR_LOCK_TASK state, requiring a
390
- * furthur call to `facil_protocol_unlock`.
391
- *
392
- * The old protocol's `on_close` (if any) will be scheduled.
393
- *
394
- * Returns -1 on error and 0 on success.
395
- *
396
- * On error, the new protocol's `on_close` callback will be called.
397
- */
398
- int facil_attach_locked(intptr_t uuid, protocol_s *protocol);
399
-
400
- /** Sets a timeout for a specific connection (if active). */
401
- void facil_set_timeout(intptr_t uuid, uint8_t timeout);
402
-
403
- /** Gets a timeout for a specific connection. Returns 0 if none. */
404
- uint8_t facil_get_timeout(intptr_t uuid);
405
-
406
- enum facil_io_event {
407
- FIO_EVENT_ON_DATA,
408
- FIO_EVENT_ON_READY,
409
- FIO_EVENT_ON_TIMEOUT,
410
- };
411
- /** Schedules an IO event, even id it did not occur. */
412
- void facil_force_event(intptr_t uuid, enum facil_io_event);
413
-
414
- /**
415
- * Temporarily prevents `on_data` events from firing.
416
- *
417
- * The `on_data` event will be automatically rescheduled when (if) the socket's
418
- * outgoing buffer fills up or when `facil_force_event` is called with
419
- * `FIO_EVENT_ON_DATA`.
420
- *
421
- * Note: the function will work as expected when called within the protocol's
422
- * `on_data` callback and the `uuid` refers to a valid socket. Otherwise the
423
- * function might quitely fail.
424
- */
425
- void facil_quite(intptr_t uuid);
426
-
427
- /* *****************************************************************************
428
- Helper API
429
- ***************************************************************************** */
430
-
431
- /**
432
- * Initializes zombie reaping for the process. Call before `facil_run` to enable
433
- * global zombie reaping.
434
- */
435
- void facil_reap_children(void);
436
-
437
- /**
438
- * Returns the last time the server reviewed any pending IO events.
439
- */
440
- struct timespec facil_last_tick(void);
441
-
442
- /** Counts all the connections of a specific type `service`. */
443
- size_t facil_count(void *service);
444
-
445
- /**
446
- * Creates a system timer (at the cost of 1 file descriptor).
447
- *
448
- * The task will repeat `repetitions` times. If `repetitions` is set to 0, task
449
- * will repeat forever.
450
- *
451
- * Returns -1 on error or the new file descriptor on succeess.
452
- *
453
- * The `on_finish` handler is always called (even on error).
454
- */
455
- int facil_run_every(size_t milliseconds, size_t repetitions,
456
- void (*task)(void *), void *arg, void (*on_finish)(void *));
457
-
458
- /**
459
- * This is used to lock the protocol againste concurrency collisions and
460
- * concurent memory deallocation.
461
- *
462
- * However, there are three levels of protection that allow non-coliding tasks
463
- * to protect the protocol object from being deallocated while in use:
464
- *
465
- * * `FIO_PR_LOCK_TASK` - a task lock locks might change data owned by the
466
- * protocol object. This task is used for tasks such as `on_data` and
467
- * (usually) `facil_defer`.
468
- *
469
- * * `FIO_PR_LOCK_WRITE` - a lock that promises only to use static data (data
470
- * that tasks never changes) in order to write to the underlying socket.
471
- * This lock is used for tasks such as `on_ready` and `ping`
472
- *
473
- * * `FIO_PR_LOCK_STATE` - a lock that promises only to retrive static data
474
- * (data that tasks never changes), performing no actions. This usually
475
- * isn't used for client side code (used internally by facil) and is only
476
- * meant for very short locks.
477
- */
478
- enum facil_protocol_lock_e {
479
- FIO_PR_LOCK_TASK = 0,
480
- FIO_PR_LOCK_WRITE = 1,
481
- FIO_PR_LOCK_STATE = 2,
482
- };
483
-
484
- /** Named arguments for the `facil_defer` function. */
485
- struct facil_defer_args_s {
486
- /** The socket (UUID) that will perform the task. This is required.*/
487
- intptr_t uuid;
488
- /** The type of task to be performed. Defaults to `FIO_PR_LOCK_TASK` but could
489
- * also be seto to `FIO_PR_LOCK_WRITE`. */
490
- enum facil_protocol_lock_e type;
491
- /** The task (function) to be performed. This is required. */
492
- void (*task)(intptr_t uuid, protocol_s *, void *arg);
493
- /** An opaque user data that will be passed along to the task. */
494
- void *arg;
495
- /** A fallback task, in case the connection was lost. Good for cleanup. */
496
- void (*fallback)(intptr_t uuid, void *arg);
497
- };
498
- /**
499
- * Schedules a protected connection task. The task will run within the
500
- * connection's lock.
501
- *
502
- * If an error ocuurs or the connection is closed before the task can run, the
503
- * `fallback` task wil be called instead, allowing for resource cleanup.
504
- */
505
- void facil_defer(struct facil_defer_args_s args);
506
- #define facil_defer(...) facil_defer((struct facil_defer_args_s){__VA_ARGS__})
507
-
508
- /** Named arguments for the `facil_defer` function. */
509
- struct facil_each_args_s {
510
- /** The socket (UUID) that originates the task or -1 if none (0 is a valid
511
- * UUID). This socket will be EXCLUDED from performing the task.*/
512
- intptr_t origin;
513
- /** The target type of protocol that should perform the task. This is
514
- * required. */
515
- const void *service;
516
- /** The type of task to be performed. Defaults to `FIO_PR_LOCK_TASK` but could
517
- * also be seto to `FIO_PR_LOCK_WRITE`. */
518
- enum facil_protocol_lock_e task_type;
519
- /** The task (function) to be performed. This is required. */
520
- void (*task)(intptr_t uuid, protocol_s *, void *arg);
521
- /** An opaque user data that will be passed along to the task. */
522
- void *arg;
523
- /** An on_complete callback. Good for cleanup. */
524
- void (*on_complete)(intptr_t uuid, void *arg);
525
- };
526
-
527
- /**
528
- * Schedules a protected connection task for each `service` connection.
529
- * The tasks will run within each of the connection's locks.
530
- *
531
- * Once all the tasks were performed, the `on_complete` callback will be called.
532
- *
533
- * Returns -1 on error. `on_complete` is always called (even on error).
534
- */
535
- int facil_each(struct facil_each_args_s args);
536
- #define facil_each(...) facil_each((struct facil_each_args_s){__VA_ARGS__})
537
-
538
- /* *****************************************************************************
539
- * Cluster specific API - local cluster messaging.
540
- *
541
- * Facil supports message process clustering, so that a multi-process
542
- * application can easily send and receive messages across process boundries.
543
- **************************************************************************** */
544
-
545
- /** returns facil.io's parent (root) process pid. */
546
- pid_t facil_parent_pid(void);
547
-
548
- /**
549
- Sets a callback / handler for a message of type `msg_type`.
550
-
551
- Callbacks are invoked using an O(n) matching, where `n` is the number of
552
- registered callbacks.
553
-
554
- The `msg_type` value can be any positive number up to 2^31-1 (2,147,483,647).
555
- All values less than 0 are reserved for internal use.
556
- */
557
- void facil_cluster_set_handler(int32_t filter,
558
- void (*on_message)(int32_t filter, FIOBJ ch,
559
- FIOBJ msg));
560
- /** Sends a message of type `msg_type` to the **other** cluster processes.
561
-
562
- `msg_type` should match a message type used when calling
563
- `facil_cluster_set_handler` to set the appropriate callback.
564
-
565
- Unknown `msg_type` values are silently ignored.
566
-
567
- The `msg_type` value can be any positive number less than 1,073,741,824. All
568
- negative values and values above 1,073,741,824 are reserved for internal use.
569
-
570
- Callbacks are invoked using an O(n) matching, where `n` is the number of
571
- registered callbacks.
572
- */
573
- int facil_cluster_send(int32_t filter, FIOBJ ch, FIOBJ msg);
574
-
575
- /* *****************************************************************************
576
- Lower Level API - for special circumstances, use with care under .
577
- ***************************************************************************** */
578
-
579
- /**
580
- * This function allows out-of-task access to a connection's `protocol_s` object
581
- * by attempting to lock it.
582
- *
583
- * CAREFUL: mostly, the protocol object will be locked and a pointer will be
584
- * sent to the connection event's callback. However, if you need access to the
585
- * protocol object from outside a running connection task, you might need to
586
- * lock the protocol to prevent it from being closed in the background.
587
- *
588
- * facil.io uses three different locks:
589
- *
590
- * * FIO_PR_LOCK_TASK locks the protocol from normal tasks (i.e. `on_data`,
591
- * `facil_defer`, `facil_every`).
592
- *
593
- * * FIO_PR_LOCK_WRITE locks the protocol for high priority `sock_write`
594
- * oriented tasks (i.e. `ping`, `on_ready`).
595
- *
596
- * * FIO_PR_LOCK_STATE locks the protocol for quick operations that need to copy
597
- * data from the protoccol's data stracture.
598
- *
599
- * IMPORTANT: Remember to call `facil_protocol_unlock` using the same lock type.
600
- *
601
- * Returns NULL on error (lock busy == EWOULDBLOCK, connection invalid == EBADF)
602
- * and a pointer to a protocol object on success.
603
- *
604
- * On error, consider calling `facil_defer` or `defer` instead of busy waiting.
605
- * Busy waiting SHOULD be avoided whenever possible.
606
- */
607
- protocol_s *facil_protocol_try_lock(intptr_t uuid, enum facil_protocol_lock_e);
608
- /** Don't unlock what you don't own... see `facil_protocol_try_lock` for
609
- * details. */
610
- void facil_protocol_unlock(protocol_s *pr, enum facil_protocol_lock_e);
611
-
612
- #ifdef __cplusplus
613
- } /* extern "C" */
614
- #endif
615
-
616
- #endif /* H_FACIL_H */