#include "liberation.h"
}
-// FIXME(loic) this may be too conservative, check back with feedback from Andreas
#define LARGEST_VECTOR_WORDSIZE 16
#define dout_subsys ceph_subsys_osd
unsigned int ErasureCodeJerasure::get_chunk_size(unsigned int object_size) const
{
unsigned alignment = get_alignment();
- unsigned tail = object_size % alignment;
- unsigned padded_length = object_size + ( tail ? ( alignment - tail ) : 0 );
- assert(padded_length % k == 0);
- return padded_length / k;
+ if (per_chunk_alignment) {
+ unsigned chunk_size = object_size / k;
+ if (object_size % k)
+ chunk_size++;
+ dout(20) << "get_chunk_size: chunk_size " << chunk_size
+ << " must be modulo " << alignment << dendl;
+ assert(alignment <= chunk_size);
+ unsigned modulo = chunk_size % alignment;
+ if (modulo) {
+ dout(10) << "get_chunk_size: " << chunk_size
+ << " padded to " << chunk_size + alignment - modulo << dendl;
+ chunk_size += alignment - modulo;
+ }
+ return chunk_size;
+ } else {
+ unsigned tail = object_size % alignment;
+ unsigned padded_length = object_size + ( tail ? ( alignment - tail ) : 0 );
+ assert(padded_length % k == 0);
+ return padded_length / k;
+ }
}
int ErasureCodeJerasure::minimum_to_decode(const set<int> &want_to_read,
return r;
}
+bool ErasureCodeJerasure::to_bool(const std::string &name,
+ const map<std::string,std::string> ¶meters,
+ bool default_value)
+{
+ if (parameters.find(name) == parameters.end() ||
+ parameters.find(name)->second.size() == 0) {
+ dout(10) << name << " defaults to " << default_value << dendl;
+ return default_value;
+ }
+ const std::string value = parameters.find(name)->second;
+ return (value == "yes") || (value == "1") || (value == "true");
+}
+
bool ErasureCodeJerasure::is_prime(int value)
{
int prime55[] = {
unsigned ErasureCodeJerasureReedSolomonVandermonde::get_alignment() const
{
- unsigned alignment = k*w*sizeof(int);
- if ( ((w*sizeof(int))%LARGEST_VECTOR_WORDSIZE) )
- alignment = k*w*LARGEST_VECTOR_WORDSIZE;
- return alignment;
-
+ if (per_chunk_alignment) {
+ return w * LARGEST_VECTOR_WORDSIZE;
+ } else {
+ unsigned alignment = k*w*sizeof(int);
+ if ( ((w*sizeof(int))%LARGEST_VECTOR_WORDSIZE) )
+ alignment = k*w*LARGEST_VECTOR_WORDSIZE;
+ return alignment;
+ }
}
void ErasureCodeJerasureReedSolomonVandermonde::parse(const map<std::string,std::string> ¶meters)
<< " must be one of {8, 16, 32} : revert to " << DEFAULT_W << dendl;
w = DEFAULT_W;
}
+ per_chunk_alignment = to_bool("jerasure-per-chunk-alignment", parameters, false);
}
void ErasureCodeJerasureReedSolomonVandermonde::prepare()
unsigned ErasureCodeJerasureReedSolomonRAID6::get_alignment() const
{
- unsigned alignment = k*w*sizeof(int);
- if ( ((w*sizeof(int))%LARGEST_VECTOR_WORDSIZE) )
- alignment = k*w*LARGEST_VECTOR_WORDSIZE;
- return alignment;
+ if (per_chunk_alignment) {
+ return w * LARGEST_VECTOR_WORDSIZE;
+ } else {
+ unsigned alignment = k*w*sizeof(int);
+ if ( ((w*sizeof(int))%LARGEST_VECTOR_WORDSIZE) )
+ alignment = k*w*LARGEST_VECTOR_WORDSIZE;
+ return alignment;
+ }
}
void ErasureCodeJerasureReedSolomonRAID6::parse(const map<std::string,std::string> ¶meters)
unsigned ErasureCodeJerasureCauchy::get_alignment() const
{
- unsigned alignment = k*w*packetsize*sizeof(int);
- if ( ((w*packetsize*sizeof(int))%LARGEST_VECTOR_WORDSIZE) )
- alignment = k*w*packetsize*LARGEST_VECTOR_WORDSIZE;
- return alignment;
+ if (per_chunk_alignment) {
+ unsigned alignment = w * packetsize;
+ unsigned modulo = alignment % LARGEST_VECTOR_WORDSIZE;
+ if (modulo)
+ alignment += LARGEST_VECTOR_WORDSIZE - modulo;
+ return alignment;
+ } else {
+ unsigned alignment = k*w*packetsize*sizeof(int);
+ if ( ((w*packetsize*sizeof(int))%LARGEST_VECTOR_WORDSIZE) )
+ alignment = k*w*packetsize*LARGEST_VECTOR_WORDSIZE;
+ return alignment;
+ }
}
void ErasureCodeJerasureCauchy::parse(const map<std::string,std::string> ¶meters)
w = DEFAULT_W;
}
packetsize = to_int("packetsize", parameters, DEFAULT_PACKETSIZE);
+ per_chunk_alignment = to_bool("jerasure-per-chunk-alignment", parameters, false);
}
void ErasureCodeJerasureCauchy::prepare_schedule(int *matrix)
TYPED_TEST(ErasureCodeTest, encode_decode)
{
- TypeParam jerasure;
- map<std::string,std::string> parameters;
- parameters["k"] = "2";
- parameters["m"] = "2";
- parameters["w"] = "7";
- parameters["packetsize"] = "8";
- jerasure.init(parameters);
+ const char *per_chunk_alignments[] = { "false", "true" };
+ for (int per_chunk_alignment = 0 ;
+ per_chunk_alignment < 2;
+ per_chunk_alignment++) {
+ TypeParam jerasure;
+ map<std::string,std::string> parameters;
+ parameters["k"] = "2";
+ parameters["m"] = "2";
+ parameters["w"] = "7";
+ parameters["packetsize"] = "8";
+ parameters["jerasure-per-chunk-alignment"] =
+ per_chunk_alignments[per_chunk_alignment];
+ jerasure.init(parameters);
#define LARGE_ENOUGH 2048
- bufferptr in_ptr(buffer::create_page_aligned(LARGE_ENOUGH));
- in_ptr.zero();
- in_ptr.set_length(0);
- const char *payload =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- in_ptr.append(payload, strlen(payload));
- bufferlist in;
- in.push_front(in_ptr);
- int want_to_encode[] = { 0, 1, 2, 3 };
- map<int, bufferlist> encoded;
- EXPECT_EQ(0, jerasure.encode(set<int>(want_to_encode, want_to_encode+4),
- in,
- &encoded));
- EXPECT_EQ(4u, encoded.size());
- unsigned length = encoded[0].length();
- EXPECT_EQ(0, strncmp(encoded[0].c_str(), in.c_str(), length));
- EXPECT_EQ(0, strncmp(encoded[1].c_str(), in.c_str() + length,
- in.length() - length));
-
-
- // all chunks are available
- {
- int want_to_decode[] = { 0, 1 };
- map<int, bufferlist> decoded;
- EXPECT_EQ(0, jerasure.decode(set<int>(want_to_decode, want_to_decode+2),
- encoded,
- &decoded));
- EXPECT_EQ(2u, decoded.size());
- EXPECT_EQ(length, decoded[0].length());
- EXPECT_EQ(0, strncmp(decoded[0].c_str(), in.c_str(), length));
- EXPECT_EQ(0, strncmp(decoded[1].c_str(), in.c_str() + length,
+ bufferptr in_ptr(buffer::create_page_aligned(LARGE_ENOUGH));
+ in_ptr.zero();
+ in_ptr.set_length(0);
+ const char *payload =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ in_ptr.append(payload, strlen(payload));
+ bufferlist in;
+ in.push_front(in_ptr);
+ int want_to_encode[] = { 0, 1, 2, 3 };
+ map<int, bufferlist> encoded;
+ EXPECT_EQ(0, jerasure.encode(set<int>(want_to_encode, want_to_encode+4),
+ in,
+ &encoded));
+ EXPECT_EQ(4u, encoded.size());
+ unsigned length = encoded[0].length();
+ EXPECT_EQ(0, strncmp(encoded[0].c_str(), in.c_str(), length));
+ EXPECT_EQ(0, strncmp(encoded[1].c_str(), in.c_str() + length,
in.length() - length));
- }
- // two chunks are missing
- {
- map<int, bufferlist> degraded = encoded;
- degraded.erase(0);
- degraded.erase(1);
- EXPECT_EQ(2u, degraded.size());
- int want_to_decode[] = { 0, 1 };
- map<int, bufferlist> decoded;
- EXPECT_EQ(0, jerasure.decode(set<int>(want_to_decode, want_to_decode+2),
- degraded,
- &decoded));
- // always decode all, regardless of want_to_decode
- EXPECT_EQ(4u, decoded.size());
- EXPECT_EQ(length, decoded[0].length());
- EXPECT_EQ(0, strncmp(decoded[0].c_str(), in.c_str(), length));
- EXPECT_EQ(0, strncmp(decoded[1].c_str(), in.c_str() + length,
- in.length() - length));
+
+ // all chunks are available
+ {
+ int want_to_decode[] = { 0, 1 };
+ map<int, bufferlist> decoded;
+ EXPECT_EQ(0, jerasure.decode(set<int>(want_to_decode, want_to_decode+2),
+ encoded,
+ &decoded));
+ EXPECT_EQ(2u, decoded.size());
+ EXPECT_EQ(length, decoded[0].length());
+ EXPECT_EQ(0, strncmp(decoded[0].c_str(), in.c_str(), length));
+ EXPECT_EQ(0, strncmp(decoded[1].c_str(), in.c_str() + length,
+ in.length() - length));
+ }
+
+ // two chunks are missing
+ {
+ map<int, bufferlist> degraded = encoded;
+ degraded.erase(0);
+ degraded.erase(1);
+ EXPECT_EQ(2u, degraded.size());
+ int want_to_decode[] = { 0, 1 };
+ map<int, bufferlist> decoded;
+ EXPECT_EQ(0, jerasure.decode(set<int>(want_to_decode, want_to_decode+2),
+ degraded,
+ &decoded));
+ // always decode all, regardless of want_to_decode
+ EXPECT_EQ(4u, decoded.size());
+ EXPECT_EQ(length, decoded[0].length());
+ EXPECT_EQ(0, strncmp(decoded[0].c_str(), in.c_str(), length));
+ EXPECT_EQ(0, strncmp(decoded[1].c_str(), in.c_str() + length,
+ in.length() - length));
+ }
}
}
parameters["w"] = "8";
jerasure.init(parameters);
- unsigned alignment = jerasure.get_alignment();
+ unsigned aligned_object_size = jerasure.get_alignment() * 2;
{
//
// When the input bufferlist needs to be padded because
bufferlist in;
map<int,bufferlist> encoded;
int want_to_encode[] = { 0, 1, 2, 3 };
- int trail_length = 10;
- in.append(string(alignment + trail_length, 'X'));
+ int trail_length = 1;
+ in.append(string(aligned_object_size + trail_length, 'X'));
EXPECT_EQ(0, jerasure.encode(set<int>(want_to_encode, want_to_encode+4),
in,
&encoded));
EXPECT_EQ(4u, encoded.size());
- for(int i = 0; i < 4; i++)
- EXPECT_EQ(alignment, encoded[i].length());
char *last_chunk = encoded[1].c_str();
+ int length =encoded[1].length();
EXPECT_EQ('X', last_chunk[0]);
- EXPECT_EQ('\0', last_chunk[trail_length]);
+ EXPECT_EQ('\0', last_chunk[length - trail_length]);
}
{
map<int,bufferlist> encoded;
set<int> want_to_encode;
want_to_encode.insert(0);
- int trail_length = 10;
- in.append(string(alignment + trail_length, 'X'));
+ int trail_length = 1;
+ in.append(string(aligned_object_size + trail_length, 'X'));
EXPECT_EQ(0, jerasure.encode(want_to_encode, in, &encoded));
EXPECT_EQ(1u, encoded.size());
- EXPECT_EQ(alignment, encoded[0].length());
}
}