aboutsummaryrefslogtreecommitdiffhomepage
path: root/tddb/td/db/binlog/BinlogEvent.h
blob: 9dd5499a4b7c9d0a7b4ae5621e6bc5e8fa0a6df2 (plain)
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
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once

#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/format.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/Storer.h"
#include "td/utils/StorerBase.h"
#include "td/utils/StringBuilder.h"

namespace td {

struct EmptyStorerImpl {
  EmptyStorerImpl() {
  }

  template <class StorerT>
  void store(StorerT &storer) const {
  }
};

inline auto EmptyStorer() {
  static const EmptyStorerImpl impl;
  return create_default_storer(impl);
}

struct BinlogDebugInfo {
  BinlogDebugInfo() = default;
  BinlogDebugInfo(const char *file, int line) : file(file), line(line) {
  }
  const char *file{""};
  int line{0};
};

inline StringBuilder &operator<<(StringBuilder &sb, const BinlogDebugInfo &info) {
  if (info.line == 0) {
    return sb;
  }
  return sb << "[" << info.file << ":" << info.line << "]";
}

struct BinlogEvent {
  static constexpr size_t MAX_SIZE = 1 << 24;
  static constexpr size_t HEADER_SIZE = 4 + 8 + 4 + 4 + 8;
  static constexpr size_t TAIL_SIZE = 4;
  static constexpr size_t MIN_SIZE = HEADER_SIZE + TAIL_SIZE;

  int64 offset_;

  uint32 size_;
  uint64 id_;
  int32 type_;  // type can be merged with flags
  int32 flags_;
  uint64 extra_;
  uint32 crc32_;

  BufferSlice raw_event_;

  BinlogDebugInfo debug_info_;

  enum ServiceTypes { Header = -1, Empty = -2, AesCtrEncryption = -3, NoEncryption = -4 };
  enum Flags { Rewrite = 1, Partial = 2 };

  Slice get_data() const;

  void clear() {
    raw_event_ = BufferSlice();
  }
  bool empty() const {
    return raw_event_.empty();
  }
  BinlogEvent clone() const {
    BinlogEvent result;
    result.debug_info_ = BinlogDebugInfo{__FILE__, __LINE__};
    result.init(raw_event_.clone()).ensure();
    return result;
  }

  BufferSlice data_as_buffer_slice() const {
    return raw_event_.from_slice(get_data());
  }

  BinlogEvent() = default;
  //explicit BinlogEvent(BufferSlice &&raw_event) {
  //init(std::move(raw_event), false).ensure();
  //}
  BinlogEvent(BufferSlice &&raw_event, BinlogDebugInfo info) {
    debug_info_ = info;
    init(std::move(raw_event), false).ensure();
  }

  Status init(BufferSlice &&raw_event, bool check_crc = true) TD_WARN_UNUSED_RESULT;

  static BufferSlice create_raw(uint64 id, int32 type, int32 flags, const Storer &storer);

  std::string public_to_string() const {
    return PSTRING() << "LogEvent[" << tag("id", format::as_hex(id_)) << tag("type", type_) << tag("flags", flags_)
                     << tag("data", get_data().size()) << "]" << debug_info_;
  }

  Status validate() const;

  void realloc();
};

inline StringBuilder &operator<<(StringBuilder &sb, const BinlogEvent &event) {
  return sb << "LogEvent[" << tag("id", format::as_hex(event.id_)) << tag("type", event.type_)
            << tag("flags", event.flags_) << tag("data", format::as_hex_dump<4>(event.get_data())) << "]"
            << event.debug_info_;
}

}  // namespace td