2 * Copyright (c) 2017-2020, De Rais <derais@cock.li>
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
24 #include <arpa/inet.h>
25 #include <netinet/in.h>
26 #include <sys/socket.h>
27 #include <sys/types.h>
33 * How many characters are needed to hold "1141709097-06-13 06:26:07Z",
34 * which is the representation of 2^55 - 1, the largest time_t that
35 * this, rather reasonable system can hold.
37 #define ISO8601_MAX 30
40 * Convert t to a string, like "2000-01-01 23:59:59Z"
48 * - Either a string in ISO 8601 format has been returned, or 0
49 * has been returned and an error message has been logged.
52 util_iso8601_from_time_t(time_t t
)
55 * XXX: If this becomes multithreaded, we have bigger
56 * problems, but we also need to use gmtime_r() or the
59 struct tm
*tm
= gmtime(&t
);
63 ERROR_MESSAGE("gmtime");
69 * Even if t > 2^55 - 1, this should only truncate the
70 * result, not corrupt memory.
72 if (!(ret
= malloc(ISO8601_MAX
+ 1))) {
73 ERROR_MESSAGE("malloc");
78 strftime(ret
, ISO8601_MAX
, "%F %H:%M:%SZ", tm
);
83 /* Put an IP address into a range-comparable form */
85 util_normalize_ip(const char *in
, char **out
)
91 if (strchr(in
, ':')) {
93 * If your C implementation doesn't implement the
94 * IPV6 functionality, you should be able to simply
95 * lop out this section entirely with no harm done.
97 struct in6_addr a
= { 0 };
99 if (inet_pton(AF_INET6
, in
, &a
) != 1) {
100 PERROR_MESSAGE("inet_pton");
104 built_len
= (4 * 8) + 7;
106 if (!(built
= malloc(built_len
+ 1))) {
107 PERROR_MESSAGE("malloc");
111 sprintf(built
, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
112 "%02x%02x:%02x%02x:%02x%02x:%02x%02x", (unsigned
114 s6_addr
[0], (unsigned int) a
.s6_addr
[1], (unsigned
116 a
.s6_addr
[2], (unsigned int) a
.s6_addr
[3], (unsigned
118 a
.s6_addr
[4], (unsigned int) a
.s6_addr
[5], (unsigned
120 a
.s6_addr
[6], (unsigned int) a
.s6_addr
[7], (unsigned
122 a
.s6_addr
[8], (unsigned int) a
.s6_addr
[9], (unsigned
124 a
.s6_addr
[10], (unsigned int) a
.s6_addr
[11], (unsigned
126 a
.s6_addr
[12], (unsigned int) a
.s6_addr
[13], (unsigned
128 a
.s6_addr
[14], (unsigned int) a
.s6_addr
[15]);
129 } else if (strchr(in
, '.')) {
130 struct in_addr a
= { 0 };
132 if (inet_pton(AF_INET
, in
, &a
) != 1) {
133 PERROR_MESSAGE("inet_pton");
137 built_len
= (3 * 4) + 3;
139 if (!(built
= malloc(built_len
+ 1))) {
140 PERROR_MESSAGE("malloc");
144 sprintf(built
, "%03u.%03u.%03u.%03u", /* */
145 (a
.s_addr
& 0x000000ff) >> 0, /* */
146 (a
.s_addr
& 0x0000ff00) >> 8, /* */
147 (a
.s_addr
& 0x00ff0000) >> 16, /* */
148 (a
.s_addr
& 0xff000000) >> 24 /* */
151 ERROR_MESSAGE("\"%s\" is not a valid IP address", in
);
168 * Call wt_write_thread and wt_write_board on everything
170 * Note: this ACQUIRES all locks, which means it must be called
171 * with NO LOCKS acquired
174 util_rebuild(struct configuration
*conf
)
176 uint_fast8_t had_errors
= 0;
178 for (size_t j
= 0; j
< conf
->boards_num
; ++j
) {
179 uint_fast8_t need_to_unlock
= 0;
180 uintmax_t *thread_ids
= 0;
181 size_t thread_ids_num
= 0;
182 size_t board_pages_num
= 0;
184 if (lock_acquire(j
) < 0) {
185 LOG("Error in lock_acquire (500)");
192 if (db_cull_and_report_threads(j
, &thread_ids
, &thread_ids_num
,
193 &board_pages_num
) < 0) {
194 LOG("Error in db_cull_and_report_threads (j = %zu)", j
);
195 goto done_with_this_board
;
198 for (size_t k
= 0; k
< thread_ids_num
; ++k
) {
199 if (wt_write_thread(j
, thread_ids
[k
]) < 0) {
200 LOG("Error in wt_write_thread (j = %zu, "
201 "thread_ids[k] = %ju)", j
, thread_ids
[k
]);
206 wt_write_board(j
, thread_ids
, thread_ids_num
, board_pages_num
);
207 done_with_this_board
:
209 if (need_to_unlock
) {
214 if (lock_acquire_recent() < 0) {
215 LOG("Error in lock_acquire_recent (500)");
220 wt_write_recent_page();
221 lock_release_recent();