]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/SloppyCRCMap.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / common / SloppyCRCMap.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 "common/SloppyCRCMap.h"
5
6 using namespace std;
7
8 void SloppyCRCMap::write(uint64_t offset, uint64_t len, const bufferlist& bl,
9 std::ostream *out)
10 {
11 int64_t left = len;
12 uint64_t pos = offset;
13 unsigned o = offset % block_size;
14 if (o) {
15 crc_map.erase(offset - o);
16 if (out)
17 *out << "write invalidate " << (offset - o) << "\n";
18 pos += (block_size - o);
19 left -= (block_size - o);
20 }
21 while (left >= block_size) {
22 bufferlist t;
23 t.substr_of(bl, pos - offset, block_size);
24 crc_map[pos] = t.crc32c(crc_iv);
25 if (out)
26 *out << "write set " << pos << " " << crc_map[pos] << "\n";
27 pos += block_size;
28 left -= block_size;
29 }
30 if (left > 0) {
31 crc_map.erase(pos);
32 if (out)
33 *out << "write invalidate " << pos << "\n";
34 }
35 }
36
37 int SloppyCRCMap::read(uint64_t offset, uint64_t len, const bufferlist& bl,
38 std::ostream *err)
39 {
40 int errors = 0;
41 int64_t left = len;
42 uint64_t pos = offset;
43 unsigned o = offset % block_size;
44 if (o) {
45 pos += (block_size - o);
46 left -= (block_size - o);
47 }
48 while (left >= block_size) {
49 // FIXME: this could be more efficient if we avoid doing a find()
50 // on each iteration
51 std::map<uint64_t,uint32_t>::iterator p = crc_map.find(pos);
52 if (p != crc_map.end()) {
53 bufferlist t;
54 t.substr_of(bl, pos - offset, block_size);
55 uint32_t crc = t.crc32c(crc_iv);
56 if (p->second != crc) {
57 errors++;
58 if (err)
59 *err << "offset " << pos << " len " << block_size
60 << " has crc " << crc << " expected " << p->second << "\n";
61 }
62 }
63 pos += block_size;
64 left -= block_size;
65 }
66 return errors;
67 }
68
69 void SloppyCRCMap::truncate(uint64_t offset)
70 {
71 offset -= offset % block_size;
72 std::map<uint64_t,uint32_t>::iterator p = crc_map.lower_bound(offset);
73 while (p != crc_map.end())
74 crc_map.erase(p++);
75 }
76
77 void SloppyCRCMap::zero(uint64_t offset, uint64_t len)
78 {
79 int64_t left = len;
80 uint64_t pos = offset;
81 unsigned o = offset % block_size;
82 if (o) {
83 crc_map.erase(offset - o);
84 pos += (block_size - o);
85 left -= (block_size - o);
86 }
87 while (left >= block_size) {
88 crc_map[pos] = zero_crc;
89 pos += block_size;
90 left -= block_size;
91 }
92 if (left > 0)
93 crc_map.erase(pos);
94 }
95
96 void SloppyCRCMap::clone_range(uint64_t offset, uint64_t len,
97 uint64_t srcoff, const SloppyCRCMap& src,
98 std::ostream *out)
99 {
100 int64_t left = len;
101 uint64_t pos = offset;
102 uint64_t srcpos = srcoff;
103 unsigned o = offset % block_size;
104 if (o) {
105 crc_map.erase(offset - o);
106 pos += (block_size - o);
107 srcpos += (block_size - o);
108 left -= (block_size - o);
109 if (out)
110 *out << "clone_range invalidate " << (offset - o) << "\n";
111 }
112 while (left >= block_size) {
113 // FIXME: this could be more efficient.
114 if (block_size == src.block_size) {
115 map<uint64_t,uint32_t>::const_iterator p = src.crc_map.find(srcpos);
116 if (p != src.crc_map.end()) {
117 crc_map[pos] = p->second;
118 if (out)
119 *out << "clone_range copy " << pos << " " << p->second << "\n";
120 } else {
121 crc_map.erase(pos);
122 if (out)
123 *out << "clone_range invalidate " << pos << "\n";
124 }
125 } else {
126 crc_map.erase(pos);
127 if (out)
128 *out << "clone_range invalidate " << pos << "\n";
129 }
130 pos += block_size;
131 srcpos += block_size;
132 left -= block_size;
133 }
134 if (left > 0) {
135 crc_map.erase(pos);
136 if (out)
137 *out << "clone_range invalidate " << pos << "\n";
138 }
139 }
140
141 void SloppyCRCMap::encode(bufferlist& bl) const
142 {
143 ENCODE_START(1, 1, bl);
144 ::encode(block_size, bl);
145 ::encode(crc_map, bl);
146 ENCODE_FINISH(bl);
147 }
148
149 void SloppyCRCMap::decode(bufferlist::iterator& bl)
150 {
151 DECODE_START(1, bl);
152 uint32_t bs;
153 ::decode(bs, bl);
154 set_block_size(bs);
155 ::decode(crc_map, bl);
156 DECODE_FINISH(bl);
157 }
158
159 void SloppyCRCMap::dump(Formatter *f) const
160 {
161 f->dump_unsigned("block_size", block_size);
162 f->open_array_section("crc_map");
163 for (map<uint64_t,uint32_t>::const_iterator p = crc_map.begin(); p != crc_map.end(); ++p) {
164 f->open_object_section("crc");
165 f->dump_unsigned("offset", p->first);
166 f->dump_unsigned("crc", p->second);
167 f->close_section();
168 }
169 f->close_section();
170 }
171
172 void SloppyCRCMap::generate_test_instances(list<SloppyCRCMap*>& ls)
173 {
174 ls.push_back(new SloppyCRCMap);
175 ls.push_back(new SloppyCRCMap(2));
176 bufferlist bl;
177 bl.append("some data");
178 ls.back()->write(1, bl.length(), bl);
179 ls.back()->write(10, bl.length(), bl);
180 ls.back()->zero(4, 2);
181 }