Merge pull request 'Persistent TM store delete time range' (#823) from persistent-tm-store-delete-time-range into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good

Reviewed-on: #823
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
This commit is contained in:
Robin Müller 2023-11-29 14:20:41 +01:00
commit f23debceac
7 changed files with 123 additions and 56 deletions

4
.gitignore vendored
View File

@ -22,3 +22,7 @@ __pycache__
!/.idea/cmake.xml !/.idea/cmake.xml
generators/*.db generators/*.db
# Clangd LSP
/compile_commands.json
/.cache

View File

@ -24,6 +24,8 @@ will consitute of a breaking change warranting a new major release:
## Added ## Added
- Added new PUS 15 subservice `DELETE_BY_TIME_RANGE` which allows to also specify a deletion
start time when deleting packets from the persistent TM store.
- Introduced a new `RELOAD_JSON_CFG_FILE` command for the STR to reload the JSON configuration - Introduced a new `RELOAD_JSON_CFG_FILE` command for the STR to reload the JSON configuration
data based on the current output of the config file path getter function. A reboot of the data based on the current output of the config file path getter function. A reboot of the
device is still necessary to load the configuration to the STR. device is still necessary to load the configuration to the STR.

View File

@ -137,16 +137,47 @@ ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
if (cmdMessage.getMessageType() == messagetypes::TM_STORE) { if (cmdMessage.getMessageType() == messagetypes::TM_STORE) {
Command_t cmd = cmdMessage.getCommand(); Command_t cmd = cmdMessage.getCommand();
if (cmd == TmStoreMessage::DELETE_STORE_CONTENT_TIME) { if (cmd == TmStoreMessage::DELETE_STORE_CONTENT_TIME) {
result = handleDeletionCmd(ipcStore, cmdMessage);
execCmd = cmd;
} else if (cmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
result = handleDumpCmd(ipcStore, cmdMessage);
execCmd = cmd;
}
}
return result;
}
ReturnValue_t PersistentTmStore::handleDeletionCmd(StorageManagerIF& ipcStore,
CommandMessage& cmdMessage) {
Clock::getClock_timeval(&currentTv); Clock::getClock_timeval(&currentTv);
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage); store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
auto accessor = ipcStore.getData(storeId); auto accessor = ipcStore.getData(storeId);
uint32_t deleteUpToUnixSeconds = 0;
size_t size = accessor.second.size(); size_t size = accessor.second.size();
SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, accessor.second.data(), &size, if (size < 4) {
return returnvalue::FAILED;
}
const uint8_t* data = accessor.second.data();
uint32_t deleteUpToUnixSeconds = 0;
if (size == 4) {
SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size,
SerializeIF::Endianness::NETWORK); SerializeIF::Endianness::NETWORK);
execCmd = cmd;
deleteUpTo(deleteUpToUnixSeconds); deleteUpTo(deleteUpToUnixSeconds);
} else if (cmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) { } else if (size == 8) {
uint32_t deleteFromUnixSeconds = 0;
SerializeAdapter::deSerialize(&deleteFromUnixSeconds, &data, &size,
SerializeIF::Endianness::NETWORK);
SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, &data, &size,
SerializeIF::Endianness::NETWORK);
deleteFromUpTo(deleteFromUnixSeconds, deleteUpToUnixSeconds);
} else {
sif::warning << "PersistentTmStore: Unknown deletion time specification" << std::endl;
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t PersistentTmStore::handleDumpCmd(StorageManagerIF& ipcStore,
CommandMessage& cmdMessage) {
Clock::getClock_timeval(&currentTv); Clock::getClock_timeval(&currentTv);
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage); store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
auto accessor = ipcStore.getData(storeId); auto accessor = ipcStore.getData(storeId);
@ -160,15 +191,12 @@ ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
SerializeIF::Endianness::NETWORK); SerializeIF::Endianness::NETWORK);
SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size, SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size,
SerializeIF::Endianness::NETWORK); SerializeIF::Endianness::NETWORK);
result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds); ReturnValue_t result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
if (result == BUSY_DUMPING) { if (result == BUSY_DUMPING) {
triggerEvent(persTmStore::BUSY_DUMPING_EVENT); triggerEvent(persTmStore::BUSY_DUMPING_EVENT);
return result; return result;
} }
execCmd = cmd; return returnvalue::OK;
}
}
return result;
} }
ReturnValue_t PersistentTmStore::startDumpFrom(uint32_t fromUnixSeconds) { ReturnValue_t PersistentTmStore::startDumpFrom(uint32_t fromUnixSeconds) {
@ -257,7 +285,9 @@ bool PersistentTmStore::updateBaseDir() {
return true; return true;
} }
void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) { void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) { deleteFromUpTo(0, unixSeconds); }
void PersistentTmStore::deleteFromUpTo(uint32_t startUnixTime, uint32_t endUnixTime) {
using namespace std::filesystem; using namespace std::filesystem;
for (auto const& file : directory_iterator(basePath)) { for (auto const& file : directory_iterator(basePath)) {
if (file.is_directory() or (activeFile.has_value() and (activeFile.value() == file.path()))) { if (file.is_directory() or (activeFile.has_value() and (activeFile.value() == file.path()))) {
@ -270,7 +300,8 @@ void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) {
continue; continue;
} }
time_t fileEpoch = timegm(&fileTime); time_t fileEpoch = timegm(&fileTime);
if (fileEpoch + rolloverDiffSeconds < unixSeconds) { if (fileEpoch + rolloverDiffSeconds < endUnixTime and
static_cast<uint32_t>(fileEpoch) >= startUnixTime) {
std::error_code e; std::error_code e;
std::filesystem::remove(file.path(), e); std::filesystem::remove(file.path(), e);
} }

View File

@ -14,6 +14,7 @@
#include "eive/eventSubsystemIds.h" #include "eive/eventSubsystemIds.h"
#include "eive/resultClassIds.h" #include "eive/resultClassIds.h"
#include "fsfw/ipc/CommandMessage.h"
enum class RolloverInterval { MINUTELY, HOURLY, DAILY }; enum class RolloverInterval { MINUTELY, HOURLY, DAILY };
@ -60,6 +61,7 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
ReturnValue_t handleCommandQueue(StorageManagerIF& ipcStore, Command_t& execCmd); ReturnValue_t handleCommandQueue(StorageManagerIF& ipcStore, Command_t& execCmd);
void deleteUpTo(uint32_t unixSeconds); void deleteUpTo(uint32_t unixSeconds);
void deleteFromUpTo(uint32_t startUnixTime, uint32_t endUnixTime);
ReturnValue_t startDumpFrom(uint32_t fromUnixSeconds); ReturnValue_t startDumpFrom(uint32_t fromUnixSeconds);
ReturnValue_t startDumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds); ReturnValue_t startDumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds);
/** /**
@ -145,6 +147,8 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
std::optional<uint8_t> extractSuffix(const std::string& pathStr); std::optional<uint8_t> extractSuffix(const std::string& pathStr);
bool updateBaseDir(); bool updateBaseDir();
ReturnValue_t assignAndOrCreateMostRecentFile(); ReturnValue_t assignAndOrCreateMostRecentFile();
ReturnValue_t handleDeletionCmd(StorageManagerIF& ipcStore, CommandMessage& cmdMessage);
ReturnValue_t handleDumpCmd(StorageManagerIF& ipcStore, CommandMessage& cmdMessage);
}; };
#endif /* MISSION_TMTC_TMSTOREBACKEND_H_ */ #endif /* MISSION_TMTC_TMSTOREBACKEND_H_ */

View File

@ -16,8 +16,9 @@ Service15TmStorage::Service15TmStorage(object_id_t objectId, uint16_t apid,
ReturnValue_t Service15TmStorage::isValidSubservice(uint8_t subservice) { ReturnValue_t Service15TmStorage::isValidSubservice(uint8_t subservice) {
switch (subservice) { switch (subservice) {
case (Subservices::DELETE_UP_TO): case (Subservice::DELETE_UP_TO):
case (Subservices::START_BY_TIME_RANGE_RETRIEVAL): { case (Subservice::DELETE_BY_TIME_RANGE):
case (Subservice::START_BY_TIME_RANGE_RETRIEVAL): {
return OK; return OK;
} }
default: { default: {
@ -45,7 +46,8 @@ ReturnValue_t Service15TmStorage::getMessageQueueAndObject(uint8_t subservice,
ReturnValue_t Service15TmStorage::prepareCommand(CommandMessage *message, uint8_t subservice, ReturnValue_t Service15TmStorage::prepareCommand(CommandMessage *message, uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen, const uint8_t *tcData, size_t tcDataLen,
uint32_t *state, object_id_t objectId) { uint32_t *state, object_id_t objectId) {
if (subservice == Subservices::START_BY_TIME_RANGE_RETRIEVAL) { switch (subservice) {
case (Subservice::START_BY_TIME_RANGE_RETRIEVAL): {
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver // TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
// to time reading and reply handling // to time reading and reply handling
if (tcDataLen != 12) { if (tcDataLen != 12) {
@ -59,7 +61,8 @@ ReturnValue_t Service15TmStorage::prepareCommand(CommandMessage *message, uint8_
// Store timestamps // Store timestamps
TmStoreMessage::setDownlinkContentTimeMessage(message, storeId); TmStoreMessage::setDownlinkContentTimeMessage(message, storeId);
return CommandingServiceBase::EXECUTION_COMPLETE; return CommandingServiceBase::EXECUTION_COMPLETE;
} else if (subservice == Subservices::DELETE_UP_TO) { }
case (Subservice::DELETE_UP_TO): {
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver // TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
// to time reading and reply handling // to time reading and reply handling
if (tcDataLen != 8) { if (tcDataLen != 8) {
@ -74,6 +77,25 @@ ReturnValue_t Service15TmStorage::prepareCommand(CommandMessage *message, uint8_
TmStoreMessage::setDeleteContentTimeMessage(message, storeId); TmStoreMessage::setDeleteContentTimeMessage(message, storeId);
return CommandingServiceBase::EXECUTION_COMPLETE; return CommandingServiceBase::EXECUTION_COMPLETE;
} }
case (Subservice::DELETE_BY_TIME_RANGE): {
// TODO: Hardcoded two UNIX timestamps.. Should allow arbitrary timestamp and let receiver
// to time reading and reply handling
if (tcDataLen != 12) {
return INVALID_TC;
}
store_address_t storeId;
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
if (result != OK) {
return result;
}
// Store timestamps
TmStoreMessage::setDeleteContentTimeMessage(message, storeId);
return CommandingServiceBase::EXECUTION_COMPLETE;
}
default: {
return CommandingServiceBase::INVALID_SUBSERVICE;
}
}
return OK; return OK;
} }

View File

@ -5,7 +5,11 @@
class Service15TmStorage : public CommandingServiceBase { class Service15TmStorage : public CommandingServiceBase {
public: public:
enum Subservices : uint8_t { START_BY_TIME_RANGE_RETRIEVAL = 9, DELETE_UP_TO = 11 }; enum Subservice : uint8_t {
START_BY_TIME_RANGE_RETRIEVAL = 9,
DELETE_UP_TO = 11,
DELETE_BY_TIME_RANGE = 128
};
explicit Service15TmStorage(object_id_t objectId, uint16_t apid, uint8_t numParallelCommands, explicit Service15TmStorage(object_id_t objectId, uint16_t apid, uint8_t numParallelCommands,
uint16_t commandTimeoutSecs = 60, size_t queueDepth = 10); uint16_t commandTimeoutSecs = 60, size_t queueDepth = 10);

2
tmtc

@ -1 +1 @@
Subproject commit 99c6c8bbd0d791d8b17720de481c6142091a54a4 Subproject commit 0a417a89e9e7f0447d35c70950685df59bf5c062