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 "SolidSyslogPosixMessageQueueBuffer.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 "SolidSyslogErrorCategory.h"
14 : : #include "SolidSyslogNullBuffer.h"
15 : : #include "SolidSyslogPoolAllocator.h"
16 : : #include "SolidSyslogPosixMessageQueueBufferErrors.h"
17 : : #include "SolidSyslogPosixMessageQueueBufferPrivate.h"
18 : : #include "SolidSyslogPrival.h"
19 : : #include "SolidSyslogTunables.h"
20 : :
21 : : struct SolidSyslogBuffer;
22 : :
23 : : /* Each pool slot's queue name is `/solidsyslog_<pid>_<slotIndex>`. The
24 : : * pid keeps the name unique per process; the slot index keeps multiple
25 : : * in-process pool entries from aliasing onto the same kernel queue
26 : : * object when the pool tunable is bumped above 1. */
27 : :
28 : : static inline size_t PosixMessageQueueBuffer_IndexFromHandle(const struct SolidSyslogBuffer* base);
29 : : static inline void PosixMessageQueueBuffer_CleanupAtIndex(size_t index, void* context);
30 : :
31 : : static bool PosixMessageQueueBuffer_InUse[SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_POOL_SIZE];
32 : : static struct SolidSyslogPosixMessageQueueBuffer
33 : : PosixMessageQueueBuffer_Pool[SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_POOL_SIZE];
34 : : static struct SolidSyslogPoolAllocator PosixMessageQueueBuffer_Allocator = {
35 : : PosixMessageQueueBuffer_InUse,
36 : : SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_POOL_SIZE
37 : : };
38 : :
39 : 73 : struct SolidSyslogBuffer* SolidSyslogPosixMessageQueueBuffer_Create(
40 : : struct SolidSyslogMutex* mutex,
41 : : size_t maxMessages,
42 : : SolidSyslogDiscardPolicyFunction getDiscardPolicy,
43 : : void* discardPolicyContext
44 : : )
45 : : {
46 : 73 : struct SolidSyslogBuffer* handle = SolidSyslogNullBuffer_Get();
47 [ + + ]: 73 : if (mutex == NULL)
48 : : {
49 : 3 : PosixMessageQueueBuffer_Report(
50 : : SOLIDSYSLOG_BAD_CONFIG_FATAL_SEVERITY,
51 : : SOLIDSYSLOG_CAT_BAD_CONFIG,
52 : : SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_ERROR_NULL_MUTEX
53 : : );
54 : : }
55 : : else
56 : : {
57 : 70 : size_t index = SolidSyslogPoolAllocator_AcquireFirstFree(&PosixMessageQueueBuffer_Allocator);
58 [ + + ]: 70 : if (SolidSyslogPoolAllocator_IndexIsValid(&PosixMessageQueueBuffer_Allocator, index) == true)
59 : : {
60 : 66 : int openErrno = SolidSyslogPosixMessageQueueBuffer_Initialise(
61 : : &PosixMessageQueueBuffer_Pool[index].Base,
62 : : mutex,
63 : : maxMessages,
64 : : index,
65 : : getDiscardPolicy,
66 : : discardPolicyContext
67 : : );
68 [ + + ]: 66 : if (openErrno == 0)
69 : : {
70 : 60 : handle = &PosixMessageQueueBuffer_Pool[index].Base;
71 : : }
72 : : else
73 : : {
74 : : /* No queue was opened, so there is none to close or unlink; the
75 : : * name may belong to a queue this buffer refused. */
76 : 6 : (void) SolidSyslogPoolAllocator_FreeIfInUse(&PosixMessageQueueBuffer_Allocator, index, NULL, NULL);
77 : 6 : SolidSyslog_ErrorWithNativeCode(
78 : : SOLIDSYSLOG_SEVERITY_ERROR,
79 : : &SolidSyslogPosixMessageQueueBufferErrorSource,
80 : : SOLIDSYSLOG_CAT_BUFFER_BACKEND_FAILED,
81 : : (int32_t) SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_ERROR_MQ_OPEN_FAILED,
82 : : (int32_t) openErrno
83 : : );
84 : : }
85 : : }
86 : : else
87 : : {
88 : 4 : PosixMessageQueueBuffer_Report(
89 : : SOLIDSYSLOG_POOL_EXHAUSTED_SEVERITY,
90 : : SOLIDSYSLOG_CAT_POOL_EXHAUSTED,
91 : : SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_ERROR_POOL_EXHAUSTED
92 : : );
93 : : }
94 : : }
95 : 73 : return handle;
96 : : }
97 : :
98 : 77 : void SolidSyslogPosixMessageQueueBuffer_Destroy(struct SolidSyslogBuffer* base)
99 : : {
100 : 77 : size_t index = PosixMessageQueueBuffer_IndexFromHandle(base);
101 [ + + + + ]: 138 : bool released = SolidSyslogPoolAllocator_IndexIsValid(&PosixMessageQueueBuffer_Allocator, index) &&
102 : 61 : SolidSyslogPoolAllocator_FreeIfInUse(
103 : : &PosixMessageQueueBuffer_Allocator,
104 : : index,
105 : : PosixMessageQueueBuffer_CleanupAtIndex,
106 : : NULL
107 : : );
108 [ + + ]: 77 : if (!released)
109 : : {
110 : 17 : PosixMessageQueueBuffer_Report(
111 : : SOLIDSYSLOG_UNKNOWN_DESTROY_SEVERITY,
112 : : SOLIDSYSLOG_CAT_UNKNOWN_DESTROY,
113 : : SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_ERROR_UNKNOWN_DESTROY
114 : : );
115 : : }
116 : 77 : }
117 : :
118 : 77 : static inline size_t PosixMessageQueueBuffer_IndexFromHandle(const struct SolidSyslogBuffer* base)
119 : : {
120 : 77 : size_t result = SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_POOL_SIZE;
121 [ + + ]: 93 : for (size_t poolIndex = 0U; poolIndex < SOLIDSYSLOG_POSIX_MESSAGE_QUEUE_BUFFER_POOL_SIZE; poolIndex++)
122 : : {
123 [ + + ]: 77 : if (base == &PosixMessageQueueBuffer_Pool[poolIndex].Base)
124 : : {
125 : 61 : result = poolIndex;
126 : 61 : break;
127 : : }
128 : : }
129 : 77 : return result;
130 : : }
131 : :
132 : 60 : static inline void PosixMessageQueueBuffer_CleanupAtIndex(size_t index, void* context)
133 : : {
134 : : (void) context;
135 : 60 : SolidSyslogPosixMessageQueueBuffer_Cleanup(&PosixMessageQueueBuffer_Pool[index].Base);
136 : 60 : }
|