2021-07-13 20:22:54 +02:00
|
|
|
#include "fsfw/fdir/FailureIsolationBase.h"
|
2022-02-02 10:29:30 +01:00
|
|
|
|
|
|
|
#include "fsfw/events/EventManagerIF.h"
|
2021-07-13 20:22:54 +02:00
|
|
|
#include "fsfw/health/HasHealthIF.h"
|
|
|
|
#include "fsfw/health/HealthMessage.h"
|
|
|
|
#include "fsfw/ipc/QueueFactory.h"
|
|
|
|
#include "fsfw/objectmanager/ObjectManager.h"
|
2018-07-12 16:29:32 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
|
|
|
|
uint8_t messageDepth, uint8_t parameterDomainBase)
|
|
|
|
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
|
|
|
|
eventQueue =
|
|
|
|
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
FailureIsolationBase::~FailureIsolationBase() {
|
2022-06-05 12:52:55 +02:00
|
|
|
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
2022-06-06 11:55:42 +02:00
|
|
|
if (manager == nullptr) {
|
2022-06-05 12:52:55 +02:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-06-06 11:55:42 +02:00
|
|
|
sif::error << "FailureIsolationBase::~FailureIsolationBase: Event Manager has not"
|
|
|
|
" been initialized!"
|
|
|
|
<< std::endl;
|
2022-06-05 12:52:55 +02:00
|
|
|
#endif
|
2022-06-06 11:55:42 +02:00
|
|
|
return;
|
|
|
|
}
|
2022-06-05 12:52:55 +02:00
|
|
|
manager->unsubscribeFromAllEvents(eventQueue->getId(), ownerId);
|
2022-06-06 11:55:42 +02:00
|
|
|
QueueFactory::instance()->deleteMessageQueue(eventQueue);
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
ReturnValue_t FailureIsolationBase::initialize() {
|
2022-02-02 10:29:30 +01:00
|
|
|
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
|
|
|
if (manager == nullptr) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::error << "FailureIsolationBase::initialize: Event Manager has not"
|
|
|
|
" been initialized!"
|
|
|
|
<< std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
ReturnValue_t result = manager->registerListener(eventQueue->getId());
|
2022-08-16 01:08:26 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if (ownerId != objects::NO_OBJECT) {
|
|
|
|
result = manager->subscribeToAllEventsFrom(eventQueue->getId(), ownerId);
|
2022-08-16 01:08:26 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
owner = ObjectManager::instance()->get<HasHealthIF>(ownerId);
|
|
|
|
if (owner == nullptr) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::error << "FailureIsolationBase::intialize: Owner object "
|
|
|
|
"invalid. Make sure it implements HasHealthIF"
|
|
|
|
<< std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2022-02-02 10:29:30 +01:00
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (faultTreeParent != objects::NO_OBJECT) {
|
|
|
|
ConfirmsFailuresIF* parentIF =
|
|
|
|
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
|
|
|
|
if (parentIF == nullptr) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::error << "FailureIsolationBase::intialize: Parent object"
|
|
|
|
<< "invalid." << std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2022-02-02 10:29:30 +01:00
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
eventQueue->setDefaultDestination(parentIF->getEventReceptionQueue());
|
|
|
|
}
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::OK;
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
void FailureIsolationBase::checkForFailures() {
|
2022-02-02 10:29:30 +01:00
|
|
|
EventMessage event;
|
2022-08-16 01:08:26 +02:00
|
|
|
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK;
|
2022-02-02 10:29:30 +01:00
|
|
|
result = eventQueue->receiveMessage(&event)) {
|
|
|
|
if (event.getSender() == eventQueue->getId()) {
|
|
|
|
// We already got this event, because we sent it.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch (event.getMessageId()) {
|
|
|
|
case EventMessage::EVENT_MESSAGE:
|
|
|
|
if (isFdirDisabledForSeverity(event.getSeverity())) {
|
|
|
|
// We do not handle events when disabled.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
eventReceived(&event);
|
|
|
|
break;
|
|
|
|
case EventMessage::CONFIRMATION_REQUEST:
|
|
|
|
doConfirmFault(&event);
|
|
|
|
break;
|
|
|
|
case EventMessage::YOUR_FAULT:
|
|
|
|
eventConfirmed(&event);
|
|
|
|
break;
|
|
|
|
case EventMessage::MY_FAULT:
|
|
|
|
wasParentsFault(&event);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
decrementFaultCounters();
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
void FailureIsolationBase::setOwnerHealth(HasHealthIF::HealthState health) {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (owner != NULL) {
|
|
|
|
owner->setHealth(health);
|
|
|
|
}
|
|
|
|
// else: owner has no health.
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
MessageQueueId_t FailureIsolationBase::getEventReceptionQueue() { return eventQueue->getId(); }
|
2016-06-15 23:48:41 +02:00
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
ReturnValue_t FailureIsolationBase::sendConfirmationRequest(EventMessage* event,
|
2022-02-02 10:29:30 +01:00
|
|
|
MessageQueueId_t destination) {
|
|
|
|
event->setMessageId(EventMessage::CONFIRMATION_REQUEST);
|
|
|
|
if (destination != MessageQueueIF::NO_QUEUE) {
|
|
|
|
return eventQueue->sendMessage(destination, event);
|
|
|
|
} else if (faultTreeParent != objects::NO_OBJECT) {
|
|
|
|
return eventQueue->sendToDefault(event);
|
|
|
|
}
|
2022-08-16 01:08:26 +02:00
|
|
|
return returnvalue::FAILED;
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
void FailureIsolationBase::eventConfirmed(EventMessage* event) {}
|
2016-06-15 23:48:41 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
void FailureIsolationBase::wasParentsFault(EventMessage* event) {}
|
2016-06-15 23:48:41 +02:00
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
void FailureIsolationBase::doConfirmFault(EventMessage* event) {
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t result = confirmFault(event);
|
|
|
|
if (result == YOUR_FAULT) {
|
|
|
|
event->setMessageId(EventMessage::YOUR_FAULT);
|
|
|
|
eventQueue->reply(event);
|
|
|
|
} else if (result == MY_FAULT) {
|
|
|
|
event->setMessageId(EventMessage::MY_FAULT);
|
|
|
|
eventQueue->reply(event);
|
|
|
|
} else {
|
|
|
|
}
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t FailureIsolationBase::confirmFault(EventMessage* event) { return YOUR_FAULT; }
|
|
|
|
|
|
|
|
void FailureIsolationBase::triggerEvent(Event event, uint32_t parameter1, uint32_t parameter2) {
|
|
|
|
// With this mechanism, all events are disabled for a certain device.
|
|
|
|
// That's not so good for visibility.
|
|
|
|
if (isFdirDisabledForSeverity(event::getSeverity(event))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
EventMessage message(event, ownerId, parameter1, parameter2);
|
|
|
|
EventManagerIF::triggerEvent(&message, eventQueue->getId());
|
|
|
|
eventReceived(&message);
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
bool FailureIsolationBase::isFdirDisabledForSeverity(EventSeverity_t severity) {
|
2022-02-02 10:29:30 +01:00
|
|
|
if ((owner != NULL) && (severity != severity::INFO)) {
|
|
|
|
if (owner->getHealth() == HasHealthIF::EXTERNAL_CONTROL) {
|
|
|
|
// External control disables handling of fault messages.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
void FailureIsolationBase::throwFdirEvent(Event event, uint32_t parameter1, uint32_t parameter2) {
|
|
|
|
EventMessage message(event, ownerId, parameter1, parameter2);
|
|
|
|
EventManagerIF::triggerEvent(&message, eventQueue->getId());
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|