iodine 0.7.1 → 0.7.2
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/.travis.yml +3 -3
- data/CHANGELOG.md +8 -0
- data/bin/mustache.rb +12 -40
- data/ext/iodine/fio.c +343 -236
- data/ext/iodine/fio.h +419 -183
- data/ext/iodine/fio_cli.c +4 -5
- data/ext/iodine/fiobj_ary.c +2 -3
- data/ext/iodine/fiobj_data.c +1 -1
- data/ext/iodine/fiobj_hash.c +88 -105
- data/ext/iodine/fiobj_json.c +4 -3
- data/ext/iodine/fiobj_numbers.c +1 -1
- data/ext/iodine/fiobj_str.c +5 -5
- data/ext/iodine/fiobject.c +14 -3
- data/ext/iodine/fiobject.h +4 -0
- data/ext/iodine/http.c +62 -77
- data/ext/iodine/http1.c +9 -12
- data/ext/iodine/http_internal.c +15 -6
- data/ext/iodine/http_internal.h +0 -8
- data/ext/iodine/iodine.c +12 -25
- data/ext/iodine/iodine_defer.c +59 -54
- data/ext/iodine/iodine_http.c +4 -32
- data/ext/iodine/iodine_mustache.c +138 -16
- data/ext/iodine/iodine_mustache.h +3 -3
- data/ext/iodine/iodine_store.c +16 -21
- data/ext/iodine/mustache_parser.h +49 -5
- data/ext/iodine/redis_engine.c +31 -31
- data/ext/iodine/websockets.c +11 -5
- data/lib/iodine.rb +13 -1
- data/lib/iodine/mustache.rb +13 -41
- data/lib/iodine/version.rb +1 -1
- metadata +2 -4
- data/ext/iodine/fio_hashmap.h +0 -813
- data/ext/iodine/fio_str.h +0 -1218
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9304bf27335fe19b9c7d7ca9442fe994772c5489a70aa598cc045bda313c755
|
4
|
+
data.tar.gz: 8acee18f9da3f77a763fb7c93ac2c4328788c79298c5b792597e6b40ee1b14c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aef5181c233342793d2c74a8d4ca6c398a357c36bc399dd133f796aa0c2e67ed881d99514b45c2e85da880e0a2b49844fa869afc28be696dc63675558b7dba2c
|
7
|
+
data.tar.gz: 6e6f11fd287cafbcc9eae4ef3df92fe4b4c543e9d930344745725c59cc4be587d24e8c226416ae65208516bd995afa90c210847f0e8faf9873dfe3913c4ef7dc
|
data/.travis.yml
CHANGED
@@ -24,8 +24,8 @@ addons:
|
|
24
24
|
script:
|
25
25
|
- gem uninstall -x iodine
|
26
26
|
- rake build
|
27
|
-
- find pkg/iodine-*.gem -exec gem install {} +
|
27
|
+
- find pkg/iodine-*.gem -exec gem install -V {} +
|
28
28
|
- gem uninstall -x iodine
|
29
|
-
- CC=gcc find pkg/iodine-*.gem -exec gem install {} +
|
29
|
+
- CC=gcc find pkg/iodine-*.gem -exec gem install -V {} +
|
30
30
|
- gem uninstall -x iodine
|
31
|
-
- CC=gcc-5 find pkg/iodine-*.gem -exec gem install {} +
|
31
|
+
- CC=gcc-5 find pkg/iodine-*.gem -exec gem install -V {} +
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,14 @@ 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.2
|
10
|
+
|
11
|
+
**Updated**: updated the logging for HTTP services startup, to minimize log clutter.
|
12
|
+
|
13
|
+
**Feature**: (mustache) added features to `Iodine::Mustache`, to expose more of the functionality offered by facil.io.
|
14
|
+
|
15
|
+
**Fix**: (facil.io) updated from the facil.io edge (master) branch. This should fix some exposed symbols (that should have been private), minimize name-collision risks, and fix an unknown issue with the mime-type registry cleanup and other possible issues.
|
16
|
+
|
9
17
|
#### Change log v.0.7.1
|
10
18
|
|
11
19
|
**Fix**: Fixed compilation issues with older `gcc` compilers.
|
data/bin/mustache.rb
CHANGED
@@ -25,6 +25,7 @@ def benchmark_mustache
|
|
25
25
|
"""
|
26
26
|
|
27
27
|
IO.write "test_template.mustache", template
|
28
|
+
filename = "test_template.mustache"
|
28
29
|
|
29
30
|
data_1 = {
|
30
31
|
products: [ {
|
@@ -33,31 +34,6 @@ def benchmark_mustache
|
|
33
34
|
:image=>"products/product.jpg"
|
34
35
|
} ]
|
35
36
|
}
|
36
|
-
|
37
|
-
data_10 = {
|
38
|
-
products: []
|
39
|
-
}
|
40
|
-
|
41
|
-
10.times do
|
42
|
-
data_10[:products] << {
|
43
|
-
:external_index=>"product",
|
44
|
-
:url=>"/products/7",
|
45
|
-
:image=>"products/product.jpg"
|
46
|
-
}
|
47
|
-
end
|
48
|
-
|
49
|
-
data_100 = {
|
50
|
-
products: []
|
51
|
-
}
|
52
|
-
|
53
|
-
100.times do
|
54
|
-
data_100[:products] << {
|
55
|
-
:external_index=>"product",
|
56
|
-
:url=>"/products/7",
|
57
|
-
:image=>"products/product.jpg"
|
58
|
-
}
|
59
|
-
end
|
60
|
-
|
61
37
|
data_1000 = {
|
62
38
|
products: []
|
63
39
|
}
|
@@ -85,7 +61,7 @@ def benchmark_mustache
|
|
85
61
|
view = Mustache.new
|
86
62
|
view.template = template
|
87
63
|
view.render # Call render once so the template will be compiled
|
88
|
-
iodine_view = Iodine::Mustache.new(
|
64
|
+
iodine_view = Iodine::Mustache.new(filename)
|
89
65
|
|
90
66
|
puts "Ruby Mustache rendering (and HTML escaping) results in:",
|
91
67
|
view.render(data_1), "",
|
@@ -95,20 +71,6 @@ def benchmark_mustache
|
|
95
71
|
# return;
|
96
72
|
|
97
73
|
Benchmark.ips do |x|
|
98
|
-
x.report("Ruby Mustache render list of 10") do |times|
|
99
|
-
view.render(data_10)
|
100
|
-
end
|
101
|
-
x.report("Iodine::Mustache render list of 10") do |times|
|
102
|
-
iodine_view.render(data_10)
|
103
|
-
end
|
104
|
-
|
105
|
-
x.report("Ruby Mustache render list of 100") do |times|
|
106
|
-
view.render(data_100)
|
107
|
-
end
|
108
|
-
x.report("Iodine::Mustache render list of 100") do |times|
|
109
|
-
iodine_view.render(data_100)
|
110
|
-
end
|
111
|
-
|
112
74
|
x.report("Ruby Mustache render list of 1000") do |times|
|
113
75
|
view.render(data_1000)
|
114
76
|
end
|
@@ -122,6 +84,16 @@ def benchmark_mustache
|
|
122
84
|
x.report("Iodine::Mustache render list of 1000 with escaped data") do |times|
|
123
85
|
iodine_view.render(data_1000_escaped)
|
124
86
|
end
|
87
|
+
|
88
|
+
x.report("Ruby Mustache - no chaching - render list of 1000") do |times|
|
89
|
+
tmp = Mustache.new
|
90
|
+
tmp.template = template
|
91
|
+
tmp.render(data_1000)
|
92
|
+
end
|
93
|
+
x.report("Iodine::Mustache - no chaching - render list of 1000") do |times|
|
94
|
+
Iodine::Mustache.render(nil, data_1000, template)
|
95
|
+
end
|
96
|
+
|
125
97
|
end
|
126
98
|
end
|
127
99
|
|
data/ext/iodine/fio.c
CHANGED
@@ -69,6 +69,10 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
69
69
|
#define DEBUG_SPINLOCK 0
|
70
70
|
#endif
|
71
71
|
|
72
|
+
#if !defined(__clang__) && !defined(__GNUC__)
|
73
|
+
#define __thread _Thread_value
|
74
|
+
#endif
|
75
|
+
|
72
76
|
/* *****************************************************************************
|
73
77
|
Patch for OSX version < 10.12 from https://stackoverflow.com/a/9781275/4025095
|
74
78
|
***************************************************************************** */
|
@@ -218,7 +222,13 @@ typedef struct {
|
|
218
222
|
fio_fd_data_s info[];
|
219
223
|
} fio_data_s;
|
220
224
|
|
221
|
-
|
225
|
+
/** The logging level */
|
226
|
+
#if DEBUG
|
227
|
+
size_t FIO_LOG_LEVEL = FIO_LOG_LEVEL_DEBUG;
|
228
|
+
#else
|
229
|
+
size_t FIO_LOG_LEVEL = FIO_LOG_LEVEL_INFO;
|
230
|
+
#endif
|
231
|
+
static fio_data_s *fio_data = NULL;
|
222
232
|
|
223
233
|
/* used for protocol locking by task type. */
|
224
234
|
typedef struct {
|
@@ -294,11 +304,15 @@ static void fio_max_fd_shrink(void) {
|
|
294
304
|
static inline int fio_clear_fd(intptr_t fd, uint8_t is_open) {
|
295
305
|
fio_packet_s *packet;
|
296
306
|
fio_protocol_s *protocol;
|
307
|
+
fio_rw_hook_s *rw_hooks;
|
308
|
+
void *rw_udata;
|
297
309
|
fio_uuid_links_s links;
|
298
310
|
fio_lock(&(fd_data(fd).sock_lock));
|
299
311
|
links = fd_data(fd).links;
|
300
312
|
packet = fd_data(fd).packet;
|
301
313
|
protocol = fd_data(fd).protocol;
|
314
|
+
rw_hooks = fd_data(fd).rw_hooks;
|
315
|
+
rw_udata = fd_data(fd).rw_udata;
|
302
316
|
fd_data(fd) = (fio_fd_data_s){
|
303
317
|
.open = is_open,
|
304
318
|
.sock_lock = fd_data(fd).sock_lock,
|
@@ -308,6 +322,8 @@ static inline int fio_clear_fd(intptr_t fd, uint8_t is_open) {
|
|
308
322
|
.packet_last = &fd_data(fd).packet,
|
309
323
|
};
|
310
324
|
fio_unlock(&(fd_data(fd).sock_lock));
|
325
|
+
if (rw_hooks && rw_hooks->cleanup)
|
326
|
+
rw_hooks->cleanup(rw_udata);
|
311
327
|
while (packet) {
|
312
328
|
fio_packet_s *tmp = packet;
|
313
329
|
packet = packet->next;
|
@@ -319,6 +335,7 @@ static inline int fio_clear_fd(intptr_t fd, uint8_t is_open) {
|
|
319
335
|
pos->obj((void *)pos->hash);
|
320
336
|
}
|
321
337
|
}
|
338
|
+
fio_uuid_links_free(&links);
|
322
339
|
if (protocol && protocol->on_close) {
|
323
340
|
fio_defer(deferred_on_close, (void *)fd2uuid(fd), protocol);
|
324
341
|
}
|
@@ -365,12 +382,10 @@ inline static void protocol_unlock(fio_protocol_s *pr,
|
|
365
382
|
}
|
366
383
|
|
367
384
|
/** returns 1 if the UUID is valid and 0 if it isn't. */
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
return 1;
|
373
|
-
}
|
385
|
+
#define uuid_is_valid(uuid) \
|
386
|
+
((intptr_t)(uuid) != -1 && \
|
387
|
+
((uint32_t)fio_uuid2fd((uuid))) < fio_data->capa && \
|
388
|
+
((uintptr_t)(uuid)&0xFF) == uuid_data((uuid)).counter)
|
374
389
|
|
375
390
|
/* public API. */
|
376
391
|
fio_protocol_s *fio_protocol_try_lock(intptr_t uuid,
|
@@ -516,7 +531,7 @@ typedef struct {
|
|
516
531
|
void (*on_finish)(void *);
|
517
532
|
} fio_timer_s;
|
518
533
|
|
519
|
-
fio_ls_embd_s fio_timers = FIO_LS_INIT(fio_timers);
|
534
|
+
static fio_ls_embd_s fio_timers = FIO_LS_INIT(fio_timers);
|
520
535
|
|
521
536
|
static fio_lock_i fio_timer_lock = FIO_LOCK_INIT;
|
522
537
|
|
@@ -961,8 +976,7 @@ static fio_defer_thread_pool_s *fio_defer_thread_pool_new(size_t count) {
|
|
961
976
|
}
|
962
977
|
return pool;
|
963
978
|
error:
|
964
|
-
|
965
|
-
"attempting shutdown.\n");
|
979
|
+
FIO_LOG_FATAL("couldn't spawn threads for thread pool, attempting shutdown.");
|
966
980
|
fio_stop();
|
967
981
|
fio_defer_thread_pool_join(pool);
|
968
982
|
return NULL;
|
@@ -1209,11 +1223,11 @@ static inline size_t fio_detect_cpu_cores(void) {
|
|
1209
1223
|
#ifdef _SC_NPROCESSORS_ONLN
|
1210
1224
|
cpu_count = sysconf(_SC_NPROCESSORS_ONLN);
|
1211
1225
|
if (cpu_count < 0) {
|
1212
|
-
|
1226
|
+
FIO_LOG_WARNING("CPU core count auto-detection failed.");
|
1213
1227
|
return 0;
|
1214
1228
|
}
|
1215
1229
|
#else
|
1216
|
-
|
1230
|
+
FIO_LOG_WARNING("CPU core count auto-detection failed.");
|
1217
1231
|
#endif
|
1218
1232
|
return cpu_count;
|
1219
1233
|
}
|
@@ -1236,13 +1250,11 @@ void fio_expected_concurrency(int16_t *threads, int16_t *processes) {
|
|
1236
1250
|
if (cpu_count > FIO_CPU_CORES_LIMIT) {
|
1237
1251
|
static int print_cores_warning = 1;
|
1238
1252
|
if (print_cores_warning) {
|
1239
|
-
|
1240
|
-
|
1241
|
-
"INFO: Detected %zu cores. Capping auto-detection of cores "
|
1242
|
-
"to %zu.\n"
|
1253
|
+
FIO_LOG_WARNING(
|
1254
|
+
"Detected %zu cores. Capping auto-detection of cores to %zu.\n"
|
1243
1255
|
" Avoid this message by setting threads / workers manually.\n"
|
1244
1256
|
" To increase auto-detection limit, recompile with:\n"
|
1245
|
-
" -DFIO_CPU_CORES_LIMIT=%zu
|
1257
|
+
" -DFIO_CPU_CORES_LIMIT=%zu",
|
1246
1258
|
(size_t)cpu_count, (size_t)FIO_CPU_CORES_LIMIT, (size_t)cpu_count);
|
1247
1259
|
print_cores_warning = 0;
|
1248
1260
|
}
|
@@ -1500,7 +1512,7 @@ static void fio_poll_init(void) {
|
|
1500
1512
|
fio_poll_close();
|
1501
1513
|
evio_fd = kqueue();
|
1502
1514
|
if (evio_fd == -1) {
|
1503
|
-
|
1515
|
+
FIO_LOG_FATAL("couldn't open kqueue.\n");
|
1504
1516
|
exit(errno);
|
1505
1517
|
}
|
1506
1518
|
}
|
@@ -1580,6 +1592,7 @@ static size_t fio_poll(void) {
|
|
1580
1592
|
// (events[i].flags & EV_EOF)
|
1581
1593
|
// ? "EV_EOF"
|
1582
1594
|
// : (events[i].flags & EV_ERROR) ? "EV_ERROR" : "WTF?");
|
1595
|
+
// uuid_data(events[i].udata).open = 0;
|
1583
1596
|
fio_force_close(fd2uuid(events[i].udata));
|
1584
1597
|
} else if (events[i].filter == EVFILT_WRITE) {
|
1585
1598
|
// we can only write if there's no error in the socket
|
@@ -1715,22 +1728,22 @@ static size_t fio_poll(void) {
|
|
1715
1728
|
touchfd(i);
|
1716
1729
|
++count;
|
1717
1730
|
if (list[i].revents & FIO_POLL_READ_EVENTS) {
|
1718
|
-
//
|
1731
|
+
// FIO_LOG_DEBUG("Poll Read %zu => %p", i, (void *)fd2uuid(i));
|
1719
1732
|
fio_poll_remove_read(i);
|
1720
1733
|
fio_defer(deferred_on_data, (void *)fd2uuid(i), NULL);
|
1721
1734
|
}
|
1722
1735
|
if (list[i].revents & FIO_POLL_WRITE_EVENTS) {
|
1723
|
-
//
|
1736
|
+
// FIO_LOG_DEBUG("Poll Write %zu => %p", i, (void *)fd2uuid(i));
|
1724
1737
|
fio_poll_remove_write(i);
|
1725
1738
|
fio_defer(deferred_on_ready, (void *)fd2uuid(i), NULL);
|
1726
1739
|
}
|
1727
1740
|
if (list[i].revents & (POLLHUP | POLLERR)) {
|
1728
|
-
//
|
1741
|
+
// FIO_LOG_DEBUG("Poll Hangup %zu => %p", i, (void *)fd2uuid(i));
|
1729
1742
|
fio_poll_remove_fd(i);
|
1730
1743
|
fio_force_close(fd2uuid(i));
|
1731
1744
|
}
|
1732
1745
|
if (list[i].revents & POLLNVAL) {
|
1733
|
-
//
|
1746
|
+
// FIO_LOG_DEBUG("Poll Invalid %zu => %p", i, (void *)fd2uuid(i));
|
1734
1747
|
fio_poll_remove_fd(i);
|
1735
1748
|
fio_lock(&fd_data(i).protocol_lock);
|
1736
1749
|
fio_clear_fd(i, 0);
|
@@ -2104,15 +2117,15 @@ static intptr_t fio_unix_socket(const char *address, uint8_t server) {
|
|
2104
2117
|
/* Unix socket */
|
2105
2118
|
if (!address) {
|
2106
2119
|
errno = EINVAL;
|
2107
|
-
|
2108
|
-
|
2109
|
-
|
2120
|
+
FIO_LOG_ERROR(
|
2121
|
+
"(fio) a Unix socket requires a valid address.\n"
|
2122
|
+
" Specify port for TCP/IP socket or change address.");
|
2110
2123
|
return -1;
|
2111
2124
|
}
|
2112
2125
|
struct sockaddr_un addr = {0};
|
2113
2126
|
size_t addr_len = strlen(address);
|
2114
2127
|
if (addr_len >= sizeof(addr.sun_path)) {
|
2115
|
-
|
2128
|
+
FIO_LOG_ERROR("(fio) a Unix socket address too long.");
|
2116
2129
|
errno = ENAMETOOLONG;
|
2117
2130
|
return -1;
|
2118
2131
|
}
|
@@ -2563,7 +2576,7 @@ void fio_force_close(intptr_t uuid) {
|
|
2563
2576
|
errno = EBADF;
|
2564
2577
|
return;
|
2565
2578
|
}
|
2566
|
-
/* clear away any packets in case we want to cut the connection short */
|
2579
|
+
/* clear away any packets in case we want to cut the connection short. */
|
2567
2580
|
fio_packet_s *packet;
|
2568
2581
|
fio_lock(&uuid_data(uuid).sock_lock);
|
2569
2582
|
packet = uuid_data(uuid).packet;
|
@@ -2702,12 +2715,16 @@ static ssize_t fio_hooks_default_flush(intptr_t uuid, void *udata) {
|
|
2702
2715
|
(void)(udata);
|
2703
2716
|
}
|
2704
2717
|
|
2718
|
+
static void fio_hooks_default_cleanup(void *udata) { (void)(udata); }
|
2719
|
+
|
2705
2720
|
const fio_rw_hook_s FIO_DEFAULT_RW_HOOKS = {
|
2706
2721
|
.read = fio_hooks_default_read,
|
2707
2722
|
.write = fio_hooks_default_write,
|
2708
2723
|
.flush = fio_hooks_default_flush,
|
2709
2724
|
.close = fio_hooks_default_close,
|
2725
|
+
.cleanup = fio_hooks_default_cleanup,
|
2710
2726
|
};
|
2727
|
+
|
2711
2728
|
/** Sets a socket hook state (a pointer to the struct). */
|
2712
2729
|
int fio_rw_hook_set(intptr_t uuid, fio_rw_hook_s *rw_hooks, void *udata) {
|
2713
2730
|
if (fio_is_closed(uuid))
|
@@ -2720,11 +2737,19 @@ int fio_rw_hook_set(intptr_t uuid, fio_rw_hook_s *rw_hooks, void *udata) {
|
|
2720
2737
|
rw_hooks->flush = fio_hooks_default_flush;
|
2721
2738
|
if (!rw_hooks->close)
|
2722
2739
|
rw_hooks->close = fio_hooks_default_close;
|
2740
|
+
if (!rw_hooks->cleanup)
|
2741
|
+
rw_hooks->cleanup = fio_hooks_default_cleanup;
|
2723
2742
|
uuid = fio_uuid2fd(uuid);
|
2743
|
+
fio_rw_hook_s *old_rw_hooks;
|
2744
|
+
void *old_udata;
|
2724
2745
|
fio_lock(&fd_data(uuid).sock_lock);
|
2746
|
+
old_rw_hooks = fd_data(uuid).rw_hooks;
|
2747
|
+
old_udata = fd_data(uuid).rw_udata;
|
2725
2748
|
fd_data(uuid).rw_hooks = rw_hooks;
|
2726
2749
|
fd_data(uuid).rw_udata = udata;
|
2727
2750
|
fio_unlock(&fd_data(uuid).sock_lock);
|
2751
|
+
if (old_rw_hooks && old_rw_hooks->cleanup)
|
2752
|
+
old_rw_hooks->cleanup(old_udata);
|
2728
2753
|
return 0;
|
2729
2754
|
}
|
2730
2755
|
|
@@ -2852,6 +2877,10 @@ typedef struct {
|
|
2852
2877
|
|
2853
2878
|
static callback_collection_s callback_collection[FIO_CALL_NEVER + 1];
|
2854
2879
|
|
2880
|
+
static void fio_state_on_idle_perform(void *task, void *arg) {
|
2881
|
+
((void (*)(void *))(uintptr_t)task)(arg);
|
2882
|
+
}
|
2883
|
+
|
2855
2884
|
static inline void fio_state_callback_ensure(callback_collection_s *c) {
|
2856
2885
|
if (c->callbacks.next)
|
2857
2886
|
return;
|
@@ -2905,12 +2934,46 @@ void fio_state_callback_force(callback_type_e c_type) {
|
|
2905
2934
|
fio_ls_embd_s copy = FIO_LS_INIT(copy);
|
2906
2935
|
fio_lock(&callback_collection[c_type].lock);
|
2907
2936
|
fio_state_callback_ensure(&callback_collection[c_type]);
|
2908
|
-
|
2909
|
-
|
2910
|
-
|
2911
|
-
|
2912
|
-
|
2937
|
+
switch (c_type) { /* the difference between `unshift` and `push` */
|
2938
|
+
case FIO_CALL_ON_INITIALIZE: /* overflow */
|
2939
|
+
case FIO_CALL_PRE_START: /* overflow */
|
2940
|
+
case FIO_CALL_BEFORE_FORK: /* overflow */
|
2941
|
+
case FIO_CALL_AFTER_FORK: /* overflow */
|
2942
|
+
case FIO_CALL_IN_CHILD: /* overflow */
|
2943
|
+
case FIO_CALL_IN_MASTER: /* overflow */
|
2944
|
+
case FIO_CALL_ON_START: /* overflow */
|
2945
|
+
FIO_LS_EMBD_FOR(&callback_collection[c_type].callbacks, pos) {
|
2946
|
+
callback_data_s *tmp = fio_malloc(sizeof(*tmp));
|
2947
|
+
FIO_ASSERT_ALLOC(tmp);
|
2948
|
+
*tmp = *(FIO_LS_EMBD_OBJ(callback_data_s, node, pos));
|
2949
|
+
fio_ls_embd_unshift(©, &tmp->node);
|
2950
|
+
}
|
2951
|
+
break;
|
2952
|
+
|
2953
|
+
case FIO_CALL_ON_IDLE: /* idle callbacks are orderless and evented */
|
2954
|
+
FIO_LS_EMBD_FOR(&callback_collection[c_type].callbacks, pos) {
|
2955
|
+
callback_data_s *tmp = FIO_LS_EMBD_OBJ(callback_data_s, node, pos);
|
2956
|
+
fio_defer(fio_state_on_idle_perform, (void *)(uintptr_t)tmp->func,
|
2957
|
+
tmp->arg);
|
2958
|
+
}
|
2959
|
+
break;
|
2960
|
+
|
2961
|
+
case FIO_CALL_ON_SHUTDOWN: /* overflow */
|
2962
|
+
case FIO_CALL_ON_FINISH: /* overflow */
|
2963
|
+
case FIO_CALL_ON_PARENT_CRUSH: /* overflow */
|
2964
|
+
case FIO_CALL_ON_CHILD_CRUSH: /* overflow */
|
2965
|
+
case FIO_CALL_AT_EXIT: /* overflow */
|
2966
|
+
case FIO_CALL_NEVER: /* overflow */
|
2967
|
+
default:
|
2968
|
+
FIO_LS_EMBD_FOR(&callback_collection[c_type].callbacks, pos) {
|
2969
|
+
callback_data_s *tmp = fio_malloc(sizeof(*tmp));
|
2970
|
+
FIO_ASSERT_ALLOC(tmp);
|
2971
|
+
*tmp = *(FIO_LS_EMBD_OBJ(callback_data_s, node, pos));
|
2972
|
+
fio_ls_embd_push(©, &tmp->node);
|
2973
|
+
}
|
2974
|
+
break;
|
2913
2975
|
}
|
2976
|
+
|
2914
2977
|
fio_unlock(&callback_collection[c_type].lock);
|
2915
2978
|
/* run callbacks + free data */
|
2916
2979
|
while (fio_ls_embd_any(©)) {
|
@@ -3004,7 +3067,6 @@ void fio_defer_io_task FIO_IGNORE_MACRO(intptr_t uuid,
|
|
3004
3067
|
Initialize the library
|
3005
3068
|
***************************************************************************** */
|
3006
3069
|
|
3007
|
-
static void fio_malloc_after_fork(void);
|
3008
3070
|
static void fio_pubsub_on_fork(void);
|
3009
3071
|
|
3010
3072
|
static void fio_mem_destroy(void);
|
@@ -3018,10 +3080,8 @@ static void __attribute__((destructor)) fio_lib_destroy(void) {
|
|
3018
3080
|
fio_free(fio_data);
|
3019
3081
|
/* memory library destruction must be last */
|
3020
3082
|
fio_mem_destroy();
|
3021
|
-
|
3022
|
-
|
3023
|
-
getpid());
|
3024
|
-
#endif
|
3083
|
+
FIO_LOG_DEBUG("(%d) facil.io resources released, exit complete.", getpid());
|
3084
|
+
fprintf(stderr, "\n"); /* add EOL to logs (logging adds EOL before text */
|
3025
3085
|
}
|
3026
3086
|
|
3027
3087
|
/* Called within a child process after it starts. */
|
@@ -3071,7 +3131,7 @@ static void __attribute__((constructor)) fio_lib_init(void) {
|
|
3071
3131
|
// try to maximize limits - collect max and set to max
|
3072
3132
|
struct rlimit rlim = {.rlim_max = 0};
|
3073
3133
|
if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) {
|
3074
|
-
|
3134
|
+
FIO_LOG_WARNING("`getrlimit` failed in `sock_max_capacity`.");
|
3075
3135
|
} else {
|
3076
3136
|
// #if defined(__APPLE__) /* Apple's getrlimit is broken. */
|
3077
3137
|
// rlim.rlim_cur = rlim.rlim_max >= FOPEN_MAX ? FOPEN_MAX :
|
@@ -3092,7 +3152,7 @@ static void __attribute__((constructor)) fio_lib_init(void) {
|
|
3092
3152
|
FIO_LOG_STATE("facil.io " FIO_VERSION_STRING " capacity initialization:\n"
|
3093
3153
|
"* Meximum open files %zu out of %zu\n"
|
3094
3154
|
"* Allocating %zu bytes for state handling.\n"
|
3095
|
-
"* %zu bytes per connection + %zu for state handling
|
3155
|
+
"* %zu bytes per connection + %zu for state handling.",
|
3096
3156
|
capa, (size_t)rlim.rlim_max,
|
3097
3157
|
(sizeof(*fio_data) + (capa * (sizeof(*fio_data->poll))) +
|
3098
3158
|
(capa * (sizeof(*fio_data->info)))),
|
@@ -3102,7 +3162,7 @@ static void __attribute__((constructor)) fio_lib_init(void) {
|
|
3102
3162
|
FIO_LOG_STATE("facil.io " FIO_VERSION_STRING " capacity initialization:\n"
|
3103
3163
|
"* Meximum open files %zu out of %zu\n"
|
3104
3164
|
"* Allocating %zu bytes for state handling.\n"
|
3105
|
-
"* %zu bytes per connection + %zu for state handling
|
3165
|
+
"* %zu bytes per connection + %zu for state handling.",
|
3106
3166
|
capa, (size_t)rlim.rlim_max,
|
3107
3167
|
(sizeof(*fio_data) + (capa * (sizeof(*fio_data->info)))),
|
3108
3168
|
(sizeof(*fio_data->info)), sizeof(*fio_data));
|
@@ -3277,7 +3337,7 @@ static void fio_worker_startup(void) {
|
|
3277
3337
|
fio_data->is_worker = 1;
|
3278
3338
|
} else if (fio_data->is_worker) {
|
3279
3339
|
/* Worker Process */
|
3280
|
-
|
3340
|
+
FIO_LOG_INFO("%d is running.", getpid());
|
3281
3341
|
} else {
|
3282
3342
|
/* Root Process should run in single thread mode */
|
3283
3343
|
fio_data->threads = 1;
|
@@ -3298,9 +3358,9 @@ static void fio_worker_startup(void) {
|
|
3298
3358
|
static void fio_worker_cleanup(void) {
|
3299
3359
|
/* switch to winding down */
|
3300
3360
|
if (fio_data->is_worker)
|
3301
|
-
|
3361
|
+
FIO_LOG_INFO("(%d) detected exit signal.", getpid());
|
3302
3362
|
else
|
3303
|
-
|
3363
|
+
FIO_LOG_INFO("Server Detected exit signal.");
|
3304
3364
|
fio_state_callback_force(FIO_CALL_ON_SHUTDOWN);
|
3305
3365
|
for (size_t i = 0; i <= fio_data->max_protocol_fd; ++i) {
|
3306
3366
|
if (fd_data(i).protocol) {
|
@@ -3325,9 +3385,9 @@ static void fio_worker_cleanup(void) {
|
|
3325
3385
|
fio_defer_perform();
|
3326
3386
|
fio_signal_handler_reset();
|
3327
3387
|
if (fio_data->parent == getpid()) {
|
3328
|
-
|
3388
|
+
FIO_LOG_INFO(" --- Shutdown Complete ---\n");
|
3329
3389
|
} else {
|
3330
|
-
|
3390
|
+
FIO_LOG_INFO("(%d) cleanup complete.", getpid());
|
3331
3391
|
}
|
3332
3392
|
}
|
3333
3393
|
|
@@ -3338,7 +3398,8 @@ static void *fio_sentinel_worker_thread(void *arg) {
|
|
3338
3398
|
/* release fork lock. */
|
3339
3399
|
fio_unlock(&fio_fork_lock);
|
3340
3400
|
if (child == -1) {
|
3341
|
-
|
3401
|
+
FIO_LOG_FATAL("couldn't spawn worker.");
|
3402
|
+
perror("\n errno");
|
3342
3403
|
kill(fio_parent_pid(), SIGINT);
|
3343
3404
|
fio_stop();
|
3344
3405
|
return NULL;
|
@@ -3348,17 +3409,10 @@ static void *fio_sentinel_worker_thread(void *arg) {
|
|
3348
3409
|
#if DEBUG
|
3349
3410
|
if (fio_data->active) { /* !WIFEXITED(status) || WEXITSTATUS(status) */
|
3350
3411
|
if (!WIFEXITED(status) || WEXITSTATUS(status)) {
|
3351
|
-
|
3352
|
-
"FATAL ERROR: Child worker (%d) crashed. Stopping services in "
|
3353
|
-
"DEBUG mode.\n",
|
3354
|
-
child);
|
3412
|
+
FIO_LOG_FATAL("Child worker (%d) crashed. Stopping services.", child);
|
3355
3413
|
fio_state_callback_force(FIO_CALL_ON_CHILD_CRUSH);
|
3356
3414
|
} else {
|
3357
|
-
|
3358
|
-
stderr,
|
3359
|
-
"INFO (FATAL): Child worker (%d) shutdown. Stopping services in "
|
3360
|
-
"DEBUG mode.\n",
|
3361
|
-
child);
|
3415
|
+
FIO_LOG_FATAL("Child worker (%d) shutdown. Stopping services.", child);
|
3362
3416
|
}
|
3363
3417
|
kill(0, SIGINT);
|
3364
3418
|
}
|
@@ -3367,13 +3421,11 @@ static void *fio_sentinel_worker_thread(void *arg) {
|
|
3367
3421
|
/* don't call any functions while forking. */
|
3368
3422
|
fio_lock(&fio_fork_lock);
|
3369
3423
|
if (!WIFEXITED(status) || WEXITSTATUS(status)) {
|
3370
|
-
|
3371
|
-
"ERROR: Child worker (%d) crashed. Respawning worker.\n",
|
3372
|
-
child);
|
3424
|
+
FIO_LOG_ERROR("Child worker (%d) crashed. Respawning worker.", child);
|
3373
3425
|
fio_state_callback_force(FIO_CALL_ON_CHILD_CRUSH);
|
3374
3426
|
} else {
|
3375
|
-
|
3376
|
-
|
3427
|
+
FIO_LOG_WARNING("Child worker (%d) shutdown. Respawning worker.",
|
3428
|
+
child);
|
3377
3429
|
}
|
3378
3430
|
fio_defer(fio_sentinel_task, NULL, NULL);
|
3379
3431
|
fio_unlock(&fio_fork_lock);
|
@@ -3402,6 +3454,7 @@ static void fio_sentinel_task(void *arg1, void *arg2) {
|
|
3402
3454
|
fio_lock(&fio_fork_lock); /* will wait for worker thread to release lock. */
|
3403
3455
|
fio_unlock(&fio_fork_lock); /* release lock for next fork. */
|
3404
3456
|
fio_state_callback_force(FIO_CALL_AFTER_FORK);
|
3457
|
+
fio_state_callback_force(FIO_CALL_IN_MASTER);
|
3405
3458
|
(void)arg1;
|
3406
3459
|
(void)arg2;
|
3407
3460
|
}
|
@@ -3846,10 +3899,10 @@ static void fio_listen_on_startup(void *pr_) {
|
|
3846
3899
|
fio_listen_protocol_s *pr = pr_;
|
3847
3900
|
fio_attach(pr->uuid, &pr->pr);
|
3848
3901
|
if (pr->port_len)
|
3849
|
-
|
3902
|
+
FIO_LOG_INFO("(%d) started listening on port %s", getpid(), pr->port);
|
3850
3903
|
else
|
3851
|
-
|
3852
|
-
|
3904
|
+
FIO_LOG_INFO("(%d) started listening on Unix Socket at %s", getpid(),
|
3905
|
+
pr->addr);
|
3853
3906
|
}
|
3854
3907
|
|
3855
3908
|
static void fio_listen_on_close(intptr_t uuid, fio_protocol_s *pr_) {
|
@@ -3867,6 +3920,8 @@ static void fio_listen_on_data(intptr_t uuid, fio_protocol_s *pr_) {
|
|
3867
3920
|
}
|
3868
3921
|
}
|
3869
3922
|
|
3923
|
+
/* stub for editor - unused */
|
3924
|
+
void fio_listen____(void);
|
3870
3925
|
/**
|
3871
3926
|
* Schedule a network service on a listening socket.
|
3872
3927
|
*
|
@@ -3922,9 +3977,9 @@ intptr_t fio_listen FIO_IGNORE_MACRO(struct fio_listen_args args) {
|
|
3922
3977
|
}
|
3923
3978
|
|
3924
3979
|
if (args.port)
|
3925
|
-
|
3980
|
+
FIO_LOG_INFO("Listening on port %s", args.port);
|
3926
3981
|
else
|
3927
|
-
|
3982
|
+
FIO_LOG_INFO("Listening on Unix Socket at %s", args.address);
|
3928
3983
|
|
3929
3984
|
return uuid;
|
3930
3985
|
error:
|
@@ -4160,7 +4215,7 @@ struct fio_collection_s {
|
|
4160
4215
|
#define COLLECTION_INIT \
|
4161
4216
|
{ .channels = FIO_SET_INIT, .lock = FIO_LOCK_INIT }
|
4162
4217
|
|
4163
|
-
struct {
|
4218
|
+
static struct {
|
4164
4219
|
fio_collection_s filters;
|
4165
4220
|
fio_collection_s pubsub;
|
4166
4221
|
fio_collection_s patterns;
|
@@ -4281,7 +4336,7 @@ static channel_s *fio_channel_dup_lock(fio_str_info_s name) {
|
|
4281
4336
|
.lock = FIO_LOCK_INIT,
|
4282
4337
|
};
|
4283
4338
|
fio_str_write(&ch->id, name.data, name.len);
|
4284
|
-
|
4339
|
+
fio_str_freeze(&ch->id);
|
4285
4340
|
uint64_t hashed_name = fio_str_hash(&ch->id);
|
4286
4341
|
ch = fio_filter_dup_lock_internal(ch, hashed_name, &fio_postoffice.pubsub);
|
4287
4342
|
if (fio_ls_embd_is_empty(&ch->subscriptions)) {
|
@@ -4331,7 +4386,7 @@ static inline void fio_subscription_free(subscription_s *s) {
|
|
4331
4386
|
/** Subscribes to a filter, pub/sub channle or patten */
|
4332
4387
|
subscription_s *fio_subscribe FIO_IGNORE_MACRO(subscribe_args_s args) {
|
4333
4388
|
if (!args.on_message)
|
4334
|
-
|
4389
|
+
goto error;
|
4335
4390
|
channel_s *ch;
|
4336
4391
|
subscription_s *s = fio_malloc(sizeof(*s));
|
4337
4392
|
FIO_ASSERT_ALLOC(s);
|
@@ -4354,6 +4409,10 @@ subscription_s *fio_subscribe FIO_IGNORE_MACRO(subscribe_args_s args) {
|
|
4354
4409
|
fio_ls_embd_push(&ch->subscriptions, &s->node);
|
4355
4410
|
fio_unlock((&ch->lock));
|
4356
4411
|
return s;
|
4412
|
+
error:
|
4413
|
+
if (args.on_unsubscribe)
|
4414
|
+
args.on_unsubscribe(args.udata1, args.udata2);
|
4415
|
+
return NULL;
|
4357
4416
|
}
|
4358
4417
|
|
4359
4418
|
/** Unsubscribes from a filter, pub/sub channle or patten */
|
@@ -4375,6 +4434,7 @@ void fio_unsubscribe(subscription_s *s) {
|
|
4375
4434
|
if (c == &fio_postoffice.patterns) {
|
4376
4435
|
pattern_s *pat = (pattern_s *)ch;
|
4377
4436
|
hashed ^= ((uintptr_t)pat->match);
|
4437
|
+
match = ((pattern_s *)(ch))->match;
|
4378
4438
|
}
|
4379
4439
|
/* lock collection */
|
4380
4440
|
fio_lock(&c->lock);
|
@@ -4387,9 +4447,6 @@ void fio_unsubscribe(subscription_s *s) {
|
|
4387
4447
|
}
|
4388
4448
|
fio_unlock(&ch->lock);
|
4389
4449
|
if (removed) {
|
4390
|
-
if (ch->parent == &fio_postoffice.patterns) {
|
4391
|
-
match = ((pattern_s *)(ch))->match;
|
4392
|
-
}
|
4393
4450
|
pubsub_on_channel_destroy(ch, match);
|
4394
4451
|
}
|
4395
4452
|
|
@@ -4678,9 +4735,6 @@ static void fio_perform_subscription_callback(void *s_, void *msg_) {
|
|
4678
4735
|
|
4679
4736
|
/** UNSAFE! publishes a message to a channel, managing the reference counts */
|
4680
4737
|
static void fio_publish2channel(channel_s *ch, fio_msg_internal_s *msg) {
|
4681
|
-
if (!ch || !msg) {
|
4682
|
-
return;
|
4683
|
-
}
|
4684
4738
|
FIO_LS_EMBD_FOR(&ch->subscriptions, pos) {
|
4685
4739
|
subscription_s *s = FIO_LS_EMBD_OBJ(subscription_s, node, pos);
|
4686
4740
|
if (!s) {
|
@@ -4694,12 +4748,18 @@ static void fio_publish2channel(channel_s *ch, fio_msg_internal_s *msg) {
|
|
4694
4748
|
}
|
4695
4749
|
static void fio_publish2channel_task(void *ch_, void *msg) {
|
4696
4750
|
channel_s *ch = ch_;
|
4751
|
+
if (!ch_)
|
4752
|
+
return;
|
4753
|
+
if (!msg)
|
4754
|
+
goto finish;
|
4697
4755
|
if (fio_trylock(&ch->lock)) {
|
4698
4756
|
fio_defer(fio_publish2channel_task, ch, msg);
|
4699
4757
|
return;
|
4700
4758
|
}
|
4701
4759
|
fio_publish2channel(ch, msg);
|
4702
4760
|
fio_unlock(&ch->lock);
|
4761
|
+
finish:
|
4762
|
+
fio_str_free(&ch->id);
|
4703
4763
|
}
|
4704
4764
|
|
4705
4765
|
/** Publishes the message to the current process and frees the strings. */
|
@@ -4718,7 +4778,8 @@ static void fio_publish2process(fio_msg_internal_s *m) {
|
|
4718
4778
|
}
|
4719
4779
|
/* exact match */
|
4720
4780
|
if (ch) {
|
4721
|
-
fio_defer(fio_publish2channel_task, ch,
|
4781
|
+
fio_defer(fio_publish2channel_task, fio_str_dup(&ch->id),
|
4782
|
+
fio_msg_internal_dup(m));
|
4722
4783
|
}
|
4723
4784
|
if (m->filter == 0) {
|
4724
4785
|
/* pattern matching match */
|
@@ -4729,7 +4790,7 @@ static void fio_publish2process(fio_msg_internal_s *m) {
|
|
4729
4790
|
}
|
4730
4791
|
pattern_s *pattern = (pattern_s *)p->obj;
|
4731
4792
|
if (pattern->match(fio_str_info(&pattern->ch.id), m->channel)) {
|
4732
|
-
fio_defer(fio_publish2channel_task, &pattern->ch,
|
4793
|
+
fio_defer(fio_publish2channel_task, fio_str_dup(&pattern->ch.id),
|
4733
4794
|
fio_msg_internal_dup(m));
|
4734
4795
|
}
|
4735
4796
|
}
|
@@ -4750,6 +4811,7 @@ static void fio_publish2process(fio_msg_internal_s *m) {
|
|
4750
4811
|
#define FIO_SET_KEY_COPY(k1, k2) \
|
4751
4812
|
(k1) = FIO_STR_INIT; \
|
4752
4813
|
fio_str_concat(&(k1), &(k2))
|
4814
|
+
#define FIO_SET_KEY_COMPARE(k1, k2) fio_str_iseq(&(k1), &(k2))
|
4753
4815
|
#define FIO_SET_KEY_DESTROY(key) fio_str_free(&(key))
|
4754
4816
|
#define FIO_SET_OBJ_DESTROY(obj) fio_unsubscribe(obj)
|
4755
4817
|
#include <fio.h>
|
@@ -4771,7 +4833,7 @@ typedef struct cluster_pr_s {
|
|
4771
4833
|
uint8_t buffer[CLUSTER_READ_BUFFER];
|
4772
4834
|
} cluster_pr_s;
|
4773
4835
|
|
4774
|
-
struct cluster_data_s {
|
4836
|
+
static struct cluster_data_s {
|
4775
4837
|
intptr_t uuid;
|
4776
4838
|
fio_ls_s clients;
|
4777
4839
|
fio_lock_i lock;
|
@@ -4782,7 +4844,7 @@ struct cluster_data_s {
|
|
4782
4844
|
static void fio_cluster_data_cleanup(int delete_file) {
|
4783
4845
|
if (delete_file && cluster_data.name[0]) {
|
4784
4846
|
#if DEBUG
|
4785
|
-
|
4847
|
+
FIO_LOG_DEBUG("(%d) unlinking cluster's Unix socket.", getpid());
|
4786
4848
|
#endif
|
4787
4849
|
unlink(cluster_data.name);
|
4788
4850
|
}
|
@@ -4896,20 +4958,16 @@ static void fio_cluster_on_data(intptr_t uuid, fio_protocol_s *pr_) {
|
|
4896
4958
|
c->filter = (int32_t)fio_str2u32(c->buffer + i + 12);
|
4897
4959
|
if (c->exp_channel) {
|
4898
4960
|
if (c->exp_channel >= (1024 * 1024 * 16)) {
|
4899
|
-
|
4900
|
-
|
4901
|
-
"limit): %u\n",
|
4902
|
-
getpid(), (unsigned int)c->exp_channel);
|
4961
|
+
FIO_LOG_FATAL("(%d) cluster message name too long (16Mb limit): %u\n",
|
4962
|
+
getpid(), (unsigned int)c->exp_channel);
|
4903
4963
|
exit(1);
|
4904
4964
|
return;
|
4905
4965
|
}
|
4906
4966
|
}
|
4907
4967
|
if (c->exp_msg) {
|
4908
4968
|
if (c->exp_msg >= (1024 * 1024 * 64)) {
|
4909
|
-
|
4910
|
-
|
4911
|
-
"limit): %u\n",
|
4912
|
-
getpid(), (unsigned int)c->exp_msg);
|
4969
|
+
FIO_LOG_FATAL("(%d) cluster message data too long (64Mb limit): %u\n",
|
4970
|
+
getpid(), (unsigned int)c->exp_msg);
|
4913
4971
|
exit(1);
|
4914
4972
|
return;
|
4915
4973
|
}
|
@@ -4988,8 +5046,7 @@ static void fio_cluster_on_close(intptr_t uuid, fio_protocol_s *pr_) {
|
|
4988
5046
|
} else if (fio_data->active) {
|
4989
5047
|
/* no shutdown message received - parent crashed. */
|
4990
5048
|
if (c->type != FIO_CLUSTER_MSG_SHUTDOWN && fio_is_running()) {
|
4991
|
-
|
4992
|
-
getpid());
|
5049
|
+
FIO_LOG_FATAL("(%d) Parent Process crash detected!", getpid());
|
4993
5050
|
fio_state_callback_force(FIO_CALL_ON_PARENT_CRUSH);
|
4994
5051
|
fio_state_callback_clear(FIO_CALL_ON_PARENT_CRUSH);
|
4995
5052
|
fio_cluster_data_cleanup(1);
|
@@ -5009,7 +5066,7 @@ fio_cluster_protocol_alloc(intptr_t uuid,
|
|
5009
5066
|
void (*sender)(fio_str_s *data, intptr_t auuid)) {
|
5010
5067
|
cluster_pr_s *p = fio_mmap(sizeof(*p));
|
5011
5068
|
if (!p) {
|
5012
|
-
|
5069
|
+
FIO_LOG_FATAL("Cluster protocol allocation failed.");
|
5013
5070
|
exit(errno);
|
5014
5071
|
}
|
5015
5072
|
p->protocol = (fio_protocol_s){
|
@@ -5142,8 +5199,7 @@ static void fio_cluster_listen_on_close(intptr_t uuid,
|
|
5142
5199
|
cluster_data.uuid = -1;
|
5143
5200
|
if (fio_parent_pid() == getpid()) {
|
5144
5201
|
#if DEBUG
|
5145
|
-
|
5146
|
-
getpid());
|
5202
|
+
FIO_LOG_DEBUG("(%d) stopped listening for cluster connections", getpid());
|
5147
5203
|
#endif
|
5148
5204
|
if (fio_data->active)
|
5149
5205
|
kill(0, SIGINT);
|
@@ -5158,8 +5214,8 @@ static void fio_listen2cluster(void *ignore) {
|
|
5158
5214
|
cluster_data.uuid = fio_socket(cluster_data.name, NULL, 1);
|
5159
5215
|
fio_unlock(&cluster_data.lock);
|
5160
5216
|
if (cluster_data.uuid < 0) {
|
5161
|
-
|
5162
|
-
|
5217
|
+
FIO_LOG_FATAL("(facil.io cluster) failed to open cluster socket.");
|
5218
|
+
perror(" check file permissions. errno:");
|
5163
5219
|
exit(errno);
|
5164
5220
|
}
|
5165
5221
|
fio_protocol_s *p = malloc(sizeof(*p));
|
@@ -5171,8 +5227,7 @@ static void fio_listen2cluster(void *ignore) {
|
|
5171
5227
|
.on_close = fio_cluster_listen_on_close,
|
5172
5228
|
};
|
5173
5229
|
#if DEBUG
|
5174
|
-
|
5175
|
-
cluster_data.name);
|
5230
|
+
FIO_LOG_DEBUG("(%d) Listening to cluster: %s", getpid(), cluster_data.name);
|
5176
5231
|
#endif
|
5177
5232
|
fio_attach(cluster_data.uuid, p);
|
5178
5233
|
(void)ignore;
|
@@ -5226,7 +5281,7 @@ static void fio_cluster_client_sender(fio_str_s *data, intptr_t ignr_) {
|
|
5226
5281
|
*
|
5227
5282
|
* Should either call `facil_attach` or close the connection.
|
5228
5283
|
*/
|
5229
|
-
void fio_cluster_on_connect(intptr_t uuid, void *udata) {
|
5284
|
+
static void fio_cluster_on_connect(intptr_t uuid, void *udata) {
|
5230
5285
|
cluster_data.uuid = uuid;
|
5231
5286
|
|
5232
5287
|
/* inform root about all existing channels */
|
@@ -5256,8 +5311,9 @@ void fio_cluster_on_connect(intptr_t uuid, void *udata) {
|
|
5256
5311
|
* The `on_fail` is called when a socket fails to connect. The old sock UUID
|
5257
5312
|
* is passed along.
|
5258
5313
|
*/
|
5259
|
-
void fio_cluster_on_fail(intptr_t uuid, void *udata) {
|
5260
|
-
|
5314
|
+
static void fio_cluster_on_fail(intptr_t uuid, void *udata) {
|
5315
|
+
FIO_LOG_FATAL("(facil.io) unknown cluster connection error");
|
5316
|
+
perror(" errno");
|
5261
5317
|
kill(fio_parent_pid(), SIGINT);
|
5262
5318
|
fio_stop();
|
5263
5319
|
// exit(errno ? errno : 1);
|
@@ -5276,7 +5332,7 @@ static void fio_connect2cluster(void *ignore) {
|
|
5276
5332
|
static void fio_send2cluster(int32_t filter, fio_str_info_s ch,
|
5277
5333
|
fio_str_info_s msg, uint8_t is_json) {
|
5278
5334
|
if (!fio_is_running()) {
|
5279
|
-
|
5335
|
+
FIO_LOG_ERROR("facio.io cluster inactive, can't send message.");
|
5280
5336
|
return;
|
5281
5337
|
}
|
5282
5338
|
if (fio_data->workers == 1) {
|
@@ -5313,7 +5369,7 @@ static inline void fio_cluster_inform_root_about_channel(channel_s *ch,
|
|
5313
5369
|
fio_str_info_s ch_name = fio_str_info(&ch->id);
|
5314
5370
|
fio_str_info_s msg = {.data = NULL, .len = 0};
|
5315
5371
|
#if DEBUG
|
5316
|
-
|
5372
|
+
FIO_LOG_DEBUG("(%d) informing root about: %s (%zu) msg type %d", getpid(),
|
5317
5373
|
ch_name.data, ch_name.len,
|
5318
5374
|
(match ? (add ? FIO_CLUSTER_MSG_PATTERN_SUB
|
5319
5375
|
: FIO_CLUSTER_MSG_PATTERN_UNSUB)
|
@@ -5494,8 +5550,8 @@ void fio_publish FIO_IGNORE_MACRO(fio_publish_args_s args) {
|
|
5494
5550
|
break;
|
5495
5551
|
default:
|
5496
5552
|
if (args.filter != 0) {
|
5497
|
-
|
5498
|
-
|
5553
|
+
FIO_LOG_ERROR("(pub/sub) pub/sub engines can only be used for "
|
5554
|
+
"pub/sub messages (no filter).");
|
5499
5555
|
return;
|
5500
5556
|
}
|
5501
5557
|
args.engine->publish(args.engine, args.channel, args.message, args.is_json);
|
@@ -5663,57 +5719,32 @@ Section Start Marker
|
|
5663
5719
|
|
5664
5720
|
***************************************************************************** */
|
5665
5721
|
|
5666
|
-
/* *****************************************************************************
|
5667
|
-
If FIO_FORCE_MALLOC is set, use glibc / library malloc
|
5668
|
-
***************************************************************************** */
|
5669
5722
|
#if FIO_FORCE_MALLOC
|
5670
|
-
|
5671
|
-
void
|
5672
|
-
|
5673
|
-
void *fio_calloc(size_t size, size_t count) { return calloc(size, count); }
|
5674
|
-
|
5675
|
-
void fio_free(void *ptr) { free(ptr); }
|
5676
|
-
|
5677
|
-
void *fio_realloc(void *ptr, size_t new_size) { return realloc(ptr, new_size); }
|
5678
|
-
void *fio_realloc2(void *ptr, size_t new_size, size_t valid_len) {
|
5679
|
-
return realloc(ptr, new_size);
|
5680
|
-
(void)valid_len;
|
5681
|
-
}
|
5682
|
-
/** Clears any memory locks, in case of a system call to `fork`. */
|
5683
|
-
static void fio_malloc_after_fork(void) {}
|
5723
|
+
void fio_mem_destroy(void) {}
|
5724
|
+
void fio_mem_init(void) {}
|
5684
5725
|
|
5685
5726
|
#else
|
5686
|
-
/* *****************************************************************************
|
5687
|
-
facil.io malloc implementation
|
5688
|
-
***************************************************************************** */
|
5689
|
-
|
5690
|
-
#if !defined(__clang__) && !defined(__GNUC__)
|
5691
|
-
#define __thread _Thread_value
|
5692
|
-
#endif
|
5693
|
-
|
5694
|
-
#undef malloc
|
5695
|
-
#undef calloc
|
5696
|
-
#undef free
|
5697
|
-
#undef realloc
|
5698
5727
|
|
5699
5728
|
/* *****************************************************************************
|
5700
5729
|
Memory Copying by 16 byte units
|
5701
5730
|
***************************************************************************** */
|
5702
5731
|
|
5732
|
+
static inline void fio_memcpy(void *__restrict dest_, void *__restrict src_,
|
5733
|
+
size_t units) {
|
5703
5734
|
#if __SIZEOF_INT128__ == 9 /* a 128bit type exists... but tests favor 64bit */
|
5704
|
-
|
5705
|
-
|
5735
|
+
register __uint128_t *dest = dest_;
|
5736
|
+
register __uint128_t *src = src_;
|
5706
5737
|
#elif SIZE_MAX == 0xFFFFFFFFFFFFFFFF /* 64 bit size_t */
|
5707
|
-
|
5708
|
-
|
5738
|
+
register size_t *dest = dest_;
|
5739
|
+
register size_t *src = src_;
|
5709
5740
|
units = units << 1;
|
5710
5741
|
#elif SIZE_MAX == 0xFFFFFFFF /* 32 bit size_t */
|
5711
|
-
|
5712
|
-
|
5742
|
+
register size_t *dest = dest_;
|
5743
|
+
register size_t *src = src_;
|
5713
5744
|
units = units << 2;
|
5714
5745
|
#else /* unknow... assume 16 bit? */
|
5715
|
-
|
5716
|
-
|
5746
|
+
register size_t *dest = dest_;
|
5747
|
+
register size_t *src = src_;
|
5717
5748
|
units = units << 3;
|
5718
5749
|
#endif
|
5719
5750
|
while (units >= 16) { /* unroll loop */
|
@@ -5926,7 +5957,7 @@ static void arena_enter(void) { arena_last_used = arena_lock(arena_last_used); }
|
|
5926
5957
|
static inline void arena_exit(void) { fio_unlock(&arena_last_used->lock); }
|
5927
5958
|
|
5928
5959
|
/** Clears any memory locks, in case of a system call to `fork`. */
|
5929
|
-
|
5960
|
+
void fio_malloc_after_fork(void) {
|
5930
5961
|
arena_last_used = NULL;
|
5931
5962
|
if (!arenas) {
|
5932
5963
|
return;
|
@@ -5972,7 +6003,7 @@ static inline void block_free(block_s *blk) {
|
|
5972
6003
|
}
|
5973
6004
|
memset(blk, 0, FIO_MEMORY_BLOCK_SIZE);
|
5974
6005
|
fio_lock(&memory.lock);
|
5975
|
-
|
6006
|
+
((block_s **)blk)[0] = memory.available;
|
5976
6007
|
memory.available = (block_s *)blk;
|
5977
6008
|
fio_unlock(&memory.lock);
|
5978
6009
|
}
|
@@ -5983,13 +6014,15 @@ static inline block_s *block_new(void) {
|
|
5983
6014
|
|
5984
6015
|
if (memory.available) {
|
5985
6016
|
fio_lock(&memory.lock);
|
5986
|
-
blk =
|
6017
|
+
blk = memory.available;
|
5987
6018
|
if (blk) {
|
5988
6019
|
memory.available = ((block_s **)blk)[0];
|
5989
6020
|
}
|
5990
6021
|
fio_unlock(&memory.lock);
|
5991
6022
|
}
|
5992
6023
|
if (blk) {
|
6024
|
+
FIO_ASSERT(((uintptr_t)blk & FIO_MEMORY_BLOCK_MASK) == 0,
|
6025
|
+
"Memory allocator error! double `fio_free`?\n");
|
5993
6026
|
fio_atomic_sub(&memory.count, 1);
|
5994
6027
|
((block_s **)blk)[0] = NULL;
|
5995
6028
|
((block_s **)blk)[1] = NULL;
|
@@ -6003,6 +6036,7 @@ static inline block_s *block_new(void) {
|
|
6003
6036
|
;
|
6004
6037
|
}
|
6005
6038
|
|
6039
|
+
/* allocates memory from within a block - called within an arena's lock */
|
6006
6040
|
static inline void *block_slice(uint16_t units) {
|
6007
6041
|
block_s *blk = arena_last_used->block;
|
6008
6042
|
if (!blk) {
|
@@ -6025,7 +6059,6 @@ static inline void *block_slice(uint16_t units) {
|
|
6025
6059
|
fio_atomic_add(&blk->ref, 1);
|
6026
6060
|
blk->pos += units;
|
6027
6061
|
if (blk->pos >= blk->max) {
|
6028
|
-
/* it's true that a 16 bytes slice remains, but statistically... */
|
6029
6062
|
/* ... the block was fully utilized, clear arena */
|
6030
6063
|
block_free(blk);
|
6031
6064
|
arena_last_used->block = NULL;
|
@@ -6033,6 +6066,7 @@ static inline void *block_slice(uint16_t units) {
|
|
6033
6066
|
return (void *)mem;
|
6034
6067
|
}
|
6035
6068
|
|
6069
|
+
/* handle's a bock's reference count - called without a lock */
|
6036
6070
|
static inline void block_slice_free(void *mem) {
|
6037
6071
|
/* locate block boundary */
|
6038
6072
|
block_s *blk = (block_s *)((uintptr_t)mem & (~FIO_MEMORY_BLOCK_MASK));
|
@@ -6043,6 +6077,7 @@ static inline void block_slice_free(void *mem) {
|
|
6043
6077
|
Non-Block allocations (direct from the system)
|
6044
6078
|
***************************************************************************** */
|
6045
6079
|
|
6080
|
+
/* allocates directly from the system adding size header - no lock required. */
|
6046
6081
|
static inline void *big_alloc(size_t size) {
|
6047
6082
|
size = sys_round_size(size + 16);
|
6048
6083
|
size_t *mem = sys_alloc(size, 1);
|
@@ -6054,11 +6089,13 @@ error:
|
|
6054
6089
|
return NULL;
|
6055
6090
|
}
|
6056
6091
|
|
6092
|
+
/* reads size header and frees memory back to the system */
|
6057
6093
|
static inline void big_free(void *ptr) {
|
6058
6094
|
size_t *mem = (void *)(((uintptr_t)ptr) - 16);
|
6059
6095
|
sys_free(mem, *mem);
|
6060
6096
|
}
|
6061
6097
|
|
6098
|
+
/* reallocates memory using the system, resetting the size header */
|
6062
6099
|
static inline void *big_realloc(void *ptr, size_t new_size) {
|
6063
6100
|
size_t *mem = (void *)(((uintptr_t)ptr) - 16);
|
6064
6101
|
new_size = sys_round_size(new_size + 16);
|
@@ -6088,10 +6125,7 @@ static void fio_mem_init(void) {
|
|
6088
6125
|
memory.cores = cpu_count;
|
6089
6126
|
memory.count = 0 - (intptr_t)cpu_count;
|
6090
6127
|
arenas = big_alloc(sizeof(*arenas) * cpu_count);
|
6091
|
-
|
6092
|
-
perror("FATAL ERROR: Couldn't initialize memory allocator");
|
6093
|
-
exit(errno);
|
6094
|
-
}
|
6128
|
+
FIO_ASSERT_ALLOC(arenas);
|
6095
6129
|
size_t pre_pool = cpu_count > 32 ? 32 : cpu_count;
|
6096
6130
|
for (size_t i = 0; i < pre_pool; ++i) {
|
6097
6131
|
void *block = sys_alloc(FIO_MEMORY_BLOCK_SIZE, 0);
|
@@ -6107,16 +6141,14 @@ static void fio_mem_destroy(void) {
|
|
6107
6141
|
if (!arenas)
|
6108
6142
|
return;
|
6109
6143
|
|
6110
|
-
arena_s *arena = arenas;
|
6111
6144
|
for (size_t i = 0; i < memory.cores; ++i) {
|
6112
|
-
if (
|
6113
|
-
block_free(
|
6114
|
-
|
6115
|
-
++arena;
|
6145
|
+
if (arenas[i].block)
|
6146
|
+
block_free(arenas[i].block);
|
6147
|
+
arenas[i].block = NULL;
|
6116
6148
|
}
|
6117
6149
|
while (memory.available) {
|
6118
6150
|
block_s *b = memory.available;
|
6119
|
-
memory.available =
|
6151
|
+
memory.available = ((block_s **)b)[0];
|
6120
6152
|
sys_free(b, FIO_MEMORY_BLOCK_SIZE);
|
6121
6153
|
}
|
6122
6154
|
big_free(arenas);
|
@@ -6980,7 +7012,7 @@ fio_sha2_s fio_sha2_init(fio_sha2_variant_e variant) {
|
|
6980
7012
|
.digest.i64[7] = 0x0eb72ddc81c52ca2,
|
6981
7013
|
};
|
6982
7014
|
}
|
6983
|
-
|
7015
|
+
FIO_LOG_FATAL("SHA-2 ERROR - variant unknown");
|
6984
7016
|
exit(2);
|
6985
7017
|
}
|
6986
7018
|
|
@@ -7609,6 +7641,15 @@ Testing Strings
|
|
7609
7641
|
#define fio_str_test()
|
7610
7642
|
#else
|
7611
7643
|
|
7644
|
+
static int fio_str_test_dealloc_counter = 0;
|
7645
|
+
|
7646
|
+
FIO_FUNC void fio_str_test_dealloc(void *s) {
|
7647
|
+
FIO_ASSERT(!fio_str_test_dealloc_counter,
|
7648
|
+
"fio_str_s reference count error!\n");
|
7649
|
+
fio_free(s);
|
7650
|
+
fprintf(stderr, "* reference counting `fio_str_free2` pass.\n");
|
7651
|
+
}
|
7652
|
+
|
7612
7653
|
/**
|
7613
7654
|
* Tests the fio_str functionality.
|
7614
7655
|
*/
|
@@ -7764,12 +7805,16 @@ FIO_FUNC inline void fio_str_test(void) {
|
|
7764
7805
|
"`fio_str_new2` error, string not initialized (%p)!", (void *)s);
|
7765
7806
|
fio_str_s *s2 = fio_str_dup(s);
|
7766
7807
|
|
7808
|
+
++fio_str_test_dealloc_counter;
|
7809
|
+
|
7767
7810
|
FIO_ASSERT(s2 == s, "`fio_str_dup` error, should return self!");
|
7768
7811
|
FIO_ASSERT(s->ref == 1,
|
7769
7812
|
"`fio_str_dup` error, reference counter not incremented!");
|
7770
7813
|
|
7771
7814
|
fprintf(stderr, "* reading a file.\n");
|
7772
7815
|
fio_str_info_s state = fio_str_readfile(s, __FILE__, 0, 0);
|
7816
|
+
if (!s->small) /* attach deallocation test */
|
7817
|
+
s->dealloc = fio_str_test_dealloc;
|
7773
7818
|
|
7774
7819
|
FIO_ASSERT(state.data,
|
7775
7820
|
"`fio_str_readfile` error, no data was read for file %s!",
|
@@ -7793,6 +7838,7 @@ FIO_FUNC inline void fio_str_test(void) {
|
|
7793
7838
|
|
7794
7839
|
fprintf(stderr, "* reviewing reference counting `fio_str_free2` (1/2).\n");
|
7795
7840
|
fio_str_free2(s2);
|
7841
|
+
--fio_str_test_dealloc_counter;
|
7796
7842
|
FIO_ASSERT(s->ref == 0,
|
7797
7843
|
"`fio_str_free2` error, reference counter not subtracted!");
|
7798
7844
|
FIO_ASSERT(s->small == 0, "`fio_str_free2` error, strring reinitialized!");
|
@@ -7885,11 +7931,11 @@ FIO_FUNC inline void fio_str_test(void) {
|
|
7885
7931
|
"Static string length should be automatically calculated.");
|
7886
7932
|
FIO_ASSERT(str.dealloc == NULL,
|
7887
7933
|
"Static string deallocation function should be NULL.");
|
7888
|
-
|
7934
|
+
fio_str_free(&str);
|
7889
7935
|
str = FIO_STR_INIT_STATIC("Welcome");
|
7890
7936
|
fio_str_info_s state = fio_str_write(&str, " Home", 5);
|
7891
7937
|
FIO_ASSERT(state.capa > 0, "Static string not converted to non-static.");
|
7892
|
-
|
7938
|
+
fio_str_free(&str);
|
7893
7939
|
}
|
7894
7940
|
fprintf(stderr, "* passed.\n");
|
7895
7941
|
}
|
@@ -7899,6 +7945,9 @@ FIO_FUNC inline void fio_str_test(void) {
|
|
7899
7945
|
Testing Memory Allocator
|
7900
7946
|
***************************************************************************** */
|
7901
7947
|
|
7948
|
+
#if FIO_FORCE_MALLOC
|
7949
|
+
#define fio_malloc_test()
|
7950
|
+
#else
|
7902
7951
|
void fio_malloc_test(void) {
|
7903
7952
|
fprintf(stderr, "=== Testing facil.io memory allocator's system calls\n");
|
7904
7953
|
char *mem = sys_alloc(FIO_MEMORY_BLOCK_SIZE, 0);
|
@@ -7929,8 +7978,18 @@ void fio_malloc_test(void) {
|
|
7929
7978
|
FIO_ASSERT(mem[0] == 'a', "fio_realloc memory wasn't copied!\n");
|
7930
7979
|
FIO_ASSERT(arena_last_used, "arena_last_used wasn't initialized!\n");
|
7931
7980
|
block_s *b = arena_last_used->block;
|
7932
|
-
|
7933
|
-
|
7981
|
+
|
7982
|
+
/* move arena to block's start */
|
7983
|
+
while (arena_last_used->block == b) {
|
7984
|
+
mem = fio_malloc(1);
|
7985
|
+
FIO_ASSERT(mem, "fio_malloc failed to allocate memory!\n");
|
7986
|
+
fio_free(mem);
|
7987
|
+
}
|
7988
|
+
/* make sure a block is assigned */
|
7989
|
+
fio_free(fio_malloc(1));
|
7990
|
+
b = arena_last_used->block;
|
7991
|
+
size_t count = 1;
|
7992
|
+
/* count allocations within block */
|
7934
7993
|
do {
|
7935
7994
|
FIO_ASSERT(mem, "fio_malloc failed to allocate memory!\n");
|
7936
7995
|
FIO_ASSERT(!((uintptr_t)mem & 15),
|
@@ -7947,18 +8006,21 @@ void fio_malloc_test(void) {
|
|
7947
8006
|
++count;
|
7948
8007
|
} while (arena_last_used->block == b);
|
7949
8008
|
{
|
8009
|
+
fprintf(stderr, "* Confirm block address: %p, last allocation was %p\n",
|
8010
|
+
(void *)arena_last_used->block, (void *)mem);
|
7950
8011
|
fprintf(
|
7951
8012
|
stderr,
|
7952
8013
|
"* Performed %zu allocations out of expected %zu allocations per "
|
7953
8014
|
"block.\n",
|
7954
8015
|
count,
|
7955
8016
|
(size_t)((FIO_MEMORY_BLOCK_SLICES - 2) - (sizeof(block_s) >> 4) - 1));
|
8017
|
+
intptr_t old_memory_pool_count = memory.count;
|
8018
|
+
fio_free(mem);
|
7956
8019
|
FIO_ASSERT(memory.available,
|
7957
8020
|
"memory pool empty (memory block wasn't freed)!\n");
|
7958
|
-
FIO_ASSERT(old_memory_pool_count == memory.count,
|
7959
|
-
"memory.count == %ld (memory block
|
7960
|
-
(long)old_memory_pool_count);
|
7961
|
-
fio_free(mem);
|
8021
|
+
FIO_ASSERT(old_memory_pool_count + 1 == memory.count,
|
8022
|
+
"memory.count == %ld , was %ld (memory block counting error)!\n",
|
8023
|
+
(long)memory.count, (long)old_memory_pool_count);
|
7962
8024
|
}
|
7963
8025
|
/* rotate block again */
|
7964
8026
|
b = arena_last_used->block;
|
@@ -8019,6 +8081,7 @@ void fio_malloc_test(void) {
|
|
8019
8081
|
|
8020
8082
|
fprintf(stderr, "* passed.\n");
|
8021
8083
|
}
|
8084
|
+
#endif
|
8022
8085
|
|
8023
8086
|
/* *****************************************************************************
|
8024
8087
|
Testing Core Callback add / remove / ensure
|
@@ -8346,114 +8409,159 @@ Set data-structure Testing
|
|
8346
8409
|
|
8347
8410
|
#define FIO_SET_TEXT_COUNT 524288UL
|
8348
8411
|
|
8349
|
-
#define FIO_SET_NAME
|
8412
|
+
#define FIO_SET_NAME fio_set_test
|
8350
8413
|
#define FIO_SET_OBJ_TYPE uintptr_t
|
8414
|
+
#include <fio.h>
|
8351
8415
|
|
8416
|
+
#define FIO_SET_NAME fio_hash_test
|
8417
|
+
#define FIO_SET_KEY_TYPE uintptr_t
|
8418
|
+
#define FIO_SET_OBJ_TYPE uintptr_t
|
8352
8419
|
#include <fio.h>
|
8353
|
-
#define FIO_SET_NAME(s) fio_hashmap_test_##s
|
8354
8420
|
|
8355
8421
|
FIO_FUNC void fio_set_test(void) {
|
8356
|
-
|
8422
|
+
fio_set_test_s s = FIO_SET_INIT;
|
8423
|
+
fio_hash_test_s h = FIO_SET_INIT;
|
8357
8424
|
fprintf(
|
8358
8425
|
stderr,
|
8359
8426
|
"=== Testing Core ordered Set (re-including fio.h with FIO_SET_NAME)\n");
|
8360
8427
|
fprintf(stderr, "* Inserting %lu items\n", FIO_SET_TEXT_COUNT);
|
8361
|
-
|
8362
|
-
|
8363
|
-
|
8364
|
-
|
8365
|
-
|
8366
|
-
|
8367
|
-
FIO_ASSERT(FIO_SET_NAME(count)(&s) == 0,
|
8368
|
-
"empty set should have zero objects");
|
8369
|
-
FIO_ASSERT(FIO_SET_NAME(capa)(&s) == 0, "empty set should have no capacity");
|
8370
|
-
FIO_ASSERT(!FIO_SET_NAME(is_fragmented)(&s),
|
8428
|
+
|
8429
|
+
FIO_ASSERT(fio_set_test_count(&s) == 0, "empty set should have zero objects");
|
8430
|
+
FIO_ASSERT(fio_set_test_capa(&s) == 0, "empty set should have no capacity");
|
8431
|
+
FIO_ASSERT(fio_hash_test_capa(&h) == 0, "empty hash should have no capacity");
|
8432
|
+
FIO_ASSERT(!fio_set_test_is_fragmented(&s),
|
8371
8433
|
"empty set shouldn't be considered fragmented");
|
8372
|
-
FIO_ASSERT(!
|
8434
|
+
FIO_ASSERT(!fio_hash_test_is_fragmented(&h),
|
8435
|
+
"empty hash shouldn't be considered fragmented");
|
8436
|
+
FIO_ASSERT(!fio_set_test_last(&s), "empty set shouldn't have a last object");
|
8437
|
+
FIO_ASSERT(!fio_hash_test_last(&h),
|
8438
|
+
"empty hash shouldn't have a last object");
|
8373
8439
|
|
8374
8440
|
for (uintptr_t i = 1; i < FIO_SET_TEXT_COUNT; ++i) {
|
8375
|
-
|
8376
|
-
|
8377
|
-
FIO_ASSERT(
|
8378
|
-
|
8379
|
-
|
8380
|
-
FIO_ASSERT(i ==
|
8441
|
+
fio_set_test_insert(&s, i, i);
|
8442
|
+
fio_hash_test_insert(&h, i, i, i + 1);
|
8443
|
+
FIO_ASSERT(fio_set_test_find(&s, i, i), "set find failed after insert");
|
8444
|
+
FIO_ASSERT(fio_hash_test_find(&h, i, i), "hash find failed after insert");
|
8445
|
+
FIO_ASSERT(i == *fio_set_test_find(&s, i, i), "set insertion != find");
|
8446
|
+
FIO_ASSERT(i + 1 == *fio_hash_test_find(&h, i, i),
|
8447
|
+
"hash insertion != find");
|
8381
8448
|
}
|
8382
8449
|
fprintf(stderr, "* Seeking %lu items\n", FIO_SET_TEXT_COUNT);
|
8383
8450
|
for (unsigned long i = 1; i < FIO_SET_TEXT_COUNT; ++i) {
|
8384
|
-
|
8385
|
-
|
8386
|
-
FIO_ASSERT((i ==
|
8451
|
+
FIO_ASSERT((i == *fio_set_test_find(&s, i, i)),
|
8452
|
+
"set insertion != find (seek)");
|
8453
|
+
FIO_ASSERT((i + 1 == *fio_hash_test_find(&h, i, i)),
|
8454
|
+
"hash insertion != find (seek)");
|
8387
8455
|
}
|
8388
8456
|
{
|
8389
|
-
fprintf(stderr, "* Testing order for %lu items\n",
|
8457
|
+
fprintf(stderr, "* Testing order for %lu items in set\n",
|
8458
|
+
FIO_SET_TEXT_COUNT);
|
8390
8459
|
uintptr_t i = 1;
|
8391
8460
|
FIO_SET_FOR_LOOP(&s, pos) {
|
8392
|
-
|
8393
|
-
|
8394
|
-
|
8461
|
+
FIO_ASSERT(pos->obj == i, "object order mismatch %lu != %lu.",
|
8462
|
+
(unsigned long)i, (unsigned long)pos->obj);
|
8463
|
+
++i;
|
8464
|
+
}
|
8465
|
+
}
|
8466
|
+
{
|
8467
|
+
fprintf(stderr, "* Testing order for %lu items in hash\n",
|
8468
|
+
FIO_SET_TEXT_COUNT);
|
8469
|
+
uintptr_t i = 1;
|
8470
|
+
FIO_SET_FOR_LOOP(&h, pos) {
|
8471
|
+
FIO_ASSERT(pos->obj.obj == i + 1 && pos->obj.key == i,
|
8472
|
+
"object order mismatch %lu != %lu.", (unsigned long)i,
|
8473
|
+
(unsigned long)pos->obj.key);
|
8395
8474
|
++i;
|
8396
8475
|
}
|
8397
8476
|
}
|
8398
8477
|
|
8399
8478
|
fprintf(stderr, "* Removing odd items from %lu items\n", FIO_SET_TEXT_COUNT);
|
8400
8479
|
for (unsigned long i = 1; i < FIO_SET_TEXT_COUNT; i += 2) {
|
8401
|
-
|
8402
|
-
|
8403
|
-
FIO_ASSERT(!(
|
8404
|
-
"Removal failed (still exists).");
|
8480
|
+
fio_set_test_remove(&s, i, i);
|
8481
|
+
fio_hash_test_remove(&h, i, i);
|
8482
|
+
FIO_ASSERT(!(fio_set_test_find(&s, i, i)),
|
8483
|
+
"Removal failed in set (still exists).");
|
8484
|
+
FIO_ASSERT(!(fio_hash_test_find(&h, i, i)),
|
8485
|
+
"Removal failed in hash (still exists).");
|
8405
8486
|
}
|
8406
8487
|
{
|
8407
8488
|
fprintf(stderr, "* Testing for %lu / 2 holes\n", FIO_SET_TEXT_COUNT);
|
8408
8489
|
uintptr_t i = 1;
|
8409
8490
|
FIO_SET_FOR_LOOP(&s, pos) {
|
8410
|
-
obj_mem.obj = pos->obj;
|
8411
8491
|
if (pos->hash == 0) {
|
8412
8492
|
FIO_ASSERT((i & 1) == 1, "deleted object wasn't odd");
|
8413
8493
|
} else {
|
8414
|
-
FIO_ASSERT(
|
8415
|
-
(unsigned long)i, (unsigned long)
|
8494
|
+
FIO_ASSERT(pos->obj == i, "deleted object value mismatch %lu != %lu",
|
8495
|
+
(unsigned long)i, (unsigned long)pos->obj);
|
8496
|
+
}
|
8497
|
+
++i;
|
8498
|
+
}
|
8499
|
+
i = 1;
|
8500
|
+
FIO_SET_FOR_LOOP(&h, pos) {
|
8501
|
+
if (pos->hash == 0) {
|
8502
|
+
FIO_ASSERT((i & 1) == 1, "deleted object wasn't odd");
|
8503
|
+
} else {
|
8504
|
+
FIO_ASSERT(pos->obj.key == i,
|
8505
|
+
"deleted object value mismatch %lu != %lu", (unsigned long)i,
|
8506
|
+
(unsigned long)pos->obj.key);
|
8416
8507
|
}
|
8417
8508
|
++i;
|
8418
8509
|
}
|
8419
8510
|
{
|
8420
8511
|
fprintf(stderr, "* Poping two elements (testing pop through holes)\n");
|
8421
|
-
FIO_ASSERT(
|
8422
|
-
|
8423
|
-
|
8424
|
-
|
8425
|
-
FIO_ASSERT(
|
8426
|
-
|
8427
|
-
|
8428
|
-
|
8429
|
-
|
8430
|
-
|
8431
|
-
|
8432
|
-
|
8512
|
+
FIO_ASSERT(fio_set_test_last(&s), "Pop `last` 1 failed - no last object");
|
8513
|
+
uintptr_t tmp = *fio_set_test_last(&s);
|
8514
|
+
FIO_ASSERT(tmp, "Pop set `last` 1 failed to collect object");
|
8515
|
+
fio_set_test_pop(&s);
|
8516
|
+
FIO_ASSERT(
|
8517
|
+
*fio_set_test_last(&s) != tmp,
|
8518
|
+
"Pop `last` 2 in set same as `last` 1 - failed to collect object");
|
8519
|
+
tmp = fio_hash_test_last(&h)->key;
|
8520
|
+
FIO_ASSERT(tmp, "Pop hash `last` 1 failed to collect object");
|
8521
|
+
fio_hash_test_pop(&h);
|
8522
|
+
FIO_ASSERT(
|
8523
|
+
fio_hash_test_last(&h)->key != tmp,
|
8524
|
+
"Pop `last` 2 in hash same as `last` 1 - failed to collect object");
|
8525
|
+
FIO_ASSERT(fio_set_test_last(&s), "Pop `last` 2 failed - no last object");
|
8526
|
+
FIO_ASSERT(fio_hash_test_last(&h),
|
8527
|
+
"Pop `last` 2 failed in hash - no last object");
|
8528
|
+
fio_set_test_pop(&s);
|
8529
|
+
fio_hash_test_pop(&h);
|
8433
8530
|
}
|
8434
8531
|
if (1) {
|
8435
|
-
|
8436
|
-
|
8532
|
+
uintptr_t tmp = 1;
|
8533
|
+
fio_set_test_remove(&s, tmp, tmp);
|
8534
|
+
fio_hash_test_remove(&h, tmp, tmp);
|
8437
8535
|
size_t count = s.count;
|
8438
|
-
|
8439
|
-
FIO_ASSERT(
|
8440
|
-
|
8441
|
-
|
8442
|
-
|
8443
|
-
|
8444
|
-
|
8445
|
-
|
8446
|
-
|
8447
|
-
|
8448
|
-
|
8536
|
+
fio_set_test_overwrite(&s, tmp, tmp);
|
8537
|
+
FIO_ASSERT(
|
8538
|
+
count + 1 == s.count,
|
8539
|
+
"Re-adding a removed item in set should increase count by 1 (%zu + "
|
8540
|
+
"1 != %zu).",
|
8541
|
+
count, (size_t)s.count);
|
8542
|
+
count = h.count;
|
8543
|
+
fio_hash_test_insert(&h, tmp, tmp, tmp);
|
8544
|
+
FIO_ASSERT(
|
8545
|
+
count + 1 == h.count,
|
8546
|
+
"Re-adding a removed item in hash should increase count by 1 (%zu + "
|
8547
|
+
"1 != %zu).",
|
8548
|
+
count, (size_t)s.count);
|
8549
|
+
tmp = *fio_set_test_find(&s, tmp, tmp);
|
8550
|
+
FIO_ASSERT(tmp == 1,
|
8551
|
+
"Re-adding a removed item should update the item in the set "
|
8552
|
+
"(%lu != 1)!",
|
8553
|
+
(unsigned long)*fio_set_test_find(&s, tmp, tmp));
|
8554
|
+
fio_set_test_remove(&s, tmp, tmp);
|
8555
|
+
fio_hash_test_remove(&h, tmp, tmp);
|
8556
|
+
FIO_ASSERT(count == h.count,
|
8449
8557
|
"Re-removing an item should decrease count (%zu != %zu).",
|
8450
8558
|
count, (size_t)s.count);
|
8451
|
-
FIO_ASSERT(!
|
8559
|
+
FIO_ASSERT(!fio_set_test_find(&s, tmp, tmp),
|
8452
8560
|
"Re-removing a re-added item should update the item!");
|
8453
8561
|
}
|
8454
8562
|
}
|
8455
8563
|
fprintf(stderr, "* Compacting HashMap to %lu\n", FIO_SET_TEXT_COUNT >> 1);
|
8456
|
-
|
8564
|
+
fio_set_test_compact(&s);
|
8457
8565
|
{
|
8458
8566
|
fprintf(stderr, "* Testing that %lu items are continuous\n",
|
8459
8567
|
FIO_SET_TEXT_COUNT >> 1);
|
@@ -8465,11 +8573,12 @@ FIO_FUNC void fio_set_test(void) {
|
|
8465
8573
|
FIO_ASSERT(i == s.count, "count error (%lu != %lu).", i, s.count);
|
8466
8574
|
}
|
8467
8575
|
|
8468
|
-
|
8576
|
+
fio_set_test_free(&s);
|
8577
|
+
fio_hash_test_free(&h);
|
8469
8578
|
FIO_ASSERT(!s.map && !s.ordered && !s.pos && !s.capa,
|
8470
8579
|
"HashMap not re-initialized after free.");
|
8471
8580
|
|
8472
|
-
|
8581
|
+
fio_set_test_capa_require(&s, FIO_SET_TEXT_COUNT);
|
8473
8582
|
|
8474
8583
|
FIO_ASSERT(
|
8475
8584
|
s.map && s.ordered && !s.pos && s.capa >= FIO_SET_TEXT_COUNT,
|
@@ -8477,16 +8586,15 @@ FIO_FUNC void fio_set_test(void) {
|
|
8477
8586
|
(void *)s.map, (void *)s.ordered, s.pos, s.capa, FIO_SET_TEXT_COUNT);
|
8478
8587
|
|
8479
8588
|
for (unsigned long i = 1; i < FIO_SET_TEXT_COUNT; ++i) {
|
8480
|
-
|
8481
|
-
|
8482
|
-
FIO_ASSERT(FIO_SET_NAME(find)(&s, obj_mem.i, obj_mem.obj),
|
8589
|
+
fio_set_test_insert(&s, i, i);
|
8590
|
+
FIO_ASSERT(fio_set_test_find(&s, i, i),
|
8483
8591
|
"find failed after insert (2nd round)");
|
8484
|
-
|
8485
|
-
|
8592
|
+
FIO_ASSERT(i == *fio_set_test_find(&s, i, i),
|
8593
|
+
"insertion (2nd round) != find");
|
8486
8594
|
FIO_ASSERT(i == s.count, "count error (%lu != %lu) post insertion.", i,
|
8487
8595
|
s.count);
|
8488
8596
|
}
|
8489
|
-
|
8597
|
+
fio_set_test_free(&s);
|
8490
8598
|
}
|
8491
8599
|
#undef FIO_SET_NAME
|
8492
8600
|
|
@@ -8561,14 +8669,14 @@ SHA-1 tests
|
|
8561
8669
|
static void fio_sha1_speed_test(void) {
|
8562
8670
|
/* test based on code from BearSSL with credit to Thomas Pornin */
|
8563
8671
|
uint8_t buffer[8192];
|
8564
|
-
uint8_t result[
|
8672
|
+
uint8_t result[21];
|
8565
8673
|
fio_sha1_s sha1;
|
8566
8674
|
memset(buffer, 'T', sizeof(buffer));
|
8567
8675
|
/* warmup */
|
8568
8676
|
for (size_t i = 0; i < 4; i++) {
|
8569
8677
|
sha1 = fio_sha1_init();
|
8570
8678
|
fio_sha1_write(&sha1, buffer, sizeof(buffer));
|
8571
|
-
memcpy(result, fio_sha1_result(&sha1),
|
8679
|
+
memcpy(result, fio_sha1_result(&sha1), 21);
|
8572
8680
|
}
|
8573
8681
|
/* loop until test runs for more than 2 seconds */
|
8574
8682
|
for (size_t cycles = 8192;;) {
|
@@ -8595,7 +8703,7 @@ static void fio_sha1_speed_test(void) {
|
|
8595
8703
|
static void fio_sha1_open_ssl_speed_test(void) {
|
8596
8704
|
/* test based on code from BearSSL with credit to Thomas Pornin */
|
8597
8705
|
uint8_t buffer[8192];
|
8598
|
-
uint8_t result[
|
8706
|
+
uint8_t result[21];
|
8599
8707
|
SHA_CTX o_sh1;
|
8600
8708
|
memset(buffer, 'T', sizeof(buffer));
|
8601
8709
|
/* warmup */
|
@@ -8993,8 +9101,7 @@ void fio_base64_test(void) {
|
|
8993
9101
|
{"foob", "Zm9vYg=="},
|
8994
9102
|
{"fooba", "Zm9vYmE="},
|
8995
9103
|
{"foobar", "Zm9vYmFy"},
|
8996
|
-
{ NULL
|
8997
|
-
NULL } // Stop
|
9104
|
+
{NULL, NULL} // Stop
|
8998
9105
|
};
|
8999
9106
|
int i = 0;
|
9000
9107
|
char buffer[1024];
|