applied formatting
Some checks failed
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit

This commit is contained in:
2022-01-17 15:58:27 +01:00
parent 975b3cd294
commit 77c45c0de9
206 changed files with 28883 additions and 30263 deletions

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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 &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;
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;
}

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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_ */