applied formatting
This commit is contained in:
@ -1,257 +1,241 @@
|
||||
#include "FileSystemHandler.h"
|
||||
|
||||
#include "bsp_q7s/core/CoreController.h"
|
||||
|
||||
#include "fsfw/tasks/TaskFactory.h"
|
||||
#include "fsfw/memory/GenericFileSystemMessage.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
FileSystemHandler::FileSystemHandler(object_id_t fileSystemHandler):
|
||||
SystemObject(fileSystemHandler) {
|
||||
mq = QueueFactory::instance()->createMessageQueue(FS_MAX_QUEUE_SIZE);
|
||||
#include "bsp_q7s/core/CoreController.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/memory/GenericFileSystemMessage.h"
|
||||
#include "fsfw/tasks/TaskFactory.h"
|
||||
|
||||
FileSystemHandler::FileSystemHandler(object_id_t fileSystemHandler)
|
||||
: SystemObject(fileSystemHandler) {
|
||||
mq = QueueFactory::instance()->createMessageQueue(FS_MAX_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
FileSystemHandler::~FileSystemHandler() {
|
||||
QueueFactory::instance()->deleteMessageQueue(mq);
|
||||
}
|
||||
FileSystemHandler::~FileSystemHandler() { QueueFactory::instance()->deleteMessageQueue(mq); }
|
||||
|
||||
ReturnValue_t FileSystemHandler::performOperation(uint8_t unsignedChar) {
|
||||
while(true) {
|
||||
try {
|
||||
fileSystemHandlerLoop();
|
||||
}
|
||||
catch(std::bad_alloc& e) {
|
||||
// Restart OBSW, hints at a memory leak
|
||||
sif::error << "Allocation error in FileSystemHandler::performOperation"
|
||||
<< e.what() << std::endl;
|
||||
// Set up an error file or a special flag in the scratch buffer for these cases
|
||||
triggerEvent(CoreController::ALLOC_FAILURE, 0 , 0);
|
||||
CoreController::incrementAllocationFailureCount();
|
||||
}
|
||||
while (true) {
|
||||
try {
|
||||
fileSystemHandlerLoop();
|
||||
} catch (std::bad_alloc& e) {
|
||||
// Restart OBSW, hints at a memory leak
|
||||
sif::error << "Allocation error in FileSystemHandler::performOperation" << e.what()
|
||||
<< std::endl;
|
||||
// Set up an error file or a special flag in the scratch buffer for these cases
|
||||
triggerEvent(CoreController::ALLOC_FAILURE, 0, 0);
|
||||
CoreController::incrementAllocationFailureCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FileSystemHandler::fileSystemHandlerLoop() {
|
||||
CommandMessage filemsg;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
while(true) {
|
||||
if(opCounter % 5 == 0) {
|
||||
if(coreCtrl->sdInitFinished()) {
|
||||
fileSystemCheckup();
|
||||
}
|
||||
}
|
||||
result = mq->receiveMessage(&filemsg);
|
||||
if(result == MessageQueueIF::EMPTY) {
|
||||
break;
|
||||
}
|
||||
else if(result != HasReturnvaluesIF::RETURN_FAILED) {
|
||||
sif::warning << "FileSystemHandler::performOperation: Message reception failed!"
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
Command_t command = filemsg.getCommand();
|
||||
switch(command) {
|
||||
case(GenericFileSystemMessage::CMD_CREATE_DIRECTORY): {
|
||||
break;
|
||||
}
|
||||
case(GenericFileSystemMessage::CMD_CREATE_FILE): {
|
||||
break;
|
||||
}
|
||||
}
|
||||
opCounter++;
|
||||
CommandMessage filemsg;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
while (true) {
|
||||
if (opCounter % 5 == 0) {
|
||||
if (coreCtrl->sdInitFinished()) {
|
||||
fileSystemCheckup();
|
||||
}
|
||||
}
|
||||
result = mq->receiveMessage(&filemsg);
|
||||
if (result == MessageQueueIF::EMPTY) {
|
||||
break;
|
||||
} else if (result != HasReturnvaluesIF::RETURN_FAILED) {
|
||||
sif::warning << "FileSystemHandler::performOperation: Message reception failed!" << std::endl;
|
||||
break;
|
||||
}
|
||||
Command_t command = filemsg.getCommand();
|
||||
switch (command) {
|
||||
case (GenericFileSystemMessage::CMD_CREATE_DIRECTORY): {
|
||||
break;
|
||||
}
|
||||
case (GenericFileSystemMessage::CMD_CREATE_FILE): {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This task will have a low priority and will run permanently in the background
|
||||
// so we will just run in a permanent loop here and check file system
|
||||
// messages permanently
|
||||
opCounter++;
|
||||
TaskFactory::instance()->delayTask(1000);
|
||||
}
|
||||
|
||||
// This task will have a low priority and will run permanently in the background
|
||||
// so we will just run in a permanent loop here and check file system
|
||||
// messages permanently
|
||||
opCounter++;
|
||||
TaskFactory::instance()->delayTask(1000);
|
||||
}
|
||||
|
||||
void FileSystemHandler::fileSystemCheckup() {
|
||||
SdCardManager::SdStatePair statusPair;
|
||||
sdcMan->getSdCardActiveStatus(statusPair);
|
||||
sd::SdCard preferredSdCard;
|
||||
sdcMan->getPreferredSdCard(preferredSdCard);
|
||||
if((preferredSdCard == sd::SdCard::SLOT_0) and
|
||||
(statusPair.first == sd::SdState::MOUNTED)) {
|
||||
currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT;
|
||||
SdCardManager::SdStatePair statusPair;
|
||||
sdcMan->getSdCardActiveStatus(statusPair);
|
||||
sd::SdCard preferredSdCard;
|
||||
sdcMan->getPreferredSdCard(preferredSdCard);
|
||||
if ((preferredSdCard == sd::SdCard::SLOT_0) and (statusPair.first == sd::SdState::MOUNTED)) {
|
||||
currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT;
|
||||
} else if ((preferredSdCard == sd::SdCard::SLOT_1) and
|
||||
(statusPair.second == sd::SdState::MOUNTED)) {
|
||||
currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT;
|
||||
} else {
|
||||
std::string sdString;
|
||||
if (preferredSdCard == sd::SdCard::SLOT_0) {
|
||||
sdString = "0";
|
||||
} else {
|
||||
sdString = "1";
|
||||
}
|
||||
else if((preferredSdCard == sd::SdCard::SLOT_1) and
|
||||
(statusPair.second == sd::SdState::MOUNTED)) {
|
||||
currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT;
|
||||
}
|
||||
else {
|
||||
std::string sdString;
|
||||
if(preferredSdCard == sd::SdCard::SLOT_0) {
|
||||
sdString = "0";
|
||||
}
|
||||
else {
|
||||
sdString = "1";
|
||||
}
|
||||
sif::warning << "FileSystemHandler::performOperation: "
|
||||
"Inconsistent state detected" << std::endl;
|
||||
sif::warning << "Preferred SD card is " << sdString <<
|
||||
" but does not appear to be mounted. Attempting fix.." << std::endl;
|
||||
// This function will appear to fix the inconsistent state
|
||||
ReturnValue_t result = sdcMan->sanitizeState(&statusPair, preferredSdCard);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// Oh no.
|
||||
triggerEvent(SdCardManager::SANITIZATION_FAILED, 0, 0);
|
||||
sif::error << "FileSystemHandler::fileSystemCheckup: Sanitization failed" << std::endl;
|
||||
}
|
||||
sif::warning << "FileSystemHandler::performOperation: "
|
||||
"Inconsistent state detected"
|
||||
<< std::endl;
|
||||
sif::warning << "Preferred SD card is " << sdString
|
||||
<< " but does not appear to be mounted. Attempting fix.." << std::endl;
|
||||
// This function will appear to fix the inconsistent state
|
||||
ReturnValue_t result = sdcMan->sanitizeState(&statusPair, preferredSdCard);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// Oh no.
|
||||
triggerEvent(SdCardManager::SANITIZATION_FAILED, 0, 0);
|
||||
sif::error << "FileSystemHandler::fileSystemCheckup: Sanitization failed" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueId_t FileSystemHandler::getCommandQueue() const {
|
||||
return mq->getId();
|
||||
}
|
||||
MessageQueueId_t FileSystemHandler::getCommandQueue() const { return mq->getId(); }
|
||||
|
||||
ReturnValue_t FileSystemHandler::initialize() {
|
||||
coreCtrl = ObjectManager::instance()->get<CoreController>(objects::CORE_CONTROLLER);
|
||||
if(coreCtrl == nullptr) {
|
||||
sif::error << "FileSystemHandler::initialize: Could not retrieve core controller handle" <<
|
||||
std::endl;
|
||||
}
|
||||
sdcMan = SdCardManager::instance();
|
||||
sd::SdCard preferredSdCard;
|
||||
ReturnValue_t result = sdcMan->getPreferredSdCard(preferredSdCard);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if(preferredSdCard == sd::SdCard::SLOT_0) {
|
||||
currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT;
|
||||
}
|
||||
else if(preferredSdCard == sd::SdCard::SLOT_1) {
|
||||
currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
coreCtrl = ObjectManager::instance()->get<CoreController>(objects::CORE_CONTROLLER);
|
||||
if (coreCtrl == nullptr) {
|
||||
sif::error << "FileSystemHandler::initialize: Could not retrieve core controller handle"
|
||||
<< std::endl;
|
||||
}
|
||||
sdcMan = SdCardManager::instance();
|
||||
sd::SdCard preferredSdCard;
|
||||
ReturnValue_t result = sdcMan->getPreferredSdCard(preferredSdCard);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if (preferredSdCard == sd::SdCard::SLOT_0) {
|
||||
currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT;
|
||||
} else if (preferredSdCard == sd::SdCard::SLOT_1) {
|
||||
currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FileSystemHandler::appendToFile(const char* repositoryPath,
|
||||
const char* filename, const uint8_t* data, size_t size,
|
||||
uint16_t packetNumber, FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / repositoryPath / filename;
|
||||
if(not std::filesystem::exists(path)) {
|
||||
return FILE_DOES_NOT_EXIST;
|
||||
}
|
||||
std::ofstream file(path, std::ios_base::app|std::ios_base::out);
|
||||
file.write(reinterpret_cast<const char*>(data), size);
|
||||
if(not file.good()) {
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FileSystemHandler::createFile(const char* repositoryPath,
|
||||
const char* filename, const uint8_t* data, size_t size, FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / filename;
|
||||
if(std::filesystem::exists(path)) {
|
||||
return FILE_ALREADY_EXISTS;
|
||||
}
|
||||
std::ofstream file(path);
|
||||
file.write(reinterpret_cast<const char*>(data), size);
|
||||
if(not file.good()) {
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FileSystemHandler::removeFile(const char* repositoryPath,
|
||||
const char* filename, FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / repositoryPath / filename;
|
||||
if(not std::filesystem::exists(path)) {
|
||||
return FILE_DOES_NOT_EXIST;
|
||||
}
|
||||
int result = std::remove(path.c_str());
|
||||
if(result != 0) {
|
||||
sif::warning << "FileSystemHandler::deleteFile: Failed with code " << result << std::endl;
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FileSystemHandler:: createDirectory(const char* repositoryPath, const char* dirname,
|
||||
bool createParentDirs, FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / repositoryPath / dirname;
|
||||
if(std::filesystem::exists(path)) {
|
||||
return DIRECTORY_ALREADY_EXISTS;
|
||||
}
|
||||
if(std::filesystem::create_directory(path)) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
sif::warning << "Creating directory " << path << " failed" << std::endl;
|
||||
ReturnValue_t FileSystemHandler::appendToFile(const char* repositoryPath, const char* filename,
|
||||
const uint8_t* data, size_t size,
|
||||
uint16_t packetNumber, FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / repositoryPath / filename;
|
||||
if (not std::filesystem::exists(path)) {
|
||||
return FILE_DOES_NOT_EXIST;
|
||||
}
|
||||
std::ofstream file(path, std::ios_base::app | std::ios_base::out);
|
||||
file.write(reinterpret_cast<const char*>(data), size);
|
||||
if (not file.good()) {
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FileSystemHandler::createFile(const char* repositoryPath, const char* filename,
|
||||
const uint8_t* data, size_t size,
|
||||
FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / filename;
|
||||
if (std::filesystem::exists(path)) {
|
||||
return FILE_ALREADY_EXISTS;
|
||||
}
|
||||
std::ofstream file(path);
|
||||
file.write(reinterpret_cast<const char*>(data), size);
|
||||
if (not file.good()) {
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FileSystemHandler::removeFile(const char* repositoryPath, const char* filename,
|
||||
FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / repositoryPath / filename;
|
||||
if (not std::filesystem::exists(path)) {
|
||||
return FILE_DOES_NOT_EXIST;
|
||||
}
|
||||
int result = std::remove(path.c_str());
|
||||
if (result != 0) {
|
||||
sif::warning << "FileSystemHandler::deleteFile: Failed with code " << result << std::endl;
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FileSystemHandler::createDirectory(const char* repositoryPath, const char* dirname,
|
||||
bool createParentDirs, FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / repositoryPath / dirname;
|
||||
if (std::filesystem::exists(path)) {
|
||||
return DIRECTORY_ALREADY_EXISTS;
|
||||
}
|
||||
if (std::filesystem::create_directory(path)) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
sif::warning << "Creating directory " << path << " failed" << std::endl;
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
|
||||
ReturnValue_t FileSystemHandler::removeDirectory(const char* repositoryPath, const char* dirname,
|
||||
bool deleteRecurively, FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / repositoryPath / dirname;
|
||||
if(not std::filesystem::exists(path)) {
|
||||
return DIRECTORY_DOES_NOT_EXIST;
|
||||
bool deleteRecurively, FileSystemArgsIF* args) {
|
||||
auto path = getInitPath(args) / repositoryPath / dirname;
|
||||
if (not std::filesystem::exists(path)) {
|
||||
return DIRECTORY_DOES_NOT_EXIST;
|
||||
}
|
||||
std::error_code err;
|
||||
if (not deleteRecurively) {
|
||||
if (std::filesystem::remove(path, err)) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
// Check error code. Most probably denied permissions because folder is not empty
|
||||
sif::warning << "FileSystemHandler::removeDirectory: Deleting directory failed with "
|
||||
"code "
|
||||
<< err.value() << ": " << strerror(err.value()) << std::endl;
|
||||
if (err.value() == ENOTEMPTY) {
|
||||
return DIRECTORY_NOT_EMPTY;
|
||||
} else {
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
}
|
||||
std::error_code err;
|
||||
if(not deleteRecurively) {
|
||||
if(std::filesystem::remove(path, err)) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
// Check error code. Most probably denied permissions because folder is not empty
|
||||
sif::warning << "FileSystemHandler::removeDirectory: Deleting directory failed with "
|
||||
"code " << err.value() << ": " << strerror(err.value()) << std::endl;
|
||||
if(err.value() == ENOTEMPTY) {
|
||||
return DIRECTORY_NOT_EMPTY;
|
||||
}
|
||||
else {
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
} else {
|
||||
if (std::filesystem::remove_all(path, err)) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
sif::warning << "FileSystemHandler::removeDirectory: Deleting directory failed with "
|
||||
"code "
|
||||
<< err.value() << ": " << strerror(err.value()) << std::endl;
|
||||
// Check error code
|
||||
if (err.value() == ENOTEMPTY) {
|
||||
return DIRECTORY_NOT_EMPTY;
|
||||
} else {
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(std::filesystem::remove_all(path, err)) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
sif::warning << "FileSystemHandler::removeDirectory: Deleting directory failed with "
|
||||
"code " << err.value() << ": " << strerror(err.value()) << std::endl;
|
||||
// Check error code
|
||||
if(err.value() == ENOTEMPTY) {
|
||||
return DIRECTORY_NOT_EMPTY;
|
||||
}
|
||||
else {
|
||||
return GENERIC_FILE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FileSystemHandler::renameFile(const char *repositoryPath, const char *oldFilename,
|
||||
const char *newFilename, FileSystemArgsIF *args) {
|
||||
auto basepath = getInitPath(args) / repositoryPath;
|
||||
std::filesystem::rename(basepath / oldFilename, basepath / newFilename);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t FileSystemHandler::renameFile(const char* repositoryPath, const char* oldFilename,
|
||||
const char* newFilename, FileSystemArgsIF* args) {
|
||||
auto basepath = getInitPath(args) / repositoryPath;
|
||||
std::filesystem::rename(basepath / oldFilename, basepath / newFilename);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void FileSystemHandler::parseCfg(FsCommandCfg *cfg, bool& useMountPrefix) {
|
||||
if(cfg != nullptr) {
|
||||
useMountPrefix = cfg->useMountPrefix;
|
||||
}
|
||||
void FileSystemHandler::parseCfg(FsCommandCfg* cfg, bool& useMountPrefix) {
|
||||
if (cfg != nullptr) {
|
||||
useMountPrefix = cfg->useMountPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
std::filesystem::path FileSystemHandler::getInitPath(FileSystemArgsIF* args) {
|
||||
bool useMountPrefix = true;
|
||||
parseCfg(reinterpret_cast<FsCommandCfg*>(args), useMountPrefix);
|
||||
std::string path;
|
||||
if(useMountPrefix) {
|
||||
path = currentMountPrefix;
|
||||
}
|
||||
return std::filesystem::path(path);
|
||||
bool useMountPrefix = true;
|
||||
parseCfg(reinterpret_cast<FsCommandCfg*>(args), useMountPrefix);
|
||||
std::string path;
|
||||
if (useMountPrefix) {
|
||||
path = currentMountPrefix;
|
||||
}
|
||||
return std::filesystem::path(path);
|
||||
}
|
||||
|
@ -1,71 +1,67 @@
|
||||
#ifndef BSP_Q7S_MEMORY_FILESYSTEMHANDLER_H_
|
||||
#define BSP_Q7S_MEMORY_FILESYSTEMHANDLER_H_
|
||||
|
||||
#include "SdCardManager.h"
|
||||
#include "OBSWConfig.h"
|
||||
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/memory/HasFileSystemIF.h"
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "SdCardManager.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/memory/HasFileSystemIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
|
||||
class CoreController;
|
||||
|
||||
class FileSystemHandler: public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public HasFileSystemIF {
|
||||
public:
|
||||
struct FsCommandCfg: public FileSystemArgsIF {
|
||||
// Can be used to automatically use mount prefix of active SD card.
|
||||
// Otherwise, the operator has to specify the full path to the mounted SD card as well.
|
||||
bool useMountPrefix = false;
|
||||
};
|
||||
class FileSystemHandler : public SystemObject, public ExecutableObjectIF, public HasFileSystemIF {
|
||||
public:
|
||||
struct FsCommandCfg : public FileSystemArgsIF {
|
||||
// Can be used to automatically use mount prefix of active SD card.
|
||||
// Otherwise, the operator has to specify the full path to the mounted SD card as well.
|
||||
bool useMountPrefix = false;
|
||||
};
|
||||
|
||||
FileSystemHandler(object_id_t fileSystemHandler);
|
||||
virtual~ FileSystemHandler();
|
||||
FileSystemHandler(object_id_t fileSystemHandler);
|
||||
virtual ~FileSystemHandler();
|
||||
|
||||
ReturnValue_t performOperation(uint8_t) override;
|
||||
ReturnValue_t performOperation(uint8_t) override;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
/**
|
||||
* Function to get the MessageQueueId_t of the implementing object
|
||||
* @return MessageQueueId_t of the object
|
||||
*/
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
ReturnValue_t appendToFile(const char* repositoryPath,
|
||||
const char* filename, const uint8_t* data, size_t size,
|
||||
uint16_t packetNumber, FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t createFile(const char* repositoryPath,
|
||||
const char* filename, const uint8_t* data = nullptr,
|
||||
size_t size = 0, FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t removeFile(const char* repositoryPath,
|
||||
const char* filename, FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t createDirectory(const char* repositoryPath, const char* dirname,
|
||||
bool createParentDirs, FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t removeDirectory(const char* repositoryPath, const char* dirname,
|
||||
bool deleteRecurively = false, FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t renameFile(const char* repositoryPath, const char* oldFilename,
|
||||
const char* newFilename, FileSystemArgsIF* args = nullptr) override;
|
||||
/**
|
||||
* Function to get the MessageQueueId_t of the implementing object
|
||||
* @return MessageQueueId_t of the object
|
||||
*/
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
ReturnValue_t appendToFile(const char* repositoryPath, const char* filename, const uint8_t* data,
|
||||
size_t size, uint16_t packetNumber,
|
||||
FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t createFile(const char* repositoryPath, const char* filename,
|
||||
const uint8_t* data = nullptr, size_t size = 0,
|
||||
FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t removeFile(const char* repositoryPath, const char* filename,
|
||||
FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t createDirectory(const char* repositoryPath, const char* dirname,
|
||||
bool createParentDirs, FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t removeDirectory(const char* repositoryPath, const char* dirname,
|
||||
bool deleteRecurively = false,
|
||||
FileSystemArgsIF* args = nullptr) override;
|
||||
ReturnValue_t renameFile(const char* repositoryPath, const char* oldFilename,
|
||||
const char* newFilename, FileSystemArgsIF* args = nullptr) override;
|
||||
|
||||
private:
|
||||
CoreController* coreCtrl = nullptr;
|
||||
MessageQueueIF* mq = nullptr;
|
||||
std::string currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT;
|
||||
static constexpr uint32_t FS_MAX_QUEUE_SIZE = config::OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE;
|
||||
private:
|
||||
CoreController* coreCtrl = nullptr;
|
||||
MessageQueueIF* mq = nullptr;
|
||||
std::string currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT;
|
||||
static constexpr uint32_t FS_MAX_QUEUE_SIZE = config::OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE;
|
||||
|
||||
SdCardManager* sdcMan = nullptr;
|
||||
uint8_t opCounter = 0;
|
||||
SdCardManager* sdcMan = nullptr;
|
||||
uint8_t opCounter = 0;
|
||||
|
||||
void fileSystemHandlerLoop();
|
||||
void fileSystemCheckup();
|
||||
std::filesystem::path getInitPath(FileSystemArgsIF* args);
|
||||
void parseCfg(FsCommandCfg* cfg, bool& useMountPrefix);
|
||||
void fileSystemHandlerLoop();
|
||||
void fileSystemCheckup();
|
||||
std::filesystem::path getInitPath(FileSystemArgsIF* args);
|
||||
void parseCfg(FsCommandCfg* cfg, bool& useMountPrefix);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* BSP_Q7S_MEMORY_FILESYSTEMMANAGER_H_ */
|
||||
|
@ -1,487 +1,462 @@
|
||||
#include "SdCardManager.h"
|
||||
#include "scratchApi.h"
|
||||
|
||||
#include "linux/utility/utility.h"
|
||||
|
||||
#include "fsfw/ipc/MutexFactory.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/ipc/MutexFactory.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "linux/utility/utility.h"
|
||||
#include "scratchApi.h"
|
||||
|
||||
SdCardManager* SdCardManager::factoryInstance = nullptr;
|
||||
|
||||
SdCardManager::SdCardManager(): cmdExecutor(256) {
|
||||
}
|
||||
SdCardManager::SdCardManager() : cmdExecutor(256) {}
|
||||
|
||||
SdCardManager::~SdCardManager() {
|
||||
}
|
||||
SdCardManager::~SdCardManager() {}
|
||||
|
||||
void SdCardManager::create() {
|
||||
if(factoryInstance == nullptr) {
|
||||
factoryInstance = new SdCardManager();
|
||||
}
|
||||
if (factoryInstance == nullptr) {
|
||||
factoryInstance = new SdCardManager();
|
||||
}
|
||||
}
|
||||
|
||||
SdCardManager* SdCardManager::instance() {
|
||||
SdCardManager::create();
|
||||
return SdCardManager::factoryInstance;
|
||||
SdCardManager::create();
|
||||
return SdCardManager::factoryInstance;
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCard,
|
||||
SdStatePair* statusPair) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
if(doMountSdCard) {
|
||||
if(not blocking) {
|
||||
sif::warning << "SdCardManager::switchOnSdCard: Two-step command but manager is"
|
||||
" not configured for blocking operation. "
|
||||
"Forcing blocking mode.." << std::endl;
|
||||
blocking = true;
|
||||
}
|
||||
SdStatePair* statusPair) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
if (doMountSdCard) {
|
||||
if (not blocking) {
|
||||
sif::warning << "SdCardManager::switchOnSdCard: Two-step command but manager is"
|
||||
" not configured for blocking operation. "
|
||||
"Forcing blocking mode.."
|
||||
<< std::endl;
|
||||
blocking = true;
|
||||
}
|
||||
std::unique_ptr<SdStatePair> sdStatusPtr;
|
||||
if(statusPair == nullptr) {
|
||||
sdStatusPtr = std::make_unique<SdStatePair>();
|
||||
statusPair = sdStatusPtr.get();
|
||||
result = getSdCardActiveStatus(*statusPair);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
std::unique_ptr<SdStatePair> sdStatusPtr;
|
||||
if (statusPair == nullptr) {
|
||||
sdStatusPtr = std::make_unique<SdStatePair>();
|
||||
statusPair = sdStatusPtr.get();
|
||||
result = getSdCardActiveStatus(*statusPair);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Not allowed, this function turns on one SD card
|
||||
if(sdCard == sd::SdCard::BOTH) {
|
||||
sif::warning << "SdCardManager::switchOffSdCard: API does not allow sd::SdStatus::BOTH"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
// Not allowed, this function turns on one SD card
|
||||
if (sdCard == sd::SdCard::BOTH) {
|
||||
sif::warning << "SdCardManager::switchOffSdCard: API does not allow sd::SdStatus::BOTH"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
sd::SdState currentState;
|
||||
if(sdCard == sd::SdCard::SLOT_0) {
|
||||
currentState = statusPair->first;
|
||||
}
|
||||
else if(sdCard == sd::SdCard::SLOT_1) {
|
||||
currentState = statusPair->second;
|
||||
}
|
||||
else {
|
||||
// Should not happen
|
||||
currentState = sd::SdState::OFF;
|
||||
}
|
||||
sd::SdState currentState;
|
||||
if (sdCard == sd::SdCard::SLOT_0) {
|
||||
currentState = statusPair->first;
|
||||
} else if (sdCard == sd::SdCard::SLOT_1) {
|
||||
currentState = statusPair->second;
|
||||
} else {
|
||||
// Should not happen
|
||||
currentState = sd::SdState::OFF;
|
||||
}
|
||||
|
||||
if(currentState == sd::SdState::ON) {
|
||||
if(not doMountSdCard) {
|
||||
return ALREADY_ON;
|
||||
}
|
||||
else {
|
||||
return mountSdCard(sdCard);
|
||||
}
|
||||
}
|
||||
else if(currentState == sd::SdState::MOUNTED) {
|
||||
result = ALREADY_MOUNTED;
|
||||
}
|
||||
else if(currentState == sd::SdState::OFF) {
|
||||
result = setSdCardState(sdCard, true);
|
||||
}
|
||||
else {
|
||||
result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
if (currentState == sd::SdState::ON) {
|
||||
if (not doMountSdCard) {
|
||||
return ALREADY_ON;
|
||||
} else {
|
||||
return mountSdCard(sdCard);
|
||||
}
|
||||
} else if (currentState == sd::SdState::MOUNTED) {
|
||||
result = ALREADY_MOUNTED;
|
||||
} else if (currentState == sd::SdState::OFF) {
|
||||
result = setSdCardState(sdCard, true);
|
||||
} else {
|
||||
result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
if(result != HasReturnvaluesIF::RETURN_OK or not doMountSdCard) {
|
||||
return result;
|
||||
}
|
||||
if (result != HasReturnvaluesIF::RETURN_OK or not doMountSdCard) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return mountSdCard(sdCard);
|
||||
return mountSdCard(sdCard);
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard,
|
||||
SdStatePair* statusPair) {
|
||||
std::pair<sd::SdState, sd::SdState> active;
|
||||
ReturnValue_t result = getSdCardActiveStatus(active);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
SdStatePair* statusPair) {
|
||||
std::pair<sd::SdState, sd::SdState> active;
|
||||
ReturnValue_t result = getSdCardActiveStatus(active);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if (doUnmountSdCard) {
|
||||
if (not blocking) {
|
||||
sif::warning << "SdCardManager::switchOffSdCard: Two-step command but manager is"
|
||||
" not configured for blocking operation. Forcing blocking mode.."
|
||||
<< std::endl;
|
||||
blocking = true;
|
||||
}
|
||||
if(doUnmountSdCard) {
|
||||
if(not blocking) {
|
||||
sif::warning << "SdCardManager::switchOffSdCard: Two-step command but manager is"
|
||||
" not configured for blocking operation. Forcing blocking mode.." << std::endl;
|
||||
blocking = true;
|
||||
}
|
||||
}
|
||||
// Not allowed, this function turns off one SD card
|
||||
if (sdCard == sd::SdCard::BOTH) {
|
||||
sif::warning << "SdCardManager::switchOffSdCard: API does not allow sd::SdStatus::BOTH"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if (sdCard == sd::SdCard::SLOT_0) {
|
||||
if (active.first == sd::SdState::OFF) {
|
||||
return ALREADY_OFF;
|
||||
}
|
||||
// Not allowed, this function turns off one SD card
|
||||
if(sdCard == sd::SdCard::BOTH) {
|
||||
sif::warning << "SdCardManager::switchOffSdCard: API does not allow sd::SdStatus::BOTH"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if(sdCard == sd::SdCard::SLOT_0) {
|
||||
if(active.first == sd::SdState::OFF) {
|
||||
return ALREADY_OFF;
|
||||
}
|
||||
}
|
||||
else if(sdCard == sd::SdCard::SLOT_1) {
|
||||
if(active.second == sd::SdState::OFF) {
|
||||
return ALREADY_OFF;
|
||||
}
|
||||
} else if (sdCard == sd::SdCard::SLOT_1) {
|
||||
if (active.second == sd::SdState::OFF) {
|
||||
return ALREADY_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
if(doUnmountSdCard) {
|
||||
result = unmountSdCard(sdCard);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if (doUnmountSdCard) {
|
||||
result = unmountSdCard(sdCard);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return setSdCardState(sdCard, false);
|
||||
return setSdCardState(sdCard, false);
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::setSdCardState(sd::SdCard sdCard, bool on) {
|
||||
using namespace std;
|
||||
if(cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||
return CommandExecutor::COMMAND_PENDING;
|
||||
}
|
||||
string sdstring = "";
|
||||
string statestring = "";
|
||||
if(sdCard == sd::SdCard::SLOT_0) {
|
||||
sdstring = "0";
|
||||
}
|
||||
else if(sdCard == sd::SdCard::SLOT_1) {
|
||||
sdstring = "1";
|
||||
}
|
||||
if(on) {
|
||||
currentOp = Operations::SWITCHING_ON;
|
||||
statestring = "on";
|
||||
}
|
||||
else {
|
||||
currentOp = Operations::SWITCHING_OFF;
|
||||
statestring = "off";
|
||||
}
|
||||
ostringstream command;
|
||||
command << "q7hw sd set " << sdstring << " " << statestring;
|
||||
cmdExecutor.load(command.str(), blocking, printCmdOutput);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if(blocking and result != HasReturnvaluesIF::RETURN_OK) {
|
||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::setSdCardState");
|
||||
}
|
||||
return result;
|
||||
using namespace std;
|
||||
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||
return CommandExecutor::COMMAND_PENDING;
|
||||
}
|
||||
string sdstring = "";
|
||||
string statestring = "";
|
||||
if (sdCard == sd::SdCard::SLOT_0) {
|
||||
sdstring = "0";
|
||||
} else if (sdCard == sd::SdCard::SLOT_1) {
|
||||
sdstring = "1";
|
||||
}
|
||||
if (on) {
|
||||
currentOp = Operations::SWITCHING_ON;
|
||||
statestring = "on";
|
||||
} else {
|
||||
currentOp = Operations::SWITCHING_OFF;
|
||||
statestring = "off";
|
||||
}
|
||||
ostringstream command;
|
||||
command << "q7hw sd set " << sdstring << " " << statestring;
|
||||
cmdExecutor.load(command.str(), blocking, printCmdOutput);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if (blocking and result != HasReturnvaluesIF::RETURN_OK) {
|
||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::setSdCardState");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::getSdCardActiveStatus(SdStatePair& active) {
|
||||
using namespace std;
|
||||
if(not filesystem::exists(SD_STATE_FILE)) {
|
||||
return STATUS_FILE_NEXISTS;
|
||||
}
|
||||
using namespace std;
|
||||
if (not filesystem::exists(SD_STATE_FILE)) {
|
||||
return STATUS_FILE_NEXISTS;
|
||||
}
|
||||
|
||||
// Now the file should exist in any case. Still check whether it exists.
|
||||
fstream sdStatus(SD_STATE_FILE);
|
||||
if (not sdStatus.good()) {
|
||||
return STATUS_FILE_NEXISTS;
|
||||
}
|
||||
string line;
|
||||
uint8_t idx = 0;
|
||||
sd::SdCard currentSd = sd::SdCard::SLOT_0;
|
||||
// Process status file line by line
|
||||
while (std::getline(sdStatus, line)) {
|
||||
processSdStatusLine(active, line, idx, currentSd);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
// Now the file should exist in any case. Still check whether it exists.
|
||||
fstream sdStatus(SD_STATE_FILE);
|
||||
if (not sdStatus.good()) {
|
||||
return STATUS_FILE_NEXISTS;
|
||||
}
|
||||
string line;
|
||||
uint8_t idx = 0;
|
||||
sd::SdCard currentSd = sd::SdCard::SLOT_0;
|
||||
// Process status file line by line
|
||||
while (std::getline(sdStatus, line)) {
|
||||
processSdStatusLine(active, line, idx, currentSd);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::mountSdCard(sd::SdCard sdCard) {
|
||||
using namespace std;
|
||||
if(cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||
return CommandExecutor::COMMAND_PENDING;
|
||||
}
|
||||
if(sdCard == sd::SdCard::BOTH) {
|
||||
sif::warning << "SdCardManager::mountSdCard: API does not allow sd::SdStatus::BOTH"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
string mountDev;
|
||||
string mountPoint;
|
||||
if(sdCard == sd::SdCard::SLOT_0) {
|
||||
mountDev = SD_0_DEV_NAME;
|
||||
mountPoint = SD_0_MOUNT_POINT;
|
||||
}
|
||||
else if(sdCard == sd::SdCard::SLOT_1) {
|
||||
mountDev = SD_1_DEV_NAME;
|
||||
mountPoint = SD_1_MOUNT_POINT;
|
||||
}
|
||||
if(not filesystem::exists(mountDev)) {
|
||||
sif::warning << "SdCardManager::mountSdCard: Device file does not exists. Make sure to"
|
||||
" turn on the SD card" << std::endl;
|
||||
return MOUNT_ERROR;
|
||||
}
|
||||
using namespace std;
|
||||
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||
return CommandExecutor::COMMAND_PENDING;
|
||||
}
|
||||
if (sdCard == sd::SdCard::BOTH) {
|
||||
sif::warning << "SdCardManager::mountSdCard: API does not allow sd::SdStatus::BOTH"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
string mountDev;
|
||||
string mountPoint;
|
||||
if (sdCard == sd::SdCard::SLOT_0) {
|
||||
mountDev = SD_0_DEV_NAME;
|
||||
mountPoint = SD_0_MOUNT_POINT;
|
||||
} else if (sdCard == sd::SdCard::SLOT_1) {
|
||||
mountDev = SD_1_DEV_NAME;
|
||||
mountPoint = SD_1_MOUNT_POINT;
|
||||
}
|
||||
if (not filesystem::exists(mountDev)) {
|
||||
sif::warning << "SdCardManager::mountSdCard: Device file does not exists. Make sure to"
|
||||
" turn on the SD card"
|
||||
<< std::endl;
|
||||
return MOUNT_ERROR;
|
||||
}
|
||||
|
||||
if(not blocking) {
|
||||
currentOp = Operations::MOUNTING;
|
||||
}
|
||||
string sdMountCommand = "mount " + mountDev + " " + mountPoint;
|
||||
cmdExecutor.load(sdMountCommand, blocking, printCmdOutput);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if(blocking and result != HasReturnvaluesIF::RETURN_OK) {
|
||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard");
|
||||
}
|
||||
return result;
|
||||
if (not blocking) {
|
||||
currentOp = Operations::MOUNTING;
|
||||
}
|
||||
string sdMountCommand = "mount " + mountDev + " " + mountPoint;
|
||||
cmdExecutor.load(sdMountCommand, blocking, printCmdOutput);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if (blocking and result != HasReturnvaluesIF::RETURN_OK) {
|
||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::unmountSdCard(sd::SdCard sdCard) {
|
||||
if(cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||
return CommandExecutor::COMMAND_PENDING;
|
||||
}
|
||||
using namespace std;
|
||||
if(sdCard == sd::SdCard::BOTH) {
|
||||
sif::warning << "SdCardManager::unmountSdCard: API does not allow sd::SdStatus::BOTH"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
string mountPoint;
|
||||
if(sdCard == sd::SdCard::SLOT_0) {
|
||||
mountPoint = SD_0_MOUNT_POINT;
|
||||
}
|
||||
else if(sdCard == sd::SdCard::SLOT_1) {
|
||||
mountPoint = SD_1_MOUNT_POINT;
|
||||
}
|
||||
if(not filesystem::exists(mountPoint)) {
|
||||
sif::error << "SdCardManager::unmountSdCard: Default mount point " << mountPoint <<
|
||||
"does not exist" << std::endl;
|
||||
return UNMOUNT_ERROR;
|
||||
}
|
||||
if(filesystem::is_empty(mountPoint)) {
|
||||
// The mount point will always exist, but if it is empty, that is strong hint that
|
||||
// the SD card was not mounted properly. Still proceed with operation.
|
||||
sif::warning << "SdCardManager::unmountSdCard: Mount point is empty!" << std::endl;
|
||||
}
|
||||
string sdUnmountCommand = "umount " + mountPoint;
|
||||
if(not blocking) {
|
||||
currentOp = Operations::UNMOUNTING;
|
||||
}
|
||||
cmdExecutor.load(sdUnmountCommand, blocking, printCmdOutput);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if(blocking and result != HasReturnvaluesIF::RETURN_OK) {
|
||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::unmountSdCard");
|
||||
}
|
||||
return result;
|
||||
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||
return CommandExecutor::COMMAND_PENDING;
|
||||
}
|
||||
using namespace std;
|
||||
if (sdCard == sd::SdCard::BOTH) {
|
||||
sif::warning << "SdCardManager::unmountSdCard: API does not allow sd::SdStatus::BOTH"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
string mountPoint;
|
||||
if (sdCard == sd::SdCard::SLOT_0) {
|
||||
mountPoint = SD_0_MOUNT_POINT;
|
||||
} else if (sdCard == sd::SdCard::SLOT_1) {
|
||||
mountPoint = SD_1_MOUNT_POINT;
|
||||
}
|
||||
if (not filesystem::exists(mountPoint)) {
|
||||
sif::error << "SdCardManager::unmountSdCard: Default mount point " << mountPoint
|
||||
<< "does not exist" << std::endl;
|
||||
return UNMOUNT_ERROR;
|
||||
}
|
||||
if (filesystem::is_empty(mountPoint)) {
|
||||
// The mount point will always exist, but if it is empty, that is strong hint that
|
||||
// the SD card was not mounted properly. Still proceed with operation.
|
||||
sif::warning << "SdCardManager::unmountSdCard: Mount point is empty!" << std::endl;
|
||||
}
|
||||
string sdUnmountCommand = "umount " + mountPoint;
|
||||
if (not blocking) {
|
||||
currentOp = Operations::UNMOUNTING;
|
||||
}
|
||||
cmdExecutor.load(sdUnmountCommand, blocking, printCmdOutput);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if (blocking and result != HasReturnvaluesIF::RETURN_OK) {
|
||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::unmountSdCard");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::sanitizeState(SdStatePair* statusPair, sd::SdCard prefSdCard) {
|
||||
std::unique_ptr<SdStatePair> sdStatusPtr;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
// Enforce blocking operation for now. Be careful to reset it when returning prematurely!
|
||||
bool resetNonBlockingState = false;
|
||||
if(not this->blocking) {
|
||||
blocking = true;
|
||||
resetNonBlockingState = true;
|
||||
}
|
||||
if(prefSdCard == sd::SdCard::NONE) {
|
||||
result = getPreferredSdCard(prefSdCard);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {}
|
||||
}
|
||||
if(statusPair == nullptr) {
|
||||
sdStatusPtr = std::make_unique<SdStatePair>();
|
||||
statusPair = sdStatusPtr.get();
|
||||
getSdCardActiveStatus(*statusPair);
|
||||
std::unique_ptr<SdStatePair> sdStatusPtr;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
// Enforce blocking operation for now. Be careful to reset it when returning prematurely!
|
||||
bool resetNonBlockingState = false;
|
||||
if (not this->blocking) {
|
||||
blocking = true;
|
||||
resetNonBlockingState = true;
|
||||
}
|
||||
if (prefSdCard == sd::SdCard::NONE) {
|
||||
result = getPreferredSdCard(prefSdCard);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
}
|
||||
}
|
||||
if (statusPair == nullptr) {
|
||||
sdStatusPtr = std::make_unique<SdStatePair>();
|
||||
statusPair = sdStatusPtr.get();
|
||||
getSdCardActiveStatus(*statusPair);
|
||||
}
|
||||
|
||||
if(statusPair->first == sd::SdState::ON) {
|
||||
result = mountSdCard(prefSdCard);
|
||||
}
|
||||
if (statusPair->first == sd::SdState::ON) {
|
||||
result = mountSdCard(prefSdCard);
|
||||
}
|
||||
|
||||
result = switchOnSdCard(prefSdCard, true, statusPair);
|
||||
if(resetNonBlockingState) {
|
||||
blocking = false;
|
||||
}
|
||||
return result;
|
||||
result = switchOnSdCard(prefSdCard, true, statusPair);
|
||||
if (resetNonBlockingState) {
|
||||
blocking = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SdCardManager::resetState() {
|
||||
cmdExecutor.reset();
|
||||
currentOp = Operations::IDLE;
|
||||
cmdExecutor.reset();
|
||||
currentOp = Operations::IDLE;
|
||||
}
|
||||
|
||||
void SdCardManager::processSdStatusLine(std::pair<sd::SdState, sd::SdState> &active,
|
||||
std::string& line, uint8_t& idx, sd::SdCard& currentSd) {
|
||||
using namespace std;
|
||||
istringstream iss(line);
|
||||
string word;
|
||||
bool slotLine = false;
|
||||
bool mountLine = false;
|
||||
while(iss >> word) {
|
||||
if (word == "Slot") {
|
||||
slotLine = true;
|
||||
}
|
||||
if(word == "Mounted") {
|
||||
mountLine = true;
|
||||
}
|
||||
|
||||
if(slotLine) {
|
||||
if (word == "1:") {
|
||||
currentSd = sd::SdCard::SLOT_1;
|
||||
}
|
||||
|
||||
if(word == "on") {
|
||||
if(currentSd == sd::SdCard::SLOT_0) {
|
||||
active.first = sd::SdState::ON;
|
||||
}
|
||||
else {
|
||||
active.second = sd::SdState::ON;
|
||||
}
|
||||
}
|
||||
else if (word == "off") {
|
||||
if(currentSd == sd::SdCard::SLOT_0) {
|
||||
active.first = sd::SdState::OFF;
|
||||
}
|
||||
else {
|
||||
active.second = sd::SdState::OFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mountLine) {
|
||||
if(currentSd == sd::SdCard::SLOT_0) {
|
||||
active.first = sd::SdState::MOUNTED;
|
||||
}
|
||||
else {
|
||||
active.second = sd::SdState::MOUNTED;
|
||||
}
|
||||
}
|
||||
|
||||
if(idx > 5) {
|
||||
sif::warning << "SdCardManager::sdCardActive: /tmp/sd_status.txt has more than 6 "
|
||||
"lines and might be invalid!" << std::endl;
|
||||
}
|
||||
void SdCardManager::processSdStatusLine(std::pair<sd::SdState, sd::SdState>& active,
|
||||
std::string& line, uint8_t& idx, sd::SdCard& currentSd) {
|
||||
using namespace std;
|
||||
istringstream iss(line);
|
||||
string word;
|
||||
bool slotLine = false;
|
||||
bool mountLine = false;
|
||||
while (iss >> word) {
|
||||
if (word == "Slot") {
|
||||
slotLine = true;
|
||||
}
|
||||
idx++;
|
||||
if (word == "Mounted") {
|
||||
mountLine = true;
|
||||
}
|
||||
|
||||
if (slotLine) {
|
||||
if (word == "1:") {
|
||||
currentSd = sd::SdCard::SLOT_1;
|
||||
}
|
||||
|
||||
if (word == "on") {
|
||||
if (currentSd == sd::SdCard::SLOT_0) {
|
||||
active.first = sd::SdState::ON;
|
||||
} else {
|
||||
active.second = sd::SdState::ON;
|
||||
}
|
||||
} else if (word == "off") {
|
||||
if (currentSd == sd::SdCard::SLOT_0) {
|
||||
active.first = sd::SdState::OFF;
|
||||
} else {
|
||||
active.second = sd::SdState::OFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mountLine) {
|
||||
if (currentSd == sd::SdCard::SLOT_0) {
|
||||
active.first = sd::SdState::MOUNTED;
|
||||
} else {
|
||||
active.second = sd::SdState::MOUNTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx > 5) {
|
||||
sif::warning << "SdCardManager::sdCardActive: /tmp/sd_status.txt has more than 6 "
|
||||
"lines and might be invalid!"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::getPreferredSdCard(sd::SdCard& sdCard) const {
|
||||
uint8_t prefSdCard = 0;
|
||||
ReturnValue_t result = scratch::readNumber(scratch::PREFERED_SDC_KEY, prefSdCard);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
sdCard = static_cast<sd::SdCard>(prefSdCard);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
uint8_t prefSdCard = 0;
|
||||
ReturnValue_t result = scratch::readNumber(scratch::PREFERED_SDC_KEY, prefSdCard);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
sdCard = static_cast<sd::SdCard>(prefSdCard);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::setPreferredSdCard(sd::SdCard sdCard) {
|
||||
if(sdCard == sd::SdCard::BOTH) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return scratch::writeNumber(scratch::PREFERED_SDC_KEY, static_cast<uint8_t>(sdCard));
|
||||
if (sdCard == sd::SdCard::BOTH) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return scratch::writeNumber(scratch::PREFERED_SDC_KEY, static_cast<uint8_t>(sdCard));
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::updateSdCardStateFile() {
|
||||
if(cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||
return CommandExecutor::COMMAND_PENDING;
|
||||
}
|
||||
// Use q7hw utility and pipe the command output into the state file
|
||||
std::string updateCmd = "q7hw sd info all > " + std::string(SD_STATE_FILE);
|
||||
cmdExecutor.load(updateCmd, blocking, printCmdOutput);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if(blocking and result != HasReturnvaluesIF::RETURN_OK) {
|
||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard");
|
||||
}
|
||||
return result;
|
||||
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||
return CommandExecutor::COMMAND_PENDING;
|
||||
}
|
||||
// Use q7hw utility and pipe the command output into the state file
|
||||
std::string updateCmd = "q7hw sd info all > " + std::string(SD_STATE_FILE);
|
||||
cmdExecutor.load(updateCmd, blocking, printCmdOutput);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if (blocking and result != HasReturnvaluesIF::RETURN_OK) {
|
||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string SdCardManager::getCurrentMountPrefix(sd::SdCard prefSdCard) {
|
||||
if(prefSdCard == sd::SdCard::NONE) {
|
||||
ReturnValue_t result = getPreferredSdCard(prefSdCard);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return SD_0_MOUNT_POINT;
|
||||
}
|
||||
}
|
||||
if(prefSdCard == sd::SdCard::SLOT_0) {
|
||||
return SD_0_MOUNT_POINT;
|
||||
}
|
||||
else {
|
||||
return SD_1_MOUNT_POINT;
|
||||
if (prefSdCard == sd::SdCard::NONE) {
|
||||
ReturnValue_t result = getPreferredSdCard(prefSdCard);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return SD_0_MOUNT_POINT;
|
||||
}
|
||||
}
|
||||
if (prefSdCard == sd::SdCard::SLOT_0) {
|
||||
return SD_0_MOUNT_POINT;
|
||||
} else {
|
||||
return SD_1_MOUNT_POINT;
|
||||
}
|
||||
}
|
||||
|
||||
SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations ¤tOp) {
|
||||
CommandExecutor::States state = cmdExecutor.getCurrentState();
|
||||
if(state == CommandExecutor::States::IDLE or state == CommandExecutor::States::COMMAND_LOADED) {
|
||||
return OpStatus::IDLE;
|
||||
}
|
||||
currentOp = this->currentOp;
|
||||
bool bytesRead = false;
|
||||
SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations& currentOp) {
|
||||
CommandExecutor::States state = cmdExecutor.getCurrentState();
|
||||
if (state == CommandExecutor::States::IDLE or state == CommandExecutor::States::COMMAND_LOADED) {
|
||||
return OpStatus::IDLE;
|
||||
}
|
||||
currentOp = this->currentOp;
|
||||
bool bytesRead = false;
|
||||
|
||||
#if OBSW_ENABLE_TIMERS == 1
|
||||
Timer timer;
|
||||
timer.setTimer(100);
|
||||
uint32_t remainingTimeMs = 0;
|
||||
Timer timer;
|
||||
timer.setTimer(100);
|
||||
uint32_t remainingTimeMs = 0;
|
||||
#endif
|
||||
while(true) {
|
||||
ReturnValue_t result = cmdExecutor.check(bytesRead);
|
||||
// This timer can prevent deadlocks due to missconfigurations
|
||||
while (true) {
|
||||
ReturnValue_t result = cmdExecutor.check(bytesRead);
|
||||
// This timer can prevent deadlocks due to missconfigurations
|
||||
#if OBSW_ENABLE_TIMERS == 1
|
||||
timer.getTimer(&remainingTimeMs);
|
||||
if(remainingTimeMs == 0) {
|
||||
sif::error << "SdCardManager::checkCurrentOp: Timeout!" << std::endl;
|
||||
return OpStatus::FAIL;
|
||||
}
|
||||
#endif
|
||||
switch(result) {
|
||||
case(CommandExecutor::BYTES_READ): {
|
||||
continue;
|
||||
}
|
||||
case(CommandExecutor::EXECUTION_FINISHED): {
|
||||
return OpStatus::SUCCESS;
|
||||
}
|
||||
case(HasReturnvaluesIF::RETURN_OK): {
|
||||
return OpStatus::ONGOING;
|
||||
}
|
||||
case(HasReturnvaluesIF::RETURN_FAILED): {
|
||||
return OpStatus::FAIL;
|
||||
}
|
||||
default: {
|
||||
sif::warning << "SdCardManager::checkCurrentOp: Unhandled case" << std::endl;
|
||||
}
|
||||
}
|
||||
timer.getTimer(&remainingTimeMs);
|
||||
if (remainingTimeMs == 0) {
|
||||
sif::error << "SdCardManager::checkCurrentOp: Timeout!" << std::endl;
|
||||
return OpStatus::FAIL;
|
||||
}
|
||||
#endif
|
||||
switch (result) {
|
||||
case (CommandExecutor::BYTES_READ): {
|
||||
continue;
|
||||
}
|
||||
case (CommandExecutor::EXECUTION_FINISHED): {
|
||||
return OpStatus::SUCCESS;
|
||||
}
|
||||
case (HasReturnvaluesIF::RETURN_OK): {
|
||||
return OpStatus::ONGOING;
|
||||
}
|
||||
case (HasReturnvaluesIF::RETURN_FAILED): {
|
||||
return OpStatus::FAIL;
|
||||
}
|
||||
default: {
|
||||
sif::warning << "SdCardManager::checkCurrentOp: Unhandled case" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SdCardManager::setBlocking(bool blocking) {
|
||||
this->blocking = blocking;
|
||||
}
|
||||
void SdCardManager::setBlocking(bool blocking) { this->blocking = blocking; }
|
||||
|
||||
void SdCardManager::setPrintCommandOutput(bool print) {
|
||||
this->printCmdOutput = print;
|
||||
|
||||
}
|
||||
void SdCardManager::setPrintCommandOutput(bool print) { this->printCmdOutput = print; }
|
||||
|
||||
bool SdCardManager::isSdCardMounted(sd::SdCard sdCard) {
|
||||
SdCardManager::SdStatePair active;
|
||||
ReturnValue_t result = this->getSdCardActiveStatus(active);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::debug << "SdCardManager::isSdCardMounted: Failed to get SD card active state";
|
||||
return false;
|
||||
}
|
||||
if (sdCard == sd::SLOT_0) {
|
||||
if (active.first == sd::MOUNTED) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (sdCard == sd::SLOT_1) {
|
||||
if (active.second == sd::MOUNTED) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sif::debug << "SdCardManager::isSdCardMounted: Unknown SD card specified" << std::endl;
|
||||
}
|
||||
SdCardManager::SdStatePair active;
|
||||
ReturnValue_t result = this->getSdCardActiveStatus(active);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::debug << "SdCardManager::isSdCardMounted: Failed to get SD card active state";
|
||||
return false;
|
||||
}
|
||||
if (sdCard == sd::SLOT_0) {
|
||||
if (active.first == sd::MOUNTED) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (sdCard == sd::SLOT_1) {
|
||||
if (active.second == sd::MOUNTED) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
sif::debug << "SdCardManager::isSdCardMounted: Unknown SD card specified" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,21 +1,20 @@
|
||||
#ifndef BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_
|
||||
#define BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_
|
||||
|
||||
#include "fsfw_hal/linux/CommandExecutor.h"
|
||||
#include "definitions.h"
|
||||
#include "returnvalues/classIds.h"
|
||||
#include "events/subsystemIdRanges.h"
|
||||
|
||||
#include "fsfw/events/Event.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "definitions.h"
|
||||
#include "events/subsystemIdRanges.h"
|
||||
#include "fsfw/events/Event.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw_hal/linux/CommandExecutor.h"
|
||||
#include "returnvalues/classIds.h"
|
||||
|
||||
class MutexIF;
|
||||
|
||||
@ -24,202 +23,188 @@ class MutexIF;
|
||||
* state
|
||||
*/
|
||||
class SdCardManager {
|
||||
friend class SdCardAccess;
|
||||
public:
|
||||
enum class Operations {
|
||||
SWITCHING_ON,
|
||||
SWITCHING_OFF,
|
||||
MOUNTING,
|
||||
UNMOUNTING,
|
||||
IDLE
|
||||
};
|
||||
friend class SdCardAccess;
|
||||
|
||||
enum class OpStatus {
|
||||
IDLE,
|
||||
TIMEOUT,
|
||||
ONGOING,
|
||||
SUCCESS,
|
||||
FAIL
|
||||
};
|
||||
public:
|
||||
enum class Operations { SWITCHING_ON, SWITCHING_OFF, MOUNTING, UNMOUNTING, IDLE };
|
||||
|
||||
using SdStatePair = std::pair<sd::SdState, sd::SdState>;
|
||||
enum class OpStatus { IDLE, TIMEOUT, ONGOING, SUCCESS, FAIL };
|
||||
|
||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::SD_CARD_MANAGER;
|
||||
using SdStatePair = std::pair<sd::SdState, sd::SdState>;
|
||||
|
||||
static constexpr ReturnValue_t OP_ONGOING =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 0);
|
||||
static constexpr ReturnValue_t ALREADY_ON =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 1);
|
||||
static constexpr ReturnValue_t ALREADY_MOUNTED =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 2);
|
||||
static constexpr ReturnValue_t ALREADY_OFF =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 3);
|
||||
static constexpr ReturnValue_t STATUS_FILE_NEXISTS =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 10);
|
||||
static constexpr ReturnValue_t STATUS_FILE_FORMAT_INVALID =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 11);
|
||||
static constexpr ReturnValue_t MOUNT_ERROR =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 12);
|
||||
static constexpr ReturnValue_t UNMOUNT_ERROR =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 13);
|
||||
static constexpr ReturnValue_t SYSTEM_CALL_ERROR =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 14);
|
||||
static constexpr ReturnValue_t POPEN_CALL_ERROR =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 15);
|
||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::SD_CARD_MANAGER;
|
||||
|
||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FILE_SYSTEM;
|
||||
static constexpr ReturnValue_t OP_ONGOING = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 0);
|
||||
static constexpr ReturnValue_t ALREADY_ON = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 1);
|
||||
static constexpr ReturnValue_t ALREADY_MOUNTED =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 2);
|
||||
static constexpr ReturnValue_t ALREADY_OFF = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 3);
|
||||
static constexpr ReturnValue_t STATUS_FILE_NEXISTS =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 10);
|
||||
static constexpr ReturnValue_t STATUS_FILE_FORMAT_INVALID =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 11);
|
||||
static constexpr ReturnValue_t MOUNT_ERROR = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 12);
|
||||
static constexpr ReturnValue_t UNMOUNT_ERROR =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 13);
|
||||
static constexpr ReturnValue_t SYSTEM_CALL_ERROR =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 14);
|
||||
static constexpr ReturnValue_t POPEN_CALL_ERROR =
|
||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 15);
|
||||
|
||||
static constexpr Event SANITIZATION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
|
||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FILE_SYSTEM;
|
||||
|
||||
// C++17 does not support constexpr std::string yet
|
||||
static constexpr char SD_0_DEV_NAME[] = "/dev/mmcblk0p1";
|
||||
static constexpr char SD_1_DEV_NAME[] = "/dev/mmcblk1p1";
|
||||
static constexpr char SD_0_MOUNT_POINT[] = "/mnt/sd0";
|
||||
static constexpr char SD_1_MOUNT_POINT[] = "/mnt/sd1";
|
||||
static constexpr char SD_STATE_FILE[] = "/tmp/sd_status.txt";
|
||||
static constexpr Event SANITIZATION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
|
||||
|
||||
virtual ~SdCardManager();
|
||||
// C++17 does not support constexpr std::string yet
|
||||
static constexpr char SD_0_DEV_NAME[] = "/dev/mmcblk0p1";
|
||||
static constexpr char SD_1_DEV_NAME[] = "/dev/mmcblk1p1";
|
||||
static constexpr char SD_0_MOUNT_POINT[] = "/mnt/sd0";
|
||||
static constexpr char SD_1_MOUNT_POINT[] = "/mnt/sd1";
|
||||
static constexpr char SD_STATE_FILE[] = "/tmp/sd_status.txt";
|
||||
|
||||
static void create();
|
||||
virtual ~SdCardManager();
|
||||
|
||||
/**
|
||||
* Returns the single instance of the SD card manager.
|
||||
*/
|
||||
static SdCardManager* instance();
|
||||
static void create();
|
||||
|
||||
/**
|
||||
* Set the preferred SD card which will determine which SD card will be used as the primary
|
||||
* SD card in hot redundant and cold redundant mode. This function will not switch the
|
||||
* SD cards which are currently on and mounted, this needs to be implemented by
|
||||
* an upper layer by using #switchOffSdCard , #switchOnSdCard and #updateSdCardStateFile
|
||||
* @param sdCard
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t setPreferredSdCard(sd::SdCard sdCard);
|
||||
/**
|
||||
* Returns the single instance of the SD card manager.
|
||||
*/
|
||||
static SdCardManager* instance();
|
||||
|
||||
/**
|
||||
* Get the currently configured preferred SD card
|
||||
* @param sdCard
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t getPreferredSdCard(sd::SdCard& sdCard) const;
|
||||
/**
|
||||
* Set the preferred SD card which will determine which SD card will be used as the primary
|
||||
* SD card in hot redundant and cold redundant mode. This function will not switch the
|
||||
* SD cards which are currently on and mounted, this needs to be implemented by
|
||||
* an upper layer by using #switchOffSdCard , #switchOnSdCard and #updateSdCardStateFile
|
||||
* @param sdCard
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t setPreferredSdCard(sd::SdCard sdCard);
|
||||
|
||||
/**
|
||||
* Switch on the specified SD card.
|
||||
* @param sdCard
|
||||
* @param doMountSdCard Mount the SD card after switching it on, which is necessary
|
||||
* to use it
|
||||
* @param statusPair If the status pair is already available, it can be passed here
|
||||
* @return - RETURN_OK on success, ALREADY_ON if it is already on,
|
||||
* SYSTEM_CALL_ERROR on system error
|
||||
*/
|
||||
ReturnValue_t switchOnSdCard(sd::SdCard sdCard, bool doMountSdCard = true,
|
||||
SdStatePair* statusPair = nullptr);
|
||||
/**
|
||||
* Get the currently configured preferred SD card
|
||||
* @param sdCard
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t getPreferredSdCard(sd::SdCard& sdCard) const;
|
||||
|
||||
/**
|
||||
* Switch off the specified SD card.
|
||||
* @param sdCard
|
||||
* @param doUnmountSdCard Unmount the SD card before switching the card off, which makes
|
||||
* the operation safer
|
||||
* @param statusPair If the status pair is already available, it can be passed here
|
||||
* @return - RETURN_OK on success, ALREADY_ON if it is already on,
|
||||
* SYSTEM_CALL_ERROR on system error
|
||||
*/
|
||||
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
|
||||
SdStatePair* statusPair = nullptr);
|
||||
/**
|
||||
* Switch on the specified SD card.
|
||||
* @param sdCard
|
||||
* @param doMountSdCard Mount the SD card after switching it on, which is necessary
|
||||
* to use it
|
||||
* @param statusPair If the status pair is already available, it can be passed here
|
||||
* @return - RETURN_OK on success, ALREADY_ON if it is already on,
|
||||
* SYSTEM_CALL_ERROR on system error
|
||||
*/
|
||||
ReturnValue_t switchOnSdCard(sd::SdCard sdCard, bool doMountSdCard = true,
|
||||
SdStatePair* statusPair = nullptr);
|
||||
|
||||
/**
|
||||
* Update the state file or creates one if it does not exist. You need to call this
|
||||
* function before calling #sdCardActive
|
||||
* @return
|
||||
* - RETURN_OK if the state file was updated successfully
|
||||
* - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending
|
||||
* - RETURN_FAILED: blocking command failed
|
||||
*/
|
||||
ReturnValue_t updateSdCardStateFile();
|
||||
/**
|
||||
* Switch off the specified SD card.
|
||||
* @param sdCard
|
||||
* @param doUnmountSdCard Unmount the SD card before switching the card off, which makes
|
||||
* the operation safer
|
||||
* @param statusPair If the status pair is already available, it can be passed here
|
||||
* @return - RETURN_OK on success, ALREADY_ON if it is already on,
|
||||
* SYSTEM_CALL_ERROR on system error
|
||||
*/
|
||||
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
|
||||
SdStatePair* statusPair = nullptr);
|
||||
|
||||
/**
|
||||
* Get the state of the SD cards. If the state file does not exist, this function will
|
||||
* take care of updating it. If it does not, the function will use the state file to get
|
||||
* the status of the SD cards and set the field of the provided boolean pair.
|
||||
* @param active Pair of booleans, where the first entry is the state of the first SD card
|
||||
* and the second one the state of the second SD card
|
||||
* @return - RETURN_OK if the state was read successfully
|
||||
* - STATUS_FILE_FORMAT_INVALID if there was an issue with the state file. The user
|
||||
* should call #updateSdCardStateFile again in that case
|
||||
* - STATUS_FILE_NEXISTS if the status file does not exist
|
||||
*/
|
||||
ReturnValue_t getSdCardActiveStatus(SdStatePair& active);
|
||||
/**
|
||||
* Update the state file or creates one if it does not exist. You need to call this
|
||||
* function before calling #sdCardActive
|
||||
* @return
|
||||
* - RETURN_OK if the state file was updated successfully
|
||||
* - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending
|
||||
* - RETURN_FAILED: blocking command failed
|
||||
*/
|
||||
ReturnValue_t updateSdCardStateFile();
|
||||
|
||||
/**
|
||||
* Mount the specified SD card. This is necessary to use it.
|
||||
* @param sdCard
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t mountSdCard(sd::SdCard sdCard);
|
||||
/**
|
||||
* Unmount the specified SD card. This is recommended before switching it off. The SD card
|
||||
* can't be used after it has been unmounted.
|
||||
* @param sdCard
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t unmountSdCard(sd::SdCard sdCard);
|
||||
/**
|
||||
* Get the state of the SD cards. If the state file does not exist, this function will
|
||||
* take care of updating it. If it does not, the function will use the state file to get
|
||||
* the status of the SD cards and set the field of the provided boolean pair.
|
||||
* @param active Pair of booleans, where the first entry is the state of the first SD card
|
||||
* and the second one the state of the second SD card
|
||||
* @return - RETURN_OK if the state was read successfully
|
||||
* - STATUS_FILE_FORMAT_INVALID if there was an issue with the state file. The user
|
||||
* should call #updateSdCardStateFile again in that case
|
||||
* - STATUS_FILE_NEXISTS if the status file does not exist
|
||||
*/
|
||||
ReturnValue_t getSdCardActiveStatus(SdStatePair& active);
|
||||
|
||||
/**
|
||||
* In case that there is a discrepancy between the preferred SD card and the currently
|
||||
* mounted one, this function will sanitize the state by attempting to mount the
|
||||
* currently preferred SD card. If the caller already has state information, it can be
|
||||
* passed into the function. For now, this operation will be enforced in blocking mode.
|
||||
* @param statusPair Current SD card status capture with #getSdCardActiveStatus
|
||||
* @param prefSdCard Preferred SD card captured with #getPreferredSdCard
|
||||
* @throws std::bad_alloc if one of the two arguments was a nullptr and an allocation failed
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t sanitizeState(SdStatePair* statusPair = nullptr,
|
||||
sd::SdCard prefSdCard = sd::SdCard::NONE);
|
||||
/**
|
||||
* Mount the specified SD card. This is necessary to use it.
|
||||
* @param sdCard
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t mountSdCard(sd::SdCard sdCard);
|
||||
/**
|
||||
* Unmount the specified SD card. This is recommended before switching it off. The SD card
|
||||
* can't be used after it has been unmounted.
|
||||
* @param sdCard
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t unmountSdCard(sd::SdCard sdCard);
|
||||
|
||||
/**
|
||||
* If sd::SdCard::NONE is passed as an argument, this function will get the currently
|
||||
* preferred SD card from the scratch buffer.
|
||||
* @param prefSdCardPtr
|
||||
* @return
|
||||
*/
|
||||
std::string getCurrentMountPrefix(sd::SdCard prefSdCardPtr = sd::SdCard::NONE);
|
||||
/**
|
||||
* In case that there is a discrepancy between the preferred SD card and the currently
|
||||
* mounted one, this function will sanitize the state by attempting to mount the
|
||||
* currently preferred SD card. If the caller already has state information, it can be
|
||||
* passed into the function. For now, this operation will be enforced in blocking mode.
|
||||
* @param statusPair Current SD card status capture with #getSdCardActiveStatus
|
||||
* @param prefSdCard Preferred SD card captured with #getPreferredSdCard
|
||||
* @throws std::bad_alloc if one of the two arguments was a nullptr and an allocation failed
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t sanitizeState(SdStatePair* statusPair = nullptr,
|
||||
sd::SdCard prefSdCard = sd::SdCard::NONE);
|
||||
|
||||
OpStatus checkCurrentOp(Operations& currentOp);
|
||||
/**
|
||||
* If sd::SdCard::NONE is passed as an argument, this function will get the currently
|
||||
* preferred SD card from the scratch buffer.
|
||||
* @param prefSdCardPtr
|
||||
* @return
|
||||
*/
|
||||
std::string getCurrentMountPrefix(sd::SdCard prefSdCardPtr = sd::SdCard::NONE);
|
||||
|
||||
/**
|
||||
* If there are issues with the state machine, it can be reset with this function
|
||||
*/
|
||||
void resetState();
|
||||
OpStatus checkCurrentOp(Operations& currentOp);
|
||||
|
||||
void setBlocking(bool blocking);
|
||||
void setPrintCommandOutput(bool print);
|
||||
/**
|
||||
* If there are issues with the state machine, it can be reset with this function
|
||||
*/
|
||||
void resetState();
|
||||
|
||||
/**
|
||||
* @brief Checks if an SD card is mounted
|
||||
*
|
||||
* @param sdCard The SD crad to check
|
||||
*
|
||||
* @return true if mounted, otherwise false
|
||||
*/
|
||||
bool isSdCardMounted(sd::SdCard sdCard);
|
||||
private:
|
||||
CommandExecutor cmdExecutor;
|
||||
Operations currentOp = Operations::IDLE;
|
||||
bool blocking = false;
|
||||
bool printCmdOutput = true;
|
||||
void setBlocking(bool blocking);
|
||||
void setPrintCommandOutput(bool print);
|
||||
|
||||
SdCardManager();
|
||||
/**
|
||||
* @brief Checks if an SD card is mounted
|
||||
*
|
||||
* @param sdCard The SD crad to check
|
||||
*
|
||||
* @return true if mounted, otherwise false
|
||||
*/
|
||||
bool isSdCardMounted(sd::SdCard sdCard);
|
||||
|
||||
ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on);
|
||||
private:
|
||||
CommandExecutor cmdExecutor;
|
||||
Operations currentOp = Operations::IDLE;
|
||||
bool blocking = false;
|
||||
bool printCmdOutput = true;
|
||||
|
||||
void processSdStatusLine(SdStatePair& active, std::string& line, uint8_t& idx,
|
||||
sd::SdCard& currentSd);
|
||||
SdCardManager();
|
||||
|
||||
std::string currentPrefix;
|
||||
ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on);
|
||||
|
||||
static SdCardManager* factoryInstance;
|
||||
void processSdStatusLine(SdStatePair& active, std::string& line, uint8_t& idx,
|
||||
sd::SdCard& currentSd);
|
||||
|
||||
std::string currentPrefix;
|
||||
|
||||
static SdCardManager* factoryInstance;
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_ */
|
||||
|
@ -5,22 +5,15 @@
|
||||
|
||||
namespace sd {
|
||||
|
||||
enum SdState: uint8_t {
|
||||
OFF = 0,
|
||||
ON = 1,
|
||||
// A mounted SD card is on as well
|
||||
MOUNTED = 2
|
||||
enum SdState : uint8_t {
|
||||
OFF = 0,
|
||||
ON = 1,
|
||||
// A mounted SD card is on as well
|
||||
MOUNTED = 2
|
||||
};
|
||||
|
||||
enum SdCard: uint8_t {
|
||||
SLOT_0 = 0,
|
||||
SLOT_1 = 1,
|
||||
BOTH,
|
||||
NONE
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
enum SdCard : uint8_t { SLOT_0 = 0, SLOT_1 = 1, BOTH, NONE };
|
||||
|
||||
} // namespace sd
|
||||
|
||||
#endif /* BSP_Q7S_MEMORY_DEFINITIONS_H_ */
|
||||
|
@ -1,49 +1,50 @@
|
||||
#include "scratchApi.h"
|
||||
|
||||
ReturnValue_t scratch::writeString(std::string name, std::string string) {
|
||||
std::ostringstream oss;
|
||||
oss << "xsc_scratch write " << name << " \"" << string << "\"";
|
||||
int result = std::system(oss.str().c_str());
|
||||
if(result != 0) {
|
||||
utility::handleSystemError(result, "scratch::writeString");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
std::ostringstream oss;
|
||||
oss << "xsc_scratch write " << name << " \"" << string << "\"";
|
||||
int result = std::system(oss.str().c_str());
|
||||
if (result != 0) {
|
||||
utility::handleSystemError(result, "scratch::writeString");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t scratch::readString(std::string key, std::string &string) {
|
||||
std::ifstream file;
|
||||
std::string filename;
|
||||
ReturnValue_t result = readToFile(key, file, filename);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
std::ifstream file;
|
||||
std::string filename;
|
||||
ReturnValue_t result = readToFile(key, file, filename);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
if (not std::getline(file, line)) {
|
||||
std::remove(filename.c_str());
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
std::string line;
|
||||
if (not std::getline(file, line)) {
|
||||
std::remove(filename.c_str());
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
size_t pos = line.find("=");
|
||||
if(pos == std::string::npos) {
|
||||
sif::warning << "scratch::readNumber: Output file format invalid, "
|
||||
"no \"=\" found" << std::endl;
|
||||
// Could not find value
|
||||
std::remove(filename.c_str());
|
||||
return KEY_NOT_FOUND;
|
||||
}
|
||||
string = line.substr(pos + 1);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
size_t pos = line.find("=");
|
||||
if (pos == std::string::npos) {
|
||||
sif::warning << "scratch::readNumber: Output file format invalid, "
|
||||
"no \"=\" found"
|
||||
<< std::endl;
|
||||
// Could not find value
|
||||
std::remove(filename.c_str());
|
||||
return KEY_NOT_FOUND;
|
||||
}
|
||||
string = line.substr(pos + 1);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t scratch::clearValue(std::string key) {
|
||||
std::ostringstream oss;
|
||||
oss << "xsc_scratch clear " << key;
|
||||
int result = std::system(oss.str().c_str());
|
||||
if(result != 0) {
|
||||
utility::handleSystemError(result, "scratch::clearValue");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
std::ostringstream oss;
|
||||
oss << "xsc_scratch clear " << key;
|
||||
int result = std::system(oss.str().c_str());
|
||||
if (result != 0) {
|
||||
utility::handleSystemError(result, "scratch::clearValue");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
#ifndef BSP_Q7S_MEMORY_SCRATCHAPI_H_
|
||||
#define BSP_Q7S_MEMORY_SCRATCHAPI_H_
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "linux/utility/utility.h"
|
||||
#include "returnvalues/classIds.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <cstdlib>
|
||||
|
||||
/**
|
||||
* @brief API for the scratch buffer
|
||||
*/
|
||||
@ -48,7 +48,7 @@ ReturnValue_t readString(std::string key, std::string& string);
|
||||
* @param num Number. Template allows to set signed, unsigned and floating point numbers
|
||||
* @return
|
||||
*/
|
||||
template<typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
template <typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
inline ReturnValue_t writeNumber(std::string key, T num) noexcept;
|
||||
|
||||
/**
|
||||
@ -59,90 +59,88 @@ inline ReturnValue_t writeNumber(std::string key, T num) noexcept;
|
||||
* @param num
|
||||
* @return
|
||||
*/
|
||||
template<typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
template <typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
inline ReturnValue_t readNumber(std::string key, T& num) noexcept;
|
||||
|
||||
|
||||
// Anonymous namespace
|
||||
namespace {
|
||||
|
||||
static uint8_t counter = 0;
|
||||
|
||||
ReturnValue_t readToFile(std::string name, std::ifstream& file, std::string& filename) {
|
||||
using namespace std;
|
||||
filename = "/tmp/sro" + std::to_string(counter++);
|
||||
ostringstream oss;
|
||||
oss << "xsc_scratch read " << name << " > " << filename;
|
||||
using namespace std;
|
||||
filename = "/tmp/sro" + std::to_string(counter++);
|
||||
ostringstream oss;
|
||||
oss << "xsc_scratch read " << name << " > " << filename;
|
||||
|
||||
int result = std::system(oss.str().c_str());
|
||||
if(result != 0) {
|
||||
if(result == 256) {
|
||||
sif::warning << "scratch::readNumber: Key " << name << " does not exist" << std::endl;
|
||||
// Could not find value
|
||||
std::remove(filename.c_str());
|
||||
return KEY_NOT_FOUND;
|
||||
}
|
||||
else {
|
||||
utility::handleSystemError(result, "scratch::readNumber");
|
||||
std::remove(filename.c_str());
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
int result = std::system(oss.str().c_str());
|
||||
if (result != 0) {
|
||||
if (result == 256) {
|
||||
sif::warning << "scratch::readNumber: Key " << name << " does not exist" << std::endl;
|
||||
// Could not find value
|
||||
std::remove(filename.c_str());
|
||||
return KEY_NOT_FOUND;
|
||||
} else {
|
||||
utility::handleSystemError(result, "scratch::readNumber");
|
||||
std::remove(filename.c_str());
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
file.open(filename);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
file.open(filename);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
} // End of anonymous namespace
|
||||
} // End of anonymous namespace
|
||||
|
||||
template<typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
template <typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
inline ReturnValue_t writeNumber(std::string key, T num) noexcept {
|
||||
std::ostringstream oss;
|
||||
oss << "xsc_scratch write " << key << " " << std::to_string(num);
|
||||
int result = std::system(oss.str().c_str());
|
||||
if(result != 0) {
|
||||
utility::handleSystemError(result, "scratch::writeNumber");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
std::ostringstream oss;
|
||||
oss << "xsc_scratch write " << key << " " << std::to_string(num);
|
||||
int result = std::system(oss.str().c_str());
|
||||
if (result != 0) {
|
||||
utility::handleSystemError(result, "scratch::writeNumber");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
template<typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
template <typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
inline ReturnValue_t readNumber(std::string key, T& num) noexcept {
|
||||
using namespace std;
|
||||
ifstream file;
|
||||
std::string filename;
|
||||
ReturnValue_t result = readToFile(key, file, filename);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
std::remove(filename.c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
string line;
|
||||
if (not std::getline(file, line)) {
|
||||
std::remove(filename.c_str());
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
size_t pos = line.find("=");
|
||||
if(pos == string::npos) {
|
||||
sif::warning << "scratch::readNumber: Output file format invalid, "
|
||||
"no \"=\" found" << std::endl;
|
||||
// Could not find value
|
||||
std::remove(filename.c_str());
|
||||
return KEY_NOT_FOUND;
|
||||
}
|
||||
std::string valueAsString = line.substr(pos + 1);
|
||||
try {
|
||||
num = std::stoi(valueAsString);
|
||||
}
|
||||
catch(std::invalid_argument& e) {
|
||||
sif::warning << "scratch::readNumber: stoi call failed with " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
ifstream file;
|
||||
std::string filename;
|
||||
ReturnValue_t result = readToFile(key, file, filename);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
std::remove(filename.c_str());
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
string line;
|
||||
if (not std::getline(file, line)) {
|
||||
std::remove(filename.c_str());
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
size_t pos = line.find("=");
|
||||
if (pos == string::npos) {
|
||||
sif::warning << "scratch::readNumber: Output file format invalid, "
|
||||
"no \"=\" found"
|
||||
<< std::endl;
|
||||
// Could not find value
|
||||
std::remove(filename.c_str());
|
||||
return KEY_NOT_FOUND;
|
||||
}
|
||||
std::string valueAsString = line.substr(pos + 1);
|
||||
try {
|
||||
num = std::stoi(valueAsString);
|
||||
} catch (std::invalid_argument& e) {
|
||||
sif::warning << "scratch::readNumber: stoi call failed with " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
std::remove(filename.c_str());
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace scratch
|
||||
|
||||
#endif /* BSP_Q7S_MEMORY_SCRATCHAPI_H_ */
|
||||
|
Reference in New Issue
Block a user