Abstraction of message queue message and command message #106

Closed
opened 2020-06-15 10:05:41 +02:00 by muellerr · 1 comment
Owner

To support variable sized packets and different kind of command messages, I suggest changes to the way message queues are used. These changes achieve dependency inversion by making the message queue implementation depending on an abstraction instead of a concrete implementation but this comes at a price: More size checking is required. Advantages are that message queue messages are not fixed to 24 bytes. I think this could be useful for certain cases and make the message queue code more generic and flexible (comes at a price, of course..).

This basically includes following changes:

New MessageQueueMessageIF

Interface for the class which holds the actual data of the message (has an internal buffer). It has following abstract functions, which are used by the the message queue implementations.

virtual void clear() = 0;

virtual const uint8_t* getBuffer() const = 0

virtual uint8_t* getBuffer() = 0

virtual void setSender(MessageQueueId_t setId) = 0

virtual MessageQueueId_t getSender() const = 0

virtual const uint8_t* getData() const = 0

virtual uint8_t* getData() = 0

virtual size_t getMinimumMessageSize() const = 0

virtual size_t getMessageSize() const = 0

virtual void setMessageSize(size_t messageSize) = 0

virtual size_t getMaximumMessageSize() const = 0

MessageQueueMessage implements all the functions above and a few more (like print).
NO_QUEUE value is 0xffffffff now (Of course, could also be 0, but I think this would be a more fitting value of an invalid value). While trying this out, I found out that some places in the code, the hardcoded number 0 was used to initialize queue IDs instead of NO_QUEUE, I replaced those where I found them.
All MessageQueue implementations take a MQM IF pointer instead of a concrete MQM pointer now
and can perform size checking by calling the interface functions. This enables new message types which can have more or less than 24 bytes (but the default MQM message will still have 24 bytes).

Of course, new size checks are required for the message queue implementations: The maximum message size has to be checked against the message queue size (which is cached by the constructor) before a message is sent.

Interesting ways this could be used: If the size of a message which is passed between objects is fixed at for example 32 bytes, a message queue could be used instead of the IPC store to exchange the data in form of messages instead of using the IPC store. Of course, for variable sized data or for huge data blocks, it propably would be better to use the IPC store, but maybe an informative comment in MQM IF would be good for that.

New CommandMessageIF

