Goby3  3.1.4
2024.02.22
log_entry.h
Go to the documentation of this file.
1 // Copyright 2017-2021:
2 // GobySoft, LLC (2013-)
3 // Community contributors (see AUTHORS file)
4 // File authors:
5 // Toby Schneider <toby@gobysoft.org>
6 //
7 //
8 // This file is part of the Goby Underwater Autonomy Project Libraries
9 // ("The Goby Libraries").
10 //
11 // The Goby Libraries are free software: you can redistribute them and/or modify
12 // them under the terms of the GNU Lesser General Public License as published by
13 // the Free Software Foundation, either version 2.1 of the License, or
14 // (at your option) any later version.
15 //
16 // The Goby Libraries are distributed in the hope that they will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public License
22 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
23 
24 #ifndef GOBY_MIDDLEWARE_LOG_LOG_ENTRY_H
25 #define GOBY_MIDDLEWARE_LOG_LOG_ENTRY_H
26 
27 #include <boost/bimap.hpp> // for bimap
28 #include <boost/crc.hpp> // for crc_32_type
29 #include <cstdint> // for uint16_t, uint32_t, uint64_t, uin...
30 #include <functional> // for function
31 #include <istream> // for ostream, istream, basic_ostream::...
32 #include <limits> // for numeric_limits
33 #include <map> // for map
34 #include <stdexcept> // for runtime_error
35 #include <string> // for string, allocator, operator+, ope...
36 #include <utility> // for move
37 #include <vector> // for vector
38 
39 #include "goby/middleware/group.h" // for Group, DynamicGroup
40 #include "goby/time/system_clock.h"
41 
42 namespace goby
43 {
44 namespace middleware
45 {
46 namespace log
47 {
48 class LogException : public std::runtime_error
49 {
50  public:
51  LogException(const std::string& s) : std::runtime_error(s){};
52 };
53 
54 template <int Bytes> struct uint
55 {
56 };
57 template <> struct uint<1>
58 {
59  using type = std::uint8_t;
60 };
61 template <> struct uint<2>
62 {
63  using type = std::uint16_t;
64 };
65 template <> struct uint<4>
66 {
67  using type = std::uint32_t;
68 };
69 template <> struct uint<8>
70 {
71  using type = std::uint64_t;
72 };
73 
74 struct LogFilter
75 {
76  int scheme;
77  std::string group;
78  std::string type;
79 };
80 
81 inline bool operator<(const LogFilter& a, const LogFilter& b)
82 {
83  if (a.scheme == b.scheme)
84  {
85  if (a.group == b.group)
86  return a.type < b.type;
87  else
88  return a.group < b.group;
89  }
90  else
91  {
92  return a.scheme < b.scheme;
93  }
94 }
95 
96 //inline bool operator==(const LogFilter& a, const LogFilter& b)
97 //{ return a.scheme == b.scheme && a.group == b.group && a.type == b.type; }
98 
99 class LogEntry
100 {
101  public:
102  static constexpr int magic_bytes_{4};
103  static constexpr int size_bytes_{4};
104  static constexpr int scheme_bytes_{2};
105  static constexpr int group_bytes_{2};
106  static constexpr int type_bytes_{2};
107  static constexpr int timestamp_bytes_{8};
108  static constexpr int crc_bytes_{4};
111 
112  static constexpr int version_bytes_{4};
113  static constexpr int compiled_current_version{3};
114  static int current_version_;
115  // "invalid_version" until version is read or written
117  static constexpr decltype(version_) invalid_version{0};
118 
119  static std::map<int, std::function<void(const std::string& type)>> new_type_hook;
120  static std::map<int, std::function<void(const Group& group)>> new_group_hook;
121 
122  static std::map<LogFilter, std::function<void(const std::vector<unsigned char>& data)>>
124 
125  public:
126  LogEntry(std::vector<unsigned char> data, int scheme, std::string type, const Group& group,
128  : data_(std::move(data)),
129  scheme_(scheme),
130  type_(std::move(type)),
131  group_(std::string(group)),
132  timestamp_(std::move(timestamp))
133  {
134  }
135 
136  LogEntry() : group_("") {}
137  void parse_version(std::istream* s);
138  void parse(std::istream* s);
139 
140  // used by the unit tests to override version numbers
141  static void set_current_version(decltype(version_) version) { current_version_ = version; }
142 
143  // [GBY3][size: 4][scheme: 2][group: 2][type: 2][timestamp: 8][data][crc32: 4]
144  // if scheme == 0xFFFF what follows is not data, but the string value for the group index
145  // if scheme == 0xFFFE what follows is not data, but the string value for the group index
146  void serialize(std::ostream* s) const;
147 
148  const std::vector<unsigned char>& data() const { return data_; }
149  int scheme() const { return scheme_; }
150  const std::string& type() const { return type_; }
151  const Group& group() const { return group_; }
152  const goby::time::SystemClock::time_point& timestamp() const { return timestamp_; }
153 
154  static void reset()
155  {
156  groups_.clear();
157  types_.clear();
158  new_type_hook.clear();
159  new_group_hook.clear();
160  filter_hook.clear();
161 
162  group_index_ = 1;
163  type_index_ = 1;
166  }
167 
168  private:
169  void _serialize(std::ostream* s, uint<scheme_bytes_>::type scheme,
170  uint<group_bytes_>::type group_index, uint<type_bytes_>::type type_index,
171  const char* data, int data_size) const;
172 
173  template <typename Unsigned>
174  Unsigned read_one(std::istream* s, boost::crc_32_type* crc = nullptr)
175  {
176  auto size = std::numeric_limits<Unsigned>::digits / 8;
177  std::string str(size, '\0');
178  s->read(&str[0], size);
179  if (crc)
180  crc->process_bytes(&str[0], size);
181 
182  return string_to_netint<Unsigned>(str);
183  }
184 
185  template <typename Unsigned> std::string netint_to_string(Unsigned u) const
186  {
187  auto size = std::numeric_limits<Unsigned>::digits / 8;
188  std::string s(size, '\0');
189  for (int i = 0; i < size; ++i) s[i] = (u >> (size - (i + 1)) * 8) & 0xff;
190  return s;
191  }
192 
193  template <typename Unsigned> Unsigned string_to_netint(std::string s) const
194  {
195  Unsigned u(0);
196  std::string::size_type size = std::numeric_limits<Unsigned>::digits / 8;
197  if (s.size() > size)
198  s.erase(0, s.size() - size);
199  if (s.size() < size)
200  s.insert(0, size - s.size(), '\0');
201 
202  for (decltype(size) i = 0; i < size; ++i)
203  u |= static_cast<Unsigned>(s[i] & 0xff) << ((size - (i + 1)) * 8);
204  return u;
205  }
206 
207  private:
208  std::vector<unsigned char> data_;
210  std::string type_;
211  DynamicGroup group_;
213 
214  // map (scheme -> map (group_name -> group_index)
216  static uint<group_bytes_>::type group_index_;
217 
218  // map (scheme -> map (group_name -> group_index)
220  static uint<type_bytes_>::type type_index_;
221 
222  const std::string magic_{"GBY3"};
223 };
224 
225 } // namespace log
226 } // namespace middleware
227 } // namespace goby
228 
229 #endif
goby::time::SystemClock::now
static time_point now() noexcept
Returns the current system time unless SimulatorSettings::using_sim_time is set to true,...
Definition: system_clock.h:63
system_clock.h
goby::middleware::log::LogEntry::crc_bytes_
static constexpr int crc_bytes_
Definition: log_entry.h:108
goby
The global namespace for the Goby project.
Definition: acomms_constants.h:33
goby::middleware::log::uint
Definition: log_entry.h:54
goby::middleware::log::LogException::LogException
LogException(const std::string &s)
Definition: log_entry.h:51
goby::middleware::log::LogEntry::current_version_
static int current_version_
Definition: log_entry.h:114
group.h
goby::middleware::log::LogEntry::version_bytes_
static constexpr int version_bytes_
Definition: log_entry.h:112
goby::middleware::log::LogEntry::group
const Group & group() const
Definition: log_entry.h:151
goby::middleware::log::LogEntry::version_
static uint< version_bytes_ >::type version_
Definition: log_entry.h:116
goby::middleware::log::LogEntry::timestamp_bytes_
static constexpr int timestamp_bytes_
Definition: log_entry.h:107
goby::middleware::log::LogFilter::scheme
int scheme
Definition: log_entry.h:76
goby::middleware::log::LogEntry::scheme_group_index_
static constexpr uint< scheme_bytes_ >::type scheme_group_index_
Definition: log_entry.h:109
goby::middleware::log::LogEntry::scheme_bytes_
static constexpr int scheme_bytes_
Definition: log_entry.h:104
goby::middleware::log::LogEntry::invalid_version
static constexpr decltype(version_) invalid_version
Definition: log_entry.h:117
goby::time::str
std::string str(TimeType value=SystemClock::now< TimeType >())
Returns the provided time (or current time if omitted) as a human-readable string.
Definition: convert.h:191
goby::middleware::log::LogEntry
Definition: log_entry.h:99
goby::middleware::log::LogEntry::compiled_current_version
static constexpr int compiled_current_version
Definition: log_entry.h:113
detail::void
j template void())
Definition: json.hpp:4822
goby::middleware::log::LogFilter
Definition: log_entry.h:74
goby::middleware::log::operator<
bool operator<(const LogFilter &a, const LogFilter &b)
Definition: log_entry.h:81
goby::middleware::log::uint< 8 >::type
std::uint64_t type
Definition: log_entry.h:71
goby::middleware::log::LogEntry::type
const std::string & type() const
Definition: log_entry.h:150
goby::middleware::log::LogEntry::scheme
int scheme() const
Definition: log_entry.h:149
goby::middleware::log::LogEntry::scheme_type_index_
static constexpr uint< scheme_bytes_ >::type scheme_type_index_
Definition: log_entry.h:110
goby::middleware::log::LogEntry::new_group_hook
static std::map< int, std::function< void(const Group &group)> > new_group_hook
Definition: log_entry.h:120
goby::middleware::log::LogEntry::new_type_hook
static std::map< int, std::function< void(const std::string &type)> > new_type_hook
Definition: log_entry.h:119
goby::time::SystemClock::time_point
std::chrono::time_point< SystemClock > time_point
Definition: system_clock.h:55
goby::middleware::log::uint< 4 >::type
std::uint32_t type
Definition: log_entry.h:67
goby::middleware::log::LogEntry::timestamp
const goby::time::SystemClock::time_point & timestamp() const
Definition: log_entry.h:152
goby::middleware::log::LogFilter::type
std::string type
Definition: log_entry.h:78
goby::middleware::log::LogEntry::data
const std::vector< unsigned char > & data() const
Definition: log_entry.h:148
jwt::json::type
type
Generic JSON types used in JWTs.
Definition: jwt.h:2071
goby::middleware::log::LogEntry::set_current_version
static void set_current_version(decltype(version_) version)
Definition: log_entry.h:141
goby::middleware::log::LogEntry::magic_bytes_
static constexpr int magic_bytes_
Definition: log_entry.h:102
goby::acomms::data_size
size_t data_size(const Container &c)
Definition: dynamic_buffer.h:59
goby::middleware::Group
Class for grouping publications in the Goby middleware. Analogous to "topics" in ROS,...
Definition: group.h:58
goby::middleware::log::LogEntry::reset
static void reset()
Definition: log_entry.h:154
goby::middleware::log::LogEntry::filter_hook
static std::map< LogFilter, std::function< void(const std::vector< unsigned char > &data)> > filter_hook
Definition: log_entry.h:123
goby::middleware::log::LogEntry::group_bytes_
static constexpr int group_bytes_
Definition: log_entry.h:105
goby::middleware::log::LogEntry::LogEntry
LogEntry(std::vector< unsigned char > data, int scheme, std::string type, const Group &group, goby::time::SystemClock::time_point timestamp=goby::time::SystemClock::now())
Definition: log_entry.h:126
goby::middleware::log::uint< 2 >::type
std::uint16_t type
Definition: log_entry.h:63
goby::middleware::log::LogEntry::parse
void parse(std::istream *s)
goby::middleware::log::LogEntry::type_bytes_
static constexpr int type_bytes_
Definition: log_entry.h:106
goby::middleware::log::LogEntry::LogEntry
LogEntry()
Definition: log_entry.h:136
goby::middleware::log::LogEntry::size_bytes_
static constexpr int size_bytes_
Definition: log_entry.h:103
goby::middleware::log::LogEntry::serialize
void serialize(std::ostream *s) const
goby::middleware::log::uint< 1 >::type
std::uint8_t type
Definition: log_entry.h:59
goby::middleware::log::LogException
Definition: log_entry.h:48
goby::middleware::log::LogFilter::group
std::string group
Definition: log_entry.h:77
goby::middleware::log::LogEntry::parse_version
void parse_version(std::istream *s)
int