2 * Copyright (c) 2017, 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>
30 * How many characters are needed to hold "1141709097-06-13 06:26:07Z",
31 * which is the representation of 2^55 - 1, the largest time_t that
32 * this, rather reasonable system can hold.
34 #define ISO8601_MAX 30
37 * Convert t to a string, like "2000-01-01 23:59:59Z"
45 * - Either a string in ISO 8601 format has been returned, or 0
46 * has been returned and an error message has been logged.
48 char * util_iso8601_from_time_t(time_t t
)
51 * XXX: If this becomes multithreaded, we have bigger
52 * problems, but we also need to use gmtime_r() or the
55 struct tm
*tm
= gmtime(&t
);
59 ERROR_MESSAGE("gmtime");
65 * Even if t > 2^55 - 1, this should only truncate the
66 * result, not corrupt memory.
68 if (!(ret
= malloc(ISO8601_MAX
+ 1))) {
69 ERROR_MESSAGE("malloc");
74 strftime(ret
, ISO8601_MAX
, "%F %H:%M:%SZ", tm
);
79 /* Put an IP address into a range-comparable form */
80 int util_normalize_ip(const char *in
, char **out
)
86 if (strchr(in
, ':')) {
88 * If your C implementation doesn't implement the
89 * IPV6 functionality, you should be able to simply
90 * lop out this section entirely with no harm done.
92 struct in6_addr a
= { 0 };
94 if (inet_pton(AF_INET6
, in
, &a
) != 1) {
95 PERROR_MESSAGE("inet_pton");
99 built_len
= (4 * 8) + 7;
101 if (!(built
= malloc(built_len
+ 1))) {
102 PERROR_MESSAGE("malloc");
106 sprintf(built
, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
107 "%02x%02x:%02x%02x:%02x%02x:%02x%02x", (unsigned
109 s6_addr
[0], (unsigned int) a
.s6_addr
[1], (unsigned
111 a
.s6_addr
[2], (unsigned int) a
.s6_addr
[3], (unsigned
113 a
.s6_addr
[4], (unsigned int) a
.s6_addr
[5], (unsigned
115 a
.s6_addr
[6], (unsigned int) a
.s6_addr
[7], (unsigned
117 a
.s6_addr
[8], (unsigned int) a
.s6_addr
[9], (unsigned
119 a
.s6_addr
[10], (unsigned int) a
.s6_addr
[11], (unsigned
121 a
.s6_addr
[12], (unsigned int) a
.s6_addr
[13], (unsigned
123 a
.s6_addr
[14], (unsigned int) a
.s6_addr
[15]);
124 } else if (strchr(in
, '.')) {
125 struct in_addr a
= { 0 };
127 if (inet_pton(AF_INET
, in
, &a
) != 1) {
128 PERROR_MESSAGE("inet_pton");
132 built_len
= (3 * 4) + 3;
134 if (!(built
= malloc(built_len
+ 1))) {
135 PERROR_MESSAGE("malloc");
139 sprintf(built
, "%03u.%03u.%03u.%03u", /* */
140 (a
.s_addr
& 0x000000ff) >> 0, /* */
141 (a
.s_addr
& 0x0000ff00) >> 8, /* */
142 (a
.s_addr
& 0x00ff0000) >> 16, /* */
143 (a
.s_addr
& 0xff000000) >> 24 /* */
146 ERROR_MESSAGE("\"%s\" is not a valid IP address", in
);
163 * Call wt_write_thread and wt_write_board on everything
165 * Note: this ACQUIRES all locks, which means it must be called
166 * with NO LOCKS acquired
168 int util_rebuild(struct configuration
*conf
)
170 uint_fast8_t had_errors
= 0;
172 for (size_t j
= 0; j
< conf
->boards_num
; ++j
) {
173 uint_fast8_t need_to_unlock
= 0;
174 uintmax_t *thread_ids
= 0;
175 size_t thread_ids_num
= 0;
176 size_t board_pages_num
= 0;
178 if (lock_acquire(j
) < 0) {
179 LOG("Error in lock_acquire (500)");
186 if (db_cull_and_report_threads(j
, &thread_ids
, &thread_ids_num
,
187 &board_pages_num
) < 0) {
188 LOG("Error in db_cull_and_report_threads (j = %zu)", j
);
189 goto done_with_this_board
;
192 for (size_t k
= 0; k
< thread_ids_num
; ++k
) {
193 if (wt_write_thread(j
, thread_ids
[k
]) < 0) {
194 LOG("Error in wt_write_thread (j = %zu, "
195 "thread_ids[k] = %ju)", j
, thread_ids
[k
]);
200 wt_write_board(j
, thread_ids
, thread_ids_num
, board_pages_num
);
201 done_with_this_board
:
203 if (need_to_unlock
) {