Interface for command messages. Header gets 2 additional bytes for command ID.
Minimal size is size of header (6).
Implements MQM IF to allow passing command messages directly. Holds a pointer to the message holding the actual data. The ctor of the command message implementation has to check the maximum size against the minimum size of the message queue message (something I don't like but becomes necessary).

virtual Command_t getCommand() const = 0

virtual uint8_t getMessageType() const = 0

virtual void setReplyRejected(ReturnValue_t reason, Command_t initialCommand) = 0

virtual ReturnValue_t getReplyRejectedReason(Command_t* initialCommand = nullptr) const = 0;

virtual MessageQueueMessageIF* getInternalMessage() const = 0

New CommandMessageBase

Base class for command messages, which implements all common functions to avoid boilerplate code. Minimal size is CommandMessageIF header (6) + space required to set rejected reply (4), so 10 bytes total.

New CommandMessageCleaner

Extraction of clean-up code into separate class. Dynamic dispatch is used to differentiate between the clean() operation of a MQM (set all bytes to 0) or a command message (look up whether special cleanup needs to be performed).

CommandMessage

The command message now only offers the functions getParameter / setParameter 1/2 and setUnknownReply (although this could propably be moved to base too..). The rest is provided by CommandMessageBase (it implements CommandMessageBase)

HousekeepingMessage

Another form of a command message, implements command message base. Offers get/setSid (for 64 bit SID consisting of object and set ID) and one uint32_t parameter (for example for float collection interval).

To support variable sized packets and different kind of command messages, I suggest changes to the way message queues are used. These changes achieve dependency inversion by making the message queue implementation depending on an abstraction instead of a concrete implementation but this comes at a price: More size checking is required. Advantages are that message queue messages are not fixed to 24 bytes. I think this could be useful for certain cases and make the message queue code more generic and flexible (comes at a price, of course..). This basically includes following changes: ### New `MessageQueueMessageIF` Interface for the class which holds the actual data of the message (has an internal buffer). It has following abstract functions, which are used by the the message queue implementations. `virtual void clear() = 0;` <br> `virtual const uint8_t* getBuffer() const = 0` <br> `virtual uint8_t* getBuffer() = 0` <br> `virtual void setSender(MessageQueueId_t setId) = 0` <br> `virtual MessageQueueId_t getSender() const = 0` <br> `virtual const uint8_t* getData() const = 0` <br> `virtual uint8_t* getData() = 0` <br> `virtual size_t getMinimumMessageSize() const = 0` <br> `virtual size_t getMessageSize() const = 0` <br> `virtual void setMessageSize(size_t messageSize) = 0` <br> `virtual size_t getMaximumMessageSize() const = 0` <br> MessageQueueMessage implements all the functions above and a few more (like `print`). `NO_QUEUE` value is 0xffffffff now (Of course, could also be 0, but I think this would be a more fitting value of an invalid value). While trying this out, I found out that some places in the code, the hardcoded number 0 was used to initialize queue IDs instead of `NO_QUEUE`, I replaced those where I found them. All MessageQueue implementations take a MQM IF pointer instead of a concrete MQM pointer now and can perform size checking by calling the interface functions. This enables new message types which can have more or less than 24 bytes (but the default MQM message will still have 24 bytes). Of course, new size checks are required for the message queue implementations: The maximum message size has to be checked against the message queue size (which is cached by the constructor) before a message is sent. Interesting ways this could be used: If the size of a message which is passed between objects is fixed at for example 32 bytes, a message queue could be used instead of the IPC store to exchange the data in form of messages instead of using the IPC store. Of course, for variable sized data or for huge data blocks, it propably would be better to use the IPC store, but maybe an informative comment in MQM IF would be good for that. ### New `CommandMessageIF` Interface for command messages. Header gets 2 additional bytes for command ID. Minimal size is size of header (6). Implements MQM IF to allow passing command messages directly. Holds a pointer to the message holding the actual data. The ctor of the command message implementation has to check the maximum size against the minimum size of the message queue message (something I don't like but becomes necessary). `virtual Command_t getCommand() const = 0` <br> `virtual uint8_t getMessageType() const = 0` <br> `virtual void setReplyRejected(ReturnValue_t reason, Command_t initialCommand) = 0` <br> `virtual ReturnValue_t getReplyRejectedReason(Command_t* initialCommand = nullptr) const = 0;` <br> `virtual MessageQueueMessageIF* getInternalMessage() const = 0` <br> ### New `CommandMessageBase` Base class for command messages, which implements all common functions to avoid boilerplate code. Minimal size is CommandMessageIF header (6) + space required to set rejected reply (4), so 10 bytes total. ### New `CommandMessageCleaner` Extraction of clean-up code into separate class. Dynamic dispatch is used to differentiate between the clean() operation of a MQM (set all bytes to 0) or a command message (look up whether special cleanup needs to be performed). ### CommandMessage The command message now only offers the functions getParameter / setParameter 1/2 and setUnknownReply (although this could propably be moved to base too..). The rest is provided by CommandMessageBase (it implements CommandMessageBase) ### HousekeepingMessage Another form of a command message, implements command message base. Offers get/setSid (for 64 bit SID consisting of object and set ID) and one uint32_t parameter (for example for float collection interval).
muellerr added the
feature
API Change
labels 2020-06-15 10:05:41 +02:00
muellerr changed title from Abstraction of message queue to Abstraction of message queue message 2020-06-15 10:08:45 +02:00
muellerr changed title from Abstraction of message queue message to Abstraction of message queue message and command message 2020-06-15 10:11:36 +02:00
Author
Owner

UPDATE:

After discussions and some thinking I scrapped the CommandMessageBase.
The command message will now expose more parameters (for example with a new getParameter3() function), which should be enough for housekeeping messages, which then can be implemented like other command messages.

The CommandMessageIF might still have its uses and I still think the MessageQueueMessageIF would be a nice feature.

UPDATE: After discussions and some thinking I scrapped the CommandMessageBase. The command message will now expose more parameters (for example with a new `getParameter3()` function), which should be enough for housekeeping messages, which then can be implemented like other command messages. The CommandMessageIF might still have its uses and I still think the MessageQueueMessageIF would be a nice feature.
Sign in to join this conversation.
No Milestone
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: fsfw/fsfw#106
No description provided.