Compare commits
440 Commits
8f83f7becd
...
ASTP_1.0.0
Author | SHA1 | Date | |
---|---|---|---|
2f511523cb | |||
9f83739771 | |||
054de9781b | |||
20e7fe6cb1 | |||
f8cd8e1e7d | |||
818634755d | |||
87fee9bd0e | |||
6a40b8244d | |||
4fd443f70b | |||
06631d06a5
|
|||
9244a96e7b | |||
03ef63302b
|
|||
c50796b785 | |||
a0caa92a8a | |||
a91139be76 | |||
fee2ac0eb9 | |||
2878f21c93 | |||
4caf906d96 | |||
b38e9ede0c | |||
17b3672330 | |||
629814bc9b
|
|||
4fb792447e
|
|||
40dae8c961 | |||
9e1f3ee585 | |||
e851d8a46c | |||
0038c1dc53 | |||
1a3bb5bada | |||
0055d34d9a | |||
a2ba3181b9 | |||
864621ee37 | |||
54ff8f9341 | |||
e4efc01e34 | |||
c455fc1417 | |||
d792679d49 | |||
38a5e7e618 | |||
0c342ad7fc | |||
524e50a6dd | |||
17adb2cc3e | |||
7b29583f8f | |||
1af7870b15 | |||
1cbeb54b8d | |||
0ec83afa13 | |||
153c44601b
|
|||
e6a8371d4a | |||
64efb8ec7f | |||
c8b2b3a038 | |||
6873d2b847 | |||
91c3692f6d | |||
69788e1279 | |||
ec69076652 | |||
a62bda97a0 | |||
32f0131973 | |||
9784d5123b | |||
ea8d887a6b | |||
29cebab790 | |||
03095776f1
|
|||
bad9f67c39 | |||
98add88d14 | |||
e1b595d620 | |||
39940823d1 | |||
4479a2628d | |||
b09119cd8d | |||
10bc568560 | |||
6e09e29ec2 | |||
43fb05ac5d | |||
e832487081 | |||
01acbaa270 | |||
a8b5fec725 | |||
321de4e46b | |||
2635ec3d56 | |||
3f7915fe49 | |||
f87a10891a | |||
f4ac5c3844 | |||
922f145ffa | |||
9731127eaf | |||
5124f314f4 | |||
4bb078c451 | |||
547538fbc5 | |||
06d34efa74 | |||
b786b53c35 | |||
e50d0738ab | |||
01d0bd6c64 | |||
5676969fe3 | |||
b4594e6f43 | |||
6e12f08965 | |||
2dd2d8f133 | |||
10c3483fe5 | |||
23e3f2f34f | |||
6983ddc3e0 | |||
c234da6f07 | |||
8930be9f32 | |||
32996338a0 | |||
2736ebbd19 | |||
509945c323 | |||
435c6e6410 | |||
3429918f5e | |||
3a75be2683 | |||
aa9d7b2226 | |||
eea482b438 | |||
3a90578780 | |||
1d818294e4 | |||
581832e4f4 | |||
9e559658a7 | |||
b1c532078e | |||
37ac579f51 | |||
aaceac81af | |||
d781c6fcec | |||
bdd9889718 | |||
a5f44b8580 | |||
d1265a55b4 | |||
b542ed5c03 | |||
8b42132cbe | |||
b1670decf7 | |||
1d3d2be853 | |||
d4ab2c6cdb | |||
1c021651d7 | |||
3175883346 | |||
4d403b40c9 | |||
f6afa36b1c | |||
0c77ce4dcf | |||
4c11b2f660 | |||
614d1ccb7c | |||
e3c44fd27f | |||
078116c7be | |||
b5a14bb9df | |||
86577f4b80 | |||
d625642abc | |||
951eb40e96 | |||
538dec7062 | |||
8f17d6623a | |||
0585ef9051 | |||
0da95b75a2 | |||
e44f8bfea3 | |||
fe2b3a01cf | |||
aa849894c6 | |||
a4ca61d834 | |||
b41eb518e7 | |||
1b8878a81f | |||
95096d83de | |||
2331188536 | |||
b2937ae510 | |||
3f8fae24dd | |||
12f47fdd0d | |||
b757c5523c | |||
5271375063 | |||
4955015f3f | |||
898e06591b | |||
d62dea442d | |||
66a09b94ac | |||
125dffcf28 | |||
8dec4c9311 | |||
26ce8d7185 | |||
1996f5949f | |||
ca4a0b1bb8 | |||
588f9471d8 | |||
703dfe9854 | |||
7bc04014e8 | |||
5eb6b277ba | |||
2684b0c68e | |||
76c571b969 | |||
c08e2f0bf7 | |||
bceca86da6 | |||
8ab2044c30 | |||
7173d2ecfc | |||
cf120e2d86 | |||
e92d3901f7 | |||
b071c850af | |||
df7434dae5 | |||
6e5b032dbb | |||
67b05fee2e | |||
286a3649cf | |||
9eefd5b95d | |||
36e524abe3 | |||
c527391b10 | |||
9602a3ed6a | |||
33823b445c | |||
e55f74a00e | |||
8b83de6ca9 | |||
3bacc8ec53 | |||
6f78c13dcf | |||
824f272432 | |||
78b6a83285 | |||
620b2ae79e | |||
8d28bc4b6a | |||
dcde177fe3 | |||
4f89fc62ab | |||
c59fa578c7 | |||
6c0972b2d5 | |||
7ad8763b14 | |||
03936fc5c1 | |||
3789663db7 | |||
b2e4438811 | |||
6501c16fd7 | |||
943495117b | |||
30910034f0 | |||
596d3bc68a | |||
1e73302ba2 | |||
9ba7fabdea | |||
676c9ffcf3 | |||
5095fd206f | |||
bb5b7bed40 | |||
e5b3b6d75e | |||
61affafecd | |||
7525c88392 | |||
3e9c19ee11 | |||
a7bf9a6734 | |||
82d7b7ed6f | |||
7598eb6b56 | |||
7b3616c41f | |||
9737d4cf2a | |||
c815905b5a | |||
59028ccc3f | |||
372e8c66a8 | |||
f5ac4368d8 | |||
6d0bc26624 | |||
baafeadcf4 | |||
dbda6fee82 | |||
cad302730e | |||
da2f594a00 | |||
d5a065eaa8 | |||
b695242420 | |||
494dd0db32 | |||
8be4f45969 | |||
4e5e6e145e | |||
e67ff6a937 | |||
bdd66072d1 | |||
1966b33613 | |||
331bbd14e7 | |||
9efc5dbd61 | |||
e7cd7c8dc3 | |||
caa3cf538b | |||
b3ca7b8667 | |||
2d069896a5 | |||
cb514e7493 | |||
bc7d956899 | |||
227074fd4d | |||
a56cf43897 | |||
e501390d7b | |||
e0d7363eed | |||
69b428222a | |||
6df1abf570 | |||
d84003d62a | |||
a7878aaf04 | |||
23873f6bc6 | |||
8de33f1301 | |||
35825a6561 | |||
043d47e5e4 | |||
bd903b8447 | |||
4250c7e022 | |||
d66e486f16 | |||
21a7fd621d | |||
dae4a5fa74 | |||
d8d18c9333 | |||
041461a066 | |||
bff8d103ba | |||
6580aa73bf | |||
9a3cd1d7fc | |||
e64de87af7 | |||
7ea4fedcea | |||
1caa45118b | |||
6e43a70af5 | |||
559c8d0637 | |||
ef5c0d50f3 | |||
3f47db9c18 | |||
91db9c362e | |||
1d3438bb7d | |||
cc84d542c8 | |||
9e9113912b | |||
9f09c190bb | |||
2b6ccbc17f | |||
458d783211 | |||
5cf2197c06 | |||
940bbf47e4 | |||
714f11f117 | |||
ffce336801 | |||
50ba377380 | |||
304773f7a7 | |||
16566a5690 | |||
68415853b5 | |||
fb5a1b93fc | |||
828115a566 | |||
d79f0e1172 | |||
35d8453b48 | |||
36039266ee | |||
a65211be51 | |||
fcff06c83f | |||
ea6ee7e79c | |||
110159eea1 | |||
788dbe4eca | |||
f45d19a961 | |||
c5ee2260d1 | |||
242a146f61 | |||
8eb25c02aa | |||
94f9d1ee16 | |||
6cded300ae | |||
1bec19bdd7 | |||
2fba1a6cfe | |||
ce770a67b2 | |||
06eadb55ab | |||
58e219981f | |||
671bab012e | |||
1443758274 | |||
e013ae954f | |||
c28398257b | |||
4154c06825 | |||
8a1f043b39 | |||
2a1aea7c73 | |||
8d748a4bbf | |||
dc88424910 | |||
03b2e1be3e | |||
10390de63b | |||
0416aaf3fe | |||
ee67e46a9f | |||
eb37a0ad2f | |||
b9cb0495a9 | |||
ac5d0cf58f | |||
48375a5221 | |||
46e4816faf | |||
85b92af777 | |||
5136d90659 | |||
cb2c66e256 | |||
72ce47358e | |||
36d1a36a74 | |||
ae5d880406 | |||
bcd51c0725 | |||
5209a9bb89 | |||
712ba5124c | |||
16763202c1 | |||
9998de086f | |||
d4d3da60a9 | |||
9b2772c126 | |||
d736e9c874 | |||
257e79f8fc | |||
3bd7ba961e | |||
6be6d593a3 | |||
1829d9cf0a | |||
255d4a90a9 | |||
f7c1aae464 | |||
cdb012fe5a | |||
2bca40c527 | |||
1446ce94bf | |||
8c5e261a0d | |||
5f197be2ff | |||
6e5252b69e | |||
093eb05269 | |||
c1cb93baa9 | |||
c0b490df65 | |||
e27d4fd060 | |||
a404bc881e | |||
5ac3762dc5 | |||
4522668066 | |||
8b90360b45 | |||
f067695353 | |||
503de9ba89 | |||
cf945d4d34 | |||
7f0db5b47c | |||
e65990feff | |||
484f9b6b37 | |||
bc722b5583 | |||
6b4bed8ca9 | |||
7f47a10cbd | |||
9266c874c1 | |||
ac6e34fc65 | |||
6127bb5ea4 | |||
98f89302c4 | |||
76d81b5b49 | |||
17a1ae9d0e | |||
dcb569a7c8 | |||
5b0758638b | |||
f85ab2b300 | |||
3b7bebeb6f | |||
2fce82db10 | |||
73dcb78a65 | |||
a0e7b45d94 | |||
8b5abd1fd5 | |||
8a0431c578 | |||
942ecc89bd | |||
3036793814 | |||
f40cdcf472 | |||
686ae101ee | |||
4136420685 | |||
de45e9b8a9 | |||
47698418fc | |||
d1cd180534 | |||
a93984869c | |||
a0dea39670 | |||
35d75bae56 | |||
578664ad06 | |||
86d0d5c4ee | |||
7e0cc471c9 | |||
194a9eef64 | |||
18fddf2755 | |||
31517604c9 | |||
38c7e050ab | |||
7310d2b5fe | |||
d39c729a16 | |||
f11e7407d6 | |||
52c177479f | |||
0bb19c5ee5 | |||
4dbd5a58e3 | |||
df9f534d12 | |||
ef93c70665 | |||
47402055f9 | |||
0495f390ef | |||
d1c83159e5 | |||
5289c274f3 | |||
094d237814 | |||
e245f56a4f | |||
a85c94ea80 | |||
8850b770ee | |||
bdd1bdb080 | |||
7b82a7c1a7 | |||
cc2e26443d | |||
50733e223a | |||
6a5f5af233 | |||
e0f8113eac | |||
94d1b5acae | |||
2e9a855181 | |||
fd5252bb57 | |||
583d354fb5 | |||
d4ca1ddb20 | |||
ca22ff5d8e | |||
b6888a8185 | |||
f4a60a0323 | |||
f7b70984c1 | |||
74def820c6 | |||
6e6e1304bb | |||
2c21400aed | |||
aa7ea35b80 | |||
0514ab4d05 | |||
a9135696a5 | |||
38dd230887 | |||
eae3175976 | |||
79cf009049 | |||
73b9d058e5 | |||
baba8fa5d7 | |||
05508418a7 | |||
f69d6d49c7 | |||
eb5548333e | |||
fd11cae7be |
24
CHANGELOG
24
CHANGELOG
@@ -22,7 +22,9 @@ a C file without issues
|
||||
|
||||
### Local Pool
|
||||
|
||||
- Interface of LocalPools has changed. LocalPool is not a template anymore. Instead the size and bucket number of the pools per page and the number of pages are passed to the ctor instead of two ctor arguments and a template parameter
|
||||
- Interface of LocalPools has changed. LocalPool is not a template anymore. Instead the size and
|
||||
bucket number of the pools per page and the number of pages are passed to the ctor instead of
|
||||
two ctor arguments and a template parameter
|
||||
|
||||
### Parameter Service
|
||||
|
||||
@@ -40,7 +42,8 @@ important use-case)
|
||||
|
||||
### File System Interface
|
||||
|
||||
- A new interfaces specifies the functions for a software object which exposes the file system of a given hardware to use message based file handling (e.g. PUS commanding)
|
||||
- A new interfaces specifies the functions for a software object which exposes the file system of
|
||||
a given hardware to use message based file handling (e.g. PUS commanding)
|
||||
|
||||
### Internal Error Reporter
|
||||
|
||||
@@ -52,7 +55,8 @@ ID for now.
|
||||
### Device Handler Base
|
||||
|
||||
- There is an additional `PERFORM_OPERATION` step for the device handler base. It is important
|
||||
that DHB users adapt their polling sequence tables to perform this step. This steps allows for aclear distinction between operation and communication steps
|
||||
that DHB users adapt their polling sequence tables to perform this step. This steps allows for
|
||||
a clear distinction between operation and communication steps
|
||||
- setNormalDatapoolEntriesInvalid is not an abstract method and a default implementation was provided
|
||||
- getTransitionDelayMs is now an abstract method
|
||||
|
||||
@@ -69,7 +73,8 @@ now
|
||||
|
||||
### Commanding Service Base
|
||||
|
||||
- CSB uses the new fsfwconfig::FSFW_CSB_FIFO_DEPTH variable to determine the FIFO depth for each CSB instance. This variable has to be set in the FSFWConfig.h file
|
||||
- CSB uses the new fsfwconfig::FSFW_CSB_FIFO_DEPTH variable to determine the FIFO depth for each
|
||||
CSB instance. This variable has to be set in the FSFWConfig.h file
|
||||
|
||||
### Service Interface
|
||||
|
||||
@@ -81,4 +86,13 @@ now
|
||||
For the fsfw, this can be done by checking the processor define FSFW_CPP_OSTREAM_ENABLED from FSFWConfig.h.
|
||||
For mission code, developers need to replace sif:: calls by the printf counterparts, but only if the CPP stream are excluded.
|
||||
If this is not the case, everything should work as usual.
|
||||
-
|
||||
|
||||
### ActionHelper and ActionMessage
|
||||
|
||||
- ActionHelper finish function and ActionMessage::setCompletionReply now expects explicit
|
||||
information whether to report a success or failure message instead of deriving it implicitely
|
||||
from returnvalue
|
||||
|
||||
### PUS Parameter Service 20
|
||||
|
||||
Added PUS parameter service 20 (only custom subservices available).
|
||||
|
@@ -1,5 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
option(FSFW_GENERATE_SECTIONS
|
||||
"Generate function and data sections. Required to remove unused code" ON
|
||||
)
|
||||
|
||||
if(FSFW_GENERATE_SECTIONS)
|
||||
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
||||
endif()
|
||||
|
||||
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
||||
# Options to exclude parts of the FSFW from compilation.
|
||||
option(FSFW_USE_RMAP "Compile with RMAP" ON)
|
||||
@@ -26,15 +34,22 @@ if(NOT OS_FSFW)
|
||||
|
||||
endif()
|
||||
|
||||
set(FSFW_OSAL_DEFINITION FSFW_HOST)
|
||||
|
||||
if(${OS_FSFW} STREQUAL host)
|
||||
set(OS_FSFW_NAME "Host")
|
||||
elseif(${OS_FSFW} STREQUAL linux)
|
||||
set(OS_FSFW_NAME "Linux")
|
||||
set(FSFW_OSAL_DEFINITION FSFW_LINUX)
|
||||
elseif(${OS_FSFW} STREQUAL freertos)
|
||||
set(OS_FSFW_NAME "FreeRTOS")
|
||||
target_link_libraries(${LIB_FSFW_NAME} ${LIB_OS_NAME})
|
||||
set(FSFW_OSAL_DEFINITION FSFW_FREERTOS)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${LIB_OS_NAME}
|
||||
)
|
||||
elseif(${OS_FSFW} STREQUAL rtems)
|
||||
set(OS_FSFW_NAME "RTEMS")
|
||||
set(FSFW_OSAL_DEFINITION FSFW_RTEMS)
|
||||
else()
|
||||
message(WARNING
|
||||
"Invalid operating system for FSFW specified! Setting to host.."
|
||||
@@ -43,10 +58,16 @@ else()
|
||||
set(OS_FSFW "host")
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${LIB_FSFW_NAME} PRIVATE
|
||||
${FSFW_OSAL_DEFINITION}
|
||||
)
|
||||
|
||||
target_compile_definitions(${LIB_FSFW_NAME} INTERFACE
|
||||
${FSFW_OSAL_DEFINITION}
|
||||
)
|
||||
|
||||
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.")
|
||||
|
||||
|
||||
|
||||
add_subdirectory(action)
|
||||
add_subdirectory(container)
|
||||
add_subdirectory(controller)
|
||||
@@ -90,6 +111,7 @@ add_subdirectory(timemanager)
|
||||
add_subdirectory(tmstorage)
|
||||
add_subdirectory(tmtcpacket)
|
||||
add_subdirectory(tmtcservices)
|
||||
add_subdirectory(unittest)
|
||||
|
||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
|
||||
# If this is not given, we include the default configuration and emit a warning.
|
||||
@@ -109,20 +131,48 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATH})
|
||||
if(IS_ABSOLUTE ${INCLUDE_PATH})
|
||||
set(CURR_ABS_INC_PATH "${FREERTOS_PATH}")
|
||||
else()
|
||||
get_filename_component(CURR_ABS_INC_PATH
|
||||
${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERBOSE)
|
||||
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
|
||||
endif()
|
||||
|
||||
list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
|
||||
endforeach()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
||||
set(FSFW_WARNING_FLAGS
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wshadow=local
|
||||
-Wimplicit-fallthrough=1
|
||||
-Wno-unused-parameter
|
||||
-Wno-psabi
|
||||
)
|
||||
|
||||
if(FSFW_WARNING_SHADOW_LOCAL_GCC)
|
||||
list(APPEND WARNING_FLAGS "-Wshadow=local")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FSFW_GENERATE_SECTIONS)
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||
"-ffunction-sections"
|
||||
"-fdata-sections"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(FSFW_REMOVE_UNUSED_CODE)
|
||||
target_link_options(${LIB_FSFW_NAME} PRIVATE
|
||||
"Wl,--gc-sections"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(FSFW_WARNING_SHADOW_LOCAL_GCC)
|
||||
list(APPEND WARNING_FLAGS "-Wshadow=local")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
@@ -134,6 +184,7 @@ endif()
|
||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||
${FSFW_ADD_INC_PATHS_ABS}
|
||||
)
|
||||
|
||||
# Includes path required to compile FSFW itself as well
|
||||
@@ -142,9 +193,14 @@ target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||
${FSFW_ADD_INC_PATHS_ABS}
|
||||
)
|
||||
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||
${FSFW_WARNING_FLAGS}
|
||||
${COMPILER_FLAGS}
|
||||
)
|
||||
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${FSFW_ADDITIONAL_LINK_LIBS}
|
||||
)
|
@@ -3,9 +3,9 @@
|
||||
|
||||
const char* const FSFW_VERSION_NAME = "ASTP";
|
||||
|
||||
#define FSFW_VERSION 0
|
||||
#define FSFW_SUBVERSION 0
|
||||
#define FSFW_REVISION 1
|
||||
#define FSFW_VERSION 1
|
||||
#define FSFW_SUBVERSION 0
|
||||
#define FSFW_REVISION 0
|
||||
|
||||
|
||||
|
||||
|
@@ -3,151 +3,119 @@
|
||||
|
||||
#include "../ipc/MessageQueueSenderIF.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
|
||||
ActionHelper::ActionHelper(HasActionsIF* setOwner,
|
||||
MessageQueueIF* useThisQueue) :
|
||||
owner(setOwner), queueToUse(useThisQueue) {
|
||||
owner(setOwner), queueToUse(useThisQueue) {
|
||||
}
|
||||
|
||||
ActionHelper::~ActionHelper() {
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
||||
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
||||
ActionId_t currentAction = ActionMessage::getActionId(command);
|
||||
prepareExecution(command->getSender(), currentAction,
|
||||
ActionMessage::getStoreId(command));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return CommandMessage::UNKNOWN_COMMAND;
|
||||
}
|
||||
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
||||
ActionId_t currentAction = ActionMessage::getActionId(command);
|
||||
prepareExecution(command->getSender(), currentAction,
|
||||
ActionMessage::getStoreId(command));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return CommandMessage::UNKNOWN_COMMAND;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if(queueToUse_ != nullptr) {
|
||||
setQueueToUse(queueToUse_);
|
||||
}
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if(queueToUse_ != nullptr) {
|
||||
setQueueToUse(queueToUse_);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo,
|
||||
ActionId_t commandId, ReturnValue_t result) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
||||
queueToUse->sendMessage(reportTo, &reply);
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
||||
queueToUse->sendMessage(reportTo, &reply);
|
||||
}
|
||||
|
||||
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
||||
void ActionHelper::finish(bool success, MessageQueueId_t reportTo, ActionId_t commandId,
|
||||
ReturnValue_t result) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setCompletionReply(&reply, commandId, result);
|
||||
queueToUse->sendMessage(reportTo, &reply);
|
||||
CommandMessage reply;
|
||||
ActionMessage::setCompletionReply(&reply, commandId, success, result);
|
||||
queueToUse->sendMessage(reportTo, &reply);
|
||||
}
|
||||
|
||||
void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
|
||||
queueToUse = queue;
|
||||
queueToUse = queue;
|
||||
}
|
||||
|
||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
||||
ActionId_t actionId, store_address_t dataAddress) {
|
||||
const uint8_t* dataPtr = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
if(result == HasActionsIF::EXECUTION_FINISHED) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setCompletionReply(&reply, actionId, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
}
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
const uint8_t* dataPtr = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
if(result == HasActionsIF::EXECUTION_FINISHED) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
}
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||
ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
||||
CommandMessage reply;
|
||||
store_address_t storeAddress;
|
||||
uint8_t *dataPtr;
|
||||
size_t maxSize = data->getSerializedSize();
|
||||
if (maxSize == 0) {
|
||||
//No error, there's simply nothing to report.
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
||||
&dataPtr);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = data->serialize(&dataPtr, &size, maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeAddress);
|
||||
return result;
|
||||
}
|
||||
// We don't need to report the objectId, as we receive REQUESTED data
|
||||
// before the completion success message.
|
||||
// True aperiodic replies need to be reported with
|
||||
// another dedicated message.
|
||||
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
||||
|
||||
// If the sender needs to be hidden, for example to handle packet
|
||||
// as unrequested reply, this will be done here.
|
||||
if (hideSender) {
|
||||
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
||||
}
|
||||
else {
|
||||
result = queueToUse->sendMessage(reportTo, &reply);
|
||||
}
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
ipcStore->deleteData(storeAddress);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ActionHelper::resetHelper() {
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||
ActionId_t replyId, const uint8_t *data, size_t dataSize,
|
||||
bool hideSender) {
|
||||
ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
||||
CommandMessage reply;
|
||||
store_address_t storeAddress;
|
||||
ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize);
|
||||
uint8_t *dataPtr;
|
||||
size_t maxSize = data->getSerializedSize();
|
||||
if (maxSize == 0) {
|
||||
/* No error, there's simply nothing to report. */
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
||||
&dataPtr);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "ActionHelper::reportData: Getting free element from IPC store failed!" <<
|
||||
std::endl;
|
||||
#else
|
||||
sif::printWarning("ActionHelper::reportData: Getting free element from IPC "
|
||||
"store failed!\n");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
result = data->serialize(&dataPtr, &size, maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeAddress);
|
||||
return result;
|
||||
}
|
||||
|
||||
// We don't need to report the objectId, as we receive REQUESTED data
|
||||
// before the completion success message.
|
||||
// True aperiodic replies need to be reported with
|
||||
// another dedicated message.
|
||||
/* We don't need to report the objectId, as we receive REQUESTED data before the completion
|
||||
success message. True aperiodic replies need to be reported with another dedicated message. */
|
||||
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
||||
|
||||
// If the sender needs to be hidden, for example to handle packet
|
||||
// as unrequested reply, this will be done here.
|
||||
/* If the sender needs to be hidden, for example to handle packet
|
||||
as unrequested reply, this will be done here. */
|
||||
if (hideSender) {
|
||||
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
||||
}
|
||||
@@ -160,3 +128,40 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ActionHelper::resetHelper() {
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||
ActionId_t replyId, const uint8_t *data, size_t dataSize,
|
||||
bool hideSender) {
|
||||
CommandMessage reply;
|
||||
store_address_t storeAddress;
|
||||
ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "ActionHelper::reportData: Adding data to IPC store failed!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("ActionHelper::reportData: Adding data to IPC store failed!\n");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/* We don't need to report the objectId, as we receive REQUESTED data before the completion
|
||||
success message. True aperiodic replies need to be reported with another dedicated message. */
|
||||
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
||||
|
||||
/* If the sender needs to be hidden, for example to handle packet
|
||||
as unrequested reply, this will be done here. */
|
||||
if (hideSender) {
|
||||
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
||||
}
|
||||
else {
|
||||
result = queueToUse->sendMessage(reportTo, &reply);
|
||||
}
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeAddress);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -18,68 +18,68 @@ class HasActionsIF;
|
||||
|
||||
class ActionHelper {
|
||||
public:
|
||||
/**
|
||||
* Constructor of the action helper
|
||||
* @param setOwner Pointer to the owner of the interface
|
||||
* @param useThisQueue messageQueue to be used, can be set during
|
||||
* initialize function as well.
|
||||
*/
|
||||
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
/**
|
||||
* Constructor of the action helper
|
||||
* @param setOwner Pointer to the owner of the interface
|
||||
* @param useThisQueue messageQueue to be used, can be set during
|
||||
* initialize function as well.
|
||||
*/
|
||||
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
|
||||
virtual ~ActionHelper();
|
||||
/**
|
||||
* Function to be called from the owner with a new command message
|
||||
*
|
||||
* If the message is a valid action message the helper will use the
|
||||
* executeAction function from HasActionsIF.
|
||||
* If the message is invalid or the callback fails a message reply will be
|
||||
* send to the sender of the message automatically.
|
||||
*
|
||||
* @param command Pointer to a command message received by the owner
|
||||
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
|
||||
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
||||
*/
|
||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||
/**
|
||||
* Helper initialize function. Must be called before use of any other
|
||||
* helper function
|
||||
* @param queueToUse_ Pointer to the messageQueue to be used, optional
|
||||
* if queue was set in constructor
|
||||
* @return Returns RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
||||
/**
|
||||
* Function to be called from the owner to send a step message.
|
||||
* Success or failure will be determined by the result value.
|
||||
*
|
||||
* @param step Number of steps already done
|
||||
* @param reportTo The messageQueueId to report the step message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void step(uint8_t step, MessageQueueId_t reportTo,
|
||||
ActionId_t commandId,
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner to send a action completion message
|
||||
*
|
||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner if an action does report data.
|
||||
* Takes a SerializeIF* pointer and serializes it into the IPC store.
|
||||
* @param reportTo MessageQueueId_t to report the action completion
|
||||
* message to
|
||||
* @param replyId ID of the executed command
|
||||
* @param data Pointer to the data
|
||||
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||
*/
|
||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
||||
SerializeIF* data, bool hideSender = false);
|
||||
virtual ~ActionHelper();
|
||||
/**
|
||||
* Function to be called from the owner with a new command message
|
||||
*
|
||||
* If the message is a valid action message the helper will use the
|
||||
* executeAction function from HasActionsIF.
|
||||
* If the message is invalid or the callback fails a message reply will be
|
||||
* send to the sender of the message automatically.
|
||||
*
|
||||
* @param command Pointer to a command message received by the owner
|
||||
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
|
||||
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
||||
*/
|
||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||
/**
|
||||
* Helper initialize function. Must be called before use of any other
|
||||
* helper function
|
||||
* @param queueToUse_ Pointer to the messageQueue to be used, optional
|
||||
* if queue was set in constructor
|
||||
* @return Returns RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
||||
/**
|
||||
* Function to be called from the owner to send a step message.
|
||||
* Success or failure will be determined by the result value.
|
||||
*
|
||||
* @param step Number of steps already done
|
||||
* @param reportTo The messageQueueId to report the step message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void step(uint8_t step, MessageQueueId_t reportTo,
|
||||
ActionId_t commandId,
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner to send a action completion message
|
||||
* @param success Specify whether action was completed successfully or not.
|
||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void finish(bool success, MessageQueueId_t reportTo, ActionId_t commandId,
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner if an action does report data.
|
||||
* Takes a SerializeIF* pointer and serializes it into the IPC store.
|
||||
* @param reportTo MessageQueueId_t to report the action completion
|
||||
* message to
|
||||
* @param replyId ID of the executed command
|
||||
* @param data Pointer to the data
|
||||
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||
*/
|
||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
||||
SerializeIF* data, bool hideSender = false);
|
||||
/**
|
||||
* Function to be called by the owner if an action does report data.
|
||||
* Takes the raw data and writes it into the IPC store.
|
||||
@@ -91,35 +91,36 @@ public:
|
||||
*/
|
||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
||||
const uint8_t* data, size_t dataSize, bool hideSender = false);
|
||||
/**
|
||||
* Function to setup the MessageQueueIF* of the helper. Can be used to
|
||||
* set the MessageQueueIF* if message queue is unavailable at construction
|
||||
* and initialize but must be setup before first call of other functions.
|
||||
* @param queue Queue to be used by the helper
|
||||
*/
|
||||
void setQueueToUse(MessageQueueIF *queue);
|
||||
/**
|
||||
* Function to setup the MessageQueueIF* of the helper. Can be used to
|
||||
* set the MessageQueueIF* if message queue is unavailable at construction
|
||||
* and initialize but must be setup before first call of other functions.
|
||||
* @param queue Queue to be used by the helper
|
||||
*/
|
||||
void setQueueToUse(MessageQueueIF *queue);
|
||||
protected:
|
||||
//!< Increase of value of this per step
|
||||
static const uint8_t STEP_OFFSET = 1;
|
||||
HasActionsIF* owner;//!< Pointer to the owner
|
||||
//! Queue to be used as response sender, has to be set in ctor or with
|
||||
//! setQueueToUse
|
||||
MessageQueueIF* queueToUse;
|
||||
//! Pointer to an IPC Store, initialized during construction or
|
||||
StorageManagerIF* ipcStore = nullptr;
|
||||
//! Increase of value of this per step
|
||||
static const uint8_t STEP_OFFSET = 1;
|
||||
//! Pointer to the owner
|
||||
HasActionsIF* owner;
|
||||
//! Queue to be used as response sender, has to be set in ctor or with
|
||||
//! setQueueToUse
|
||||
MessageQueueIF* queueToUse;
|
||||
//! Pointer to an IPC Store, initialized during construction or
|
||||
StorageManagerIF* ipcStore = nullptr;
|
||||
|
||||
/**
|
||||
* Internal function called by handleActionMessage
|
||||
* @param commandedBy MessageQueueID of Commander
|
||||
* @param actionId ID of action to be done
|
||||
* @param dataAddress Address of additional data in IPC Store
|
||||
*/
|
||||
virtual void prepareExecution(MessageQueueId_t commandedBy,
|
||||
ActionId_t actionId, store_address_t dataAddress);
|
||||
/**
|
||||
* @brief Default implementation is empty.
|
||||
*/
|
||||
virtual void resetHelper();
|
||||
/**
|
||||
* Internal function called by handleActionMessage
|
||||
* @param commandedBy MessageQueueID of Commander
|
||||
* @param actionId ID of action to be done
|
||||
* @param dataAddress Address of additional data in IPC Store
|
||||
*/
|
||||
virtual void prepareExecution(MessageQueueId_t commandedBy,
|
||||
ActionId_t actionId, store_address_t dataAddress);
|
||||
/**
|
||||
* @brief Default implementation is empty.
|
||||
*/
|
||||
virtual void resetHelper();
|
||||
};
|
||||
|
||||
#endif /* FSFW_ACTION_ACTIONHELPER_H_ */
|
||||
|
@@ -11,71 +11,72 @@ ActionMessage::~ActionMessage() {
|
||||
}
|
||||
|
||||
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
|
||||
store_address_t parameters) {
|
||||
message->setCommand(EXECUTE_ACTION);
|
||||
message->setParameter(fid);
|
||||
message->setParameter2(parameters.raw);
|
||||
store_address_t parameters) {
|
||||
message->setCommand(EXECUTE_ACTION);
|
||||
message->setParameter(fid);
|
||||
message->setParameter2(parameters.raw);
|
||||
}
|
||||
|
||||
ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
|
||||
return ActionId_t(message->getParameter());
|
||||
return ActionId_t(message->getParameter());
|
||||
}
|
||||
|
||||
store_address_t ActionMessage::getStoreId(const CommandMessage* message) {
|
||||
store_address_t temp;
|
||||
temp.raw = message->getParameter2();
|
||||
return temp;
|
||||
store_address_t temp;
|
||||
temp.raw = message->getParameter2();
|
||||
return temp;
|
||||
}
|
||||
|
||||
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
||||
ReturnValue_t result) {
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
message->setCommand(STEP_SUCCESS);
|
||||
} else {
|
||||
message->setCommand(STEP_FAILED);
|
||||
}
|
||||
message->setParameter(fid);
|
||||
message->setParameter2((step << 16) + result);
|
||||
ReturnValue_t result) {
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
message->setCommand(STEP_SUCCESS);
|
||||
} else {
|
||||
message->setCommand(STEP_FAILED);
|
||||
}
|
||||
message->setParameter(fid);
|
||||
message->setParameter2((step << 16) + result);
|
||||
}
|
||||
|
||||
uint8_t ActionMessage::getStep(const CommandMessage* message) {
|
||||
return uint8_t((message->getParameter2() >> 16) & 0xFF);
|
||||
return uint8_t((message->getParameter2() >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) {
|
||||
return message->getParameter2() & 0xFFFF;
|
||||
return message->getParameter2() & 0xFFFF;
|
||||
}
|
||||
|
||||
void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||
store_address_t data) {
|
||||
message->setCommand(DATA_REPLY);
|
||||
message->setParameter(actionId);
|
||||
message->setParameter2(data.raw);
|
||||
store_address_t data) {
|
||||
message->setCommand(DATA_REPLY);
|
||||
message->setParameter(actionId);
|
||||
message->setParameter2(data.raw);
|
||||
}
|
||||
|
||||
void ActionMessage::setCompletionReply(CommandMessage* message,
|
||||
ActionId_t fid, ReturnValue_t result) {
|
||||
if (result == HasReturnvaluesIF::RETURN_OK or result == HasActionsIF::EXECUTION_FINISHED) {
|
||||
message->setCommand(COMPLETION_SUCCESS);
|
||||
} else {
|
||||
message->setCommand(COMPLETION_FAILED);
|
||||
}
|
||||
message->setParameter(fid);
|
||||
message->setParameter2(result);
|
||||
ActionId_t fid, bool success, ReturnValue_t result) {
|
||||
if (success) {
|
||||
message->setCommand(COMPLETION_SUCCESS);
|
||||
}
|
||||
else {
|
||||
message->setCommand(COMPLETION_FAILED);
|
||||
}
|
||||
message->setParameter(fid);
|
||||
message->setParameter2(result);
|
||||
}
|
||||
|
||||
void ActionMessage::clear(CommandMessage* message) {
|
||||
switch(message->getCommand()) {
|
||||
case EXECUTE_ACTION:
|
||||
case DATA_REPLY: {
|
||||
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
|
||||
objects::IPC_STORE);
|
||||
if (ipcStore != NULL) {
|
||||
ipcStore->deleteData(getStoreId(message));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(message->getCommand()) {
|
||||
case EXECUTE_ACTION:
|
||||
case DATA_REPLY: {
|
||||
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
|
||||
objects::IPC_STORE);
|
||||
if (ipcStore != NULL) {
|
||||
ipcStore->deleteData(getStoreId(message));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -15,29 +15,33 @@ using ActionId_t = uint32_t;
|
||||
*/
|
||||
class ActionMessage {
|
||||
private:
|
||||
ActionMessage();
|
||||
ActionMessage();
|
||||
public:
|
||||
static const uint8_t MESSAGE_ID = messagetypes::ACTION;
|
||||
static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1);
|
||||
static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2);
|
||||
static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3);
|
||||
static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4);
|
||||
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
||||
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
||||
virtual ~ActionMessage();
|
||||
static void setCommand(CommandMessage* message, ActionId_t fid,
|
||||
store_address_t parameters);
|
||||
static ActionId_t getActionId(const CommandMessage* message );
|
||||
static store_address_t getStoreId(const CommandMessage* message );
|
||||
static void setStepReply(CommandMessage* message, ActionId_t fid,
|
||||
uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
static uint8_t getStep(const CommandMessage* message );
|
||||
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
||||
static void setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||
store_address_t data);
|
||||
static void setCompletionReply(CommandMessage* message, ActionId_t fid,
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
static void clear(CommandMessage* message);
|
||||
static const uint8_t MESSAGE_ID = messagetypes::ACTION;
|
||||
static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1);
|
||||
static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2);
|
||||
static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3);
|
||||
static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4);
|
||||
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
||||
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
||||
|
||||
virtual ~ActionMessage();
|
||||
static void setCommand(CommandMessage* message, ActionId_t fid,
|
||||
store_address_t parameters);
|
||||
|
||||
static ActionId_t getActionId(const CommandMessage* message );
|
||||
static store_address_t getStoreId(const CommandMessage* message);
|
||||
|
||||
static void setStepReply(CommandMessage* message, ActionId_t fid,
|
||||
uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
static uint8_t getStep(const CommandMessage* message );
|
||||
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
||||
static void setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||
store_address_t data);
|
||||
static void setCompletionReply(CommandMessage* message, ActionId_t fid,
|
||||
bool success, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
|
||||
static void clear(CommandMessage* message);
|
||||
};
|
||||
|
||||
#endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */
|
||||
|
@@ -1,7 +1,7 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ActionHelper.cpp
|
||||
ActionMessage.cpp
|
||||
CommandActionHelper.cpp
|
||||
SimpleActionHelper.cpp
|
||||
PRIVATE
|
||||
ActionHelper.cpp
|
||||
ActionMessage.cpp
|
||||
CommandActionHelper.cpp
|
||||
SimpleActionHelper.cpp
|
||||
)
|
@@ -5,123 +5,123 @@
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
|
||||
CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) :
|
||||
owner(setOwner), queueToUse(NULL), ipcStore(
|
||||
NULL), commandCount(0), lastTarget(0) {
|
||||
owner(setOwner), queueToUse(NULL), ipcStore(
|
||||
NULL), commandCount(0), lastTarget(0) {
|
||||
}
|
||||
|
||||
CommandActionHelper::~CommandActionHelper() {
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, SerializeIF *data) {
|
||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
uint8_t *storePointer;
|
||||
size_t maxSize = data->getSerializedSize();
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
|
||||
&storePointer);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
size_t size = 0;
|
||||
result = data->serialize(&storePointer, &size, maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||
ActionId_t actionId, SerializeIF *data) {
|
||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
uint8_t *storePointer;
|
||||
size_t maxSize = data->getSerializedSize();
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
|
||||
&storePointer);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
size_t size = 0;
|
||||
result = data->serialize(&storePointer, &size, maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, const uint8_t *data, uint32_t size) {
|
||||
// if (commandCount != 0) {
|
||||
// return CommandsFunctionsIF::ALREADY_COMMANDING;
|
||||
// }
|
||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||
ActionId_t actionId, const uint8_t *data, uint32_t size) {
|
||||
// if (commandCount != 0) {
|
||||
// return CommandsFunctionsIF::ALREADY_COMMANDING;
|
||||
// }
|
||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
|
||||
ActionId_t actionId, store_address_t storeId) {
|
||||
CommandMessage command;
|
||||
ActionMessage::setCommand(&command, actionId, storeId);
|
||||
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeId);
|
||||
}
|
||||
lastTarget = queueId;
|
||||
commandCount++;
|
||||
return result;
|
||||
ActionId_t actionId, store_address_t storeId) {
|
||||
CommandMessage command;
|
||||
ActionMessage::setCommand(&command, actionId, storeId);
|
||||
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeId);
|
||||
}
|
||||
lastTarget = queueId;
|
||||
commandCount++;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::initialize() {
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
queueToUse = owner->getCommandQueuePtr();
|
||||
if (queueToUse == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
queueToUse = owner->getCommandQueuePtr();
|
||||
if (queueToUse == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
||||
if (reply->getSender() != lastTarget) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
switch (reply->getCommand()) {
|
||||
case ActionMessage::COMPLETION_SUCCESS:
|
||||
commandCount--;
|
||||
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::COMPLETION_FAILED:
|
||||
commandCount--;
|
||||
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::STEP_SUCCESS:
|
||||
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStep(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::STEP_FAILED:
|
||||
commandCount--;
|
||||
owner->stepFailedReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStep(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::DATA_REPLY:
|
||||
extractDataForOwner(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStoreId(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if (reply->getSender() != lastTarget) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
switch (reply->getCommand()) {
|
||||
case ActionMessage::COMPLETION_SUCCESS:
|
||||
commandCount--;
|
||||
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::COMPLETION_FAILED:
|
||||
commandCount--;
|
||||
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::STEP_SUCCESS:
|
||||
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStep(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::STEP_FAILED:
|
||||
commandCount--;
|
||||
owner->stepFailedReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStep(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::DATA_REPLY:
|
||||
extractDataForOwner(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStoreId(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CommandActionHelper::getCommandCount() const {
|
||||
return commandCount;
|
||||
return commandCount;
|
||||
}
|
||||
|
||||
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
|
||||
const uint8_t * data = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
owner->dataReceived(actionId, data, size);
|
||||
ipcStore->deleteData(storeId);
|
||||
const uint8_t * data = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
owner->dataReceived(actionId, data, size);
|
||||
ipcStore->deleteData(storeId);
|
||||
}
|
||||
|
@@ -11,26 +11,26 @@
|
||||
class CommandsActionsIF;
|
||||
|
||||
class CommandActionHelper {
|
||||
friend class CommandsActionsIF;
|
||||
friend class CommandsActionsIF;
|
||||
public:
|
||||
CommandActionHelper(CommandsActionsIF* owner);
|
||||
virtual ~CommandActionHelper();
|
||||
ReturnValue_t commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, const uint8_t* data, uint32_t size);
|
||||
ReturnValue_t commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, SerializeIF* data);
|
||||
ReturnValue_t initialize();
|
||||
ReturnValue_t handleReply(CommandMessage* reply);
|
||||
uint8_t getCommandCount() const;
|
||||
CommandActionHelper(CommandsActionsIF* owner);
|
||||
virtual ~CommandActionHelper();
|
||||
ReturnValue_t commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, const uint8_t* data, uint32_t size);
|
||||
ReturnValue_t commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, SerializeIF* data);
|
||||
ReturnValue_t initialize();
|
||||
ReturnValue_t handleReply(CommandMessage* reply);
|
||||
uint8_t getCommandCount() const;
|
||||
private:
|
||||
CommandsActionsIF* owner;
|
||||
MessageQueueIF* queueToUse;
|
||||
StorageManagerIF* ipcStore;
|
||||
uint8_t commandCount;
|
||||
MessageQueueId_t lastTarget;
|
||||
void extractDataForOwner(ActionId_t actionId, store_address_t storeId);
|
||||
ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId,
|
||||
store_address_t storeId);
|
||||
CommandsActionsIF* owner;
|
||||
MessageQueueIF* queueToUse;
|
||||
StorageManagerIF* ipcStore;
|
||||
uint8_t commandCount;
|
||||
MessageQueueId_t lastTarget;
|
||||
void extractDataForOwner(ActionId_t actionId, store_address_t storeId);
|
||||
ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId,
|
||||
store_address_t storeId);
|
||||
};
|
||||
|
||||
#endif /* COMMANDACTIONHELPER_H_ */
|
||||
|
@@ -15,22 +15,22 @@
|
||||
* - replyReceived(id, step, cause) (if cause == OK, it's a success).
|
||||
*/
|
||||
class CommandsActionsIF {
|
||||
friend class CommandActionHelper;
|
||||
friend class CommandActionHelper;
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
|
||||
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
|
||||
virtual ~CommandsActionsIF() {}
|
||||
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
|
||||
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
|
||||
virtual ~CommandsActionsIF() {}
|
||||
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
||||
protected:
|
||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
|
||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
ReturnValue_t returnCode) = 0;
|
||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size) = 0;
|
||||
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
||||
virtual void completionFailedReceived(ActionId_t actionId,
|
||||
ReturnValue_t returnCode) = 0;
|
||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
|
||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
ReturnValue_t returnCode) = 0;
|
||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size) = 0;
|
||||
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
||||
virtual void completionFailedReceived(ActionId_t actionId,
|
||||
ReturnValue_t returnCode) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -35,28 +35,28 @@
|
||||
*/
|
||||
class HasActionsIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
|
||||
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
||||
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
||||
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
||||
virtual ~HasActionsIF() { }
|
||||
/**
|
||||
* Function to get the MessageQueueId_t of the implementing object
|
||||
* @return MessageQueueId_t of the object
|
||||
*/
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
/**
|
||||
* Execute or initialize the execution of a certain function.
|
||||
* The ActionHelpers will execute this function and behave differently
|
||||
* depending on the returnvalue.
|
||||
*
|
||||
* @return
|
||||
* -@c EXECUTION_FINISHED Finish reply will be generated
|
||||
* -@c Not RETURN_OK Step failure reply will be generated
|
||||
*/
|
||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
|
||||
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
||||
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
||||
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
||||
virtual ~HasActionsIF() { }
|
||||
/**
|
||||
* Function to get the MessageQueueId_t of the implementing object
|
||||
* @return MessageQueueId_t of the object
|
||||
*/
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
/**
|
||||
* Execute or initialize the execution of a certain function.
|
||||
* The ActionHelpers will execute this function and behave differently
|
||||
* depending on the returnvalue.
|
||||
*
|
||||
* @return
|
||||
* -@c EXECUTION_FINISHED Finish reply will be generated
|
||||
* -@c Not RETURN_OK Step failure reply will be generated
|
||||
*/
|
||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -2,74 +2,74 @@
|
||||
#include "SimpleActionHelper.h"
|
||||
|
||||
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
||||
MessageQueueIF* useThisQueue) :
|
||||
ActionHelper(setOwner, useThisQueue), isExecuting(false) {
|
||||
MessageQueueIF* useThisQueue) :
|
||||
ActionHelper(setOwner, useThisQueue), isExecuting(false) {
|
||||
}
|
||||
|
||||
SimpleActionHelper::~SimpleActionHelper() {
|
||||
}
|
||||
|
||||
void SimpleActionHelper::step(ReturnValue_t result) {
|
||||
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
||||
// method, which is not necessary here.
|
||||
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
||||
result);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
resetHelper();
|
||||
}
|
||||
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
||||
// method, which is not necessary here.
|
||||
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
||||
result);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
resetHelper();
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleActionHelper::finish(ReturnValue_t result) {
|
||||
ActionHelper::finish(lastCommander, lastAction, result);
|
||||
resetHelper();
|
||||
ActionHelper::finish(lastCommander, lastAction, result);
|
||||
resetHelper();
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
|
||||
return ActionHelper::reportData(lastCommander, lastAction, data);
|
||||
return ActionHelper::reportData(lastCommander, lastAction, data);
|
||||
}
|
||||
|
||||
void SimpleActionHelper::resetHelper() {
|
||||
stepCount = 0;
|
||||
isExecuting = false;
|
||||
lastAction = 0;
|
||||
lastCommander = 0;
|
||||
stepCount = 0;
|
||||
isExecuting = false;
|
||||
lastAction = 0;
|
||||
lastCommander = 0;
|
||||
}
|
||||
|
||||
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
||||
ActionId_t actionId, store_address_t dataAddress) {
|
||||
CommandMessage reply;
|
||||
if (isExecuting) {
|
||||
ipcStore->deleteData(dataAddress);
|
||||
ActionMessage::setStepReply(&reply, actionId, 0,
|
||||
HasActionsIF::IS_BUSY);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
}
|
||||
const uint8_t* dataPtr = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
lastCommander = commandedBy;
|
||||
lastAction = actionId;
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
switch (result) {
|
||||
case HasReturnvaluesIF::RETURN_OK:
|
||||
isExecuting = true;
|
||||
stepCount++;
|
||||
break;
|
||||
case HasActionsIF::EXECUTION_FINISHED:
|
||||
ActionMessage::setCompletionReply(&reply, actionId,
|
||||
HasReturnvaluesIF::RETURN_OK);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
break;
|
||||
default:
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
break;
|
||||
}
|
||||
ActionId_t actionId, store_address_t dataAddress) {
|
||||
CommandMessage reply;
|
||||
if (isExecuting) {
|
||||
ipcStore->deleteData(dataAddress);
|
||||
ActionMessage::setStepReply(&reply, actionId, 0,
|
||||
HasActionsIF::IS_BUSY);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
}
|
||||
const uint8_t* dataPtr = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
lastCommander = commandedBy;
|
||||
lastAction = actionId;
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
switch (result) {
|
||||
case HasReturnvaluesIF::RETURN_OK:
|
||||
isExecuting = true;
|
||||
stepCount++;
|
||||
break;
|
||||
case HasActionsIF::EXECUTION_FINISHED:
|
||||
ActionMessage::setCompletionReply(&reply, actionId,
|
||||
true, HasReturnvaluesIF::RETURN_OK);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
break;
|
||||
default:
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -4,27 +4,27 @@
|
||||
#include "ActionHelper.h"
|
||||
|
||||
/**
|
||||
* @brief This is an action helper which is only able to service one action
|
||||
* at a time but remembers last commander and last action which
|
||||
* simplifies usage
|
||||
* @brief This is an action helper which is only able to service one action
|
||||
* at a time but remembers last commander and last action which
|
||||
* simplifies usage
|
||||
*/
|
||||
class SimpleActionHelper: public ActionHelper {
|
||||
public:
|
||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
virtual ~SimpleActionHelper();
|
||||
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
ReturnValue_t reportData(SerializeIF* data);
|
||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
virtual ~SimpleActionHelper();
|
||||
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
ReturnValue_t reportData(SerializeIF* data);
|
||||
|
||||
protected:
|
||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
store_address_t dataAddress);
|
||||
virtual void resetHelper();
|
||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
store_address_t dataAddress);
|
||||
virtual void resetHelper();
|
||||
private:
|
||||
bool isExecuting;
|
||||
MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE;
|
||||
ActionId_t lastAction = 0;
|
||||
uint8_t stepCount = 0;
|
||||
bool isExecuting;
|
||||
MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE;
|
||||
ActionId_t lastAction = 0;
|
||||
uint8_t stepCount = 0;
|
||||
};
|
||||
|
||||
#endif /* SIMPLEACTIONHELPER_H_ */
|
||||
|
@@ -6,7 +6,7 @@
|
||||
#include "../serialize/SerializeIF.h"
|
||||
|
||||
/**
|
||||
* @brief A List that stores its values in an array.
|
||||
* @brief A List that stores its values in an array.
|
||||
* @details
|
||||
* The underlying storage is an array that can be allocated by the class
|
||||
* itself or supplied via ctor.
|
||||
@@ -15,237 +15,237 @@
|
||||
*/
|
||||
template<typename T, typename count_t = uint8_t>
|
||||
class ArrayList {
|
||||
template<typename U, typename count> friend class SerialArrayListAdapter;
|
||||
template<typename U, typename count> friend class SerialArrayListAdapter;
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
|
||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
|
||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
||||
|
||||
/**
|
||||
* This is the allocating constructor.
|
||||
* It allocates an array of the specified size.
|
||||
* @param maxSize
|
||||
*/
|
||||
ArrayList(count_t maxSize) :
|
||||
size(0), maxSize_(maxSize), allocated(true) {
|
||||
entries = new T[maxSize];
|
||||
}
|
||||
/**
|
||||
* This is the allocating constructor.
|
||||
* It allocates an array of the specified size.
|
||||
* @param maxSize
|
||||
*/
|
||||
ArrayList(count_t maxSize) :
|
||||
size(0), maxSize_(maxSize), allocated(true) {
|
||||
entries = new T[maxSize];
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the non-allocating constructor
|
||||
*
|
||||
* It expects a pointer to an array of a certain size and initializes
|
||||
* itself to it.
|
||||
*
|
||||
* @param storage the array to use as backend
|
||||
* @param maxSize size of storage
|
||||
* @param size size of data already present in storage
|
||||
*/
|
||||
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
|
||||
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
|
||||
}
|
||||
/**
|
||||
* This is the non-allocating constructor
|
||||
*
|
||||
* It expects a pointer to an array of a certain size and initializes
|
||||
* itself to it.
|
||||
*
|
||||
* @param storage the array to use as backend
|
||||
* @param maxSize size of storage
|
||||
* @param size size of data already present in storage
|
||||
*/
|
||||
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
|
||||
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copying is forbiden by declaring copy ctor and copy assignment deleted
|
||||
* It is too ambigous in this case.
|
||||
* (Allocate a new backend? Use the same? What to do in an modifying call?)
|
||||
*/
|
||||
ArrayList(const ArrayList& other) = delete;
|
||||
const ArrayList& operator=(const ArrayList& other) = delete;
|
||||
/**
|
||||
* Copying is forbiden by declaring copy ctor and copy assignment deleted
|
||||
* It is too ambigous in this case.
|
||||
* (Allocate a new backend? Use the same? What to do in an modifying call?)
|
||||
*/
|
||||
ArrayList(const ArrayList& other) = delete;
|
||||
const ArrayList& operator=(const ArrayList& other) = delete;
|
||||
|
||||
/**
|
||||
* Number of Elements stored in this List
|
||||
*/
|
||||
count_t size;
|
||||
/**
|
||||
* Number of Elements stored in this List
|
||||
*/
|
||||
count_t size;
|
||||
|
||||
|
||||
/**
|
||||
* Destructor, if the allocating constructor was used, it deletes the array.
|
||||
*/
|
||||
virtual ~ArrayList() {
|
||||
if (allocated) {
|
||||
delete[] entries;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Destructor, if the allocating constructor was used, it deletes the array.
|
||||
*/
|
||||
virtual ~ArrayList() {
|
||||
if (allocated) {
|
||||
delete[] entries;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An Iterator to go trough an ArrayList
|
||||
*
|
||||
* It stores a pointer to an element and increments the
|
||||
* pointer when incremented itself.
|
||||
*/
|
||||
class Iterator {
|
||||
public:
|
||||
/**
|
||||
* Empty ctor, points to NULL
|
||||
*/
|
||||
Iterator(): value(0) {}
|
||||
/**
|
||||
* An Iterator to go trough an ArrayList
|
||||
*
|
||||
* It stores a pointer to an element and increments the
|
||||
* pointer when incremented itself.
|
||||
*/
|
||||
class Iterator {
|
||||
public:
|
||||
/**
|
||||
* Empty ctor, points to NULL
|
||||
*/
|
||||
Iterator(): value(0) {}
|
||||
|
||||
/**
|
||||
* Initializes the Iterator to point to an element
|
||||
*
|
||||
* @param initialize
|
||||
*/
|
||||
Iterator(T *initialize) {
|
||||
value = initialize;
|
||||
}
|
||||
/**
|
||||
* Initializes the Iterator to point to an element
|
||||
*
|
||||
* @param initialize
|
||||
*/
|
||||
Iterator(T *initialize) {
|
||||
value = initialize;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current element the iterator points to
|
||||
*/
|
||||
T *value;
|
||||
/**
|
||||
* The current element the iterator points to
|
||||
*/
|
||||
T *value;
|
||||
|
||||
Iterator& operator++() {
|
||||
value++;
|
||||
return *this;
|
||||
}
|
||||
Iterator& operator++() {
|
||||
value++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator++(int) {
|
||||
Iterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
Iterator operator++(int) {
|
||||
Iterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Iterator& operator--() {
|
||||
value--;
|
||||
return *this;
|
||||
}
|
||||
Iterator& operator--() {
|
||||
value--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator--(int) {
|
||||
Iterator tmp(*this);
|
||||
operator--();
|
||||
return tmp;
|
||||
}
|
||||
Iterator operator--(int) {
|
||||
Iterator tmp(*this);
|
||||
operator--();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
T& operator*() {
|
||||
return *value;
|
||||
}
|
||||
T& operator*() {
|
||||
return *value;
|
||||
}
|
||||
|
||||
const T& operator*() const {
|
||||
return *value;
|
||||
}
|
||||
const T& operator*() const {
|
||||
return *value;
|
||||
}
|
||||
|
||||
T *operator->() {
|
||||
return value;
|
||||
}
|
||||
T *operator->() {
|
||||
return value;
|
||||
}
|
||||
|
||||
const T *operator->() const {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
const T *operator->() const {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
friend bool operator==(const ArrayList::Iterator& lhs,
|
||||
const ArrayList::Iterator& rhs) {
|
||||
return (lhs.value == rhs.value);
|
||||
}
|
||||
friend bool operator==(const ArrayList::Iterator& lhs,
|
||||
const ArrayList::Iterator& rhs) {
|
||||
return (lhs.value == rhs.value);
|
||||
}
|
||||
|
||||
friend bool operator!=(const ArrayList::Iterator& lhs,
|
||||
const ArrayList::Iterator& rhs) {
|
||||
return not (lhs.value == rhs.value);
|
||||
}
|
||||
friend bool operator!=(const ArrayList::Iterator& lhs,
|
||||
const ArrayList::Iterator& rhs) {
|
||||
return not (lhs.value == rhs.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator pointing to the first stored elmement
|
||||
*
|
||||
* @return Iterator to the first element
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(&entries[0]);
|
||||
}
|
||||
/**
|
||||
* Iterator pointing to the first stored elmement
|
||||
*
|
||||
* @return Iterator to the first element
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(&entries[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an Iterator pointing to the element after the last stored entry
|
||||
*
|
||||
* @return Iterator to the element after the last entry
|
||||
*/
|
||||
Iterator end() const {
|
||||
return Iterator(&entries[size]);
|
||||
}
|
||||
/**
|
||||
* returns an Iterator pointing to the element after the last stored entry
|
||||
*
|
||||
* @return Iterator to the element after the last entry
|
||||
*/
|
||||
Iterator end() const {
|
||||
return Iterator(&entries[size]);
|
||||
}
|
||||
|
||||
T & operator[](count_t i) const {
|
||||
return entries[i];
|
||||
}
|
||||
T & operator[](count_t i) const {
|
||||
return entries[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* The first element
|
||||
*
|
||||
* @return pointer to the first stored element
|
||||
*/
|
||||
T *front() {
|
||||
return entries;
|
||||
}
|
||||
/**
|
||||
* The first element
|
||||
*
|
||||
* @return pointer to the first stored element
|
||||
*/
|
||||
T *front() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* The last element
|
||||
*
|
||||
* does not return a valid pointer if called on an empty list.
|
||||
*
|
||||
* @return pointer to the last stored element
|
||||
*/
|
||||
T *back() {
|
||||
return &entries[size - 1];
|
||||
//Alternative solution
|
||||
//return const_cast<T*>(static_cast<const T*>(*this).back());
|
||||
}
|
||||
/**
|
||||
* The last element
|
||||
*
|
||||
* does not return a valid pointer if called on an empty list.
|
||||
*
|
||||
* @return pointer to the last stored element
|
||||
*/
|
||||
T *back() {
|
||||
return &entries[size - 1];
|
||||
//Alternative solution
|
||||
//return const_cast<T*>(static_cast<const T*>(*this).back());
|
||||
}
|
||||
|
||||
const T* back() const{
|
||||
return &entries[size-1];
|
||||
}
|
||||
const T* back() const{
|
||||
return &entries[size-1];
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of elements this List can contain
|
||||
*
|
||||
* @return maximum number of elements
|
||||
*/
|
||||
size_t maxSize() const {
|
||||
return this->maxSize_;
|
||||
}
|
||||
/**
|
||||
* The maximum number of elements this List can contain
|
||||
*
|
||||
* @return maximum number of elements
|
||||
*/
|
||||
size_t maxSize() const {
|
||||
return this->maxSize_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new element into the list.
|
||||
*
|
||||
* The new element is inserted after the last stored element.
|
||||
*
|
||||
* @param entry
|
||||
* @return
|
||||
* -@c FULL if the List is full
|
||||
* -@c RETURN_OK else
|
||||
*/
|
||||
ReturnValue_t insert(T entry) {
|
||||
if (size >= maxSize_) {
|
||||
return FULL;
|
||||
}
|
||||
entries[size] = entry;
|
||||
++size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
/**
|
||||
* Insert a new element into the list.
|
||||
*
|
||||
* The new element is inserted after the last stored element.
|
||||
*
|
||||
* @param entry
|
||||
* @return
|
||||
* -@c FULL if the List is full
|
||||
* -@c RETURN_OK else
|
||||
*/
|
||||
ReturnValue_t insert(T entry) {
|
||||
if (size >= maxSize_) {
|
||||
return FULL;
|
||||
}
|
||||
entries[size] = entry;
|
||||
++size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear the List
|
||||
*
|
||||
* This does not actually clear all entries, it only sets the size to 0.
|
||||
*/
|
||||
void clear() {
|
||||
size = 0;
|
||||
}
|
||||
/**
|
||||
* clear the List
|
||||
*
|
||||
* This does not actually clear all entries, it only sets the size to 0.
|
||||
*/
|
||||
void clear() {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
count_t remaining() {
|
||||
return (maxSize_ - size);
|
||||
}
|
||||
count_t remaining() {
|
||||
return (maxSize_ - size);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* pointer to the array in which the entries are stored
|
||||
*/
|
||||
T *entries;
|
||||
/**
|
||||
* remembering the maximum size
|
||||
*/
|
||||
size_t maxSize_;
|
||||
/**
|
||||
* pointer to the array in which the entries are stored
|
||||
*/
|
||||
T *entries;
|
||||
/**
|
||||
* remembering the maximum size
|
||||
*/
|
||||
size_t maxSize_;
|
||||
|
||||
/**
|
||||
* true if the array was allocated and needs to be deleted in the destructor.
|
||||
*/
|
||||
bool allocated;
|
||||
/**
|
||||
* true if the array was allocated and needs to be deleted in the destructor.
|
||||
*/
|
||||
bool allocated;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -7,65 +7,65 @@
|
||||
template<typename Tp>
|
||||
class BinaryNode {
|
||||
public:
|
||||
BinaryNode(Tp* setValue) :
|
||||
value(setValue), left(NULL), right(NULL), parent(NULL) {
|
||||
}
|
||||
Tp *value;
|
||||
BinaryNode* left;
|
||||
BinaryNode* right;
|
||||
BinaryNode* parent;
|
||||
BinaryNode(Tp* setValue) :
|
||||
value(setValue), left(NULL), right(NULL), parent(NULL) {
|
||||
}
|
||||
Tp *value;
|
||||
BinaryNode* left;
|
||||
BinaryNode* right;
|
||||
BinaryNode* parent;
|
||||
};
|
||||
|
||||
template<typename Tp>
|
||||
class ExplicitNodeIterator {
|
||||
public:
|
||||
typedef ExplicitNodeIterator<Tp> _Self;
|
||||
typedef BinaryNode<Tp> _Node;
|
||||
typedef Tp value_type;
|
||||
typedef Tp* pointer;
|
||||
typedef Tp& reference;
|
||||
ExplicitNodeIterator() :
|
||||
element(NULL) {
|
||||
}
|
||||
ExplicitNodeIterator(_Node* node) :
|
||||
element(node) {
|
||||
}
|
||||
BinaryNode<Tp>* element;
|
||||
_Self up() {
|
||||
return _Self(element->parent);
|
||||
}
|
||||
_Self left() {
|
||||
if (element != NULL) {
|
||||
return _Self(element->left);
|
||||
} else {
|
||||
return _Self(NULL);
|
||||
}
|
||||
typedef ExplicitNodeIterator<Tp> _Self;
|
||||
typedef BinaryNode<Tp> _Node;
|
||||
typedef Tp value_type;
|
||||
typedef Tp* pointer;
|
||||
typedef Tp& reference;
|
||||
ExplicitNodeIterator() :
|
||||
element(NULL) {
|
||||
}
|
||||
ExplicitNodeIterator(_Node* node) :
|
||||
element(node) {
|
||||
}
|
||||
BinaryNode<Tp>* element;
|
||||
_Self up() {
|
||||
return _Self(element->parent);
|
||||
}
|
||||
_Self left() {
|
||||
if (element != NULL) {
|
||||
return _Self(element->left);
|
||||
} else {
|
||||
return _Self(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
_Self right() {
|
||||
if (element != NULL) {
|
||||
return _Self(element->right);
|
||||
} else {
|
||||
return _Self(NULL);
|
||||
}
|
||||
}
|
||||
_Self right() {
|
||||
if (element != NULL) {
|
||||
return _Self(element->right);
|
||||
} else {
|
||||
return _Self(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
bool operator==(const _Self& __x) const {
|
||||
return element == __x.element;
|
||||
}
|
||||
bool operator!=(const _Self& __x) const {
|
||||
return element != __x.element;
|
||||
}
|
||||
}
|
||||
bool operator==(const _Self& __x) const {
|
||||
return element == __x.element;
|
||||
}
|
||||
bool operator!=(const _Self& __x) const {
|
||||
return element != __x.element;
|
||||
}
|
||||
pointer
|
||||
operator->() const {
|
||||
if (element != NULL) {
|
||||
return element->value;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
if (element != NULL) {
|
||||
return element->value;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
pointer operator*() const {
|
||||
return this->operator->();
|
||||
return this->operator->();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,77 +75,77 @@ public:
|
||||
template<typename Tp>
|
||||
class BinaryTree {
|
||||
public:
|
||||
typedef ExplicitNodeIterator<Tp> iterator;
|
||||
typedef BinaryNode<Tp> Node;
|
||||
typedef std::pair<iterator, iterator> children;
|
||||
BinaryTree() :
|
||||
rootNode(NULL) {
|
||||
}
|
||||
BinaryTree(Node* rootNode) :
|
||||
rootNode(rootNode) {
|
||||
}
|
||||
iterator begin() const {
|
||||
return iterator(rootNode);
|
||||
}
|
||||
static iterator end() {
|
||||
return iterator(NULL);
|
||||
}
|
||||
iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) {
|
||||
newNode->parent = parentNode.element;
|
||||
if (parentNode.element != NULL) {
|
||||
if (insertLeft) {
|
||||
parentNode.element->left = newNode;
|
||||
} else {
|
||||
parentNode.element->right = newNode;
|
||||
}
|
||||
} else {
|
||||
//Insert first element.
|
||||
rootNode = newNode;
|
||||
}
|
||||
return iterator(newNode);
|
||||
}
|
||||
//No recursion to children. Needs to be done externally.
|
||||
children erase(iterator node) {
|
||||
if (node.element == rootNode) {
|
||||
//We're root node
|
||||
rootNode = NULL;
|
||||
} else {
|
||||
//Delete parent's reference
|
||||
if (node.up().left() == node) {
|
||||
node.up().element->left = NULL;
|
||||
} else {
|
||||
node.up().element->right = NULL;
|
||||
}
|
||||
}
|
||||
return children(node.element->left, node.element->right);
|
||||
}
|
||||
static uint32_t countLeft(iterator start) {
|
||||
if (start == end()) {
|
||||
return 0;
|
||||
}
|
||||
//We also count the start node itself.
|
||||
uint32_t count = 1;
|
||||
while (start.left() != end()) {
|
||||
count++;
|
||||
start = start.left();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
static uint32_t countRight(iterator start) {
|
||||
if (start == end()) {
|
||||
return 0;
|
||||
}
|
||||
//We also count the start node itself.
|
||||
uint32_t count = 1;
|
||||
while (start.right() != end()) {
|
||||
count++;
|
||||
start = start.right();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
typedef ExplicitNodeIterator<Tp> iterator;
|
||||
typedef BinaryNode<Tp> Node;
|
||||
typedef std::pair<iterator, iterator> children;
|
||||
BinaryTree() :
|
||||
rootNode(NULL) {
|
||||
}
|
||||
BinaryTree(Node* rootNode) :
|
||||
rootNode(rootNode) {
|
||||
}
|
||||
iterator begin() const {
|
||||
return iterator(rootNode);
|
||||
}
|
||||
static iterator end() {
|
||||
return iterator(NULL);
|
||||
}
|
||||
iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) {
|
||||
newNode->parent = parentNode.element;
|
||||
if (parentNode.element != NULL) {
|
||||
if (insertLeft) {
|
||||
parentNode.element->left = newNode;
|
||||
} else {
|
||||
parentNode.element->right = newNode;
|
||||
}
|
||||
} else {
|
||||
//Insert first element.
|
||||
rootNode = newNode;
|
||||
}
|
||||
return iterator(newNode);
|
||||
}
|
||||
//No recursion to children. Needs to be done externally.
|
||||
children erase(iterator node) {
|
||||
if (node.element == rootNode) {
|
||||
//We're root node
|
||||
rootNode = NULL;
|
||||
} else {
|
||||
//Delete parent's reference
|
||||
if (node.up().left() == node) {
|
||||
node.up().element->left = NULL;
|
||||
} else {
|
||||
node.up().element->right = NULL;
|
||||
}
|
||||
}
|
||||
return children(node.element->left, node.element->right);
|
||||
}
|
||||
static uint32_t countLeft(iterator start) {
|
||||
if (start == end()) {
|
||||
return 0;
|
||||
}
|
||||
//We also count the start node itself.
|
||||
uint32_t count = 1;
|
||||
while (start.left() != end()) {
|
||||
count++;
|
||||
start = start.left();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
static uint32_t countRight(iterator start) {
|
||||
if (start == end()) {
|
||||
return 0;
|
||||
}
|
||||
//We also count the start node itself.
|
||||
uint32_t count = 1;
|
||||
while (start.right() != end()) {
|
||||
count++;
|
||||
start = start.right();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected:
|
||||
Node* rootNode;
|
||||
Node* rootNode;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
SharedRingBuffer.cpp
|
||||
SimpleRingBuffer.cpp
|
||||
PRIVATE
|
||||
SharedRingBuffer.cpp
|
||||
SimpleRingBuffer.cpp
|
||||
)
|
@@ -5,8 +5,8 @@
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief Simple First-In-First-Out data structure. The maximum size
|
||||
* can be set in the constructor.
|
||||
* @brief Simple First-In-First-Out data structure. The maximum size
|
||||
* can be set in the constructor.
|
||||
* @details
|
||||
* The maximum capacity can be determined at run-time, so this container
|
||||
* performs dynamic memory allocation!
|
||||
@@ -17,39 +17,39 @@
|
||||
template<typename T>
|
||||
class DynamicFIFO: public FIFOBase<T> {
|
||||
public:
|
||||
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
|
||||
fifoVector(maxCapacity) {
|
||||
// trying to pass the pointer of the uninitialized vector
|
||||
// to the FIFOBase constructor directly lead to a super evil bug.
|
||||
// So we do it like this now.
|
||||
this->setContainer(fifoVector.data());
|
||||
};
|
||||
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
|
||||
fifoVector(maxCapacity) {
|
||||
// trying to pass the pointer of the uninitialized vector
|
||||
// to the FIFOBase constructor directly lead to a super evil bug.
|
||||
// So we do it like this now.
|
||||
this->setContainer(fifoVector.data());
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Custom copy constructor which prevents setting the
|
||||
* underlying pointer wrong. This function allocates memory!
|
||||
* @details This is a very heavy operation so try to avoid this!
|
||||
*
|
||||
*/
|
||||
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
|
||||
fifoVector(other.maxCapacity) {
|
||||
this->fifoVector = other.fifoVector;
|
||||
this->setContainer(fifoVector.data());
|
||||
}
|
||||
/**
|
||||
* @brief Custom copy constructor which prevents setting the
|
||||
* underlying pointer wrong. This function allocates memory!
|
||||
* @details This is a very heavy operation so try to avoid this!
|
||||
*
|
||||
*/
|
||||
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
|
||||
fifoVector(other.maxCapacity) {
|
||||
this->fifoVector = other.fifoVector;
|
||||
this->setContainer(fifoVector.data());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Custom assignment operator
|
||||
* @details This is a very heavy operation so try to avoid this!
|
||||
* @param other DyamicFIFO to copy from
|
||||
*/
|
||||
DynamicFIFO& operator=(const DynamicFIFO& other){
|
||||
FIFOBase<T>::operator=(other);
|
||||
this->fifoVector = other.fifoVector;
|
||||
this->setContainer(fifoVector.data());
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Custom assignment operator
|
||||
* @details This is a very heavy operation so try to avoid this!
|
||||
* @param other DyamicFIFO to copy from
|
||||
*/
|
||||
DynamicFIFO& operator=(const DynamicFIFO& other){
|
||||
FIFOBase<T>::operator=(other);
|
||||
this->fifoVector = other.fifoVector;
|
||||
this->setContainer(fifoVector.data());
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
std::vector<T> fifoVector;
|
||||
std::vector<T> fifoVector;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CONTAINER_DYNAMICFIFO_H_ */
|
||||
|
@@ -5,8 +5,8 @@
|
||||
#include <array>
|
||||
|
||||
/**
|
||||
* @brief Simple First-In-First-Out data structure with size fixed at
|
||||
* compile time
|
||||
* @brief Simple First-In-First-Out data structure with size fixed at
|
||||
* compile time
|
||||
* @details
|
||||
* Performs no dynamic memory allocation.
|
||||
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
||||
@@ -16,32 +16,32 @@
|
||||
template<typename T, size_t capacity>
|
||||
class FIFO: public FIFOBase<T> {
|
||||
public:
|
||||
FIFO(): FIFOBase<T>(nullptr, capacity) {
|
||||
this->setContainer(fifoArray.data());
|
||||
};
|
||||
FIFO(): FIFOBase<T>(nullptr, capacity) {
|
||||
this->setContainer(fifoArray.data());
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Custom copy constructor to set pointer correctly.
|
||||
* @param other
|
||||
*/
|
||||
FIFO(const FIFO& other): FIFOBase<T>(other) {
|
||||
this->fifoArray = other.fifoArray;
|
||||
this->setContainer(fifoArray.data());
|
||||
}
|
||||
/**
|
||||
* @brief Custom copy constructor to set pointer correctly.
|
||||
* @param other
|
||||
*/
|
||||
FIFO(const FIFO& other): FIFOBase<T>(other) {
|
||||
this->fifoArray = other.fifoArray;
|
||||
this->setContainer(fifoArray.data());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Custom assignment operator
|
||||
* @param other
|
||||
*/
|
||||
FIFO& operator=(const FIFO& other){
|
||||
FIFOBase<T>::operator=(other);
|
||||
this->fifoArray = other.fifoArray;
|
||||
this->setContainer(fifoArray.data());
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Custom assignment operator
|
||||
* @param other
|
||||
*/
|
||||
FIFO& operator=(const FIFO& other){
|
||||
FIFOBase<T>::operator=(other);
|
||||
this->fifoArray = other.fifoArray;
|
||||
this->setContainer(fifoArray.data());
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<T, capacity> fifoArray;
|
||||
std::array<T, capacity> fifoArray;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CONTAINER_FIFO_H_ */
|
||||
|
@@ -8,70 +8,70 @@
|
||||
template <typename T>
|
||||
class FIFOBase {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
|
||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
|
||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
|
||||
|
||||
/** Default ctor, takes pointer to first entry of underlying container
|
||||
* and maximum capacity */
|
||||
FIFOBase(T* values, const size_t maxCapacity);
|
||||
/** Default ctor, takes pointer to first entry of underlying container
|
||||
* and maximum capacity */
|
||||
FIFOBase(T* values, const size_t maxCapacity);
|
||||
|
||||
/**
|
||||
* Insert value into FIFO
|
||||
* @param value
|
||||
* @return RETURN_OK on success, FULL if full
|
||||
*/
|
||||
ReturnValue_t insert(T value);
|
||||
/**
|
||||
* Retrieve item from FIFO. This removes the item from the FIFO.
|
||||
* @param value Must point to a valid T
|
||||
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
||||
*/
|
||||
ReturnValue_t retrieve(T *value);
|
||||
/**
|
||||
* Retrieve item from FIFO without removing it from FIFO.
|
||||
* @param value Must point to a valid T
|
||||
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
||||
*/
|
||||
ReturnValue_t peek(T * value);
|
||||
/**
|
||||
* Remove item from FIFO.
|
||||
* @return RETURN_OK on success, EMPTY if empty
|
||||
*/
|
||||
ReturnValue_t pop();
|
||||
/**
|
||||
* Insert value into FIFO
|
||||
* @param value
|
||||
* @return RETURN_OK on success, FULL if full
|
||||
*/
|
||||
ReturnValue_t insert(T value);
|
||||
/**
|
||||
* Retrieve item from FIFO. This removes the item from the FIFO.
|
||||
* @param value Must point to a valid T
|
||||
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
||||
*/
|
||||
ReturnValue_t retrieve(T *value);
|
||||
/**
|
||||
* Retrieve item from FIFO without removing it from FIFO.
|
||||
* @param value Must point to a valid T
|
||||
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
||||
*/
|
||||
ReturnValue_t peek(T * value);
|
||||
/**
|
||||
* Remove item from FIFO.
|
||||
* @return RETURN_OK on success, EMPTY if empty
|
||||
*/
|
||||
ReturnValue_t pop();
|
||||
|
||||
/***
|
||||
* Check if FIFO is empty
|
||||
* @return True if empty, False if not
|
||||
*/
|
||||
bool empty();
|
||||
/***
|
||||
* Check if FIFO is Full
|
||||
* @return True if full, False if not
|
||||
*/
|
||||
bool full();
|
||||
/***
|
||||
* Current used size (elements) used
|
||||
* @return size_t in elements
|
||||
*/
|
||||
size_t size();
|
||||
/***
|
||||
* Get maximal capacity of fifo
|
||||
* @return size_t with max capacity of this fifo
|
||||
*/
|
||||
size_t getMaxCapacity() const;
|
||||
/***
|
||||
* Check if FIFO is empty
|
||||
* @return True if empty, False if not
|
||||
*/
|
||||
bool empty();
|
||||
/***
|
||||
* Check if FIFO is Full
|
||||
* @return True if full, False if not
|
||||
*/
|
||||
bool full();
|
||||
/***
|
||||
* Current used size (elements) used
|
||||
* @return size_t in elements
|
||||
*/
|
||||
size_t size();
|
||||
/***
|
||||
* Get maximal capacity of fifo
|
||||
* @return size_t with max capacity of this fifo
|
||||
*/
|
||||
size_t getMaxCapacity() const;
|
||||
|
||||
protected:
|
||||
void setContainer(T* data);
|
||||
size_t maxCapacity = 0;
|
||||
void setContainer(T* data);
|
||||
size_t maxCapacity = 0;
|
||||
|
||||
T* values;
|
||||
T* values;
|
||||
|
||||
size_t readIndex = 0;
|
||||
size_t writeIndex = 0;
|
||||
size_t currentSize = 0;
|
||||
size_t readIndex = 0;
|
||||
size_t writeIndex = 0;
|
||||
size_t currentSize = 0;
|
||||
|
||||
size_t next(size_t current);
|
||||
size_t next(size_t current);
|
||||
};
|
||||
|
||||
#include "FIFOBase.tpp"
|
||||
|
@@ -7,87 +7,87 @@
|
||||
|
||||
template<typename T>
|
||||
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity):
|
||||
maxCapacity(maxCapacity), values(values){};
|
||||
maxCapacity(maxCapacity), values(values){};
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
||||
if (full()) {
|
||||
return FULL;
|
||||
} else {
|
||||
values[writeIndex] = value;
|
||||
writeIndex = next(writeIndex);
|
||||
++currentSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
if (full()) {
|
||||
return FULL;
|
||||
} else {
|
||||
values[writeIndex] = value;
|
||||
writeIndex = next(writeIndex);
|
||||
++currentSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
||||
if (empty()) {
|
||||
return EMPTY;
|
||||
} else {
|
||||
if (value == nullptr){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*value = values[readIndex];
|
||||
readIndex = next(readIndex);
|
||||
--currentSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
if (empty()) {
|
||||
return EMPTY;
|
||||
} else {
|
||||
if (value == nullptr){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*value = values[readIndex];
|
||||
readIndex = next(readIndex);
|
||||
--currentSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t FIFOBase<T>::peek(T* value) {
|
||||
if(empty()) {
|
||||
return EMPTY;
|
||||
} else {
|
||||
if (value == nullptr){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*value = values[readIndex];
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
if(empty()) {
|
||||
return EMPTY;
|
||||
} else {
|
||||
if (value == nullptr){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*value = values[readIndex];
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t FIFOBase<T>::pop() {
|
||||
T value;
|
||||
return this->retrieve(&value);
|
||||
T value;
|
||||
return this->retrieve(&value);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline bool FIFOBase<T>::empty() {
|
||||
return (currentSize == 0);
|
||||
return (currentSize == 0);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline bool FIFOBase<T>::full() {
|
||||
return (currentSize == maxCapacity);
|
||||
return (currentSize == maxCapacity);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline size_t FIFOBase<T>::size() {
|
||||
return currentSize;
|
||||
return currentSize;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline size_t FIFOBase<T>::next(size_t current) {
|
||||
++current;
|
||||
if (current == maxCapacity) {
|
||||
current = 0;
|
||||
}
|
||||
return current;
|
||||
++current;
|
||||
if (current == maxCapacity) {
|
||||
current = 0;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
||||
return maxCapacity;
|
||||
return maxCapacity;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline void FIFOBase<T>::setContainer(T *data) {
|
||||
this->values = data;
|
||||
this->values = data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -8,30 +8,32 @@
|
||||
*/
|
||||
template<typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
||||
class FixedArrayList: public ArrayList<T, count_t> {
|
||||
static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
|
||||
#if !defined(_MSC_VER)
|
||||
static_assert(MAX_SIZE <= (std::pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
|
||||
#endif
|
||||
private:
|
||||
T data[MAX_SIZE];
|
||||
T data[MAX_SIZE];
|
||||
public:
|
||||
FixedArrayList() :
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
}
|
||||
FixedArrayList() :
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
}
|
||||
|
||||
FixedArrayList(const FixedArrayList& other) :
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
memcpy(this->data, other.data, sizeof(this->data));
|
||||
this->entries = data;
|
||||
this->size = other.size;
|
||||
}
|
||||
FixedArrayList(const FixedArrayList& other) :
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
memcpy(this->data, other.data, sizeof(this->data));
|
||||
this->entries = data;
|
||||
this->size = other.size;
|
||||
}
|
||||
|
||||
FixedArrayList& operator=(FixedArrayList other) {
|
||||
memcpy(this->data, other.data, sizeof(this->data));
|
||||
this->entries = data;
|
||||
this->size = other.size;
|
||||
return *this;
|
||||
}
|
||||
FixedArrayList& operator=(FixedArrayList other) {
|
||||
memcpy(this->data, other.data, sizeof(this->data));
|
||||
this->entries = data;
|
||||
this->size = other.size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~FixedArrayList() {
|
||||
}
|
||||
virtual ~FixedArrayList() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -18,212 +18,212 @@
|
||||
*/
|
||||
template<typename key_t, typename T>
|
||||
class FixedMap: public SerializeIF {
|
||||
static_assert (std::is_trivially_copyable<T>::value or
|
||||
std::is_base_of<SerializeIF, T>::value,
|
||||
"Types used in FixedMap must either be trivial copy-able or a "
|
||||
"derived class from SerializeIF to be serialize-able");
|
||||
static_assert (std::is_trivially_copyable<T>::value or
|
||||
std::is_base_of<SerializeIF, T>::value,
|
||||
"Types used in FixedMap must either be trivial copy-able or a "
|
||||
"derived class from SerializeIF to be serialize-able");
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
|
||||
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
|
||||
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
|
||||
|
||||
private:
|
||||
static const key_t EMPTY_SLOT = -1;
|
||||
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
||||
uint32_t _size;
|
||||
static const key_t EMPTY_SLOT = -1;
|
||||
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
||||
uint32_t _size;
|
||||
|
||||
uint32_t findIndex(key_t key) const {
|
||||
if (_size == 0) {
|
||||
return 1;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < _size; ++i) {
|
||||
if (theMap[i].first == key) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
uint32_t findIndex(key_t key) const {
|
||||
if (_size == 0) {
|
||||
return 1;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < _size; ++i) {
|
||||
if (theMap[i].first == key) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
public:
|
||||
FixedMap(uint32_t maxSize) :
|
||||
theMap(maxSize), _size(0) {
|
||||
}
|
||||
FixedMap(uint32_t maxSize) :
|
||||
theMap(maxSize), _size(0) {
|
||||
}
|
||||
|
||||
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
|
||||
public:
|
||||
Iterator() :
|
||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
|
||||
}
|
||||
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
|
||||
public:
|
||||
Iterator() :
|
||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
|
||||
}
|
||||
|
||||
Iterator(std::pair<key_t, T> *pair) :
|
||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
|
||||
}
|
||||
};
|
||||
Iterator(std::pair<key_t, T> *pair) :
|
||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
|
||||
}
|
||||
};
|
||||
|
||||
friend bool operator==(const typename FixedMap::Iterator& lhs,
|
||||
const typename FixedMap::Iterator& rhs) {
|
||||
return (lhs.value == rhs.value);
|
||||
}
|
||||
friend bool operator==(const typename FixedMap::Iterator& lhs,
|
||||
const typename FixedMap::Iterator& rhs) {
|
||||
return (lhs.value == rhs.value);
|
||||
}
|
||||
|
||||
friend bool operator!=(const typename FixedMap::Iterator& lhs,
|
||||
const typename FixedMap::Iterator& rhs) {
|
||||
return not (lhs.value == rhs.value);
|
||||
}
|
||||
friend bool operator!=(const typename FixedMap::Iterator& lhs,
|
||||
const typename FixedMap::Iterator& rhs) {
|
||||
return not (lhs.value == rhs.value);
|
||||
}
|
||||
|
||||
Iterator begin() const {
|
||||
return Iterator(&theMap[0]);
|
||||
}
|
||||
Iterator begin() const {
|
||||
return Iterator(&theMap[0]);
|
||||
}
|
||||
|
||||
Iterator end() const {
|
||||
return Iterator(&theMap[_size]);
|
||||
}
|
||||
Iterator end() const {
|
||||
return Iterator(&theMap[_size]);
|
||||
}
|
||||
|
||||
uint32_t size() const {
|
||||
return _size;
|
||||
}
|
||||
uint32_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) {
|
||||
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
|
||||
return KEY_ALREADY_EXISTS;
|
||||
}
|
||||
if (_size == theMap.maxSize()) {
|
||||
return MAP_FULL;
|
||||
}
|
||||
theMap[_size].first = key;
|
||||
theMap[_size].second = value;
|
||||
if (storedValue != nullptr) {
|
||||
*storedValue = Iterator(&theMap[_size]);
|
||||
}
|
||||
++_size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) {
|
||||
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
|
||||
return KEY_ALREADY_EXISTS;
|
||||
}
|
||||
if (_size == theMap.maxSize()) {
|
||||
return MAP_FULL;
|
||||
}
|
||||
theMap[_size].first = key;
|
||||
theMap[_size].second = value;
|
||||
if (storedValue != nullptr) {
|
||||
*storedValue = Iterator(&theMap[_size]);
|
||||
}
|
||||
++_size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t insert(std::pair<key_t, T> pair) {
|
||||
return insert(pair.first, pair.second);
|
||||
}
|
||||
ReturnValue_t insert(std::pair<key_t, T> pair) {
|
||||
return insert(pair.first, pair.second);
|
||||
}
|
||||
|
||||
ReturnValue_t exists(key_t key) const {
|
||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||
if (findIndex(key) < _size) {
|
||||
result = HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
ReturnValue_t exists(key_t key) const {
|
||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||
if (findIndex(key) < _size) {
|
||||
result = HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t erase(Iterator *iter) {
|
||||
uint32_t i;
|
||||
if ((i = findIndex((*iter).value->first)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
theMap[i] = theMap[_size - 1];
|
||||
--_size;
|
||||
--((*iter).value);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
ReturnValue_t erase(Iterator *iter) {
|
||||
uint32_t i;
|
||||
if ((i = findIndex((*iter).value->first)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
theMap[i] = theMap[_size - 1];
|
||||
--_size;
|
||||
--((*iter).value);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t erase(key_t key) {
|
||||
uint32_t i;
|
||||
if ((i = findIndex(key)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
theMap[i] = theMap[_size - 1];
|
||||
--_size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
ReturnValue_t erase(key_t key) {
|
||||
uint32_t i;
|
||||
if ((i = findIndex(key)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
theMap[i] = theMap[_size - 1];
|
||||
--_size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
T *findValue(key_t key) const {
|
||||
return &theMap[findIndex(key)].second;
|
||||
}
|
||||
T *findValue(key_t key) const {
|
||||
return &theMap[findIndex(key)].second;
|
||||
}
|
||||
|
||||
Iterator find(key_t key) const {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return end();
|
||||
}
|
||||
return Iterator(&theMap[findIndex(key)]);
|
||||
}
|
||||
Iterator find(key_t key) const {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return end();
|
||||
}
|
||||
return Iterator(&theMap[findIndex(key)]);
|
||||
}
|
||||
|
||||
ReturnValue_t find(key_t key, T **value) const {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
*value = &theMap[findIndex(key)].second;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
ReturnValue_t find(key_t key, T **value) const {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
*value = &theMap[findIndex(key)].second;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
if(_size == 0) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool empty() {
|
||||
if(_size == 0) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool full() {
|
||||
if(_size >= theMap.maxSize()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool full() {
|
||||
if(_size >= theMap.maxSize()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_size = 0;
|
||||
}
|
||||
void clear() {
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
uint32_t maxSize() const {
|
||||
return theMap.maxSize();
|
||||
}
|
||||
uint32_t maxSize() const {
|
||||
return theMap.maxSize();
|
||||
}
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
size_t maxSize, Endianness streamEndianness) const {
|
||||
ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
|
||||
buffer, size, maxSize, streamEndianness);
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
|
||||
size, maxSize, streamEndianness);
|
||||
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
|
||||
maxSize, streamEndianness);
|
||||
++i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
size_t maxSize, Endianness streamEndianness) const {
|
||||
ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
|
||||
buffer, size, maxSize, streamEndianness);
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
|
||||
size, maxSize, streamEndianness);
|
||||
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
|
||||
maxSize, streamEndianness);
|
||||
++i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const {
|
||||
uint32_t printSize = sizeof(_size);
|
||||
uint32_t i = 0;
|
||||
virtual size_t getSerializedSize() const {
|
||||
uint32_t printSize = sizeof(_size);
|
||||
uint32_t i = 0;
|
||||
|
||||
for (i = 0; i < _size; ++i) {
|
||||
printSize += SerializeAdapter::getSerializedSize(
|
||||
&theMap[i].first);
|
||||
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
|
||||
}
|
||||
for (i = 0; i < _size; ++i) {
|
||||
printSize += SerializeAdapter::getSerializedSize(
|
||||
&theMap[i].first);
|
||||
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
|
||||
}
|
||||
|
||||
return printSize;
|
||||
}
|
||||
return printSize;
|
||||
}
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
|
||||
buffer, size, streamEndianness);
|
||||
if (this->_size > theMap.maxSize()) {
|
||||
return SerializeIF::TOO_MANY_ELEMENTS;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
|
||||
size, streamEndianness);
|
||||
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
|
||||
streamEndianness);
|
||||
++i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
|
||||
buffer, size, streamEndianness);
|
||||
if (this->_size > theMap.maxSize()) {
|
||||
return SerializeIF::TOO_MANY_ELEMENTS;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
|
||||
size, streamEndianness);
|
||||
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
|
||||
streamEndianness);
|
||||
++i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -34,172 +34,172 @@
|
||||
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
|
||||
class FixedOrderedMultimap {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
|
||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
|
||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
|
||||
|
||||
/***
|
||||
* Constructor which needs a size_t for the maximum allowed size
|
||||
*
|
||||
* Can not be resized during runtime
|
||||
*
|
||||
* Allocates memory at construction
|
||||
* @param maxSize size_t of Maximum allowed size
|
||||
*/
|
||||
/***
|
||||
* Constructor which needs a size_t for the maximum allowed size
|
||||
*
|
||||
* Can not be resized during runtime
|
||||
*
|
||||
* Allocates memory at construction
|
||||
* @param maxSize size_t of Maximum allowed size
|
||||
*/
|
||||
FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
|
||||
}
|
||||
|
||||
/***
|
||||
* Virtual destructor frees Memory by deleting its member
|
||||
*/
|
||||
virtual ~FixedOrderedMultimap() {
|
||||
}
|
||||
/***
|
||||
* Virtual destructor frees Memory by deleting its member
|
||||
*/
|
||||
virtual ~FixedOrderedMultimap() {
|
||||
}
|
||||
|
||||
/***
|
||||
* Special iterator for FixedOrderedMultimap
|
||||
*/
|
||||
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
|
||||
public:
|
||||
Iterator() :
|
||||
ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
|
||||
}
|
||||
/***
|
||||
* Special iterator for FixedOrderedMultimap
|
||||
*/
|
||||
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
|
||||
public:
|
||||
Iterator() :
|
||||
ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
|
||||
}
|
||||
|
||||
Iterator(std::pair<key_t, T> *pair) :
|
||||
ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
|
||||
}
|
||||
};
|
||||
Iterator(std::pair<key_t, T> *pair) :
|
||||
ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
|
||||
}
|
||||
};
|
||||
|
||||
/***
|
||||
* Returns an iterator pointing to the first element
|
||||
* @return Iterator pointing to first element
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(&theMap[0]);
|
||||
}
|
||||
/***
|
||||
* Returns an iterator pointing to the first element
|
||||
* @return Iterator pointing to first element
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(&theMap[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator pointing to one element past the end
|
||||
* @return Iterator pointing to one element past the end
|
||||
*/
|
||||
Iterator end() const {
|
||||
return Iterator(&theMap[_size]);
|
||||
}
|
||||
/**
|
||||
* Returns an iterator pointing to one element past the end
|
||||
* @return Iterator pointing to one element past the end
|
||||
*/
|
||||
Iterator end() const {
|
||||
return Iterator(&theMap[_size]);
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns the current size of the map (not maximum size!)
|
||||
* @return Current size
|
||||
*/
|
||||
size_t size() const{
|
||||
return _size;
|
||||
}
|
||||
/***
|
||||
* Returns the current size of the map (not maximum size!)
|
||||
* @return Current size
|
||||
*/
|
||||
size_t size() const{
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the map, does not deallocate any memory
|
||||
*/
|
||||
void clear(){
|
||||
_size = 0;
|
||||
}
|
||||
/**
|
||||
* Clears the map, does not deallocate any memory
|
||||
*/
|
||||
void clear(){
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum size of the map
|
||||
* @return Maximum size of the map
|
||||
*/
|
||||
size_t maxSize() const{
|
||||
return theMap.maxSize();
|
||||
}
|
||||
/**
|
||||
* Returns the maximum size of the map
|
||||
* @return Maximum size of the map
|
||||
*/
|
||||
size_t maxSize() const{
|
||||
return theMap.maxSize();
|
||||
}
|
||||
|
||||
/***
|
||||
* Used to insert a key and value separately.
|
||||
*
|
||||
* @param[in] key Key of the new element
|
||||
* @param[in] value Value of the new element
|
||||
* @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr
|
||||
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
||||
*/
|
||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
|
||||
/***
|
||||
* Used to insert a key and value separately.
|
||||
*
|
||||
* @param[in] key Key of the new element
|
||||
* @param[in] value Value of the new element
|
||||
* @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr
|
||||
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
||||
*/
|
||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
|
||||
|
||||
/***
|
||||
* Used to insert new pair instead of single values
|
||||
*
|
||||
* @param pair Pair to be inserted
|
||||
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
||||
*/
|
||||
ReturnValue_t insert(std::pair<key_t, T> pair);
|
||||
/***
|
||||
* Used to insert new pair instead of single values
|
||||
*
|
||||
* @param pair Pair to be inserted
|
||||
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
||||
*/
|
||||
ReturnValue_t insert(std::pair<key_t, T> pair);
|
||||
|
||||
/***
|
||||
* Can be used to check if a certain key is in the map
|
||||
* @param key Key to be checked
|
||||
* @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
|
||||
*/
|
||||
ReturnValue_t exists(key_t key) const;
|
||||
/***
|
||||
* Can be used to check if a certain key is in the map
|
||||
* @param key Key to be checked
|
||||
* @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
|
||||
*/
|
||||
ReturnValue_t exists(key_t key) const;
|
||||
|
||||
/***
|
||||
* Used to delete the element in the iterator
|
||||
*
|
||||
* The iterator will point to the element before or begin(),
|
||||
* but never to one element in front of the map.
|
||||
*
|
||||
* @warning The iterator needs to be valid and dereferenceable
|
||||
* @param[in/out] iter Pointer to iterator to the element that needs to be ereased
|
||||
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
||||
*/
|
||||
ReturnValue_t erase(Iterator *iter);
|
||||
/***
|
||||
* Used to delete the element in the iterator
|
||||
*
|
||||
* The iterator will point to the element before or begin(),
|
||||
* but never to one element in front of the map.
|
||||
*
|
||||
* @warning The iterator needs to be valid and dereferenceable
|
||||
* @param[in/out] iter Pointer to iterator to the element that needs to be ereased
|
||||
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
||||
*/
|
||||
ReturnValue_t erase(Iterator *iter);
|
||||
|
||||
/***
|
||||
* Used to erase by key
|
||||
* @param key Key to be erased
|
||||
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
||||
*/
|
||||
ReturnValue_t erase(key_t key);
|
||||
/***
|
||||
* Used to erase by key
|
||||
* @param key Key to be erased
|
||||
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
||||
*/
|
||||
ReturnValue_t erase(key_t key);
|
||||
|
||||
/***
|
||||
* Find returns the first appearance of the key
|
||||
*
|
||||
* If the key does not exist, it points to end()
|
||||
*
|
||||
* @param key Key to search for
|
||||
* @return Iterator pointing to the first entry of key
|
||||
*/
|
||||
Iterator find(key_t key) const{
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return end();
|
||||
}
|
||||
return Iterator(&theMap[findFirstIndex(key)]);
|
||||
};
|
||||
/***
|
||||
* Find returns the first appearance of the key
|
||||
*
|
||||
* If the key does not exist, it points to end()
|
||||
*
|
||||
* @param key Key to search for
|
||||
* @return Iterator pointing to the first entry of key
|
||||
*/
|
||||
Iterator find(key_t key) const{
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return end();
|
||||
}
|
||||
return Iterator(&theMap[findFirstIndex(key)]);
|
||||
};
|
||||
|
||||
/***
|
||||
* Finds first entry of the given key and returns a
|
||||
* pointer to the value
|
||||
*
|
||||
* @param key Key to search for
|
||||
* @param value Found value
|
||||
* @return RETURN_OK if it points to the value,
|
||||
* KEY_DOES_NOT_EXIST if the key is not in the map
|
||||
*/
|
||||
ReturnValue_t find(key_t key, T **value) const;
|
||||
/***
|
||||
* Finds first entry of the given key and returns a
|
||||
* pointer to the value
|
||||
*
|
||||
* @param key Key to search for
|
||||
* @param value Found value
|
||||
* @return RETURN_OK if it points to the value,
|
||||
* KEY_DOES_NOT_EXIST if the key is not in the map
|
||||
*/
|
||||
ReturnValue_t find(key_t key, T **value) const;
|
||||
|
||||
friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs,
|
||||
const typename FixedOrderedMultimap::Iterator& rhs) {
|
||||
return (lhs.value == rhs.value);
|
||||
}
|
||||
friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs,
|
||||
const typename FixedOrderedMultimap::Iterator& rhs) {
|
||||
return (lhs.value == rhs.value);
|
||||
}
|
||||
|
||||
friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
|
||||
const typename FixedOrderedMultimap::Iterator& rhs) {
|
||||
return not (lhs.value == rhs.value);
|
||||
}
|
||||
friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
|
||||
const typename FixedOrderedMultimap::Iterator& rhs) {
|
||||
return not (lhs.value == rhs.value);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef KEY_COMPARE compare;
|
||||
compare myComp;
|
||||
ArrayList<std::pair<key_t, T>, size_t> theMap;
|
||||
size_t _size;
|
||||
typedef KEY_COMPARE compare;
|
||||
compare myComp;
|
||||
ArrayList<std::pair<key_t, T>, size_t> theMap;
|
||||
size_t _size;
|
||||
|
||||
size_t findFirstIndex(key_t key, size_t startAt = 0) const;
|
||||
size_t findFirstIndex(key_t key, size_t startAt = 0) const;
|
||||
|
||||
size_t findNicePlace(key_t key) const;
|
||||
size_t findNicePlace(key_t key) const;
|
||||
|
||||
void removeFromPosition(size_t position);
|
||||
void removeFromPosition(size_t position);
|
||||
};
|
||||
|
||||
#include "FixedOrderedMultimap.tpp"
|
||||
|
@@ -4,105 +4,105 @@
|
||||
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
|
||||
if (_size == theMap.maxSize()) {
|
||||
return MAP_FULL;
|
||||
}
|
||||
size_t position = findNicePlace(key);
|
||||
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
|
||||
(_size - position) * sizeof(std::pair<key_t,T>));
|
||||
theMap[position].first = key;
|
||||
theMap[position].second = value;
|
||||
++_size;
|
||||
if (storedValue != nullptr) {
|
||||
*storedValue = Iterator(&theMap[position]);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
if (_size == theMap.maxSize()) {
|
||||
return MAP_FULL;
|
||||
}
|
||||
size_t position = findNicePlace(key);
|
||||
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
|
||||
(_size - position) * sizeof(std::pair<key_t,T>));
|
||||
theMap[position].first = key;
|
||||
theMap[position].second = value;
|
||||
++_size;
|
||||
if (storedValue != nullptr) {
|
||||
*storedValue = Iterator(&theMap[position]);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
|
||||
return insert(pair.first, pair.second);
|
||||
return insert(pair.first, pair.second);
|
||||
}
|
||||
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
|
||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||
if (findFirstIndex(key) < _size) {
|
||||
result = HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
return result;
|
||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||
if (findFirstIndex(key) < _size) {
|
||||
result = HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
|
||||
size_t i;
|
||||
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
removeFromPosition(i);
|
||||
if (*iter != begin()) {
|
||||
(*iter)--;
|
||||
} else {
|
||||
*iter = begin();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
size_t i;
|
||||
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
removeFromPosition(i);
|
||||
if (*iter != begin()) {
|
||||
(*iter)--;
|
||||
} else {
|
||||
*iter = begin();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
|
||||
size_t i;
|
||||
if ((i = findFirstIndex(key)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
do {
|
||||
removeFromPosition(i);
|
||||
i = findFirstIndex(key, i);
|
||||
} while (i < _size);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
size_t i;
|
||||
if ((i = findFirstIndex(key)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
do {
|
||||
removeFromPosition(i);
|
||||
i = findFirstIndex(key, i);
|
||||
} while (i < _size);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
*value = &theMap[findFirstIndex(key)].second;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
*value = &theMap[findFirstIndex(key)].second;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
|
||||
if (startAt >= _size) {
|
||||
return startAt + 1;
|
||||
}
|
||||
size_t i = startAt;
|
||||
for (i = startAt; i < _size; ++i) {
|
||||
if (theMap[i].first == key) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
if (startAt >= _size) {
|
||||
return startAt + 1;
|
||||
}
|
||||
size_t i = startAt;
|
||||
for (i = startAt; i < _size; ++i) {
|
||||
if (theMap[i].first == key) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
||||
size_t i = 0;
|
||||
for (i = 0; i < _size; ++i) {
|
||||
if (myComp(key, theMap[i].first)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
size_t i = 0;
|
||||
for (i = 0; i < _size; ++i) {
|
||||
if (myComp(key, theMap[i].first)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
|
||||
if (_size <= position) {
|
||||
return;
|
||||
}
|
||||
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
|
||||
(_size - position - 1) * sizeof(std::pair<key_t,T>));
|
||||
--_size;
|
||||
if (_size <= position) {
|
||||
return;
|
||||
}
|
||||
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
|
||||
(_size - position - 1) * sizeof(std::pair<key_t,T>));
|
||||
--_size;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -6,85 +6,85 @@
|
||||
|
||||
template<typename T, typename count_t = uint8_t>
|
||||
class HybridIterator: public LinkedElement<T>::Iterator,
|
||||
public ArrayList<T, count_t>::Iterator {
|
||||
public ArrayList<T, count_t>::Iterator {
|
||||
public:
|
||||
HybridIterator() {}
|
||||
HybridIterator() {}
|
||||
|
||||
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
|
||||
LinkedElement<T>::Iterator(*iter), value(iter->value),
|
||||
linked(true) {
|
||||
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
|
||||
LinkedElement<T>::Iterator(*iter), value(iter->value),
|
||||
linked(true) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator(LinkedElement<T> *start) :
|
||||
LinkedElement<T>::Iterator(start), value(start->value),
|
||||
linked(true) {
|
||||
HybridIterator(LinkedElement<T> *start) :
|
||||
LinkedElement<T>::Iterator(start), value(start->value),
|
||||
linked(true) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||
typename ArrayList<T, count_t>::Iterator end) :
|
||||
ArrayList<T, count_t>::Iterator(start), value(start.value),
|
||||
linked(false), end(end.value) {
|
||||
if (value == this->end) {
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||
typename ArrayList<T, count_t>::Iterator end) :
|
||||
ArrayList<T, count_t>::Iterator(start), value(start.value),
|
||||
linked(false), end(end.value) {
|
||||
if (value == this->end) {
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator(T *firstElement, T *lastElement) :
|
||||
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
|
||||
linked(false), end(++lastElement) {
|
||||
if (value == end) {
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
HybridIterator(T *firstElement, T *lastElement) :
|
||||
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
|
||||
linked(false), end(++lastElement) {
|
||||
if (value == end) {
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator& operator++() {
|
||||
if (linked) {
|
||||
LinkedElement<T>::Iterator::operator++();
|
||||
if (LinkedElement<T>::Iterator::value != nullptr) {
|
||||
value = LinkedElement<T>::Iterator::value->value;
|
||||
} else {
|
||||
value = nullptr;
|
||||
}
|
||||
} else {
|
||||
ArrayList<T, count_t>::Iterator::operator++();
|
||||
value = ArrayList<T, count_t>::Iterator::value;
|
||||
HybridIterator& operator++() {
|
||||
if (linked) {
|
||||
LinkedElement<T>::Iterator::operator++();
|
||||
if (LinkedElement<T>::Iterator::value != nullptr) {
|
||||
value = LinkedElement<T>::Iterator::value->value;
|
||||
} else {
|
||||
value = nullptr;
|
||||
}
|
||||
} else {
|
||||
ArrayList<T, count_t>::Iterator::operator++();
|
||||
value = ArrayList<T, count_t>::Iterator::value;
|
||||
|
||||
if (value == end) {
|
||||
value = nullptr;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
if (value == end) {
|
||||
value = nullptr;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
HybridIterator operator++(int) {
|
||||
HybridIterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
HybridIterator operator++(int) {
|
||||
HybridIterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const HybridIterator& other) const {
|
||||
return value == other.value;
|
||||
}
|
||||
bool operator==(const HybridIterator& other) const {
|
||||
return value == other.value;
|
||||
}
|
||||
|
||||
bool operator!=(const HybridIterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
bool operator!=(const HybridIterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
return *value;
|
||||
}
|
||||
T operator*() {
|
||||
return *value;
|
||||
}
|
||||
|
||||
T *operator->() {
|
||||
return value;
|
||||
}
|
||||
T *operator->() {
|
||||
return value;
|
||||
}
|
||||
|
||||
T* value = nullptr;
|
||||
T* value = nullptr;
|
||||
|
||||
private:
|
||||
bool linked = false;
|
||||
T *end = nullptr;
|
||||
bool linked = false;
|
||||
T *end = nullptr;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -22,50 +22,50 @@
|
||||
*/
|
||||
class PlacementFactory {
|
||||
public:
|
||||
PlacementFactory(StorageManagerIF* backend) :
|
||||
dataBackend(backend) {
|
||||
}
|
||||
PlacementFactory(StorageManagerIF* backend) :
|
||||
dataBackend(backend) {
|
||||
}
|
||||
|
||||
/***
|
||||
* Generates an object of type T in the backend storage.
|
||||
*
|
||||
* @warning Do not use with any Type that allocates memory internally!
|
||||
*
|
||||
* @tparam T Type of Object
|
||||
* @param args Constructor Arguments to be passed
|
||||
* @return A pointer to the new object or a nullptr in case of failure
|
||||
*/
|
||||
template<typename T, typename ... Args>
|
||||
T* generate(Args&&... args) {
|
||||
store_address_t tempId;
|
||||
uint8_t* pData = nullptr;
|
||||
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
|
||||
&pData);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return nullptr;
|
||||
}
|
||||
T* temp = new (pData) T(std::forward<Args>(args)...);
|
||||
return temp;
|
||||
}
|
||||
/***
|
||||
* Function to destroy the object allocated with generate and free space in backend.
|
||||
* This must be called by the user.
|
||||
*
|
||||
* @param thisElement Element to be destroyed
|
||||
* @return RETURN_OK if the element was destroyed, different errors on failure
|
||||
*/
|
||||
template<typename T>
|
||||
ReturnValue_t destroy(T* thisElement) {
|
||||
if (thisElement == nullptr){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
|
||||
thisElement->~T();
|
||||
uint8_t* pointer = (uint8_t*) (thisElement);
|
||||
return dataBackend->deleteData(pointer, sizeof(T));
|
||||
}
|
||||
/***
|
||||
* Generates an object of type T in the backend storage.
|
||||
*
|
||||
* @warning Do not use with any Type that allocates memory internally!
|
||||
*
|
||||
* @tparam T Type of Object
|
||||
* @param args Constructor Arguments to be passed
|
||||
* @return A pointer to the new object or a nullptr in case of failure
|
||||
*/
|
||||
template<typename T, typename ... Args>
|
||||
T* generate(Args&&... args) {
|
||||
store_address_t tempId;
|
||||
uint8_t* pData = nullptr;
|
||||
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
|
||||
&pData);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return nullptr;
|
||||
}
|
||||
T* temp = new (pData) T(std::forward<Args>(args)...);
|
||||
return temp;
|
||||
}
|
||||
/***
|
||||
* Function to destroy the object allocated with generate and free space in backend.
|
||||
* This must be called by the user.
|
||||
*
|
||||
* @param thisElement Element to be destroyed
|
||||
* @return RETURN_OK if the element was destroyed, different errors on failure
|
||||
*/
|
||||
template<typename T>
|
||||
ReturnValue_t destroy(T* thisElement) {
|
||||
if (thisElement == nullptr){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
|
||||
thisElement->~T();
|
||||
uint8_t* pointer = (uint8_t*) (thisElement);
|
||||
return dataBackend->deleteData(pointer, sizeof(T));
|
||||
}
|
||||
private:
|
||||
StorageManagerIF* dataBackend;
|
||||
StorageManagerIF* dataBackend;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */
|
||||
|
@@ -7,107 +7,107 @@
|
||||
template<uint8_t N_READ_PTRS = 1>
|
||||
class RingBufferBase {
|
||||
public:
|
||||
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
|
||||
start(startAddress), write(startAddress), size(size),
|
||||
overwriteOld(overwriteOld) {
|
||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||
read[count] = startAddress;
|
||||
}
|
||||
}
|
||||
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
|
||||
start(startAddress), write(startAddress), size(size),
|
||||
overwriteOld(overwriteOld) {
|
||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||
read[count] = startAddress;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~RingBufferBase() {}
|
||||
virtual ~RingBufferBase() {}
|
||||
|
||||
bool isFull(uint8_t n = 0) {
|
||||
return (availableWriteSpace(n) == 0);
|
||||
}
|
||||
bool isEmpty(uint8_t n = 0) {
|
||||
return (getAvailableReadData(n) == 0);
|
||||
}
|
||||
bool isFull(uint8_t n = 0) {
|
||||
return (availableWriteSpace(n) == 0);
|
||||
}
|
||||
bool isEmpty(uint8_t n = 0) {
|
||||
return (getAvailableReadData(n) == 0);
|
||||
}
|
||||
|
||||
size_t getAvailableReadData(uint8_t n = 0) const {
|
||||
return ((write + size) - read[n]) % size;
|
||||
}
|
||||
size_t availableWriteSpace(uint8_t n = 0) const {
|
||||
//One less to avoid ambiguous full/empty problem.
|
||||
return (((read[n] + size) - write - 1) % size);
|
||||
}
|
||||
size_t getAvailableReadData(uint8_t n = 0) const {
|
||||
return ((write + size) - read[n]) % size;
|
||||
}
|
||||
size_t availableWriteSpace(uint8_t n = 0) const {
|
||||
//One less to avoid ambiguous full/empty problem.
|
||||
return (((read[n] + size) - write - 1) % size);
|
||||
}
|
||||
|
||||
bool overwritesOld() const {
|
||||
return overwriteOld;
|
||||
}
|
||||
bool overwritesOld() const {
|
||||
return overwriteOld;
|
||||
}
|
||||
|
||||
size_t getMaxSize() const {
|
||||
return size - 1;
|
||||
}
|
||||
size_t getMaxSize() const {
|
||||
return size - 1;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
write = start;
|
||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||
read[count] = start;
|
||||
}
|
||||
}
|
||||
void clear() {
|
||||
write = start;
|
||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||
read[count] = start;
|
||||
}
|
||||
}
|
||||
|
||||
size_t writeTillWrap() {
|
||||
return (start + size) - write;
|
||||
}
|
||||
size_t writeTillWrap() {
|
||||
return (start + size) - write;
|
||||
}
|
||||
|
||||
size_t readTillWrap(uint8_t n = 0) {
|
||||
return (start + size) - read[n];
|
||||
}
|
||||
size_t readTillWrap(uint8_t n = 0) {
|
||||
return (start + size) - read[n];
|
||||
}
|
||||
|
||||
size_t getStart() const {
|
||||
return start;
|
||||
}
|
||||
size_t getStart() const {
|
||||
return start;
|
||||
}
|
||||
|
||||
protected:
|
||||
const size_t start;
|
||||
size_t write;
|
||||
size_t read[N_READ_PTRS];
|
||||
const size_t size;
|
||||
const bool overwriteOld;
|
||||
const size_t start;
|
||||
size_t write;
|
||||
size_t read[N_READ_PTRS];
|
||||
const size_t size;
|
||||
const bool overwriteOld;
|
||||
|
||||
void incrementWrite(uint32_t amount) {
|
||||
write = ((write + amount - start) % size) + start;
|
||||
}
|
||||
void incrementRead(uint32_t amount, uint8_t n = 0) {
|
||||
read[n] = ((read[n] + amount - start) % size) + start;
|
||||
}
|
||||
void incrementWrite(uint32_t amount) {
|
||||
write = ((write + amount - start) % size) + start;
|
||||
}
|
||||
void incrementRead(uint32_t amount, uint8_t n = 0) {
|
||||
read[n] = ((read[n] + amount - start) % size) + start;
|
||||
}
|
||||
|
||||
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
|
||||
if (getAvailableReadData(n) >= amount) {
|
||||
incrementRead(amount, n);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
|
||||
if (getAvailableReadData(n) >= amount) {
|
||||
incrementRead(amount, n);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t writeData(uint32_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
ReturnValue_t writeData(uint32_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
size_t getRead(uint8_t n = 0) const {
|
||||
return read[n];
|
||||
}
|
||||
size_t getRead(uint8_t n = 0) const {
|
||||
return read[n];
|
||||
}
|
||||
|
||||
void setRead(uint32_t read, uint8_t n = 0) {
|
||||
if (read >= start && read < (start+size)) {
|
||||
this->read[n] = read;
|
||||
}
|
||||
}
|
||||
void setRead(uint32_t read, uint8_t n = 0) {
|
||||
if (read >= start && read < (start+size)) {
|
||||
this->read[n] = read;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t getWrite() const {
|
||||
return write;
|
||||
}
|
||||
uint32_t getWrite() const {
|
||||
return write;
|
||||
}
|
||||
|
||||
void setWrite(uint32_t write) {
|
||||
this->write = write;
|
||||
}
|
||||
void setWrite(uint32_t write) {
|
||||
this->write = write;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */
|
||||
|
@@ -1,25 +1,28 @@
|
||||
#include "SharedRingBuffer.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
#include "../ipc/MutexHelper.h"
|
||||
#include "../ipc/MutexGuard.h"
|
||||
|
||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes):
|
||||
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
|
||||
maxExcessBytes) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
bool overwriteOld, size_t maxExcessBytes):
|
||||
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
|
||||
maxExcessBytes) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
|
||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
||||
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
||||
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
||||
maxExcessBytes) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
||||
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
||||
maxExcessBytes) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
SharedRingBuffer::~SharedRingBuffer() {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
}
|
||||
|
||||
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) {
|
||||
this->fifoDepth = fifoDepth;
|
||||
this->fifoDepth = fifoDepth;
|
||||
}
|
||||
|
||||
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
|
||||
@@ -38,20 +41,20 @@ MutexIF* SharedRingBuffer::getMutexHandle() const {
|
||||
}
|
||||
|
||||
ReturnValue_t SharedRingBuffer::initialize() {
|
||||
if(fifoDepth > 0) {
|
||||
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
|
||||
}
|
||||
return SystemObject::initialize();
|
||||
if(fifoDepth > 0) {
|
||||
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
|
||||
}
|
||||
return SystemObject::initialize();
|
||||
}
|
||||
|
||||
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
|
||||
if(receiveSizesFIFO == nullptr) {
|
||||
// Configuration error.
|
||||
if(receiveSizesFIFO == nullptr) {
|
||||
// Configuration error.
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
||||
<< " was not configured to have sizes FIFO, returning nullptr!"
|
||||
<< std::endl;
|
||||
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
||||
<< " was not configured to have sizes FIFO, returning nullptr!"
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
return receiveSizesFIFO;
|
||||
}
|
||||
return receiveSizesFIFO;
|
||||
}
|
||||
|
@@ -15,76 +15,79 @@
|
||||
* and unlock operations.
|
||||
*/
|
||||
class SharedRingBuffer: public SystemObject,
|
||||
public SimpleRingBuffer {
|
||||
public SimpleRingBuffer {
|
||||
public:
|
||||
/**
|
||||
* This constructor allocates a new internal buffer with the supplied size.
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
*/
|
||||
SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes);
|
||||
/**
|
||||
* This constructor allocates a new internal buffer with the supplied size.
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
*/
|
||||
SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes);
|
||||
/**
|
||||
* This constructor takes an external buffer with the specified size.
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
*/
|
||||
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes);
|
||||
|
||||
/**
|
||||
* @brief This function can be used to add an optional FIFO to the class
|
||||
* @details
|
||||
* This FIFO will be allocated in the initialize function (and will
|
||||
* have a fixed maximum size after that). It can be used to store
|
||||
* values like packet sizes, for example for a shared ring buffer
|
||||
* used by producer/consumer tasks.
|
||||
*/
|
||||
void setToUseReceiveSizeFIFO(size_t fifoDepth);
|
||||
virtual~ SharedRingBuffer();
|
||||
|
||||
/**
|
||||
* This constructor takes an external buffer with the specified size.
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
*/
|
||||
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes);
|
||||
/**
|
||||
* @brief This function can be used to add an optional FIFO to the class
|
||||
* @details
|
||||
* This FIFO will be allocated in the initialize function (and will
|
||||
* have a fixed maximum size after that). It can be used to store
|
||||
* values like packet sizes, for example for a shared ring buffer
|
||||
* used by producer/consumer tasks.
|
||||
*/
|
||||
void setToUseReceiveSizeFIFO(size_t fifoDepth);
|
||||
|
||||
/**
|
||||
* Unless a read-only constant value is read, all operations on the
|
||||
* shared ring buffer should be protected by calling this function.
|
||||
* @param timeoutType
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
|
||||
dur_millis_t timeout);
|
||||
/**
|
||||
* Any locked mutex also has to be unlocked, otherwise, access to the
|
||||
* shared ring buffer will be blocked.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t unlockRingBufferMutex();
|
||||
|
||||
/**
|
||||
* The mutex handle can be accessed directly, for example to perform
|
||||
* the lock with the #MutexHelper for a RAII compliant lock operation.
|
||||
* @return
|
||||
*/
|
||||
MutexIF* getMutexHandle() const;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
/**
|
||||
* Unless a read-only constant value is read, all operations on the
|
||||
* shared ring buffer should be protected by calling this function.
|
||||
* @param timeoutType
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
|
||||
dur_millis_t timeout);
|
||||
/**
|
||||
* Any locked mutex also has to be unlocked, otherwise, access to the
|
||||
* shared ring buffer will be blocked.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t unlockRingBufferMutex();
|
||||
|
||||
/**
|
||||
* If the shared ring buffer was configured to have a sizes FIFO, a handle
|
||||
* to that FIFO can be retrieved with this function.
|
||||
* Do not forget to protect access with a lock if required!
|
||||
* @return
|
||||
*/
|
||||
DynamicFIFO<size_t>* getReceiveSizesFIFO();
|
||||
/**
|
||||
* The mutex handle can be accessed directly, for example to perform
|
||||
* the lock with the #MutexGuard for a RAII compliant lock operation.
|
||||
* @return
|
||||
*/
|
||||
MutexIF* getMutexHandle() const;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
/**
|
||||
* If the shared ring buffer was configured to have a sizes FIFO, a handle
|
||||
* to that FIFO can be retrieved with this function.
|
||||
* Do not forget to protect access with a lock if required!
|
||||
* @return
|
||||
*/
|
||||
DynamicFIFO<size_t>* getReceiveSizesFIFO();
|
||||
private:
|
||||
MutexIF* mutex = nullptr;
|
||||
MutexIF* mutex = nullptr;
|
||||
|
||||
size_t fifoDepth = 0;
|
||||
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
|
||||
size_t fifoDepth = 0;
|
||||
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -2,31 +2,31 @@
|
||||
#include <cstring>
|
||||
|
||||
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes) :
|
||||
RingBufferBase<>(0, size, overwriteOld),
|
||||
maxExcessBytes(maxExcessBytes) {
|
||||
if(maxExcessBytes > size) {
|
||||
this->maxExcessBytes = size;
|
||||
}
|
||||
else {
|
||||
this->maxExcessBytes = maxExcessBytes;
|
||||
}
|
||||
buffer = new uint8_t[size + maxExcessBytes];
|
||||
size_t maxExcessBytes) :
|
||||
RingBufferBase<>(0, size, overwriteOld),
|
||||
maxExcessBytes(maxExcessBytes) {
|
||||
if(maxExcessBytes > size) {
|
||||
this->maxExcessBytes = size;
|
||||
}
|
||||
else {
|
||||
this->maxExcessBytes = maxExcessBytes;
|
||||
}
|
||||
buffer = new uint8_t[size + maxExcessBytes];
|
||||
}
|
||||
|
||||
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes):
|
||||
bool overwriteOld, size_t maxExcessBytes):
|
||||
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
|
||||
if(maxExcessBytes > size) {
|
||||
this->maxExcessBytes = size;
|
||||
}
|
||||
else {
|
||||
this->maxExcessBytes = maxExcessBytes;
|
||||
}
|
||||
if(maxExcessBytes > size) {
|
||||
this->maxExcessBytes = size;
|
||||
}
|
||||
else {
|
||||
this->maxExcessBytes = maxExcessBytes;
|
||||
}
|
||||
}
|
||||
|
||||
SimpleRingBuffer::~SimpleRingBuffer() {
|
||||
delete[] buffer;
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
||||
@@ -48,58 +48,58 @@ ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
||||
}
|
||||
|
||||
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
|
||||
if(getExcessBytes() > 0) {
|
||||
moveExcessBytesToStart();
|
||||
}
|
||||
incrementWrite(amount);
|
||||
if(getExcessBytes() > 0) {
|
||||
moveExcessBytesToStart();
|
||||
}
|
||||
incrementWrite(amount);
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
||||
size_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
size_t amountTillWrap = writeTillWrap();
|
||||
if (amountTillWrap >= amount) {
|
||||
// remaining size in buffer is sufficient to fit full amount.
|
||||
memcpy(&buffer[write], data, amount);
|
||||
}
|
||||
else {
|
||||
memcpy(&buffer[write], data, amountTillWrap);
|
||||
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
|
||||
}
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
size_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
size_t amountTillWrap = writeTillWrap();
|
||||
if (amountTillWrap >= amount) {
|
||||
// remaining size in buffer is sufficient to fit full amount.
|
||||
memcpy(&buffer[write], data, amount);
|
||||
}
|
||||
else {
|
||||
memcpy(&buffer[write], data, amountTillWrap);
|
||||
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
|
||||
}
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
|
||||
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
|
||||
size_t availableData = getAvailableReadData(READ_PTR);
|
||||
size_t amountTillWrap = readTillWrap(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (readRemaining) {
|
||||
// more data available than amount specified.
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != nullptr) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
if (amountTillWrap >= amount) {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amount);
|
||||
} else {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
|
||||
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
|
||||
}
|
||||
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
|
||||
size_t availableData = getAvailableReadData(READ_PTR);
|
||||
size_t amountTillWrap = readTillWrap(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (readRemaining) {
|
||||
// more data available than amount specified.
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != nullptr) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
if (amountTillWrap >= amount) {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amount);
|
||||
} else {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
|
||||
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
|
||||
}
|
||||
|
||||
if(incrementReadPtr) {
|
||||
deleteData(amount, readRemaining);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
if(incrementReadPtr) {
|
||||
deleteData(amount, readRemaining);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
size_t SimpleRingBuffer::getExcessBytes() const {
|
||||
@@ -114,18 +114,18 @@ void SimpleRingBuffer::moveExcessBytesToStart() {
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
|
||||
bool deleteRemaining, size_t* trueAmount) {
|
||||
size_t availableData = getAvailableReadData(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (deleteRemaining) {
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != nullptr) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
incrementRead(amount, READ_PTR);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
bool deleteRemaining, size_t* trueAmount) {
|
||||
size_t availableData = getAvailableReadData(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (deleteRemaining) {
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != nullptr) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
incrementRead(amount, READ_PTR);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* @brief Circular buffer implementation, useful for buffering
|
||||
* @brief Circular buffer implementation, useful for buffering
|
||||
* into data streams.
|
||||
* @details
|
||||
* Note that the deleteData() has to be called to increment the read pointer.
|
||||
@@ -25,104 +25,104 @@ public:
|
||||
* with getFreeElement.
|
||||
*
|
||||
*/
|
||||
SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes = 0);
|
||||
/**
|
||||
* This constructor takes an external buffer with the specified size.
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes = 0);
|
||||
/**
|
||||
* This constructor takes an external buffer with the specified size.
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
* @param maxExcessBytes
|
||||
* If the buffer can accomodate additional bytes for contigous write
|
||||
* operations with getFreeElement, this is the maximum allowed additional
|
||||
* size
|
||||
*/
|
||||
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes = 0);
|
||||
* @param maxExcessBytes
|
||||
* If the buffer can accomodate additional bytes for contigous write
|
||||
* operations with getFreeElement, this is the maximum allowed additional
|
||||
* size
|
||||
*/
|
||||
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes = 0);
|
||||
|
||||
virtual ~SimpleRingBuffer();
|
||||
virtual ~SimpleRingBuffer();
|
||||
|
||||
/**
|
||||
* Write to circular buffer and increment write pointer by amount.
|
||||
* @param data
|
||||
* @param amount
|
||||
* @return -@c RETURN_OK if write operation was successfull
|
||||
* -@c RETURN_FAILED if
|
||||
*/
|
||||
ReturnValue_t writeData(const uint8_t* data, size_t amount);
|
||||
/**
|
||||
* Write to circular buffer and increment write pointer by amount.
|
||||
* @param data
|
||||
* @param amount
|
||||
* @return -@c RETURN_OK if write operation was successfull
|
||||
* -@c RETURN_FAILED if
|
||||
*/
|
||||
ReturnValue_t writeData(const uint8_t* data, size_t amount);
|
||||
|
||||
/**
|
||||
* Returns a pointer to a free element. If the remaining buffer is
|
||||
* not large enough, the data will be written past the actual size
|
||||
* and the amount of excess bytes will be cached. This function
|
||||
* does not increment the write pointer!
|
||||
* @param writePointer Pointer to a pointer which can be used to write
|
||||
* contiguous blocks into the ring buffer
|
||||
* @param amount
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
|
||||
/**
|
||||
* Returns a pointer to a free element. If the remaining buffer is
|
||||
* not large enough, the data will be written past the actual size
|
||||
* and the amount of excess bytes will be cached. This function
|
||||
* does not increment the write pointer!
|
||||
* @param writePointer Pointer to a pointer which can be used to write
|
||||
* contiguous blocks into the ring buffer
|
||||
* @param amount
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
|
||||
|
||||
/**
|
||||
* This increments the write pointer and also copies the excess bytes
|
||||
* to the beginning. It should be called if the write operation
|
||||
* conducted after calling getFreeElement() was performed.
|
||||
* @return
|
||||
*/
|
||||
void confirmBytesWritten(size_t amount);
|
||||
/**
|
||||
* This increments the write pointer and also copies the excess bytes
|
||||
* to the beginning. It should be called if the write operation
|
||||
* conducted after calling getFreeElement() was performed.
|
||||
* @return
|
||||
*/
|
||||
void confirmBytesWritten(size_t amount);
|
||||
|
||||
virtual size_t getExcessBytes() const;
|
||||
/**
|
||||
* Helper functions which moves any excess bytes to the start
|
||||
* of the ring buffer.
|
||||
* @return
|
||||
*/
|
||||
virtual void moveExcessBytesToStart();
|
||||
virtual size_t getExcessBytes() const;
|
||||
/**
|
||||
* Helper functions which moves any excess bytes to the start
|
||||
* of the ring buffer.
|
||||
* @return
|
||||
*/
|
||||
virtual void moveExcessBytesToStart();
|
||||
|
||||
/**
|
||||
* Read from circular buffer at read pointer.
|
||||
* @param data
|
||||
* @param amount
|
||||
* @param incrementReadPtr
|
||||
* If this is set to true, the read pointer will be incremented.
|
||||
* If readRemaining is set to true, the read pointer will be incremented
|
||||
* accordingly.
|
||||
* @param readRemaining
|
||||
* If this is set to true, the data will be read even if the amount
|
||||
* specified exceeds the read data available.
|
||||
* @param trueAmount [out]
|
||||
* If readRemaining was set to true, the true amount read will be assigned
|
||||
* to the passed value.
|
||||
* @return
|
||||
* - @c RETURN_OK if data was read successfully
|
||||
* - @c RETURN_FAILED if not enough data was available and readRemaining
|
||||
* was set to false.
|
||||
*/
|
||||
ReturnValue_t readData(uint8_t* data, size_t amount,
|
||||
bool incrementReadPtr = false, bool readRemaining = false,
|
||||
size_t* trueAmount = nullptr);
|
||||
/**
|
||||
* Read from circular buffer at read pointer.
|
||||
* @param data
|
||||
* @param amount
|
||||
* @param incrementReadPtr
|
||||
* If this is set to true, the read pointer will be incremented.
|
||||
* If readRemaining is set to true, the read pointer will be incremented
|
||||
* accordingly.
|
||||
* @param readRemaining
|
||||
* If this is set to true, the data will be read even if the amount
|
||||
* specified exceeds the read data available.
|
||||
* @param trueAmount [out]
|
||||
* If readRemaining was set to true, the true amount read will be assigned
|
||||
* to the passed value.
|
||||
* @return
|
||||
* - @c RETURN_OK if data was read successfully
|
||||
* - @c RETURN_FAILED if not enough data was available and readRemaining
|
||||
* was set to false.
|
||||
*/
|
||||
ReturnValue_t readData(uint8_t* data, size_t amount,
|
||||
bool incrementReadPtr = false, bool readRemaining = false,
|
||||
size_t* trueAmount = nullptr);
|
||||
|
||||
/**
|
||||
* Delete data by incrementing read pointer.
|
||||
* @param amount
|
||||
* @param deleteRemaining
|
||||
* If the amount specified is larger than the remaing size to read and this
|
||||
* is set to true, the remaining amount will be deleted as well
|
||||
* @param trueAmount [out]
|
||||
* If deleteRemaining was set to true, the amount deleted will be assigned
|
||||
* to the passed value.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
|
||||
size_t* trueAmount = nullptr);
|
||||
/**
|
||||
* Delete data by incrementing read pointer.
|
||||
* @param amount
|
||||
* @param deleteRemaining
|
||||
* If the amount specified is larger than the remaing size to read and this
|
||||
* is set to true, the remaining amount will be deleted as well
|
||||
* @param trueAmount [out]
|
||||
* If deleteRemaining was set to true, the amount deleted will be assigned
|
||||
* to the passed value.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
|
||||
size_t* trueAmount = nullptr);
|
||||
|
||||
private:
|
||||
static const uint8_t READ_PTR = 0;
|
||||
uint8_t* buffer = nullptr;
|
||||
size_t maxExcessBytes;
|
||||
size_t excessBytes = 0;
|
||||
static const uint8_t READ_PTR = 0;
|
||||
uint8_t* buffer = nullptr;
|
||||
size_t maxExcessBytes;
|
||||
size_t excessBytes = 0;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */
|
||||
|
@@ -5,71 +5,71 @@
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* @brief Linked list data structure,
|
||||
* each entry has a pointer to the next entry (singly)
|
||||
* @brief Linked list data structure,
|
||||
* each entry has a pointer to the next entry (singly)
|
||||
* @ingroup container
|
||||
*/
|
||||
template<typename T>
|
||||
class LinkedElement {
|
||||
public:
|
||||
T *value;
|
||||
class Iterator {
|
||||
public:
|
||||
LinkedElement<T> *value = nullptr;
|
||||
Iterator() {}
|
||||
T *value;
|
||||
class Iterator {
|
||||
public:
|
||||
LinkedElement<T> *value = nullptr;
|
||||
Iterator() {}
|
||||
|
||||
Iterator(LinkedElement<T> *element) :
|
||||
value(element) {
|
||||
}
|
||||
Iterator(LinkedElement<T> *element) :
|
||||
value(element) {
|
||||
}
|
||||
|
||||
Iterator& operator++() {
|
||||
value = value->getNext();
|
||||
return *this;
|
||||
}
|
||||
Iterator& operator++() {
|
||||
value = value->getNext();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator++(int) {
|
||||
Iterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
Iterator operator++(int) {
|
||||
Iterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(Iterator other) {
|
||||
return value == other.value;
|
||||
}
|
||||
bool operator==(Iterator other) {
|
||||
return value == other.value;
|
||||
}
|
||||
|
||||
bool operator!=(Iterator other) {
|
||||
return !(*this == other);
|
||||
}
|
||||
T *operator->() {
|
||||
return value->value;
|
||||
}
|
||||
};
|
||||
bool operator!=(Iterator other) {
|
||||
return !(*this == other);
|
||||
}
|
||||
T *operator->() {
|
||||
return value->value;
|
||||
}
|
||||
};
|
||||
|
||||
LinkedElement(T* setElement, LinkedElement<T>* setNext = nullptr):
|
||||
value(setElement), next(setNext) {}
|
||||
LinkedElement(T* setElement, LinkedElement<T>* setNext = nullptr):
|
||||
value(setElement), next(setNext) {}
|
||||
|
||||
virtual ~LinkedElement(){}
|
||||
virtual ~LinkedElement(){}
|
||||
|
||||
virtual LinkedElement* getNext() const {
|
||||
return next;
|
||||
}
|
||||
virtual LinkedElement* getNext() const {
|
||||
return next;
|
||||
}
|
||||
|
||||
virtual void setNext(LinkedElement* next) {
|
||||
this->next = next;
|
||||
}
|
||||
virtual void setNext(LinkedElement* next) {
|
||||
this->next = next;
|
||||
}
|
||||
|
||||
virtual void setEnd() {
|
||||
this->next = nullptr;
|
||||
}
|
||||
virtual void setEnd() {
|
||||
this->next = nullptr;
|
||||
}
|
||||
|
||||
LinkedElement* begin() {
|
||||
return this;
|
||||
}
|
||||
LinkedElement* end() {
|
||||
return nullptr;
|
||||
}
|
||||
LinkedElement* begin() {
|
||||
return this;
|
||||
}
|
||||
LinkedElement* end() {
|
||||
return nullptr;
|
||||
}
|
||||
private:
|
||||
LinkedElement *next;
|
||||
LinkedElement *next;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -77,52 +77,52 @@ class SinglyLinkedList {
|
||||
public:
|
||||
using ElementIterator = typename LinkedElement<T>::Iterator;
|
||||
|
||||
SinglyLinkedList() {}
|
||||
SinglyLinkedList() {}
|
||||
|
||||
SinglyLinkedList(ElementIterator start) :
|
||||
start(start.value) {}
|
||||
SinglyLinkedList(ElementIterator start) :
|
||||
start(start.value) {}
|
||||
|
||||
SinglyLinkedList(LinkedElement<T>* startElement) :
|
||||
start(startElement) {}
|
||||
SinglyLinkedList(LinkedElement<T>* startElement) :
|
||||
start(startElement) {}
|
||||
|
||||
ElementIterator begin() const {
|
||||
return ElementIterator::Iterator(start);
|
||||
}
|
||||
ElementIterator begin() const {
|
||||
return ElementIterator::Iterator(start);
|
||||
}
|
||||
|
||||
/** Returns iterator to nulltr */
|
||||
ElementIterator end() const {
|
||||
return ElementIterator::Iterator();
|
||||
}
|
||||
/** Returns iterator to nulltr */
|
||||
ElementIterator end() const {
|
||||
return ElementIterator::Iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns last element in singly linked list.
|
||||
* @return
|
||||
*/
|
||||
ElementIterator back() const {
|
||||
LinkedElement<T> *element = start;
|
||||
while (element->getNext() != nullptr) {
|
||||
element = element->getNext();
|
||||
}
|
||||
return ElementIterator::Iterator(element);
|
||||
}
|
||||
/**
|
||||
* Returns last element in singly linked list.
|
||||
* @return
|
||||
*/
|
||||
ElementIterator back() const {
|
||||
LinkedElement<T> *element = start;
|
||||
while (element->getNext() != nullptr) {
|
||||
element = element->getNext();
|
||||
}
|
||||
return ElementIterator::Iterator(element);
|
||||
}
|
||||
|
||||
size_t getSize() const {
|
||||
size_t size = 0;
|
||||
LinkedElement<T> *element = start;
|
||||
while (element != nullptr) {
|
||||
size++;
|
||||
element = element->getNext();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
void setStart(LinkedElement<T>* firstElement) {
|
||||
start = firstElement;
|
||||
}
|
||||
size_t getSize() const {
|
||||
size_t size = 0;
|
||||
LinkedElement<T> *element = start;
|
||||
while (element != nullptr) {
|
||||
size++;
|
||||
element = element->getNext();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
void setStart(LinkedElement<T>* firstElement) {
|
||||
start = firstElement;
|
||||
}
|
||||
|
||||
void setNext(LinkedElement<T>* currentElement,
|
||||
LinkedElement<T>* nextElement) {
|
||||
currentElement->setNext(nextElement);
|
||||
}
|
||||
void setNext(LinkedElement<T>* currentElement,
|
||||
LinkedElement<T>* nextElement) {
|
||||
currentElement->setNext(nextElement);
|
||||
}
|
||||
|
||||
void setLast(LinkedElement<T>* lastElement) {
|
||||
lastElement->setEnd();
|
||||
@@ -148,7 +148,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
LinkedElement<T> *start = nullptr;
|
||||
LinkedElement<T> *start = nullptr;
|
||||
};
|
||||
|
||||
#endif /* SINGLYLINKEDLIST_H_ */
|
||||
|
@@ -1,4 +1,4 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ControllerBase.cpp
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
ControllerBase.cpp
|
||||
ExtendedControllerBase.cpp
|
||||
)
|
@@ -5,128 +5,128 @@
|
||||
#include "../action/HasActionsIF.h"
|
||||
|
||||
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||
size_t commandQueueDepth) :
|
||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
|
||||
submode(SUBMODE_NONE), modeHelper(this),
|
||||
healthHelper(this, setObjectId) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||
commandQueueDepth);
|
||||
size_t commandQueueDepth) :
|
||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
|
||||
submode(SUBMODE_NONE), modeHelper(this),
|
||||
healthHelper(this, setObjectId) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||
commandQueueDepth);
|
||||
}
|
||||
|
||||
ControllerBase::~ControllerBase() {
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
MessageQueueId_t parentQueue = 0;
|
||||
if (parentId != objects::NO_OBJECT) {
|
||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
||||
if (parent == nullptr) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
parentQueue = parent->getCommandQueue();
|
||||
MessageQueueId_t parentQueue = 0;
|
||||
if (parentId != objects::NO_OBJECT) {
|
||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
||||
if (parent == nullptr) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
parentQueue = parent->getCommandQueue();
|
||||
|
||||
parent->registerChild(getObjectId());
|
||||
}
|
||||
parent->registerChild(getObjectId());
|
||||
}
|
||||
|
||||
result = healthHelper.initialize(parentQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = healthHelper.initialize(parentQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = modeHelper.initialize(parentQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = modeHelper.initialize(parentQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t ControllerBase::getCommandQueue() const {
|
||||
return commandQueue->getId();
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
void ControllerBase::handleQueue() {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
for (result = commandQueue->receiveMessage(&command);
|
||||
result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&command)) {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
for (result = commandQueue->receiveMessage(&command);
|
||||
result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&command)) {
|
||||
|
||||
result = modeHelper.handleModeCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
result = modeHelper.handleModeCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = healthHelper.handleHealthCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
result = handleCommandMessage(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
command.setToUnknownCommand();
|
||||
commandQueue->reply(&command);
|
||||
}
|
||||
result = healthHelper.handleHealthCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
result = handleCommandMessage(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
command.setToUnknownCommand();
|
||||
commandQueue->reply(&command);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||
changeHK(this->mode, this->submode, false);
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
this->mode = mode;
|
||||
this->submode = submode;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
changeHK(this->mode, this->submode, true);
|
||||
changeHK(this->mode, this->submode, false);
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
this->mode = mode;
|
||||
this->submode = submode;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
changeHK(this->mode, this->submode, true);
|
||||
}
|
||||
|
||||
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
||||
*mode = this->mode;
|
||||
*submode = this->submode;
|
||||
*mode = this->mode;
|
||||
*submode = this->submode;
|
||||
}
|
||||
|
||||
void ControllerBase::setToExternalControl() {
|
||||
healthHelper.setHealth(EXTERNAL_CONTROL);
|
||||
healthHelper.setHealth(EXTERNAL_CONTROL);
|
||||
}
|
||||
|
||||
void ControllerBase::announceMode(bool recursive) {
|
||||
triggerEvent(MODE_INFO, mode, submode);
|
||||
triggerEvent(MODE_INFO, mode, submode);
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
performControlOperation();
|
||||
return RETURN_OK;
|
||||
handleQueue();
|
||||
performControlOperation();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||
switch (health) {
|
||||
case HEALTHY:
|
||||
case EXTERNAL_CONTROL:
|
||||
healthHelper.setHealth(health);
|
||||
return RETURN_OK;
|
||||
default:
|
||||
return INVALID_HEALTH_STATE;
|
||||
}
|
||||
switch (health) {
|
||||
case HEALTHY:
|
||||
case EXTERNAL_CONTROL:
|
||||
healthHelper.setHealth(health);
|
||||
return RETURN_OK;
|
||||
default:
|
||||
return INVALID_HEALTH_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
HasHealthIF::HealthState ControllerBase::getHealth() {
|
||||
return healthHelper.getHealth();
|
||||
return healthHelper.getHealth();
|
||||
}
|
||||
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
|
||||
executingTask = task_;
|
||||
executingTask = task_;
|
||||
}
|
||||
|
||||
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||
|
@@ -17,39 +17,39 @@
|
||||
* a mode and a health state. This avoids boilerplate code.
|
||||
*/
|
||||
class ControllerBase: public HasModesIF,
|
||||
public HasHealthIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject,
|
||||
public HasReturnvaluesIF {
|
||||
public HasHealthIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject,
|
||||
public HasReturnvaluesIF {
|
||||
public:
|
||||
static const Mode_t MODE_NORMAL = 2;
|
||||
static const Mode_t MODE_NORMAL = 2;
|
||||
|
||||
ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||
size_t commandQueueDepth = 3);
|
||||
virtual ~ControllerBase();
|
||||
ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||
size_t commandQueueDepth = 3);
|
||||
virtual ~ControllerBase();
|
||||
|
||||
/** SystemObject override */
|
||||
virtual ReturnValue_t initialize() override;
|
||||
/** SystemObject override */
|
||||
virtual ReturnValue_t initialize() override;
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
/** HasHealthIF overrides */
|
||||
virtual ReturnValue_t setHealth(HealthState health) override;
|
||||
virtual HasHealthIF::HealthState getHealth() override;
|
||||
/** HasHealthIF overrides */
|
||||
virtual ReturnValue_t setHealth(HealthState health) override;
|
||||
virtual HasHealthIF::HealthState getHealth() override;
|
||||
|
||||
/** ExecutableObjectIF overrides */
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
virtual void setTaskIF(PeriodicTaskIF* task) override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
/** ExecutableObjectIF overrides */
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
virtual void setTaskIF(PeriodicTaskIF* task) override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Implemented by child class. Handle command messages which are not
|
||||
* mode or health messages.
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
/**
|
||||
* Implemented by child class. Handle command messages which are not
|
||||
* mode or health messages.
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
||||
|
||||
/**
|
||||
@@ -60,35 +60,35 @@ protected:
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) = 0;
|
||||
|
||||
const object_id_t parentId;
|
||||
const object_id_t parentId;
|
||||
|
||||
Mode_t mode;
|
||||
Mode_t mode;
|
||||
|
||||
Submode_t submode;
|
||||
Submode_t submode;
|
||||
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
|
||||
ModeHelper modeHelper;
|
||||
ModeHelper modeHelper;
|
||||
|
||||
HealthHelper healthHelper;
|
||||
HealthHelper healthHelper;
|
||||
|
||||
/**
|
||||
* Pointer to the task which executes this component,
|
||||
* is invalid before setTaskIF was called.
|
||||
*/
|
||||
PeriodicTaskIF* executingTask = nullptr;
|
||||
/**
|
||||
* Pointer to the task which executes this component,
|
||||
* is invalid before setTaskIF was called.
|
||||
*/
|
||||
PeriodicTaskIF* executingTask = nullptr;
|
||||
|
||||
/** Handle mode and health messages */
|
||||
virtual void handleQueue();
|
||||
/** Handle mode and health messages */
|
||||
virtual void handleQueue();
|
||||
|
||||
/** Mode helpers */
|
||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||
virtual void setToExternalControl();
|
||||
virtual void announceMode(bool recursive);
|
||||
/** HK helpers */
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
/** Mode helpers */
|
||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||
virtual void setToExternalControl();
|
||||
virtual void announceMode(bool recursive);
|
||||
/** HK helpers */
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
};
|
||||
|
||||
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */
|
||||
|
@@ -8,17 +8,12 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId,
|
||||
actionHelper(this, commandQueue) {
|
||||
}
|
||||
|
||||
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t *data, size_t size) {
|
||||
// needs to be overriden and implemented by child class.
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
ExtendedControllerBase::~ExtendedControllerBase() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
ReturnValue_t ExtendedControllerBase::initializeLocalDataPool(
|
||||
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
// needs to be overriden and implemented by child class.
|
||||
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t *data, size_t size) {
|
||||
/* Needs to be overriden and implemented by child class. */
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
@@ -93,8 +88,10 @@ ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
|
||||
|
||||
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
poolManager.performHkOperation();
|
||||
performControlOperation();
|
||||
/* We do this after performing control operation because variables will be set changed
|
||||
in this function. */
|
||||
poolManager.performHkOperation();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
@@ -102,14 +99,6 @@ MessageQueueId_t ExtendedControllerBase::getCommandQueue() const {
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase* ExtendedControllerBase::getDataSetHandle(sid_t sid) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "ExtendedControllerBase::getDataSetHandle: No child "
|
||||
<< " implementation provided, returning nullptr!" << std::endl;
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() {
|
||||
return &poolManager;
|
||||
}
|
||||
|
@@ -22,13 +22,14 @@ class ExtendedControllerBase: public ControllerBase,
|
||||
public:
|
||||
ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
|
||||
size_t commandQueueDepth = 3);
|
||||
virtual ~ExtendedControllerBase();
|
||||
|
||||
/** SystemObjectIF overrides */
|
||||
/* SystemObjectIF overrides */
|
||||
virtual ReturnValue_t initialize() override;
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
/** ExecutableObjectIF overrides */
|
||||
/* ExecutableObjectIF overrides */
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
@@ -49,22 +50,22 @@ protected:
|
||||
*/
|
||||
virtual void performControlOperation() = 0;
|
||||
|
||||
/** Handle the four messages mentioned above */
|
||||
/* Handle the four messages mentioned above */
|
||||
void handleQueue() override;
|
||||
|
||||
/** HasActionsIF overrides */
|
||||
/* HasActionsIF overrides */
|
||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data,
|
||||
size_t size) override;
|
||||
|
||||
/** HasLocalDatapoolIF overrides */
|
||||
/* HasLocalDatapoolIF overrides */
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||
virtual object_id_t getObjectId() const override;
|
||||
virtual ReturnValue_t initializeLocalDataPool(
|
||||
localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
virtual uint32_t getPeriodicOperationFrequency() const override;
|
||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
|
||||
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override = 0;
|
||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -18,15 +18,13 @@ class PoolVariableIF;
|
||||
class DataSetIF {
|
||||
public:
|
||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS;
|
||||
static constexpr ReturnValue_t INVALID_PARAMETER_DEFINITION =
|
||||
MAKE_RETURN_CODE( 0x01 );
|
||||
static constexpr ReturnValue_t SET_WAS_ALREADY_READ = MAKE_RETURN_CODE( 0x02 );
|
||||
static constexpr ReturnValue_t COMMITING_WITHOUT_READING =
|
||||
MAKE_RETURN_CODE(0x03);
|
||||
static constexpr ReturnValue_t INVALID_PARAMETER_DEFINITION = MAKE_RETURN_CODE(1);
|
||||
static constexpr ReturnValue_t SET_WAS_ALREADY_READ = MAKE_RETURN_CODE(2);
|
||||
static constexpr ReturnValue_t COMMITING_WITHOUT_READING = MAKE_RETURN_CODE(3);
|
||||
|
||||
static constexpr ReturnValue_t DATA_SET_UNINITIALISED = MAKE_RETURN_CODE( 0x04 );
|
||||
static constexpr ReturnValue_t DATA_SET_FULL = MAKE_RETURN_CODE( 0x05 );
|
||||
static constexpr ReturnValue_t POOL_VAR_NULL = MAKE_RETURN_CODE( 0x06 );
|
||||
static constexpr ReturnValue_t DATA_SET_UNINITIALISED = MAKE_RETURN_CODE(4);
|
||||
static constexpr ReturnValue_t DATA_SET_FULL = MAKE_RETURN_CODE(5);
|
||||
static constexpr ReturnValue_t POOL_VAR_NULL = MAKE_RETURN_CODE(6);
|
||||
|
||||
/**
|
||||
* @brief This is an empty virtual destructor,
|
||||
|
@@ -7,7 +7,7 @@ HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) :
|
||||
}
|
||||
|
||||
HkSwitchHelper::~HkSwitchHelper() {
|
||||
// TODO Auto-generated destructor stub
|
||||
QueueFactory::instance()->deleteMessageQueue(actionQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::initialize() {
|
||||
|
@@ -1,71 +1,82 @@
|
||||
#include "PoolDataSetBase.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "ReadCommitIFAttorney.h"
|
||||
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxFillCount):
|
||||
registeredVariables(registeredVariablesArray),
|
||||
maxFillCount(maxFillCount) {
|
||||
}
|
||||
maxFillCount(maxFillCount) {}
|
||||
|
||||
PoolDataSetBase::~PoolDataSetBase() {}
|
||||
|
||||
|
||||
ReturnValue_t PoolDataSetBase::registerVariable(
|
||||
PoolVariableIF *variable) {
|
||||
if (state != States::STATE_SET_UNINITIALISED) {
|
||||
ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF *variable) {
|
||||
if(registeredVariables == nullptr) {
|
||||
/* Underlying container invalid */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if (state != States::STATE_SET_UNINITIALISED) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DataSet::registerVariable: "
|
||||
"Call made in wrong position." << std::endl;
|
||||
sif::error << "DataSet::registerVariable: Call made in wrong position." << std::endl;
|
||||
#else
|
||||
sif::printError("DataSet::registerVariable: Call made in wrong position.");
|
||||
#endif
|
||||
return DataSetIF::DATA_SET_UNINITIALISED;
|
||||
}
|
||||
if (variable == nullptr) {
|
||||
return DataSetIF::DATA_SET_UNINITIALISED;
|
||||
}
|
||||
if (variable == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DataSet::registerVariable: "
|
||||
"Pool variable is nullptr." << std::endl;
|
||||
sif::error << "DataSet::registerVariable: Pool variable is nullptr." << std::endl;
|
||||
#else
|
||||
sif::printError("DataSet::registerVariable: Pool variable is nullptr.\n");
|
||||
#endif
|
||||
return DataSetIF::POOL_VAR_NULL;
|
||||
}
|
||||
if (fillCount >= maxFillCount) {
|
||||
return DataSetIF::POOL_VAR_NULL;
|
||||
}
|
||||
if (fillCount >= maxFillCount) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DataSet::registerVariable: "
|
||||
"DataSet is full." << std::endl;
|
||||
sif::error << "DataSet::registerVariable: DataSet is full." << std::endl;
|
||||
#else
|
||||
sif::printError("DataSet::registerVariable: DataSet is full.\n");
|
||||
#endif
|
||||
return DataSetIF::DATA_SET_FULL;
|
||||
}
|
||||
registeredVariables[fillCount] = variable;
|
||||
fillCount++;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return DataSetIF::DATA_SET_FULL;
|
||||
}
|
||||
registeredVariables[fillCount] = variable;
|
||||
fillCount++;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t lockTimeout) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t error = result;
|
||||
if (state == States::STATE_SET_UNINITIALISED) {
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = readVariable(count);
|
||||
if(result != RETURN_OK) {
|
||||
error = result;
|
||||
}
|
||||
}
|
||||
state = States::STATE_SET_WAS_READ;
|
||||
unlockDataPool();
|
||||
}
|
||||
else {
|
||||
uint32_t lockTimeout) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t error = result;
|
||||
if (state == States::STATE_SET_UNINITIALISED) {
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = readVariable(count);
|
||||
if(result != RETURN_OK) {
|
||||
error = result;
|
||||
}
|
||||
}
|
||||
state = States::STATE_SET_WAS_READ;
|
||||
unlockDataPool();
|
||||
}
|
||||
else {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DataSet::read(): "
|
||||
"Call made in wrong position. Don't forget to commit"
|
||||
" member datasets!" << std::endl;
|
||||
#endif
|
||||
result = SET_WAS_ALREADY_READ;
|
||||
}
|
||||
sif::warning << "PoolDataSetBase::read: Call made in wrong position. Don't forget to "
|
||||
"commit member datasets!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("PoolDataSetBase::read: Call made in wrong position. Don't forget to "
|
||||
"commit member datasets!\n");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
result = SET_WAS_ALREADY_READ;
|
||||
}
|
||||
|
||||
if(error != HasReturnvaluesIF::RETURN_OK) {
|
||||
result = error;
|
||||
}
|
||||
return result;
|
||||
if(error != HasReturnvaluesIF::RETURN_OK) {
|
||||
result = error;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t PoolDataSetBase::getFillCount() const {
|
||||
@@ -73,144 +84,136 @@ uint16_t PoolDataSetBase::getFillCount() const {
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
if(registeredVariables[count] == nullptr) {
|
||||
// configuration error.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
if(registeredVariables[count] == nullptr) {
|
||||
/* Configuration error. */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
// These checks are often performed by the respective
|
||||
// variable implementation too, but I guess a double check does not hurt.
|
||||
if (registeredVariables[count]->getReadWriteMode() !=
|
||||
PoolVariableIF::VAR_WRITE and
|
||||
registeredVariables[count]->getDataPoolId()
|
||||
!= PoolVariableIF::NO_PARAMETER)
|
||||
{
|
||||
if(protectEveryReadCommitCall) {
|
||||
result = registeredVariables[count]->read(
|
||||
timeoutTypeForSingleVars,
|
||||
mutexTimeoutForSingleVars);
|
||||
}
|
||||
else {
|
||||
result = registeredVariables[count]->readWithoutLock();
|
||||
}
|
||||
/* These checks are often performed by the respective variable implementation too, but I guess
|
||||
a double check does not hurt. */
|
||||
if (registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_WRITE and
|
||||
registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) {
|
||||
if(protectEveryReadCommitCall) {
|
||||
result = registeredVariables[count]->read(timeoutTypeForSingleVars,
|
||||
mutexTimeoutForSingleVars);
|
||||
}
|
||||
else {
|
||||
/* The readWithoutLock function is protected, so we use the attorney here */
|
||||
result = ReadCommitIFAttorney::readWithoutLock(registeredVariables[count]);
|
||||
}
|
||||
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
result = INVALID_PARAMETER_DEFINITION;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
result = INVALID_PARAMETER_DEFINITION;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t lockTimeout) {
|
||||
if (state == States::STATE_SET_WAS_READ) {
|
||||
handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
return handleUnreadDatasetCommit(timeoutType, lockTimeout);
|
||||
}
|
||||
uint32_t lockTimeout) {
|
||||
if (state == States::STATE_SET_WAS_READ) {
|
||||
handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
return handleUnreadDatasetCommit(timeoutType, lockTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void PoolDataSetBase::handleAlreadyReadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if (registeredVariables[count]->getReadWriteMode()
|
||||
!= PoolVariableIF::VAR_READ
|
||||
&& registeredVariables[count]->getDataPoolId()
|
||||
!= PoolVariableIF::NO_PARAMETER) {
|
||||
if(protectEveryReadCommitCall) {
|
||||
registeredVariables[count]->commit(
|
||||
timeoutTypeForSingleVars,
|
||||
mutexTimeoutForSingleVars);
|
||||
}
|
||||
else {
|
||||
registeredVariables[count]->commitWithoutLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
state = States::STATE_SET_UNINITIALISED;
|
||||
unlockDataPool();
|
||||
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if ((registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_READ) and
|
||||
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
|
||||
if(protectEveryReadCommitCall) {
|
||||
registeredVariables[count]->commit(timeoutTypeForSingleVars,
|
||||
mutexTimeoutForSingleVars);
|
||||
}
|
||||
else {
|
||||
/* The commitWithoutLock function is protected, so we use the attorney here */
|
||||
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
|
||||
}
|
||||
}
|
||||
}
|
||||
state = States::STATE_SET_UNINITIALISED;
|
||||
unlockDataPool();
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if (registeredVariables[count]->getReadWriteMode()
|
||||
== PoolVariableIF::VAR_WRITE
|
||||
&& registeredVariables[count]->getDataPoolId()
|
||||
!= PoolVariableIF::NO_PARAMETER) {
|
||||
if(protectEveryReadCommitCall) {
|
||||
result = registeredVariables[count]->commit(
|
||||
timeoutTypeForSingleVars,
|
||||
mutexTimeoutForSingleVars);
|
||||
}
|
||||
else {
|
||||
result = registeredVariables[count]->commitWithoutLock();
|
||||
}
|
||||
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if ((registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE) and
|
||||
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
|
||||
if(protectEveryReadCommitCall) {
|
||||
result = registeredVariables[count]->commit(timeoutTypeForSingleVars,
|
||||
mutexTimeoutForSingleVars);
|
||||
}
|
||||
else {
|
||||
/* The commitWithoutLock function is protected, so we use the attorney here */
|
||||
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
|
||||
}
|
||||
|
||||
} else if (registeredVariables[count]->getDataPoolId()
|
||||
!= PoolVariableIF::NO_PARAMETER) {
|
||||
if (result != COMMITING_WITHOUT_READING) {
|
||||
} else if (registeredVariables[count]->getDataPoolId()
|
||||
!= PoolVariableIF::NO_PARAMETER) {
|
||||
if (result != COMMITING_WITHOUT_READING) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DataSet::commit(): commit-without-read call made "
|
||||
"with non write-only variable." << std::endl;
|
||||
sif::error << "DataSet::commit(): commit-without-read call made "
|
||||
"with non write-only variable." << std::endl;
|
||||
#endif
|
||||
result = COMMITING_WITHOUT_READING;
|
||||
}
|
||||
}
|
||||
}
|
||||
state = States::STATE_SET_UNINITIALISED;
|
||||
unlockDataPool();
|
||||
return result;
|
||||
result = COMMITING_WITHOUT_READING;
|
||||
}
|
||||
}
|
||||
}
|
||||
state = States::STATE_SET_UNINITIALISED;
|
||||
unlockDataPool();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t lockTimeout) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
uint32_t lockTimeout) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::unlockDataPool() {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t maxSize, SerializeIF::Endianness streamEndianness) const {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = registeredVariables[count]->serialize(buffer, size, maxSize,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
const size_t maxSize, SerializeIF::Endianness streamEndianness) const {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = registeredVariables[count]->deSerialize(buffer, size,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = registeredVariables[count]->deSerialize(buffer, size,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t PoolDataSetBase::getSerializedSize() const {
|
||||
uint32_t size = 0;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
size += registeredVariables[count]->getSerializedSize();
|
||||
}
|
||||
return size;
|
||||
uint32_t size = 0;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
size += registeredVariables[count]->getSerializedSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) {
|
||||
@@ -218,13 +221,13 @@ void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) {
|
||||
}
|
||||
|
||||
PoolVariableIF** PoolDataSetBase::getContainer() const {
|
||||
return registeredVariables;
|
||||
return registeredVariables;
|
||||
}
|
||||
|
||||
void PoolDataSetBase::setReadCommitProtectionBehaviour(
|
||||
bool protectEveryReadCommit, MutexIF::TimeoutType timeoutType,
|
||||
uint32_t mutexTimeout) {
|
||||
this->protectEveryReadCommitCall = protectEveryReadCommit;
|
||||
this->timeoutTypeForSingleVars = timeoutType;
|
||||
this->mutexTimeoutForSingleVars = mutexTimeout;
|
||||
bool protectEveryReadCommit, MutexIF::TimeoutType timeoutType,
|
||||
uint32_t mutexTimeout) {
|
||||
this->protectEveryReadCommitCall = protectEveryReadCommit;
|
||||
this->timeoutTypeForSingleVars = timeoutType;
|
||||
this->mutexTimeoutForSingleVars = mutexTimeout;
|
||||
}
|
||||
|
@@ -29,96 +29,99 @@
|
||||
* @author Bastian Baetz
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
class PoolDataSetBase: public PoolDataSetIF,
|
||||
public SerializeIF,
|
||||
public HasReturnvaluesIF {
|
||||
class PoolDataSetBase:
|
||||
public PoolDataSetIF,
|
||||
public SerializeIF,
|
||||
public HasReturnvaluesIF {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Creates an empty dataset. Use registerVariable or
|
||||
* supply a pointer to this dataset to PoolVariable
|
||||
* initializations to register pool variables.
|
||||
*/
|
||||
PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxFillCount);
|
||||
virtual~ PoolDataSetBase();
|
||||
/**
|
||||
* @brief Creates an empty dataset. Use registerVariable or
|
||||
* supply a pointer to this dataset to PoolVariable
|
||||
* initializations to register pool variables.
|
||||
*/
|
||||
PoolDataSetBase(PoolVariableIF** registeredVariablesArray, const size_t maxFillCount);
|
||||
|
||||
/**
|
||||
* @brief The read call initializes reading out all registered variables.
|
||||
* It is mandatory to call commit after every read call!
|
||||
* @details
|
||||
* It iterates through the list of registered variables and calls all read()
|
||||
* functions of the registered pool variables (which read out their values
|
||||
* from the data pool) which are not write-only.
|
||||
* In case of an error (e.g. a wrong data type, or an invalid data pool id),
|
||||
* the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned.
|
||||
*
|
||||
* The data pool is locked during the whole read operation and
|
||||
* freed afterwards. It is mandatory to call commit after a read call,
|
||||
* even if the read operation is not successful!
|
||||
* @return
|
||||
* - @c RETURN_OK if all variables were read successfully.
|
||||
* - @c INVALID_PARAMETER_DEFINITION if a pool entry does not exist or there
|
||||
* is a type conflict.
|
||||
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
||||
* commit() in between
|
||||
*/
|
||||
virtual ReturnValue_t read(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
/**
|
||||
* @brief The commit call initializes writing back the registered variables.
|
||||
* @details
|
||||
* It iterates through the list of registered variables and calls the
|
||||
* commit() method of the remaining registered variables (which write back
|
||||
* their values to the pool).
|
||||
*
|
||||
* The data pool is locked during the whole commit operation and
|
||||
* freed afterwards. The state changes to "was committed" after this operation.
|
||||
*
|
||||
* If the set does contain at least one variable which is not write-only
|
||||
* commit() can only be called after read(). If the set only contains
|
||||
* variables which are write only, commit() can be called without a
|
||||
* preceding read() call. Every read call must be followed by a commit call!
|
||||
* @return - @c RETURN_OK if all variables were read successfully.
|
||||
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
||||
* contains non write-only variables
|
||||
*/
|
||||
virtual ReturnValue_t commit(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
/* Forbidden for now */
|
||||
PoolDataSetBase(const PoolDataSetBase& otherSet) = delete;
|
||||
const PoolDataSetBase& operator=(const PoolDataSetBase& otherSet) = delete;
|
||||
|
||||
/**
|
||||
* Register the passed pool variable instance into the data set.
|
||||
* @param variable
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t registerVariable( PoolVariableIF* variable) override;
|
||||
virtual~ PoolDataSetBase();
|
||||
|
||||
/**
|
||||
* Provides the means to lock the underlying data structure to ensure
|
||||
* thread-safety. Default implementation is empty
|
||||
* @return Always returns -@c RETURN_OK
|
||||
*/
|
||||
virtual ReturnValue_t lockDataPool(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20) override;
|
||||
/**
|
||||
* Provides the means to unlock the underlying data structure to ensure
|
||||
* thread-safety. Default implementation is empty
|
||||
* @return Always returns -@c RETURN_OK
|
||||
*/
|
||||
virtual ReturnValue_t unlockDataPool() override;
|
||||
/**
|
||||
* @brief The read call initializes reading out all registered variables.
|
||||
* It is mandatory to call commit after every read call!
|
||||
* @details
|
||||
* It iterates through the list of registered variables and calls all read()
|
||||
* functions of the registered pool variables (which read out their values
|
||||
* from the data pool) which are not write-only.
|
||||
* In case of an error (e.g. a wrong data type, or an invalid data pool id),
|
||||
* the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned.
|
||||
*
|
||||
* The data pool is locked during the whole read operation and
|
||||
* freed afterwards. It is mandatory to call commit after a read call,
|
||||
* even if the read operation is not successful!
|
||||
* @return
|
||||
* - @c RETURN_OK if all variables were read successfully.
|
||||
* - @c INVALID_PARAMETER_DEFINITION if a pool entry does not exist or there
|
||||
* is a type conflict.
|
||||
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
||||
* commit() in between
|
||||
*/
|
||||
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
/**
|
||||
* @brief The commit call initializes writing back the registered variables.
|
||||
* @details
|
||||
* It iterates through the list of registered variables and calls the
|
||||
* commit() method of the remaining registered variables (which write back
|
||||
* their values to the pool).
|
||||
*
|
||||
* The data pool is locked during the whole commit operation and
|
||||
* freed afterwards. The state changes to "was committed" after this operation.
|
||||
*
|
||||
* If the set does contain at least one variable which is not write-only
|
||||
* commit() can only be called after read(). If the set only contains
|
||||
* variables which are write only, commit() can be called without a
|
||||
* preceding read() call. Every read call must be followed by a commit call!
|
||||
* @return - @c RETURN_OK if all variables were read successfully.
|
||||
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
||||
* contains non write-only variables
|
||||
*/
|
||||
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
|
||||
virtual uint16_t getFillCount() const;
|
||||
/**
|
||||
* Register the passed pool variable instance into the data set.
|
||||
* @param variable
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t registerVariable( PoolVariableIF* variable) override;
|
||||
|
||||
/* SerializeIF implementations */
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
/**
|
||||
* Provides the means to lock the underlying data structure to ensure
|
||||
* thread-safety. Default implementation is empty
|
||||
* @return Always returns -@c RETURN_OK
|
||||
*/
|
||||
virtual ReturnValue_t lockDataPool(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20) override;
|
||||
/**
|
||||
* Provides the means to unlock the underlying data structure to ensure
|
||||
* thread-safety. Default implementation is empty
|
||||
* @return Always returns -@c RETURN_OK
|
||||
*/
|
||||
virtual ReturnValue_t unlockDataPool() override;
|
||||
|
||||
virtual uint16_t getFillCount() const;
|
||||
|
||||
/* SerializeIF implementations */
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* Can be used to individually protect every read and commit call.
|
||||
@@ -130,48 +133,48 @@ public:
|
||||
uint32_t mutexTimeout = 20);
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief The fill_count attribute ensures that the variables
|
||||
* register in the correct array position and that the maximum
|
||||
* number of variables is not exceeded.
|
||||
*/
|
||||
uint16_t fillCount = 0;
|
||||
/**
|
||||
* States of the seet.
|
||||
*/
|
||||
enum class States {
|
||||
STATE_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
|
||||
STATE_SET_WAS_READ //!< DATA_SET_WAS_READ
|
||||
};
|
||||
/**
|
||||
* @brief state manages the internal state of the data set,
|
||||
* which is important e.g. for the behavior on destruction.
|
||||
*/
|
||||
States state = States::STATE_SET_UNINITIALISED;
|
||||
/**
|
||||
* @brief The fill_count attribute ensures that the variables
|
||||
* register in the correct array position and that the maximum
|
||||
* number of variables is not exceeded.
|
||||
*/
|
||||
uint16_t fillCount = 0;
|
||||
/**
|
||||
* States of the seet.
|
||||
*/
|
||||
enum class States {
|
||||
STATE_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
|
||||
STATE_SET_WAS_READ //!< DATA_SET_WAS_READ
|
||||
};
|
||||
/**
|
||||
* @brief state manages the internal state of the data set,
|
||||
* which is important e.g. for the behavior on destruction.
|
||||
*/
|
||||
States state = States::STATE_SET_UNINITIALISED;
|
||||
|
||||
/**
|
||||
* @brief This array represents all pool variables registered in this set.
|
||||
* Child classes can use a static or dynamic container to create
|
||||
* an array of registered variables and assign the first entry here.
|
||||
*/
|
||||
PoolVariableIF** registeredVariables = nullptr;
|
||||
const size_t maxFillCount = 0;
|
||||
/**
|
||||
* @brief This array represents all pool variables registered in this set.
|
||||
* Child classes can use a static or dynamic container to create
|
||||
* an array of registered variables and assign the first entry here.
|
||||
*/
|
||||
PoolVariableIF** registeredVariables = nullptr;
|
||||
const size_t maxFillCount = 0;
|
||||
|
||||
void setContainer(PoolVariableIF** variablesContainer);
|
||||
PoolVariableIF** getContainer() const;
|
||||
void setContainer(PoolVariableIF** variablesContainer);
|
||||
PoolVariableIF** getContainer() const;
|
||||
|
||||
private:
|
||||
bool protectEveryReadCommitCall = false;
|
||||
MutexIF::TimeoutType timeoutTypeForSingleVars = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t mutexTimeoutForSingleVars = 20;
|
||||
bool protectEveryReadCommitCall = false;
|
||||
MutexIF::TimeoutType timeoutTypeForSingleVars = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t mutexTimeoutForSingleVars = 20;
|
||||
|
||||
ReturnValue_t readVariable(uint16_t count);
|
||||
void handleAlreadyReadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20);
|
||||
ReturnValue_t handleUnreadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20);
|
||||
ReturnValue_t readVariable(uint16_t count);
|
||||
void handleAlreadyReadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20);
|
||||
ReturnValue_t handleUnreadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20);
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */
|
||||
|
@@ -8,7 +8,9 @@
|
||||
* @brief Extendes the DataSetIF by adding abstract functions to lock
|
||||
* and unlock a data pool and read/commit semantics.
|
||||
*/
|
||||
class PoolDataSetIF: public DataSetIF, public ReadCommitIF {
|
||||
class PoolDataSetIF:
|
||||
virtual public DataSetIF,
|
||||
virtual public ReadCommitIF {
|
||||
public:
|
||||
virtual~ PoolDataSetIF() {};
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, bool setValid ):
|
||||
length(initValue.size()), valid(setValid) {
|
||||
length(static_cast<uint8_t>(initValue.size())), valid(setValid) {
|
||||
this->address = new T[this->length];
|
||||
if(initValue.size() == 0) {
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
|
@@ -8,9 +8,9 @@
|
||||
/**
|
||||
* @brief Helper class to read data sets or pool variables
|
||||
*/
|
||||
class PoolReadHelper {
|
||||
class PoolReadGuard {
|
||||
public:
|
||||
PoolReadHelper(ReadCommitIF* readObject,
|
||||
PoolReadGuard(ReadCommitIF* readObject,
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t mutexTimeout = 20):
|
||||
readObject(readObject), mutexTimeout(mutexTimeout) {
|
||||
@@ -32,8 +32,18 @@ public:
|
||||
return readResult;
|
||||
}
|
||||
|
||||
~PoolReadHelper() {
|
||||
if(readObject != nullptr) {
|
||||
/**
|
||||
* @brief Can be used to suppress commit on destruction.
|
||||
*/
|
||||
void setNoCommitMode(bool commit) {
|
||||
this->noCommit = commit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Default destructor which will take care of commiting changed values.
|
||||
*/
|
||||
~PoolReadGuard() {
|
||||
if(readObject != nullptr and not noCommit) {
|
||||
readObject->commit(timeoutType, mutexTimeout);
|
||||
}
|
||||
|
||||
@@ -42,6 +52,7 @@ public:
|
||||
private:
|
||||
ReadCommitIF* readObject = nullptr;
|
||||
ReturnValue_t readResult = HasReturnvaluesIF::RETURN_OK;
|
||||
bool noCommit = false;
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t mutexTimeout = 20;
|
||||
};
|
@@ -1,9 +1,10 @@
|
||||
#ifndef FSFW_DATAPOOL_POOLVARIABLEIF_H_
|
||||
#define FSFW_DATAPOOL_POOLVARIABLEIF_H_
|
||||
|
||||
#include "ReadCommitIF.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
#include "ReadCommitIF.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief This interface is used to control data pool
|
||||
@@ -18,47 +19,48 @@
|
||||
* @author Bastian Baetz
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
class PoolVariableIF : public SerializeIF,
|
||||
public ReadCommitIF {
|
||||
friend class PoolDataSetBase;
|
||||
friend class LocalPoolDataSetBase;
|
||||
class PoolVariableIF :
|
||||
public SerializeIF,
|
||||
public ReadCommitIF {
|
||||
|
||||
public:
|
||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF;
|
||||
static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0);
|
||||
static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
|
||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF;
|
||||
static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0);
|
||||
static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
|
||||
|
||||
static constexpr bool VALID = 1;
|
||||
static constexpr bool INVALID = 0;
|
||||
static constexpr uint32_t NO_PARAMETER = 0xffffffff;
|
||||
static constexpr bool VALID = 1;
|
||||
static constexpr bool INVALID = 0;
|
||||
static constexpr uint32_t NO_PARAMETER = 0xffffffff;
|
||||
|
||||
enum ReadWriteMode_t {
|
||||
VAR_READ, VAR_WRITE, VAR_READ_WRITE
|
||||
};
|
||||
enum ReadWriteMode_t {
|
||||
VAR_READ, VAR_WRITE, VAR_READ_WRITE
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This is an empty virtual destructor,
|
||||
* as it is proposed for C++ interfaces.
|
||||
*/
|
||||
virtual ~PoolVariableIF() {}
|
||||
/**
|
||||
* @brief This method returns if the variable is write-only,
|
||||
* read-write or read-only.
|
||||
*/
|
||||
virtual ReadWriteMode_t getReadWriteMode() const = 0;
|
||||
/**
|
||||
* @brief This operation shall return the data pool id of the variable.
|
||||
*/
|
||||
virtual uint32_t getDataPoolId() const = 0;
|
||||
/**
|
||||
* @brief With this call, the valid information of the
|
||||
* variable is returned.
|
||||
*/
|
||||
virtual bool isValid() const = 0;
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is set.
|
||||
*/
|
||||
virtual void setValid(bool validity) = 0;
|
||||
/**
|
||||
* @brief This is an empty virtual destructor,
|
||||
* as it is proposed for C++ interfaces.
|
||||
*/
|
||||
virtual ~PoolVariableIF() {}
|
||||
/**
|
||||
* @brief This method returns if the variable is write-only,
|
||||
* read-write or read-only.
|
||||
*/
|
||||
virtual ReadWriteMode_t getReadWriteMode() const = 0;
|
||||
virtual void setReadWriteMode(ReadWriteMode_t newMode) = 0;
|
||||
|
||||
/**
|
||||
* @brief This operation shall return the data pool id of the variable.
|
||||
*/
|
||||
virtual uint32_t getDataPoolId() const = 0;
|
||||
/**
|
||||
* @brief With this call, the valid information of the
|
||||
* variable is returned.
|
||||
*/
|
||||
virtual bool isValid() const = 0;
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is set.
|
||||
*/
|
||||
virtual void setValid(bool validity) = 0;
|
||||
};
|
||||
|
||||
using pool_rwm_t = PoolVariableIF::ReadWriteMode_t;
|
||||
|
@@ -9,6 +9,7 @@
|
||||
* semantics.
|
||||
*/
|
||||
class ReadCommitIF {
|
||||
friend class ReadCommitIFAttorney;
|
||||
public:
|
||||
virtual ~ReadCommitIF() {}
|
||||
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType,
|
||||
@@ -18,9 +19,8 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
//! Optional and protected because this is interesting for classes grouping
|
||||
//! members with commit and read semantics where the lock is only necessary
|
||||
//! once.
|
||||
/* Optional and protected because this is interesting for classes grouping members with commit
|
||||
and read semantics where the lock is only necessary once. */
|
||||
virtual ReturnValue_t readWithoutLock() {
|
||||
return read(MutexIF::TimeoutType::WAITING, 20);
|
||||
}
|
||||
|
32
datapool/ReadCommitIFAttorney.h
Normal file
32
datapool/ReadCommitIFAttorney.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_
|
||||
#define FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_
|
||||
|
||||
#include <fsfw/datapool/ReadCommitIF.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
/**
|
||||
* @brief This class determines which members are allowed to access protected members
|
||||
* of the ReadCommitIF.
|
||||
*/
|
||||
class ReadCommitIFAttorney {
|
||||
private:
|
||||
static ReturnValue_t readWithoutLock(ReadCommitIF* readCommitIF) {
|
||||
if(readCommitIF == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return readCommitIF->readWithoutLock();
|
||||
}
|
||||
|
||||
static ReturnValue_t commitWithoutLock(ReadCommitIF* readCommitIF) {
|
||||
if(readCommitIF == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return readCommitIF->commitWithoutLock();
|
||||
}
|
||||
|
||||
friend class PoolDataSetBase;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_ */
|
@@ -1,13 +1,15 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
||||
#define FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
||||
|
||||
#include "PoolDataSetIF.h"
|
||||
|
||||
class SharedDataSetIF: public PoolDataSetIF {
|
||||
class SharedDataSetIF {
|
||||
public:
|
||||
virtual ~SharedDataSetIF() {};
|
||||
|
||||
private:
|
||||
virtual ReturnValue_t lockDataset(dur_millis_t mutexTimeout) = 0;
|
||||
virtual ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType,
|
||||
dur_millis_t mutexTimeout) = 0;
|
||||
virtual ReturnValue_t unlockDataset() = 0;
|
||||
};
|
||||
|
||||
|
@@ -18,7 +18,7 @@ public:
|
||||
* This function is protected because it should only be used by the
|
||||
* class imlementing the interface.
|
||||
*/
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
|
||||
virtual LocalDataPoolManager* getPoolManagerHandle() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
|
@@ -23,11 +23,21 @@ class LocalPoolObjectBase;
|
||||
* @details
|
||||
* Any class implementing this interface shall also have a LocalDataPoolManager member class which
|
||||
* contains the actual pool data structure and exposes the public interface for it.
|
||||
*
|
||||
* The local data pool can be accessed using helper classes by using the
|
||||
* LocalPoolVariable, LocalPoolVector or LocalDataSet classes. Every local pool variable can
|
||||
* be uniquely identified by a global pool ID (gp_id_t) and every dataset tied
|
||||
* to a pool manager can be uniqely identified by a global structure ID (sid_t).
|
||||
*
|
||||
* All software objects which want to use the local pool of another object shall also use this
|
||||
* interface, for example to get a handle to the subscription interface. The interface
|
||||
* can be retrieved using the object manager, provided the target object is a SystemObject.
|
||||
* For example, the following line of code can be used to retrieve the interface
|
||||
*
|
||||
* HasLocalDataPoolIF* poolIF = objectManager->get<HasLocalDataPoolIF>(objects::SOME_OBJECT);
|
||||
* if(poolIF != nullptr) {
|
||||
* doSomething()
|
||||
* }
|
||||
*/
|
||||
class HasLocalDataPoolIF {
|
||||
friend class HasLocalDpIFManagerAttorney;
|
||||
@@ -55,34 +65,45 @@ public:
|
||||
* usually be the period the pool owner performs its periodic operation.
|
||||
* @return
|
||||
*/
|
||||
virtual uint32_t getPeriodicOperationFrequency() const = 0;
|
||||
virtual dur_millis_t getPeriodicOperationFrequency() const = 0;
|
||||
|
||||
/**
|
||||
* @brief This function will be called by the manager if an update
|
||||
* notification is received.
|
||||
* @details HasLocalDataPoolIF
|
||||
* Can be overriden by the child class to handle changed datasets.
|
||||
* @param sid
|
||||
* @param storeId If a snapshot was requested, data will be located inside
|
||||
* @param sid SID of the updated set
|
||||
* @param storeId If a snapshot was requested, data will be located inside
|
||||
* the IPC store with this store ID.
|
||||
* @param clearMessage If this is set to true, the pool manager will take care of
|
||||
* clearing the store automatically
|
||||
*/
|
||||
virtual void handleChangedDataset(sid_t sid,
|
||||
store_address_t storeId = storeId::INVALID_STORE_ADDRESS) {
|
||||
return;
|
||||
store_address_t storeId = storeId::INVALID_STORE_ADDRESS,
|
||||
bool* clearMessage = nullptr) {
|
||||
if(clearMessage != nullptr) {
|
||||
*clearMessage = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function will be called by the manager if an update
|
||||
* notification is received.
|
||||
* @details
|
||||
* Can be overriden by the child class to handle changed pool IDs.
|
||||
* @param sid
|
||||
* @param storeId If a snapshot was requested, data will be located inside
|
||||
* Can be overriden by the child class to handle changed pool variables.
|
||||
* @param gpid GPID of the updated variable.
|
||||
* @param storeId If a snapshot was requested, data will be located inside
|
||||
* the IPC store with this store ID.
|
||||
* @param clearMessage Relevant for snapshots. If the boolean this points to is set to true,
|
||||
* the pool manager will take care of clearing the store automatically
|
||||
* after the callback.
|
||||
*/
|
||||
virtual void handleChangedPoolVariable(lp_id_t poolId,
|
||||
store_address_t storeId = storeId::INVALID_STORE_ADDRESS) {
|
||||
return;
|
||||
virtual void handleChangedPoolVariable(gp_id_t gpid,
|
||||
store_address_t storeId = storeId::INVALID_STORE_ADDRESS,
|
||||
bool* clearMessage = nullptr) {
|
||||
if(clearMessage != nullptr) {
|
||||
*clearMessage = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,8 +173,8 @@ protected:
|
||||
*/
|
||||
virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "HasLocalDataPoolIF::getPoolObjectHandle: Not overriden"
|
||||
<< ". Returning nullptr!" << std::endl;
|
||||
sif::warning << "HasLocalDataPoolIF::getPoolObjectHandle: Not overriden. "
|
||||
"Returning nullptr!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("HasLocalDataPoolIF::getPoolObjectHandle: "
|
||||
"Not overriden. Returning nullptr!\n");
|
||||
|
@@ -5,12 +5,12 @@
|
||||
#include "internal/LocalPoolDataSetAttorney.h"
|
||||
#include "internal/HasLocalDpIFManagerAttorney.h"
|
||||
|
||||
#include "../housekeeping/HousekeepingPacketUpdate.h"
|
||||
#include "../housekeeping/HousekeepingSetPacket.h"
|
||||
#include "../housekeeping/HousekeepingSnapshot.h"
|
||||
#include "../housekeeping/AcceptsHkPacketsIF.h"
|
||||
#include "../timemanager/CCSDSTime.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
#include "../ipc/MutexHelper.h"
|
||||
#include "../ipc/MutexGuard.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
|
||||
#include <array>
|
||||
@@ -38,19 +38,23 @@ LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQue
|
||||
hkQueue = queueToUse;
|
||||
}
|
||||
|
||||
LocalDataPoolManager::~LocalDataPoolManager() {}
|
||||
LocalDataPoolManager::~LocalDataPoolManager() {
|
||||
if(mutex != nullptr) {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
|
||||
if(queueToUse == nullptr) {
|
||||
// error, all destinations invalid
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR,
|
||||
"initialize", QUEUE_OR_DESTINATION_INVALID);
|
||||
/* Error, all destinations invalid */
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize",
|
||||
QUEUE_OR_DESTINATION_INVALID);
|
||||
}
|
||||
hkQueue = queueToUse;
|
||||
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if(ipcStore == nullptr) {
|
||||
// error, all destinations invalid
|
||||
/* Error, all destinations invalid */
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR,
|
||||
"initialize", HasReturnvaluesIF::RETURN_FAILED,
|
||||
"Could not set IPC store.");
|
||||
@@ -98,11 +102,11 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::performHkOperation() {
|
||||
ReturnValue_t status = HasReturnvaluesIF::RETURN_OK;
|
||||
for(auto& receiver: hkReceiversMap) {
|
||||
for(auto& receiver: hkReceivers) {
|
||||
switch(receiver.reportingType) {
|
||||
case(ReportingType::PERIODIC): {
|
||||
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
|
||||
// Periodic packets shall only be generated from datasets.
|
||||
/* Periodic packets shall only be generated from datasets */
|
||||
continue;
|
||||
}
|
||||
performPeriodicHkGeneration(receiver);
|
||||
@@ -132,13 +136,16 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() {
|
||||
ReturnValue_t LocalDataPoolManager::handleHkUpdate(HkReceiver& receiver,
|
||||
ReturnValue_t& status) {
|
||||
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
|
||||
// Update packets shall only be generated from datasets.
|
||||
/* Update packets shall only be generated from datasets. */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
|
||||
receiver.dataId.sid);
|
||||
if(dataSet == nullptr) {
|
||||
return DATASET_NOT_FOUND;
|
||||
}
|
||||
if(dataSet->hasChanged()) {
|
||||
// prepare and send update notification
|
||||
/* Prepare and send update notification */
|
||||
ReturnValue_t result = generateHousekeepingPacket(
|
||||
receiver.dataId.sid, dataSet, true);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
@@ -156,19 +163,17 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
|
||||
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
|
||||
LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
||||
receiver.dataId.localPoolId);
|
||||
//LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle(receiver.dataId.localPoolId);
|
||||
if(poolObj == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
"handleNotificationUpdate", POOLOBJECT_NOT_FOUND);
|
||||
return POOLOBJECT_NOT_FOUND;
|
||||
}
|
||||
if(poolObj->hasChanged()) {
|
||||
// prepare and send update notification.
|
||||
/* Prepare and send update notification. */
|
||||
CommandMessage notification;
|
||||
HousekeepingMessage::setUpdateNotificationVariableCommand(¬ification,
|
||||
receiver.dataId.localPoolId);
|
||||
ReturnValue_t result = hkQueue->sendMessage(
|
||||
receiver.destinationQueue, ¬ification);
|
||||
gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId));
|
||||
ReturnValue_t result = hkQueue->sendMessage(receiver.destinationQueue, ¬ification);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
status = result;
|
||||
}
|
||||
@@ -185,10 +190,10 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
|
||||
return DATASET_NOT_FOUND;
|
||||
}
|
||||
if(dataSet->hasChanged()) {
|
||||
// prepare and send update notification
|
||||
/* Prepare and send update notification */
|
||||
CommandMessage notification;
|
||||
HousekeepingMessage::setUpdateNotificationSetCommand(
|
||||
¬ification, receiver.dataId.sid);
|
||||
HousekeepingMessage::setUpdateNotificationSetCommand(¬ification,
|
||||
receiver.dataId.sid);
|
||||
ReturnValue_t result = hkQueue->sendMessage(
|
||||
receiver.destinationQueue, ¬ification);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
@@ -198,8 +203,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
|
||||
}
|
||||
}
|
||||
if(toReset != nullptr) {
|
||||
handleChangeResetLogic(receiver.dataType,
|
||||
receiver.dataId, toReset);
|
||||
handleChangeResetLogic(receiver.dataType, receiver.dataId, toReset);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
@@ -207,7 +211,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
|
||||
ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
HkReceiver& receiver, ReturnValue_t& status) {
|
||||
MarkChangedIF* toReset = nullptr;
|
||||
// check whether data has changed and send messages in case it has.
|
||||
/* Check whether data has changed and send messages in case it has */
|
||||
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
|
||||
LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
||||
receiver.dataId.localPoolId);
|
||||
@@ -221,14 +225,14 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
// prepare and send update snapshot.
|
||||
/* Prepare and send update snapshot */
|
||||
timeval now;
|
||||
Clock::getClock_timeval(&now);
|
||||
CCSDSTime::CDS_short cds;
|
||||
CCSDSTime::convertToCcsds(&cds, &now);
|
||||
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||
sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
||||
receiver.dataId.localPoolId));
|
||||
HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
|
||||
HasLocalDpIFManagerAttorney::getPoolObjectHandle(
|
||||
owner,receiver.dataId.localPoolId));
|
||||
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = addUpdateToStore(updatePacket, storeId);
|
||||
@@ -238,7 +242,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
|
||||
CommandMessage notification;
|
||||
HousekeepingMessage::setUpdateSnapshotVariableCommand(¬ification,
|
||||
receiver.dataId.localPoolId, storeId);
|
||||
gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId), storeId);
|
||||
result = hkQueue->sendMessage(receiver.destinationQueue,
|
||||
¬ification);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
@@ -259,12 +263,12 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
// prepare and send update snapshot.
|
||||
/* Prepare and send update snapshot */
|
||||
timeval now;
|
||||
Clock::getClock_timeval(&now);
|
||||
CCSDSTime::CDS_short cds;
|
||||
CCSDSTime::convertToCcsds(&cds, &now);
|
||||
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||
HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||
sizeof(cds), HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
|
||||
receiver.dataId.sid));
|
||||
|
||||
@@ -292,7 +296,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
}
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::addUpdateToStore(
|
||||
HousekeepingPacketUpdate& updatePacket, store_address_t& storeId) {
|
||||
HousekeepingSnapshot& updatePacket, store_address_t& storeId) {
|
||||
size_t updatePacketSize = updatePacket.getSerializedSize();
|
||||
uint8_t *storePtr = nullptr;
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId,
|
||||
@@ -309,7 +313,7 @@ ReturnValue_t LocalDataPoolManager::addUpdateToStore(
|
||||
void LocalDataPoolManager::handleChangeResetLogic(
|
||||
DataType type, DataId dataId, MarkChangedIF* toReset) {
|
||||
if(hkUpdateResetList == nullptr) {
|
||||
// config error!
|
||||
/* Config error */
|
||||
return;
|
||||
}
|
||||
HkUpdateResetList& listRef = *hkUpdateResetList;
|
||||
@@ -326,16 +330,16 @@ void LocalDataPoolManager::handleChangeResetLogic(
|
||||
continue;
|
||||
}
|
||||
|
||||
// only one update recipient, we can reset changes status immediately.
|
||||
/* Only one update recipient, we can reset changes status immediately */
|
||||
if(changeInfo.updateCounter <= 1) {
|
||||
toReset->setChanged(false);
|
||||
}
|
||||
// All recipients have been notified, reset the changed flag.
|
||||
if(changeInfo.currentUpdateCounter <= 1) {
|
||||
/* All recipients have been notified, reset the changed flag */
|
||||
else if(changeInfo.currentUpdateCounter <= 1) {
|
||||
toReset->setChanged(false);
|
||||
changeInfo.currentUpdateCounter = 0;
|
||||
}
|
||||
// Not all recipiens have been notified yet, decrement.
|
||||
/* Not all recipiens have been notified yet, decrement */
|
||||
else {
|
||||
changeInfo.currentUpdateCounter--;
|
||||
}
|
||||
@@ -371,20 +375,19 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid,
|
||||
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
|
||||
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
if(dataSet != nullptr) {
|
||||
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enableReporting);
|
||||
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics);
|
||||
LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, collectionInterval,
|
||||
owner->getPeriodicOperationFrequency(), isDiagnostics);
|
||||
owner->getPeriodicOperationFrequency());
|
||||
}
|
||||
|
||||
hkReceiversMap.push_back(hkReceiver);
|
||||
hkReceivers.push_back(hkReceiver);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::subscribeForUpdatePackets(sid_t sid,
|
||||
ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(sid_t sid,
|
||||
bool isDiagnostics, bool reportingEnabled,
|
||||
object_id_t packetDestination) {
|
||||
AcceptsHkPacketsIF* hkReceiverObject =
|
||||
@@ -402,19 +405,18 @@ ReturnValue_t LocalDataPoolManager::subscribeForUpdatePackets(sid_t sid,
|
||||
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
|
||||
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
if(dataSet != nullptr) {
|
||||
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true);
|
||||
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics);
|
||||
}
|
||||
|
||||
hkReceiversMap.push_back(hkReceiver);
|
||||
hkReceivers.push_back(hkReceiver);
|
||||
|
||||
handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::subscribeForSetUpdateMessages(
|
||||
ReturnValue_t LocalDataPoolManager::subscribeForSetUpdateMessage(
|
||||
const uint32_t setId, object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId, bool generateSnapshot) {
|
||||
struct HkReceiver hkReceiver;
|
||||
@@ -429,13 +431,13 @@ ReturnValue_t LocalDataPoolManager::subscribeForSetUpdateMessages(
|
||||
hkReceiver.reportingType = ReportingType::UPDATE_NOTIFICATION;
|
||||
}
|
||||
|
||||
hkReceiversMap.push_back(hkReceiver);
|
||||
hkReceivers.push_back(hkReceiver);
|
||||
|
||||
handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::subscribeForVariableUpdateMessages(
|
||||
ReturnValue_t LocalDataPoolManager::subscribeForVariableUpdateMessage(
|
||||
const lp_id_t localPoolId, object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId, bool generateSnapshot) {
|
||||
struct HkReceiver hkReceiver;
|
||||
@@ -450,7 +452,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForVariableUpdateMessages(
|
||||
hkReceiver.reportingType = ReportingType::UPDATE_NOTIFICATION;
|
||||
}
|
||||
|
||||
hkReceiversMap.push_back(hkReceiver);
|
||||
hkReceivers.push_back(hkReceiver);
|
||||
|
||||
handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
@@ -520,11 +522,19 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): {
|
||||
return generateSetStructurePacket(sid, true);
|
||||
result = generateSetStructurePacket(sid, true);
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): {
|
||||
return generateSetStructurePacket(sid, false);
|
||||
result = generateSetStructurePacket(sid, false);
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL):
|
||||
case(HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): {
|
||||
@@ -544,41 +554,49 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
|
||||
case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT):
|
||||
case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): {
|
||||
LocalPoolDataSetBase* dataSet =HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
if(command == HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT
|
||||
and LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
|
||||
return WRONG_HK_PACKET_TYPE;
|
||||
result = WRONG_HK_PACKET_TYPE;
|
||||
break;
|
||||
}
|
||||
else if(command == HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT
|
||||
and not LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
|
||||
return WRONG_HK_PACKET_TYPE;
|
||||
result = WRONG_HK_PACKET_TYPE;
|
||||
break;
|
||||
}
|
||||
return generateHousekeepingPacket(HousekeepingMessage::getSid(message),
|
||||
dataSet, true);
|
||||
}
|
||||
|
||||
// Notification handling.
|
||||
/* Notification handling */
|
||||
case(HousekeepingMessage::UPDATE_NOTIFICATION_SET): {
|
||||
owner->handleChangedDataset(sid);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
case(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE): {
|
||||
lp_id_t locPoolId = HousekeepingMessage::
|
||||
getUpdateNotificationVariableCommand(message);
|
||||
owner->handleChangedPoolVariable(locPoolId);
|
||||
gp_id_t globPoolId = HousekeepingMessage::getUpdateNotificationVariableCommand(message);
|
||||
owner->handleChangedPoolVariable(globPoolId);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
case(HousekeepingMessage::UPDATE_SNAPSHOT_SET): {
|
||||
store_address_t storeId;
|
||||
HousekeepingMessage::getUpdateSnapshotSetCommand(message, &storeId);
|
||||
owner->handleChangedDataset(sid, storeId);
|
||||
bool clearMessage = true;
|
||||
owner->handleChangedDataset(sid, storeId, &clearMessage);
|
||||
if(clearMessage) {
|
||||
message->clear();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
case(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE): {
|
||||
store_address_t storeId;
|
||||
lp_id_t localPoolId = HousekeepingMessage::
|
||||
getUpdateSnapshotVariableCommand(message, &storeId);
|
||||
owner->handleChangedPoolVariable(localPoolId, storeId);
|
||||
gp_id_t globPoolId = HousekeepingMessage::getUpdateSnapshotVariableCommand(message,
|
||||
&storeId);
|
||||
bool clearMessage = true;
|
||||
owner->handleChangedPoolVariable(globPoolId, storeId, &clearMessage);
|
||||
if(clearMessage) {
|
||||
message->clear();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
@@ -621,7 +639,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
|
||||
LocalPoolDataSetBase* dataSet, bool forDownlink,
|
||||
MessageQueueId_t destination) {
|
||||
if(dataSet == nullptr) {
|
||||
// Configuration error.
|
||||
/* Configuration error. */
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
"generateHousekeepingPacket",
|
||||
DATASET_NOT_FOUND);
|
||||
@@ -637,7 +655,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
|
||||
return result;
|
||||
}
|
||||
|
||||
// and now we set a HK message and send it the HK packet destination.
|
||||
/* Now we set a HK message and send it the HK packet destination. */
|
||||
CommandMessage hkMessage;
|
||||
if(LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
|
||||
HousekeepingMessage::setHkDiagnosticsReply(&hkMessage, sid, storeId);
|
||||
@@ -647,7 +665,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
|
||||
}
|
||||
|
||||
if(hkQueue == nullptr) {
|
||||
// error, no queue available to send packet with.
|
||||
/* Error, no queue available to send packet with. */
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
"generateHousekeepingPacket",
|
||||
QUEUE_OR_DESTINATION_INVALID);
|
||||
@@ -655,7 +673,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
|
||||
}
|
||||
if(destination == MessageQueueIF::NO_QUEUE) {
|
||||
if(hkDestinationId == MessageQueueIF::NO_QUEUE) {
|
||||
// error, all destinations invalid
|
||||
/* Error, all destinations invalid */
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
"generateHousekeepingPacket",
|
||||
QUEUE_OR_DESTINATION_INVALID);
|
||||
@@ -693,7 +711,6 @@ void LocalDataPoolManager::setNonDiagnosticIntervalFactor(
|
||||
|
||||
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
||||
sid_t sid = receiver.dataId.sid;
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
if(dataSet == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
@@ -710,24 +727,23 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
||||
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
|
||||
|
||||
if(periodicHelper == nullptr) {
|
||||
// Configuration error.
|
||||
/* Configuration error */
|
||||
return;
|
||||
}
|
||||
|
||||
if(periodicHelper->checkOpNecessary()) {
|
||||
if(not periodicHelper->checkOpNecessary()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnValue_t result = generateHousekeepingPacket(
|
||||
sid, dataSet, true);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// configuration error
|
||||
/* Configuration error */
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalDataPoolManager::performHkOperation: "
|
||||
<< "HK generation failed." << std::endl;
|
||||
sif::warning << "LocalDataPoolManager::performHkOperation: HK generation failed." <<
|
||||
std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalDataPoolManager::performHkOperation: "
|
||||
"HK generation failed.\n");
|
||||
sif::printWarning("LocalDataPoolManager::performHkOperation: HK generation failed.\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -735,8 +751,13 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid,
|
||||
bool enable, bool isDiagnostics) {
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
if(dataSet == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "togglePeriodicGeneration",
|
||||
DATASET_NOT_FOUND);
|
||||
return DATASET_NOT_FOUND;
|
||||
}
|
||||
|
||||
if((LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and not isDiagnostics) or
|
||||
(not LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and isDiagnostics)) {
|
||||
return WRONG_HK_PACKET_TYPE;
|
||||
@@ -753,8 +774,13 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid,
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
|
||||
float newCollectionInterval, bool isDiagnostics) {
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
if(dataSet == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
|
||||
DATASET_NOT_FOUND);
|
||||
return DATASET_NOT_FOUND;
|
||||
}
|
||||
|
||||
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
|
||||
if((targetIsDiagnostics and not isDiagnostics) or
|
||||
(not targetIsDiagnostics and isDiagnostics)) {
|
||||
@@ -765,7 +791,7 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
|
||||
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
|
||||
|
||||
if(periodicHelper == nullptr) {
|
||||
// config error
|
||||
/* Configuration error, set might not have a corresponding pool manager */
|
||||
return PERIODIC_HELPER_INVALID;
|
||||
}
|
||||
|
||||
@@ -775,13 +801,11 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid,
|
||||
bool isDiagnostics) {
|
||||
// Get and check dataset first.
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
/* Get and check dataset first. */
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
if(dataSet == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
"performPeriodicHkGeneration",
|
||||
DATASET_NOT_FOUND);
|
||||
"performPeriodicHkGeneration", DATASET_NOT_FOUND);
|
||||
return DATASET_NOT_FOUND;
|
||||
}
|
||||
|
||||
@@ -838,8 +862,12 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid,
|
||||
}
|
||||
|
||||
void LocalDataPoolManager::clearReceiversList() {
|
||||
// clear the vector completely and releases allocated memory.
|
||||
HkReceivers().swap(hkReceiversMap);
|
||||
/* Clear the vector completely and releases allocated memory. */
|
||||
HkReceivers().swap(hkReceivers);
|
||||
/* Also clear the reset helper if it exists */
|
||||
if(hkUpdateResetList != nullptr) {
|
||||
HkUpdateResetList().swap(*hkUpdateResetList);
|
||||
}
|
||||
}
|
||||
|
||||
MutexIF* LocalDataPoolManager::getLocalPoolMutex() {
|
||||
@@ -848,11 +876,11 @@ MutexIF* LocalDataPoolManager::getLocalPoolMutex() {
|
||||
|
||||
object_id_t LocalDataPoolManager::getCreatorObjectId() const {
|
||||
return owner->getObjectId();
|
||||
//return owner->getObjectId();
|
||||
}
|
||||
|
||||
void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
||||
const char* functionName, ReturnValue_t error, const char* errorPrint) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
if(errorPrint == nullptr) {
|
||||
if(error == DATASET_NOT_FOUND) {
|
||||
errorPrint = "Dataset not found";
|
||||
@@ -881,31 +909,34 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
||||
errorPrint = "Unknown error";
|
||||
}
|
||||
}
|
||||
object_id_t objectId = 0xffffffff;
|
||||
if(owner != nullptr) {
|
||||
objectId = owner->getObjectId();
|
||||
}
|
||||
|
||||
if(outputType == sif::OutputTypes::OUT_WARNING) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalDataPoolManager::" << functionName
|
||||
<< ": Object ID " << std::setw(8) << std::setfill('0')
|
||||
<< std::hex << owner->getObjectId() << " | " << errorPrint
|
||||
<< std::dec << std::setfill(' ') << std::endl;
|
||||
sif::warning << "LocalDataPoolManager::" << functionName << ": Object ID 0x" <<
|
||||
std::setw(8) << std::setfill('0') << std::hex << objectId << " | " << errorPrint <<
|
||||
std::dec << std::setfill(' ') << std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||
owner->getObjectId(), errorPrint);
|
||||
#endif
|
||||
functionName, objectId, errorPrint);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
}
|
||||
else if(outputType == sif::OutputTypes::OUT_ERROR) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LocalDataPoolManager::" << functionName
|
||||
<< ": Object ID " << std::setw(8) << std::setfill('0')
|
||||
<< std::hex << owner->getObjectId() << " | " << errorPrint
|
||||
<< std::dec << std::setfill(' ') << std::endl;
|
||||
sif::error << "LocalDataPoolManager::" << functionName << ": Object ID 0x" <<
|
||||
std::setw(8) << std::setfill('0') << std::hex << objectId << " | " << errorPrint <<
|
||||
std::dec << std::setfill(' ') << std::endl;
|
||||
#else
|
||||
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||
owner->getObjectId(), errorPrint);
|
||||
#endif
|
||||
functionName, objectId, errorPrint);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
}
|
||||
#endif /* #if FSFW_VERBOSE_LEVEL >= 1 */
|
||||
}
|
||||
|
||||
LocalDataPoolManager* LocalDataPoolManager::getHkManagerHandle() {
|
||||
LocalDataPoolManager* LocalDataPoolManager::getPoolManagerHandle() {
|
||||
return this;
|
||||
}
|
||||
|
@@ -14,7 +14,7 @@
|
||||
#include "../ipc/MutexIF.h"
|
||||
#include "../ipc/CommandMessage.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
#include "../ipc/MutexHelper.h"
|
||||
#include "../ipc/MutexGuard.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
@@ -24,7 +24,7 @@ void setStaticFrameworkObjectIds();
|
||||
}
|
||||
|
||||
class LocalPoolDataSetBase;
|
||||
class HousekeepingPacketUpdate;
|
||||
class HousekeepingSnapshot;
|
||||
class HasLocalDataPoolIF;
|
||||
class LocalDataPool;
|
||||
|
||||
@@ -52,17 +52,17 @@ class LocalDataPool;
|
||||
* Each pool entry has a valid state too.
|
||||
* @author R. Mueller
|
||||
*/
|
||||
class LocalDataPoolManager: public ProvidesDataPoolSubscriptionIF,
|
||||
public AccessPoolManagerIF {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
//! Some classes using the pool manager directly need to access class internals of the
|
||||
//! manager. The attorney provides granular control of access to these internals.
|
||||
friend class LocalDpManagerAttorney;
|
||||
class LocalDataPoolManager:
|
||||
public ProvidesDataPoolSubscriptionIF,
|
||||
public AccessPoolManagerIF {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
//! Some classes using the pool manager directly need to access class internals of the
|
||||
//! manager. The attorney provides granular control of access to these internals.
|
||||
friend class LocalDpManagerAttorney;
|
||||
public:
|
||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
|
||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
|
||||
|
||||
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
|
||||
|
||||
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
|
||||
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
|
||||
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
|
||||
@@ -81,29 +81,29 @@ public:
|
||||
* @param appendValidityBuffer Specify whether a buffer containing the
|
||||
* validity state is generated when serializing or deserializing packets.
|
||||
*/
|
||||
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
|
||||
bool appendValidityBuffer = true);
|
||||
virtual~ LocalDataPoolManager();
|
||||
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
|
||||
bool appendValidityBuffer = true);
|
||||
virtual~ LocalDataPoolManager();
|
||||
|
||||
/**
|
||||
* Assigns the queue to use. Make sure to call this in the #initialize
|
||||
* function of the owner.
|
||||
* @param queueToUse
|
||||
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t initialize(MessageQueueIF* queueToUse);
|
||||
/**
|
||||
* Assigns the queue to use. Make sure to call this in the #initialize
|
||||
* function of the owner.
|
||||
* @param queueToUse
|
||||
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t initialize(MessageQueueIF* queueToUse);
|
||||
|
||||
/**
|
||||
* Initializes the map by calling the map initialization function and
|
||||
* setting the periodic factor for non-diagnostic packets.
|
||||
* Don't forget to call this in the #initializeAfterTaskCreation call of
|
||||
* the owner, otherwise the map will be invalid!
|
||||
* @param nonDiagInvlFactor
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t initializeAfterTaskCreation(
|
||||
uint8_t nonDiagInvlFactor = 5);
|
||||
/**
|
||||
* Initializes the map by calling the map initialization function and
|
||||
* setting the periodic factor for non-diagnostic packets.
|
||||
* Don't forget to call this in the #initializeAfterTaskCreation call of
|
||||
* the owner, otherwise the map will be invalid!
|
||||
* @param nonDiagInvlFactor
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t initializeAfterTaskCreation(
|
||||
uint8_t nonDiagInvlFactor = 5);
|
||||
|
||||
/**
|
||||
* @brief This should be called in the periodic handler of the owner.
|
||||
@@ -116,49 +116,49 @@ public:
|
||||
*/
|
||||
virtual ReturnValue_t performHkOperation();
|
||||
|
||||
/**
|
||||
* @brief Subscribe for the generation of periodic packets.
|
||||
* @details
|
||||
/**
|
||||
* @brief Subscribe for the generation of periodic packets.
|
||||
* @details
|
||||
* This subscription mechanism will generally be used by the data creator
|
||||
* to generate housekeeping packets which are downlinked directly.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
|
||||
float collectionInterval, bool isDiagnostics,
|
||||
object_id_t packetDestination = defaultHkDestination) override;
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
|
||||
float collectionInterval, bool isDiagnostics,
|
||||
object_id_t packetDestination = defaultHkDestination) override;
|
||||
|
||||
/**
|
||||
* @brief Subscribe for the generation of packets if the dataset
|
||||
* is marked as changed.
|
||||
* @details
|
||||
* This subscription mechanism will generally be used by the data creator.
|
||||
* @param sid
|
||||
* @param isDiagnostics
|
||||
* @param packetDestination
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t subscribeForUpdatePackets(sid_t sid, bool reportingEnabled,
|
||||
/**
|
||||
* @brief Subscribe for the generation of packets if the dataset
|
||||
* is marked as changed.
|
||||
* @details
|
||||
* This subscription mechanism will generally be used by the data creator.
|
||||
* @param sid
|
||||
* @param isDiagnostics
|
||||
* @param packetDestination
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t subscribeForUpdatePacket(sid_t sid, bool reportingEnabled,
|
||||
bool isDiagnostics,
|
||||
object_id_t packetDestination = defaultHkDestination) override;
|
||||
|
||||
/**
|
||||
* @brief Subscribe for a notification message which will be sent
|
||||
* if a dataset has changed.
|
||||
* @details
|
||||
* This subscription mechanism will generally be used internally by
|
||||
* other software components.
|
||||
* @param setId Set ID of the set to receive update messages from.
|
||||
* @param destinationObject
|
||||
* @param targetQueueId
|
||||
* @param generateSnapshot If this is set to true, a copy of the current
|
||||
* data with a timestamp will be generated and sent via message.
|
||||
* Otherwise, only an notification message is sent.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
|
||||
object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot) override;
|
||||
/**
|
||||
* @brief Subscribe for a notification message which will be sent
|
||||
* if a dataset has changed.
|
||||
* @details
|
||||
* This subscription mechanism will generally be used internally by
|
||||
* other software components.
|
||||
* @param setId Set ID of the set to receive update messages from.
|
||||
* @param destinationObject
|
||||
* @param targetQueueId
|
||||
* @param generateSnapshot If this is set to true, a copy of the current
|
||||
* data with a timestamp will be generated and sent via message.
|
||||
* Otherwise, only an notification message is sent.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId,
|
||||
object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot) override;
|
||||
|
||||
/**
|
||||
* @brief Subscribe for an notification message which will be sent if a
|
||||
@@ -174,23 +174,21 @@ public:
|
||||
* Otherwise, only an notification message is sent.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t subscribeForVariableUpdateMessages(const lp_id_t localPoolId,
|
||||
ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId,
|
||||
object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot) override;
|
||||
|
||||
MutexIF* getLocalPoolMutex() override;
|
||||
|
||||
/**
|
||||
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
||||
* than diagnostic packets.
|
||||
* A factor can be specified to determine the minimum sampling frequency
|
||||
* for non-diagnostic packets. The minimum sampling frequency of the
|
||||
* diagnostics packets,which is usually jusst the period of the
|
||||
* performOperation calls, is multiplied with that factor.
|
||||
* @param factor
|
||||
*/
|
||||
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
|
||||
/**
|
||||
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
||||
* than diagnostic packets.
|
||||
* A factor can be specified to determine the minimum sampling frequency
|
||||
* for non-diagnostic packets. The minimum sampling frequency of the
|
||||
* diagnostics packets,which is usually jusst the period of the
|
||||
* performOperation calls, is multiplied with that factor.
|
||||
* @param factor
|
||||
*/
|
||||
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
|
||||
|
||||
/**
|
||||
* @brief The manager is also able to handle housekeeping messages.
|
||||
@@ -206,18 +204,18 @@ public:
|
||||
*/
|
||||
virtual ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
|
||||
|
||||
/**
|
||||
* Generate a housekeeping packet with a given SID.
|
||||
* @param sid
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t generateHousekeepingPacket(sid_t sid,
|
||||
LocalPoolDataSetBase* dataSet, bool forDownlink,
|
||||
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
||||
/**
|
||||
* Generate a housekeeping packet with a given SID.
|
||||
* @param sid
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t generateHousekeepingPacket(sid_t sid,
|
||||
LocalPoolDataSetBase* dataSet, bool forDownlink,
|
||||
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
||||
|
||||
HasLocalDataPoolIF* getOwner();
|
||||
HasLocalDataPoolIF* getOwner();
|
||||
|
||||
ReturnValue_t printPoolEntry(lp_id_t localPoolId);
|
||||
ReturnValue_t printPoolEntry(lp_id_t localPoolId);
|
||||
|
||||
/**
|
||||
* Different types of housekeeping reporting are possible.
|
||||
@@ -236,22 +234,19 @@ public:
|
||||
PERIODIC,
|
||||
//! Housekeeping packet will be generated if values have changed.
|
||||
UPDATE_HK,
|
||||
//! Update notification will be sent out as message.
|
||||
UPDATE_NOTIFICATION,
|
||||
//! Update notification will be sent out as message.
|
||||
UPDATE_NOTIFICATION,
|
||||
//! Notification will be sent out as message and a snapshot of the
|
||||
//! current data will be generated.
|
||||
UPDATE_SNAPSHOT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Different data types are possible in the HK receiver map.
|
||||
* For example, updates can be requested for full datasets or
|
||||
* for single pool variables. Periodic reporting is only possible for
|
||||
* data sets.
|
||||
*/
|
||||
/** Different data types are possible in the HK receiver map. For example, updates can be
|
||||
requested for full datasets or for single pool variables. Periodic reporting is only possible
|
||||
for data sets. */
|
||||
enum class DataType: uint8_t {
|
||||
LOCAL_POOL_VARIABLE,
|
||||
DATA_SET
|
||||
LOCAL_POOL_VARIABLE,
|
||||
DATA_SET
|
||||
};
|
||||
|
||||
/* Copying forbidden */
|
||||
@@ -267,11 +262,22 @@ public:
|
||||
|
||||
object_id_t getCreatorObjectId() const;
|
||||
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||
private:
|
||||
/**
|
||||
* Get the pointer to the mutex. Can be used to lock the data pool
|
||||
* externally. Use with care and don't forget to unlock locked mutexes!
|
||||
* For now, only friend classes can accss this function.
|
||||
* @return
|
||||
*/
|
||||
MutexIF* getMutexHandle();
|
||||
|
||||
virtual LocalDataPoolManager* getPoolManagerHandle() override;
|
||||
|
||||
protected:
|
||||
|
||||
/** Core data structure for the actual pool data */
|
||||
localpool::DataPool localPoolMap;
|
||||
//! Every housekeeping data manager has a mutex to protect access
|
||||
//! to it's data pool.
|
||||
/** Every housekeeping data manager has a mutex to protect access
|
||||
to it's data pool. */
|
||||
MutexIF* mutex = nullptr;
|
||||
|
||||
/** The class which actually owns the manager (and its datapool). */
|
||||
@@ -279,9 +285,9 @@ private:
|
||||
|
||||
uint8_t nonDiagnosticIntervalFactor = 0;
|
||||
|
||||
/** Default receiver for periodic HK packets */
|
||||
static object_id_t defaultHkDestination;
|
||||
MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE;
|
||||
/** Default receiver for periodic HK packets */
|
||||
static object_id_t defaultHkDestination;
|
||||
MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE;
|
||||
|
||||
union DataId {
|
||||
DataId(): sid() {};
|
||||
@@ -291,10 +297,10 @@ private:
|
||||
|
||||
/** The data pool manager will keep an internal map of HK receivers. */
|
||||
struct HkReceiver {
|
||||
/** Object ID of receiver */
|
||||
object_id_t objectId = objects::NO_OBJECT;
|
||||
/** Object ID of receiver */
|
||||
object_id_t objectId = objects::NO_OBJECT;
|
||||
|
||||
DataType dataType = DataType::DATA_SET;
|
||||
DataType dataType = DataType::DATA_SET;
|
||||
DataId dataId;
|
||||
|
||||
ReportingType reportingType = ReportingType::PERIODIC;
|
||||
@@ -304,7 +310,7 @@ private:
|
||||
/** This vector will contain the list of HK receivers. */
|
||||
using HkReceivers = std::vector<struct HkReceiver>;
|
||||
|
||||
HkReceivers hkReceiversMap;
|
||||
HkReceivers hkReceivers;
|
||||
|
||||
struct HkUpdateResetHelper {
|
||||
DataType dataType = DataType::DATA_SET;
|
||||
@@ -314,7 +320,8 @@ private:
|
||||
};
|
||||
|
||||
using HkUpdateResetList = std::vector<struct HkUpdateResetHelper>;
|
||||
// Will only be created when needed.
|
||||
/** This list is used to manage creating multiple update packets and only resetting
|
||||
the update flag if all of them were created. Will only be created when needed. */
|
||||
HkUpdateResetList* hkUpdateResetList = nullptr;
|
||||
|
||||
/** This is the map holding the actual data. Should only be initialized
|
||||
@@ -324,37 +331,28 @@ private:
|
||||
* of generated housekeeping packets. */
|
||||
bool appendValidityBuffer = true;
|
||||
|
||||
/**
|
||||
* @brief Queue used for communication, for example commands.
|
||||
* Is also used to send messages. Can be set either in the constructor
|
||||
/**
|
||||
* @brief Queue used for communication, for example commands.
|
||||
* Is also used to send messages. Can be set either in the constructor
|
||||
* or in the initialize() function.
|
||||
*/
|
||||
MessageQueueIF* hkQueue = nullptr;
|
||||
*/
|
||||
MessageQueueIF* hkQueue = nullptr;
|
||||
|
||||
/** Global IPC store is used to store all packets. */
|
||||
StorageManagerIF* ipcStore = nullptr;
|
||||
/**
|
||||
* Get the pointer to the mutex. Can be used to lock the data pool
|
||||
* externally. Use with care and don't forget to unlock locked mutexes!
|
||||
* For now, only friend classes can accss this function.
|
||||
* @return
|
||||
*/
|
||||
MutexIF* getMutexHandle();
|
||||
/** Global IPC store is used to store all packets. */
|
||||
StorageManagerIF* ipcStore = nullptr;
|
||||
|
||||
/**
|
||||
* Read a variable by supplying its local pool ID and assign the pool
|
||||
* entry to the supplied PoolEntry pointer. The type of the pool entry
|
||||
* is deduced automatically. This call is not thread-safe!
|
||||
* For now, only friend classes like LocalPoolVar may access this
|
||||
* function.
|
||||
* @tparam T Type of the pool entry
|
||||
* @param localPoolId Pool ID of the variable to read
|
||||
* @param poolVar [out] Corresponding pool entry will be assigned to the
|
||||
* supplied pointer.
|
||||
* @return
|
||||
*/
|
||||
template <class T> ReturnValue_t fetchPoolEntry(lp_id_t localPoolId,
|
||||
PoolEntry<T> **poolEntry);
|
||||
/**
|
||||
* Read a variable by supplying its local pool ID and assign the pool
|
||||
* entry to the supplied PoolEntry pointer. The type of the pool entry
|
||||
* is deduced automatically. This call is not thread-safe!
|
||||
* For now, only classes designated by the LocalDpManagerAttorney may use this function.
|
||||
* @tparam T Type of the pool entry
|
||||
* @param localPoolId Pool ID of the variable to read
|
||||
* @param poolVar [out] Corresponding pool entry will be assigned to the
|
||||
* supplied pointer.
|
||||
* @return
|
||||
*/
|
||||
template <class T> ReturnValue_t fetchPoolEntry(lp_id_t localPoolId, PoolEntry<T> **poolEntry);
|
||||
|
||||
/**
|
||||
* This function is used to fill the local data pool map with pool
|
||||
@@ -364,55 +362,53 @@ private:
|
||||
*/
|
||||
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
|
||||
|
||||
ReturnValue_t serializeHkPacketIntoStore(
|
||||
HousekeepingPacketDownlink& hkPacket,
|
||||
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
|
||||
MutexIF* getLocalPoolMutex() override;
|
||||
|
||||
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
||||
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable,
|
||||
bool isDiagnostics);
|
||||
ReturnValue_t changeCollectionInterval(sid_t sid,
|
||||
float newCollectionInterval, bool isDiagnostics);
|
||||
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
|
||||
ReturnValue_t serializeHkPacketIntoStore(HousekeepingPacketDownlink& hkPacket,
|
||||
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
|
||||
|
||||
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
||||
void handleChangeResetLogic(DataType type,
|
||||
DataId dataId, MarkChangedIF* toReset);
|
||||
void resetHkUpdateResetHelper();
|
||||
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
||||
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics);
|
||||
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval,
|
||||
bool isDiagnostics);
|
||||
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
|
||||
|
||||
ReturnValue_t handleHkUpdate(HkReceiver& hkReceiver,
|
||||
ReturnValue_t& status);
|
||||
ReturnValue_t handleNotificationUpdate(HkReceiver& hkReceiver,
|
||||
ReturnValue_t& status);
|
||||
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver,
|
||||
ReturnValue_t& status);
|
||||
ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket,
|
||||
store_address_t& storeId);
|
||||
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
||||
void handleChangeResetLogic(DataType type,
|
||||
DataId dataId, MarkChangedIF* toReset);
|
||||
void resetHkUpdateResetHelper();
|
||||
|
||||
void printWarningOrError(sif::OutputTypes outputType,
|
||||
const char* functionName,
|
||||
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
||||
const char* errorPrint = nullptr);
|
||||
ReturnValue_t handleHkUpdate(HkReceiver& hkReceiver, ReturnValue_t& status);
|
||||
ReturnValue_t handleNotificationUpdate(HkReceiver& hkReceiver, ReturnValue_t& status);
|
||||
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver, ReturnValue_t& status);
|
||||
ReturnValue_t addUpdateToStore(HousekeepingSnapshot& updatePacket, store_address_t& storeId);
|
||||
|
||||
void printWarningOrError(sif::OutputTypes outputType, const char* functionName,
|
||||
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
||||
const char* errorPrint = nullptr);
|
||||
};
|
||||
|
||||
|
||||
template<class T> inline
|
||||
ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
|
||||
PoolEntry<T> **poolEntry) {
|
||||
auto poolIter = localPoolMap.find(localPoolId);
|
||||
if (poolIter == localPoolMap.end()) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
||||
localpool::POOL_ENTRY_NOT_FOUND);
|
||||
return localpool::POOL_ENTRY_NOT_FOUND;
|
||||
}
|
||||
ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, PoolEntry<T> **poolEntry) {
|
||||
if(poolEntry == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
||||
if(*poolEntry == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
||||
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
||||
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
auto poolIter = localPoolMap.find(localPoolId);
|
||||
if (poolIter == localPoolMap.end()) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||
localpool::POOL_ENTRY_NOT_FOUND);
|
||||
return localpool::POOL_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
||||
if(*poolEntry == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
||||
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -4,11 +4,26 @@
|
||||
#include "LocalPoolDataSetBase.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief This dataset type can be used to group related pool variables if the number of
|
||||
* variables should not be fixed.
|
||||
* @details
|
||||
* This will is the primary data structure to organize pool variables into
|
||||
* sets which can be accessed via the housekeeping service interface or
|
||||
* which can be sent to other software objects.
|
||||
*
|
||||
* It is recommended to read the documentation of the LocalPoolDataSetBase
|
||||
* class for more information on how this class works and how to use it.
|
||||
* @tparam capacity Capacity of the static dataset, which is usually known
|
||||
* beforehand.
|
||||
*/
|
||||
class LocalDataSet: public LocalPoolDataSetBase {
|
||||
public:
|
||||
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
|
||||
const size_t maxSize);
|
||||
|
||||
LocalDataSet(sid_t sid, const size_t maxSize);
|
||||
|
||||
virtual~ LocalDataSet();
|
||||
|
||||
//! Copying forbidden for now.
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include "internal/HasLocalDpIFUserAttorney.h"
|
||||
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../globalfunctions/bitutility.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "../housekeeping/PeriodicHousekeepingHelper.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
@@ -28,37 +29,36 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
|
||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
|
||||
if(accessor != nullptr) {
|
||||
poolManager = accessor->getHkManagerHandle();
|
||||
poolManager = accessor->getPoolManagerHandle();
|
||||
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
||||
}
|
||||
|
||||
this->sid.objectId = hkOwner->getObjectId();
|
||||
this->sid.ownerSetId = setId;
|
||||
|
||||
// Data creators get a periodic helper for periodic HK data generation.
|
||||
/* Data creators get a periodic helper for periodic HK data generation. */
|
||||
if(periodicHandling) {
|
||||
periodicHelper = new PeriodicHousekeepingHelper(this);
|
||||
}
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
|
||||
PoolVariableIF** registeredVariablesArray,
|
||||
LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxNumberOfVariables):
|
||||
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
||||
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
||||
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(
|
||||
sid.objectId);
|
||||
if(hkOwner != nullptr) {
|
||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
if(accessor != nullptr) {
|
||||
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
||||
poolManager = accessor->getPoolManagerHandle();
|
||||
}
|
||||
}
|
||||
|
||||
this->sid = sid;
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase::LocalPoolDataSetBase(
|
||||
PoolVariableIF **registeredVariablesArray,
|
||||
LocalPoolDataSetBase::LocalPoolDataSetBase(PoolVariableIF **registeredVariablesArray,
|
||||
const size_t maxNumberOfVariables, bool protectEveryReadCommitCall):
|
||||
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
||||
this->setReadCommitProtectionBehaviour(protectEveryReadCommitCall);
|
||||
@@ -66,9 +66,19 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(
|
||||
|
||||
|
||||
LocalPoolDataSetBase::~LocalPoolDataSetBase() {
|
||||
/* We only delete objects which were created in the class constructor */
|
||||
if(periodicHelper != nullptr) {
|
||||
delete periodicHelper;
|
||||
}
|
||||
/* In case set was read but not comitted, we commit all variables with an invalid state */
|
||||
if(state == States::STATE_SET_WAS_READ) {
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if(registeredVariables[count] != nullptr) {
|
||||
registeredVariables[count]->setValid(false);
|
||||
registeredVariables[count]->commit(MutexIF::TimeoutType::WAITING, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t LocalPoolDataSetBase::lockDataPool(
|
||||
@@ -83,24 +93,33 @@ ReturnValue_t LocalPoolDataSetBase::lockDataPool(
|
||||
ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer,
|
||||
size_t *size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount)/8.0);
|
||||
uint8_t validityMask[validityMaskSize];
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
const uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount)/8.0);
|
||||
uint8_t* validityPtr = nullptr;
|
||||
#ifdef _MSC_VER
|
||||
/* Use a std::vector here because MSVC will (rightly) not create a fixed size array
|
||||
with a non constant size specifier */
|
||||
std::vector<uint8_t> validityMask(validityMaskSize);
|
||||
validityPtr = validityMask.data();
|
||||
#else
|
||||
uint8_t validityMask[validityMaskSize] = {0};
|
||||
validityPtr = validityMask;
|
||||
#endif
|
||||
uint8_t validBufferIndex = 0;
|
||||
uint8_t validBufferIndexBit = 0;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if(registeredVariables[count]->isValid()) {
|
||||
// set validity buffer here.
|
||||
this->bitSetter(validityMask + validBufferIndex,
|
||||
validBufferIndexBit);
|
||||
if(validBufferIndexBit == 7) {
|
||||
validBufferIndex ++;
|
||||
validBufferIndexBit = 0;
|
||||
}
|
||||
else {
|
||||
validBufferIndexBit ++;
|
||||
}
|
||||
/* Set bit at correct position */
|
||||
bitutil::bitSet(validityPtr + validBufferIndex, validBufferIndexBit);
|
||||
}
|
||||
if(validBufferIndexBit == 7) {
|
||||
validBufferIndex ++;
|
||||
validBufferIndexBit = 0;
|
||||
}
|
||||
else {
|
||||
validBufferIndexBit ++;
|
||||
}
|
||||
|
||||
result = registeredVariables[count]->serialize(buffer, size, maxSize,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
@@ -112,7 +131,7 @@ ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
// copy validity buffer to end
|
||||
std::memcpy(*buffer, validityMask, validityMaskSize);
|
||||
std::memcpy(*buffer, validityPtr, validityMaskSize);
|
||||
*size += validityMaskSize;
|
||||
return result;
|
||||
}
|
||||
@@ -137,7 +156,7 @@ ReturnValue_t LocalPoolDataSetBase::deSerializeWithValidityBuffer(
|
||||
uint8_t validBufferIndexBit = 0;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
// set validity buffer here.
|
||||
bool nextVarValid = this->bitGetter(*buffer +
|
||||
bool nextVarValid = bitutil::bitGet(*buffer +
|
||||
validBufferIndex, validBufferIndexBit);
|
||||
registeredVariables[count]->setValid(nextVarValid);
|
||||
|
||||
@@ -162,7 +181,7 @@ ReturnValue_t LocalPoolDataSetBase::unlockDataPool() {
|
||||
ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
|
||||
size_t* size, size_t maxSize,SerializeIF::Endianness streamEndianness,
|
||||
bool serializeFillCount) const {
|
||||
// Serialize as uint8_t
|
||||
/* Serialize fill count as uint8_t */
|
||||
uint8_t fillCount = this->fillCount;
|
||||
if(serializeFillCount) {
|
||||
SerializeAdapter::serialize(&fillCount, buffer, size, maxSize,
|
||||
@@ -235,21 +254,6 @@ ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size,
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const {
|
||||
if(position > 7) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalPoolDataSetBase::bitSetter: Invalid position!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalPoolDataSetBase::bitSetter: "
|
||||
"Invalid position!\n\r");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint8_t shiftNumber = position + (7 - 2 * position);
|
||||
*byte |= 1 << shiftNumber;
|
||||
}
|
||||
|
||||
void LocalPoolDataSetBase::setDiagnostic(bool isDiagnostics) {
|
||||
this->diagnostic = isDiagnostics;
|
||||
}
|
||||
@@ -266,11 +270,9 @@ bool LocalPoolDataSetBase::getReportingEnabled() const {
|
||||
return reportingEnabled;
|
||||
}
|
||||
|
||||
void LocalPoolDataSetBase::initializePeriodicHelper(
|
||||
float collectionInterval, dur_millis_t minimumPeriodicInterval,
|
||||
bool isDiagnostics, uint8_t nonDiagIntervalFactor) {
|
||||
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval,
|
||||
isDiagnostics, nonDiagIntervalFactor);
|
||||
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
|
||||
dur_millis_t minimumPeriodicInterval, uint8_t nonDiagIntervalFactor) {
|
||||
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor);
|
||||
}
|
||||
|
||||
void LocalPoolDataSetBase::setChanged(bool changed) {
|
||||
@@ -285,19 +287,6 @@ sid_t LocalPoolDataSetBase::getSid() const {
|
||||
return sid;
|
||||
}
|
||||
|
||||
bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte,
|
||||
uint8_t position) const {
|
||||
if(position > 7) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "Pool Raw Access: Bit setting invalid position"
|
||||
<< std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
uint8_t shiftNumber = position + (7 - 2 * position);
|
||||
return *byte & (1 << shiftNumber);
|
||||
}
|
||||
|
||||
bool LocalPoolDataSetBase::isValid() const {
|
||||
return this->valid;
|
||||
}
|
||||
@@ -305,7 +294,7 @@ bool LocalPoolDataSetBase::isValid() const {
|
||||
void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
|
||||
if(setEntriesRecursively) {
|
||||
for(size_t idx = 0; idx < this->getFillCount(); idx++) {
|
||||
registeredVariables[idx] -> setValid(valid);
|
||||
registeredVariables[idx]->setValid(valid);
|
||||
}
|
||||
}
|
||||
this->valid = valid;
|
||||
@@ -317,3 +306,18 @@ object_id_t LocalPoolDataSetBase::getCreatorObjectId() {
|
||||
}
|
||||
return objects::NO_OBJECT;
|
||||
}
|
||||
|
||||
void LocalPoolDataSetBase::setAllVariablesReadOnly() {
|
||||
for(size_t idx = 0; idx < this->getFillCount(); idx++) {
|
||||
registeredVariables[idx]->setReadWriteMode(pool_rwm_t::VAR_READ);
|
||||
}
|
||||
}
|
||||
|
||||
float LocalPoolDataSetBase::getCollectionInterval() const {
|
||||
if(periodicHelper != nullptr) {
|
||||
return periodicHelper->getCollectionIntervalInSeconds();
|
||||
}
|
||||
else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Constructor for users of the local pool data, which need
|
||||
* to access data created by one (!) HK manager.
|
||||
* to access data created by one HK manager.
|
||||
* @details
|
||||
* Unlike the first constructor, no component for periodic handling
|
||||
* will be initiated.
|
||||
@@ -97,12 +97,24 @@ public:
|
||||
* @brief The destructor automatically manages writing the valid
|
||||
* information of variables.
|
||||
* @details
|
||||
* In case the data set was read out, but not committed(indicated by state),
|
||||
* In case the data set was read out, but not committed (indicated by state),
|
||||
* the destructor parses all variables that are still registered to the set.
|
||||
* For each, the valid flag in the data pool is set to "invalid".
|
||||
*/
|
||||
~LocalPoolDataSetBase();
|
||||
|
||||
/* The copy constructor and assingment constructor are forbidden for now.
|
||||
The use-cases are limited and the first step would be to implement them properly for the
|
||||
base class */
|
||||
LocalPoolDataSetBase(const LocalPoolDataSetBase& otherSet) = delete;
|
||||
const LocalPoolDataSetBase& operator=(const LocalPoolDataSetBase& otherSet) = delete;
|
||||
|
||||
/**
|
||||
* Helper functions used to set all currently contained variables to read-only.
|
||||
* It is recommended to call this in set constructors intended to be used
|
||||
* by data consumers to prevent accidentally changing pool data.
|
||||
*/
|
||||
void setAllVariablesReadOnly();
|
||||
void setValidityBufferGeneration(bool withValidityBuffer);
|
||||
|
||||
sid_t getSid() const;
|
||||
@@ -153,6 +165,17 @@ public:
|
||||
bool hasChanged() const override;
|
||||
|
||||
object_id_t getCreatorObjectId();
|
||||
|
||||
bool getReportingEnabled() const;
|
||||
|
||||
/**
|
||||
* Returns the current periodic HK generation interval this set
|
||||
* belongs to a HK manager and the interval is not 0. Otherwise,
|
||||
* returns 0.0
|
||||
* @return
|
||||
*/
|
||||
float getCollectionInterval() const;
|
||||
|
||||
protected:
|
||||
sid_t sid;
|
||||
//! This mutex is used if the data is created by one object only.
|
||||
@@ -167,11 +190,9 @@ protected:
|
||||
*/
|
||||
bool reportingEnabled = false;
|
||||
void setReportingEnabled(bool enabled);
|
||||
bool getReportingEnabled() const;
|
||||
|
||||
void initializePeriodicHelper(float collectionInterval,
|
||||
dur_millis_t minimumPeriodicInterval,
|
||||
bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5);
|
||||
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
|
||||
uint8_t nonDiagIntervalFactor = 5);
|
||||
|
||||
/**
|
||||
* If the valid state of a dataset is always relevant to the whole
|
||||
@@ -211,13 +232,6 @@ protected:
|
||||
*/
|
||||
ReturnValue_t unlockDataPool() override;
|
||||
|
||||
/**
|
||||
* Set n-th bit of a byte, with n being the position from 0
|
||||
* (most significant bit) to 7 (least significant bit)
|
||||
*/
|
||||
void bitSetter(uint8_t* byte, uint8_t position) const;
|
||||
bool bitGetter(const uint8_t* byte, uint8_t position) const;
|
||||
|
||||
PeriodicHousekeepingHelper* periodicHelper = nullptr;
|
||||
LocalDataPoolManager* poolManager = nullptr;
|
||||
|
||||
|
@@ -1,10 +1,12 @@
|
||||
#include "LocalPoolObjectBase.h"
|
||||
#include "LocalDataPoolManager.h"
|
||||
#include "internal/HasLocalDpIFUserAttorney.h"
|
||||
#include "AccessLocalPoolF.h"
|
||||
#include "HasLocalDataPoolIF.h"
|
||||
#include "internal/HasLocalDpIFUserAttorney.h"
|
||||
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
|
||||
|
||||
LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
|
||||
DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
|
||||
localPoolId(poolId), readWriteMode(setReadWriteMode) {
|
||||
@@ -22,7 +24,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkO
|
||||
return;
|
||||
}
|
||||
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
hkManager = poolManAccessor->getHkManagerHandle();
|
||||
hkManager = poolManAccessor->getPoolManagerHandle();
|
||||
|
||||
if (dataSet != nullptr) {
|
||||
dataSet->registerVariable(this);
|
||||
@@ -35,22 +37,27 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
||||
if(poolId == PoolVariableIF::NO_PARAMETER) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
|
||||
<< "which is the NO_PARAMETER value!" << std::endl;
|
||||
"which is the NO_PARAMETER value!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
|
||||
"which is the NO_PARAMETER value!\n");
|
||||
#endif
|
||||
}
|
||||
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(poolOwner);
|
||||
if(hkOwner == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LocalPoolVariable: The supplied pool owner did not "
|
||||
<< "implement the correct interface"
|
||||
<< " HasLocalDataPoolIF!" << std::endl;
|
||||
sif::error << "LocalPoolVariable: The supplied pool owner did not implement the correct "
|
||||
"interface HasLocalDataPoolIF!" << std::endl;
|
||||
#else
|
||||
sif::printError( "LocalPoolVariable: The supplied pool owner did not implement the correct "
|
||||
"interface HasLocalDataPoolIF!\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
if(accessor != nullptr) {
|
||||
hkManager = accessor->getHkManagerHandle();
|
||||
hkManager = accessor->getPoolManagerHandle();
|
||||
}
|
||||
|
||||
if(dataSet != nullptr) {
|
||||
@@ -93,6 +100,10 @@ void LocalPoolObjectBase::setReadWriteMode(pool_rwm_t newReadWriteMode) {
|
||||
void LocalPoolObjectBase::reportReadCommitError(const char* variableType,
|
||||
ReturnValue_t error, bool read, object_id_t objectId, lp_id_t lpId) {
|
||||
#if FSFW_DISABLE_PRINTOUT == 0
|
||||
const char* variablePrintout = variableType;
|
||||
if(variablePrintout == nullptr) {
|
||||
variablePrintout = "Unknown Type";
|
||||
}
|
||||
const char* type = nullptr;
|
||||
if(read) {
|
||||
type = "read";
|
||||
@@ -119,12 +130,12 @@ void LocalPoolObjectBase::reportReadCommitError(const char* variableType,
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << variableType << ": " << type << " call | " << errMsg << " | Owner: 0x"
|
||||
sif::warning << variablePrintout << ": " << type << " call | " << errMsg << " | Owner: 0x"
|
||||
<< std::hex << std::setw(8) << std::setfill('0') << objectId << std::dec
|
||||
<< " LPID: " << lpId << std::endl;
|
||||
#else
|
||||
sif::printWarning("%s: %s call | %s | Owner: 0x%08x LPID: %lu\n",
|
||||
variableType, type, errMsg, objectId, lpId);
|
||||
variablePrintout, type, errMsg, objectId, lpId);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
|
||||
}
|
||||
|
@@ -20,12 +20,10 @@ class LocalPoolObjectBase: public PoolVariableIF,
|
||||
public HasReturnvaluesIF,
|
||||
public MarkChangedIF {
|
||||
public:
|
||||
LocalPoolObjectBase(lp_id_t poolId,
|
||||
HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
|
||||
LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
|
||||
pool_rwm_t setReadWriteMode);
|
||||
|
||||
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
|
||||
void setReadWriteMode(pool_rwm_t newReadWriteMode);
|
||||
|
@@ -26,8 +26,17 @@ inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId,
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::read(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return readWithoutLock();
|
||||
if(hkManager == nullptr) {
|
||||
return readWithoutLock();
|
||||
}
|
||||
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
||||
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = readWithoutLock();
|
||||
mutex->unlockMutex();
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -43,7 +52,6 @@ inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
//ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVariable", result,
|
||||
@@ -51,15 +59,6 @@ inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Actually this should never happen..
|
||||
// if(poolEntry->address == nullptr) {
|
||||
// result = PoolVariableIF::INVALID_POOL_ENTRY;
|
||||
// object_id_t ownerObjectId = hkManager->getOwner()->getObjectId();
|
||||
// reportReadCommitError("LocalPoolVariable", result,
|
||||
// false, ownerObjectId, localPoolId);
|
||||
// return result;
|
||||
// }
|
||||
|
||||
this->value = *(poolEntry->getDataPtr());
|
||||
this->valid = poolEntry->getValid();
|
||||
return RETURN_OK;
|
||||
@@ -75,8 +74,17 @@ inline ReturnValue_t LocalPoolVariable<T>::commit(bool setValid,
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::commit(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return commitWithoutLock();
|
||||
if(hkManager == nullptr) {
|
||||
return commitWithoutLock();
|
||||
}
|
||||
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
||||
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = commitWithoutLock();
|
||||
mutex->unlockMutex();
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -90,7 +98,6 @@ inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
|
||||
}
|
||||
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
//ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
|
@@ -77,8 +77,7 @@ public:
|
||||
* @param dataSet
|
||||
* @param setReadWriteMode
|
||||
*/
|
||||
LocalPoolVector(gp_id_t globalPoolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
|
||||
/**
|
||||
@@ -87,7 +86,7 @@ public:
|
||||
* The user can work on this attribute just like he would on a local
|
||||
* array of this type.
|
||||
*/
|
||||
T value[vectorSize];
|
||||
T value[vectorSize]= {};
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
|
@@ -16,7 +16,6 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
|
||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
@@ -26,7 +25,7 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return readWithoutLock();
|
||||
}
|
||||
template<typename T, uint16_t vectorSize>
|
||||
@@ -65,7 +64,7 @@ inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(bool valid,
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return commitWithoutLock();
|
||||
}
|
||||
|
||||
|
@@ -17,12 +17,8 @@ public:
|
||||
* to generate housekeeping packets which are downlinked directly.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t subscribeForPeriodicPacket(sid_t sid,
|
||||
bool enableReporting,
|
||||
float collectionInterval, bool isDiagnostics,
|
||||
object_id_t packetDestination) = 0;
|
||||
|
||||
|
||||
virtual ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
|
||||
float collectionInterval, bool isDiagnostics, object_id_t packetDestination) = 0;
|
||||
/**
|
||||
* @brief Subscribe for the generation of packets if the dataset
|
||||
* is marked as changed.
|
||||
@@ -33,51 +29,42 @@ public:
|
||||
* @param packetDestination
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t subscribeForUpdatePackets(sid_t sid,
|
||||
bool reportingEnabled,
|
||||
bool isDiagnostics,
|
||||
object_id_t packetDestination) = 0;
|
||||
|
||||
|
||||
virtual ReturnValue_t subscribeForUpdatePacket(sid_t sid, bool reportingEnabled,
|
||||
bool isDiagnostics, object_id_t packetDestination) = 0;
|
||||
/**
|
||||
* @brief Subscribe for a notification message which will be sent
|
||||
* if a dataset has changed.
|
||||
* @details
|
||||
* This subscription mechanism will generally be used internally by
|
||||
* other software components.
|
||||
* @param setId Set ID of the set to receive update messages from.
|
||||
* @param destinationObject
|
||||
* @param targetQueueId
|
||||
* @param generateSnapshot If this is set to true, a copy of the current
|
||||
* data with a timestamp will be generated and sent via message.
|
||||
* Otherwise, only an notification message is sent.
|
||||
* @param setId Set ID of the set to receive update messages from.
|
||||
* @param destinationObject Object ID of the receiver.
|
||||
* @param targetQueueId Receiver queue ID
|
||||
* @param generateSnapshot If this is set to true, a copy of the current data with a
|
||||
* timestamp will be generated and sent via message.
|
||||
* Otherwise, only an notification message is sent.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
|
||||
object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
virtual ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId,
|
||||
object_id_t destinationObject, MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot) = 0;
|
||||
|
||||
/**
|
||||
* @brief Subscribe for an notification message which will be sent if a
|
||||
* pool variable has changed.
|
||||
* @details
|
||||
* This subscription mechanism will generally be used internally by
|
||||
* other software components.
|
||||
* @param localPoolId Pool ID of the pool variable
|
||||
* @param destinationObject
|
||||
* @param targetQueueId
|
||||
* @param generateSnapshot If this is set to true, a copy of the current
|
||||
* data with a timestamp will be generated and sent via message.
|
||||
* Otherwise, only an notification message is sent.
|
||||
* @param localPoolId Pool ID of the pool variable
|
||||
* @param destinationObject Object ID of the receiver
|
||||
* @param targetQueueId Receiver queue ID
|
||||
* @param generateSnapshot If this is set to true, a copy of the current data with a
|
||||
* timestamp will be generated and sent via message. Otherwise,
|
||||
* only an notification message is sent.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t subscribeForVariableUpdateMessages(
|
||||
const lp_id_t localPoolId,
|
||||
object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
virtual ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId,
|
||||
object_id_t destinationObject, MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ */
|
||||
|
@@ -1,16 +1,37 @@
|
||||
#include "SharedLocalDataSet.h"
|
||||
|
||||
|
||||
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, sid_t sid,
|
||||
const size_t maxSize): SystemObject(objectId),
|
||||
LocalPoolDataSetBase(sid, nullptr, maxSize) {
|
||||
LocalPoolDataSetBase(sid, nullptr, maxSize), poolVarVector(maxSize) {
|
||||
this->setContainer(poolVarVector.data());
|
||||
datasetLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t SharedLocalDataSet::lockDataset(dur_millis_t mutexTimeout) {
|
||||
return datasetLock->lockMutex(MutexIF::TimeoutType::WAITING, mutexTimeout);
|
||||
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId,
|
||||
HasLocalDataPoolIF *owner, uint32_t setId,
|
||||
const size_t maxSize): SystemObject(objectId),
|
||||
LocalPoolDataSetBase(owner, setId, nullptr, maxSize), poolVarVector(maxSize) {
|
||||
this->setContainer(poolVarVector.data());
|
||||
datasetLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t SharedLocalDataSet::lockDataset(MutexIF::TimeoutType timeoutType,
|
||||
dur_millis_t mutexTimeout) {
|
||||
if(datasetLock != nullptr) {
|
||||
return datasetLock->lockMutex(timeoutType, mutexTimeout);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
|
||||
SharedLocalDataSet::~SharedLocalDataSet() {
|
||||
MutexFactory::instance()->deleteMutex(datasetLock);
|
||||
}
|
||||
|
||||
ReturnValue_t SharedLocalDataSet::unlockDataset() {
|
||||
return datasetLock->unlockMutex();
|
||||
if(datasetLock != nullptr) {
|
||||
return datasetLock->unlockMutex();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
@@ -11,16 +11,22 @@
|
||||
* multiple threads. It provides a lock in addition to all other functionalities provided
|
||||
* by the LocalPoolDataSetBase class.
|
||||
*
|
||||
* TODO: override and protect read, commit and some other calls used by pool manager.
|
||||
* The user is completely responsible for lockingand unlocking the dataset when using the
|
||||
* shared dataset.
|
||||
*/
|
||||
class SharedLocalDataSet:
|
||||
public SystemObject,
|
||||
public LocalPoolDataSetBase,
|
||||
public SharedDataSetIF {
|
||||
public:
|
||||
SharedLocalDataSet(object_id_t objectId, sid_t sid,
|
||||
SharedLocalDataSet(object_id_t objectId, HasLocalDataPoolIF* owner, uint32_t setId,
|
||||
const size_t maxSize);
|
||||
ReturnValue_t lockDataset(dur_millis_t mutexTimeout) override;
|
||||
SharedLocalDataSet(object_id_t objectId, sid_t sid, const size_t maxSize);
|
||||
|
||||
virtual~ SharedLocalDataSet();
|
||||
|
||||
ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
dur_millis_t mutexTimeout = 20) override;
|
||||
ReturnValue_t unlockDataset() override;
|
||||
private:
|
||||
|
||||
|
@@ -2,11 +2,15 @@
|
||||
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
||||
|
||||
#include "LocalPoolDataSetBase.h"
|
||||
#include "LocalPoolVariable.h"
|
||||
#include "LocalPoolVector.h"
|
||||
|
||||
#include "../objectmanager/SystemObjectIF.h"
|
||||
#include <array>
|
||||
|
||||
/**
|
||||
* @brief This local dataset type is created on the stack.
|
||||
* @brief This dataset type can be used to group related pool variables if the number of
|
||||
* variables is fixed.
|
||||
* @details
|
||||
* This will is the primary data structure to organize pool variables into
|
||||
* sets which can be accessed via the housekeeping service interface or
|
||||
|
12
datapoollocal/datapoollocal.h
Normal file
12
datapoollocal/datapoollocal.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
|
||||
#define FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
|
||||
|
||||
/* Collected related headers */
|
||||
#include "LocalPoolVariable.h"
|
||||
#include "LocalPoolVector.h"
|
||||
#include "StaticLocalDataSet.h"
|
||||
#include "LocalDataSet.h"
|
||||
#include "SharedLocalDataSet.h"
|
||||
|
||||
|
||||
#endif /* FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_ */
|
@@ -24,7 +24,6 @@ private:
|
||||
return manager.getMutexHandle();
|
||||
}
|
||||
|
||||
|
||||
template<typename T> friend class LocalPoolVariable;
|
||||
template<typename T, uint16_t vecSize> friend class LocalPoolVector;
|
||||
};
|
||||
|
@@ -14,9 +14,8 @@ private:
|
||||
}
|
||||
|
||||
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
|
||||
uint32_t minimumPeriodicIntervalMs,
|
||||
bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5) {
|
||||
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs, isDiagnostics,
|
||||
uint32_t minimumPeriodicIntervalMs, uint8_t nonDiagIntervalFactor = 5) {
|
||||
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs,
|
||||
nonDiagIntervalFactor);
|
||||
}
|
||||
|
||||
|
@@ -21,8 +21,8 @@ static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF;
|
||||
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00);
|
||||
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x01);
|
||||
|
||||
//! This is the core data structure of the local data pools. Users should insert all desired
|
||||
//! pool variables, using the std::map interface.
|
||||
/** This is the core data structure of the local data pools. Users should insert all desired
|
||||
pool variables, using the std::map interface. */
|
||||
using DataPool = std::map<lp_id_t, PoolEntryIF*>;
|
||||
using DataPoolMapIter = DataPool::iterator;
|
||||
|
||||
@@ -96,11 +96,11 @@ union gp_id_t {
|
||||
return raw == INVALID_GPID;
|
||||
}
|
||||
|
||||
bool operator==(const sid_t& other) const {
|
||||
bool operator==(const gp_id_t& other) const {
|
||||
return raw == other.raw;
|
||||
}
|
||||
|
||||
bool operator!=(const sid_t& other) const {
|
||||
bool operator!=(const gp_id_t& other) const {
|
||||
return not (raw == other.raw);
|
||||
}
|
||||
};
|
||||
|
@@ -40,6 +40,13 @@
|
||||
//! Specify whether a special mode store is used for Subsystem components.
|
||||
#define FSFW_USE_MODESTORE 0
|
||||
|
||||
//! Defines if the real time scheduler for linux should be used.
|
||||
//! If set to 0, this will also disable priority settings for linux
|
||||
//! as most systems will not allow to set nice values without privileges
|
||||
//! For embedded linux system set this to 1.
|
||||
//! If set to 1 the binary needs "cap_sys_nice=eip" privileges to run
|
||||
#define FSFW_USE_REALTIME_FOR_LINUX 1
|
||||
|
||||
namespace fsfwconfig {
|
||||
//! Default timestamp size. The default timestamp will be an eight byte CDC
|
||||
//! short timestamp.
|
||||
@@ -52,11 +59,12 @@ static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
|
||||
|
||||
//! Defines the FIFO depth of each commanding service base which
|
||||
//! also determines how many commands a CSB service can handle in one cycle
|
||||
//! simulataneously. This will increase the required RAM for
|
||||
//! simultaneously. This will increase the required RAM for
|
||||
//! each CSB service !
|
||||
static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
|
||||
|
||||
static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124;
|
||||
|
||||
}
|
||||
|
||||
#endif /* CONFIG_FSFWCONFIG_H_ */
|
||||
|
@@ -24,6 +24,13 @@
|
||||
* 1. check logic when active-> checkChildrenStateOn
|
||||
* 2. transition logic to change the mode -> commandChildren
|
||||
*
|
||||
* Important:
|
||||
*
|
||||
* The implementation must call registerChild(object_id_t child)
|
||||
* for all commanded children during initialization.
|
||||
* The implementation must call the initialization function of the base class.
|
||||
* (This will call the function in SubsystemBase)
|
||||
*
|
||||
*/
|
||||
class AssemblyBase: public SubsystemBase {
|
||||
public:
|
||||
@@ -41,9 +48,6 @@ public:
|
||||
virtual ~AssemblyBase();
|
||||
|
||||
protected:
|
||||
|
||||
// SHOULDDO: Change that OVERWRITE_HEALTH may be returned
|
||||
// (or return internalState directly?)
|
||||
/**
|
||||
* Command children to reach [mode,submode] combination
|
||||
* Can be done by setting #commandsOutstanding correctly,
|
||||
@@ -68,6 +72,18 @@ protected:
|
||||
virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode,
|
||||
Submode_t wantedSubmode) = 0;
|
||||
|
||||
/**
|
||||
* Check whether a combination of mode and submode is valid.
|
||||
*
|
||||
* Ground Controller like precise return values from HasModesIF.
|
||||
* So, please return any of them.
|
||||
*
|
||||
* @param mode The targeted mode
|
||||
* @param submode The targeted submmode
|
||||
* @return Any information why this combination is invalid from HasModesIF
|
||||
* like HasModesIF::INVALID_SUBMODE.
|
||||
* On success return HasReturnvaluesIF::RETURN_OK
|
||||
*/
|
||||
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
|
||||
Submode_t submode) = 0;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -209,20 +209,20 @@ void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId,
|
||||
ReturnValue_t result = strangeReplyCount.getParameter(domainId, uniqueId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
}
|
||||
result = missedReplyCount.getParameter(domainId, parameterId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
result = missedReplyCount.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||
startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
}
|
||||
result = recoveryCounter.getParameter(domainId, parameterId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
result = recoveryCounter.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||
startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
}
|
||||
|
@@ -17,9 +17,9 @@ public:
|
||||
ReturnValue_t initialize();
|
||||
void triggerEvent(Event event, uint32_t parameter1 = 0,
|
||||
uint32_t parameter2 = 0);bool isFdirActionInProgress();
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex);
|
||||
|
||||
protected:
|
||||
FaultCounter strangeReplyCount;
|
||||
|
@@ -16,9 +16,9 @@ ReturnValue_t HealthDevice::performOperation(uint8_t opCode) {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&command);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
healthHelper.handleHealthCommand(&command);
|
||||
result = healthHelper.handleHealthCommand(&command);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t HealthDevice::initialize() {
|
||||
|
@@ -1,3 +1,172 @@
|
||||
## Local Data Pools
|
||||
## Local Data Pools Developer Information
|
||||
|
||||
The following text is targeted towards mission software developers which would like
|
||||
to use the local data pools provided by the FSFW to store data like sensor values so they can be
|
||||
used by other software objects like controllers as well. If a custom class should have a local
|
||||
pool which can be used by other software objects as well, following steps have to be performed:
|
||||
|
||||
1. Create a `LocalDataPoolManager` member object in the custom class
|
||||
2. Implement the `HasLocalDataPoolIF` with specifies the interface between the local pool manager
|
||||
and the class owning the local pool.
|
||||
|
||||
The local data pool manager is also able to process housekeeping service requests in form
|
||||
of messages, generate periodic housekeeping packet, generate notification and snapshots of changed
|
||||
variables and datasets and process notifications and snapshots coming from other objects.
|
||||
The two former tasks are related to the external interface using telemetry and telecommands (TMTC)
|
||||
while the later two are related to data consumers like controllers only acting on data change
|
||||
detected by the data creator instead of checking the data manually each cycle. Two important
|
||||
framework classes `DeviceHandlerBase` and `ExtendedControllerBase` already perform the two steps
|
||||
shown above so the steps required are altered slightly.
|
||||
|
||||
### Storing and Accessing pool data
|
||||
|
||||
The pool manager is responsible for thread-safe access of the pool data, but the actual
|
||||
access to the pool data from the point of view of a mission software developer happens via proxy
|
||||
classes like pool variable classes. These classes store a copy
|
||||
of the pool variable with the matching datatype and copy the actual data from the local pool
|
||||
on a `read` call. Changed variables can then be written to the local pool with a `commit` call.
|
||||
The `read` and `commit` calls are thread-safe and can be called concurrently from data creators
|
||||
and data consumers. Generally, a user will create a dataset class which in turn groups all
|
||||
cohesive pool variables. These sets simply iterator over the list of variables and call the
|
||||
`read` and `commit` functions of each variable. The following diagram shows the
|
||||
high-level architecture of the local data pools.
|
||||
|
||||
<img align="center" src="./images/PoolArchitecture.png" width="50%"> <br>
|
||||
|
||||
An example is shown for using the local data pools with a Gyroscope.
|
||||
For example, the following code shows an implementation to access data from a Gyroscope taken
|
||||
from the SOURCE CubeSat project:
|
||||
|
||||
```cpp
|
||||
class GyroPrimaryDataset: public StaticLocalDataSet<3 * sizeof(float)> {
|
||||
public:
|
||||
/**
|
||||
* Constructor for data users
|
||||
* @param gyroId
|
||||
*/
|
||||
GyroPrimaryDataset(object_id_t gyroId):
|
||||
StaticLocalDataSet(sid_t(gyroId, gyrodefs::GYRO_DATA_SET_ID)) {
|
||||
setAllVariablesReadOnly();
|
||||
}
|
||||
|
||||
lp_var_t<float> angVelocityX = lp_var_t<float>(sid.objectId,
|
||||
gyrodefs::ANGULAR_VELOCITY_X, this);
|
||||
lp_var_t<float> angVelocityY = lp_var_t<float>(sid.objectId,
|
||||
gyrodefs::ANGULAR_VELOCITY_Y, this);
|
||||
lp_var_t<float> angVelocityZ = lp_var_t<float>(sid.objectId,
|
||||
gyrodefs::ANGULAR_VELOCITY_Z, this);
|
||||
private:
|
||||
|
||||
friend class GyroHandler;
|
||||
/**
|
||||
* Constructor for data creator
|
||||
* @param hkOwner
|
||||
*/
|
||||
GyroPrimaryDataset(HasLocalDataPoolIF* hkOwner):
|
||||
StaticLocalDataSet(hkOwner, gyrodefs::GYRO_DATA_SET_ID) {}
|
||||
};
|
||||
```
|
||||
|
||||
There is a public constructor for users which sets all variables to read-only and there is a
|
||||
constructor for the GyroHandler data creator by marking it private and declaring the `GyroHandler`
|
||||
as a friend class. Both the atittude controller and the `GyroHandler` can now
|
||||
use the same class definition to access the pool variables with `read` and `commit` semantics
|
||||
in a thread-safe way. Generally, each class requiring access will have the set class as a member
|
||||
class. The data creator will also be generally a `DeviceHandlerBase` subclass and some additional
|
||||
steps are necessary to expose the set for housekeeping purposes.
|
||||
|
||||
### Using the local data pools in a `DeviceHandlerBase` subclass
|
||||
|
||||
It is very common to store data generated by devices like a sensor into a pool which can
|
||||
then be used by other objects. Therefore, the `DeviceHandlerBase` already has a
|
||||
local pool. Using the aforementioned example, our `GyroHandler` will now have the set class
|
||||
as a member:
|
||||
|
||||
```cpp
|
||||
class GyroHandler: ... {
|
||||
|
||||
public:
|
||||
...
|
||||
private:
|
||||
...
|
||||
GyroPrimaryDataset gyroData;
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
The constructor used for the creators expects the owner class as a parameter, so we initialize
|
||||
the object in the `GyroHandler` constructor like this:
|
||||
|
||||
```cpp
|
||||
GyroHandler::GyroHandler(object_id_t objectId, object_id_t comIF,
|
||||
CookieIF *comCookie, uint8_t switchId):
|
||||
DeviceHandlerBase(objectId, comIF, comCookie), switchId(switchId),
|
||||
gyroData(this) {}
|
||||
```
|
||||
|
||||
We need to assign the set to a reply ID used in the `DeviceHandlerBase`.
|
||||
The combination of the `GyroHandler` object ID and the reply ID will be the 64-bit structure ID
|
||||
`sid_t` and is used to globally identify the set, for example when requesting housekeeping data or
|
||||
generating update messages. We need to assign our custom set class in some way so that the local
|
||||
pool manager can access the custom data sets as well.
|
||||
By default, the `getDataSetHandle` will take care of this tasks. The default implementation for a
|
||||
`DeviceHandlerBase` subclass will use the internal command map to retrieve
|
||||
a handle to a dataset from a given reply ID. Therefore,
|
||||
we assign the set in the `fillCommandAndReplyMap` function:
|
||||
|
||||
```cpp
|
||||
void GyroHandler::fillCommandAndReplyMap() {
|
||||
...
|
||||
this->insertInCommandAndReplyMap(gyrodefs::GYRO_DATA, 3, &gyroData);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Now, we need to create the actual pool entries as well, using the `initializeLocalDataPool`
|
||||
function. Here, we also immediately subscribe for periodic housekeeping packets
|
||||
with an interval of 4 seconds. They are still disabled in this example and can be enabled
|
||||
with a housekeeping service command.
|
||||
|
||||
```cpp
|
||||
ReturnValue_t GyroHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(gyrodefs::ANGULAR_VELOCITY_X,
|
||||
new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(gyrodefs::ANGULAR_VELOCITY_Y,
|
||||
new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(gyrodefs::ANGULAR_VELOCITY_Z,
|
||||
new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(gyrodefs::GENERAL_CONFIG_REG42,
|
||||
new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(gyrodefs::RANGE_CONFIG_REG43,
|
||||
new PoolEntry<uint8_t>({0}));
|
||||
|
||||
poolManager.subscribeForPeriodicPacket(gyroData.getSid(), false, 4.0, false);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
```
|
||||
|
||||
Now, if we receive some sensor data and converted them into the right format,
|
||||
we can write it into the pool like this, using a guard class to ensure the set is commited back
|
||||
in any case:
|
||||
|
||||
```cpp
|
||||
PoolReadGuard readHelper(&gyroData);
|
||||
if(readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
|
||||
if(not gyroData.isValid()) {
|
||||
gyroData.setValidity(true, true);
|
||||
}
|
||||
|
||||
gyroData.angVelocityX = angularVelocityX;
|
||||
gyroData.angVelocityY = angularVelocityY;
|
||||
gyroData.angVelocityZ = angularVelocityZ;
|
||||
}
|
||||
```
|
||||
|
||||
The guard class will commit the changed data on destruction automatically.
|
||||
|
||||
### Using the local data pools in a `ExtendedControllerBase` subclass
|
||||
|
||||
Coming soon
|
||||
|
||||
|
||||
|
3
doc/doxy/.gitignore
vendored
Normal file
3
doc/doxy/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
html
|
||||
latex
|
||||
rtf
|
2609
doc/doxy/OPUS.doxyfile
Normal file
2609
doc/doxy/OPUS.doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/images/PoolArchitecture.png
Normal file
BIN
doc/images/PoolArchitecture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
@@ -6,6 +6,7 @@
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
|
||||
MessageQueueId_t EventManagerIF::eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
||||
|
||||
// If one checks registerListener calls, there are around 40 (to max 50)
|
||||
// objects registering for certain events.
|
||||
|
@@ -1,11 +1,12 @@
|
||||
#ifndef EVENTMANAGERIF_H_
|
||||
#define EVENTMANAGERIF_H_
|
||||
#ifndef FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||
#define FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||
|
||||
#include "EventMessage.h"
|
||||
#include "eventmatching/eventmatching.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../ipc/MessageQueueSenderIF.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
|
||||
class EventManagerIF {
|
||||
public:
|
||||
@@ -41,11 +42,19 @@ public:
|
||||
|
||||
static void triggerEvent(EventMessage* message,
|
||||
MessageQueueId_t sentFrom = 0) {
|
||||
static MessageQueueId_t eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
||||
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
|
||||
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
|
||||
objects::EVENT_MANAGER);
|
||||
if (eventmanager == nullptr) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "EventManagerIF::triggerEvent: EventManager invalid or not found!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning("EventManagerIF::triggerEvent: "
|
||||
"EventManager invalid or not found!");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return;
|
||||
}
|
||||
eventmanagerQueue = eventmanager->getEventReportQueue();
|
||||
@@ -53,6 +62,10 @@ public:
|
||||
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
|
||||
}
|
||||
|
||||
private:
|
||||
//! Initialized by EventManager (C++11 does not allow header-only static member initialization).
|
||||
static MessageQueueId_t eventmanagerQueue;
|
||||
|
||||
};
|
||||
|
||||
#endif /* EVENTMANAGERIF_H_ */
|
||||
#endif /* FSFW_EVENTS_EVENTMANAGERIF_H_ */
|
||||
|
@@ -109,6 +109,6 @@ bool EventMessage::isClearedEventMessage() {
|
||||
return getEvent() == INVALID_EVENT;
|
||||
}
|
||||
|
||||
size_t EventMessage::getMinimumMessageSize() {
|
||||
size_t EventMessage::getMinimumMessageSize() const {
|
||||
return EVENT_MESSAGE_SIZE;
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ public:
|
||||
|
||||
protected:
|
||||
static const Event INVALID_EVENT = 0;
|
||||
virtual size_t getMinimumMessageSize();
|
||||
virtual size_t getMinimumMessageSize() const override;
|
||||
|
||||
};
|
||||
|
||||
|
@@ -58,14 +58,14 @@ FaultCounter::FaultCounter() :
|
||||
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
|
||||
}
|
||||
|
||||
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||
uint16_t startAtIndex) {
|
||||
if (domainId != parameterDomain) {
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case 0:
|
||||
parameterWrapper->set(failureThreshold);
|
||||
break;
|
||||
|
@@ -23,7 +23,7 @@ public:
|
||||
void setFailureThreshold(uint32_t failureThreshold);
|
||||
void setFaultDecrementTimeMs(uint32_t timeMs);
|
||||
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
|
@@ -7,6 +7,7 @@ target_sources(${LIB_FSFW_NAME}
|
||||
PeriodicOperationDivider.cpp
|
||||
timevalOperations.cpp
|
||||
Type.cpp
|
||||
bitutility.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(math)
|
||||
add_subdirectory(math)
|
||||
|
@@ -2,76 +2,128 @@
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include <bitset>
|
||||
|
||||
|
||||
void arrayprinter::print(const uint8_t *data, size_t size, OutputType type,
|
||||
bool printInfo, size_t maxCharPerLine) {
|
||||
bool printInfo, size_t maxCharPerLine) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
if(printInfo) {
|
||||
sif::info << "Printing data with size " << size << ": ";
|
||||
}
|
||||
sif::info << "[";
|
||||
if(printInfo) {
|
||||
sif::info << "Printing data with size " << size << ": " << std::endl;
|
||||
}
|
||||
#else
|
||||
sif::printInfo("Printing data with size %zu: [", size);
|
||||
#endif
|
||||
if(type == OutputType::HEX) {
|
||||
arrayprinter::printHex(data, size, maxCharPerLine);
|
||||
}
|
||||
else if (type == OutputType::DEC) {
|
||||
arrayprinter::printDec(data, size, maxCharPerLine);
|
||||
}
|
||||
else if(type == OutputType::BIN) {
|
||||
arrayprinter::printBin(data, size);
|
||||
}
|
||||
#if FSFW_NO_C99_IO == 1
|
||||
sif::printInfo("Printing data with size %lu: \n", static_cast<unsigned long>(size));
|
||||
#else
|
||||
sif::printInfo("Printing data with size %zu: \n", size);
|
||||
#endif /* FSFW_NO_C99_IO == 1 */
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
|
||||
if(type == OutputType::HEX) {
|
||||
arrayprinter::printHex(data, size, maxCharPerLine);
|
||||
}
|
||||
else if (type == OutputType::DEC) {
|
||||
arrayprinter::printDec(data, size, maxCharPerLine);
|
||||
}
|
||||
else if(type == OutputType::BIN) {
|
||||
arrayprinter::printBin(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
void arrayprinter::printHex(const uint8_t *data, size_t size,
|
||||
size_t maxCharPerLine) {
|
||||
size_t maxCharPerLine) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << std::hex;
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
sif::info << "0x" << static_cast<int>(data[i]);
|
||||
if(i < size - 1){
|
||||
sif::info << " , ";
|
||||
if(i > 0 and i % maxCharPerLine == 0) {
|
||||
sif::info << std::endl;
|
||||
if(sif::info.crAdditionEnabled()) {
|
||||
std::cout << "\r" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
sif::info << std::dec;
|
||||
sif::info << "]" << std::endl;
|
||||
std::cout << "[" << std::hex;
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
std::cout << "0x" << static_cast<int>(data[i]);
|
||||
if(i < size - 1) {
|
||||
std::cout << " , ";
|
||||
if(i > 0 and (i + 1) % maxCharPerLine == 0) {
|
||||
std::cout << std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << std::dec;
|
||||
std::cout << "]" << std::endl;
|
||||
#else
|
||||
// how much memory to reserve for printout?
|
||||
// General format: 0x01, 0x02, 0x03 so it is number of chars times 6
|
||||
// plus line break plus small safety margin.
|
||||
char printBuffer[(size + 1) * 7 + 1] = {};
|
||||
size_t currentPos = 0;
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
// To avoid buffer overflows.
|
||||
if(sizeof(printBuffer) - currentPos <= 7) {
|
||||
break;
|
||||
}
|
||||
|
||||
currentPos += snprintf(printBuffer + currentPos, 6, "0x%02x", data[i]);
|
||||
if(i < size - 1) {
|
||||
currentPos += sprintf(printBuffer + currentPos, ", ");
|
||||
if(i > 0 and (i + 1) % maxCharPerLine == 0) {
|
||||
currentPos += sprintf(printBuffer + currentPos, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#if FSFW_DISABLE_PRINTOUT == 0
|
||||
printf("[%s]\n", printBuffer);
|
||||
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
|
||||
#endif
|
||||
}
|
||||
|
||||
void arrayprinter::printDec(const uint8_t *data, size_t size,
|
||||
size_t maxCharPerLine) {
|
||||
size_t maxCharPerLine) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << std::dec;
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
sif::info << static_cast<int>(data[i]);
|
||||
if(i < size - 1){
|
||||
sif::info << " , ";
|
||||
if(i > 0 and i % maxCharPerLine == 0) {
|
||||
sif::info << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
sif::info << "]" << std::endl;
|
||||
if(sif::info.crAdditionEnabled()) {
|
||||
std::cout << "\r" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "[" << std::dec;
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
std::cout << static_cast<int>(data[i]);
|
||||
if(i < size - 1){
|
||||
std::cout << " , ";
|
||||
if(i > 0 and (i + 1) % maxCharPerLine == 0) {
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
#else
|
||||
// how much memory to reserve for printout?
|
||||
// General format: 32, 243, -12 so it is number of chars times 5
|
||||
// plus line break plus small safety margin.
|
||||
char printBuffer[(size + 1) * 5 + 1] = {};
|
||||
size_t currentPos = 0;
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
// To avoid buffer overflows.
|
||||
if(sizeof(printBuffer) - currentPos <= 5) {
|
||||
break;
|
||||
}
|
||||
|
||||
currentPos += snprintf(printBuffer + currentPos, 3, "%d", data[i]);
|
||||
if(i < size - 1) {
|
||||
currentPos += sprintf(printBuffer + currentPos, ", ");
|
||||
if(i > 0 and (i + 1) % maxCharPerLine == 0) {
|
||||
currentPos += sprintf(printBuffer + currentPos, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#if FSFW_DISABLE_PRINTOUT == 0
|
||||
printf("[%s]\n", printBuffer);
|
||||
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
|
||||
#endif
|
||||
}
|
||||
|
||||
void arrayprinter::printBin(const uint8_t *data, size_t size) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "\n" << std::flush;
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
sif::info << "Byte " << i + 1 << ": 0b"<<
|
||||
std::bitset<8>(data[i]) << ",\n" << std::flush;
|
||||
sif::info << "Byte " << i + 1 << ": 0b" << std::bitset<8>(data[i]) << std::endl;
|
||||
}
|
||||
sif::info << "]" << std::endl;
|
||||
#else
|
||||
// how much memory to reserve for printout?
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
sif::printInfo("Byte %d: 0b" BYTE_TO_BINARY_PATTERN "\n", i + 1, BYTE_TO_BINARY(data[i]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@@ -1,20 +1,25 @@
|
||||
#ifndef FRAMEWORK_GLOBALFUNCTIONS_ARRAYPRINTER_H_
|
||||
#define FRAMEWORK_GLOBALFUNCTIONS_ARRAYPRINTER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
enum class OutputType {
|
||||
DEC,
|
||||
HEX,
|
||||
BIN
|
||||
DEC,
|
||||
HEX,
|
||||
BIN
|
||||
};
|
||||
|
||||
namespace arrayprinter {
|
||||
|
||||
|
||||
|
||||
void print(const uint8_t* data, size_t size, OutputType type = OutputType::HEX,
|
||||
bool printInfo = true, size_t maxCharPerLine = 12);
|
||||
void printHex(const uint8_t* data, size_t size, size_t maxCharPerLine = 12);
|
||||
void printDec(const uint8_t* data, size_t size, size_t maxCharPerLine = 12);
|
||||
bool printInfo = true, size_t maxCharPerLine = 10);
|
||||
void printHex(const uint8_t* data, size_t size, size_t maxCharPerLine = 10);
|
||||
void printDec(const uint8_t* data, size_t size, size_t maxCharPerLine = 10);
|
||||
void printBin(const uint8_t* data, size_t size);
|
||||
|
||||
}
|
||||
|
||||
#endif /* FRAMEWORK_GLOBALFUNCTIONS_ARRAYPRINTER_H_ */
|
||||
|
33
globalfunctions/bitutility.cpp
Normal file
33
globalfunctions/bitutility.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "bitutility.h"
|
||||
|
||||
void bitutil::bitSet(uint8_t *byte, uint8_t position) {
|
||||
if(position > 7) {
|
||||
return;
|
||||
}
|
||||
uint8_t shiftNumber = position + (7 - 2 * position);
|
||||
*byte |= 1 << shiftNumber;
|
||||
}
|
||||
|
||||
void bitutil::bitToggle(uint8_t *byte, uint8_t position) {
|
||||
if(position > 7) {
|
||||
return;
|
||||
}
|
||||
uint8_t shiftNumber = position + (7 - 2 * position);
|
||||
*byte ^= 1 << shiftNumber;
|
||||
}
|
||||
|
||||
void bitutil::bitClear(uint8_t *byte, uint8_t position) {
|
||||
if(position > 7) {
|
||||
return;
|
||||
}
|
||||
uint8_t shiftNumber = position + (7 - 2 * position);
|
||||
*byte &= ~(1 << shiftNumber);
|
||||
}
|
||||
|
||||
bool bitutil::bitGet(const uint8_t *byte, uint8_t position) {
|
||||
if(position > 7) {
|
||||
return false;
|
||||
}
|
||||
uint8_t shiftNumber = position + (7 - 2 * position);
|
||||
return *byte & (1 << shiftNumber);
|
||||
}
|
18
globalfunctions/bitutility.h
Normal file
18
globalfunctions/bitutility.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef FSFW_GLOBALFUNCTIONS_BITUTIL_H_
|
||||
#define FSFW_GLOBALFUNCTIONS_BITUTIL_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace bitutil {
|
||||
|
||||
/* Helper functions for manipulating the individual bits of a byte.
|
||||
Position refers to n-th bit of a byte, going from 0 (most significant bit) to
|
||||
7 (least significant bit) */
|
||||
void bitSet(uint8_t* byte, uint8_t position);
|
||||
void bitToggle(uint8_t* byte, uint8_t position);
|
||||
void bitClear(uint8_t* byte, uint8_t position);
|
||||
bool bitGet(const uint8_t* byte, uint8_t position);
|
||||
|
||||
}
|
||||
|
||||
#endif /* FSFW_GLOBALFUNCTIONS_BITUTIL_H_ */
|
@@ -1,5 +1,5 @@
|
||||
#include "HealthTable.h"
|
||||
#include "../ipc/MutexHelper.h"
|
||||
#include "../ipc/MutexGuard.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
|
||||
@@ -31,7 +31,7 @@ ReturnValue_t HealthTable::registerObject(object_id_t object,
|
||||
|
||||
void HealthTable::setHealth(object_id_t object,
|
||||
HasHealthIF::HealthState newState) {
|
||||
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||
MutexGuard(mutex, timeoutType, mutexTimeoutMs);
|
||||
HealthMap::iterator iter = healthMap.find(object);
|
||||
if (iter != healthMap.end()) {
|
||||
iter->second = newState;
|
||||
@@ -40,7 +40,7 @@ void HealthTable::setHealth(object_id_t object,
|
||||
|
||||
HasHealthIF::HealthState HealthTable::getHealth(object_id_t object) {
|
||||
HasHealthIF::HealthState state = HasHealthIF::HEALTHY;
|
||||
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||
MutexGuard(mutex, timeoutType, mutexTimeoutMs);
|
||||
HealthMap::iterator iter = healthMap.find(object);
|
||||
if (iter != healthMap.end()) {
|
||||
state = iter->second;
|
||||
@@ -49,7 +49,7 @@ HasHealthIF::HealthState HealthTable::getHealth(object_id_t object) {
|
||||
}
|
||||
|
||||
bool HealthTable::hasHealth(object_id_t object) {
|
||||
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||
MutexGuard(mutex, timeoutType, mutexTimeoutMs);
|
||||
HealthMap::iterator iter = healthMap.find(object);
|
||||
if (iter != healthMap.end()) {
|
||||
return true;
|
||||
@@ -58,35 +58,51 @@ bool HealthTable::hasHealth(object_id_t object) {
|
||||
}
|
||||
|
||||
size_t HealthTable::getPrintSize() {
|
||||
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||
MutexGuard(mutex, timeoutType, mutexTimeoutMs);
|
||||
uint32_t size = healthMap.size() * sizeof(object_id_t) +
|
||||
sizeof(HasHealthIF::HealthState) + sizeof(uint16_t);
|
||||
return size;
|
||||
}
|
||||
|
||||
void HealthTable::printAll(uint8_t* pointer, size_t maxSize) {
|
||||
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||
MutexGuard(mutex, timeoutType, mutexTimeoutMs);
|
||||
size_t size = 0;
|
||||
uint16_t count = healthMap.size();
|
||||
SerializeAdapter::serialize(&count,
|
||||
ReturnValue_t result = SerializeAdapter::serialize(&count,
|
||||
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "HealthTable::printAll: Serialization of health table failed" << std::endl;
|
||||
#else
|
||||
sif::printWarning("HealthTable::printAll: Serialization of health table failed\n");
|
||||
#endif
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return;
|
||||
}
|
||||
for (const auto& health: healthMap) {
|
||||
SerializeAdapter::serialize(&health.first,
|
||||
result = SerializeAdapter::serialize(&health.first,
|
||||
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
uint8_t healthValue = health.second;
|
||||
SerializeAdapter::serialize(&healthValue, &pointer, &size,
|
||||
result = SerializeAdapter::serialize(&healthValue, &pointer, &size,
|
||||
maxSize, SerializeIF::Endianness::BIG);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t HealthTable::iterate(HealthEntry *value, bool reset) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||
MutexGuard(mutex, timeoutType, mutexTimeoutMs);
|
||||
if (reset) {
|
||||
mapIterator = healthMap.begin();
|
||||
}
|
||||
if (mapIterator == healthMap.end()) {
|
||||
result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*value = *mapIterator;
|
||||
mapIterator++;
|
||||
|
@@ -84,15 +84,21 @@ void HousekeepingMessage::setCollectionIntervalModificationCommand(
|
||||
else {
|
||||
command->setCommand(MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL);
|
||||
}
|
||||
command->setParameter3(collectionInterval);
|
||||
|
||||
/* Raw storage of the float in the message. Do not use setParameter3, does
|
||||
implicit conversion to integer type! */
|
||||
std::memcpy(command->getData() + 2 * sizeof(uint32_t), &collectionInterval,
|
||||
sizeof(collectionInterval));
|
||||
|
||||
setSid(command, sid);
|
||||
}
|
||||
|
||||
sid_t HousekeepingMessage::getCollectionIntervalModificationCommand(
|
||||
const CommandMessage* command, float* newCollectionInterval) {
|
||||
|
||||
if(newCollectionInterval != nullptr) {
|
||||
*newCollectionInterval = command->getParameter3();
|
||||
std::memcpy(newCollectionInterval, command->getData() + 2 * sizeof(uint32_t),
|
||||
sizeof(*newCollectionInterval));
|
||||
}
|
||||
|
||||
return getSid(command);
|
||||
@@ -125,8 +131,10 @@ sid_t HousekeepingMessage::getSid(const CommandMessage* message) {
|
||||
return sid;
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setSid(CommandMessage *message, sid_t sid) {
|
||||
std::memcpy(message->getData(), &sid.raw, sizeof(sid.raw));
|
||||
gp_id_t HousekeepingMessage::getGpid(const CommandMessage* message) {
|
||||
gp_id_t globalPoolId;
|
||||
std::memcpy(&globalPoolId.raw, message->getData(), sizeof(globalPoolId.raw));
|
||||
return globalPoolId;
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setHkStuctureReportReply(CommandMessage *reply,
|
||||
@@ -149,7 +157,8 @@ void HousekeepingMessage::clear(CommandMessage* message) {
|
||||
case(DIAGNOSTICS_REPORT):
|
||||
case(HK_DEFINITIONS_REPORT):
|
||||
case(DIAGNOSTICS_DEFINITION_REPORT):
|
||||
case(UPDATE_SNAPSHOT_SET): {
|
||||
case(UPDATE_SNAPSHOT_SET):
|
||||
case(UPDATE_SNAPSHOT_VARIABLE): {
|
||||
store_address_t storeId;
|
||||
getHkDataReply(message, &storeId);
|
||||
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
|
||||
@@ -169,22 +178,22 @@ void HousekeepingMessage::setUpdateNotificationSetCommand(
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setUpdateNotificationVariableCommand(
|
||||
CommandMessage *command, lp_id_t localPoolId) {
|
||||
CommandMessage *command, gp_id_t globalPoolId) {
|
||||
command->setCommand(UPDATE_NOTIFICATION_VARIABLE);
|
||||
command->setParameter(localPoolId);
|
||||
setGpid(command, globalPoolId);
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
|
||||
sid_t sid, store_address_t storeId) {
|
||||
command->setCommand(UPDATE_SNAPSHOT_VARIABLE);
|
||||
command->setCommand(UPDATE_SNAPSHOT_SET);
|
||||
setSid(command, sid);
|
||||
command->setParameter3(storeId.raw);
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setUpdateSnapshotVariableCommand(
|
||||
CommandMessage *command, lp_id_t localPoolId, store_address_t storeId) {
|
||||
CommandMessage *command, gp_id_t globalPoolId, store_address_t storeId) {
|
||||
command->setCommand(UPDATE_SNAPSHOT_VARIABLE);
|
||||
command->setParameter(localPoolId);
|
||||
setGpid(command, globalPoolId);
|
||||
command->setParameter3(storeId.raw);
|
||||
}
|
||||
|
||||
@@ -193,9 +202,9 @@ sid_t HousekeepingMessage::getUpdateNotificationSetCommand(
|
||||
return getSid(command);
|
||||
}
|
||||
|
||||
lp_id_t HousekeepingMessage::getUpdateNotificationVariableCommand(
|
||||
gp_id_t HousekeepingMessage::getUpdateNotificationVariableCommand(
|
||||
const CommandMessage *command) {
|
||||
return command->getParameter();
|
||||
return getGpid(command);
|
||||
}
|
||||
|
||||
sid_t HousekeepingMessage::getUpdateSnapshotSetCommand(
|
||||
@@ -206,10 +215,18 @@ sid_t HousekeepingMessage::getUpdateSnapshotSetCommand(
|
||||
return getSid(command);
|
||||
}
|
||||
|
||||
lp_id_t HousekeepingMessage::getUpdateSnapshotVariableCommand(
|
||||
gp_id_t HousekeepingMessage::getUpdateSnapshotVariableCommand(
|
||||
const CommandMessage *command, store_address_t *storeId) {
|
||||
if(storeId != nullptr) {
|
||||
*storeId = command->getParameter3();
|
||||
}
|
||||
return command->getParameter();
|
||||
return getGpid(command);
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setSid(CommandMessage *message, sid_t sid) {
|
||||
std::memcpy(message->getData(), &sid.raw, sizeof(sid.raw));
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setGpid(CommandMessage *message, gp_id_t globalPoolId) {
|
||||
std::memcpy(message->getData(), &globalPoolId.raw, sizeof(globalPoolId.raw));
|
||||
}
|
||||
|
@@ -75,6 +75,7 @@ public:
|
||||
//static constexpr Command_t UPDATE_HK_REPORT = MAKE_COMMAND_ID(134);
|
||||
|
||||
static sid_t getSid(const CommandMessage* message);
|
||||
static gp_id_t getGpid(const CommandMessage* message);
|
||||
|
||||
/* Housekeeping Interface Messages */
|
||||
|
||||
@@ -123,26 +124,27 @@ public:
|
||||
static void setUpdateNotificationSetCommand(CommandMessage* command,
|
||||
sid_t sid);
|
||||
static void setUpdateNotificationVariableCommand(CommandMessage* command,
|
||||
lp_id_t localPoolId);
|
||||
gp_id_t globalPoolId);
|
||||
|
||||
static void setUpdateSnapshotSetCommand(CommandMessage* command, sid_t sid,
|
||||
store_address_t storeId);
|
||||
static void setUpdateSnapshotVariableCommand(CommandMessage* command,
|
||||
lp_id_t localPoolId, store_address_t storeId);
|
||||
gp_id_t globalPoolId, store_address_t storeId);
|
||||
|
||||
static sid_t getUpdateNotificationSetCommand(const CommandMessage* command);
|
||||
static lp_id_t getUpdateNotificationVariableCommand(
|
||||
static gp_id_t getUpdateNotificationVariableCommand(
|
||||
const CommandMessage* command);
|
||||
|
||||
static sid_t getUpdateSnapshotSetCommand(const CommandMessage* command,
|
||||
store_address_t* storeId);
|
||||
static lp_id_t getUpdateSnapshotVariableCommand(const CommandMessage* command,
|
||||
static gp_id_t getUpdateSnapshotVariableCommand(const CommandMessage* command,
|
||||
store_address_t* storeId);
|
||||
|
||||
/** Utility */
|
||||
static void clear(CommandMessage* message);
|
||||
private:
|
||||
static void setSid(CommandMessage* message, sid_t sid);
|
||||
static void setGpid(CommandMessage* message, gp_id_t globalPoolId);
|
||||
};
|
||||
|
||||
|
||||
|
@@ -10,7 +10,11 @@
|
||||
* which are destined to be downlinked into the store.
|
||||
* @details
|
||||
* The housekeeping packets are stored into the IPC store and forwarded
|
||||
* to the designated housekeeping handler.
|
||||
* to the designated housekeeping handler. The packet will consist of the following fields
|
||||
* - SID (8 byte): Structure ID, with the first 4 bytes being the object ID and the last four
|
||||
* bytes being the set ID
|
||||
* - Housekeeping Data: The rest of the packet will be the serialized housekeeping data. A validity
|
||||
* buffer might be appended at the end, depending on the set configuration.
|
||||
*/
|
||||
class HousekeepingPacketDownlink: public SerialLinkedListAdapter<SerializeIF> {
|
||||
public:
|
||||
|
@@ -1,24 +1,38 @@
|
||||
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_
|
||||
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_
|
||||
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
|
||||
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
|
||||
|
||||
#include "../serialize/SerialBufferAdapter.h"
|
||||
#include "../serialize/SerialLinkedListAdapter.h"
|
||||
#include "../datapoollocal/LocalPoolDataSetBase.h"
|
||||
#include "../datapoollocal/LocalPoolObjectBase.h"
|
||||
#include "../timemanager/CCSDSTime.h"
|
||||
|
||||
/**
|
||||
* @brief This helper class will be used to serialize and deserialize
|
||||
* update housekeeping packets into the store.
|
||||
* @brief This helper class will be used to serialize and deserialize update housekeeping packets
|
||||
* into the store.
|
||||
*/
|
||||
class HousekeepingPacketUpdate: public SerializeIF {
|
||||
class HousekeepingSnapshot:
|
||||
public SerializeIF {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Update packet constructor for datasets
|
||||
* @param timeStamp
|
||||
* @param timeStampSize
|
||||
* @param hkData
|
||||
* @param hkDataSize
|
||||
* Update packet constructor for datasets.
|
||||
* @param cdsShort If a CSD short timestamp is used, a reference should be
|
||||
* supplied here
|
||||
* @param dataSetPtr Pointer to the dataset instance to serialize or deserialize the
|
||||
* data into
|
||||
*/
|
||||
HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize,
|
||||
HousekeepingSnapshot(CCSDSTime::CDS_short* cdsShort, LocalPoolDataSetBase* dataSetPtr):
|
||||
timeStamp(reinterpret_cast<uint8_t*>(cdsShort)),
|
||||
timeStampSize(sizeof(CCSDSTime::CDS_short)), updateData(dataSetPtr) {};
|
||||
|
||||
/**
|
||||
* Update packet constructor for datasets.
|
||||
* @param timeStamp Pointer to the buffer where the timestamp will be stored.
|
||||
* @param timeStampSize Size of the timestamp
|
||||
* @param dataSetPtr Pointer to the dataset instance to deserialize the data into
|
||||
*/
|
||||
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize,
|
||||
LocalPoolDataSetBase* dataSetPtr):
|
||||
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
||||
updateData(dataSetPtr) {};
|
||||
@@ -29,13 +43,24 @@ public:
|
||||
* @param timeStampSize
|
||||
* @param dataSetPtr
|
||||
*/
|
||||
HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize,
|
||||
HousekeepingSnapshot(CCSDSTime::CDS_short* cdsShort, LocalPoolObjectBase* dataSetPtr):
|
||||
timeStamp(reinterpret_cast<uint8_t*>(cdsShort)),
|
||||
timeStampSize(sizeof(CCSDSTime::CDS_short)), updateData(dataSetPtr) {};
|
||||
|
||||
|
||||
/**
|
||||
* Update packet constructor for pool variables.
|
||||
* @param timeStamp
|
||||
* @param timeStampSize
|
||||
* @param dataSetPtr
|
||||
*/
|
||||
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize,
|
||||
LocalPoolObjectBase* dataSetPtr):
|
||||
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
||||
updateData(dataSetPtr) {};
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
|
||||
size_t maxSize, Endianness streamEndianness) const {
|
||||
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
if(timeStamp != nullptr) {
|
||||
/* Endianness will always be MACHINE, so we can simply use memcpy
|
||||
here. */
|
||||
@@ -89,4 +114,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ */
|
||||
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_ */
|
@@ -4,46 +4,87 @@
|
||||
#include <cmath>
|
||||
|
||||
PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(
|
||||
LocalPoolDataSetBase* owner): owner(owner) {}
|
||||
|
||||
LocalPoolDataSetBase* owner): owner(owner) {}
|
||||
|
||||
void PeriodicHousekeepingHelper::initialize(float collectionInterval,
|
||||
dur_millis_t minimumPeriodicInterval, bool isDiagnostics,
|
||||
uint8_t nonDiagIntervalFactor) {
|
||||
this->minimumPeriodicInterval = minimumPeriodicInterval;
|
||||
if(not isDiagnostics) {
|
||||
this->minimumPeriodicInterval = this->minimumPeriodicInterval *
|
||||
nonDiagIntervalFactor;
|
||||
}
|
||||
collectionIntervalTicks = intervalSecondsToInterval(collectionInterval);
|
||||
dur_millis_t minimumPeriodicInterval, uint8_t nonDiagIntervalFactor) {
|
||||
this->minimumPeriodicInterval = minimumPeriodicInterval;
|
||||
this->nonDiagIntervalFactor = nonDiagIntervalFactor;
|
||||
collectionIntervalTicks = intervalSecondsToIntervalTicks(collectionInterval);
|
||||
/* This will cause a checkOpNecessary call to be true immediately. I think it's okay
|
||||
if a HK packet is generated immediately instead of waiting one generation cycle. */
|
||||
internalTickCounter = collectionIntervalTicks;
|
||||
}
|
||||
|
||||
float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() {
|
||||
return intervalToIntervalSeconds(collectionIntervalTicks);
|
||||
float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() const {
|
||||
return intervalTicksToSeconds(collectionIntervalTicks);
|
||||
}
|
||||
|
||||
bool PeriodicHousekeepingHelper::checkOpNecessary() {
|
||||
if(internalTickCounter >= collectionIntervalTicks) {
|
||||
internalTickCounter = 1;
|
||||
return true;
|
||||
}
|
||||
internalTickCounter++;
|
||||
return false;
|
||||
if(internalTickCounter >= collectionIntervalTicks) {
|
||||
internalTickCounter = 1;
|
||||
return true;
|
||||
}
|
||||
internalTickCounter++;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t PeriodicHousekeepingHelper::intervalSecondsToInterval(
|
||||
float collectionIntervalSeconds) {
|
||||
return std::ceil(collectionIntervalSeconds * 1000
|
||||
/ minimumPeriodicInterval);
|
||||
uint32_t PeriodicHousekeepingHelper::intervalSecondsToIntervalTicks(
|
||||
float collectionIntervalSeconds) {
|
||||
if(owner == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
bool isDiagnostics = owner->isDiagnostics();
|
||||
|
||||
/* Avoid division by zero */
|
||||
if(minimumPeriodicInterval == 0) {
|
||||
if(isDiagnostics) {
|
||||
/* Perform operation each cycle */
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return nonDiagIntervalFactor;
|
||||
}
|
||||
}
|
||||
else {
|
||||
dur_millis_t intervalInMs = collectionIntervalSeconds * 1000;
|
||||
uint32_t divisor = minimumPeriodicInterval;
|
||||
if(not isDiagnostics) {
|
||||
/* We need to multiply the divisor because non-diagnostics only
|
||||
allow a multiple of the minimum periodic interval */
|
||||
divisor *= nonDiagIntervalFactor;
|
||||
}
|
||||
uint32_t ticks = std::ceil(static_cast<float>(intervalInMs) / divisor);
|
||||
if(not isDiagnostics) {
|
||||
/* Now we need to multiply the calculated ticks with the factor as as well
|
||||
because the minimum tick count to generate a non-diagnostic is the factor itself.
|
||||
|
||||
Example calculation for non-diagnostic with
|
||||
0.4 second interval and 0.2 second task interval.
|
||||
Resultant tick count of 5 is equal to operation each second.
|
||||
|
||||
Examle calculation for non-diagnostic with 2.0 second interval and 0.2 second
|
||||
task interval.
|
||||
Resultant tick count of 10 is equal to operatin every 2 seconds.
|
||||
|
||||
Example calculation for diagnostic with 0.4 second interval and 0.3
|
||||
second task interval. Resulting tick count of 2 is equal to operation
|
||||
every 0.6 seconds. */
|
||||
ticks *= nonDiagIntervalFactor;
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
}
|
||||
|
||||
float PeriodicHousekeepingHelper::intervalToIntervalSeconds(
|
||||
uint32_t collectionInterval) {
|
||||
return static_cast<float>(collectionInterval *
|
||||
minimumPeriodicInterval);
|
||||
float PeriodicHousekeepingHelper::intervalTicksToSeconds(
|
||||
uint32_t collectionInterval) const {
|
||||
/* Number of ticks times the minimum interval is in milliseconds, so we divide by 1000 to get
|
||||
the value in seconds */
|
||||
return static_cast<float>(collectionInterval * minimumPeriodicInterval / 1000.0);
|
||||
}
|
||||
|
||||
void PeriodicHousekeepingHelper::changeCollectionInterval(
|
||||
float newIntervalSeconds) {
|
||||
collectionIntervalTicks = intervalSecondsToInterval(newIntervalSeconds);
|
||||
float newIntervalSeconds) {
|
||||
collectionIntervalTicks = intervalSecondsToIntervalTicks(newIntervalSeconds);
|
||||
}
|
||||
|
||||
|
@@ -10,18 +10,19 @@ class PeriodicHousekeepingHelper {
|
||||
public:
|
||||
PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner);
|
||||
|
||||
void initialize(float collectionInterval,
|
||||
dur_millis_t minimumPeriodicInterval, bool isDiagnostics,
|
||||
uint8_t nonDiagIntervalFactor);
|
||||
void initialize(float collectionInterval, dur_millis_t minimumPeriodicInterval,
|
||||
uint8_t nonDiagIntervalFactor);
|
||||
|
||||
void changeCollectionInterval(float newInterval);
|
||||
float getCollectionIntervalInSeconds();
|
||||
float getCollectionIntervalInSeconds() const;
|
||||
bool checkOpNecessary();
|
||||
|
||||
private:
|
||||
LocalPoolDataSetBase* owner = nullptr;
|
||||
uint8_t nonDiagIntervalFactor = 0;
|
||||
|
||||
uint32_t intervalSecondsToInterval(float collectionIntervalSeconds);
|
||||
float intervalToIntervalSeconds(uint32_t collectionInterval);
|
||||
uint32_t intervalSecondsToIntervalTicks(float collectionIntervalSeconds);
|
||||
float intervalTicksToSeconds(uint32_t collectionInterval) const;
|
||||
|
||||
dur_millis_t minimumPeriodicInterval = 0;
|
||||
uint32_t internalTickCounter = 1;
|
||||
|
@@ -3,19 +3,20 @@
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../datapool/PoolReadGuard.h"
|
||||
|
||||
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
|
||||
uint32_t messageQueueDepth): SystemObject(setObjectId),
|
||||
commandQueue(QueueFactory::instance()->
|
||||
createMessageQueue(messageQueueDepth)),
|
||||
poolManager(this, commandQueue),
|
||||
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
||||
internalErrorDataset(this) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
commandQueue(QueueFactory::instance()->
|
||||
createMessageQueue(messageQueueDepth)),
|
||||
poolManager(this, commandQueue),
|
||||
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
||||
internalErrorDataset(this) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
InternalErrorReporter::~InternalErrorReporter() {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
}
|
||||
|
||||
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
|
||||
@@ -23,126 +24,128 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
|
||||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
||||
internalErrorDataset.read(timeoutType, timeoutMs);
|
||||
CommandMessage message;
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&message);
|
||||
if(result != MessageQueueIF::EMPTY) {
|
||||
poolManager.handleHousekeepingMessage(&message);
|
||||
}
|
||||
|
||||
uint32_t newQueueHits = getAndResetQueueHits();
|
||||
uint32_t newTmHits = getAndResetTmHits();
|
||||
uint32_t newStoreHits = getAndResetStoreHits();
|
||||
uint32_t newQueueHits = getAndResetQueueHits();
|
||||
uint32_t newTmHits = getAndResetTmHits();
|
||||
uint32_t newStoreHits = getAndResetStoreHits();
|
||||
|
||||
#if FSFW_VERBOSE_LEVEL == 1
|
||||
if(diagnosticPrintout) {
|
||||
if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
if(diagnosticPrintout) {
|
||||
if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "InternalErrorReporter::performOperation: Errors "
|
||||
<< "occured!" << std::endl;
|
||||
sif::debug << "Queue errors: " << newQueueHits << std::endl;
|
||||
sif::debug << "TM errors: " << newTmHits << std::endl;
|
||||
sif::debug << "Store errors: " << newStoreHits << std::endl;
|
||||
sif::debug << "InternalErrorReporter::performOperation: Errors "
|
||||
<< "occured!" << std::endl;
|
||||
sif::debug << "Queue errors: " << newQueueHits << std::endl;
|
||||
sif::debug << "TM errors: " << newTmHits << std::endl;
|
||||
sif::debug << "Store errors: " << newStoreHits << std::endl;
|
||||
#else
|
||||
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
|
||||
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
|
||||
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
|
||||
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
|
||||
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
|
||||
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
|
||||
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
|
||||
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internalErrorDataset.queueHits.value += newQueueHits;
|
||||
internalErrorDataset.storeHits.value += newStoreHits;
|
||||
internalErrorDataset.tmHits.value += newTmHits;
|
||||
internalErrorDataset.setValidity(true, true);
|
||||
internalErrorDataset.commit(timeoutType, timeoutMs);
|
||||
{
|
||||
PoolReadGuard readGuard(&internalErrorDataset);
|
||||
if(readGuard.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
|
||||
internalErrorDataset.queueHits.value += newQueueHits;
|
||||
internalErrorDataset.storeHits.value += newStoreHits;
|
||||
internalErrorDataset.tmHits.value += newTmHits;
|
||||
internalErrorDataset.setValidity(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
poolManager.performHkOperation();
|
||||
|
||||
CommandMessage message;
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&message);
|
||||
if(result != MessageQueueIF::EMPTY) {
|
||||
poolManager.handleHousekeepingMessage(&message);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
poolManager.performHkOperation();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::queueMessageNotSent() {
|
||||
incrementQueueHits();
|
||||
incrementQueueHits();
|
||||
}
|
||||
|
||||
void InternalErrorReporter::lostTm() {
|
||||
incrementTmHits();
|
||||
incrementTmHits();
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getAndResetQueueHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = queueHits;
|
||||
queueHits = 0;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = queueHits;
|
||||
queueHits = 0;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getQueueHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = queueHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = queueHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementQueueHits() {
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
queueHits++;
|
||||
mutex->unlockMutex();
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
queueHits++;
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getAndResetTmHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = tmHits;
|
||||
tmHits = 0;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = tmHits;
|
||||
tmHits = 0;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getTmHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = tmHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = tmHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementTmHits() {
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
tmHits++;
|
||||
mutex->unlockMutex();
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
tmHits++;
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
|
||||
void InternalErrorReporter::storeFull() {
|
||||
incrementStoreHits();
|
||||
incrementStoreHits();
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getAndResetStoreHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = storeHits;
|
||||
storeHits = 0;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = storeHits;
|
||||
storeHits = 0;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getStoreHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = storeHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = storeHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementStoreHits() {
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
storeHits++;
|
||||
mutex->unlockMutex();
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
storeHits++;
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
|
||||
object_id_t InternalErrorReporter::getObjectId() const {
|
||||
@@ -155,14 +158,11 @@ MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
|
||||
|
||||
ReturnValue_t InternalErrorReporter::initializeLocalDataPool(
|
||||
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(errorPoolIds::TM_HITS,
|
||||
new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS,
|
||||
new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(errorPoolIds::STORE_HITS,
|
||||
new PoolEntry<uint32_t>());
|
||||
poolManager.subscribeForPeriodicPacket(internalErrorSid, false,
|
||||
getPeriodicOperationFrequency(), true);
|
||||
localDataPoolMap.emplace(errorPoolIds::TM_HITS, new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, new PoolEntry<uint32_t>());
|
||||
poolManager.subscribeForPeriodicPacket(internalErrorSid, false, getPeriodicOperationFrequency(),
|
||||
true);
|
||||
internalErrorDataset.setValidity(true, true);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
@@ -192,9 +192,9 @@ ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() {
|
||||
}
|
||||
|
||||
void InternalErrorReporter::setMutexTimeout(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) {
|
||||
this->timeoutType = timeoutType;
|
||||
this->timeoutMs = timeoutMs;
|
||||
uint32_t timeoutMs) {
|
||||
this->timeoutType = timeoutType;
|
||||
this->timeoutMs = timeoutMs;
|
||||
}
|
||||
|
||||
LocalDataPoolManager* InternalErrorReporter::getHkManagerHandle() {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user