EC-ISA: provide a 10% faster simple parity operation for (k, m=1). Add simple parity unit test for k=4,m=1

This commit is contained in:
Andreas-Joachim Peters 2014-08-04 15:03:32 +02:00
parent 3de7b7c52c
commit 516101ae99
3 changed files with 115 additions and 3 deletions

View File

@ -248,8 +248,13 @@ ErasureCodeIsaDefault::isa_encode(char **data,
char **coding,
int blocksize)
{
ec_encode_data(blocksize, k, m, g_encode_tbls,
(unsigned char**) data, (unsigned char**) coding);
if (m==1)
// single parity stripe
region_xor( (unsigned char**) data, (unsigned char*) coding[0], k, blocksize );
else
ec_encode_data(blocksize, k, m, g_encode_tbls,
(unsigned char**) data, (unsigned char**) coding);
}
// -----------------------------------------------------------------------------
@ -382,6 +387,15 @@ ErasureCodeIsaDefault::isa_decode(int *erasures,
}
}
if (m==1) {
// single parity decoding
assert (1 == nerrs);
dout(20) << "isa_decode: reconstruct using region xor [" << erasures[0] << "]" << dendl;
region_xor(recover_source, recover_target[0], k, blocksize);
return 0;
}
if ((matrixtype == kVandermonde) &&
(nerrs == 1) &&
(erasures[0] < (k + 1))) {

View File

@ -137,7 +137,7 @@ public:
return g_decode_tbls_lru.size();
}
// we implement an LRU cache for coding matrix - the cache size is sufficient up to (10,4) decodings
// we implement an LRU cache for coding matrix - the cache size is sufficient up to (12,4) decodings
typedef std::pair<std::list<std::string>::iterator, bufferptr> lru_entry_t;
std::map<std::string, lru_entry_t> g_decode_tbls_map;

View File

@ -607,6 +607,104 @@ TYPED_TEST(IsaErasureCodeTest, isa_cauchy_exhaustive)
EXPECT_EQ(2516, Isa.get_tbls_lru_size());
}
TYPED_TEST(IsaErasureCodeTest, isa_xor_codec)
{
// Test all possible failure scenarios and reconstruction cases for
// a (4,1) RAID-5 like configuration
TypeParam Isa;
map<std::string, std::string> parameters;
parameters["k"] = "4";
parameters["m"] = "1";
Isa.init(parameters);
int k = 4;
int m = 1;
#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"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
in_ptr.append(payload, strlen(payload));
bufferlist in;
in.push_front(in_ptr);
set<int>want_to_encode;
map<int, bufferlist> encoded;
for (int i = 0; i < (k + m); i++) {
want_to_encode.insert(i);
}
EXPECT_EQ(0, Isa.encode(want_to_encode,
in,
&encoded));
EXPECT_EQ((unsigned) (k + m), encoded.size());
unsigned length = encoded[0].length();
for (int i = 0; i < k; i++) {
EXPECT_EQ(0, strncmp(encoded[i].c_str(), in.c_str() + (i * length), length));
}
buffer::ptr enc[k + m];
// create buffers with a copy of the original data to be able to compare it after decoding
{
for (int i = 0; i < (k + m); i++) {
buffer::ptr newenc(buffer::create_page_aligned(LARGE_ENOUGH));
enc[i] = newenc;
enc[i].zero();
enc[i].set_length(0);
enc[i].append(encoded[i].c_str(), length);
}
}
// loop through all possible loss scenarios
bool err = true;
int cnt_cf = 0;
for (int l1 = 0; l1 < (k + m); l1++) {
map<int, bufferlist> degraded = encoded;
set<int> want_to_decode;
degraded.erase(l1);
want_to_decode.insert(l1);
err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length);
EXPECT_EQ(0, err);
cnt_cf++;
degraded[l1] = encoded[l1];
want_to_decode.erase(l1);
}
EXPECT_EQ(5, cnt_cf);
}
int main(int argc, char **argv)
{
vector<const char*> args;