fprime/Svc/BufferLogger/BufferLoggerFile.cpp
M Starch 2dcd21902d
Testing with configured fixed-size types (#3409)
* Testing with configured fixed-size types

* Linux fixes

* Final settings

* Removing FwNativeIntType
2025-03-28 11:11:13 -07:00

272 lines
7.3 KiB
C++

// ======================================================================
// \title BufferLoggerFile.cpp
// \author bocchino, dinkel, mereweth
// \brief Implementation for Svc::BufferLogger::BufferLoggerFile
//
// \copyright
// Copyright (C) 2015-2017 California Institute of Technology.
// ALL RIGHTS RESERVED. United States Government Sponsorship
// acknowledged.
//
// ======================================================================
#include "Svc/BufferLogger/BufferLogger.hpp"
#include "Os/ValidateFile.hpp"
#include "Os/ValidatedFile.hpp"
namespace Svc {
// ----------------------------------------------------------------------
// Constructors and destructors
// ----------------------------------------------------------------------
BufferLogger::File ::
File(
BufferLogger& bufferLogger
) :
m_bufferLogger(bufferLogger),
m_prefix(""),
m_suffix(""),
m_baseName(""),
m_fileCounter(0),
m_maxSize(0),
m_sizeOfSize(0),
m_mode(Mode::CLOSED),
m_bytesWritten(0)
{
}
BufferLogger::File ::
~File()
{
this->close();
}
// ----------------------------------------------------------------------
// Public functions
// ----------------------------------------------------------------------
void BufferLogger::File ::
init(
const char *const logFilePrefix,
const char *const logFileSuffix,
const FwSizeType maxFileSize,
const U8 sizeOfSize
)
{
//NOTE(mereweth) - only call this before opening the file
FW_ASSERT(this->m_mode == File::Mode::CLOSED);
this->m_prefix = logFilePrefix;
this->m_suffix = logFileSuffix;
this->m_maxSize = maxFileSize;
this->m_sizeOfSize = sizeOfSize;
FW_ASSERT(sizeOfSize <= sizeof(FwSizeType), static_cast<FwAssertArgType>(sizeOfSize));
FW_ASSERT(m_maxSize > sizeOfSize, static_cast<FwAssertArgType>(m_maxSize));
}
void BufferLogger::File ::
setBaseName(
const Fw::StringBase& baseName
)
{
if (this->m_mode == File::Mode::OPEN) {
this->closeAndEmitEvent();
}
this->m_baseName = baseName;
this->m_fileCounter = 0;
this->open();
}
void BufferLogger::File ::
logBuffer(
const U8 *const data,
const FwSizeType size
)
{
// Close the file if it will be too big
if (this->m_mode == File::Mode::OPEN) {
const FwSizeType projectedByteCount =
this->m_bytesWritten + this->m_sizeOfSize + size;
if (projectedByteCount > this->m_maxSize) {
this->closeAndEmitEvent();
}
}
// Open a file if necessary
if (this->m_mode == File::Mode::CLOSED) {
this->open();
}
// Write to the file if it is open
if (this->m_mode == File::Mode::OPEN) {
(void) this->writeBuffer(data, size);
}
}
void BufferLogger::File ::
closeAndEmitEvent()
{
if (this->m_mode == File::Mode::OPEN) {
this->close();
Fw::LogStringArg logStringArg(this->m_name.toChar());
this->m_bufferLogger.log_DIAGNOSTIC_BL_LogFileClosed(logStringArg);
}
}
// ----------------------------------------------------------------------
// Private functions
// ----------------------------------------------------------------------
void BufferLogger::File ::
open()
{
FW_ASSERT(this->m_mode == File::Mode::CLOSED);
// NOTE(mereweth) - check that file path has been set and that initLog has been called
if ((this->m_baseName.toChar()[0] == '\0') ||
(this->m_sizeOfSize > sizeof(FwSizeType)) ||
(this->m_maxSize <= this->m_sizeOfSize)) {
this->m_bufferLogger.log_WARNING_HI_BL_NoLogFileOpenInitError();
return;
}
if (this->m_fileCounter == 0) {
this->m_name.format(
"%s%s%s",
this->m_prefix.toChar(),
this->m_baseName.toChar(),
this->m_suffix.toChar()
);
}
else {
this->m_name.format(
"%s%s%" PRI_FwSizeType "%s",
this->m_prefix.toChar(),
this->m_baseName.toChar(),
this->m_fileCounter,
this->m_suffix.toChar()
);
}
const Os::File::Status status = this->m_osFile.open(
this->m_name.toChar(),
Os::File::OPEN_WRITE
);
if (status == Os::File::OP_OK) {
this->m_fileCounter++;
// Reset bytes written
this->m_bytesWritten = 0;
// Set mode
this->m_mode = File::Mode::OPEN;
}
else {
Fw::LogStringArg string(this->m_name.toChar());
this->m_bufferLogger.log_WARNING_HI_BL_LogFileOpenError(status, string);
}
}
bool BufferLogger::File ::
writeBuffer(
const U8 *const data,
const FwSizeType size
)
{
bool status = this->writeSize(size);
if (status) {
status = this->writeBytes(data, size);
}
return status;
}
bool BufferLogger::File ::
writeSize(const FwSizeType size)
{
FW_ASSERT(this->m_sizeOfSize <= sizeof(FwSizeType));
U8 sizeBuffer[sizeof(FwSizeType)];
FwSizeType sizeRegister = size;
for (U8 i = 0; i < this->m_sizeOfSize; ++i) {
sizeBuffer[this->m_sizeOfSize - i - 1] = sizeRegister & 0xFF;
sizeRegister >>= 8;
}
const bool status = this->writeBytes(
sizeBuffer,
this->m_sizeOfSize
);
return status;
}
bool BufferLogger::File ::
writeBytes(
const void *const data,
const FwSizeType length
)
{
FW_ASSERT((length > 0) and (length <= std::numeric_limits<FwSignedSizeType>::max()), static_cast<FwAssertArgType>(length));
FwSignedSizeType size = static_cast<FwSignedSizeType>(length);
const Os::File::Status fileStatus = this->m_osFile.write(reinterpret_cast<const U8*>(data), size);
bool status;
if (fileStatus == Os::File::OP_OK && static_cast<FwSizeType>(size) == length) {
this->m_bytesWritten += length;
status = true;
}
else {
Fw::LogStringArg string(this->m_name.toChar());
this->m_bufferLogger.log_WARNING_HI_BL_LogFileWriteError(fileStatus, static_cast<U32>(size), static_cast<U32>(length), string);
status = false;
}
return status;
}
void BufferLogger::File ::
writeHashFile()
{
Os::ValidatedFile validatedFile(this->m_name.toChar());
const Os::ValidateFile::Status status =
validatedFile.createHashFile();
if (status != Os::ValidateFile::VALIDATION_OK) {
const Fw::StringBase &hashFileName = validatedFile.getHashFileName();
Fw::LogStringArg logStringArg(hashFileName.toChar());
this->m_bufferLogger.log_WARNING_HI_BL_LogFileValidationError(
logStringArg,
status
);
}
}
bool BufferLogger::File ::
flush()
{
return true;
// NOTE(if your fprime uses buffered file I/O, re-enable this)
/*bool status = true;
if(this->mode == File::Mode::OPEN)
{
const Os::File::Status fileStatus = this->osFile.flush();
if(fileStatus == Os::File::OP_OK)
{
status = true;
}
else
{
status = false;
}
}
return status;*/
}
void BufferLogger::File ::
close()
{
if (this->m_mode == File::Mode::OPEN) {
// Close file
this->m_osFile.close();
// Write out the hash file to disk
this->writeHashFile();
// Update mode
this->m_mode = File::Mode::CLOSED;
}
}
}