3 #include <boost/algorithm/string.hpp> 15 template <
typename Func>
16 double measure_sec(Func f)
18 auto tic = std::chrono::high_resolution_clock::now();
22 auto toc = std::chrono::high_resolution_clock::now();
24 return std::chrono::duration_cast<std::chrono::nanoseconds>(toc-tic).count()*1e-9;
48 enable_compression(false),
49 default_buffer_size(1e4)
56 std::string get_file_extension(std::string file)
58 std::vector<std::string> token_list;
59 boost::split(token_list, file, [](
char c){
return c ==
'.';});
61 if(token_list.size() > 1)
63 return token_list.back();
69 std::string date_time_as_string()
74 memset(buffer, 0, 80*
sizeof(buffer[0]));
77 timeinfo = localtime(&rawtime);
79 strftime(buffer, 80,
"%Y_%m_%d__%H_%M_%S", timeinfo);
81 return std::string(buffer);
86 MatLogger2::MatLogger2(std::string file,
Options opt):
93 std::string extension = get_file_extension(file);
97 _file_name +=
"__" + date_time_as_string() +
".mat";
99 else if(extension !=
"mat")
101 throw std::invalid_argument(
"MAT-file name should either have .mat \ 102 extension, or no extension at all");
106 _backend = Backend::MakeInstance(
"matio");
110 throw std::runtime_error(
"MatLogger2: unable to create backend");
113 if(!_backend->init(_file_name, _opt.enable_compression))
115 throw std::runtime_error(
"MatLogger2: unable to initialize backend");
131 std::lock_guard<MutexType> lock(_vars_mutex->get());
135 p.second.set_on_block_available(callback);
138 _on_block_available = callback;
143 std::lock_guard<MutexType> lock(_vars_mutex->get());
147 p.second.set_buffer_mode(buffer_mode);
150 _buffer_mode = buffer_mode;
156 if(buffer_size == -1)
158 buffer_size = _opt.default_buffer_size;
161 if(!(rows > 0 && cols > 0 && buffer_size > 0))
163 fprintf(stderr,
"Unable to create variable '%s': invalid parameters \ 164 (rows=%d, cols=%d, buf_size=%d)\n",
165 var_name.c_str(), rows, cols, buffer_size);
169 std::lock_guard<MutexType> lock(_vars_mutex->get());
172 auto it = _vars.find(var_name);
174 if(it != _vars.end())
176 fprintf(stderr,
"Variable '%s' already exists\n", var_name.c_str());
184 printf(
"Created variable '%s' (%d blocks, %d elem each)\n",
188 _vars.emplace(std::piecewise_construct,
189 std::forward_as_tuple(var_name),
190 std::forward_as_tuple(var_name, rows, cols, block_size));
194 _vars.at(var_name).set_on_block_available(_on_block_available);
195 _vars.at(var_name).set_buffer_mode(_buffer_mode);
203 Eigen::Matrix<double, 1, 1> data(scalar);
205 VariableBuffer * vbuf = find_or_create(var_name, data.rows(), data.cols());
207 return vbuf && vbuf->
add_elem(data);
217 std::lock_guard<MutexType> lock(_vars_mutex->get());
220 Eigen::MatrixXd block;
224 while(p.second.read_block(block, valid_elems))
227 auto dims = p.second.get_dimension();
232 bool is_vector =
false;
246 slices = valid_elems;
251 _backend->write(p.second.get_name().c_str(),
256 bytes += block.rows() * valid_elems *
sizeof(double);
267 auto it = _vars.find(var_name);
270 if(it != _vars.end())
272 return &(it->second);
276 if(!
create(var_name, rows, cols))
282 return find_or_create(var_name, rows, cols);
287 bool MatLogger2::flush_to_queue_all()
292 ret = p.second.flush_to_queue() && ret;
311 while(!flush_to_queue_all())
319 printf(
"Flushed all data for file '%s'\n", _file_name.c_str());
326 #define ADD_EXPLICIT_INSTANTIATION(EigenType) \ 327 template bool MatLogger2::add(const std::string&, const Eigen::MatrixBase<EigenType>&); \ 328 template bool VariableBuffer::add_elem(const Eigen::MatrixBase<EigenType>&); \ 329 template bool VariableBuffer::BufferBlock::add(const Eigen::MatrixBase<EigenType>&); 331 #define ADD_EXPLICIT_INSTANTIATION_STD_VECTOR(Scalar) \ 332 template bool MatLogger2::add(const std::string&, const std::vector<Scalar>&); \ 335 template <
typename Scalar>
338 template <
typename Scalar>
339 using MapX = Eigen::Map<Eigen::Matrix<Scalar, -1, 1>>;
~MatLogger2()
Destructor flushes all buffers to disk, then releases any resource connected with the underlying MAT-...
Mode
Enum for specifying the type of buffer.
bool add_elem(const Eigen::MatrixBase< Derived > &data)
Add an element to the buffer.
Options get_options() const
Returns the MatLogger2::Options struct associated with this object.
void set_on_data_available_callback(VariableBuffer::CallbackType callback)
Set the callback that is invoked whenever new data is available for writing to disk.
Eigen::Map< Eigen::Matrix< Scalar,-1, 1 >> MapX
#define ADD_EXPLICIT_INSTANTIATION(EigenType)
const std::string & get_filename() const
Returns the full path associated with this logger object.
#define ADD_EXPLICIT_INSTANTIATION_STD_VECTOR(Scalar)
The VariableBuffer class implements a memory buffer for a single logged variable. ...
bool add(const std::string &var_name, const Eigen::MatrixBase< Derived > &data)
Add an element to an existing variable.
Eigen::Matrix< Scalar, 6, 1 > Vector6
std::function< void(BufferInfo)> CallbackType
const std::string & get_name() const
bool create(const std::string &var_name, int rows, int cols=1, int buffer_size=-1)
Create a logged variable from its name as it will appear inside the MAT-file, dimensions, and buffer size.
void set_buffer_mode(VariableBuffer::Mode buffer_mode)
Set whether this buffer should be treated as a (possibly dual threaded) producer-consumer queue...
int flush_available_data()
Flush available data to disk.