1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
4 #include "include/encoding.h"
10 const stripe_info_t
&sinfo
,
11 ErasureCodeInterfaceRef
&ec_impl
,
12 map
<int, bufferlist
> &to_decode
,
14 ceph_assert(to_decode
.size());
16 uint64_t total_data_size
= to_decode
.begin()->second
.length();
17 ceph_assert(total_data_size
% sinfo
.get_chunk_size() == 0);
20 ceph_assert(out
->length() == 0);
22 for (map
<int, bufferlist
>::iterator i
= to_decode
.begin();
25 ceph_assert(i
->second
.length() == total_data_size
);
28 if (total_data_size
== 0)
31 for (uint64_t i
= 0; i
< total_data_size
; i
+= sinfo
.get_chunk_size()) {
32 map
<int, bufferlist
> chunks
;
33 for (map
<int, bufferlist
>::iterator j
= to_decode
.begin();
36 chunks
[j
->first
].substr_of(j
->second
, i
, sinfo
.get_chunk_size());
39 int r
= ec_impl
->decode_concat(chunks
, &bl
);
41 ceph_assert(bl
.length() == sinfo
.get_stripe_width());
42 out
->claim_append(bl
);
48 const stripe_info_t
&sinfo
,
49 ErasureCodeInterfaceRef
&ec_impl
,
50 map
<int, bufferlist
> &to_decode
,
51 map
<int, bufferlist
*> &out
) {
53 ceph_assert(to_decode
.size());
55 for (auto &&i
: to_decode
) {
56 if(i
.second
.length() == 0)
61 for (map
<int, bufferlist
*>::iterator i
= out
.begin();
64 ceph_assert(i
->second
);
65 ceph_assert(i
->second
->length() == 0);
66 need
.insert(i
->first
);
70 for (auto &&i
: to_decode
) {
71 ceph_assert(i
.second
.length() != 0);
72 avail
.insert(i
.first
);
75 map
<int, vector
<pair
<int, int>>> min
;
76 int r
= ec_impl
->minimum_to_decode(need
, avail
, &min
);
80 int repair_data_per_chunk
= 0;
81 int subchunk_size
= sinfo
.get_chunk_size()/ec_impl
->get_sub_chunk_count();
83 for (auto &&i
: to_decode
) {
84 auto found
= min
.find(i
.first
);
85 if (found
!= min
.end()) {
86 int repair_subchunk_count
= 0;
87 for (auto& subchunks
: min
[i
.first
]) {
88 repair_subchunk_count
+= subchunks
.second
;
90 repair_data_per_chunk
= repair_subchunk_count
* subchunk_size
;
91 chunks_count
= (int)i
.second
.length() / repair_data_per_chunk
;
96 for (int i
= 0; i
< chunks_count
; i
++) {
97 map
<int, bufferlist
> chunks
;
98 for (auto j
= to_decode
.begin();
101 chunks
[j
->first
].substr_of(j
->second
,
102 i
*repair_data_per_chunk
,
103 repair_data_per_chunk
);
105 map
<int, bufferlist
> out_bls
;
106 r
= ec_impl
->decode(need
, chunks
, &out_bls
, sinfo
.get_chunk_size());
108 for (auto j
= out
.begin(); j
!= out
.end(); ++j
) {
109 ceph_assert(out_bls
.count(j
->first
));
110 ceph_assert(out_bls
[j
->first
].length() == sinfo
.get_chunk_size());
111 j
->second
->claim_append(out_bls
[j
->first
]);
114 for (auto &&i
: out
) {
115 ceph_assert(i
.second
->length() == chunks_count
* sinfo
.get_chunk_size());
121 const stripe_info_t
&sinfo
,
122 ErasureCodeInterfaceRef
&ec_impl
,
124 const set
<int> &want
,
125 map
<int, bufferlist
> *out
) {
127 uint64_t logical_size
= in
.length();
129 ceph_assert(logical_size
% sinfo
.get_stripe_width() == 0);
131 ceph_assert(out
->empty());
133 if (logical_size
== 0)
136 for (uint64_t i
= 0; i
< logical_size
; i
+= sinfo
.get_stripe_width()) {
137 map
<int, bufferlist
> encoded
;
139 buf
.substr_of(in
, i
, sinfo
.get_stripe_width());
140 int r
= ec_impl
->encode(want
, buf
, &encoded
);
142 for (map
<int, bufferlist
>::iterator i
= encoded
.begin();
145 ceph_assert(i
->second
.length() == sinfo
.get_chunk_size());
146 (*out
)[i
->first
].claim_append(i
->second
);
150 for (map
<int, bufferlist
>::iterator i
= out
->begin();
153 ceph_assert(i
->second
.length() % sinfo
.get_chunk_size() == 0);
155 sinfo
.aligned_chunk_offset_to_logical_offset(i
->second
.length()) ==
161 void ECUtil::HashInfo::append(uint64_t old_size
,
162 map
<int, bufferlist
> &to_append
) {
163 ceph_assert(old_size
== total_chunk_size
);
164 uint64_t size_to_append
= to_append
.begin()->second
.length();
165 if (has_chunk_hash()) {
166 ceph_assert(to_append
.size() == cumulative_shard_hashes
.size());
167 for (map
<int, bufferlist
>::iterator i
= to_append
.begin();
168 i
!= to_append
.end();
170 ceph_assert(size_to_append
== i
->second
.length());
171 ceph_assert((unsigned)i
->first
< cumulative_shard_hashes
.size());
172 uint32_t new_hash
= i
->second
.crc32c(cumulative_shard_hashes
[i
->first
]);
173 cumulative_shard_hashes
[i
->first
] = new_hash
;
176 total_chunk_size
+= size_to_append
;
179 void ECUtil::HashInfo::encode(bufferlist
&bl
) const
181 ENCODE_START(1, 1, bl
);
182 encode(total_chunk_size
, bl
);
183 encode(cumulative_shard_hashes
, bl
);
187 void ECUtil::HashInfo::decode(bufferlist::const_iterator
&bl
)
190 decode(total_chunk_size
, bl
);
191 decode(cumulative_shard_hashes
, bl
);
192 projected_total_chunk_size
= total_chunk_size
;
196 void ECUtil::HashInfo::dump(Formatter
*f
) const
198 f
->dump_unsigned("total_chunk_size", total_chunk_size
);
199 f
->open_array_section("cumulative_shard_hashes");
200 for (unsigned i
= 0; i
!= cumulative_shard_hashes
.size(); ++i
) {
201 f
->open_object_section("hash");
202 f
->dump_unsigned("shard", i
);
203 f
->dump_unsigned("hash", cumulative_shard_hashes
[i
]);
210 std::ostream
& operator<<(std::ostream
& out
, const HashInfo
& hi
)
212 ostringstream hashes
;
213 for (auto hash
: hi
.cumulative_shard_hashes
)
214 hashes
<< " " << hex
<< hash
;
215 return out
<< "tcs=" << hi
.total_chunk_size
<< hashes
.str();
219 void ECUtil::HashInfo::generate_test_instances(list
<HashInfo
*>& o
)
221 o
.push_back(new HashInfo(3));
225 map
<int, bufferlist
> buffers
;
229 o
.back()->append(0, buffers
);
230 o
.back()->append(20, buffers
);
232 o
.push_back(new HashInfo(4));
235 const string HINFO_KEY
= "hinfo_key";
237 bool ECUtil::is_hinfo_key_string(const string
&key
)
239 return key
== HINFO_KEY
;
242 const string
&ECUtil::get_hinfo_key()