Solaris Software
Loading...
Searching...
No Matches
pubsub.c
Go to the documentation of this file.
1/**
2 * @file pubsub.c
3 * @brief Priority-aware publish-subscribe packet router implementation.
4 */
5
8#include "spp/util/macros.h"
10#include "spp/core/commonbit.h"
11#include "spp/services/kpid.h"
12
13
14//TODO: Tener una forma de guardar los data packets que te llegan
15// Una forma de distribuir ese data packet por consumidores prioritarios
16// Devolver el datapacketal bank
17/* ----------------------------------------------------------------
18 * CONSTANTS
19 * ---------------------------------------------------------------- */
27
35
40
45
46static volatile spp_bool_t s_producerReady = false;
47
48/* ----------------------------------------------------------------
49 * STATIC FUNCTIONS DECLARATIONS
50 * ---------------------------------------------------------------- */
51static void SPP_SERVICES_PUBSUB_sendToMailbox(void);
52static void SPP_SERVICES_PUBSUB_sortConsumers(void);
53
54/* ----------------------------------------------------------------
55* PUBLIC FUNCTIONS
56* ---------------------------------------------------------------- */
57
59 SPP_Kpid_t *p_assignedKpid)
60{
62 if (p_producerData == NULL || p_assignedKpid == NULL)
63 {
65 }
67 {
69 }
70 else
71 {
73
75
77 /*
78 * First bit reserved to logs, second bit reserved for the FSM
79 * with s_registeredProducers = 0 -> producer 0: 0000 0100
80 * with s_registeredProducers = 1 -> producer 1: 0000 1000
81 *
82 * Then u can do an OR:
83 * producer[X].kpid.value | producer[Y].kpid.value
84 */
85
86 *p_assignedKpid = s_producers[s_registeredProducers].kpid;
88
89 ret = K_SPP_OK;
90 }
91 return ret;
92}
93
95 SPP_Kpid_t subscription)
96{
98 if (p_consumerData == NULL)
99 {
101 }
103 {
105 }
106 else
107 {
111
112
114 ret = K_SPP_OK;
115 }
116 return ret;
117}
118
120{
121 s_producerReady = false;
122 for (spp_uint8_t i = 0U; i < s_registeredProducers; i++)
123 {
124 (void)s_producers[i].p_contract->acquireData(s_producers[i].kpid);
125 }
126}
127
129{
131
132 if (p_pkt == NULL)
133 {
135 }
136
138 {
139 ret = K_SPP_ERROR;
140 }
141 else
142 {
146 }
147
149 return ret;
150}
151
153{
154 // Sends the received data via de publish to the consumer mailbox
156 for (spp_uint8_t j = 0U; j < s_registeredConsumers; j++)
157 {
158 if (s_consumers[j].p_contract->consumeData == NULL)
159 {
160 continue;
161 }
162 /* Preempt lower-priority consumers if a producer has new data pending. */
163 if (s_producerReady && (s_consumers[j].p_contract->priority > K_SPP_SERVICES_PUBSUB_PREEMPT_PRIORITY))
164 {
165 s_producerReady = false;
166 break;
167 }
168 (void)s_consumers[j].p_contract->consumeData(NULL);
169 }
170}
171
176
181
183{
184 spp_uint8_t failedConsumers = 0U;
185 spp_uint8_t failedProducers = 0U;
186
188
189 for (spp_uint8_t i = 0U; i < s_registeredConsumers; i++)
190 {
192 if (s_consumers[i].initResult != K_SPP_OK)
193 {
194 failedConsumers++;
195 }
196 }
197
198 for (spp_uint8_t i = 0U; i < s_registeredProducers; i++)
199 {
201 if (s_producers[i].initResult != K_SPP_OK)
202 {
203 failedProducers++;
204 }
205 }
206
207 if ((s_registeredConsumers > 0U) && (failedConsumers == s_registeredConsumers))
208 {
209 return K_SPP_ERROR;
210 }
211
212 if ((s_registeredProducers > 0U) && (failedProducers == s_registeredProducers))
213 {
214 return K_SPP_ERROR;
215 }
216
217 return K_SPP_OK;
218}
219
221 SPP_RetVal_t *p_initResult)
222{
223 if (p_producerData == NULL || p_initResult == NULL)
224 {
226 }
227
228 for (spp_uint8_t i = 0; i < s_registeredProducers; i++)
229 {
230 if (p_producerData == s_producers[i].p_contract)
231 {
232 *p_initResult = s_producers[i].initResult;
233 return K_SPP_OK;
234 }
235 }
236 return K_SPP_ERROR;
237}
238
240 SPP_RetVal_t *p_initResult)
241{
242 if (p_consumerData == NULL || p_initResult == NULL)
243 {
245 }
246
247 for (spp_uint8_t i = 0; i < s_registeredConsumers; i++)
248 {
249 if (p_consumerData == s_consumers[i].p_contract)
250 {
251 *p_initResult = s_consumers[i].initResult;
252 return K_SPP_OK;
253 }
254 }
255 return K_SPP_ERROR;
256}
257
258/* ----------------------------------------------------------------
259 * STATIC FUNCTIONS
260 * ---------------------------------------------------------------- */
261/**
262 * @brief Copies each buffered packet to every consumer whose APID subscription matches,
263 * then resets the internal FIFO (head, tail and count back to zero).
264 *
265 * Iterates the circular packet buffer from head to head+count. For each packet
266 * it walks the registered consumer list and performs a bitmask check on
267 * @c suscribeToApid vs @c primaryHeader.apid. On a match the full
268 * @ref SPP_Packet_t is copied by value into the consumer's @c p_mailBox.
269 * When all consumers have been served the buffer is cleared.
270 */
272{
273 if (s_bufferCount == 0U)
274 {
275 return;
276 }
278 for (spp_uint8_t j = 0U; j < s_registeredConsumers; j++)
279 {
280 if (s_consumers[j].p_contract->deliverToMailbox == NULL)
281 {
282 continue;
283 }
284 if ((s_consumers[j].subcription.value & packet.primaryHeader.apid) == 0U)
285 {
286 continue;
287 }
288 (void)s_consumers[j].p_contract->deliverToMailbox(packet);
289 }
292}
293
294/**
295 * @brief Sorts the registered consumer array in ascending priority order using
296 * insertion sort. Stable — consumers with equal priority retain their
297 * registration order. Called once during init before any dispatch.
298 */
299
SPP_RetVal_t SPP_SERVICES_DATABANK_returnPacket(SPP_Packet_t *p_packet)
Return a packet to the pool after processing.
Definition databank.c:64
Static packet pool manager.
APID bitmask assignments for every SPP producer.
SPP logging service.
Compile-time configuration flags and utility macros for SPP.
SPP_Packet_t
Definition packet.h:79
static spp_uint8_t s_bufferCount
Definition pubsub.c:44
SPP_RetVal_t SPP_SERVICES_PUBSUB_getConsumerInitResult(const SPP_SERVICE_ConsumerContract_t *p_consumerData, SPP_RetVal_t *p_initResult)
Definition pubsub.c:239
void SPP_SERVICES_PUBSUB_signalProducerReady(void)
Signals that a producer has new data pending.
Definition pubsub.c:177
void SPP_SERVICES_PUBSUB_callConsumers(void)
Routes all buffered packets to matching consumer mailboxes, then clears the buffer.
Definition pubsub.c:152
SPP_RetVal_t SPP_SERVICES_PUBSUB_init(void)
Definition pubsub.c:182
static SPP_SERVICES_PUBSUB_Producer_t s_producers[K_SPP_SERVICES_PUBSUB_MAX_PRODUCERS]
Definition pubsub.c:36
spp_uint8_t SPP_SERVICES_PUBSUB_queueDepth(void)
Returns the number of packets currently held in the internal FIFO buffer.
Definition pubsub.c:172
static SPP_Packet_t s_packetBuffer[K_SPP_SERVICES_PUBSUB_BUFFER_SIZE]
Definition pubsub.c:41
static SPP_SERVICES_PUBSUB_Consumer_t s_consumers[K_SPP_SERVICES_PUBSUB_MAX_CONSUMERS]
Definition pubsub.c:38
void SPP_SERVICES_PUBSUB_callProducers(void)
Calls acquireData on every registered producer.
Definition pubsub.c:119
SPP_RetVal_t SPP_SERVICES_PUBSUB_getProducerInitResult(const SPP_SERVICE_ProducerContract_t *p_producerData, SPP_RetVal_t *p_initResult)
Definition pubsub.c:220
static void SPP_SERVICES_PUBSUB_sendToMailbox(void)
Copies each buffered packet to every consumer whose APID subscription matches, then resets the intern...
Definition pubsub.c:271
SPP_RetVal_t SPP_SERVICES_PUBSUB_registerProducer(const SPP_SERVICE_ProducerContract_t *p_producerData, SPP_Kpid_t *p_assignedKpid)
Definition pubsub.c:58
static volatile spp_bool_t s_producerReady
Definition pubsub.c:46
static spp_uint8_t s_registeredConsumers
Definition pubsub.c:39
SPP_RetVal_t SPP_SERVICES_PUBSUB_publish(SPP_Packet_t *p_pkt)
Copies a packet into the internal buffer and returns it to the databank.
Definition pubsub.c:128
SPP_RetVal_t SPP_SERVICES_PUBSUB_registerConsumer(const SPP_SERVICE_ConsumerContract_t *p_consumerData, SPP_Kpid_t subscription)
Definition pubsub.c:94
static spp_uint16_t s_registeredProducers
Definition pubsub.c:37
static spp_uint8_t s_bufferTail
Definition pubsub.c:43
static spp_uint8_t s_bufferHead
Definition pubsub.c:42
static void SPP_SERVICES_PUBSUB_sortConsumers(void)
Sorts the registered consumer array in ascending priority order using insertion sort....
Definition pubsub.c:300
Publish-subscribe packet router.
#define K_SPP_SERVICES_PUBSUB_STEP
Definition pubsub.h:24
#define K_SPP_SERVICES_PUBSUB_BUFFER_SIZE
Definition pubsub.h:21
#define K_SPP_SERVICES_PUBSUB_MAX_CONSUMERS
Definition pubsub.h:20
#define K_SPP_SERVICES_PUBSUB_PREEMPT_PRIORITY
Definition pubsub.h:22
#define K_SPP_SERVICES_PUBSUB_MAX_PRODUCERS
Definition pubsub.h:19
#define K_SPP_SERVICES_PUBSUB_SORT_START_INDEX
Definition pubsub.h:25
#define K_SPP_SERVICES_PUBSUB_ZERO_INDEX
Definition pubsub.h:27
#define K_SPP_SERVICES_PUBSUB_OFFSET
Definition pubsub.h:26
SPP_RetVal_t
Unified return type for all SPP API functions.
Definition returnTypes.h:24
@ K_SPP_ERROR_NOT_INITIALIZED
Definition returnTypes.h:31
@ K_SPP_OK
Definition returnTypes.h:25
@ K_SPP_ERROR
Definition returnTypes.h:26
@ K_SPP_ERROR_REGISTRY_FULL
Definition returnTypes.h:36
@ K_SPP_ERROR_NULL_POINTER
Definition returnTypes.h:30
const SPP_SERVICE_ConsumerContract_t * p_contract
Definition pubsub.c:30
const SPP_SERVICE_ProducerContract_t * p_contract
Definition pubsub.c:22
Describes the contract of a consumer module. This module needs to have:
Definition service.h:43
SPP_RetVal_t(*) init()
Definition service.h:48
Describes the contract of a producer module. This module needs to have:
Definition service.h:28
SPP_RetVal_t(*) init()
Definition service.h:31
uint16_t spp_uint16_t
Definition types.h:29
int8_t spp_int8_t
Definition types.h:28
uint8_t spp_uint8_t
Definition types.h:27
bool spp_bool_t
Definition types.h:36
spp_uint16_t value
Definition kpid.h:25