Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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 }