X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Ferasure-code%2FTestErasureCodeIsa.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Ferasure-code%2FTestErasureCodeIsa.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=828349c6ca3e98f7e41a1a9fecdac599ae9a1876;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/test/erasure-code/TestErasureCodeIsa.cc b/src/ceph/src/test/erasure-code/TestErasureCodeIsa.cc deleted file mode 100644 index 828349c..0000000 --- a/src/ceph/src/test/erasure-code/TestErasureCodeIsa.cc +++ /dev/null @@ -1,965 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2014 CERN (Switzerland) - * Copyright (C) 2014 Red Hat - * - * Author: Andreas-Joachim Peters - * Author: Loic Dachary - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - */ - -#include -#include - -#include "crush/CrushWrapper.h" -#include "include/stringify.h" -#include "erasure-code/isa/ErasureCodeIsa.h" -#include "erasure-code/isa/xor_op.h" -#include "global/global_context.h" -#include "common/config.h" -#include "gtest/gtest.h" - -ErasureCodeIsaTableCache tcache; - -class IsaErasureCodeTest : public ::testing::Test { -public: - void compare_chunks(bufferlist &in, map &encoded); - void encode_decode(unsigned object_size); -}; - -void IsaErasureCodeTest::compare_chunks(bufferlist &in, map &encoded) -{ - unsigned object_size = in.length(); - unsigned chunk_size = encoded[0].length(); - for (unsigned i = 0; i < encoded.size(); i++) { - if (i * chunk_size >= object_size) - break; - int chunk_length = object_size > (i + 1) * chunk_size ? chunk_size : object_size - i * chunk_size; - EXPECT_EQ(0, memcmp(encoded[i].c_str(), in.c_str() + i * chunk_size, chunk_length)); - } -} - -void IsaErasureCodeTest::encode_decode(unsigned object_size) -{ - ErasureCodeIsaDefault Isa(tcache); - - ErasureCodeProfile profile; - profile["k"] = "2"; - profile["m"] = "2"; - Isa.init(profile, &cerr); - - string payload(object_size, 'X'); - bufferlist in; - // may be multiple bufferptr if object_size is larger than CEPH_PAGE_SIZE - in.append(payload.c_str(), payload.length()); - int want_to_encode[] = {0, 1, 2, 3}; - map encoded; - EXPECT_EQ(0, Isa.encode(set(want_to_encode, want_to_encode + 4), - in, - &encoded)); - EXPECT_EQ(4u, encoded.size()); - unsigned chunk_size = encoded[0].length(); - EXPECT_EQ(chunk_size, Isa.get_chunk_size(object_size)); - compare_chunks(in, encoded); - - // all chunks are available - { - int want_to_decode[] = {0, 1}; - map decoded; - EXPECT_EQ(0, Isa.decode(set(want_to_decode, want_to_decode + 2), - encoded, - &decoded)); - EXPECT_EQ(2u, decoded.size()); - EXPECT_EQ(chunk_size, decoded[0].length()); - compare_chunks(in, decoded); - } - - // one data chunk is missing - { - map degraded = encoded; - - string enc1(encoded[1].c_str(), chunk_size); - - degraded.erase(1); - EXPECT_EQ(3u, degraded.size()); - int want_to_decode[] = {1}; - map decoded; - EXPECT_EQ(0, Isa.decode(set(want_to_decode, want_to_decode + 1), - degraded, - &decoded)); - // always decode all, regardless of want_to_decode - EXPECT_EQ(4u, decoded.size()); - EXPECT_EQ(chunk_size, decoded[1].length()); - EXPECT_EQ(0, memcmp(decoded[1].c_str(), enc1.c_str(), chunk_size)); - } - - // non-xor coding chunk is missing - { - map degraded = encoded; - - string enc3(encoded[3].c_str(), chunk_size); - - degraded.erase(3); - EXPECT_EQ(3u, degraded.size()); - int want_to_decode[] = {3}; - map decoded; - EXPECT_EQ(0, Isa.decode(set(want_to_decode, want_to_decode + 1), - degraded, - &decoded)); - // always decode all, regardless of want_to_decode - EXPECT_EQ(4u, decoded.size()); - EXPECT_EQ(chunk_size, decoded[3].length()); - EXPECT_EQ(0, memcmp(decoded[3].c_str(), enc3.c_str(), chunk_size)); - } - - // xor coding chunk is missing - { - map degraded = encoded; - - string enc2(encoded[2].c_str(), chunk_size); - - degraded.erase(2); - EXPECT_EQ(3u, degraded.size()); - int want_to_decode[] = {2}; - map decoded; - EXPECT_EQ(0, Isa.decode(set(want_to_decode, want_to_decode + 1), - degraded, - &decoded)); - // always decode all, regardless of want_to_decode - EXPECT_EQ(4u, decoded.size()); - EXPECT_EQ(chunk_size, decoded[2].length()); - EXPECT_EQ(0, memcmp(decoded[2].c_str(), enc2.c_str(), chunk_size)); - } - - // one data and one coding chunk is missing - { - map degraded = encoded; - - string enc3(encoded[3].c_str(), chunk_size); - - degraded.erase(1); - degraded.erase(3); - EXPECT_EQ(2u, degraded.size()); - int want_to_decode[] = {1, 3}; - map decoded; - EXPECT_EQ(0, Isa.decode(set(want_to_decode, want_to_decode + 2), - degraded, - &decoded)); - // always decode all, regardless of want_to_decode - EXPECT_EQ(4u, decoded.size()); - EXPECT_EQ(chunk_size, decoded[1].length()); - EXPECT_EQ(0, memcmp(decoded[3].c_str(), enc3.c_str(), chunk_size)); - } - - // two data chunks are missing - { - map degraded = encoded; - degraded.erase(0); - degraded.erase(1); - EXPECT_EQ(2u, degraded.size()); - int want_to_decode[] = {0, 1}; - map decoded; - EXPECT_EQ(0, Isa.decode(set(want_to_decode, want_to_decode + 2), - degraded, - &decoded)); - // always decode all, regardless of want_to_decode - EXPECT_EQ(4u, decoded.size()); - EXPECT_EQ(chunk_size, decoded[0].length()); - compare_chunks(in, decoded); - } - -} - -TEST_F(IsaErasureCodeTest, encode_decode) -{ - encode_decode(1); - encode_decode(EC_ISA_ADDRESS_ALIGNMENT); - encode_decode(EC_ISA_ADDRESS_ALIGNMENT + 1); - encode_decode(2048); - encode_decode(4096); - encode_decode(4096 + 1); -} - -TEST_F(IsaErasureCodeTest, minimum_to_decode) -{ - ErasureCodeIsaDefault Isa(tcache); - ErasureCodeProfile profile; - profile["k"] = "2"; - profile["m"] = "2"; - Isa.init(profile, &cerr); - - // - // If trying to read nothing, the minimum is empty. - // - { - set want_to_read; - set available_chunks; - set minimum; - - EXPECT_EQ(0, Isa.minimum_to_decode(want_to_read, - available_chunks, - &minimum)); - EXPECT_TRUE(minimum.empty()); - } - // - // There is no way to read a chunk if none are available. - // - { - set want_to_read; - set available_chunks; - set minimum; - - want_to_read.insert(0); - - EXPECT_EQ(-EIO, Isa.minimum_to_decode(want_to_read, - available_chunks, - &minimum)); - } - // - // Reading a subset of the available chunks is always possible. - // - { - set want_to_read; - set available_chunks; - set minimum; - - want_to_read.insert(0); - available_chunks.insert(0); - - EXPECT_EQ(0, Isa.minimum_to_decode(want_to_read, - available_chunks, - &minimum)); - EXPECT_EQ(want_to_read, minimum); - } - // - // There is no way to read a missing chunk if there is less than k - // chunks available. - // - { - set want_to_read; - set available_chunks; - set minimum; - - want_to_read.insert(0); - want_to_read.insert(1); - available_chunks.insert(0); - - EXPECT_EQ(-EIO, Isa.minimum_to_decode(want_to_read, - available_chunks, - &minimum)); - } - // - // When chunks are not available, the minimum can be made of any - // chunks. For instance, to read 1 and 3 below the minimum could be - // 2 and 3 which may seem better because it contains one of the - // chunks to be read. But it won't be more efficient than retrieving - // 0 and 2 instead because, in both cases, the decode function will - // need to run the same recovery operation and use the same amount - // of CPU and memory. - // - { - set want_to_read; - set available_chunks; - set minimum; - - want_to_read.insert(1); - want_to_read.insert(3); - available_chunks.insert(0); - available_chunks.insert(2); - available_chunks.insert(3); - - EXPECT_EQ(0, Isa.minimum_to_decode(want_to_read, - available_chunks, - &minimum)); - EXPECT_EQ(2u, minimum.size()); - EXPECT_EQ(0u, minimum.count(3)); - } -} - -TEST_F(IsaErasureCodeTest, chunk_size) -{ - { - ErasureCodeIsaDefault Isa(tcache); - ErasureCodeProfile profile; - profile["k"] = "2"; - profile["m"] = "1"; - Isa.init(profile, &cerr); - const int k = 2; - - ASSERT_EQ(EC_ISA_ADDRESS_ALIGNMENT, Isa.get_chunk_size(1)); - ASSERT_EQ(EC_ISA_ADDRESS_ALIGNMENT, Isa.get_chunk_size(EC_ISA_ADDRESS_ALIGNMENT * k - 1)); - ASSERT_EQ(EC_ISA_ADDRESS_ALIGNMENT * 2, Isa.get_chunk_size(EC_ISA_ADDRESS_ALIGNMENT * k + 1)); - } - { - ErasureCodeIsaDefault Isa(tcache); - ErasureCodeProfile profile; - profile["k"] = "3"; - profile["m"] = "1"; - Isa.init(profile, &cerr); - const int k = 3; - - ASSERT_EQ(EC_ISA_ADDRESS_ALIGNMENT, Isa.get_chunk_size(1)); - ASSERT_EQ(EC_ISA_ADDRESS_ALIGNMENT, Isa.get_chunk_size(EC_ISA_ADDRESS_ALIGNMENT * k - 1)); - ASSERT_EQ(EC_ISA_ADDRESS_ALIGNMENT * 2, Isa.get_chunk_size(EC_ISA_ADDRESS_ALIGNMENT * k + 1)); - unsigned object_size = EC_ISA_ADDRESS_ALIGNMENT * k * 1024 + 1; - ASSERT_NE(0u, object_size % k); - ASSERT_NE(0u, object_size % EC_ISA_ADDRESS_ALIGNMENT); - unsigned chunk_size = Isa.get_chunk_size(object_size); - ASSERT_EQ(0u, chunk_size % EC_ISA_ADDRESS_ALIGNMENT); - ASSERT_GT(chunk_size, (chunk_size * k) - object_size); - } -} - -TEST_F(IsaErasureCodeTest, encode) -{ - ErasureCodeIsaDefault Isa(tcache); - ErasureCodeProfile profile; - profile["k"] = "2"; - profile["m"] = "2"; - Isa.init(profile, &cerr); - - unsigned aligned_object_size = Isa.get_alignment() * 2; - { - // - // When the input bufferlist needs to be padded because - // it is not properly aligned, it is padded with zeros. - // - bufferlist in; - map encoded; - int want_to_encode[] = { 0, 1, 2, 3 }; - int trail_length = 1; - in.append(string(aligned_object_size + trail_length, 'X')); - EXPECT_EQ(0, Isa.encode(set(want_to_encode, want_to_encode+4), - in, - &encoded)); - EXPECT_EQ(4u, encoded.size()); - char *last_chunk = encoded[1].c_str(); - int length =encoded[1].length(); - EXPECT_EQ('X', last_chunk[0]); - EXPECT_EQ('\0', last_chunk[length - trail_length]); - } - - { - // - // When only the first chunk is required, the encoded map only - // contains the first chunk. Although the Isa encode - // internally allocated a buffer because of padding requirements - // and also computes the coding chunks, they are released before - // the return of the method, as shown when running the tests thru - // valgrind (there is no leak). - // - bufferlist in; - map encoded; - set want_to_encode; - want_to_encode.insert(0); - int trail_length = 1; - in.append(string(aligned_object_size + trail_length, 'X')); - EXPECT_EQ(0, Isa.encode(want_to_encode, in, &encoded)); - EXPECT_EQ(1u, encoded.size()); - } -} - -TEST_F(IsaErasureCodeTest, sanity_check_k) -{ - ErasureCodeIsaDefault Isa(tcache); - ErasureCodeProfile profile; - profile["k"] = "1"; - profile["m"] = "1"; - ostringstream errors; - EXPECT_EQ(-EINVAL, Isa.init(profile, &errors)); - EXPECT_NE(std::string::npos, errors.str().find("must be >= 2")); -} - -bool -DecodeAndVerify(ErasureCodeIsaDefault& Isa, map °raded, set want_to_decode, buffer::ptr* enc, int length) -{ - map decoded; - bool ok; - - // decode as requested - ok = Isa.decode(want_to_decode, - degraded, - &decoded); - - for (int i = 0; i < (int) decoded.size(); i++) { - // compare all the buffers with their original - ok |= memcmp(decoded[i].c_str(), enc[i].c_str(), length); - } - - return ok; -} - -TEST_F(IsaErasureCodeTest, isa_vandermonde_exhaustive) -{ - // Test all possible failure scenarios and reconstruction cases for - // a (12,4) configuration using the vandermonde matrix - - ErasureCodeIsaDefault Isa(tcache); - ErasureCodeProfile profile; - profile["k"] = "12"; - profile["m"] = "4"; - Isa.init(profile, &cerr); - - const int k = 12; - const int m = 4; - -#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, memcmp(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 - int cnt_cf = 0; - - for (int l1 = 0; l1 < (k + m); l1++) { - map degraded = encoded; - set want_to_decode; - bool err; - degraded.erase(l1); - want_to_decode.insert(l1); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - cnt_cf++; - for (int l2 = l1 + 1; l2 < (k + m); l2++) { - degraded.erase(l2); - want_to_decode.insert(l2); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - cnt_cf++; - for (int l3 = l2 + 1; l3 < (k + m); l3++) { - degraded.erase(l3); - want_to_decode.insert(l3); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - cnt_cf++; - for (int l4 = l3 + 1; l4 < (k + m); l4++) { - degraded.erase(l4); - want_to_decode.insert(l4); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - degraded[l4] = encoded[l4]; - want_to_decode.erase(l4); - cnt_cf++; - } - degraded[l3] = encoded[l3]; - want_to_decode.erase(l3); - } - degraded[l2] = encoded[l2]; - want_to_decode.erase(l2); - } - degraded[l1] = encoded[l1]; - want_to_decode.erase(l1); - } - EXPECT_EQ(2516, cnt_cf); - EXPECT_EQ(2506, tcache.getDecodingTableCacheSize()); // 3 entries from (2,2) test and 2503 from (12,4) -} - -TEST_F(IsaErasureCodeTest, isa_cauchy_exhaustive) -{ - // Test all possible failure scenarios and reconstruction cases for - // a (12,4) configuration using the cauchy matrix - ErasureCodeIsaDefault Isa(tcache,ErasureCodeIsaDefault::kCauchy); - ErasureCodeProfile profile; - profile["k"] = "12"; - profile["m"] = "4"; - profile["technique"] = "cauchy"; - - Isa.init(profile, &cerr); - - const int k = 12; - const int m = 4; - -#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, memcmp(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 - int cnt_cf = 0; - - for (int l1 = 0; l1 < (k + m); l1++) { - map degraded = encoded; - set want_to_decode; - bool err; - degraded.erase(l1); - want_to_decode.insert(l1); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - cnt_cf++; - for (int l2 = l1 + 1; l2 < (k + m); l2++) { - degraded.erase(l2); - want_to_decode.insert(l2); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - cnt_cf++; - for (int l3 = l2 + 1; l3 < (k + m); l3++) { - degraded.erase(l3); - want_to_decode.insert(l3); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - cnt_cf++; - for (int l4 = l3 + 1; l4 < (k + m); l4++) { - degraded.erase(l4); - want_to_decode.insert(l4); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - degraded[l4] = encoded[l4]; - want_to_decode.erase(l4); - cnt_cf++; - } - degraded[l3] = encoded[l3]; - want_to_decode.erase(l3); - } - degraded[l2] = encoded[l2]; - want_to_decode.erase(l2); - } - degraded[l1] = encoded[l1]; - want_to_decode.erase(l1); - } - EXPECT_EQ(2516, cnt_cf); - EXPECT_EQ(2516, tcache.getDecodingTableCacheSize(ErasureCodeIsaDefault::kCauchy)); -} - -TEST_F(IsaErasureCodeTest, isa_cauchy_cache_trash) -{ - // Test all possible failure scenarios and reconstruction cases for - // a (12,4) configuration using the cauchy matrix - ErasureCodeIsaDefault Isa(tcache,ErasureCodeIsaDefault::kCauchy); - ErasureCodeProfile profile; - profile["k"] = "16"; - profile["m"] = "4"; - profile["technique"] = "cauchy"; - - Isa.init(profile, &cerr); - - const int k = 16; - const int m = 4; - -#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, memcmp(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 - int cnt_cf = 0; - - for (int l1 = 0; l1 < (k + m); l1++) { - map degraded = encoded; - set want_to_decode; - bool err; - degraded.erase(l1); - want_to_decode.insert(l1); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - cnt_cf++; - for (int l2 = l1 + 1; l2 < (k + m); l2++) { - degraded.erase(l2); - want_to_decode.insert(l2); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - cnt_cf++; - for (int l3 = l2 + 1; l3 < (k + m); l3++) { - degraded.erase(l3); - want_to_decode.insert(l3); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - cnt_cf++; - for (int l4 = l3 + 1; l4 < (k + m); l4++) { - degraded.erase(l4); - want_to_decode.insert(l4); - err = DecodeAndVerify(Isa, degraded, want_to_decode, enc, length); - EXPECT_EQ(0, err); - degraded[l4] = encoded[l4]; - want_to_decode.erase(l4); - cnt_cf++; - } - degraded[l3] = encoded[l3]; - want_to_decode.erase(l3); - } - degraded[l2] = encoded[l2]; - want_to_decode.erase(l2); - } - degraded[l1] = encoded[l1]; - want_to_decode.erase(l1); - } - EXPECT_EQ(6195, cnt_cf); - EXPECT_EQ(2516, tcache.getDecodingTableCacheSize(ErasureCodeIsaDefault::kCauchy)); -} - -TEST_F(IsaErasureCodeTest, isa_xor_codec) -{ - // Test all possible failure scenarios and reconstruction cases for - // a (4,1) RAID-5 like configuration - - ErasureCodeIsaDefault Isa(tcache); - ErasureCodeProfile profile; - profile["k"] = "4"; - profile["m"] = "1"; - Isa.init(profile, &cerr); - - const int k = 4; - const 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, memcmp(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 - int cnt_cf = 0; - - for (int l1 = 0; l1 < (k + m); l1++) { - map degraded = encoded; - set want_to_decode; - bool err; - 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); -} - -TEST_F(IsaErasureCodeTest, create_rule) -{ - CrushWrapper *c = new CrushWrapper; - c->create(); - int root_type = 2; - c->set_type_name(root_type, "root"); - int host_type = 1; - c->set_type_name(host_type, "host"); - int osd_type = 0; - c->set_type_name(osd_type, "osd"); - - int rootno; - c->add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_RJENKINS1, - root_type, 0, NULL, NULL, &rootno); - c->set_item_name(rootno, "default"); - - map loc; - loc["root"] = "default"; - - int num_host = 4; - int num_osd = 5; - int osd = 0; - for (int h=0; hinsert_item(g_ceph_context, osd, 1.0, string("osd.") + stringify(osd), loc); - } - } - - c->finalize(); - - { - stringstream ss; - ErasureCodeIsaDefault isa(tcache); - ErasureCodeProfile profile; - profile["k"] = "2"; - profile["m"] = "2"; - profile["w"] = "8"; - isa.init(profile, &cerr); - int ruleset = isa.create_rule("myrule", *c, &ss); - EXPECT_EQ(0, ruleset); - EXPECT_EQ(-EEXIST, isa.create_rule("myrule", *c, &ss)); - // - // the minimum that is expected from the created ruleset is to - // successfully map get_chunk_count() devices from the crushmap, - // at least once. - // - vector<__u32> weight(c->get_max_devices(), 0x10000); - vector out; - int x = 0; - c->do_rule(ruleset, x, out, isa.get_chunk_count(), weight, 0); - ASSERT_EQ(out.size(), isa.get_chunk_count()); - for (unsigned i=0; i