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   	  using ceph::encode;
29   	  bufferlist data_bl;
30   	  encode(preamble, data_bl);
(1) Event overrun-buffer-val: Overrunning buffer pointed to by "__u8 const(1)" of 1 bytes by passing it to a function which accesses it at byte offset 7. [details]
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);
35   	
36   	  uint32_t crc = data_bl.crc32c(0);
37   	  uint32_t bl_offset = bl.length();
38   	  bl.claim_append(data_bl);
39   	  encode(crc, bl);
40   	  ceph_assert(get_fixed_size() + m_data.length() + bl_offset == bl.length());
41   	}
42   	
43   	void Entry::decode(bufferlist::const_iterator &iter) {
44   	  using ceph::decode;
45   	  uint32_t start_offset = iter.get_off();
46   	  uint64_t bl_preamble;
47   	  decode(bl_preamble, iter);
48   	  if (bl_preamble != preamble) {
49   	    throw buffer::malformed_input("incorrect preamble: " +
50   	                                  stringify(bl_preamble));
51   	  }
52   	
53   	  uint8_t version;
54   	  decode(version, iter);
55   	  if (version != 1) {
56   	    throw buffer::malformed_input("unknown version: " + stringify(version));
57   	  }
58   	
59   	  decode(m_entry_tid, iter);
60   	  decode(m_tag_tid, iter);
61   	  decode(m_data, iter);
62   	  uint32_t end_offset = iter.get_off();
63   	
64   	  uint32_t crc;
65   	  decode(crc, iter);
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   	
85   	bool Entry::is_readable(bufferlist::const_iterator iter, uint32_t *bytes_needed) {
86   	  using ceph::decode;
87   	  uint32_t start_off = iter.get_off();
88   	  if (iter.get_remaining() < HEADER_FIXED_SIZE) {
89   	    bufferlist sub_bl;
90   	    sub_bl.substr_of(iter.get_bl(), iter.get_off(), iter.get_remaining());
91   	    if (sub_bl.length() > 0 && sub_bl.is_zero()) {
92   	      // pad bytes
93   	      *bytes_needed = 0;
94   	    } else {
95   	      *bytes_needed = HEADER_FIXED_SIZE - iter.get_remaining();
96   	    }
97   	    return false;
98   	  }
99   	  uint64_t bl_preamble;
100  	  decode(bl_preamble, iter);
101  	  if (bl_preamble != preamble) {
102  	    *bytes_needed = 0;
103  	    return false;
104  	  }
105  	  iter.advance(HEADER_FIXED_SIZE - sizeof(bl_preamble));
106  	
107  	  if (iter.get_remaining() < sizeof(uint32_t)) {
108  	    *bytes_needed = sizeof(uint32_t) - iter.get_remaining();
109  	    return false;
110  	  }
111  	  uint32_t data_size;
112  	  decode(data_size, iter);
113  	
114  	  if (iter.get_remaining() < data_size) {
115  	    *bytes_needed = data_size - iter.get_remaining();
116  	    return false;
117  	  }
118  	  iter.advance(data_size);
119  	  uint32_t end_off = iter.get_off();
120  	
121  	  if (iter.get_remaining() < sizeof(uint32_t)) {
122  	    *bytes_needed = sizeof(uint32_t) - iter.get_remaining();
123  	    return false;
124  	  }
125  	
126  	  bufferlist crc_bl;
127  	  crc_bl.substr_of(iter.get_bl(), start_off, end_off - start_off);
128  	
129  	  *bytes_needed = 0;
130  	  uint32_t crc;
131  	  decode(crc, iter);
132  	  if (crc != crc_bl.crc32c(0)) {
133  	    return false;
134  	  }
135  	  return true;
136  	}
137  	
138  	void Entry::generate_test_instances(std::list<Entry *> &o) {
139  	  o.push_back(new Entry(1, 123, bufferlist()));
140  	
141  	  bufferlist bl;
142  	  bl.append("data");
143  	  o.push_back(new Entry(2, 123, bl));
144  	}
145  	
146  	bool Entry::operator==(const Entry& rhs) const {
147  	  return (m_tag_tid == rhs.m_tag_tid && m_entry_tid == rhs.m_entry_tid &&
148  	          const_cast<bufferlist&>(m_data).contents_equal(
149  	            const_cast<bufferlist&>(rhs.m_data)));
150  	}
151  	
152  	std::ostream &operator<<(std::ostream &os, const Entry &entry) {
153  	  os << "Entry[tag_tid=" << entry.get_tag_tid() << ", "
154  	     << "entry_tid=" << entry.get_entry_tid() << ", "
155  	     << "data size=" << entry.get_data().length() << "]";
156  	  return os;
157  	}
158  	
159  	} // namespace journal
160