2013-02-28 16:17:58 -04:00
|
|
|
/*
|
2019-01-18 00:23:42 -04:00
|
|
|
AP_Logger logging - file oriented variant
|
2013-02-28 16:17:58 -04:00
|
|
|
|
|
|
|
This uses posix file IO to create log files called logNN.dat in the
|
|
|
|
given directory
|
|
|
|
*/
|
2016-02-17 21:25:53 -04:00
|
|
|
#pragma once
|
2013-02-28 16:17:58 -04:00
|
|
|
|
2019-08-01 02:14:22 -03:00
|
|
|
#include <AP_Filesystem/AP_Filesystem.h>
|
|
|
|
|
2016-07-29 21:52:21 -03:00
|
|
|
#include <AP_HAL/utility/RingBuffer.h>
|
2019-01-18 00:23:42 -04:00
|
|
|
#include "AP_Logger_Backend.h"
|
2015-06-25 10:53:20 -03:00
|
|
|
|
2021-01-06 22:04:09 -04:00
|
|
|
#if HAL_LOGGING_FILESYSTEM_ENABLED
|
|
|
|
|
2021-01-06 06:44:50 -04:00
|
|
|
#ifndef HAL_LOGGER_WRITE_CHUNK_SIZE
|
|
|
|
#define HAL_LOGGER_WRITE_CHUNK_SIZE 4096
|
|
|
|
#endif
|
|
|
|
|
2019-01-18 00:23:42 -04:00
|
|
|
class AP_Logger_File : public AP_Logger_Backend
|
2013-02-28 16:17:58 -04:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
// constructor
|
2019-01-18 00:23:42 -04:00
|
|
|
AP_Logger_File(AP_Logger &front,
|
2021-11-02 22:34:52 -03:00
|
|
|
LoggerMessageWriter_DFLogStart *);
|
|
|
|
|
|
|
|
static AP_Logger_Backend *probe(AP_Logger &front,
|
|
|
|
LoggerMessageWriter_DFLogStart *ls) {
|
|
|
|
return new AP_Logger_File(front, ls);
|
|
|
|
}
|
2013-02-28 16:17:58 -04:00
|
|
|
|
|
|
|
// initialisation
|
2015-11-09 18:14:22 -04:00
|
|
|
void Init() override;
|
2017-06-14 22:19:54 -03:00
|
|
|
bool CardInserted(void) const override;
|
2013-02-28 16:17:58 -04:00
|
|
|
|
|
|
|
// erase handling
|
2017-03-30 06:23:17 -03:00
|
|
|
void EraseAll() override;
|
2013-02-28 16:17:58 -04:00
|
|
|
|
|
|
|
/* Write a block of data at current offset */
|
2017-06-30 08:09:20 -03:00
|
|
|
bool _WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical) override;
|
2017-03-30 06:23:17 -03:00
|
|
|
uint32_t bufferspace_available() override;
|
2013-02-28 16:17:58 -04:00
|
|
|
|
|
|
|
// high level interface
|
2015-10-20 07:32:31 -03:00
|
|
|
uint16_t find_last_log() override;
|
2019-01-18 18:45:36 -04:00
|
|
|
void get_log_boundaries(uint16_t log_num, uint32_t & start_page, uint32_t & end_page) override;
|
2017-03-30 06:23:17 -03:00
|
|
|
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;
|
2015-10-20 07:32:31 -03:00
|
|
|
uint16_t get_num_logs() override;
|
2020-01-20 13:27:12 -04:00
|
|
|
void start_new_log(void) override;
|
2020-05-05 14:00:54 -03:00
|
|
|
uint16_t find_oldest_log() override;
|
2013-02-28 16:17:58 -04:00
|
|
|
|
2015-06-18 22:57:01 -03:00
|
|
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX
|
2017-03-30 06:23:17 -03:00
|
|
|
void flush(void) override;
|
2015-06-18 22:57:01 -03:00
|
|
|
#endif
|
2018-07-28 13:28:54 -03:00
|
|
|
void periodic_1Hz() override;
|
|
|
|
void periodic_fullrate() override;
|
2016-07-07 04:12:27 -03:00
|
|
|
|
|
|
|
// this method is used when reporting system status over mavlink
|
2017-03-30 06:23:17 -03:00
|
|
|
bool logging_failed() const override;
|
2016-07-07 04:12:27 -03:00
|
|
|
|
2017-07-06 22:34:31 -03:00
|
|
|
bool logging_started(void) const override { return _write_fd != -1; }
|
2020-12-22 13:25:44 -04:00
|
|
|
void io_timer(void) override;
|
2017-07-06 22:34:31 -03:00
|
|
|
|
2017-06-08 22:36:18 -03:00
|
|
|
protected:
|
|
|
|
|
|
|
|
bool WritesOK() const override;
|
2017-06-30 08:09:20 -03:00
|
|
|
bool StartNewLogOK() const override;
|
2021-06-14 22:09:24 -03:00
|
|
|
void PrepForArming_start_logging() override;
|
2017-06-08 22:36:18 -03:00
|
|
|
|
2013-02-28 16:17:58 -04:00
|
|
|
private:
|
2021-01-06 06:44:50 -04:00
|
|
|
int _write_fd = -1;
|
2018-06-13 21:32:44 -03:00
|
|
|
char *_write_filename;
|
2023-04-11 07:14:09 -03:00
|
|
|
bool last_log_is_marked_discard;
|
2018-06-13 21:32:44 -03:00
|
|
|
uint32_t _last_write_ms;
|
2024-02-19 14:43:08 -04:00
|
|
|
#if AP_RTC_ENABLED && CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
|
2019-07-10 23:16:29 -03:00
|
|
|
bool _need_rtc_update;
|
2019-07-15 20:39:49 -03:00
|
|
|
#endif
|
2018-06-13 21:32:44 -03:00
|
|
|
|
2021-01-06 06:44:50 -04:00
|
|
|
int _read_fd = -1;
|
2013-12-15 03:57:49 -04:00
|
|
|
uint16_t _read_fd_log_num;
|
2013-04-17 08:32:53 -03:00
|
|
|
uint32_t _read_offset;
|
2014-01-12 23:25:16 -04:00
|
|
|
uint32_t _write_offset;
|
2019-10-03 23:10:39 -03:00
|
|
|
volatile uint32_t _open_error_ms;
|
2013-02-28 16:17:58 -04:00
|
|
|
const char *_log_directory;
|
2019-08-03 04:00:17 -03:00
|
|
|
bool _last_write_failed;
|
2013-02-28 16:17:58 -04:00
|
|
|
|
2016-11-06 02:09:39 -04:00
|
|
|
uint32_t _io_timer_heartbeat;
|
|
|
|
bool io_thread_alive() const;
|
2017-04-17 07:42:30 -03:00
|
|
|
uint8_t io_thread_warning_decimation_counter;
|
2016-11-06 02:09:39 -04:00
|
|
|
|
2019-10-03 23:10:39 -03:00
|
|
|
// do we have a recent open error?
|
|
|
|
bool recent_open_error(void) const;
|
|
|
|
|
2015-08-08 03:13:38 -03:00
|
|
|
// possibly time-consuming preparations handling
|
|
|
|
void Prep_MinSpace();
|
2015-10-20 07:32:31 -03:00
|
|
|
int64_t disk_space_avail();
|
|
|
|
int64_t disk_space();
|
2015-08-08 03:13:38 -03:00
|
|
|
|
2020-05-10 23:15:11 -03:00
|
|
|
void ensure_log_directory_exists();
|
|
|
|
|
2015-10-20 07:32:31 -03:00
|
|
|
bool file_exists(const char *filename) const;
|
|
|
|
bool log_exists(const uint16_t lognum) const;
|
|
|
|
|
2022-04-17 21:25:16 -03:00
|
|
|
bool dirent_to_log_num(const dirent *de, uint16_t &log_num) const;
|
2023-04-11 07:14:09 -03:00
|
|
|
bool write_lastlog_file(uint16_t log_num);
|
2022-04-17 21:25:16 -03:00
|
|
|
|
2013-02-28 16:17:58 -04:00
|
|
|
// write buffer
|
2021-01-06 06:44:50 -04:00
|
|
|
ByteBuffer _writebuf{0};
|
|
|
|
const uint16_t _writebuf_chunk = HAL_LOGGER_WRITE_CHUNK_SIZE;
|
2013-09-28 03:29:58 -03:00
|
|
|
uint32_t _last_write_time;
|
2013-02-28 16:17:58 -04:00
|
|
|
|
|
|
|
/* construct a file name given a log number. Caller must free. */
|
2015-10-20 07:32:31 -03:00
|
|
|
char *_log_file_name(const uint16_t log_num) const;
|
2017-02-10 22:39:50 -04:00
|
|
|
char *_log_file_name_long(const uint16_t log_num) const;
|
|
|
|
char *_log_file_name_short(const uint16_t log_num) const;
|
2015-10-20 07:32:31 -03:00
|
|
|
char *_lastlog_file_name() const;
|
2018-10-11 20:35:04 -03:00
|
|
|
uint32_t _get_log_size(const uint16_t log_num);
|
|
|
|
uint32_t _get_log_time(const uint16_t log_num);
|
2013-04-17 08:32:53 -03:00
|
|
|
|
2017-03-30 06:23:17 -03:00
|
|
|
void stop_logging(void) override;
|
2013-12-27 23:24:28 -04:00
|
|
|
|
2018-08-14 22:36:09 -03:00
|
|
|
uint32_t last_messagewrite_message_sent;
|
2015-08-06 09:18:28 -03:00
|
|
|
|
2016-07-06 05:58:47 -03:00
|
|
|
// 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.
|
2016-11-06 01:26:31 -04:00
|
|
|
uint32_t _free_space_last_check_time; // milliseconds
|
|
|
|
const uint32_t _free_space_check_interval = 1000UL; // milliseconds
|
2016-07-06 05:58:47 -03:00
|
|
|
const uint32_t _free_space_min_avail = 8388608; // bytes
|
|
|
|
|
2017-09-12 22:46:34 -03:00
|
|
|
// semaphore mediates access to the ringbuffer
|
2018-10-11 20:35:04 -03:00
|
|
|
HAL_Semaphore semaphore;
|
2017-09-12 22:46:34 -03:00
|
|
|
// 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
|
2018-10-11 20:35:04 -03:00
|
|
|
HAL_Semaphore write_fd_semaphore;
|
2017-07-27 23:07:35 -03:00
|
|
|
|
2021-03-28 22:05:57 -03:00
|
|
|
// async erase state
|
|
|
|
struct {
|
|
|
|
bool was_logging;
|
|
|
|
uint16_t log_num;
|
|
|
|
} erase;
|
|
|
|
void erase_next(void);
|
|
|
|
|
2017-07-27 23:07:35 -03:00
|
|
|
const char *last_io_operation = "";
|
2021-06-13 20:46:51 -03:00
|
|
|
|
|
|
|
bool start_new_log_pending;
|
2013-02-28 16:17:58 -04:00
|
|
|
};
|
|
|
|
|
2021-01-06 22:04:09 -04:00
|
|
|
#endif // HAL_LOGGING_FILESYSTEM_ENABLED
|