mirror of
https://gitee.com/xiaohuolufeihua/bizhang_-obav.git
synced 2026-05-22 01:12:31 +00:00
logger: add mission file to LogWriterFile backend
Not used yet, it should not affect anything, except for slight RAM increase.
This commit is contained in:
@@ -100,7 +100,7 @@ bool LogWriter::is_started() const
|
||||
bool ret = false;
|
||||
|
||||
if (_log_writer_file) {
|
||||
ret = _log_writer_file->is_started();
|
||||
ret = _log_writer_file->is_started(LogType::Full);
|
||||
}
|
||||
|
||||
if (_log_writer_mavlink) {
|
||||
@@ -113,7 +113,7 @@ bool LogWriter::is_started() const
|
||||
bool LogWriter::is_started(Backend query_backend) const
|
||||
{
|
||||
if (query_backend == BackendFile && _log_writer_file) {
|
||||
return _log_writer_file->is_started();
|
||||
return _log_writer_file->is_started(LogType::Full);
|
||||
}
|
||||
|
||||
if (query_backend == BackendMavlink && _log_writer_mavlink) {
|
||||
@@ -126,14 +126,14 @@ bool LogWriter::is_started(Backend query_backend) const
|
||||
void LogWriter::start_log_file(const char *filename)
|
||||
{
|
||||
if (_log_writer_file) {
|
||||
_log_writer_file->start_log(filename);
|
||||
_log_writer_file->start_log(LogType::Full, filename);
|
||||
}
|
||||
}
|
||||
|
||||
void LogWriter::stop_log_file()
|
||||
{
|
||||
if (_log_writer_file) {
|
||||
_log_writer_file->stop_log();
|
||||
_log_writer_file->stop_log(LogType::Full);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ int LogWriter::write_message(void *ptr, size_t size, uint64_t dropout_start)
|
||||
int ret_file = 0, ret_mavlink = 0;
|
||||
|
||||
if (_log_writer_file_for_write) {
|
||||
ret_file = _log_writer_file_for_write->write_message(ptr, size, dropout_start);
|
||||
ret_file = _log_writer_file_for_write->write_message(LogType::Full, ptr, size, dropout_start);
|
||||
}
|
||||
|
||||
if (_log_writer_mavlink_for_write) {
|
||||
|
||||
@@ -118,21 +118,21 @@ public:
|
||||
|
||||
size_t get_total_written_file() const
|
||||
{
|
||||
if (_log_writer_file) { return _log_writer_file->get_total_written(); }
|
||||
if (_log_writer_file) { return _log_writer_file->get_total_written(LogType::Full); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t get_buffer_size_file() const
|
||||
{
|
||||
if (_log_writer_file) { return _log_writer_file->get_buffer_size(); }
|
||||
if (_log_writer_file) { return _log_writer_file->get_buffer_size(LogType::Full); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t get_buffer_fill_count_file() const
|
||||
{
|
||||
if (_log_writer_file) { return _log_writer_file->get_buffer_fill_count(); }
|
||||
if (_log_writer_file) { return _log_writer_file->get_buffer_fill_count(LogType::Full); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -51,17 +51,21 @@ namespace logger
|
||||
{
|
||||
constexpr size_t LogWriterFile::_min_write_chunk;
|
||||
|
||||
|
||||
LogWriterFile::LogWriterFile(size_t buffer_size) :
|
||||
LogWriterFile::LogWriterFile(size_t buffer_size)
|
||||
: _buffers{
|
||||
//We always write larger chunks (orb messages) to the buffer, so the buffer
|
||||
//needs to be larger than the minimum write chunk (300 is somewhat arbitrary)
|
||||
_buffer_size(math::max(buffer_size, _min_write_chunk + 300))
|
||||
{
|
||||
math::max(buffer_size, _min_write_chunk + 300),
|
||||
perf_alloc(PC_ELAPSED, "logger_sd_write"), perf_alloc(PC_ELAPSED, "logger_sd_fsync")},
|
||||
|
||||
{
|
||||
300, // buffer size for the mission log (can be kept fairly small)
|
||||
perf_alloc(PC_ELAPSED, "logger_sd_write_mission"), perf_alloc(PC_ELAPSED, "logger_sd_fsync_mission")}
|
||||
}
|
||||
{
|
||||
pthread_mutex_init(&_mtx, nullptr);
|
||||
pthread_cond_init(&_cv, nullptr);
|
||||
/* allocate write performance counters */
|
||||
_perf_write = perf_alloc(PC_ELAPSED, "logger_sd_write");
|
||||
_perf_fsync = perf_alloc(PC_ELAPSED, "logger_sd_fsync");
|
||||
}
|
||||
|
||||
bool LogWriterFile::init()
|
||||
@@ -73,59 +77,26 @@ LogWriterFile::~LogWriterFile()
|
||||
{
|
||||
pthread_mutex_destroy(&_mtx);
|
||||
pthread_cond_destroy(&_cv);
|
||||
perf_free(_perf_write);
|
||||
perf_free(_perf_fsync);
|
||||
|
||||
if (_fd >= 0) {
|
||||
::close(_fd);
|
||||
}
|
||||
|
||||
if (_buffer) {
|
||||
delete[] _buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void LogWriterFile::start_log(const char *filename)
|
||||
void LogWriterFile::start_log(LogType type, const char *filename)
|
||||
{
|
||||
// register the current file with the hardfault handler: if the system crashes,
|
||||
// the hardfault handler will append the crash log to that file on the next reboot.
|
||||
// Note that we don't deregister it when closing the log, so that crashes after disarming
|
||||
// are appended as well (the same holds for crashes before arming, which can be a bit misleading)
|
||||
int ret = hardfault_store_filename(filename);
|
||||
if (type == LogType::Full) {
|
||||
// register the current file with the hardfault handler: if the system crashes,
|
||||
// the hardfault handler will append the crash log to that file on the next reboot.
|
||||
// Note that we don't deregister it when closing the log, so that crashes after disarming
|
||||
// are appended as well (the same holds for crashes before arming, which can be a bit misleading)
|
||||
int ret = hardfault_store_filename(filename);
|
||||
|
||||
if (ret) {
|
||||
PX4_ERR("Failed to register ULog file to the hardfault handler (%i)", ret);
|
||||
}
|
||||
|
||||
_fd = ::open(filename, O_CREAT | O_WRONLY, PX4_O_MODE_666);
|
||||
|
||||
if (_fd < 0) {
|
||||
PX4_ERR("Can't open log file %s, errno: %d", filename, errno);
|
||||
_should_run = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_buffer == nullptr) {
|
||||
_buffer = new uint8_t[_buffer_size];
|
||||
|
||||
if (_buffer == nullptr) {
|
||||
PX4_ERR("Can't create log buffer");
|
||||
::close(_fd);
|
||||
_fd = -1;
|
||||
_should_run = false;
|
||||
return;
|
||||
if (ret) {
|
||||
PX4_ERR("Failed to register ULog file to the hardfault handler (%i)", ret);
|
||||
}
|
||||
}
|
||||
|
||||
PX4_INFO("Opened log file: %s", filename);
|
||||
_should_run = true;
|
||||
_running = true;
|
||||
|
||||
// Clear buffer and counters
|
||||
_head = 0;
|
||||
_count = 0;
|
||||
_total_written = 0;
|
||||
notify();
|
||||
if (_buffers[(int)type].start_log(filename)) {
|
||||
PX4_INFO("Opened %s log file: %s", log_type_str(type), filename);
|
||||
notify();
|
||||
}
|
||||
}
|
||||
|
||||
int LogWriterFile::hardfault_store_filename(const char *log_file)
|
||||
@@ -160,9 +131,9 @@ int LogWriterFile::hardfault_store_filename(const char *log_file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LogWriterFile::stop_log()
|
||||
void LogWriterFile::stop_log(LogType type)
|
||||
{
|
||||
_should_run = false;
|
||||
_buffers[(int)type]._should_run = false;
|
||||
notify();
|
||||
}
|
||||
|
||||
@@ -188,7 +159,7 @@ void LogWriterFile::thread_stop()
|
||||
{
|
||||
// this will terminate the main loop of the writer thread
|
||||
_exit_thread = true;
|
||||
_should_run = false;
|
||||
_buffers[0]._should_run = _buffers[1]._should_run = false;
|
||||
|
||||
notify();
|
||||
|
||||
@@ -218,7 +189,7 @@ void LogWriterFile::run()
|
||||
bool start = false;
|
||||
pthread_mutex_lock(&_mtx);
|
||||
pthread_cond_wait(&_cv, &_mtx);
|
||||
start = _should_run;
|
||||
start = _buffers[0]._should_run || _buffers[1]._should_run;
|
||||
pthread_mutex_unlock(&_mtx);
|
||||
|
||||
if (start) {
|
||||
@@ -234,95 +205,95 @@ void LogWriterFile::run()
|
||||
int written = 0;
|
||||
hrt_abstime last_fsync = hrt_absolute_time();
|
||||
|
||||
pthread_mutex_lock(&_mtx);
|
||||
|
||||
while (true) {
|
||||
size_t available = 0;
|
||||
void *read_ptr = nullptr;
|
||||
bool is_part = false;
|
||||
|
||||
/* lock _buffer
|
||||
* wait for sufficient data, cycle on notify()
|
||||
*/
|
||||
pthread_mutex_lock(&_mtx);
|
||||
const hrt_abstime now = hrt_absolute_time();
|
||||
|
||||
while (true) {
|
||||
available = get_read_ptr(&read_ptr, &is_part);
|
||||
/* call fsync periodically to minimize potential loss of data */
|
||||
const bool call_fsync = ++poll_count >= 100 || now - last_fsync > 1_s;
|
||||
|
||||
/* if sufficient data available or partial read or terminating, exit this wait loop */
|
||||
if ((available >= _min_write_chunk) || is_part || !_should_run) {
|
||||
/* GOTO end of block */
|
||||
break;
|
||||
}
|
||||
|
||||
/* wait for a call to notify()
|
||||
* this call unlocks the mutex while waiting, and returns with the mutex locked
|
||||
*/
|
||||
pthread_cond_wait(&_cv, &_mtx);
|
||||
if (call_fsync) {
|
||||
last_fsync = now;
|
||||
poll_count = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_mtx);
|
||||
written = 0;
|
||||
constexpr size_t min_available[(int)LogType::Count] = {
|
||||
_min_write_chunk,
|
||||
1 // For the mission log, write as soon as there is data available
|
||||
};
|
||||
|
||||
if (available > 0) {
|
||||
perf_begin(_perf_write);
|
||||
written = ::write(_fd, read_ptr, available);
|
||||
perf_end(_perf_write);
|
||||
/* Check all buffers for available data. Mission log is first to avoid drops */
|
||||
int i = (int)LogType::Count - 1;
|
||||
|
||||
const hrt_abstime now = hrt_absolute_time();
|
||||
while (i >= 0) {
|
||||
void *read_ptr;
|
||||
bool is_part;
|
||||
LogFileBuffer &buffer = _buffers[i];
|
||||
size_t available = buffer.get_read_ptr(&read_ptr, &is_part);
|
||||
|
||||
/* call fsync periodically to minimize potential loss of data */
|
||||
if (++poll_count >= 100 || now - last_fsync > 1_s) {
|
||||
perf_begin(_perf_fsync);
|
||||
::fsync(_fd);
|
||||
perf_end(_perf_fsync);
|
||||
poll_count = 0;
|
||||
last_fsync = now;
|
||||
}
|
||||
/* if sufficient data available or partial read or terminating, write data */
|
||||
if (available >= min_available[i] || is_part || (!buffer._should_run && available > 0)) {
|
||||
pthread_mutex_unlock(&_mtx);
|
||||
|
||||
if (written < 0) {
|
||||
PX4_WARN("error writing log file");
|
||||
_should_run = false;
|
||||
/* GOTO end of block */
|
||||
break;
|
||||
}
|
||||
written = buffer.write_to_file(read_ptr, available, call_fsync);
|
||||
|
||||
pthread_mutex_lock(&_mtx);
|
||||
/* subtract bytes written from number in _buffer (_count -= written) */
|
||||
mark_read(written);
|
||||
pthread_mutex_unlock(&_mtx);
|
||||
/* buffer.mark_read() requires _mtx to be locked */
|
||||
pthread_mutex_lock(&_mtx);
|
||||
|
||||
_total_written += written;
|
||||
}
|
||||
if (written >= 0) {
|
||||
/* subtract bytes written from number in buffer (count -= written) */
|
||||
buffer.mark_read(written);
|
||||
|
||||
if (!_should_run && written == static_cast<int>(available) && !is_part) {
|
||||
// Stop only when all data written
|
||||
_running = false;
|
||||
_head = 0;
|
||||
_count = 0;
|
||||
|
||||
if (_fd >= 0) {
|
||||
int res = ::close(_fd);
|
||||
_fd = -1;
|
||||
|
||||
if (res) {
|
||||
PX4_WARN("error closing log file");
|
||||
if (!buffer._should_run && written == static_cast<int>(available) && !is_part) {
|
||||
/* Stop only when all data written */
|
||||
buffer.close_file();
|
||||
}
|
||||
|
||||
} else {
|
||||
PX4_INFO("closed logfile, bytes written: %zu", _total_written);
|
||||
PX4_ERR("write failed (%i)", errno);
|
||||
buffer._should_run = false;
|
||||
buffer.close_file();
|
||||
}
|
||||
|
||||
} else if (call_fsync) {
|
||||
buffer.fsync();
|
||||
|
||||
} else if (available == 0 && !buffer._should_run) {
|
||||
buffer.close_file();
|
||||
}
|
||||
|
||||
/* if split into 2 parts, write the second part immediately as well */
|
||||
if (!is_part) {
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_buffers[0].fd() < 0 && _buffers[1].fd() < 0) {
|
||||
// stop when both files are closed
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait for a call to notify(), which indicates new data is available.
|
||||
* Note that at this point there could already be new data available (because of a longer write),
|
||||
* and calling pthread_cond_wait() will still wait for the next notify(). But this is generally
|
||||
* not an issue because notify() is called regularly. */
|
||||
pthread_cond_wait(&_cv, &_mtx);
|
||||
}
|
||||
|
||||
// go back to idle
|
||||
pthread_mutex_unlock(&_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
int LogWriterFile::write_message(void *ptr, size_t size, uint64_t dropout_start)
|
||||
int LogWriterFile::write_message(LogType type, void *ptr, size_t size, uint64_t dropout_start)
|
||||
{
|
||||
if (_need_reliable_transfer) {
|
||||
int ret;
|
||||
|
||||
while ((ret = write(ptr, size, dropout_start)) == -1) {
|
||||
while ((ret = write(type, ptr, size, dropout_start)) == -1) {
|
||||
unlock();
|
||||
notify();
|
||||
usleep(3000);
|
||||
@@ -332,17 +303,17 @@ int LogWriterFile::write_message(void *ptr, size_t size, uint64_t dropout_start)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return write(ptr, size, dropout_start);
|
||||
return write(type, ptr, size, dropout_start);
|
||||
}
|
||||
|
||||
int LogWriterFile::write(void *ptr, size_t size, uint64_t dropout_start)
|
||||
int LogWriterFile::write(LogType type, void *ptr, size_t size, uint64_t dropout_start)
|
||||
{
|
||||
if (!is_started()) {
|
||||
if (!is_started(type)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Bytes available to write
|
||||
size_t available = _buffer_size - _count;
|
||||
size_t available = _buffers[(int)type].available();
|
||||
size_t dropout_size = 0;
|
||||
|
||||
if (dropout_start) {
|
||||
@@ -358,14 +329,44 @@ int LogWriterFile::write(void *ptr, size_t size, uint64_t dropout_start)
|
||||
//write dropout msg
|
||||
ulog_message_dropout_s dropout_msg;
|
||||
dropout_msg.duration = (uint16_t)(hrt_elapsed_time(&dropout_start) / 1000);
|
||||
write_no_check(&dropout_msg, sizeof(dropout_msg));
|
||||
_buffers[(int)type].write_no_check(&dropout_msg, sizeof(dropout_msg));
|
||||
}
|
||||
|
||||
write_no_check(ptr, size);
|
||||
_buffers[(int)type].write_no_check(ptr, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LogWriterFile::write_no_check(void *ptr, size_t size)
|
||||
const char *log_type_str(LogType type)
|
||||
{
|
||||
switch (type) {
|
||||
case LogType::Full: return "full";
|
||||
|
||||
case LogType::Mission: return "mission";
|
||||
|
||||
case LogType::Count: break;
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
LogWriterFile::LogFileBuffer::LogFileBuffer(size_t buffer_size, perf_counter_t perf_write, perf_counter_t perf_fsync)
|
||||
: _buffer_size(buffer_size), _perf_write(perf_write), _perf_fsync(perf_fsync)
|
||||
{
|
||||
}
|
||||
|
||||
LogWriterFile::LogFileBuffer::~LogFileBuffer()
|
||||
{
|
||||
if (_fd >= 0) {
|
||||
close(_fd);
|
||||
}
|
||||
|
||||
delete[] _buffer;
|
||||
|
||||
perf_free(_perf_write);
|
||||
perf_free(_perf_fsync);
|
||||
}
|
||||
|
||||
void LogWriterFile::LogFileBuffer::write_no_check(void *ptr, size_t size)
|
||||
{
|
||||
size_t n = _buffer_size - _head; // bytes to end of the buffer
|
||||
|
||||
@@ -387,7 +388,7 @@ void LogWriterFile::write_no_check(void *ptr, size_t size)
|
||||
_count += size;
|
||||
}
|
||||
|
||||
size_t LogWriterFile::get_read_ptr(void **ptr, bool *is_part)
|
||||
size_t LogWriterFile::LogFileBuffer::get_read_ptr(void **ptr, bool *is_part)
|
||||
{
|
||||
// bytes available to read
|
||||
int read_ptr = _head - _count;
|
||||
@@ -405,5 +406,73 @@ size_t LogWriterFile::get_read_ptr(void **ptr, bool *is_part)
|
||||
}
|
||||
}
|
||||
|
||||
bool LogWriterFile::LogFileBuffer::start_log(const char *filename)
|
||||
{
|
||||
_fd = ::open(filename, O_CREAT | O_WRONLY, PX4_O_MODE_666);
|
||||
|
||||
if (_fd < 0) {
|
||||
PX4_ERR("Can't open log file %s, errno: %d", filename, errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_buffer == nullptr) {
|
||||
_buffer = new uint8_t[_buffer_size];
|
||||
|
||||
if (_buffer == nullptr) {
|
||||
PX4_ERR("Can't create log buffer");
|
||||
::close(_fd);
|
||||
_fd = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear buffer and counters
|
||||
_head = 0;
|
||||
_count = 0;
|
||||
_total_written = 0;
|
||||
|
||||
_should_run = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LogWriterFile::LogFileBuffer::fsync() const
|
||||
{
|
||||
perf_begin(_perf_fsync);
|
||||
::fsync(_fd);
|
||||
perf_end(_perf_fsync);
|
||||
}
|
||||
|
||||
ssize_t LogWriterFile::LogFileBuffer::write_to_file(const void *buffer, size_t size, bool call_fsync) const
|
||||
{
|
||||
perf_begin(_perf_write);
|
||||
ssize_t ret = ::write(_fd, buffer, size);
|
||||
perf_end(_perf_write);
|
||||
|
||||
if (call_fsync) {
|
||||
fsync();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LogWriterFile::LogFileBuffer::close_file()
|
||||
{
|
||||
_head = 0;
|
||||
_count = 0;
|
||||
|
||||
if (_fd >= 0) {
|
||||
int res = close(_fd);
|
||||
_fd = -1;
|
||||
|
||||
if (res) {
|
||||
PX4_WARN("closing log file failed (%i)", errno);
|
||||
|
||||
} else {
|
||||
PX4_INFO("closed logfile, bytes written: %zu", _total_written);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,19 @@ namespace px4
|
||||
namespace logger
|
||||
{
|
||||
|
||||
/**
|
||||
* @enum LogType
|
||||
* Defines different log (file) types
|
||||
*/
|
||||
enum class LogType {
|
||||
Full = 0, //!< Normal, full size log
|
||||
Mission, //!< reduced mission log (e.g. for geotagging)
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
const char *log_type_str(LogType type);
|
||||
|
||||
/**
|
||||
* @class LogWriterFile
|
||||
* Writes logging data to a file
|
||||
@@ -64,14 +77,14 @@ public:
|
||||
|
||||
void thread_stop();
|
||||
|
||||
void start_log(const char *filename);
|
||||
void start_log(LogType type, const char *filename);
|
||||
|
||||
void stop_log();
|
||||
void stop_log(LogType type);
|
||||
|
||||
bool is_started() const { return _should_run; }
|
||||
bool is_started(LogType type) const { return _buffers[(int)type]._should_run; }
|
||||
|
||||
/** @see LogWriter::write_message() */
|
||||
int write_message(void *ptr, size_t size, uint64_t dropout_start = 0);
|
||||
int write_message(LogType type, void *ptr, size_t size, uint64_t dropout_start = 0);
|
||||
|
||||
void lock()
|
||||
{
|
||||
@@ -88,19 +101,19 @@ public:
|
||||
pthread_cond_broadcast(&_cv);
|
||||
}
|
||||
|
||||
size_t get_total_written() const
|
||||
size_t get_total_written(LogType type) const
|
||||
{
|
||||
return _total_written;
|
||||
return _buffers[(int)type].total_written();
|
||||
}
|
||||
|
||||
size_t get_buffer_size() const
|
||||
size_t get_buffer_size(LogType type) const
|
||||
{
|
||||
return _buffer_size;
|
||||
return _buffers[(int)type].buffer_size();
|
||||
}
|
||||
|
||||
size_t get_buffer_fill_count() const
|
||||
size_t get_buffer_fill_count(LogType type) const
|
||||
{
|
||||
return _count;
|
||||
return _buffers[(int)type].count();
|
||||
}
|
||||
|
||||
void set_need_reliable_transfer(bool need_reliable)
|
||||
@@ -120,13 +133,6 @@ private:
|
||||
|
||||
void run();
|
||||
|
||||
size_t get_read_ptr(void **ptr, bool *is_part);
|
||||
|
||||
void mark_read(size_t n)
|
||||
{
|
||||
_count -= n;
|
||||
}
|
||||
|
||||
/**
|
||||
* permanently store the ulog file name for the hardfault crash handler, so that it can
|
||||
* append crash logs to the last ulog file.
|
||||
@@ -138,30 +144,62 @@ private:
|
||||
/**
|
||||
* write w/o waiting/blocking
|
||||
*/
|
||||
int write(void *ptr, size_t size, uint64_t dropout_start);
|
||||
|
||||
/**
|
||||
* Write to the buffer but assuming there is enough space
|
||||
*/
|
||||
inline void write_no_check(void *ptr, size_t size);
|
||||
int write(LogType type, void *ptr, size_t size, uint64_t dropout_start);
|
||||
|
||||
/* 512 didn't seem to work properly, 4096 should match the FAT cluster size */
|
||||
static constexpr size_t _min_write_chunk = 4096;
|
||||
|
||||
int _fd = -1;
|
||||
uint8_t *_buffer = nullptr;
|
||||
const size_t _buffer_size;
|
||||
size_t _head = 0; ///< next position to write to
|
||||
size_t _count = 0; ///< number of bytes in _buffer to be written
|
||||
size_t _total_written = 0;
|
||||
bool _should_run = false;
|
||||
bool _running = false;
|
||||
class LogFileBuffer
|
||||
{
|
||||
public:
|
||||
LogFileBuffer(size_t buffer_size, perf_counter_t perf_write, perf_counter_t perf_fsync);
|
||||
|
||||
~LogFileBuffer();
|
||||
|
||||
bool start_log(const char *filename);
|
||||
|
||||
void close_file();
|
||||
|
||||
size_t get_read_ptr(void **ptr, bool *is_part);
|
||||
|
||||
/**
|
||||
* Write to the buffer but assuming there is enough space
|
||||
*/
|
||||
inline void write_no_check(void *ptr, size_t size);
|
||||
|
||||
size_t available() const { return _buffer_size - _count; }
|
||||
|
||||
int fd() const { return _fd; }
|
||||
|
||||
inline ssize_t write_to_file(const void *buffer, size_t size, bool call_fsync) const;
|
||||
|
||||
inline void fsync() const;
|
||||
|
||||
void mark_read(size_t n) { _count -= n; _total_written += n; }
|
||||
|
||||
size_t total_written() const { return _total_written; }
|
||||
size_t buffer_size() const { return _buffer_size; }
|
||||
size_t count() const { return _count; }
|
||||
|
||||
bool _should_run = false;
|
||||
|
||||
private:
|
||||
const size_t _buffer_size;
|
||||
int _fd = -1;
|
||||
uint8_t *_buffer = nullptr;
|
||||
size_t _head = 0; ///< next position to write to
|
||||
size_t _count = 0; ///< number of bytes in _buffer to be written
|
||||
size_t _total_written = 0;
|
||||
perf_counter_t _perf_write;
|
||||
perf_counter_t _perf_fsync;
|
||||
};
|
||||
|
||||
LogFileBuffer _buffers[(int)LogType::Count];
|
||||
|
||||
bool _exit_thread = false;
|
||||
bool _need_reliable_transfer = false;
|
||||
pthread_mutex_t _mtx;
|
||||
pthread_cond_t _cv;
|
||||
perf_counter_t _perf_write;
|
||||
perf_counter_t _perf_fsync;
|
||||
pthread_t _thread = 0;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user