1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "journal/Entry.h"
5 #include "include/encoding.h"
6 #include "include/stringify.h"
7 #include "common/Formatter.h"
10 #define dout_subsys ceph_subsys_journaler
12 #define dout_prefix *_dout << "Entry: " << this << " "
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
21 } // anonymous namespace
23 uint32_t Entry::get_fixed_size() {
24 return HEADER_FIXED_SIZE + REMAINDER_FIXED_SIZE;
27 void Entry::encode(bufferlist &bl) const {
29 ::encode(preamble, data_bl);
30 ::encode(static_cast<uint8_t>(1), data_bl);
31 ::encode(m_entry_tid, data_bl);
32 ::encode(m_tag_tid, data_bl);
33 ::encode(m_data, data_bl);
35 uint32_t crc = data_bl.crc32c(0);
36 uint32_t bl_offset = bl.length();
37 bl.claim_append(data_bl);
39 assert(get_fixed_size() + m_data.length() + bl_offset == bl.length());
42 void Entry::decode(bufferlist::iterator &iter) {
43 uint32_t start_offset = iter.get_off();
45 ::decode(bl_preamble, iter);
46 if (bl_preamble != preamble) {
47 throw buffer::malformed_input("incorrect preamble: " +
48 stringify(bl_preamble));
52 ::decode(version, iter);
54 throw buffer::malformed_input("unknown version: " + stringify(version));
57 ::decode(m_entry_tid, iter);
58 ::decode(m_tag_tid, iter);
59 ::decode(m_data, iter);
60 uint32_t end_offset = iter.get_off();
66 data_bl.substr_of(iter.get_bl(), start_offset, end_offset - start_offset);
67 uint32_t actual_crc = data_bl.crc32c(0);
68 if (crc != actual_crc) {
69 throw buffer::malformed_input("crc mismatch: " + stringify(crc) +
70 " != " + stringify(actual_crc));
74 void Entry::dump(Formatter *f) const {
75 f->dump_unsigned("tag_tid", m_tag_tid);
76 f->dump_unsigned("entry_tid", m_entry_tid);
78 std::stringstream data;
80 f->dump_string("data", data.str());
83 bool Entry::is_readable(bufferlist::iterator iter, uint32_t *bytes_needed) {
84 uint32_t start_off = iter.get_off();
85 if (iter.get_remaining() < HEADER_FIXED_SIZE) {
86 *bytes_needed = HEADER_FIXED_SIZE - iter.get_remaining();
90 ::decode(bl_preamble, iter);
91 if (bl_preamble != preamble) {
95 iter.advance(HEADER_FIXED_SIZE - sizeof(bl_preamble));
97 if (iter.get_remaining() < sizeof(uint32_t)) {
98 *bytes_needed = sizeof(uint32_t) - iter.get_remaining();
102 ::decode(data_size, iter);
104 if (iter.get_remaining() < data_size) {
105 *bytes_needed = data_size - iter.get_remaining();
108 iter.advance(data_size);
109 uint32_t end_off = iter.get_off();
111 if (iter.get_remaining() < sizeof(uint32_t)) {
112 *bytes_needed = sizeof(uint32_t) - iter.get_remaining();
117 crc_bl.substr_of(iter.get_bl(), start_off, end_off - start_off);
122 if (crc != crc_bl.crc32c(0)) {
128 void Entry::generate_test_instances(std::list<Entry *> &o) {
129 o.push_back(new Entry(1, 123, bufferlist()));
133 o.push_back(new Entry(2, 123, bl));
136 bool Entry::operator==(const Entry& rhs) const {
137 return (m_tag_tid == rhs.m_tag_tid && m_entry_tid == rhs.m_entry_tid &&
138 const_cast<bufferlist&>(m_data).contents_equal(
139 const_cast<bufferlist&>(rhs.m_data)));
142 std::ostream &operator<<(std::ostream &os, const Entry &entry) {
143 os << "Entry[tag_tid=" << entry.get_tag_tid() << ", "
144 << "entry_tid=" << entry.get_entry_tid() << ", "
145 << "data size=" << entry.get_data().length() << "]";
149 } // namespace journal