From 516101ae990f25a08e961da0b1c53fe60f7a3d95 Mon Sep 17 00:00:00 2001 From: Andreas-Joachim Peters Date: Mon, 4 Aug 2014 15:03:32 +0200 Subject: [PATCH] EC-ISA: provide a 10% faster simple parity operation for (k, m=1). Add simple parity unit test for k=4,m=1 --- src/erasure-code/isa/ErasureCodeIsa.cc | 18 +++- src/erasure-code/isa/ErasureCodeIsa.h | 2 +- src/test/erasure-code/TestErasureCodeIsa.cc | 98 +++++++++++++++++++++ 3 files changed, 115 insertions(+), 3 deletions(-) diff --git a/src/erasure-code/isa/ErasureCodeIsa.cc b/src/erasure-code/isa/ErasureCodeIsa.cc index 7c997d2c811..0722374d9a7 100644 --- a/src/erasure-code/isa/ErasureCodeIsa.cc +++ b/src/erasure-code/isa/ErasureCodeIsa.cc @@ -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))) { diff --git a/src/erasure-code/isa/ErasureCodeIsa.h b/src/erasure-code/isa/ErasureCodeIsa.h index f42756ec67d..385a8438fa3 100644 --- a/src/erasure-code/isa/ErasureCodeIsa.h +++ b/src/erasure-code/isa/ErasureCodeIsa.h @@ -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::iterator, bufferptr> lru_entry_t; std::map g_decode_tbls_map; diff --git a/src/test/erasure-code/TestErasureCodeIsa.cc b/src/test/erasure-code/TestErasureCodeIsa.cc index d08d05ab8a9..bbef4ab2aed 100644 --- a/src/test/erasure-code/TestErasureCodeIsa.cc +++ b/src/test/erasure-code/TestErasureCodeIsa.cc @@ -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 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); + + setwant_to_encode; + + map 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 degraded = encoded; + set 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 args;