1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
4 #include "include/encoding.h"
9 const stripe_info_t
&sinfo
,
10 ErasureCodeInterfaceRef
&ec_impl
,
11 map
<int, bufferlist
> &to_decode
,
13 assert(to_decode
.size());
15 uint64_t total_data_size
= to_decode
.begin()->second
.length();
16 assert(total_data_size
% sinfo
.get_chunk_size() == 0);
19 assert(out
->length() == 0);
21 for (map
<int, bufferlist
>::iterator i
= to_decode
.begin();
24 assert(i
->second
.length() == total_data_size
);
27 if (total_data_size
== 0)
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();
35 chunks
[j
->first
].substr_of(j
->second
, i
, sinfo
.get_chunk_size());
38 int r
= ec_impl
->decode_concat(chunks
, &bl
);
39 assert(bl
.length() == sinfo
.get_stripe_width());
41 out
->claim_append(bl
);
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());
53 uint64_t total_data_size
= to_decode
.begin()->second
.length();
54 assert(total_data_size
% sinfo
.get_chunk_size() == 0);
56 for (map
<int, bufferlist
>::iterator i
= to_decode
.begin();
59 assert(i
->second
.length() == total_data_size
);
62 if (total_data_size
== 0)
66 for (map
<int, bufferlist
*>::iterator i
= out
.begin();
70 assert(i
->second
->length() == 0);
71 need
.insert(i
->first
);
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();
79 chunks
[j
->first
].substr_of(j
->second
, i
, sinfo
.get_chunk_size());
81 map
<int, bufferlist
> out_bls
;
82 int r
= ec_impl
->decode(need
, chunks
, &out_bls
);
84 for (map
<int, bufferlist
*>::iterator j
= out
.begin();
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
]);
92 for (map
<int, bufferlist
*>::iterator i
= out
.begin();
95 assert(i
->second
->length() == total_data_size
);
101 const stripe_info_t
&sinfo
,
102 ErasureCodeInterfaceRef
&ec_impl
,
104 const set
<int> &want
,
105 map
<int, bufferlist
> *out
) {
107 uint64_t logical_size
= in
.length();
109 assert(logical_size
% sinfo
.get_stripe_width() == 0);
111 assert(out
->empty());
113 if (logical_size
== 0)
116 for (uint64_t i
= 0; i
< logical_size
; i
+= sinfo
.get_stripe_width()) {
117 map
<int, bufferlist
> encoded
;
119 buf
.substr_of(in
, i
, sinfo
.get_stripe_width());
120 int r
= ec_impl
->encode(want
, buf
, &encoded
);
122 for (map
<int, bufferlist
>::iterator i
= encoded
.begin();
125 assert(i
->second
.length() == sinfo
.get_chunk_size());
126 (*out
)[i
->first
].claim_append(i
->second
);
130 for (map
<int, bufferlist
>::iterator i
= out
->begin();
133 assert(i
->second
.length() % sinfo
.get_chunk_size() == 0);
135 sinfo
.aligned_chunk_offset_to_logical_offset(i
->second
.length()) ==
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();
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
;
156 total_chunk_size
+= size_to_append
;
159 void ECUtil::HashInfo::encode(bufferlist
&bl
) const
161 ENCODE_START(1, 1, bl
);
162 ::encode(total_chunk_size
, bl
);
163 ::encode(cumulative_shard_hashes
, bl
);
167 void ECUtil::HashInfo::decode(bufferlist::iterator
&bl
)
170 ::decode(total_chunk_size
, bl
);
171 ::decode(cumulative_shard_hashes
, bl
);
172 projected_total_chunk_size
= total_chunk_size
;
176 void ECUtil::HashInfo::dump(Formatter
*f
) const
178 f
->dump_unsigned("total_chunk_size", total_chunk_size
);
179 f
->open_array_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
]);
190 std::ostream
& operator<<(std::ostream
& out
, const HashInfo
& hi
)
192 ostringstream hashes
;
193 for (auto hash
: hi
.cumulative_shard_hashes
)
194 hashes
<< " " << hex
<< hash
;
195 return out
<< "tcs=" << hi
.total_chunk_size
<< hashes
.str();
199 void ECUtil::HashInfo::generate_test_instances(list
<HashInfo
*>& o
)
201 o
.push_back(new HashInfo(3));
205 map
<int, bufferlist
> buffers
;
209 o
.back()->append(0, buffers
);
210 o
.back()->append(20, buffers
);
212 o
.push_back(new HashInfo(4));
215 const string HINFO_KEY
= "hinfo_key";
217 bool ECUtil::is_hinfo_key_string(const string
&key
)
219 return key
== HINFO_KEY
;
222 const string
&ECUtil::get_hinfo_key()