1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #pragma once
8 
9 #include "td/utils/buffer.h"
10 #include "td/utils/common.h"
11 #include "td/utils/format.h"
12 #include "td/utils/Slice.h"
13 #include "td/utils/SliceBuilder.h"
14 #include "td/utils/Status.h"
15 #include "td/utils/Storer.h"
16 #include "td/utils/StorerBase.h"
17 #include "td/utils/StringBuilder.h"
18 
19 namespace td {
20 
21 struct EmptyStorerImpl {
EmptyStorerImplEmptyStorerImpl22   EmptyStorerImpl() {
23   }
24 
25   template <class StorerT>
storeEmptyStorerImpl26   void store(StorerT &storer) const {
27   }
28 };
29 
EmptyStorer()30 inline auto EmptyStorer() {
31   static const EmptyStorerImpl impl;
32   return create_default_storer(impl);
33 }
34 
35 struct BinlogDebugInfo {
36   BinlogDebugInfo() = default;
BinlogDebugInfoBinlogDebugInfo37   BinlogDebugInfo(const char *file, int line) : file(file), line(line) {
38   }
39   const char *file{""};
40   int line{0};
41 };
42 
43 inline StringBuilder &operator<<(StringBuilder &sb, const BinlogDebugInfo &info) {
44   if (info.line == 0) {
45     return sb;
46   }
47   return sb << "[" << info.file << ":" << info.line << "]";
48 }
49 
50 struct BinlogEvent {
51   static constexpr size_t MAX_SIZE = 1 << 24;
52   static constexpr size_t HEADER_SIZE = 4 + 8 + 4 + 4 + 8;
53   static constexpr size_t TAIL_SIZE = 4;
54   static constexpr size_t MIN_SIZE = HEADER_SIZE + TAIL_SIZE;
55 
56   int64 offset_;
57 
58   uint32 size_;
59   uint64 id_;
60   int32 type_;  // type can be merged with flags
61   int32 flags_;
62   uint64 extra_;
63   MutableSlice data_;
64   uint32 crc32_;
65 
66   BufferSlice raw_event_;
67 
68   BinlogDebugInfo debug_info_;
69 
70   enum ServiceTypes { Header = -1, Empty = -2, AesCtrEncryption = -3, NoEncryption = -4 };
71   enum Flags { Rewrite = 1, Partial = 2 };
72 
clearBinlogEvent73   void clear() {
74     raw_event_ = BufferSlice();
75   }
emptyBinlogEvent76   bool empty() const {
77     return raw_event_.empty();
78   }
cloneBinlogEvent79   BinlogEvent clone() const {
80     BinlogEvent result;
81     result.debug_info_ = BinlogDebugInfo{__FILE__, __LINE__};
82     result.init(raw_event_.clone()).ensure();
83     return result;
84   }
85 
data_as_buffer_sliceBinlogEvent86   BufferSlice data_as_buffer_slice() const {
87     return raw_event_.from_slice(data_);
88   }
89 
90   BinlogEvent() = default;
91   //explicit BinlogEvent(BufferSlice &&raw_event) {
92   //init(std::move(raw_event), false).ensure();
93   //}
BinlogEventBinlogEvent94   BinlogEvent(BufferSlice &&raw_event, BinlogDebugInfo info) {
95     debug_info_ = info;
96     init(std::move(raw_event), false).ensure();
97   }
98 
99   Status init(BufferSlice &&raw_event, bool check_crc = true) TD_WARN_UNUSED_RESULT;
100 
101   static BufferSlice create_raw(uint64 id, int32 type, int32 flags, const Storer &storer);
102 
public_to_stringBinlogEvent103   std::string public_to_string() const {
104     return PSTRING() << "LogEvent[" << tag("id", format::as_hex(id_)) << tag("type", type_) << tag("flags", flags_)
105                      << tag("data", data_.size()) << "]" << debug_info_;
106   }
107 
108   Status validate() const;
109 
110   void realloc();
111 };
112 
113 inline StringBuilder &operator<<(StringBuilder &sb, const BinlogEvent &event) {
114   return sb << "LogEvent[" << tag("id", format::as_hex(event.id_)) << tag("type", event.type_)
115             << tag("flags", event.flags_) << tag("data", format::as_hex_dump<4>(event.data_)) << "]"
116             << event.debug_info_;
117 }
118 
119 }  // namespace td
120