Branch data Line data Source code
1 : : /* SPDX-FileCopyrightText: Copyright 2026 Cozens Software Solutions Limited
2 : : * SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0 OR LicenseRef-COSOSO-Commercial
3 : : */
4 : :
5 : : #include "SolidSyslogPendingEvents.h"
6 : :
7 : : #include <stdbool.h>
8 : : #include <stddef.h>
9 : : #include <stdint.h>
10 : :
11 : : #include "SolidSyslogBufferCategories.h"
12 : : #include "SolidSyslogError.h"
13 : : #include "SolidSyslogFileCategories.h"
14 : : #include "SolidSyslogLoggerCategories.h"
15 : : #include "SolidSyslogSecurityPolicyCategories.h"
16 : : #include "SolidSyslogSenderCategories.h"
17 : : #include "SolidSyslogStoreCategories.h"
18 : : #include "SolidSyslogTlsStreamCategories.h"
19 : :
20 : : struct PendingEventSlot
21 : : {
22 : : const struct SolidSyslogErrorSource* Source;
23 : : int32_t Detail;
24 : : int32_t NativeCode;
25 : : /* The event's position in PendingEvents_Severities plus one. Zero, where a
26 : : * slot starts and where Clear returns it, stands for the kind's own
27 : : * severity, so a slot read before its first event lands says nothing
28 : : * more severe than its kind is raised at. */
29 : : uint8_t SeverityCode;
30 : : bool HasNativeCode;
31 : : bool Pending;
32 : : };
33 : :
34 : : /* A reported kind and the least severe severity it is raised at. */
35 : : struct PendingEventKind
36 : : {
37 : : uint16_t Category;
38 : : enum SolidSyslogSeverity Severity;
39 : : };
40 : :
41 : : /* The reported kinds, in slot order. Index is identity: Take reports the
42 : : * category from this table, so a slot never has to store it. The causes come
43 : : * first, then the losses they lead to, then the halt a loss can end in, then
44 : : * the delivery state, so a reader walking the slots in order reports a cause
45 : : * ahead of what it caused: a file fault ahead of the freeze, a threshold
46 : : * crossed ahead of the full store's refusal, that refusal ahead of the halt, a
47 : : * refused handshake ahead of the failed delivery. */
48 : : static const struct PendingEventKind PendingEvents_Kinds[SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT] = {
49 : : {SOLIDSYSLOG_CAT_FILE_IO_FAILED, SOLIDSYSLOG_SEVERITY_ERROR},
50 : : {SOLIDSYSLOG_CAT_SECURITY_POLICY_KEY_UNAVAILABLE, SOLIDSYSLOG_SEVERITY_ERROR},
51 : : {SOLIDSYSLOG_CAT_SECURITY_POLICY_SEAL_FAILED, SOLIDSYSLOG_SEVERITY_ERROR},
52 : : {SOLIDSYSLOG_CAT_SECURITY_POLICY_OPEN_FAILED, SOLIDSYSLOG_SEVERITY_ERROR},
53 : : {SOLIDSYSLOG_CAT_TLS_STREAM_HANDSHAKE_FAILED, SOLIDSYSLOG_SEVERITY_WARNING},
54 : : {SOLIDSYSLOG_CAT_BUFFER_BACKEND_FAILED, SOLIDSYSLOG_SEVERITY_ERROR},
55 : : {SOLIDSYSLOG_CAT_BUFFER_RECORDS_LOST, SOLIDSYSLOG_SEVERITY_WARNING},
56 : : {SOLIDSYSLOG_CAT_STORE_THRESHOLD_CROSSED, SOLIDSYSLOG_SEVERITY_WARNING},
57 : : {SOLIDSYSLOG_CAT_STORE_RECORDS_LOST, SOLIDSYSLOG_SEVERITY_WARNING},
58 : : {SOLIDSYSLOG_CAT_STORE_RECORD_DISCARDED, SOLIDSYSLOG_SEVERITY_ERROR},
59 : : {SOLIDSYSLOG_CAT_STORE_WRITE_FAILED, SOLIDSYSLOG_SEVERITY_ERROR},
60 : : {SOLIDSYSLOG_CAT_STORE_FROZEN, SOLIDSYSLOG_SEVERITY_ERROR},
61 : : {SOLIDSYSLOG_CAT_SENDER_RECORDS_LOST, SOLIDSYSLOG_SEVERITY_ERROR},
62 : : {SOLIDSYSLOG_CAT_LOGGER_HALTED, SOLIDSYSLOG_SEVERITY_ERROR},
63 : : {SOLIDSYSLOG_CAT_SENDER_DELIVERY_FAILED, SOLIDSYSLOG_SEVERITY_WARNING},
64 : : {SOLIDSYSLOG_CAT_SENDER_DELIVERY_RESTORED, SOLIDSYSLOG_SEVERITY_NOTICE},
65 : : };
66 : :
67 : : /* The severities in RFC 5424 order, which a slot's code indexes. */
68 : : static const enum SolidSyslogSeverity PendingEvents_Severities[] = {
69 : : SOLIDSYSLOG_SEVERITY_EMERGENCY,
70 : : SOLIDSYSLOG_SEVERITY_ALERT,
71 : : SOLIDSYSLOG_SEVERITY_CRITICAL,
72 : : SOLIDSYSLOG_SEVERITY_ERROR,
73 : : SOLIDSYSLOG_SEVERITY_WARNING,
74 : : SOLIDSYSLOG_SEVERITY_NOTICE,
75 : : SOLIDSYSLOG_SEVERITY_INFORMATIONAL,
76 : : SOLIDSYSLOG_SEVERITY_DEBUG,
77 : : };
78 : :
79 : : static volatile struct PendingEventSlot PendingEvents_Slots[SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT];
80 : :
81 : : static inline size_t PendingEvents_IndexOf(uint16_t category);
82 : : static inline uint8_t PendingEvents_SeverityCode(enum SolidSyslogSeverity severity);
83 : : static inline enum SolidSyslogSeverity PendingEvents_SeverityOf(const struct PendingEventKind* kind, uint8_t code);
84 : :
85 : 9292 : void SolidSyslogPendingEvents_Record(const struct SolidSyslogErrorEvent* event)
86 : : {
87 : 9292 : size_t index = PendingEvents_IndexOf(event->Category);
88 [ + + ]: 9292 : if (index < SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT)
89 : : {
90 : 7729 : volatile struct PendingEventSlot* slot = &PendingEvents_Slots[index];
91 : : /* Volatile stores, Pending last: the header states what that buys. */
92 : 7729 : slot->SeverityCode = PendingEvents_SeverityCode(event->Severity);
93 : 7729 : slot->Source = event->Source;
94 : 7729 : slot->Detail = event->Detail;
95 : 7729 : slot->NativeCode = event->NativeCode;
96 : 7729 : slot->HasNativeCode = event->HasNativeCode;
97 : 7729 : slot->Pending = true;
98 : : }
99 : 9292 : }
100 : :
101 : : /* The slot index of a reported kind, or SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT for
102 : : * a category that is not one. */
103 : 9292 : static inline size_t PendingEvents_IndexOf(uint16_t category)
104 : : {
105 : 9292 : size_t found = SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT;
106 : 9292 : for (size_t index = 0U;
107 [ + + + + ]: 113142 : (index < SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT) && (found == SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT);
108 : 103850 : index++)
109 : : {
110 [ + + ]: 103850 : if (PendingEvents_Kinds[index].Category == category)
111 : : {
112 : 7729 : found = index;
113 : : }
114 : : }
115 : 9292 : return found;
116 : : }
117 : :
118 : : /* A severity the table does not hold keeps code zero, the kind's own. */
119 : 7729 : static inline uint8_t PendingEvents_SeverityCode(enum SolidSyslogSeverity severity)
120 : : {
121 : 7729 : const size_t severityCount = sizeof(PendingEvents_Severities) / sizeof(PendingEvents_Severities[0]);
122 : 7729 : uint8_t code = 0U;
123 [ + + ]: 69561 : for (size_t position = 0U; position < severityCount; position++)
124 : : {
125 [ + + ]: 61832 : if (PendingEvents_Severities[position] == severity)
126 : : {
127 : 7729 : code = (uint8_t) (position + 1U);
128 : : }
129 : : }
130 : 7729 : return code;
131 : : }
132 : :
133 : 58652 : bool SolidSyslogPendingEvents_IsPending(size_t index)
134 : : {
135 : 58652 : bool pending = false;
136 [ + + ]: 58652 : if (index < SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT)
137 : : {
138 : 58651 : pending = PendingEvents_Slots[index].Pending;
139 : : }
140 : 58652 : return pending;
141 : : }
142 : :
143 : 728 : bool SolidSyslogPendingEvents_AnyPending(void)
144 : : {
145 : 728 : bool pending = false;
146 [ + + + + ]: 12143 : for (size_t index = 0U; (index < SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT) && !pending; index++)
147 : : {
148 : 11415 : pending = PendingEvents_Slots[index].Pending;
149 : : }
150 : 728 : return pending;
151 : : }
152 : :
153 : 987 : bool SolidSyslogPendingEvents_Take(size_t index, struct SolidSyslogErrorEvent* event)
154 : : {
155 : 987 : bool wasPending = false;
156 [ + + ]: 987 : if (index < SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT)
157 : : {
158 : 986 : volatile struct PendingEventSlot* slot = &PendingEvents_Slots[index];
159 : 986 : wasPending = slot->Pending;
160 : 986 : slot->Pending = false;
161 : 986 : event->Severity = PendingEvents_SeverityOf(&PendingEvents_Kinds[index], slot->SeverityCode);
162 : 986 : event->Category = PendingEvents_Kinds[index].Category;
163 : 986 : event->HasNativeCode = slot->HasNativeCode;
164 : 986 : event->Source = slot->Source;
165 : 986 : event->Detail = slot->Detail;
166 : 986 : event->NativeCode = slot->NativeCode;
167 : : }
168 : 987 : return wasPending;
169 : : }
170 : :
171 : : /* A nonzero code comes only from PendingEvents_SeverityCode, so it is always
172 : : * a position in the table plus one. */
173 : 986 : static inline enum SolidSyslogSeverity PendingEvents_SeverityOf(const struct PendingEventKind* kind, uint8_t code)
174 : : {
175 : 986 : enum SolidSyslogSeverity severity = kind->Severity;
176 [ + + ]: 986 : if (code > 0U)
177 : : {
178 : 621 : severity = PendingEvents_Severities[code - 1U];
179 : : }
180 : 986 : return severity;
181 : : }
182 : :
183 : 2789 : void SolidSyslogPendingEvents_Clear(void)
184 : : {
185 [ + + ]: 47413 : for (size_t index = 0U; index < SOLIDSYSLOG_PENDING_EVENT_KIND_COUNT; index++)
186 : : {
187 : 44624 : PendingEvents_Slots[index].Pending = false;
188 : 44624 : PendingEvents_Slots[index].SeverityCode = 0U;
189 : : }
190 : 2789 : }
|