-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcommon_header.cpp
More file actions
127 lines (107 loc) · 5.1 KB
/
common_header.cpp
File metadata and controls
127 lines (107 loc) · 5.1 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
// Copyright (c) 2023-2024 Percona and/or its affiliates.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 2.0,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License, version 2.0, for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "binsrv/event/common_header.hpp"
#include <ostream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <boost/align/align_up.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
#include <boost/date_time/posix_time/time_formatters.hpp>
#include "binsrv/event/code_type.hpp"
#include "binsrv/event/common_header_flag_type.hpp"
#include "util/byte_span_extractors.hpp"
#include "util/byte_span_fwd.hpp"
#include "util/conversion_helpers.hpp"
#include "util/exception_location_helpers.hpp"
#include "util/flag_set.hpp"
namespace binsrv::event {
common_header::common_header(util::const_byte_span portion) {
// TODO: rework with direct member initialization
/*
https://github.com/mysql/mysql-server/blob/mysql-8.0.43/libbinlogevents/src/binlog_event.cpp#L198
https://github.com/mysql/mysql-server/blob/mysql-8.4.6/libs/mysql/binlog/event/binlog_event.cpp#L242
The first 19 bytes in the header is as follows:
+============================================+
| member_variable offset : len |
+============================================+
| when.tv_sec 0 : 4 |
+--------------------------------------------+
| type_code EVENT_TYPE_OFFSET(4) : 1 |
+--------------------------------------------+
| server_id SERVER_ID_OFFSET(5) : 4 |
+--------------------------------------------+
| data_written EVENT_LEN_OFFSET(9) : 4 |
+--------------------------------------------+
| log_pos LOG_POS_OFFSET(13) : 4 |
+--------------------------------------------+
| flags FLAGS_OFFSET(17) : 2 |
+--------------------------------------------+
| extra_headers 19 : x-19|
+============================================+
*/
// TODO: initialize size_in_bytes directly based on the sum of fields
// widths instead of this static_assert
static_assert(sizeof timestamp_ + sizeof type_code_ + sizeof server_id_ +
sizeof event_size_ + sizeof next_event_position_ +
sizeof flags_ ==
size_in_bytes,
"mismatch in common_header::size_in_bytes");
// make sure we did OK with data members reordering
static_assert(sizeof *this == boost::alignment::align_up(
size_in_bytes, alignof(decltype(*this))),
"inefficient data member reordering in common_header");
if (std::size(portion) != size_in_bytes) {
util::exception_location().raise<std::invalid_argument>(
"invalid event common header length");
}
auto remainder = portion;
util::extract_fixed_int_from_byte_span(remainder, timestamp_);
util::extract_fixed_int_from_byte_span(remainder, type_code_);
util::extract_fixed_int_from_byte_span(remainder, server_id_);
util::extract_fixed_int_from_byte_span(remainder, event_size_);
util::extract_fixed_int_from_byte_span(remainder, next_event_position_);
util::extract_fixed_int_from_byte_span(remainder, flags_);
if (get_type_code_raw() >= util::enum_to_index(code_type::delimiter) ||
to_string_view(get_type_code()).empty()) {
util::exception_location().raise<std::logic_error>(
"invalid event code in event header");
}
// TODO: check if flags are valid (all the bits have corresponding enum)
}
[[nodiscard]] std::string common_header::get_readable_timestamp() const {
return boost::posix_time::to_simple_string(
boost::posix_time::from_time_t(get_timestamp()));
}
[[nodiscard]] std::string_view
common_header::get_readable_type_code() const noexcept {
return to_string_view(get_type_code());
}
[[nodiscard]] common_header_flag_set common_header::get_flags() const noexcept {
return common_header_flag_set{get_flags_raw()};
}
[[nodiscard]] std::string common_header::get_readable_flags() const {
return to_string(get_flags());
}
std::ostream &operator<<(std::ostream &output, const common_header &obj) {
return output << "ts: " << obj.get_readable_timestamp()
<< ", type: " << obj.get_readable_type_code()
<< ", server id: " << obj.get_server_id_raw()
<< ", event size: " << obj.get_event_size_raw()
<< ", next event position: "
<< obj.get_next_event_position_raw()
<< ", flags: " << obj.get_readable_flags();
}
} // namespace binsrv::event