eive-obsw/bsp_q7s/memory/FileSystemHandler.cpp
2021-07-12 17:50:01 +02:00

185 lines
6.5 KiB
C++

#include "FileSystemHandler.h"
#include "fsfw/tasks/TaskFactory.h"
#include "fsfw/memory/GenericFileSystemMessage.h"
#include "fsfw/ipc/QueueFactory.h"
#include <filesystem>
FileSystemHandler::FileSystemHandler(object_id_t fileSystemHandler):
SystemObject(fileSystemHandler) {
mq = QueueFactory::instance()->createMessageQueue(FS_MAX_QUEUE_SIZE);
}
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;
// TODO: If we trigger an event, it might not get sent because were restarting
// Set up an error file or a special flag in the scratch buffer.
// TODO: CoreController: Implement function to restart OBC
}
}
}
void FileSystemHandler::fileSystemHandlerLoop() {
CommandMessage filemsg;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
while(true) {
if(opCounter % 5 == 0) {
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++;
}
// 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
TaskFactory::instance()->delayTask(1000);
}
void FileSystemHandler::fileSystemCheckup() {
SdCardManager::SdStatusPair statusPair;
sdcMan->getSdCardActiveStatus(statusPair);
sd::SdCard preferredSdCard;
sdcMan->getPreferredSdCard(preferredSdCard);
if((preferredSdCard == sd::SdCard::SLOT_0) and
(statusPair.first == sd::SdStatus::MOUNTED)) {
currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT;
}
if((preferredSdCard == sd::SdCard::SLOT_1) and
(statusPair.second == sd::SdStatus::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. 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(&preferredSdCard, &statusPair);
if(result != HasReturnvaluesIF::RETURN_OK) {
// Oh no.
// TODO: Trigger medium severity event
sif::error << "Fix failed" << std::endl;
}
}
}
MessageQueueId_t FileSystemHandler::getCommandQueue() const {
return mq->getId();
}
ReturnValue_t FileSystemHandler::initialize() {
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, void *args) {
// A double slash between repo and filename should not be an issue, so add it in any case
std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" +
std::string(filename);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t FileSystemHandler::createFile(const char *repositoryPath, const char *filename,
const uint8_t *data, size_t size, void *args) {
// A double slash between repo and filename should not be an issue, so add it in any case
std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" +
std::string(filename);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t FileSystemHandler::deleteFile(const char *repositoryPath, const char *filename,
void *args) {
// A double slash between repo and filename should not be an issue, so add it in any case
std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" +
std::string(filename);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t FileSystemHandler::createDirectory(const char *repositoryPath, void *args) {
std::string fullPath = currentMountPrefix + std::string(repositoryPath);
if(std::filesystem::exists(fullPath)) {
return DIRECTORY_ALREADY_EXISTS;
}
if(std::filesystem::create_directory(fullPath)) {
return HasReturnvaluesIF::RETURN_OK;
}
sif::warning << "Creating directory " << fullPath << " failed" << std::endl;
return GENERIC_FILE_ERROR;
}
ReturnValue_t FileSystemHandler::removeDirectory(const char *repositoryPath,
bool deleteRecurively, void *args) {
std::string fullPath = currentMountPrefix + std::string(repositoryPath);
if(not std::filesystem::exists(fullPath)) {
return DIRECTORY_DOES_NOT_EXIST;
}
std::error_code err;
if(not deleteRecurively) {
if(std::filesystem::remove(fullPath, err)) {
return HasReturnvaluesIF::RETURN_OK;
}
else {
// Check error code. Most probably denied permissions because folder is not empty
}
}
else {
if(std::filesystem::remove_all(fullPath, err)) {
return HasReturnvaluesIF::RETURN_OK;
}
else {
// Check error code
}
}
return HasReturnvaluesIF::RETURN_OK;
}