F´ Flight Software - C/C++ Documentation devel
A framework for building embedded system applications to NASA flight quality standards.
Loading...
Searching...
No Matches
BufferAccumulator.cpp
Go to the documentation of this file.
1// ======================================================================
2// \title BufferAccumulator.cpp
3// \author bocchino
4// \brief BufferAccumulator implementation
5//
6// \copyright
7// Copyright (C) 2017 California Institute of Technology.
8// ALL RIGHTS RESERVED. United States Government Sponsorship
9// acknowledged.
10//
11// ======================================================================
12
14
15#include <sys/time.h>
16
18
19
20namespace Svc {
21
22// ----------------------------------------------------------------------
23// Construction, initialization, and destruction
24// ----------------------------------------------------------------------
25
26BufferAccumulator ::
27 BufferAccumulator(const char* const compName)
29 m_mode(BufferAccumulator_OpState::ACCUMULATE),
30 m_bufferMemory(nullptr),
31 m_bufferQueue(),
32 m_send(false),
33 m_waitForBuffer(false),
34 m_numWarnings(0u),
35 m_numDrained(0u),
36 m_numToDrain(0u),
37 m_opCode(),
38 m_cmdSeq(0u),
39 m_allocatorId(0) {
40}
41
42void BufferAccumulator ::init(const NATIVE_INT_TYPE queueDepth,
43 const NATIVE_INT_TYPE instance) {
44 BufferAccumulatorComponentBase::init(queueDepth, instance);
45}
46
47BufferAccumulator ::~BufferAccumulator() {}
48
49// ----------------------------------------------------------------------
50// Public methods
51// ----------------------------------------------------------------------
52
53void BufferAccumulator ::allocateQueue(
54 NATIVE_INT_TYPE identifier, Fw::MemAllocator& allocator,
55 NATIVE_UINT_TYPE maxNumBuffers
56) {
57
58 this->m_allocatorId = identifier;
59 NATIVE_UINT_TYPE memSize = sizeof(Fw::Buffer) * maxNumBuffers;
60 bool recoverable = false;
61 this->m_bufferMemory = static_cast<Fw::Buffer*>(
62 allocator.allocate(identifier, memSize, recoverable));
63 //TODO: Fail gracefully here
64 m_bufferQueue.init(this->m_bufferMemory, maxNumBuffers);
65}
66
67void BufferAccumulator ::deallocateQueue(Fw::MemAllocator& allocator) {
68 allocator.deallocate(this->m_allocatorId, this->m_bufferMemory);
69}
70
71// ----------------------------------------------------------------------
72// Handler implementations for user-defined typed input ports
73// ----------------------------------------------------------------------
74
75void BufferAccumulator ::bufferSendInFill_handler(const NATIVE_INT_TYPE portNum,
76 Fw::Buffer& buffer) {
77
78 const bool status = this->m_bufferQueue.enqueue(buffer);
79 if (status) {
80 if (this->m_numWarnings > 0) {
81 this->log_ACTIVITY_HI_BA_BufferAccepted();
82 }
83 this->m_numWarnings = 0;
84 } else {
85 if (this->m_numWarnings == 0) {
86 this->log_WARNING_HI_BA_QueueFull();
87 }
88 m_numWarnings++;
89 }
90 if (this->m_send) {
91 this->sendStoredBuffer();
92 }
93
94 this->tlmWrite_BA_NumQueuedBuffers(this->m_bufferQueue.getSize());
95}
96
97void BufferAccumulator ::bufferSendInReturn_handler(
98 const NATIVE_INT_TYPE portNum, Fw::Buffer& buffer) {
99
100 this->bufferSendOutReturn_out(0, buffer);
101 this->m_waitForBuffer = false;
102 if ((this->m_mode == BufferAccumulator_OpState::DRAIN) || // we are draining ALL buffers
103 (this->m_numDrained < this->m_numToDrain)) { // OR we aren't done draining some buffers
104 // in a partial drain
105 this->m_send = true;
106 this->sendStoredBuffer();
107 }
108}
109
110void BufferAccumulator ::pingIn_handler(const NATIVE_INT_TYPE portNum,
111 U32 key) {
112 this->pingOut_out(0, key);
113}
114
115// ----------------------------------------------------------------------
116// Command handler implementations
117// ----------------------------------------------------------------------
118
119void BufferAccumulator ::BA_SetMode_cmdHandler(const FwOpcodeType opCode,
120 const U32 cmdSeq,
121 BufferAccumulator_OpState mode) {
122
123 // cancel an in-progress partial drain
124 if (this->m_numToDrain > 0) {
125 // reset counters for partial buffer drain
126 this->m_numToDrain = 0;
127 this->m_numDrained = 0;
128 // respond to the original command
129 this->cmdResponse_out(this->m_opCode, this->m_cmdSeq, Fw::CmdResponse::OK);
130 }
131
132 this->m_mode = mode;
134 if (!this->m_waitForBuffer) {
135 this->m_send = true;
136 this->sendStoredBuffer();
137 }
138 } else {
139 this->m_send = false;
140 }
141 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
142}
143
144void BufferAccumulator ::BA_DrainBuffers_cmdHandler(
145 const FwOpcodeType opCode, const U32 cmdSeq, U32 numToDrain,
146 BufferAccumulator_BlockMode blockMode) {
147
148 if (this->m_numDrained < this->m_numToDrain) {
149 this->log_WARNING_HI_BA_StillDraining(this->m_numDrained, this->m_numToDrain);
150 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::BUSY);
151 return;
152 }
153
154 if (this->m_mode == BufferAccumulator_OpState::DRAIN) {
155 this->log_WARNING_HI_BA_AlreadyDraining();
156 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
157 return;
158 }
159
160 if (numToDrain == 0) {
161 this->log_ACTIVITY_HI_BA_PartialDrainDone(0);
162 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
163 return;
164 }
165
166 this->m_opCode = opCode;
167 this->m_cmdSeq = cmdSeq;
168 this->m_numDrained = 0;
169 this->m_numToDrain = numToDrain;
170
171 if (blockMode == BufferAccumulator_BlockMode::NOBLOCK) {
172 U32 numBuffers = this->m_bufferQueue.getSize();
173
174 if (numBuffers < numToDrain) {
175 this->m_numToDrain = numBuffers;
176 this->log_WARNING_LO_BA_NonBlockDrain(this->m_numToDrain, numToDrain);
177 }
178
179 /* OK if there were 0 buffers queued, and we
180 * end up setting numToDrain to 0
181 */
182 if (0 == this->m_numToDrain) {
183 this->log_ACTIVITY_HI_BA_PartialDrainDone(0);
184 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
185 return;
186 }
187 }
188
189 // We are still waiting for a buffer from last time
190 if (!this->m_waitForBuffer) {
191 this->m_send = true;
192 this->sendStoredBuffer(); // kick off the draining;
193 }
194}
195
196// ----------------------------------------------------------------------
197// Private helper methods
198// ----------------------------------------------------------------------
199
200void BufferAccumulator ::sendStoredBuffer() {
201
202 FW_ASSERT(this->m_send);
203 Fw::Buffer buffer;
204 if ((this->m_numToDrain == 0) || // we are draining ALL buffers
205 (this->m_numDrained < this->m_numToDrain)) { // OR we aren't done draining some buffers in a
206 // partial drain
207 const bool status = this->m_bufferQueue.dequeue(buffer);
208 if (status) { // a buffer was dequeued
209 this->m_numDrained++;
210 this->bufferSendOutDrain_out(0, buffer);
211 this->m_waitForBuffer = true;
212 this->m_send = false;
213 } else if (this->m_numToDrain > 0) {
214 this->log_WARNING_HI_BA_DrainStalled(this->m_numDrained, this->m_numToDrain);
215 }
216 }
217
218 /* This used to be "else if", but then you wait for all
219 * drained buffers in a partial drain to be RETURNED before returning OK.
220 * Correct thing is to return OK once they are SENT
221 */
222 if ((this->m_numToDrain > 0) && // we are doing a partial drain
223 (this->m_numDrained == this->m_numToDrain)) { // AND we just finished draining
224 //
225 this->log_ACTIVITY_HI_BA_PartialDrainDone(this->m_numDrained);
226 // reset counters for partial buffer drain
227 this->m_numToDrain = 0;
228 this->m_numDrained = 0;
229 this->m_send = false;
230 this->cmdResponse_out(this->m_opCode, this->m_cmdSeq, Fw::CmdResponse::OK);
231 }
232
233 this->tlmWrite_BA_NumQueuedBuffers(this->m_bufferQueue.getSize());
234}
235
236} // namespace Svc
#define FW_ASSERT(...)
Definition Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition BasicTypes.h:51
PlatformUIntType NATIVE_UINT_TYPE
Definition BasicTypes.h:52
C++ header for working with basic fprime types.
U32 FwOpcodeType
Definition FpConfig.h:56
@ VALIDATION_ERROR
Command failed validation.
@ OK
Command successfully executed.
@ BUSY
Component busy.
virtual void * allocate(const NATIVE_UINT_TYPE identifier, NATIVE_UINT_TYPE &size, bool &recoverable)=0
Allocate memory.
virtual void deallocate(const NATIVE_UINT_TYPE identifier, void *ptr)=0
Deallocate memory.
void init()
Object initializer.
Definition ObjBase.cpp:27
Auto-generated base for BufferAccumulator component.