*/
#include "ErasureCode.h"
+int ErasureCode::encode_prepare(const bufferlist &raw,
+ bufferlist *prepared) const
+{
+ unsigned int k = get_data_chunk_count();
+ unsigned int m = get_chunk_count() - k;
+ unsigned blocksize = get_chunk_size(raw.length());
+ unsigned padded_length = blocksize * k;
+ *prepared = raw;
+ if (padded_length - raw.length() > 0) {
+ bufferptr pad(padded_length - raw.length());
+ pad.zero();
+ prepared->push_back(pad);
+ }
+ unsigned coding_length = blocksize * m;
+ bufferptr coding(buffer::create_page_aligned(coding_length));
+ prepared->push_back(coding);
+ prepared->rebuild_page_aligned();
+ return 0;
+}
+
+int ErasureCode::encode(const set<int> &want_to_encode,
+ const bufferlist &in,
+ map<int, bufferlist> *encoded)
+{
+ unsigned int k = get_data_chunk_count();
+ unsigned int m = get_chunk_count() - k;
+ bufferlist out;
+ int err = encode_prepare(in, &out);
+ if (err)
+ return err;
+ unsigned blocksize = get_chunk_size(in.length());
+ for (unsigned int i = 0; i < k + m; i++) {
+ bufferlist &chunk = (*encoded)[i];
+ chunk.substr_of(out, i * blocksize, blocksize);
+ }
+ encode_chunks(want_to_encode, encoded);
+ for (unsigned int i = 0; i < k + m; i++) {
+ if (want_to_encode.count(i) == 0)
+ encoded->erase(i);
+ }
+ return 0;
+}
+
+int ErasureCode::encode_chunks(const set<int> &want_to_encode,
+ map<int, bufferlist> *encoded)
+{
+ assert("ErasureCode::encode_chunks not implemented" == 0);
+}
+
+int ErasureCode::decode(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded)
+{
+ vector<int> have;
+ have.reserve(chunks.size());
+ for (map<int, bufferlist>::const_iterator i = chunks.begin();
+ i != chunks.end();
+ ++i) {
+ have.push_back(i->first);
+ }
+ if (includes(
+ have.begin(), have.end(), want_to_read.begin(), want_to_read.end())) {
+ for (set<int>::iterator i = want_to_read.begin();
+ i != want_to_read.end();
+ ++i) {
+ (*decoded)[*i] = chunks.find(*i)->second;
+ }
+ return 0;
+ }
+ unsigned int k = get_data_chunk_count();
+ unsigned int m = get_chunk_count() - k;
+ unsigned blocksize = (*chunks.begin()).second.length();
+ for (unsigned int i = 0; i < k + m; i++) {
+ if (chunks.find(i) == chunks.end()) {
+ bufferptr ptr(buffer::create_page_aligned(blocksize));
+ (*decoded)[i].push_front(ptr);
+ } else {
+ (*decoded)[i] = chunks.find(i)->second;
+ (*decoded)[i].rebuild_page_aligned();
+ }
+ }
+ return decode_chunks(want_to_read, chunks, decoded);
+}
+
+int ErasureCode::decode_chunks(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded)
+{
+ assert("ErasureCode::decode_chunks not implemented" == 0);
+}
+
+
#ifndef CEPH_ERASURE_CODE_H
#define CEPH_ERASURE_CODE_H
+/*! @file ErasureCode.h
+ @brief Base class for erasure code plugins implementors
+
+ */
+
#include "ErasureCodeInterface.h"
namespace ceph {
public:
virtual ~ErasureCode() {}
+ int encode_prepare(const bufferlist &raw, bufferlist *prepared) const;
+
+ virtual int encode(const set<int> &want_to_encode,
+ const bufferlist &in,
+ map<int, bufferlist> *encoded);
+
+ virtual int encode_chunks(const set<int> &want_to_encode,
+ map<int, bufferlist> *encoded);
+
+ virtual int decode(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded);
+
+ virtual int decode_chunks(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded);
+
};
}
const bufferlist &in,
map<int, bufferlist> *encoded) = 0;
+
+ virtual int encode_chunks(const set<int> &want_to_encode,
+ map<int, bufferlist> *encoded) = 0;
+
/**
* Decode the **chunks** and store at least **want_to_read**
* chunks in **decoded**.
const map<int, bufferlist> &chunks,
map<int, bufferlist> *decoded) = 0;
+ virtual int decode_chunks(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded) = 0;
+
/**
* Decode the first **get_data_chunk_count()** **chunks** and
* concatenate them them into **decoded**.
return minimum_to_decode(want_to_read, available_chunks, minimum);
}
-// -----------------------------------------------------------------------------
-
-int
-ErasureCodeIsa::encode(const set<int> &want_to_encode,
- const bufferlist &in,
- map<int, bufferlist> *encoded)
+int ErasureCodeIsa::encode_chunks(const set<int> &want_to_encode,
+ map<int, bufferlist> *encoded)
{
- unsigned blocksize = get_chunk_size(in.length());
- unsigned padded_length = blocksize * k;
- dout(10) << "encode adjusted buffer length from " << in.length()
- << " to " << padded_length << dendl;
- assert(padded_length % k == 0);
- bufferlist out(in);
-
- if (padded_length - in.length() > 0) {
- bufferptr pad(padded_length - in.length());
- pad.zero();
- out.push_back(pad);
- }
- unsigned coding_length = blocksize * m;
- bufferptr coding(buffer::create_page_aligned(coding_length));
- out.push_back(coding);
- out.rebuild_page_aligned();
char *chunks[k + m];
-
- for (int i = 0; i < k + m; i++) {
- bufferlist &chunk = (*encoded)[i];
- chunk.substr_of(out, i * blocksize, blocksize);
- chunks[i] = chunk.c_str();
- }
-
- isa_encode(&chunks[0], &chunks[k], blocksize);
-
- for (int i = 0; i < k + m; i++) {
- if (want_to_encode.count(i) == 0)
- encoded->erase(i);
- }
-
+ for (int i = 0; i < k + m; i++)
+ chunks[i] = (*encoded)[i].c_str();
+ isa_encode(&chunks[0], &chunks[k], (*encoded)[0].length());
return 0;
}
-// -----------------------------------------------------------------------------
-
-int
-ErasureCodeIsa::decode(const set<int> &want_to_read,
- const map<int, bufferlist> &chunks,
- map<int, bufferlist> *decoded)
+int ErasureCodeIsa::decode_chunks(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded)
{
- vector<int> have;
- have.reserve(chunks.size());
-
- for (map<int, bufferlist>::const_iterator i = chunks.begin();
- i != chunks.end();
- ++i) {
- have.push_back(i->first);
- }
-
- if (includes(
- have.begin(),
- have.end(),
- want_to_read.begin(),
- want_to_read.end())) {
- for (set<int>::iterator i = want_to_read.begin();
- i != want_to_read.end();
- ++i) {
- (*decoded)[*i] = chunks.find(*i)->second;
- }
- return 0;
- }
unsigned blocksize = (*chunks.begin()).second.length();
int erasures[k + m + 1];
int erasures_count = 0;
char *data[k];
char *coding[m];
-
- for (int i = 0; i < k + m; i++) {
+ for (int i = 0; i < k + m; i++) {
if (chunks.find(i) == chunks.end()) {
erasures[erasures_count] = i;
erasures_count++;
- bufferptr ptr(buffer::create_page_aligned(blocksize));
- (*decoded)[i].push_front(ptr);
- } else {
- (*decoded)[i] = chunks.find(i)->second;
- (*decoded)[i].rebuild_page_aligned();
}
- if (i < k) {
+ if (i < k)
data[i] = (*decoded)[i].c_str();
- } else {
+ else
coding[i - k] = (*decoded)[i].c_str();
- }
}
erasures[erasures_count] = -1;
-
- if (erasures_count > 0) {
- int retc = isa_decode(erasures, data, coding, blocksize);
- return retc;
- } else
- return 0;
+ assert(erasures_count > 0);
+ return isa_decode(erasures, data, coding, blocksize);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
#include "common/Mutex.h"
-#include "erasure-code/ErasureCodeInterface.h"
+#include "erasure-code/ErasureCode.h"
// -----------------------------------------------------------------------------
#include <list>
// -----------------------------------------------------------------------------
-class ErasureCodeIsa : public ErasureCodeInterface {
+class ErasureCodeIsa : public ErasureCode {
public:
enum eMatrix {kVandermonde=0, kCauchy=1};
virtual int minimum_to_decode(const set<int> &want_to_read,
const set<int> &available_chunks,
set<int> *minimum);
+ virtual int encode_chunks(const set<int> &want_to_encode,
+ map<int, bufferlist> *encoded);
virtual int minimum_to_decode_with_cost(const set<int> &want_to_read,
const map<int, int> &available,
set<int> *minimum);
- virtual int encode(const set<int> &want_to_encode,
- const bufferlist &in,
- map<int, bufferlist> *encoded);
-
- virtual int decode(const set<int> &want_to_read,
- const map<int, bufferlist> &chunks,
- map<int, bufferlist> *decoded);
+ virtual int decode_chunks(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded);
void init(const map<std::string, std::string> ¶meters);
*
*/
-#include <errno.h>
-#include <algorithm>
#include "common/debug.h"
#include "ErasureCodeJerasure.h"
#include "crush/CrushWrapper.h"
return minimum_to_decode(want_to_read, available_chunks, minimum);
}
-int ErasureCodeJerasure::encode(const set<int> &want_to_encode,
- const bufferlist &in,
- map<int, bufferlist> *encoded)
-{
- unsigned blocksize = get_chunk_size(in.length());
- unsigned padded_length = blocksize * k;
- if (in.length() != padded_length)
- dout(10) << "encode adjusted buffer length from " << in.length()
- << " to " << padded_length << dendl;
- bufferlist out(in);
- if (padded_length - in.length() > 0) {
- bufferptr pad(padded_length - in.length());
- pad.zero();
- out.push_back(pad);
- }
- unsigned coding_length = blocksize * m;
- bufferptr coding(buffer::create_page_aligned(coding_length));
- out.push_back(coding);
- out.rebuild_page_aligned();
+int ErasureCodeJerasure::encode_chunks(const set<int> &want_to_encode,
+ map<int, bufferlist> *encoded)
+{
char *chunks[k + m];
- for (int i = 0; i < k + m; i++) {
- bufferlist &chunk = (*encoded)[i];
- chunk.substr_of(out, i * blocksize, blocksize);
- chunks[i] = chunk.c_str();
- }
- jerasure_encode(&chunks[0], &chunks[k], blocksize);
- for (int i = 0; i < k + m; i++) {
- if (want_to_encode.count(i) == 0)
- encoded->erase(i);
- }
+ for (int i = 0; i < k + m; i++)
+ chunks[i] = (*encoded)[i].c_str();
+ jerasure_encode(&chunks[0], &chunks[k], (*encoded)[0].length());
return 0;
}
-int ErasureCodeJerasure::decode(const set<int> &want_to_read,
- const map<int, bufferlist> &chunks,
- map<int, bufferlist> *decoded)
+int ErasureCodeJerasure::decode_chunks(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded)
{
- vector<int> have;
- have.reserve(chunks.size());
- for (map<int, bufferlist>::const_iterator i = chunks.begin();
- i != chunks.end();
- ++i) {
- have.push_back(i->first);
- }
- if (includes(
- have.begin(), have.end(), want_to_read.begin(), want_to_read.end())) {
- for (set<int>::iterator i = want_to_read.begin();
- i != want_to_read.end();
- ++i) {
- (*decoded)[*i] = chunks.find(*i)->second;
- }
- return 0;
- }
unsigned blocksize = (*chunks.begin()).second.length();
int erasures[k + m + 1];
int erasures_count = 0;
if (chunks.find(i) == chunks.end()) {
erasures[erasures_count] = i;
erasures_count++;
- bufferptr ptr(buffer::create_page_aligned(blocksize));
- (*decoded)[i].push_front(ptr);
- } else {
- (*decoded)[i] = chunks.find(i)->second;
- (*decoded)[i].rebuild_page_aligned();
}
if (i < k)
data[i] = (*decoded)[i].c_str();
}
erasures[erasures_count] = -1;
- if (erasures_count > 0)
- return jerasure_decode(erasures, data, coding, blocksize);
- else
- return 0;
+ assert(erasures_count > 0);
+ return jerasure_decode(erasures, data, coding, blocksize);
}
int ErasureCodeJerasure::to_int(const std::string &name,
virtual int minimum_to_decode(const set<int> &want_to_read,
const set<int> &available_chunks,
set<int> *minimum);
+ virtual int encode_chunks(const set<int> &want_to_encode,
+ map<int, bufferlist> *encoded);
virtual int minimum_to_decode_with_cost(const set<int> &want_to_read,
const map<int, int> &available,
set<int> *minimum);
- virtual int encode(const set<int> &want_to_encode,
- const bufferlist &in,
- map<int, bufferlist> *encoded);
-
- virtual int decode(const set<int> &want_to_read,
- const map<int, bufferlist> &chunks,
- map<int, bufferlist> *decoded);
+ virtual int decode_chunks(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded);
void init(const map<std::string,std::string> ¶meters);
virtual void jerasure_encode(char **data,
return 0;
}
+ virtual int encode_chunks(const set<int> &want_to_encode,
+ map<int, bufferlist> *encoded) {
+ assert(0);
+ return 0;
+ }
+
virtual int decode(const set<int> &want_to_read,
const map<int, bufferlist> &chunks,
map<int, bufferlist> *decoded) {
}
return 0;
}
+
+ virtual int decode_chunks(const set<int> &want_to_read,
+ const map<int, bufferlist> &chunks,
+ map<int, bufferlist> *decoded) {
+ assert(0);
+ return 0;
+ }
+
};
#endif