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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +4 -4
- data/SPEC-Websocket-Draft.md +3 -6
- data/bin/mustache.rb +128 -0
- data/examples/test_template.mustache +16 -0
- data/ext/iodine/fio.c +9397 -0
- data/ext/iodine/fio.h +4723 -0
- data/ext/iodine/fio_ary.h +353 -54
- data/ext/iodine/fio_cli.c +351 -361
- data/ext/iodine/fio_cli.h +84 -105
- data/ext/iodine/fio_hashmap.h +70 -16
- data/ext/iodine/fio_json_parser.h +35 -24
- data/ext/iodine/fio_siphash.c +104 -4
- data/ext/iodine/fio_siphash.h +18 -2
- data/ext/iodine/fio_str.h +1218 -0
- data/ext/iodine/fio_tmpfile.h +1 -1
- data/ext/iodine/fiobj.h +13 -8
- data/ext/iodine/fiobj4sock.h +6 -8
- data/ext/iodine/fiobj_ary.c +107 -17
- data/ext/iodine/fiobj_ary.h +36 -4
- data/ext/iodine/fiobj_data.c +146 -127
- data/ext/iodine/fiobj_data.h +25 -23
- data/ext/iodine/fiobj_hash.c +7 -7
- data/ext/iodine/fiobj_hash.h +6 -5
- data/ext/iodine/fiobj_json.c +20 -17
- data/ext/iodine/fiobj_json.h +5 -5
- data/ext/iodine/fiobj_mem.h +71 -0
- data/ext/iodine/fiobj_mustache.c +310 -0
- data/ext/iodine/fiobj_mustache.h +40 -0
- data/ext/iodine/fiobj_numbers.c +199 -94
- data/ext/iodine/fiobj_numbers.h +7 -7
- data/ext/iodine/fiobj_str.c +142 -333
- data/ext/iodine/fiobj_str.h +65 -55
- data/ext/iodine/fiobject.c +49 -11
- data/ext/iodine/fiobject.h +40 -39
- data/ext/iodine/http.c +382 -190
- data/ext/iodine/http.h +124 -80
- data/ext/iodine/http1.c +99 -127
- data/ext/iodine/http1.h +5 -5
- data/ext/iodine/http1_parser.c +3 -2
- data/ext/iodine/http1_parser.h +2 -2
- data/ext/iodine/http_internal.c +14 -12
- data/ext/iodine/http_internal.h +25 -19
- data/ext/iodine/iodine.c +37 -18
- data/ext/iodine/iodine.h +4 -0
- data/ext/iodine/iodine_caller.c +9 -2
- data/ext/iodine/iodine_caller.h +2 -0
- data/ext/iodine/iodine_connection.c +82 -117
- data/ext/iodine/iodine_defer.c +57 -50
- data/ext/iodine/iodine_defer.h +0 -1
- data/ext/iodine/iodine_fiobj2rb.h +4 -2
- data/ext/iodine/iodine_helpers.c +4 -4
- data/ext/iodine/iodine_http.c +25 -32
- data/ext/iodine/iodine_json.c +2 -1
- data/ext/iodine/iodine_mustache.c +423 -0
- data/ext/iodine/iodine_mustache.h +6 -0
- data/ext/iodine/iodine_pubsub.c +48 -153
- data/ext/iodine/iodine_pubsub.h +5 -4
- data/ext/iodine/iodine_rack_io.c +7 -5
- data/ext/iodine/iodine_store.c +16 -13
- data/ext/iodine/iodine_tcp.c +26 -34
- data/ext/iodine/mustache_parser.h +1085 -0
- data/ext/iodine/redis_engine.c +740 -646
- data/ext/iodine/redis_engine.h +13 -15
- data/ext/iodine/resp_parser.h +11 -5
- data/ext/iodine/websocket_parser.h +13 -13
- data/ext/iodine/websockets.c +240 -393
- data/ext/iodine/websockets.h +52 -113
- data/lib/iodine.rb +1 -1
- data/lib/iodine/mustache.rb +140 -0
- data/lib/iodine/version.rb +1 -1
- metadata +15 -28
- data/ext/iodine/defer.c +0 -566
- data/ext/iodine/defer.h +0 -148
- data/ext/iodine/evio.c +0 -26
- data/ext/iodine/evio.h +0 -161
- data/ext/iodine/evio_callbacks.c +0 -26
- data/ext/iodine/evio_epoll.c +0 -251
- data/ext/iodine/evio_kqueue.c +0 -194
- data/ext/iodine/facil.c +0 -2325
- data/ext/iodine/facil.h +0 -616
- data/ext/iodine/fio_base64.c +0 -277
- data/ext/iodine/fio_base64.h +0 -71
- data/ext/iodine/fio_llist.h +0 -257
- data/ext/iodine/fio_mem.c +0 -675
- data/ext/iodine/fio_mem.h +0 -143
- data/ext/iodine/fio_random.c +0 -248
- data/ext/iodine/fio_random.h +0 -45
- data/ext/iodine/fio_sha1.c +0 -362
- data/ext/iodine/fio_sha1.h +0 -107
- data/ext/iodine/fio_sha2.c +0 -842
- data/ext/iodine/fio_sha2.h +0 -169
- data/ext/iodine/pubsub.c +0 -867
- data/ext/iodine/pubsub.h +0 -221
- data/ext/iodine/sock.c +0 -1366
- data/ext/iodine/sock.h +0 -566
- data/ext/iodine/spnlock.inc +0 -111
data/ext/iodine/facil.h
DELETED
@@ -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 */
|