]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "journal/Entry.h" | |
5 | #include "include/encoding.h" | |
6 | #include "include/stringify.h" | |
7 | #include "common/Formatter.h" | |
8 | #include <strstream> | |
9 | ||
10 | #define dout_subsys ceph_subsys_journaler | |
11 | #undef dout_prefix | |
12 | #define dout_prefix *_dout << "Entry: " << this << " " | |
13 | ||
14 | namespace journal { | |
15 | ||
16 | namespace { | |
17 | ||
18 | const uint32_t HEADER_FIXED_SIZE = 25; /// preamble, version, entry tid, tag id | |
19 | const uint32_t REMAINDER_FIXED_SIZE = 8; /// data size, crc | |
20 | ||
21 | } // anonymous namespace | |
22 | ||
23 | uint32_t Entry::get_fixed_size() { | |
24 | return HEADER_FIXED_SIZE + REMAINDER_FIXED_SIZE; | |
25 | } | |
26 | ||
27 | void Entry::encode(bufferlist &bl) const { | |
11fdf7f2 | 28 | using ceph::encode; |
7c673cae | 29 | bufferlist data_bl; |
11fdf7f2 TL |
30 | encode(preamble, data_bl); |
31 | encode(static_cast<uint8_t>(1), data_bl); | |
32 | encode(m_entry_tid, data_bl); | |
33 | encode(m_tag_tid, data_bl); | |
34 | encode(m_data, data_bl); | |
7c673cae FG |
35 | |
36 | uint32_t crc = data_bl.crc32c(0); | |
37 | uint32_t bl_offset = bl.length(); | |
38 | bl.claim_append(data_bl); | |
11fdf7f2 TL |
39 | encode(crc, bl); |
40 | ceph_assert(get_fixed_size() + m_data.length() + bl_offset == bl.length()); | |
7c673cae FG |
41 | } |
42 | ||
11fdf7f2 TL |
43 | void Entry::decode(bufferlist::const_iterator &iter) { |
44 | using ceph::decode; | |
7c673cae FG |
45 | uint32_t start_offset = iter.get_off(); |
46 | uint64_t bl_preamble; | |
11fdf7f2 | 47 | decode(bl_preamble, iter); |
7c673cae FG |
48 | if (bl_preamble != preamble) { |
49 | throw buffer::malformed_input("incorrect preamble: " + | |
50 | stringify(bl_preamble)); | |
51 | } | |
52 | ||
53 | uint8_t version; | |
11fdf7f2 | 54 | decode(version, iter); |
7c673cae FG |
55 | if (version != 1) { |
56 | throw buffer::malformed_input("unknown version: " + stringify(version)); | |
57 | } | |
58 | ||
11fdf7f2 TL |
59 | decode(m_entry_tid, iter); |
60 | decode(m_tag_tid, iter); | |
61 | decode(m_data, iter); | |
7c673cae FG |
62 | uint32_t end_offset = iter.get_off(); |
63 | ||
64 | uint32_t crc; | |
11fdf7f2 | 65 | decode(crc, iter); |
7c673cae FG |
66 | |
67 | bufferlist data_bl; | |
68 | data_bl.substr_of(iter.get_bl(), start_offset, end_offset - start_offset); | |
69 | uint32_t actual_crc = data_bl.crc32c(0); | |
70 | if (crc != actual_crc) { | |
71 | throw buffer::malformed_input("crc mismatch: " + stringify(crc) + | |
72 | " != " + stringify(actual_crc)); | |
73 | } | |
74 | } | |
75 | ||
76 | void Entry::dump(Formatter *f) const { | |
77 | f->dump_unsigned("tag_tid", m_tag_tid); | |
78 | f->dump_unsigned("entry_tid", m_entry_tid); | |
79 | ||
80 | std::stringstream data; | |
81 | m_data.hexdump(data); | |
82 | f->dump_string("data", data.str()); | |
83 | } | |
84 | ||
11fdf7f2 TL |
85 | bool Entry::is_readable(bufferlist::const_iterator iter, uint32_t *bytes_needed) { |
86 | using ceph::decode; | |
7c673cae FG |
87 | uint32_t start_off = iter.get_off(); |
88 | if (iter.get_remaining() < HEADER_FIXED_SIZE) { | |
89 | *bytes_needed = HEADER_FIXED_SIZE - iter.get_remaining(); | |
90 | return false; | |
91 | } | |
92 | uint64_t bl_preamble; | |
11fdf7f2 | 93 | decode(bl_preamble, iter); |
7c673cae FG |
94 | if (bl_preamble != preamble) { |
95 | *bytes_needed = 0; | |
96 | return false; | |
97 | } | |
98 | iter.advance(HEADER_FIXED_SIZE - sizeof(bl_preamble)); | |
99 | ||
100 | if (iter.get_remaining() < sizeof(uint32_t)) { | |
101 | *bytes_needed = sizeof(uint32_t) - iter.get_remaining(); | |
102 | return false; | |
103 | } | |
104 | uint32_t data_size; | |
11fdf7f2 | 105 | decode(data_size, iter); |
7c673cae FG |
106 | |
107 | if (iter.get_remaining() < data_size) { | |
108 | *bytes_needed = data_size - iter.get_remaining(); | |
109 | return false; | |
110 | } | |
111 | iter.advance(data_size); | |
112 | uint32_t end_off = iter.get_off(); | |
113 | ||
114 | if (iter.get_remaining() < sizeof(uint32_t)) { | |
115 | *bytes_needed = sizeof(uint32_t) - iter.get_remaining(); | |
116 | return false; | |
117 | } | |
118 | ||
119 | bufferlist crc_bl; | |
120 | crc_bl.substr_of(iter.get_bl(), start_off, end_off - start_off); | |
121 | ||
122 | *bytes_needed = 0; | |
123 | uint32_t crc; | |
11fdf7f2 | 124 | decode(crc, iter); |
7c673cae FG |
125 | if (crc != crc_bl.crc32c(0)) { |
126 | return false; | |
127 | } | |
128 | return true; | |
129 | } | |
130 | ||
131 | void Entry::generate_test_instances(std::list<Entry *> &o) { | |
132 | o.push_back(new Entry(1, 123, bufferlist())); | |
133 | ||
134 | bufferlist bl; | |
135 | bl.append("data"); | |
136 | o.push_back(new Entry(2, 123, bl)); | |
137 | } | |
138 | ||
139 | bool Entry::operator==(const Entry& rhs) const { | |
140 | return (m_tag_tid == rhs.m_tag_tid && m_entry_tid == rhs.m_entry_tid && | |
141 | const_cast<bufferlist&>(m_data).contents_equal( | |
142 | const_cast<bufferlist&>(rhs.m_data))); | |
143 | } | |
144 | ||
145 | std::ostream &operator<<(std::ostream &os, const Entry &entry) { | |
146 | os << "Entry[tag_tid=" << entry.get_tag_tid() << ", " | |
147 | << "entry_tid=" << entry.get_entry_tid() << ", " | |
148 | << "data size=" << entry.get_data().length() << "]"; | |
149 | return os; | |
150 | } | |
151 | ||
152 | } // namespace journal |