log_writer_file.h
5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/****************************************************************************
*
* Copyright (c) 2016 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include <px4_platform_common/defines.h>
#include <stdint.h>
#include <pthread.h>
#include <drivers/drv_hrt.h>
#include <perf/perf_counter.h>
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
*/
class LogWriterFile
{
public:
LogWriterFile(size_t buffer_size);
~LogWriterFile();
bool init();
/**
* start the thread
* @return 0 on success, error number otherwise (@see pthread_create)
*/
int thread_start();
void thread_stop();
void start_log(LogType type, const char *filename);
void stop_log(LogType type);
bool is_started(LogType type) const { return _buffers[(int)type]._should_run; }
/** @see LogWriter::write_message() */
int write_message(LogType type, void *ptr, size_t size, uint64_t dropout_start = 0);
void lock()
{
pthread_mutex_lock(&_mtx);
}
void unlock()
{
pthread_mutex_unlock(&_mtx);
}
void notify()
{
pthread_cond_broadcast(&_cv);
}
size_t get_total_written(LogType type) const
{
return _buffers[(int)type].total_written();
}
size_t get_buffer_size(LogType type) const
{
return _buffers[(int)type].buffer_size();
}
size_t get_buffer_fill_count(LogType type) const
{
return _buffers[(int)type].count();
}
void set_need_reliable_transfer(bool need_reliable)
{
_need_reliable_transfer = need_reliable;
}
bool need_reliable_transfer() const
{
return _need_reliable_transfer;
}
pthread_t thread_id() const { return _thread; }
private:
static void *run_helper(void *);
void run();
/**
* permanently store the ulog file name for the hardfault crash handler, so that it can
* append crash logs to the last ulog file.
* @param log_file path to the log file
* @return 0 on success, <0 errno otherwise
*/
int hardfault_store_filename(const char *log_file);
/**
* write w/o waiting/blocking
*/
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;
class LogFileBuffer
{
public:
LogFileBuffer(size_t log_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;
pthread_t _thread = 0;
};
}
}