]>
git.proxmox.com Git - ceph.git/blob - ceph/src/erasure-code/ErasureCode.cc
353ab4f0d8e68afd83d6328463fc430d18d702eb
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph distributed storage system
6 * Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
7 * Copyright (C) 2014 Red Hat <contact@redhat.com>
9 * Author: Loic Dachary <loic@dachary.org>
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
21 #include "ErasureCode.h"
23 #include "common/strtol.h"
24 #include "include/buffer.h"
28 const unsigned ErasureCode::SIMD_ALIGN
= 32;
30 int ErasureCode::sanity_check_k(int k
, ostream
*ss
)
33 *ss
<< "k=" << k
<< " must be >= 2" << std::endl
;
40 int ErasureCode::chunk_index(unsigned int i
) const
42 return chunk_mapping
.size() > i
? chunk_mapping
[i
] : i
;
45 int ErasureCode::minimum_to_decode(const set
<int> &want_to_read
,
46 const set
<int> &available_chunks
,
49 if (includes(available_chunks
.begin(), available_chunks
.end(),
50 want_to_read
.begin(), want_to_read
.end())) {
51 *minimum
= want_to_read
;
53 unsigned int k
= get_data_chunk_count();
54 if (available_chunks
.size() < (unsigned)k
)
58 for (i
= available_chunks
.begin(), j
= 0; j
< (unsigned)k
; ++i
, j
++)
64 int ErasureCode::minimum_to_decode_with_cost(const set
<int> &want_to_read
,
65 const map
<int, int> &available
,
68 set
<int> available_chunks
;
69 for (map
<int, int>::const_iterator i
= available
.begin();
72 available_chunks
.insert(i
->first
);
73 return minimum_to_decode(want_to_read
, available_chunks
, minimum
);
76 int ErasureCode::encode_prepare(const bufferlist
&raw
,
77 map
<int, bufferlist
> &encoded
) const
79 unsigned int k
= get_data_chunk_count();
80 unsigned int m
= get_chunk_count() - k
;
81 unsigned blocksize
= get_chunk_size(raw
.length());
82 unsigned padded_chunks
= k
- raw
.length() / blocksize
;
83 bufferlist prepared
= raw
;
85 for (unsigned int i
= 0; i
< k
- padded_chunks
; i
++) {
86 bufferlist
&chunk
= encoded
[chunk_index(i
)];
87 chunk
.substr_of(prepared
, i
* blocksize
, blocksize
);
88 chunk
.rebuild_aligned_size_and_memory(blocksize
, SIMD_ALIGN
);
89 assert(chunk
.is_contiguous());
92 unsigned remainder
= raw
.length() - (k
- padded_chunks
) * blocksize
;
93 bufferptr
buf(buffer::create_aligned(blocksize
, SIMD_ALIGN
));
95 raw
.copy((k
- padded_chunks
) * blocksize
, remainder
, buf
.c_str());
96 buf
.zero(remainder
, blocksize
- remainder
);
97 encoded
[chunk_index(k
-padded_chunks
)].push_back(std::move(buf
));
99 for (unsigned int i
= k
- padded_chunks
+ 1; i
< k
; i
++) {
100 bufferptr
buf(buffer::create_aligned(blocksize
, SIMD_ALIGN
));
102 encoded
[chunk_index(i
)].push_back(std::move(buf
));
105 for (unsigned int i
= k
; i
< k
+ m
; i
++) {
106 bufferlist
&chunk
= encoded
[chunk_index(i
)];
107 chunk
.push_back(buffer::create_aligned(blocksize
, SIMD_ALIGN
));
113 int ErasureCode::encode(const set
<int> &want_to_encode
,
114 const bufferlist
&in
,
115 map
<int, bufferlist
> *encoded
)
117 unsigned int k
= get_data_chunk_count();
118 unsigned int m
= get_chunk_count() - k
;
120 int err
= encode_prepare(in
, *encoded
);
123 encode_chunks(want_to_encode
, encoded
);
124 for (unsigned int i
= 0; i
< k
+ m
; i
++) {
125 if (want_to_encode
.count(i
) == 0)
131 int ErasureCode::encode_chunks(const set
<int> &want_to_encode
,
132 map
<int, bufferlist
> *encoded
)
134 assert("ErasureCode::encode_chunks not implemented" == 0);
137 int ErasureCode::decode(const set
<int> &want_to_read
,
138 const map
<int, bufferlist
> &chunks
,
139 map
<int, bufferlist
> *decoded
)
142 have
.reserve(chunks
.size());
143 for (map
<int, bufferlist
>::const_iterator i
= chunks
.begin();
146 have
.push_back(i
->first
);
149 have
.begin(), have
.end(), want_to_read
.begin(), want_to_read
.end())) {
150 for (set
<int>::iterator i
= want_to_read
.begin();
151 i
!= want_to_read
.end();
153 (*decoded
)[*i
] = chunks
.find(*i
)->second
;
157 unsigned int k
= get_data_chunk_count();
158 unsigned int m
= get_chunk_count() - k
;
159 unsigned blocksize
= (*chunks
.begin()).second
.length();
160 for (unsigned int i
= 0; i
< k
+ m
; i
++) {
161 if (chunks
.find(i
) == chunks
.end()) {
162 bufferptr
ptr(buffer::create_aligned(blocksize
, SIMD_ALIGN
));
163 (*decoded
)[i
].push_front(ptr
);
165 (*decoded
)[i
] = chunks
.find(i
)->second
;
166 (*decoded
)[i
].rebuild_aligned(SIMD_ALIGN
);
169 return decode_chunks(want_to_read
, chunks
, decoded
);
172 int ErasureCode::decode_chunks(const set
<int> &want_to_read
,
173 const map
<int, bufferlist
> &chunks
,
174 map
<int, bufferlist
> *decoded
)
176 assert("ErasureCode::decode_chunks not implemented" == 0);
179 int ErasureCode::parse(const ErasureCodeProfile
&profile
,
182 return to_mapping(profile
, ss
);
185 const vector
<int> &ErasureCode::get_chunk_mapping() const {
186 return chunk_mapping
;
189 int ErasureCode::to_mapping(const ErasureCodeProfile
&profile
,
192 if (profile
.find("mapping") != profile
.end()) {
193 std::string mapping
= profile
.find("mapping")->second
;
195 vector
<int> coding_chunk_mapping
;
196 for(std::string::iterator it
= mapping
.begin(); it
!= mapping
.end(); ++it
) {
198 chunk_mapping
.push_back(position
);
200 coding_chunk_mapping
.push_back(position
);
203 chunk_mapping
.insert(chunk_mapping
.end(),
204 coding_chunk_mapping
.begin(),
205 coding_chunk_mapping
.end());
210 int ErasureCode::to_int(const std::string
&name
,
211 ErasureCodeProfile
&profile
,
213 const std::string
&default_value
,
216 if (profile
.find(name
) == profile
.end() ||
217 profile
.find(name
)->second
.size() == 0)
218 profile
[name
] = default_value
;
219 std::string p
= profile
.find(name
)->second
;
221 int r
= strict_strtol(p
.c_str(), 10, &err
);
223 *ss
<< "could not convert " << name
<< "=" << p
224 << " to int because " << err
225 << ", set to default " << default_value
<< std::endl
;
226 *value
= strict_strtol(default_value
.c_str(), 10, &err
);
233 int ErasureCode::to_bool(const std::string
&name
,
234 ErasureCodeProfile
&profile
,
236 const std::string
&default_value
,
239 if (profile
.find(name
) == profile
.end() ||
240 profile
.find(name
)->second
.size() == 0)
241 profile
[name
] = default_value
;
242 const std::string p
= profile
.find(name
)->second
;
243 *value
= (p
== "yes") || (p
== "true");
247 int ErasureCode::to_string(const std::string
&name
,
248 ErasureCodeProfile
&profile
,
250 const std::string
&default_value
,
253 if (profile
.find(name
) == profile
.end() ||
254 profile
.find(name
)->second
.size() == 0)
255 profile
[name
] = default_value
;
256 *value
= profile
[name
];
260 int ErasureCode::decode_concat(const map
<int, bufferlist
> &chunks
,
263 set
<int> want_to_read
;
265 for (unsigned int i
= 0; i
< get_data_chunk_count(); i
++) {
266 want_to_read
.insert(chunk_index(i
));
268 map
<int, bufferlist
> decoded_map
;
269 int r
= decode(want_to_read
, chunks
, &decoded_map
);
271 for (unsigned int i
= 0; i
< get_data_chunk_count(); i
++) {
272 decoded
->claim_append(decoded_map
[chunk_index(i
)]);