| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ====================================================================== | ||
| 2 | // \title ComAggregator.cpp | ||
| 3 | // \author lestarch | ||
| 4 | // \brief cpp file for ComAggregator component implementation class | ||
| 5 | // ====================================================================== | ||
| 6 | |||
| 7 | #include "Svc/ComAggregator/ComAggregator.hpp" | ||
| 8 | |||
| 9 | namespace Svc { | ||
| 10 | |||
| 11 | // ---------------------------------------------------------------------- | ||
| 12 | // Component construction and destruction | ||
| 13 | // ---------------------------------------------------------------------- | ||
| 14 | |||
| 15 | 10 | ComAggregator ::ComAggregator(const char* const compName) | |
| 16 | : ComAggregatorComponentBase(compName), | ||
| 17 | 10 | m_bufferState(Fw::Buffer::OwnershipState::OWNED), | |
| 18 |
1/1✓ Branch 6 taken 10 times.
|
10 | m_frameBuffer(m_frameBufferStore, sizeof(m_frameBufferStore)), |
| 19 |
1/1✓ Branch 7 taken 10 times.
|
10 | m_frameSerializer(m_frameBuffer.getSerializer()), |
| 20 |
2/2✓ Branch 10 taken 10 times.
✓ Branch 16 taken 10 times.
|
20 | m_allow_timeout(false) {} |
| 21 | |||
| 22 | 20 | ComAggregator ::~ComAggregator() {} | |
| 23 | |||
| 24 | 10 | void ComAggregator ::preamble() { | |
| 25 |
1/1✓ Branch 2 taken 10 times.
|
10 | Fw::Success good = Fw::Success::SUCCESS; |
| 26 |
1/1✓ Branch 5 taken 10 times.
|
10 | this->comStatusOut_out(0, good); |
| 27 | 20 | } | |
| 28 | |||
| 29 | // ---------------------------------------------------------------------- | ||
| 30 | // Handler implementations for typed input ports | ||
| 31 | // ---------------------------------------------------------------------- | ||
| 32 | |||
| 33 | 45 | void ComAggregator ::comStatusIn_handler(FwIndexType portNum, Fw::Success& condition) { | |
| 34 | 45 | this->aggregationMachine_sendSignal_status(condition); | |
| 35 | 45 | } | |
| 36 | |||
| 37 | 33 | void ComAggregator ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { | |
| 38 |
1/1✓ Branch 3 taken 33 times.
|
33 | Svc::ComDataContextPair pair(data, context); |
| 39 |
1/1✓ Branch 5 taken 33 times.
|
33 | this->aggregationMachine_sendSignal_fill(pair); |
| 40 | 66 | } | |
| 41 | |||
| 42 | 10 | void ComAggregator ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context) { | |
| 43 | // This handler runs on the returning caller's thread: take ownership atomically | ||
| 44 | 10 | const Fw::Buffer::OwnershipState previousState = this->m_bufferState.exchange(Fw::Buffer::OwnershipState::OWNED); | |
| 45 | 10 | FW_ASSERT(previousState == Fw::Buffer::OwnershipState::NOT_OWNED, static_cast<FwAssertArgType>(previousState)); | |
| 46 | 10 | } | |
| 47 | |||
| 48 | 35 | void ComAggregator ::timeout_handler(FwIndexType portNum, U32 context) { | |
| 49 | // Timeout is ignored in WAIT_STATUS state. However, the queue may not process timeout messages until the wait | ||
| 50 | // status is returned because the port chain may be synchronous and downstream components (radio, retry, etc) may | ||
| 51 | // take a long time to complete the transmission of data. This can cause the queue to overflow with messages that | ||
| 52 | // will soon be discarded. | ||
| 53 | // | ||
| 54 | // Therefore, to fix the risk of queue overflow we only queue timeout messages when they would be processed by the | ||
| 55 | // state machine (i.e. in the FILL state). Otherwise, these messages are not queued. | ||
| 56 | // | ||
| 57 | // Behaviorally, this solution will work exactly like the naive implementation with an infinite queue depth, but | ||
| 58 | // prevents queue overflow when using finite queues. | ||
| 59 |
2/2✓ Branch 4 taken 6 times.
✓ Branch 5 taken 29 times.
|
35 | if (this->m_allow_timeout) { |
| 60 | 6 | this->aggregationMachine_sendSignal_timeout(); | |
| 61 | } | ||
| 62 | 35 | } | |
| 63 | |||
| 64 | // ---------------------------------------------------------------------- | ||
| 65 | // Implementations for internal state machine actions | ||
| 66 | // ---------------------------------------------------------------------- | ||
| 67 | |||
| 68 | 20 | void ComAggregator ::Svc_AggregationMachine_action_doClear(SmId smId, Svc_AggregationMachine::Signal signal) { | |
| 69 | 20 | this->m_allow_timeout = true; // Allow timeout messages in FILL state | |
| 70 | 20 | this->m_frameSerializer.resetSer(); | |
| 71 | 20 | this->m_frameBuffer.setSize(sizeof(this->m_frameBufferStore)); | |
| 72 |
2/2✓ Branch 2 taken 20 times.
✓ Branch 11 taken 20 times.
|
20 | this->m_lastContext = ComCfg::FrameContext(); |
| 73 |
2/2✓ Branch 10 taken 5 times.
✓ Branch 11 taken 15 times.
|
20 | if (this->m_held.get_data().isValid()) { |
| 74 | // Fill the held data | ||
| 75 | 5 | this->Svc_AggregationMachine_action_doFill(smId, signal, this->m_held); | |
| 76 |
2/2✓ Branch 2 taken 5 times.
✓ Branch 11 taken 5 times.
|
5 | this->m_held = Svc::ComDataContextPair(); |
| 77 | } | ||
| 78 | 20 | } | |
| 79 | |||
| 80 | 33 | void ComAggregator ::Svc_AggregationMachine_action_doFill(SmId smId, | |
| 81 | Svc_AggregationMachine::Signal signal, | ||
| 82 | const Svc::ComDataContextPair& value) { | ||
| 83 |
1/1✓ Branch 6 taken 33 times.
|
66 | Fw::SerializeStatus status = this->m_frameSerializer.serializeFrom( |
| 84 |
2/2✓ Branch 15 taken 33 times.
✓ Branch 18 taken 33 times.
|
66 | value.get_data().getData(), value.get_data().getSize(), Fw::Serialization::OMIT_LENGTH); |
| 85 | 33 | FW_ASSERT(status == Fw::SerializeStatus::FW_SERIALIZE_OK); | |
| 86 |
1/1✓ Branch 10 taken 33 times.
|
33 | this->m_lastContext = value.get_context(); |
| 87 |
1/1✓ Branch 2 taken 33 times.
|
33 | Fw::Success good = Fw::Success::SUCCESS; |
| 88 | // Return port does not alter data and thus const-cast is safe | ||
| 89 |
1/1✓ Branch 14 taken 33 times.
|
33 | this->dataReturnOut_out(0, const_cast<Fw::Buffer&>(value.get_data()), value.get_context()); |
| 90 |
1/1✓ Branch 5 taken 33 times.
|
33 | this->comStatusOut_out(0, good); |
| 91 | 66 | } | |
| 92 | |||
| 93 | 10 | void ComAggregator ::Svc_AggregationMachine_action_doSend(SmId smId, Svc_AggregationMachine::Signal signal) { | |
| 94 | // Send only when the buffer will be valid | ||
| 95 |
1/2✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
|
10 | if (this->m_frameSerializer.getSize() > 0) { |
| 96 | const Fw::Buffer::OwnershipState previousState = | ||
| 97 | 10 | this->m_bufferState.exchange(Fw::Buffer::OwnershipState::NOT_OWNED); | |
| 98 | 10 | FW_ASSERT(previousState == Fw::Buffer::OwnershipState::OWNED, static_cast<FwAssertArgType>(previousState)); | |
| 99 | 10 | this->m_frameBuffer.setSize(this->m_frameSerializer.getSize()); | |
| 100 | 10 | this->m_allow_timeout = false; // Timeout messages should be discarded in WAIT_STATUS state | |
| 101 | 10 | this->dataOut_out(0, this->m_frameBuffer, this->m_lastContext); | |
| 102 | } | ||
| 103 | 10 | } | |
| 104 | |||
| 105 | 5 | void ComAggregator ::Svc_AggregationMachine_action_doHold(SmId smId, | |
| 106 | Svc_AggregationMachine::Signal signal, | ||
| 107 | const Svc::ComDataContextPair& value) { | ||
| 108 | 5 | FW_ASSERT(not this->m_held.get_data().isValid()); | |
| 109 | 5 | this->m_held = value; | |
| 110 | 5 | } | |
| 111 | |||
| 112 | ✗ | void ComAggregator ::Svc_AggregationMachine_action_assertNoStatus(SmId smId, Svc_AggregationMachine::Signal signal) { | |
| 113 | // Status is not possible in this state, confirm by assertion | ||
| 114 | ✗ | FW_ASSERT(false); | |
| 115 | ✗ | } | |
| 116 | |||
| 117 | // ---------------------------------------------------------------------- | ||
| 118 | // Implementations for internal state machine guards | ||
| 119 | // ---------------------------------------------------------------------- | ||
| 120 | |||
| 121 | 32 | bool ComAggregator ::Svc_AggregationMachine_guard_isFull(SmId smId, | |
| 122 | Svc_AggregationMachine::Signal signal, | ||
| 123 | const Svc::ComDataContextPair& value) const { | ||
| 124 | 32 | FW_ASSERT(value.get_data().getSize() <= ComCfg::AggregationSize); | |
| 125 | 32 | const FwSizeType remaining = this->m_frameSerializer.getCapacity() - this->m_frameSerializer.getSize(); | |
| 126 | 32 | return (remaining < value.get_data().getSize()); | |
| 127 | } | ||
| 128 | |||
| 129 | 28 | bool ComAggregator ::Svc_AggregationMachine_guard_willFill(SmId smId, | |
| 130 | Svc_AggregationMachine::Signal signal, | ||
| 131 | const Svc::ComDataContextPair& value) const { | ||
| 132 | 28 | FW_ASSERT(value.get_data().getSize() <= ComCfg::AggregationSize); | |
| 133 | 28 | const FwSizeType remaining = this->m_frameSerializer.getCapacity() - this->m_frameSerializer.getSize(); | |
| 134 | 28 | return (remaining == value.get_data().getSize()); | |
| 135 | } | ||
| 136 | |||
| 137 | 6 | bool ComAggregator ::Svc_AggregationMachine_guard_isNotEmpty(SmId smId, Svc_AggregationMachine::Signal signal) const { | |
| 138 | 6 | return this->m_frameSerializer.getSize() > 0; | |
| 139 | } | ||
| 140 | |||
| 141 | 45 | bool ComAggregator ::Svc_AggregationMachine_guard_isGood(SmId smId, | |
| 142 | Svc_AggregationMachine::Signal signal, | ||
| 143 | const Fw::Success& value) const { | ||
| 144 | 45 | return value == Fw::Success::SUCCESS; | |
| 145 | } | ||
| 146 | |||
| 147 | } // namespace Svc | ||
| 148 |