mirror of https://github.com/ArduPilot/ardupilot
AP_Logger: write formats out as required rather than at start of log
This commit is contained in:
parent
681e2d7993
commit
0056ef2d90
|
@ -101,6 +101,7 @@ void AP_Logger_Backend::start_new_log_reset_variables()
|
||||||
_startup_messagewriter->reset();
|
_startup_messagewriter->reset();
|
||||||
_front.backend_starting_new_log(this);
|
_front.backend_starting_new_log(this);
|
||||||
_log_file_size_bytes = 0;
|
_log_file_size_bytes = 0;
|
||||||
|
_formats_written.clearall();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We may need to make sure data is loggable before starting the
|
// We may need to make sure data is loggable before starting the
|
||||||
|
@ -124,42 +125,6 @@ void AP_Logger_Backend::push_log_blocks() {
|
||||||
WriteMoreStartupMessages();
|
WriteMoreStartupMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if all format messages have been written, and thus it is OK
|
|
||||||
// for other messages to go out to the log
|
|
||||||
bool AP_Logger_Backend::WriteBlockCheckStartupMessages()
|
|
||||||
{
|
|
||||||
#if APM_BUILD_TYPE(APM_BUILD_Replay)
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (_startup_messagewriter->fmt_done()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_writing_startup_messages) {
|
|
||||||
// we have been called by a messagewriter, so writing is OK
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_startup_messagewriter->finished() &&
|
|
||||||
!hal.scheduler->in_main_thread()) {
|
|
||||||
// only the main thread may write startup messages out
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we're not writing startup messages, so this must be some random
|
|
||||||
// caller hoping to write blocks out. Push out log blocks - we
|
|
||||||
// might end up clearing the buffer.....
|
|
||||||
push_log_blocks();
|
|
||||||
|
|
||||||
// even if we did finish writing startup messages, we can't
|
|
||||||
// permit any message to go in as its timestamp will be before
|
|
||||||
// any we wrote in. Time going backwards annoys log readers.
|
|
||||||
|
|
||||||
// sorry! currently busy writing out startup messages...
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// source more messages from the startup message writer:
|
// source more messages from the startup message writer:
|
||||||
void AP_Logger_Backend::WriteMoreStartupMessages()
|
void AP_Logger_Backend::WriteMoreStartupMessages()
|
||||||
{
|
{
|
||||||
|
@ -363,6 +328,23 @@ bool AP_Logger_Backend::StartNewLogOK() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validate that pBuffer looks like a message, extract message type.
|
||||||
|
// Returns false if this doesn't look like a valid message.
|
||||||
|
bool AP_Logger_Backend::message_type_from_block(const void *pBuffer, uint16_t size, LogMessages &type) const
|
||||||
|
{
|
||||||
|
if (size < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (((uint8_t*)pBuffer)[0] != HEAD_BYTE1 ||
|
||||||
|
((uint8_t*)pBuffer)[1] != HEAD_BYTE2) {
|
||||||
|
// Not passed a message
|
||||||
|
INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
type = LogMessages(((uint8_t*)pBuffer)[2]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
|
||||||
void AP_Logger_Backend::validate_WritePrioritisedBlock(const void *pBuffer,
|
void AP_Logger_Backend::validate_WritePrioritisedBlock(const void *pBuffer,
|
||||||
uint16_t size)
|
uint16_t size)
|
||||||
|
@ -381,11 +363,10 @@ void AP_Logger_Backend::validate_WritePrioritisedBlock(const void *pBuffer,
|
||||||
if (size < 3) {
|
if (size < 3) {
|
||||||
AP_HAL::panic("Short prioritised block");
|
AP_HAL::panic("Short prioritised block");
|
||||||
}
|
}
|
||||||
if (((uint8_t*)pBuffer)[0] != HEAD_BYTE1 ||
|
LogMessages type;
|
||||||
((uint8_t*)pBuffer)[1] != HEAD_BYTE2) {
|
if (!message_type_from_block(pBuffer, size, type)) {
|
||||||
AP_HAL::panic("Not passed a message");
|
AP_HAL::panic("Not passed a message");
|
||||||
}
|
}
|
||||||
const uint8_t type = ((uint8_t*)pBuffer)[2];
|
|
||||||
uint8_t type_len;
|
uint8_t type_len;
|
||||||
const char *name_src;
|
const char *name_src;
|
||||||
const struct LogStructure *s = _front.structure_for_msg_type(type);
|
const struct LogStructure *s = _front.structure_for_msg_type(type);
|
||||||
|
@ -413,6 +394,57 @@ void AP_Logger_Backend::validate_WritePrioritisedBlock(const void *pBuffer,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool AP_Logger_Backend::emit_format_for_type(LogMessages a_type)
|
||||||
|
{
|
||||||
|
// linearly scan the formats structure to find the format for the type:
|
||||||
|
for (uint8_t i=0; i< num_types(); i++) {
|
||||||
|
const auto &s { structure(i) };
|
||||||
|
if (s == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (s->msg_type != a_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// found the relevant structure. Attempt to write it:
|
||||||
|
if (!Write_Format(s)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// didn't find the structure. That's probably bad...
|
||||||
|
INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Logger_Backend::ensure_format_emitted(const void *pBuffer, uint16_t size)
|
||||||
|
{
|
||||||
|
#if APM_BUILD_TYPE(APM_BUILD_Replay)
|
||||||
|
// we trust that Replay will correctly emit formats as required
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// extract the ID:
|
||||||
|
LogMessages type;
|
||||||
|
if (!message_type_from_block(pBuffer, size, type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (have_emitted_format_for_type(type)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the FMT message has gone out!
|
||||||
|
if (type == LOG_FORMAT_MSG) {
|
||||||
|
// kind of? Our caller is just about to emit this....
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!have_emitted_format_for_type(LOG_FORMAT_MSG) &&
|
||||||
|
!emit_format_for_type(LOG_FORMAT_MSG)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return emit_format_for_type(type);
|
||||||
|
}
|
||||||
|
|
||||||
bool AP_Logger_Backend::WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical, bool writev_streaming)
|
bool AP_Logger_Backend::WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical, bool writev_streaming)
|
||||||
{
|
{
|
||||||
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL && !APM_BUILD_TYPE(APM_BUILD_Replay)
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL && !APM_BUILD_TYPE(APM_BUILD_Replay)
|
||||||
|
@ -435,6 +467,10 @@ bool AP_Logger_Backend::WritePrioritisedBlock(const void *pBuffer, uint16_t size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ensure_format_emitted(pBuffer, size)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return _WritePrioritisedBlock(pBuffer, size, is_critical);
|
return _WritePrioritisedBlock(pBuffer, size, is_critical);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <GCS_MAVLink/GCS_MAVLink.h>
|
#include <GCS_MAVLink/GCS_MAVLink.h>
|
||||||
#include <AP_Mission/AP_Mission.h>
|
#include <AP_Mission/AP_Mission.h>
|
||||||
#include <AP_Vehicle/ModeReason.h>
|
#include <AP_Vehicle/ModeReason.h>
|
||||||
|
#include "LogStructure.h"
|
||||||
|
|
||||||
class LoggerMessageWriter_DFLogStart;
|
class LoggerMessageWriter_DFLogStart;
|
||||||
|
|
||||||
|
@ -132,6 +133,9 @@ public:
|
||||||
bool Write_Fence();
|
bool Write_Fence();
|
||||||
#endif
|
#endif
|
||||||
bool Write_Format(const struct LogStructure *structure);
|
bool Write_Format(const struct LogStructure *structure);
|
||||||
|
bool have_emitted_format_for_type(LogMessages a_type) const {
|
||||||
|
return _formats_written.get(uint8_t(a_type));
|
||||||
|
}
|
||||||
bool Write_Message(const char *message);
|
bool Write_Message(const char *message);
|
||||||
bool Write_MessageF(const char *fmt, ...);
|
bool Write_MessageF(const char *fmt, ...);
|
||||||
bool Write_Mission_Cmd(const AP_Mission &mission,
|
bool Write_Mission_Cmd(const AP_Mission &mission,
|
||||||
|
@ -195,7 +199,6 @@ protected:
|
||||||
/*
|
/*
|
||||||
read a block
|
read a block
|
||||||
*/
|
*/
|
||||||
virtual bool WriteBlockCheckStartupMessages();
|
|
||||||
virtual void WriteMoreStartupMessages();
|
virtual void WriteMoreStartupMessages();
|
||||||
virtual void push_log_blocks();
|
virtual void push_log_blocks();
|
||||||
|
|
||||||
|
@ -262,6 +265,12 @@ private:
|
||||||
|
|
||||||
void Write_AP_Logger_Stats_File(const struct df_stats &_stats);
|
void Write_AP_Logger_Stats_File(const struct df_stats &_stats);
|
||||||
void validate_WritePrioritisedBlock(const void *pBuffer, uint16_t size);
|
void validate_WritePrioritisedBlock(const void *pBuffer, uint16_t size);
|
||||||
|
|
||||||
|
bool message_type_from_block(const void *pBuffer, uint16_t size, LogMessages &type) const;
|
||||||
|
bool ensure_format_emitted(const void *pBuffer, uint16_t size);
|
||||||
|
bool emit_format_for_type(LogMessages a_type);
|
||||||
|
Bitmask<256> _formats_written;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HAL_LOGGING_ENABLED
|
#endif // HAL_LOGGING_ENABLED
|
||||||
|
|
|
@ -132,11 +132,6 @@ bool AP_Logger_Block::_WritePrioritisedBlock(const void *pBuffer, uint16_t size,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteBlockCheckStartupMessages()) {
|
|
||||||
_dropped++;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
WITH_SEMAPHORE(write_sem);
|
WITH_SEMAPHORE(write_sem);
|
||||||
|
|
||||||
const uint32_t space = writebuf.space();
|
const uint32_t space = writebuf.space();
|
||||||
|
|
|
@ -474,11 +474,6 @@ bool AP_Logger_File::_WritePrioritisedBlock(const void *pBuffer, uint16_t size,
|
||||||
{
|
{
|
||||||
WITH_SEMAPHORE(semaphore);
|
WITH_SEMAPHORE(semaphore);
|
||||||
|
|
||||||
if (! WriteBlockCheckStartupMessages()) {
|
|
||||||
_dropped++;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if APM_BUILD_TYPE(APM_BUILD_Replay)
|
#if APM_BUILD_TYPE(APM_BUILD_Replay)
|
||||||
if (AP::FS().write(_write_fd, pBuffer, size) != size) {
|
if (AP::FS().write(_write_fd, pBuffer, size) != size) {
|
||||||
AP_HAL::panic("Short write");
|
AP_HAL::panic("Short write");
|
||||||
|
|
|
@ -136,11 +136,6 @@ bool AP_Logger_MAVLink::_WritePrioritisedBlock(const void *pBuffer, uint16_t siz
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! WriteBlockCheckStartupMessages()) {
|
|
||||||
semaphore.give();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bufferspace_available() < size) {
|
if (bufferspace_available() < size) {
|
||||||
if (_startup_messagewriter->finished()) {
|
if (_startup_messagewriter->finished()) {
|
||||||
// do not count the startup packets as being dropped...
|
// do not count the startup packets as being dropped...
|
||||||
|
|
|
@ -60,7 +60,11 @@ bool AP_Logger_Backend::Write_Format(const struct LogStructure *s)
|
||||||
{
|
{
|
||||||
struct log_Format pkt;
|
struct log_Format pkt;
|
||||||
Fill_Format(s, pkt);
|
Fill_Format(s, pkt);
|
||||||
return WriteCriticalBlock(&pkt, sizeof(pkt));
|
if (!WriteCriticalBlock(&pkt, sizeof(pkt))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_formats_written.set(s->msg_type);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -109,7 +109,12 @@ void LoggerMessageWriter_DFLogStart::process()
|
||||||
case Stage::FORMATS:
|
case Stage::FORMATS:
|
||||||
// write log formats so the log is self-describing
|
// write log formats so the log is self-describing
|
||||||
while (next_format_to_send < _logger_backend->num_types()) {
|
while (next_format_to_send < _logger_backend->num_types()) {
|
||||||
if (!_logger_backend->Write_Format(_logger_backend->structure(next_format_to_send))) {
|
const auto &s { _logger_backend->structure(next_format_to_send) };
|
||||||
|
if (_logger_backend->have_emitted_format_for_type((LogMessages)s->msg_type)) {
|
||||||
|
next_format_to_send++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!_logger_backend->Write_Format(s)) {
|
||||||
return; // call me again!
|
return; // call me again!
|
||||||
}
|
}
|
||||||
next_format_to_send++;
|
next_format_to_send++;
|
||||||
|
|
Loading…
Reference in New Issue