mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-05 07:28:29 -04:00
ccb583d092
add support for log time to block logger refactor rotation into backed. Don't start logs when erasing correct log start logic separate read and write points so that requesting log information does not corrupt the current log when starting a new log stop logging first clear the write buffer when starting a new log insert utc time when requesting info for the current log stop logging and request formats again when starting a new log cope with erase happening while we are logging keep pushing out startup messages even when format messages are done don't log to the gcs in the io thread don't start new logs in the io thread don't validate logs while erasing flush logs when stopping logging account for page header when calculating logs sizes don't return data when asked for more data than in the log optimize locking and use separate semaphore to mediate ring buffer access stop logging when the chip is full and send a notification calculate logs sizes correctly even when they wrap read log data correctly even when it wraps add stats support to block logger reset dropped when starting a new log fail logging when the chip is full refactor critical bufferspace checks increase messagewriter budget to 250us and to 300us for FMT
138 lines
4.1 KiB
C++
138 lines
4.1 KiB
C++
/*
|
|
AP_Logger logging - file oriented variant
|
|
|
|
This uses posix file IO to create log files called logNN.dat in the
|
|
given directory
|
|
*/
|
|
#pragma once
|
|
|
|
#include <AP_Filesystem/AP_Filesystem.h>
|
|
|
|
#if HAVE_FILESYSTEM_SUPPORT
|
|
|
|
#include <AP_HAL/utility/RingBuffer.h>
|
|
#include "AP_Logger_Backend.h"
|
|
|
|
class AP_Logger_File : public AP_Logger_Backend
|
|
{
|
|
public:
|
|
// constructor
|
|
AP_Logger_File(AP_Logger &front,
|
|
LoggerMessageWriter_DFLogStart *,
|
|
const char *log_directory);
|
|
|
|
// initialisation
|
|
void Init() override;
|
|
bool CardInserted(void) const override;
|
|
|
|
// erase handling
|
|
void EraseAll() override;
|
|
|
|
// possibly time-consuming preparation handling:
|
|
void Prep() override;
|
|
|
|
/* Write a block of data at current offset */
|
|
bool _WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical) override;
|
|
uint32_t bufferspace_available() override;
|
|
|
|
// high level interface
|
|
uint16_t find_last_log() override;
|
|
void get_log_boundaries(uint16_t log_num, uint32_t & start_page, uint32_t & end_page) override;
|
|
void get_log_info(uint16_t log_num, uint32_t &size, uint32_t &time_utc) override;
|
|
int16_t get_log_data(uint16_t log_num, uint16_t page, uint32_t offset, uint16_t len, uint8_t *data) override;
|
|
uint16_t get_num_logs() override;
|
|
void start_new_log(void) override;
|
|
uint16_t find_oldest_log() override;
|
|
|
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX
|
|
void flush(void) override;
|
|
#endif
|
|
void periodic_1Hz() override;
|
|
void periodic_fullrate() override;
|
|
|
|
// this method is used when reporting system status over mavlink
|
|
bool logging_failed() const override;
|
|
|
|
bool logging_started(void) const override { return _write_fd != -1; }
|
|
|
|
protected:
|
|
|
|
bool WritesOK() const override;
|
|
bool StartNewLogOK() const override;
|
|
|
|
private:
|
|
int _write_fd;
|
|
char *_write_filename;
|
|
uint32_t _last_write_ms;
|
|
#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
|
bool _need_rtc_update;
|
|
#endif
|
|
|
|
int _read_fd;
|
|
uint16_t _read_fd_log_num;
|
|
uint32_t _read_offset;
|
|
uint32_t _write_offset;
|
|
volatile bool _open_error;
|
|
const char *_log_directory;
|
|
bool _last_write_failed;
|
|
|
|
uint32_t _io_timer_heartbeat;
|
|
bool io_thread_alive() const;
|
|
uint8_t io_thread_warning_decimation_counter;
|
|
|
|
// possibly time-consuming preparations handling
|
|
void Prep_MinSpace();
|
|
int64_t disk_space_avail();
|
|
int64_t disk_space();
|
|
|
|
void ensure_log_directory_exists();
|
|
bool NeedPrep();
|
|
|
|
bool file_exists(const char *filename) const;
|
|
bool log_exists(const uint16_t lognum) const;
|
|
|
|
// write buffer
|
|
ByteBuffer _writebuf;
|
|
const uint16_t _writebuf_chunk;
|
|
uint32_t _last_write_time;
|
|
|
|
/* construct a file name given a log number. Caller must free. */
|
|
char *_log_file_name(const uint16_t log_num) const;
|
|
char *_log_file_name_long(const uint16_t log_num) const;
|
|
char *_log_file_name_short(const uint16_t log_num) const;
|
|
char *_lastlog_file_name() const;
|
|
uint32_t _get_log_size(const uint16_t log_num);
|
|
uint32_t _get_log_time(const uint16_t log_num);
|
|
|
|
void stop_logging(void) override;
|
|
|
|
void _io_timer(void);
|
|
|
|
uint32_t last_messagewrite_message_sent;
|
|
|
|
// free-space checks; filling up SD cards under NuttX leads to
|
|
// corrupt filesystems which cause loss of data, failure to gather
|
|
// data and failures-to-boot.
|
|
uint32_t _free_space_last_check_time; // milliseconds
|
|
const uint32_t _free_space_check_interval = 1000UL; // milliseconds
|
|
const uint32_t _free_space_min_avail = 8388608; // bytes
|
|
|
|
// semaphore mediates access to the ringbuffer
|
|
HAL_Semaphore semaphore;
|
|
// write_fd_semaphore mediates access to write_fd so the frontend
|
|
// can open/close files without causing the backend to write to a
|
|
// bad fd
|
|
HAL_Semaphore write_fd_semaphore;
|
|
|
|
// performance counters
|
|
AP_HAL::Util::perf_counter_t _perf_write;
|
|
AP_HAL::Util::perf_counter_t _perf_fsync;
|
|
AP_HAL::Util::perf_counter_t _perf_errors;
|
|
AP_HAL::Util::perf_counter_t _perf_overruns;
|
|
|
|
const char *last_io_operation = "";
|
|
};
|
|
|
|
#endif // HAVE_FILESYSTEM_SUPPORT
|
|
|