ardupilot/libraries/AP_Logger/AP_Logger_File.h
Andy Piper ccb583d092 AP_Logger: make block logger conform to mavlink expectations of numbering
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
2020-09-05 10:20:39 +10:00

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