Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / osd / ECUtil.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2
3 #include <errno.h>
4 #include "include/encoding.h"
5 #include "ECUtil.h"
6 using namespace std;
7
8 int ECUtil::decode(
9   const stripe_info_t &sinfo,
10   ErasureCodeInterfaceRef &ec_impl,
11   map<int, bufferlist> &to_decode,
12   bufferlist *out) {
13   assert(to_decode.size());
14
15   uint64_t total_data_size = to_decode.begin()->second.length();
16   assert(total_data_size % sinfo.get_chunk_size() == 0);
17
18   assert(out);
19   assert(out->length() == 0);
20
21   for (map<int, bufferlist>::iterator i = to_decode.begin();
22        i != to_decode.end();
23        ++i) {
24     assert(i->second.length() == total_data_size);
25   }
26
27   if (total_data_size == 0)
28     return 0;
29
30   for (uint64_t i = 0; i < total_data_size; i += sinfo.get_chunk_size()) {
31     map<int, bufferlist> chunks;
32     for (map<int, bufferlist>::iterator j = to_decode.begin();
33          j != to_decode.end();
34          ++j) {
35       chunks[j->first].substr_of(j->second, i, sinfo.get_chunk_size());
36     }
37     bufferlist bl;
38     int r = ec_impl->decode_concat(chunks, &bl);
39     assert(bl.length() == sinfo.get_stripe_width());
40     assert(r == 0);
41     out->claim_append(bl);
42   }
43   return 0;
44 }
45
46 int ECUtil::decode(
47   const stripe_info_t &sinfo,
48   ErasureCodeInterfaceRef &ec_impl,
49   map<int, bufferlist> &to_decode,
50   map<int, bufferlist*> &out) {
51   assert(to_decode.size());
52
53   uint64_t total_data_size = to_decode.begin()->second.length();
54   assert(total_data_size % sinfo.get_chunk_size() == 0);
55
56   for (map<int, bufferlist>::iterator i = to_decode.begin();
57        i != to_decode.end();
58        ++i) {
59     assert(i->second.length() == total_data_size);
60   }
61
62   if (total_data_size == 0)
63     return 0;
64
65   set<int> need;
66   for (map<int, bufferlist*>::iterator i = out.begin();
67        i != out.end();
68        ++i) {
69     assert(i->second);
70     assert(i->second->length() == 0);
71     need.insert(i->first);
72   }
73
74   for (uint64_t i = 0; i < total_data_size; i += sinfo.get_chunk_size()) {
75     map<int, bufferlist> chunks;
76     for (map<int, bufferlist>::iterator j = to_decode.begin();
77          j != to_decode.end();
78          ++j) {
79       chunks[j->first].substr_of(j->second, i, sinfo.get_chunk_size());
80     }
81     map<int, bufferlist> out_bls;
82     int r = ec_impl->decode(need, chunks, &out_bls);
83     assert(r == 0);
84     for (map<int, bufferlist*>::iterator j = out.begin();
85          j != out.end();
86          ++j) {
87       assert(out_bls.count(j->first));
88       assert(out_bls[j->first].length() == sinfo.get_chunk_size());
89       j->second->claim_append(out_bls[j->first]);
90     }
91   }
92   for (map<int, bufferlist*>::iterator i = out.begin();
93        i != out.end();
94        ++i) {
95     assert(i->second->length() == total_data_size);
96   }
97   return 0;
98 }
99
100 int ECUtil::encode(
101   const stripe_info_t &sinfo,
102   ErasureCodeInterfaceRef &ec_impl,
103   bufferlist &in,
104   const set<int> &want,
105   map<int, bufferlist> *out) {
106
107   uint64_t logical_size = in.length();
108
109   assert(logical_size % sinfo.get_stripe_width() == 0);
110   assert(out);
111   assert(out->empty());
112
113   if (logical_size == 0)
114     return 0;
115
116   for (uint64_t i = 0; i < logical_size; i += sinfo.get_stripe_width()) {
117     map<int, bufferlist> encoded;
118     bufferlist buf;
119     buf.substr_of(in, i, sinfo.get_stripe_width());
120     int r = ec_impl->encode(want, buf, &encoded);
121     assert(r == 0);
122     for (map<int, bufferlist>::iterator i = encoded.begin();
123          i != encoded.end();
124          ++i) {
125       assert(i->second.length() == sinfo.get_chunk_size());
126       (*out)[i->first].claim_append(i->second);
127     }
128   }
129
130   for (map<int, bufferlist>::iterator i = out->begin();
131        i != out->end();
132        ++i) {
133     assert(i->second.length() % sinfo.get_chunk_size() == 0);
134     assert(
135       sinfo.aligned_chunk_offset_to_logical_offset(i->second.length()) ==
136       logical_size);
137   }
138   return 0;
139 }
140
141 void ECUtil::HashInfo::append(uint64_t old_size,
142                               map<int, bufferlist> &to_append) {
143   assert(old_size == total_chunk_size);
144   uint64_t size_to_append = to_append.begin()->second.length();
145   if (has_chunk_hash()) {
146     assert(to_append.size() == cumulative_shard_hashes.size());
147     for (map<int, bufferlist>::iterator i = to_append.begin();
148          i != to_append.end();
149          ++i) {
150       assert(size_to_append == i->second.length());
151       assert((unsigned)i->first < cumulative_shard_hashes.size());
152       uint32_t new_hash = i->second.crc32c(cumulative_shard_hashes[i->first]);
153       cumulative_shard_hashes[i->first] = new_hash;
154     }
155   }
156   total_chunk_size += size_to_append;
157 }
158
159 void ECUtil::HashInfo::encode(bufferlist &bl) const
160 {
161   ENCODE_START(1, 1, bl);
162   ::encode(total_chunk_size, bl);
163   ::encode(cumulative_shard_hashes, bl);
164   ENCODE_FINISH(bl);
165 }
166
167 void ECUtil::HashInfo::decode(bufferlist::iterator &bl)
168 {
169   DECODE_START(1, bl);
170   ::decode(total_chunk_size, bl);
171   ::decode(cumulative_shard_hashes, bl);
172   projected_total_chunk_size = total_chunk_size;
173   DECODE_FINISH(bl);
174 }
175
176 void ECUtil::HashInfo::dump(Formatter *f) const
177 {
178   f->dump_unsigned("total_chunk_size", total_chunk_size);
179   f->open_object_section("cumulative_shard_hashes");
180   for (unsigned i = 0; i != cumulative_shard_hashes.size(); ++i) {
181     f->open_object_section("hash");
182     f->dump_unsigned("shard", i);
183     f->dump_unsigned("hash", cumulative_shard_hashes[i]);
184     f->close_section();
185   }
186   f->close_section();
187 }
188
189 void ECUtil::HashInfo::generate_test_instances(list<HashInfo*>& o)
190 {
191   o.push_back(new HashInfo(3));
192   {
193     bufferlist bl;
194     bl.append_zero(20);
195     map<int, bufferlist> buffers;
196     buffers[0] = bl;
197     buffers[1] = bl;
198     buffers[2] = bl;
199     o.back()->append(0, buffers);
200     o.back()->append(20, buffers);
201   }
202   o.push_back(new HashInfo(4));
203 }
204
205 const string HINFO_KEY = "hinfo_key";
206
207 bool ECUtil::is_hinfo_key_string(const string &key)
208 {
209   return key == HINFO_KEY;
210 }
211
212 const string &ECUtil::get_hinfo_key()
213 {
214   return HINFO_KEY;
215 }