Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / journal / Entry.cc
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 {
28   bufferlist data_bl;
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);
34
35   uint32_t crc = data_bl.crc32c(0);
36   uint32_t bl_offset = bl.length();
37   bl.claim_append(data_bl);
38   ::encode(crc, bl);
39   assert(get_fixed_size() + m_data.length() + bl_offset == bl.length());
40 }
41
42 void Entry::decode(bufferlist::iterator &iter) {
43   uint32_t start_offset = iter.get_off();
44   uint64_t bl_preamble;
45   ::decode(bl_preamble, iter);
46   if (bl_preamble != preamble) {
47     throw buffer::malformed_input("incorrect preamble: " +
48                                   stringify(bl_preamble));
49   }
50
51   uint8_t version;
52   ::decode(version, iter);
53   if (version != 1) {
54     throw buffer::malformed_input("unknown version: " + stringify(version));
55   }
56
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();
61
62   uint32_t crc;
63   ::decode(crc, iter);
64
65   bufferlist data_bl;
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));
71   }
72 }
73
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);
77
78   std::stringstream data;
79   m_data.hexdump(data);
80   f->dump_string("data", data.str());
81 }
82
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();
87     return false;
88   }
89   uint64_t bl_preamble;
90   ::decode(bl_preamble, iter);
91   if (bl_preamble != preamble) {
92     *bytes_needed = 0;
93     return false;
94   }
95   iter.advance(HEADER_FIXED_SIZE - sizeof(bl_preamble));
96
97   if (iter.get_remaining() < sizeof(uint32_t)) {
98     *bytes_needed = sizeof(uint32_t) - iter.get_remaining();
99     return false;
100   }
101   uint32_t data_size;
102   ::decode(data_size, iter);
103
104   if (iter.get_remaining() < data_size) {
105     *bytes_needed = data_size - iter.get_remaining();
106     return false;
107   }
108   iter.advance(data_size);
109   uint32_t end_off = iter.get_off();
110
111   if (iter.get_remaining() < sizeof(uint32_t)) {
112     *bytes_needed = sizeof(uint32_t) - iter.get_remaining();
113     return false;
114   }
115
116   bufferlist crc_bl;
117   crc_bl.substr_of(iter.get_bl(), start_off, end_off - start_off);
118
119   *bytes_needed = 0;
120   uint32_t crc;
121   ::decode(crc, iter);
122   if (crc != crc_bl.crc32c(0)) {
123     return false;
124   }
125   return true;
126 }
127
128 void Entry::generate_test_instances(std::list<Entry *> &o) {
129   o.push_back(new Entry(1, 123, bufferlist()));
130
131   bufferlist bl;
132   bl.append("data");
133   o.push_back(new Entry(2, 123, bl));
134 }
135
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)));
140 }
141
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() << "]";
146   return os;
147 }
148
149 } // namespace journal