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
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:
commit
f23debceac
4
.gitignore
vendored
4
.gitignore
vendored
@ -22,3 +22,7 @@ __pycache__
|
|||||||
!/.idea/cmake.xml
|
!/.idea/cmake.xml
|
||||||
|
|
||||||
generators/*.db
|
generators/*.db
|
||||||
|
|
||||||
|
# Clangd LSP
|
||||||
|
/compile_commands.json
|
||||||
|
/.cache
|
||||||
|
@ -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.
|
||||||
|
@ -137,40 +137,68 @@ 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) {
|
||||||
Clock::getClock_timeval(¤tTv);
|
result = handleDeletionCmd(ipcStore, cmdMessage);
|
||||||
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
|
||||||
auto accessor = ipcStore.getData(storeId);
|
|
||||||
uint32_t deleteUpToUnixSeconds = 0;
|
|
||||||
size_t size = accessor.second.size();
|
|
||||||
SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, accessor.second.data(), &size,
|
|
||||||
SerializeIF::Endianness::NETWORK);
|
|
||||||
execCmd = cmd;
|
execCmd = cmd;
|
||||||
deleteUpTo(deleteUpToUnixSeconds);
|
|
||||||
} else if (cmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
|
} else if (cmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
|
||||||
Clock::getClock_timeval(¤tTv);
|
result = handleDumpCmd(ipcStore, cmdMessage);
|
||||||
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
|
||||||
auto accessor = ipcStore.getData(storeId);
|
|
||||||
if (accessor.second.size() < 8) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
uint32_t dumpFromUnixSeconds = 0;
|
|
||||||
uint32_t dumpUntilUnixSeconds = 0;
|
|
||||||
size_t size = 8;
|
|
||||||
SerializeAdapter::deSerialize(&dumpFromUnixSeconds, accessor.second.data(), &size,
|
|
||||||
SerializeIF::Endianness::NETWORK);
|
|
||||||
SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size,
|
|
||||||
SerializeIF::Endianness::NETWORK);
|
|
||||||
result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
|
|
||||||
if (result == BUSY_DUMPING) {
|
|
||||||
triggerEvent(persTmStore::BUSY_DUMPING_EVENT);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
execCmd = cmd;
|
execCmd = cmd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::handleDeletionCmd(StorageManagerIF& ipcStore,
|
||||||
|
CommandMessage& cmdMessage) {
|
||||||
|
Clock::getClock_timeval(¤tTv);
|
||||||
|
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
||||||
|
auto accessor = ipcStore.getData(storeId);
|
||||||
|
size_t size = accessor.second.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);
|
||||||
|
deleteUpTo(deleteUpToUnixSeconds);
|
||||||
|
} 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(¤tTv);
|
||||||
|
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
|
||||||
|
auto accessor = ipcStore.getData(storeId);
|
||||||
|
if (accessor.second.size() < 8) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
uint32_t dumpFromUnixSeconds = 0;
|
||||||
|
uint32_t dumpUntilUnixSeconds = 0;
|
||||||
|
size_t size = 8;
|
||||||
|
SerializeAdapter::deSerialize(&dumpFromUnixSeconds, accessor.second.data(), &size,
|
||||||
|
SerializeIF::Endianness::NETWORK);
|
||||||
|
SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size,
|
||||||
|
SerializeIF::Endianness::NETWORK);
|
||||||
|
ReturnValue_t result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
|
||||||
|
if (result == BUSY_DUMPING) {
|
||||||
|
triggerEvent(persTmStore::BUSY_DUMPING_EVENT);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t PersistentTmStore::startDumpFrom(uint32_t fromUnixSeconds) {
|
ReturnValue_t PersistentTmStore::startDumpFrom(uint32_t fromUnixSeconds) {
|
||||||
return startDumpFromUpTo(fromUnixSeconds, currentTv.tv_sec);
|
return startDumpFromUpTo(fromUnixSeconds, currentTv.tv_sec);
|
||||||
}
|
}
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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_ */
|
||||||
|
@ -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,34 +46,55 @@ 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) {
|
||||||
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
case (Subservice::START_BY_TIME_RANGE_RETRIEVAL): {
|
||||||
// to time reading and reply handling
|
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||||
if (tcDataLen != 12) {
|
// to time reading and reply handling
|
||||||
return INVALID_TC;
|
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::setDownlinkContentTimeMessage(message, storeId);
|
||||||
|
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||||
}
|
}
|
||||||
store_address_t storeId;
|
case (Subservice::DELETE_UP_TO): {
|
||||||
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
|
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||||
if (result != OK) {
|
// to time reading and reply handling
|
||||||
return result;
|
if (tcDataLen != 8) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
// Store timestamps
|
case (Subservice::DELETE_BY_TIME_RANGE): {
|
||||||
TmStoreMessage::setDownlinkContentTimeMessage(message, storeId);
|
// TODO: Hardcoded two UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
||||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
// to time reading and reply handling
|
||||||
} else if (subservice == Subservices::DELETE_UP_TO) {
|
if (tcDataLen != 12) {
|
||||||
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
|
return INVALID_TC;
|
||||||
// to time reading and reply handling
|
}
|
||||||
if (tcDataLen != 8) {
|
store_address_t storeId;
|
||||||
return INVALID_TC;
|
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;
|
||||||
}
|
}
|
||||||
store_address_t storeId;
|
default: {
|
||||||
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
|
return CommandingServiceBase::INVALID_SUBSERVICE;
|
||||||
if (result != OK) {
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
// Store timestamps
|
|
||||||
TmStoreMessage::setDeleteContentTimeMessage(message, storeId);
|
|
||||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -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
2
tmtc
@ -1 +1 @@
|
|||||||
Subproject commit 99c6c8bbd0d791d8b17720de481c6142091a54a4
|
Subproject commit 0a417a89e9e7f0447d35c70950685df59bf5c062
|
Loading…
Reference in New Issue
Block a user