iodine 0.7.23 → 0.7.24
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 +10 -0
- data/README.md +22 -1
- data/ext/iodine/extconf.rb +22 -7
- data/ext/iodine/fio.c +239 -292
- data/ext/iodine/fio.h +9 -0
- data/ext/iodine/hpack.h +1775 -0
- data/lib/iodine/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14bd75ae5e5c3c0c2fa768fa147a4dfdeb27feb66b7db6896478814cd06c8452
|
4
|
+
data.tar.gz: 84b5ee6178d1bc91945a43d79d4180d08a90f4975d74ef62f7ec0c9e7cea9b66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39c5fcb1bd65f16a20854493d900f39bcdd8dcf705828af5dabec5842290ac879c5dd3e2fd8c7eaa491cf90b3ef81a68636f34744a85bd23483c7545c2acf518
|
7
|
+
data.tar.gz: 1743ce505418cc271f1607632dddbadaddf88aa6ba8c22fa1b459df8a8a70b19007bc14dba93860971bebb0e7a84b643812dea4e66af0ea95b48cc2415122161
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,16 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
6
6
|
|
7
7
|
## Changes:
|
8
8
|
|
9
|
+
#### Change log v.0.7.24
|
10
|
+
|
11
|
+
**Fix**: (`fio`) fixed server shutdown on pub/sub stress, where internal pub/sub stress was mistakingly identified as a Slowloris attack. Credit to @moxgeek (Marouane Elmidaoui) for exposing this issue (plezi#32).
|
12
|
+
|
13
|
+
**Fix**: (`fio`): fixed Slowloris detection for buffer attack variation.
|
14
|
+
|
15
|
+
**Fix**: (`fio`): fixed `pending` result, where packet count wouldn't decrement until queue was drained.
|
16
|
+
|
17
|
+
**Updates**: (`fio`) facil.io updates, including pub/sub memory improvements for cluster mode.
|
18
|
+
|
9
19
|
#### Change log v.0.7.23
|
10
20
|
|
11
21
|
**Fix**: (`fio`): fixed logging message for overflowing log messages. Credit to @weskerfoot (Wesley Kerfoot) and @adam12 (Adam Daniels) for exposing the issue (issue #56).
|
data/README.md
CHANGED
@@ -64,7 +64,28 @@ Then start your application from the command-line / terminal using iodine:
|
|
64
64
|
bundler exec iodine
|
65
65
|
```
|
66
66
|
|
67
|
-
|
67
|
+
#### Installing with SSL/TLS
|
68
|
+
|
69
|
+
Make sure to update OpenSSL to the latest version **before installing Ruby** (`rbenv` should do this automatically).
|
70
|
+
|
71
|
+
To avoid name resolution conflicts, iodine will bind to the same OpenSSL version Ruby is bound to. To use SSL/TLS this should be OpenSSL >= 1.1.0 or LibreSSL >= 2.7.4.
|
72
|
+
|
73
|
+
Verbose installation should provide a confirmation message, such as:
|
74
|
+
|
75
|
+
```bash
|
76
|
+
$ gem install iodine -f -V
|
77
|
+
...
|
78
|
+
checking for -lcrypto... yes
|
79
|
+
checking for -lssl... yes
|
80
|
+
Detected OpenSSL library, testing for version.
|
81
|
+
Confirmed OpenSSL to be version 1.1.0 or above (OpenSSL 1.1.0j 20 Nov 2018)...
|
82
|
+
* Compiling with HAVE_OPENSSL.
|
83
|
+
...
|
84
|
+
```
|
85
|
+
|
86
|
+
**KNOWN ISSUE:**
|
87
|
+
|
88
|
+
The installation script tests for OpenSSL 1.1.0 and above. However, this testing approach sometimes provides false positives. If TLS isn't required, install with `NO_SSL=1`. i.e.:
|
68
89
|
|
69
90
|
```bash
|
70
91
|
NO_SSL=1 bundler exec iodine
|
data/ext/iodine/extconf.rb
CHANGED
@@ -29,17 +29,34 @@ else
|
|
29
29
|
puts 'using an unknown (old?) compiler... who knows if this will work out... we hope.'
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
32
|
# Test for OpenSSL version equal to 1.0.0 or greater.
|
34
|
-
unless ENV['NO_SSL']
|
33
|
+
unless ENV['NO_SSL'] || ENV['NO_TLS'] || ENV["DISABLE_SSL"]
|
34
|
+
OPENSSL_TEST_CODE = <<EOS
|
35
|
+
\#include <openssl/bio.h>
|
36
|
+
\#include <openssl/err.h>
|
37
|
+
\#include <openssl/ssl.h>
|
38
|
+
\#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
39
|
+
\#error "OpenSSL version too small"
|
40
|
+
\#endif
|
41
|
+
int main(void) {
|
42
|
+
SSL_library_init();
|
43
|
+
SSL_CTX *ctx = SSL_CTX_new(TLS_method());
|
44
|
+
SSL *ssl = SSL_new(ctx);
|
45
|
+
BIO *bio = BIO_new_socket(3, 0);
|
46
|
+
BIO_up_ref(bio);
|
47
|
+
SSL_set0_rbio(ssl, bio);
|
48
|
+
SSL_set0_wbio(ssl, bio);
|
49
|
+
}
|
50
|
+
EOS
|
51
|
+
|
52
|
+
dir_config("openssl")
|
35
53
|
begin
|
36
54
|
require 'openssl'
|
37
55
|
rescue LoadError
|
38
56
|
else
|
39
57
|
if have_library('crypto') && have_library('ssl')
|
40
|
-
puts "Detected OpenSSL library, testing for version."
|
41
|
-
if try_compile(
|
42
|
-
# if ((OpenSSL::OPENSSL_VERSION_NUMBER >> 24) > 16) || (((OpenSSL::OPENSSL_VERSION_NUMBER >> 24) == 16) && (((OpenSSL::OPENSSL_VERSION_NUMBER >> 16) & 255) >= 16))
|
58
|
+
puts "Detected OpenSSL library, testing for version and required functions."
|
59
|
+
if try_compile(OPENSSL_TEST_CODE)
|
43
60
|
$defs << "-DHAVE_OPENSSL"
|
44
61
|
puts "Confirmed OpenSSL to be version 1.1.0 or above (#{OpenSSL::OPENSSL_LIBRARY_VERSION})...\n* Compiling with HAVE_OPENSSL."
|
45
62
|
else
|
@@ -54,6 +71,4 @@ RbConfig::MAKEFILE_CONFIG['CFLAGS'] = $CFLAGS = "-std=c11 -DFIO_PRINT_STATE=0 #{
|
|
54
71
|
RbConfig::MAKEFILE_CONFIG['CC'] = $CC = ENV['CC'] if ENV['CC']
|
55
72
|
RbConfig::MAKEFILE_CONFIG['CPP'] = $CPP = ENV['CPP'] if ENV['CPP']
|
56
73
|
|
57
|
-
# abort "Missing OpenSSL." unless have_library("ssl")
|
58
|
-
|
59
74
|
create_makefile 'iodine/iodine'
|
data/ext/iodine/fio.c
CHANGED
@@ -2138,15 +2138,18 @@ postpone:
|
|
2138
2138
|
|
2139
2139
|
static void deferred_on_ready(void *arg, void *arg2) {
|
2140
2140
|
errno = 0;
|
2141
|
-
if (fio_flush((intptr_t)arg) > 0 || errno == EWOULDBLOCK) {
|
2142
|
-
|
2141
|
+
if (fio_flush((intptr_t)arg) > 0 || errno == EWOULDBLOCK || errno == EAGAIN) {
|
2142
|
+
if (arg2)
|
2143
|
+
fio_defer_push_urgent(deferred_on_ready, arg, NULL);
|
2144
|
+
else
|
2145
|
+
fio_poll_add_write(fio_uuid2fd(arg));
|
2143
2146
|
return;
|
2144
2147
|
}
|
2145
2148
|
if (!uuid_data(arg).protocol) {
|
2146
2149
|
return;
|
2147
2150
|
}
|
2151
|
+
|
2148
2152
|
fio_defer_push_task(deferred_on_ready_usr, arg, NULL);
|
2149
|
-
(void)arg2;
|
2150
2153
|
}
|
2151
2154
|
|
2152
2155
|
static void deferred_on_data(void *uuid, void *arg2) {
|
@@ -2571,12 +2574,12 @@ static void fio_sock_perform_close_fd(intptr_t fd) { close(fd); }
|
|
2571
2574
|
static inline void fio_sock_packet_rotate_unsafe(uintptr_t fd) {
|
2572
2575
|
fio_packet_s *packet = fd_data(fd).packet;
|
2573
2576
|
fd_data(fd).packet = packet->next;
|
2577
|
+
fio_atomic_sub(&fd_data(fd).packet_count, 1);
|
2574
2578
|
if (!packet->next) {
|
2575
2579
|
fd_data(fd).packet_last = &fd_data(fd).packet;
|
2576
2580
|
fd_data(fd).packet_count = 0;
|
2577
2581
|
} else if (&packet->next == fd_data(fd).packet_last) {
|
2578
2582
|
fd_data(fd).packet_last = &fd_data(fd).packet;
|
2579
|
-
fio_atomic_sub(&fd_data(fd).packet_count, 1);
|
2580
2583
|
}
|
2581
2584
|
fio_packet_free(packet);
|
2582
2585
|
}
|
@@ -2797,7 +2800,7 @@ ssize_t fio_write2_fn(intptr_t uuid, fio_write_args_s options) {
|
|
2797
2800
|
|
2798
2801
|
if (was_empty) {
|
2799
2802
|
touchfd(fio_uuid2fd(uuid));
|
2800
|
-
|
2803
|
+
deferred_on_ready((void *)uuid, (void *)1);
|
2801
2804
|
}
|
2802
2805
|
return 0;
|
2803
2806
|
locked_error:
|
@@ -2860,7 +2863,7 @@ void fio_force_close(intptr_t uuid) {
|
|
2860
2863
|
if (!uuid_data(uuid).close)
|
2861
2864
|
uuid_data(uuid).close = 1;
|
2862
2865
|
/* clear away any packets in case we want to cut the connection short. */
|
2863
|
-
fio_packet_s *packet;
|
2866
|
+
fio_packet_s *packet = NULL;
|
2864
2867
|
fio_lock(&uuid_data(uuid).sock_lock);
|
2865
2868
|
packet = uuid_data(uuid).packet;
|
2866
2869
|
uuid_data(uuid).packet = NULL;
|
@@ -2913,7 +2916,7 @@ ssize_t fio_flush(intptr_t uuid) {
|
|
2913
2916
|
if (!uuid_data(uuid).packet)
|
2914
2917
|
goto flush_rw_hook;
|
2915
2918
|
|
2916
|
-
const
|
2919
|
+
const fio_packet_s *old_packet = uuid_data(uuid).packet;
|
2917
2920
|
const size_t old_sent = uuid_data(uuid).sent;
|
2918
2921
|
|
2919
2922
|
tmp = uuid_data(uuid).packet->write_func(fio_uuid2fd(uuid),
|
@@ -2922,7 +2925,8 @@ ssize_t fio_flush(intptr_t uuid) {
|
|
2922
2925
|
goto test_errno;
|
2923
2926
|
}
|
2924
2927
|
|
2925
|
-
if (
|
2928
|
+
if (uuid_data(uuid).packet_count >= 1024 &&
|
2929
|
+
uuid_data(uuid).packet == old_packet &&
|
2926
2930
|
uuid_data(uuid).sent >= old_sent &&
|
2927
2931
|
(uuid_data(uuid).sent - old_sent) < 32768) {
|
2928
2932
|
/* Slowloris attack assumed */
|
@@ -2965,11 +2969,16 @@ test_errno:
|
|
2965
2969
|
#if EWOULDBLOCK != EAGAIN
|
2966
2970
|
case EAGAIN: /* ovreflow */
|
2967
2971
|
#endif
|
2968
|
-
case ENOTCONN:
|
2969
|
-
case EINPROGRESS:
|
2970
|
-
case ENOSPC:
|
2972
|
+
case ENOTCONN: /* ovreflow */
|
2973
|
+
case EINPROGRESS: /* ovreflow */
|
2974
|
+
case ENOSPC: /* ovreflow */
|
2975
|
+
case EADDRNOTAVAIL: /* ovreflow */
|
2971
2976
|
case EINTR:
|
2972
2977
|
return 1;
|
2978
|
+
case EFAULT:
|
2979
|
+
FIO_LOG_ERROR("fio_flush EFAULT - possible memory address error sent to "
|
2980
|
+
"Unix socket.");
|
2981
|
+
/* ovreflow */
|
2973
2982
|
case EPIPE: /* ovreflow */
|
2974
2983
|
case EIO: /* ovreflow */
|
2975
2984
|
case EINVAL: /* ovreflow */
|
@@ -2978,6 +2987,8 @@ test_errno:
|
|
2978
2987
|
fio_force_close(uuid);
|
2979
2988
|
return -1;
|
2980
2989
|
}
|
2990
|
+
fprintf(stderr, "UUID error: %p (%d)\n", (void *)uuid, errno);
|
2991
|
+
perror("No errno handler");
|
2981
2992
|
return 0;
|
2982
2993
|
|
2983
2994
|
invalid:
|
@@ -3447,14 +3458,13 @@ static void fio_pubsub_on_fork(void);
|
|
3447
3458
|
|
3448
3459
|
/* Called within a child process after it starts. */
|
3449
3460
|
static void fio_on_fork(void) {
|
3461
|
+
fio_timer_lock = FIO_LOCK_INIT;
|
3450
3462
|
fio_data->lock = FIO_LOCK_INIT;
|
3451
3463
|
fio_defer_on_fork();
|
3452
3464
|
fio_malloc_after_fork();
|
3453
3465
|
fio_poll_init();
|
3454
3466
|
fio_state_callback_on_fork();
|
3455
|
-
|
3456
|
-
fio_timer_lock = FIO_LOCK_INIT;
|
3457
|
-
fio_max_fd_shrink();
|
3467
|
+
|
3458
3468
|
const size_t limit = fio_data->capa;
|
3459
3469
|
for (size_t i = 0; i < limit; ++i) {
|
3460
3470
|
fd_data(i).sock_lock = FIO_LOCK_INIT;
|
@@ -3464,6 +3474,9 @@ static void fio_on_fork(void) {
|
|
3464
3474
|
fio_force_close(fd2uuid(i));
|
3465
3475
|
}
|
3466
3476
|
}
|
3477
|
+
|
3478
|
+
fio_pubsub_on_fork();
|
3479
|
+
fio_max_fd_shrink();
|
3467
3480
|
uint16_t old_active = fio_data->active;
|
3468
3481
|
fio_data->active = 0;
|
3469
3482
|
fio_defer_perform();
|
@@ -5180,8 +5193,6 @@ fio_pubsub_engine_s *FIO_PUBSUB_DEFAULT = FIO_PUBSUB_CLUSTER;
|
|
5180
5193
|
Internal message object creation
|
5181
5194
|
***************************************************************************** */
|
5182
5195
|
|
5183
|
-
#if 1 /* Copy Meta-Data Array vs. lock and unlock per callback */
|
5184
|
-
|
5185
5196
|
/** returns a temporary fio_meta_ary_s with a copy of the metadata array */
|
5186
5197
|
static fio_meta_ary_s fio_postoffice_meta_copy_new(void) {
|
5187
5198
|
fio_meta_ary_s t = FIO_ARY_INIT;
|
@@ -5189,56 +5200,17 @@ static fio_meta_ary_s fio_postoffice_meta_copy_new(void) {
|
|
5189
5200
|
return t;
|
5190
5201
|
}
|
5191
5202
|
fio_lock(&fio_postoffice.meta.lock);
|
5192
|
-
|
5193
|
-
if (len) {
|
5194
|
-
t.end = t.capa = len;
|
5195
|
-
t.arry = fio_malloc(sizeof(*t.arry) * len);
|
5196
|
-
FIO_ASSERT_ALLOC(t.arry);
|
5197
|
-
memcpy(t.arry, fio_meta_ary_to_a(&fio_postoffice.meta.ary),
|
5198
|
-
sizeof(*t.arry) * len);
|
5199
|
-
}
|
5203
|
+
fio_meta_ary_concat(&t, &fio_postoffice.meta.ary);
|
5200
5204
|
fio_unlock(&fio_postoffice.meta.lock);
|
5201
5205
|
return t;
|
5202
5206
|
}
|
5203
5207
|
|
5204
5208
|
/** frees a temporary copy created by postoffice_meta_copy_new */
|
5205
|
-
static void fio_postoffice_meta_copy_free(fio_meta_ary_s cpy) {
|
5206
|
-
|
5207
|
-
}
|
5208
|
-
|
5209
|
-
static fio_msg_internal_s *
|
5210
|
-
fio_pubsub_create_message(int32_t filter, fio_str_info_s ch,
|
5211
|
-
fio_str_info_s data, int8_t is_json, int8_t cpy) {
|
5212
|
-
fio_meta_ary_s t = FIO_ARY_INIT;
|
5213
|
-
if (!filter)
|
5214
|
-
t = fio_postoffice_meta_copy_new();
|
5215
|
-
fio_msg_internal_s *m = fio_malloc(sizeof(*m) + (sizeof(*m->meta) * t.end) +
|
5216
|
-
(ch.len + 1) + (data.len + 1));
|
5217
|
-
*m = (fio_msg_internal_s){
|
5218
|
-
.filter = filter,
|
5219
|
-
.channel =
|
5220
|
-
(fio_str_info_s){.data = (char *)(m->meta + t.end), .len = ch.len},
|
5221
|
-
.data = (fio_str_info_s){.data = ((char *)(m->meta + t.end) + ch.len + 1),
|
5222
|
-
.len = data.len},
|
5223
|
-
.is_json = is_json,
|
5224
|
-
.ref = 1,
|
5225
|
-
.meta_len = t.end,
|
5226
|
-
};
|
5227
|
-
// m->channel.data[ch.len] = 0; /* redundant, fio_malloc is all zero */
|
5228
|
-
// m->data.data[data.len] = 0; /* redundant, fio_malloc is all zero */
|
5229
|
-
if (cpy) {
|
5230
|
-
memcpy(m->channel.data, ch.data, ch.len);
|
5231
|
-
memcpy(m->data.data, data.data, data.len);
|
5232
|
-
while (t.end) {
|
5233
|
-
--t.end;
|
5234
|
-
m->meta[t.end] = t.arry[t.end](m->channel, m->data, is_json);
|
5235
|
-
}
|
5236
|
-
}
|
5237
|
-
fio_postoffice_meta_copy_free(t);
|
5238
|
-
return m;
|
5209
|
+
static inline void fio_postoffice_meta_copy_free(fio_meta_ary_s *cpy) {
|
5210
|
+
fio_meta_ary_free(cpy);
|
5239
5211
|
}
|
5240
5212
|
|
5241
|
-
static void
|
5213
|
+
static void fio_postoffice_meta_update(fio_msg_internal_s *m) {
|
5242
5214
|
if (m->filter || !m->meta_len)
|
5243
5215
|
return;
|
5244
5216
|
fio_meta_ary_s t = fio_postoffice_meta_copy_new();
|
@@ -5249,119 +5221,102 @@ static void fio_pubsub_create_message_update_meta(fio_msg_internal_s *m) {
|
|
5249
5221
|
--t.end;
|
5250
5222
|
m->meta[t.end] = t.arry[t.end](m->channel, m->data, m->is_json);
|
5251
5223
|
}
|
5252
|
-
fio_postoffice_meta_copy_free(t);
|
5253
|
-
}
|
5254
|
-
|
5255
|
-
#else
|
5256
|
-
|
5257
|
-
/** returns the pub/sub metadata count safely (locks) */
|
5258
|
-
static size_t fio_postoffice_meta_count(void) {
|
5259
|
-
size_t count;
|
5260
|
-
fio_lock(&fio_postoffice.meta.lock);
|
5261
|
-
count = fio_meta_ary_count(&fio_postoffice.meta.ary);
|
5262
|
-
fio_unlock(&fio_postoffice.meta.lock);
|
5263
|
-
return count;
|
5264
|
-
}
|
5265
|
-
/** collects a callback by index, from within a loop */
|
5266
|
-
static fio_msg_metadata_fn fio_postoffice_meta_index(intptr_t index) {
|
5267
|
-
fio_msg_metadata_fn cb;
|
5268
|
-
fio_lock(&fio_postoffice.meta.lock);
|
5269
|
-
cb = fio_meta_ary_get(&fio_postoffice.meta.ary, index);
|
5270
|
-
fio_unlock(&fio_postoffice.meta.lock);
|
5271
|
-
return cb;
|
5224
|
+
fio_postoffice_meta_copy_free(&t);
|
5272
5225
|
}
|
5273
5226
|
|
5274
5227
|
static fio_msg_internal_s *
|
5275
|
-
|
5276
|
-
|
5277
|
-
|
5228
|
+
fio_msg_internal_create(int32_t filter, uint32_t type, fio_str_info_s ch,
|
5229
|
+
fio_str_info_s data, int8_t is_json, int8_t cpy) {
|
5230
|
+
fio_meta_ary_s t = FIO_ARY_INIT;
|
5278
5231
|
if (!filter)
|
5279
|
-
|
5280
|
-
fio_msg_internal_s *m =
|
5281
|
-
|
5282
|
-
|
5232
|
+
t = fio_postoffice_meta_copy_new();
|
5233
|
+
fio_msg_internal_s *m = fio_malloc(sizeof(*m) + (sizeof(*m->meta) * t.end) +
|
5234
|
+
(ch.len) + (data.len) + 16 + 2);
|
5235
|
+
FIO_ASSERT_ALLOC(m);
|
5283
5236
|
*m = (fio_msg_internal_s){
|
5284
5237
|
.filter = filter,
|
5285
|
-
.channel =
|
5286
|
-
|
5287
|
-
.data =
|
5288
|
-
|
5289
|
-
|
5238
|
+
.channel = (fio_str_info_s){.data = (char *)(m->meta + t.end) + 16,
|
5239
|
+
.len = ch.len},
|
5240
|
+
.data = (fio_str_info_s){.data = ((char *)(m->meta + t.end) + ch.len +
|
5241
|
+
16 + 1),
|
5242
|
+
.len = data.len},
|
5290
5243
|
.is_json = is_json,
|
5291
5244
|
.ref = 1,
|
5292
|
-
.meta_len =
|
5245
|
+
.meta_len = t.end,
|
5293
5246
|
};
|
5247
|
+
fio_u2str32((uint8_t *)(m + 1) + (sizeof(*m->meta) * t.end), ch.len);
|
5248
|
+
fio_u2str32((uint8_t *)(m + 1) + (sizeof(*m->meta) * t.end) + 4, data.len);
|
5249
|
+
fio_u2str32((uint8_t *)(m + 1) + (sizeof(*m->meta) * t.end) + 8, type);
|
5250
|
+
fio_u2str32((uint8_t *)(m + 1) + (sizeof(*m->meta) * t.end) + 12,
|
5251
|
+
(uint32_t)filter);
|
5294
5252
|
// m->channel.data[ch.len] = 0; /* redundant, fio_malloc is all zero */
|
5295
5253
|
// m->data.data[data.len] = 0; /* redundant, fio_malloc is all zero */
|
5296
5254
|
if (cpy) {
|
5297
5255
|
memcpy(m->channel.data, ch.data, ch.len);
|
5298
5256
|
memcpy(m->data.data, data.data, data.len);
|
5299
|
-
while (
|
5300
|
-
--
|
5301
|
-
|
5302
|
-
if (cb)
|
5303
|
-
m->meta[meta_len] = cb(m->channel, m->data, is_json);
|
5257
|
+
while (t.end) {
|
5258
|
+
--t.end;
|
5259
|
+
m->meta[t.end] = t.arry[t.end](m->channel, m->data, is_json);
|
5304
5260
|
}
|
5305
5261
|
}
|
5262
|
+
fio_postoffice_meta_copy_free(&t);
|
5306
5263
|
return m;
|
5307
5264
|
}
|
5308
5265
|
|
5309
|
-
|
5310
|
-
|
5266
|
+
/** frees the internal message data */
|
5267
|
+
static inline void fio_msg_internal_finalize(fio_msg_internal_s *m) {
|
5268
|
+
if (!m->channel.len)
|
5269
|
+
m->channel.data = NULL;
|
5270
|
+
if (!m->data.len)
|
5271
|
+
m->data.data = NULL;
|
5272
|
+
}
|
5273
|
+
|
5274
|
+
/** frees the internal message data */
|
5275
|
+
static inline void fio_msg_internal_free(fio_msg_internal_s *m) {
|
5276
|
+
if (fio_atomic_sub(&m->ref, 1))
|
5311
5277
|
return;
|
5312
|
-
|
5313
|
-
|
5314
|
-
|
5315
|
-
|
5316
|
-
|
5317
|
-
|
5278
|
+
while (m->meta_len) {
|
5279
|
+
--m->meta_len;
|
5280
|
+
if (m->meta[m->meta_len].on_finish) {
|
5281
|
+
fio_msg_s tmp_msg = {
|
5282
|
+
.channel = m->channel,
|
5283
|
+
.msg = m->data,
|
5284
|
+
};
|
5285
|
+
m->meta[m->meta_len].on_finish(&tmp_msg, m->meta[m->meta_len].metadata);
|
5286
|
+
}
|
5318
5287
|
}
|
5288
|
+
fio_free(m);
|
5319
5289
|
}
|
5320
5290
|
|
5321
|
-
|
5291
|
+
static void fio_msg_internal_free2(void *m) { fio_msg_internal_free(m); }
|
5322
5292
|
|
5323
|
-
/*
|
5324
|
-
|
5325
|
-
|
5293
|
+
/* add reference count to fio_msg_internal_s */
|
5294
|
+
static inline fio_msg_internal_s *fio_msg_internal_dup(fio_msg_internal_s *m) {
|
5295
|
+
fio_atomic_add(&m->ref, 1);
|
5296
|
+
return m;
|
5297
|
+
}
|
5326
5298
|
|
5327
|
-
|
5328
|
-
|
5329
|
-
|
5330
|
-
|
5331
|
-
|
5332
|
-
|
5333
|
-
|
5334
|
-
|
5335
|
-
continue;
|
5336
|
-
pos->obj->lock = FIO_LOCK_INIT;
|
5337
|
-
FIO_LS_EMBD_FOR(&pos->obj->subscriptions, n) {
|
5338
|
-
FIO_LS_EMBD_OBJ(subscription_s, node, n)->lock = FIO_LOCK_INIT;
|
5339
|
-
}
|
5340
|
-
}
|
5341
|
-
FIO_SET_FOR_LOOP(&fio_postoffice.pubsub.channels, pos) {
|
5342
|
-
if (!pos->hash)
|
5343
|
-
continue;
|
5344
|
-
pos->obj->lock = FIO_LOCK_INIT;
|
5345
|
-
FIO_LS_EMBD_FOR(&pos->obj->subscriptions, n) {
|
5346
|
-
FIO_LS_EMBD_OBJ(subscription_s, node, n)->lock = FIO_LOCK_INIT;
|
5347
|
-
}
|
5348
|
-
}
|
5349
|
-
FIO_SET_FOR_LOOP(&fio_postoffice.patterns.channels, pos) {
|
5350
|
-
if (!pos->hash)
|
5351
|
-
continue;
|
5352
|
-
pos->obj->lock = FIO_LOCK_INIT;
|
5353
|
-
FIO_LS_EMBD_FOR(&pos->obj->subscriptions, n) {
|
5354
|
-
FIO_LS_EMBD_OBJ(subscription_s, node, n)->lock = FIO_LOCK_INIT;
|
5355
|
-
}
|
5356
|
-
}
|
5299
|
+
/** internal helper */
|
5300
|
+
|
5301
|
+
static inline ssize_t fio_msg_internal_send_dup(intptr_t uuid,
|
5302
|
+
fio_msg_internal_s *m) {
|
5303
|
+
return fio_write2(uuid, .data.buffer = fio_msg_internal_dup(m),
|
5304
|
+
.offset = (sizeof(*m) + (m->meta_len * sizeof(*m->meta))),
|
5305
|
+
.length = 16 + m->data.len + m->channel.len + 2,
|
5306
|
+
.after.dealloc = fio_msg_internal_free2);
|
5357
5307
|
}
|
5358
5308
|
|
5309
|
+
/**
|
5310
|
+
* A mock pub/sub callback for external subscriptions.
|
5311
|
+
*/
|
5312
|
+
static void fio_mock_on_message(fio_msg_s *msg) { (void)msg; }
|
5313
|
+
|
5359
5314
|
/* *****************************************************************************
|
5360
5315
|
Channel Subscription Management
|
5361
5316
|
***************************************************************************** */
|
5362
5317
|
|
5363
|
-
static void
|
5364
|
-
static void
|
5318
|
+
static void fio_pubsub_on_channel_create(channel_s *ch);
|
5319
|
+
static void fio_pubsub_on_channel_destroy(channel_s *ch);
|
5365
5320
|
|
5366
5321
|
/* some comon tasks extracted */
|
5367
5322
|
static inline channel_s *fio_filter_dup_lock_internal(channel_s *ch,
|
@@ -5399,7 +5354,7 @@ static channel_s *fio_channel_dup_lock(fio_str_info_s name) {
|
|
5399
5354
|
channel_s *ch_p =
|
5400
5355
|
fio_filter_dup_lock_internal(&ch, hashed_name, &fio_postoffice.pubsub);
|
5401
5356
|
if (fio_ls_embd_is_empty(&ch_p->subscriptions)) {
|
5402
|
-
|
5357
|
+
fio_pubsub_on_channel_create(ch_p);
|
5403
5358
|
}
|
5404
5359
|
return ch_p;
|
5405
5360
|
}
|
@@ -5419,7 +5374,7 @@ static channel_s *fio_channel_match_dup_lock(fio_str_info_s name,
|
|
5419
5374
|
channel_s *ch_p =
|
5420
5375
|
fio_filter_dup_lock_internal(&ch, hashed_name, &fio_postoffice.patterns);
|
5421
5376
|
if (fio_ls_embd_is_empty(&ch_p->subscriptions)) {
|
5422
|
-
|
5377
|
+
fio_pubsub_on_channel_create(ch_p);
|
5423
5378
|
}
|
5424
5379
|
return ch_p;
|
5425
5380
|
}
|
@@ -5436,6 +5391,9 @@ static inline void fio_subscription_free(subscription_s *s) {
|
|
5436
5391
|
fio_free(s);
|
5437
5392
|
}
|
5438
5393
|
|
5394
|
+
/** SublimeText 3 marker */
|
5395
|
+
subscription_s *fio_subscribe___(subscribe_args_s args);
|
5396
|
+
|
5439
5397
|
/** Subscribes to a filter, pub/sub channle or patten */
|
5440
5398
|
subscription_s *fio_subscribe FIO_IGNORE_MACRO(subscribe_args_s args) {
|
5441
5399
|
if (!args.on_message)
|
@@ -5495,7 +5453,7 @@ void fio_unsubscribe(subscription_s *s) {
|
|
5495
5453
|
}
|
5496
5454
|
fio_unlock(&ch->lock);
|
5497
5455
|
if (removed) {
|
5498
|
-
|
5456
|
+
fio_pubsub_on_channel_destroy(ch);
|
5499
5457
|
}
|
5500
5458
|
|
5501
5459
|
/* promise the subscription will be inactive */
|
@@ -5525,7 +5483,7 @@ static inline void fio_cluster_inform_root_about_channel(channel_s *ch,
|
|
5525
5483
|
int add);
|
5526
5484
|
|
5527
5485
|
/* runs in lock(!) let'm all know */
|
5528
|
-
static void
|
5486
|
+
static void fio_pubsub_on_channel_create(channel_s *ch) {
|
5529
5487
|
fio_lock(&fio_postoffice.engines.lock);
|
5530
5488
|
FIO_SET_FOR_LOOP(&fio_postoffice.engines.set, pos) {
|
5531
5489
|
if (!pos->hash)
|
@@ -5539,7 +5497,7 @@ static void pubsub_on_channel_create(channel_s *ch) {
|
|
5539
5497
|
}
|
5540
5498
|
|
5541
5499
|
/* runs in lock(!) let'm all know */
|
5542
|
-
static void
|
5500
|
+
static void fio_pubsub_on_channel_destroy(channel_s *ch) {
|
5543
5501
|
fio_lock(&fio_postoffice.engines.lock);
|
5544
5502
|
FIO_SET_FOR_LOOP(&fio_postoffice.engines.set, pos) {
|
5545
5503
|
if (!pos->hash)
|
@@ -5689,29 +5647,6 @@ static channel_s *fio_channel_find_dup(fio_str_info_s name) {
|
|
5689
5647
|
return ch;
|
5690
5648
|
}
|
5691
5649
|
|
5692
|
-
/** frees the internal message data */
|
5693
|
-
static inline void fio_msg_internal_free(fio_msg_internal_s *msg) {
|
5694
|
-
if (fio_atomic_sub(&msg->ref, 1))
|
5695
|
-
return;
|
5696
|
-
while (msg->meta_len) {
|
5697
|
-
--msg->meta_len;
|
5698
|
-
if (msg->meta[msg->meta_len].on_finish) {
|
5699
|
-
fio_msg_s tmp_msg = {
|
5700
|
-
.channel = msg->channel,
|
5701
|
-
.msg = msg->data,
|
5702
|
-
};
|
5703
|
-
msg->meta[msg->meta_len].on_finish(&tmp_msg,
|
5704
|
-
msg->meta[msg->meta_len].metadata);
|
5705
|
-
}
|
5706
|
-
}
|
5707
|
-
fio_free(msg);
|
5708
|
-
}
|
5709
|
-
/* add reference count to fio_msg_internal_s */
|
5710
|
-
static inline fio_msg_internal_s *fio_msg_internal_dup(fio_msg_internal_s *m) {
|
5711
|
-
fio_atomic_add(&m->ref, 1);
|
5712
|
-
return m;
|
5713
|
-
}
|
5714
|
-
|
5715
5650
|
/* defers the callback (mark only) */
|
5716
5651
|
void fio_message_defer(fio_msg_s *msg_) {
|
5717
5652
|
fio_msg_client_s *cl = (fio_msg_client_s *)msg_;
|
@@ -5756,7 +5691,7 @@ static void fio_perform_subscription_callback(void *s_, void *msg_) {
|
|
5756
5691
|
static void fio_publish2channel(channel_s *ch, fio_msg_internal_s *msg) {
|
5757
5692
|
FIO_LS_EMBD_FOR(&ch->subscriptions, pos) {
|
5758
5693
|
subscription_s *s = FIO_LS_EMBD_OBJ(subscription_s, node, pos);
|
5759
|
-
if (!s) {
|
5694
|
+
if (!s || s->on_message == fio_mock_on_message) {
|
5760
5695
|
continue;
|
5761
5696
|
}
|
5762
5697
|
fio_atomic_add(&s->ref, 1);
|
@@ -5783,6 +5718,7 @@ finish:
|
|
5783
5718
|
|
5784
5719
|
/** Publishes the message to the current process and frees the strings. */
|
5785
5720
|
static void fio_publish2process(fio_msg_internal_s *m) {
|
5721
|
+
fio_msg_internal_finalize(m);
|
5786
5722
|
channel_s *ch;
|
5787
5723
|
if (m->filter) {
|
5788
5724
|
ch = fio_filter_find_dup(m->filter);
|
@@ -5842,7 +5778,7 @@ typedef struct cluster_pr_s {
|
|
5842
5778
|
fio_protocol_s protocol;
|
5843
5779
|
fio_msg_internal_s *msg;
|
5844
5780
|
void (*handler)(struct cluster_pr_s *pr);
|
5845
|
-
void (*sender)(
|
5781
|
+
void (*sender)(void *data, intptr_t avoid_uuid);
|
5846
5782
|
fio_sub_hash_s pubsub;
|
5847
5783
|
fio_sub_hash_s patterns;
|
5848
5784
|
intptr_t uuid;
|
@@ -5928,36 +5864,14 @@ static void fio_cluster_init(void) {
|
|
5928
5864
|
* Cluster Protocol callbacks
|
5929
5865
|
**************************************************************************** */
|
5930
5866
|
|
5931
|
-
typedef struct cluster_msg_s {
|
5932
|
-
fio_msg_s message;
|
5933
|
-
size_t ref;
|
5934
|
-
} cluster_msg_s;
|
5935
|
-
|
5936
|
-
static inline fio_str_s *
|
5937
|
-
fio_cluster_wrap_message(uint32_t ch_len, uint32_t msg_len, uint32_t type,
|
5938
|
-
int32_t filter, void *ch_data, void *msg_data) {
|
5939
|
-
fio_str_s *buf = fio_str_new2();
|
5940
|
-
fio_str_info_s i = fio_str_resize(buf, ch_len + msg_len + 16);
|
5941
|
-
fio_u2str32((uint8_t *)i.data, ch_len);
|
5942
|
-
fio_u2str32((uint8_t *)(i.data + 4), msg_len);
|
5943
|
-
fio_u2str32((uint8_t *)(i.data + 8), type);
|
5944
|
-
fio_u2str32((uint8_t *)(i.data + 12), (uint32_t)filter);
|
5945
|
-
if (ch_len && ch_data) {
|
5946
|
-
memcpy((i.data + 16), ch_data, ch_len);
|
5947
|
-
}
|
5948
|
-
if (msg_len && msg_data) {
|
5949
|
-
memcpy((i.data + 16 + ch_len), msg_data, msg_len);
|
5950
|
-
}
|
5951
|
-
return buf;
|
5952
|
-
}
|
5953
|
-
|
5954
5867
|
static inline void fio_cluster_protocol_free(void *pr) { fio_free(pr); }
|
5955
5868
|
|
5956
5869
|
static uint8_t fio_cluster_on_shutdown(intptr_t uuid, fio_protocol_s *pr_) {
|
5957
5870
|
cluster_pr_s *p = (cluster_pr_s *)pr_;
|
5958
|
-
p->sender(
|
5959
|
-
|
5960
|
-
|
5871
|
+
p->sender(fio_msg_internal_create(0, FIO_CLUSTER_MSG_SHUTDOWN,
|
5872
|
+
(fio_str_info_s){.len = 0},
|
5873
|
+
(fio_str_info_s){.len = 0}, 0, 1),
|
5874
|
+
-1);
|
5961
5875
|
return 255;
|
5962
5876
|
(void)pr_;
|
5963
5877
|
(void)uuid;
|
@@ -5975,12 +5889,12 @@ static void fio_cluster_on_data(intptr_t uuid, fio_protocol_s *pr_) {
|
|
5975
5889
|
if (!c->exp_channel && !c->exp_msg) {
|
5976
5890
|
if (c->length - i < 16)
|
5977
5891
|
break;
|
5978
|
-
c->exp_channel = fio_str2u32(c->buffer + i);
|
5979
|
-
c->exp_msg = fio_str2u32(c->buffer + i + 4);
|
5892
|
+
c->exp_channel = fio_str2u32(c->buffer + i) + 1;
|
5893
|
+
c->exp_msg = fio_str2u32(c->buffer + i + 4) + 1;
|
5980
5894
|
c->type = fio_str2u32(c->buffer + i + 8);
|
5981
5895
|
c->filter = (int32_t)fio_str2u32(c->buffer + i + 12);
|
5982
5896
|
if (c->exp_channel) {
|
5983
|
-
if (c->exp_channel >= (1024 * 1024 * 16)) {
|
5897
|
+
if (c->exp_channel >= (1024 * 1024 * 16) + 1) {
|
5984
5898
|
FIO_LOG_FATAL("(%d) cluster message name too long (16Mb limit): %u\n",
|
5985
5899
|
getpid(), (unsigned int)c->exp_channel);
|
5986
5900
|
exit(1);
|
@@ -5988,18 +5902,19 @@ static void fio_cluster_on_data(intptr_t uuid, fio_protocol_s *pr_) {
|
|
5988
5902
|
}
|
5989
5903
|
}
|
5990
5904
|
if (c->exp_msg) {
|
5991
|
-
if (c->exp_msg >= (1024 * 1024 * 64)) {
|
5905
|
+
if (c->exp_msg >= (1024 * 1024 * 64) + 1) {
|
5992
5906
|
FIO_LOG_FATAL("(%d) cluster message data too long (64Mb limit): %u\n",
|
5993
5907
|
getpid(), (unsigned int)c->exp_msg);
|
5994
5908
|
exit(1);
|
5995
5909
|
return;
|
5996
5910
|
}
|
5997
5911
|
}
|
5998
|
-
c->msg =
|
5999
|
-
c->filter,
|
6000
|
-
(fio_str_info_s){.data = (char *)(c->msg + 1),
|
5912
|
+
c->msg = fio_msg_internal_create(
|
5913
|
+
c->filter, c->type,
|
5914
|
+
(fio_str_info_s){.data = (char *)(c->msg + 1),
|
5915
|
+
.len = c->exp_channel - 1},
|
6001
5916
|
(fio_str_info_s){.data = ((char *)(c->msg + 1) + c->exp_channel + 1),
|
6002
|
-
.len = c->exp_msg},
|
5917
|
+
.len = c->exp_msg - 1},
|
6003
5918
|
(int8_t)(c->type == FIO_CLUSTER_MSG_JSON ||
|
6004
5919
|
c->type == FIO_CLUSTER_MSG_ROOT_JSON),
|
6005
5920
|
0);
|
@@ -6007,13 +5922,15 @@ static void fio_cluster_on_data(intptr_t uuid, fio_protocol_s *pr_) {
|
|
6007
5922
|
}
|
6008
5923
|
if (c->exp_channel) {
|
6009
5924
|
if (c->exp_channel + i > c->length) {
|
6010
|
-
memcpy(c->msg->channel.data +
|
5925
|
+
memcpy(c->msg->channel.data +
|
5926
|
+
((c->msg->channel.len + 1) - c->exp_channel),
|
6011
5927
|
(char *)c->buffer + i, (size_t)(c->length - i));
|
6012
5928
|
c->exp_channel -= (c->length - i);
|
6013
5929
|
i = c->length;
|
6014
5930
|
break;
|
6015
5931
|
} else {
|
6016
|
-
memcpy(c->msg->channel.data +
|
5932
|
+
memcpy(c->msg->channel.data +
|
5933
|
+
((c->msg->channel.len + 1) - c->exp_channel),
|
6017
5934
|
(char *)c->buffer + i, (size_t)(c->exp_channel));
|
6018
5935
|
i += c->exp_channel;
|
6019
5936
|
c->exp_channel = 0;
|
@@ -6021,19 +5938,19 @@ static void fio_cluster_on_data(intptr_t uuid, fio_protocol_s *pr_) {
|
|
6021
5938
|
}
|
6022
5939
|
if (c->exp_msg) {
|
6023
5940
|
if (c->exp_msg + i > c->length) {
|
6024
|
-
memcpy(c->msg->data.data + (c->msg->data.len - c->exp_msg),
|
5941
|
+
memcpy(c->msg->data.data + ((c->msg->data.len + 1) - c->exp_msg),
|
6025
5942
|
(char *)c->buffer + i, (size_t)(c->length - i));
|
6026
5943
|
c->exp_msg -= (c->length - i);
|
6027
5944
|
i = c->length;
|
6028
5945
|
break;
|
6029
5946
|
} else {
|
6030
|
-
memcpy(c->msg->data.data + (c->msg->data.len - c->exp_msg),
|
5947
|
+
memcpy(c->msg->data.data + ((c->msg->data.len + 1) - c->exp_msg),
|
6031
5948
|
(char *)c->buffer + i, (size_t)(c->exp_msg));
|
6032
5949
|
i += c->exp_msg;
|
6033
5950
|
c->exp_msg = 0;
|
6034
5951
|
}
|
6035
5952
|
}
|
6036
|
-
|
5953
|
+
fio_postoffice_meta_update(c->msg);
|
6037
5954
|
c->handler(c);
|
6038
5955
|
fio_msg_internal_free(c->msg);
|
6039
5956
|
c->msg = NULL;
|
@@ -6046,8 +5963,11 @@ static void fio_cluster_on_data(intptr_t uuid, fio_protocol_s *pr_) {
|
|
6046
5963
|
}
|
6047
5964
|
|
6048
5965
|
static void fio_cluster_ping(intptr_t uuid, fio_protocol_s *pr_) {
|
6049
|
-
|
6050
|
-
|
5966
|
+
fio_msg_internal_s *m = fio_msg_internal_create(
|
5967
|
+
0, FIO_CLUSTER_MSG_PING, (fio_str_info_s){.len = 0},
|
5968
|
+
(fio_str_info_s){.len = 0}, 0, 1);
|
5969
|
+
fio_msg_internal_send_dup(uuid, m);
|
5970
|
+
fio_msg_internal_free(m);
|
6051
5971
|
(void)pr_;
|
6052
5972
|
}
|
6053
5973
|
|
@@ -6084,7 +6004,7 @@ static void fio_cluster_on_close(intptr_t uuid, fio_protocol_s *pr_) {
|
|
6084
6004
|
static inline fio_protocol_s *
|
6085
6005
|
fio_cluster_protocol_alloc(intptr_t uuid,
|
6086
6006
|
void (*handler)(struct cluster_pr_s *pr),
|
6087
|
-
void (*sender)(
|
6007
|
+
void (*sender)(void *data, intptr_t auuid)) {
|
6088
6008
|
cluster_pr_s *p = fio_mmap(sizeof(*p));
|
6089
6009
|
if (!p) {
|
6090
6010
|
FIO_LOG_FATAL("Cluster protocol allocation failed.");
|
@@ -6109,35 +6029,28 @@ fio_cluster_protocol_alloc(intptr_t uuid,
|
|
6109
6029
|
* Master (server) IPC Connections
|
6110
6030
|
**************************************************************************** */
|
6111
6031
|
|
6112
|
-
|
6113
|
-
*
|
6114
|
-
*/
|
6115
|
-
static void fio_mock_on_message(fio_msg_s *msg) { (void)msg; }
|
6116
|
-
|
6117
|
-
static void fio_cluster_server_sender(fio_str_s *data, intptr_t avoid_uuid) {
|
6032
|
+
static void fio_cluster_server_sender(void *m_, intptr_t avoid_uuid) {
|
6033
|
+
fio_msg_internal_s *m = m_;
|
6118
6034
|
fio_lock(&cluster_data.lock);
|
6119
6035
|
FIO_LS_FOR(&cluster_data.clients, pos) {
|
6120
6036
|
if ((intptr_t)pos->obj != -1) {
|
6121
6037
|
if ((intptr_t)pos->obj != avoid_uuid) {
|
6122
|
-
|
6038
|
+
fio_msg_internal_send_dup((intptr_t)pos->obj, m);
|
6123
6039
|
}
|
6124
6040
|
}
|
6125
6041
|
}
|
6126
6042
|
fio_unlock(&cluster_data.lock);
|
6127
|
-
|
6043
|
+
fio_msg_internal_free(m);
|
6128
6044
|
}
|
6129
6045
|
|
6130
6046
|
static void fio_cluster_server_handler(struct cluster_pr_s *pr) {
|
6131
6047
|
/* what to do? */
|
6048
|
+
// fprintf(stderr, "-");
|
6132
6049
|
switch ((fio_cluster_message_type_e)pr->type) {
|
6133
6050
|
|
6134
6051
|
case FIO_CLUSTER_MSG_FORWARD: /* fallthrough */
|
6135
6052
|
case FIO_CLUSTER_MSG_JSON: {
|
6136
|
-
fio_cluster_server_sender(
|
6137
|
-
fio_cluster_wrap_message(pr->msg->channel.len, pr->msg->data.len,
|
6138
|
-
pr->type, pr->msg->filter,
|
6139
|
-
pr->msg->channel.data, pr->msg->data.data),
|
6140
|
-
pr->uuid);
|
6053
|
+
fio_cluster_server_sender(fio_msg_internal_dup(pr->msg), pr->uuid);
|
6141
6054
|
fio_publish2process(fio_msg_internal_dup(pr->msg));
|
6142
6055
|
break;
|
6143
6056
|
}
|
@@ -6262,9 +6175,7 @@ static void fio_listen2cluster(void *ignore) {
|
|
6262
6175
|
.ping = mock_ping_eternal,
|
6263
6176
|
.on_close = fio_cluster_listen_on_close,
|
6264
6177
|
};
|
6265
|
-
#if DEBUG
|
6266
6178
|
FIO_LOG_DEBUG("(%d) Listening to cluster: %s", getpid(), cluster_data.name);
|
6267
|
-
#endif
|
6268
6179
|
fio_attach(cluster_data.uuid, p);
|
6269
6180
|
(void)ignore;
|
6270
6181
|
}
|
@@ -6296,15 +6207,16 @@ static void fio_cluster_client_handler(struct cluster_pr_s *pr) {
|
|
6296
6207
|
break;
|
6297
6208
|
}
|
6298
6209
|
}
|
6299
|
-
static void fio_cluster_client_sender(
|
6210
|
+
static void fio_cluster_client_sender(void *m_, intptr_t ignr_) {
|
6211
|
+
fio_msg_internal_s *m = m_;
|
6300
6212
|
if (!uuid_is_valid(cluster_data.uuid) && fio_data->active) {
|
6301
6213
|
/* delay message delivery until we have a vaild uuid */
|
6302
|
-
fio_defer_push_task((void (*)(void *, void *))fio_cluster_client_sender,
|
6303
|
-
|
6214
|
+
fio_defer_push_task((void (*)(void *, void *))fio_cluster_client_sender, m_,
|
6215
|
+
(void *)ignr_);
|
6304
6216
|
return;
|
6305
6217
|
}
|
6306
|
-
|
6307
|
-
(
|
6218
|
+
fio_msg_internal_send_dup(cluster_data.uuid, m);
|
6219
|
+
fio_msg_internal_free(m);
|
6308
6220
|
}
|
6309
6221
|
|
6310
6222
|
/** The address of the server we are connecting to. */
|
@@ -6357,15 +6269,17 @@ static void fio_cluster_on_fail(intptr_t uuid, void *udata) {
|
|
6357
6269
|
}
|
6358
6270
|
|
6359
6271
|
static void fio_connect2cluster(void *ignore) {
|
6272
|
+
if (cluster_data.uuid)
|
6273
|
+
fio_force_close(cluster_data.uuid);
|
6274
|
+
cluster_data.uuid = 0;
|
6360
6275
|
/* this is called for each child, but not for single a process worker. */
|
6361
|
-
|
6362
|
-
|
6363
|
-
|
6276
|
+
fio_connect(.address = cluster_data.name, .port = NULL,
|
6277
|
+
.on_connect = fio_cluster_on_connect,
|
6278
|
+
.on_fail = fio_cluster_on_fail);
|
6364
6279
|
(void)ignore;
|
6365
6280
|
}
|
6366
6281
|
|
6367
|
-
static void fio_send2cluster(
|
6368
|
-
fio_str_info_s msg, uint8_t is_json) {
|
6282
|
+
static void fio_send2cluster(fio_msg_internal_s *m) {
|
6369
6283
|
if (!fio_is_running()) {
|
6370
6284
|
FIO_LOG_ERROR("facio.io cluster inactive, can't send message.");
|
6371
6285
|
return;
|
@@ -6375,19 +6289,9 @@ static void fio_send2cluster(int32_t filter, fio_str_info_s ch,
|
|
6375
6289
|
return;
|
6376
6290
|
}
|
6377
6291
|
if (fio_is_master()) {
|
6378
|
-
fio_cluster_server_sender(
|
6379
|
-
fio_cluster_wrap_message(
|
6380
|
-
ch.len, msg.len,
|
6381
|
-
(is_json ? FIO_CLUSTER_MSG_JSON : FIO_CLUSTER_MSG_FORWARD), filter,
|
6382
|
-
ch.data, msg.data),
|
6383
|
-
-1);
|
6292
|
+
fio_cluster_server_sender(fio_msg_internal_dup(m), -1);
|
6384
6293
|
} else {
|
6385
|
-
fio_cluster_client_sender(
|
6386
|
-
fio_cluster_wrap_message(
|
6387
|
-
ch.len, msg.len,
|
6388
|
-
(is_json ? FIO_CLUSTER_MSG_JSON : FIO_CLUSTER_MSG_FORWARD), filter,
|
6389
|
-
ch.data, msg.data),
|
6390
|
-
-1);
|
6294
|
+
fio_cluster_client_sender(fio_msg_internal_dup(m), -1);
|
6391
6295
|
}
|
6392
6296
|
}
|
6393
6297
|
|
@@ -6418,13 +6322,13 @@ static inline void fio_cluster_inform_root_about_channel(channel_s *ch,
|
|
6418
6322
|
}
|
6419
6323
|
|
6420
6324
|
fio_cluster_client_sender(
|
6421
|
-
|
6422
|
-
|
6423
|
-
|
6424
|
-
|
6425
|
-
|
6426
|
-
|
6427
|
-
|
6325
|
+
fio_msg_internal_create(0,
|
6326
|
+
(ch->match
|
6327
|
+
? (add ? FIO_CLUSTER_MSG_PATTERN_SUB
|
6328
|
+
: FIO_CLUSTER_MSG_PATTERN_UNSUB)
|
6329
|
+
: (add ? FIO_CLUSTER_MSG_PUBSUB_SUB
|
6330
|
+
: FIO_CLUSTER_MSG_PUBSUB_UNSUB)),
|
6331
|
+
ch_name, msg, 0, 1),
|
6428
6332
|
-1);
|
6429
6333
|
}
|
6430
6334
|
|
@@ -6432,13 +6336,9 @@ static inline void fio_cluster_inform_root_about_channel(channel_s *ch,
|
|
6432
6336
|
* Initialization
|
6433
6337
|
**************************************************************************** */
|
6434
6338
|
|
6435
|
-
static void
|
6436
|
-
|
6437
|
-
|
6438
|
-
fio_cluster_listen_accept(cluster_data.uuid, NULL);
|
6439
|
-
} else {
|
6440
|
-
/* this is called for each child. */
|
6441
|
-
}
|
6339
|
+
static void fio_accept_after_fork(void *ignore) {
|
6340
|
+
/* prevent `accept` backlog in parent */
|
6341
|
+
fio_cluster_listen_accept(cluster_data.uuid, NULL);
|
6442
6342
|
(void)ignore;
|
6443
6343
|
}
|
6444
6344
|
|
@@ -6497,12 +6397,50 @@ static void fio_cluster_at_exit(void *ignore) {
|
|
6497
6397
|
static void fio_pubsub_initialize(void) {
|
6498
6398
|
fio_cluster_init();
|
6499
6399
|
fio_state_callback_add(FIO_CALL_PRE_START, fio_listen2cluster, NULL);
|
6500
|
-
fio_state_callback_add(
|
6400
|
+
fio_state_callback_add(FIO_CALL_IN_MASTER, fio_accept_after_fork, NULL);
|
6501
6401
|
fio_state_callback_add(FIO_CALL_IN_CHILD, fio_connect2cluster, NULL);
|
6502
6402
|
fio_state_callback_add(FIO_CALL_ON_FINISH, fio_cluster_cleanup, NULL);
|
6503
6403
|
fio_state_callback_add(FIO_CALL_AT_EXIT, fio_cluster_at_exit, NULL);
|
6504
6404
|
}
|
6505
6405
|
|
6406
|
+
/* *****************************************************************************
|
6407
|
+
Cluster forking handler
|
6408
|
+
***************************************************************************** */
|
6409
|
+
|
6410
|
+
static void fio_pubsub_on_fork(void) {
|
6411
|
+
fio_postoffice.filters.lock = FIO_LOCK_INIT;
|
6412
|
+
fio_postoffice.pubsub.lock = FIO_LOCK_INIT;
|
6413
|
+
fio_postoffice.patterns.lock = FIO_LOCK_INIT;
|
6414
|
+
fio_postoffice.engines.lock = FIO_LOCK_INIT;
|
6415
|
+
fio_postoffice.meta.lock = FIO_LOCK_INIT;
|
6416
|
+
cluster_data.lock = FIO_LOCK_INIT;
|
6417
|
+
cluster_data.uuid = 0;
|
6418
|
+
FIO_SET_FOR_LOOP(&fio_postoffice.filters.channels, pos) {
|
6419
|
+
if (!pos->hash)
|
6420
|
+
continue;
|
6421
|
+
pos->obj->lock = FIO_LOCK_INIT;
|
6422
|
+
FIO_LS_EMBD_FOR(&pos->obj->subscriptions, n) {
|
6423
|
+
FIO_LS_EMBD_OBJ(subscription_s, node, n)->lock = FIO_LOCK_INIT;
|
6424
|
+
}
|
6425
|
+
}
|
6426
|
+
FIO_SET_FOR_LOOP(&fio_postoffice.pubsub.channels, pos) {
|
6427
|
+
if (!pos->hash)
|
6428
|
+
continue;
|
6429
|
+
pos->obj->lock = FIO_LOCK_INIT;
|
6430
|
+
FIO_LS_EMBD_FOR(&pos->obj->subscriptions, n) {
|
6431
|
+
FIO_LS_EMBD_OBJ(subscription_s, node, n)->lock = FIO_LOCK_INIT;
|
6432
|
+
}
|
6433
|
+
}
|
6434
|
+
FIO_SET_FOR_LOOP(&fio_postoffice.patterns.channels, pos) {
|
6435
|
+
if (!pos->hash)
|
6436
|
+
continue;
|
6437
|
+
pos->obj->lock = FIO_LOCK_INIT;
|
6438
|
+
FIO_LS_EMBD_FOR(&pos->obj->subscriptions, n) {
|
6439
|
+
FIO_LS_EMBD_OBJ(subscription_s, node, n)->lock = FIO_LOCK_INIT;
|
6440
|
+
}
|
6441
|
+
}
|
6442
|
+
}
|
6443
|
+
|
6506
6444
|
/* *****************************************************************************
|
6507
6445
|
* External API
|
6508
6446
|
**************************************************************************** */
|
@@ -6513,15 +6451,11 @@ static void fio_cluster_signal_children(void) {
|
|
6513
6451
|
kill(getpid(), SIGINT);
|
6514
6452
|
return;
|
6515
6453
|
}
|
6516
|
-
fio_cluster_server_sender(
|
6517
|
-
|
6518
|
-
|
6519
|
-
|
6520
|
-
|
6521
|
-
static inline void fio_publish2process2(int32_t filter, fio_str_info_s ch_name,
|
6522
|
-
fio_str_info_s msg, uint8_t is_json) {
|
6523
|
-
fio_publish2process(
|
6524
|
-
fio_pubsub_create_message(filter, ch_name, msg, is_json, 1));
|
6454
|
+
fio_cluster_server_sender(fio_msg_internal_create(0, FIO_CLUSTER_MSG_SHUTDOWN,
|
6455
|
+
(fio_str_info_s){.len = 0},
|
6456
|
+
(fio_str_info_s){.len = 0},
|
6457
|
+
0, 1),
|
6458
|
+
-1);
|
6525
6459
|
}
|
6526
6460
|
|
6527
6461
|
/* Sublime Text marker */
|
@@ -6549,29 +6483,40 @@ void fio_publish FIO_IGNORE_MACRO(fio_publish_args_s args) {
|
|
6549
6483
|
} else if (!args.engine) {
|
6550
6484
|
args.engine = FIO_PUBSUB_DEFAULT;
|
6551
6485
|
}
|
6486
|
+
fio_msg_internal_s *m = NULL;
|
6552
6487
|
switch ((uintptr_t)args.engine) {
|
6553
6488
|
case 0UL: /* fallthrough (missing default) */
|
6554
6489
|
case 1UL: // ((uintptr_t)FIO_PUBSUB_CLUSTER):
|
6555
|
-
|
6556
|
-
|
6490
|
+
m = fio_msg_internal_create(
|
6491
|
+
args.filter,
|
6492
|
+
(args.is_json ? FIO_CLUSTER_MSG_JSON : FIO_CLUSTER_MSG_FORWARD),
|
6493
|
+
args.channel, args.message, args.is_json, 1);
|
6494
|
+
fio_send2cluster(m);
|
6495
|
+
fio_publish2process(m);
|
6557
6496
|
break;
|
6558
6497
|
case 2UL: // ((uintptr_t)FIO_PUBSUB_PROCESS):
|
6559
|
-
|
6498
|
+
m = fio_msg_internal_create(args.filter, 0, args.channel, args.message,
|
6499
|
+
args.is_json, 1);
|
6500
|
+
fio_publish2process(m);
|
6560
6501
|
break;
|
6561
6502
|
case 3UL: // ((uintptr_t)FIO_PUBSUB_SIBLINGS):
|
6562
|
-
|
6503
|
+
m = fio_msg_internal_create(
|
6504
|
+
args.filter,
|
6505
|
+
(args.is_json ? FIO_CLUSTER_MSG_JSON : FIO_CLUSTER_MSG_FORWARD),
|
6506
|
+
args.channel, args.message, args.is_json, 1);
|
6507
|
+
fio_send2cluster(m);
|
6508
|
+
fio_msg_internal_free(m);
|
6509
|
+
m = NULL;
|
6563
6510
|
break;
|
6564
6511
|
case 4UL: // ((uintptr_t)FIO_PUBSUB_ROOT):
|
6512
|
+
m = fio_msg_internal_create(
|
6513
|
+
args.filter,
|
6514
|
+
(args.is_json ? FIO_CLUSTER_MSG_ROOT_JSON : FIO_CLUSTER_MSG_ROOT),
|
6515
|
+
args.channel, args.message, args.is_json, 1);
|
6565
6516
|
if (fio_data->is_worker == 0 || fio_data->workers == 1) {
|
6566
|
-
|
6567
|
-
args.is_json);
|
6517
|
+
fio_publish2process(m);
|
6568
6518
|
} else {
|
6569
|
-
fio_cluster_client_sender(
|
6570
|
-
fio_cluster_wrap_message(
|
6571
|
-
args.channel.len, args.message.len,
|
6572
|
-
(args.is_json ? FIO_CLUSTER_MSG_ROOT_JSON : FIO_CLUSTER_MSG_ROOT),
|
6573
|
-
args.filter, args.channel.data, args.message.data),
|
6574
|
-
-1);
|
6519
|
+
fio_cluster_client_sender(m, -1);
|
6575
6520
|
}
|
6576
6521
|
break;
|
6577
6522
|
default:
|
@@ -6582,8 +6527,6 @@ void fio_publish FIO_IGNORE_MACRO(fio_publish_args_s args) {
|
|
6582
6527
|
}
|
6583
6528
|
args.engine->publish(args.engine, args.channel, args.message, args.is_json);
|
6584
6529
|
}
|
6585
|
-
// fio_str_free2(ch);
|
6586
|
-
// fio_str_free2(msg);
|
6587
6530
|
return;
|
6588
6531
|
}
|
6589
6532
|
|
@@ -9145,7 +9088,8 @@ FIO_FUNC inline void fio_str_test(void) {
|
|
9145
9088
|
FIO_ASSERT(str.dealloc, "Missing static string deallocation function"
|
9146
9089
|
" after `fio_str_write`.");
|
9147
9090
|
|
9148
|
-
fprintf(stderr, "* reviewing `fio_str_detach`.\n (%zu): %s\n",
|
9091
|
+
fprintf(stderr, "* reviewing `fio_str_detach`.\n (%zu): %s\n",
|
9092
|
+
fio_str_info(&str).len, fio_str_info(&str).data);
|
9149
9093
|
char *cstr = fio_str_detach(&str);
|
9150
9094
|
FIO_ASSERT(cstr, "`fio_str_detach` returned NULL");
|
9151
9095
|
FIO_ASSERT(!memcmp(cstr, "Welcome Home\0", 13),
|
@@ -9460,9 +9404,12 @@ FIO_FUNC void fio_socket_test(void) {
|
|
9460
9404
|
ssize_t r = -1;
|
9461
9405
|
ssize_t timer_junk;
|
9462
9406
|
fio_write(client1, "Hello World", 11);
|
9463
|
-
if (
|
9464
|
-
|
9465
|
-
|
9407
|
+
if (0) {
|
9408
|
+
/* packet may have been sent synchronously, don't test */
|
9409
|
+
if (!uuid_data(client1).packet)
|
9410
|
+
unlink(__FILE__ ".sock");
|
9411
|
+
FIO_ASSERT(uuid_data(client1).packet, "fio_write error, no packet!")
|
9412
|
+
}
|
9466
9413
|
/* prevent poll from hanging */
|
9467
9414
|
fio_run_every(5, 1, fio_timer_test_task, &timer_junk, fio_timer_test_task);
|
9468
9415
|
errno = EAGAIN;
|