X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Ferasure-code%2FTestErasureCodeLrc.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Ferasure-code%2FTestErasureCodeLrc.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=72747a5a60bae069eece6afe2e774ce0d32e6bab;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/test/erasure-code/TestErasureCodeLrc.cc b/src/ceph/src/test/erasure-code/TestErasureCodeLrc.cc deleted file mode 100644 index 72747a5..0000000 --- a/src/ceph/src/test/erasure-code/TestErasureCodeLrc.cc +++ /dev/null @@ -1,918 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph distributed storage system - * - * Copyright (C) 2014 Cloudwatt - * Copyright (C) 2014 Red Hat - * - * 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/lrc/ErasureCodeLrc.h" -#include "global/global_context.h" -#include "common/config.h" -#include "gtest/gtest.h" - - -TEST(ErasureCodeLrc, parse_rule) -{ - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - EXPECT_EQ("default", lrc.rule_root); - EXPECT_EQ("host", lrc.rule_steps.front().type); - - ErasureCodeProfile profile; - profile["crush-root"] = "other"; - EXPECT_EQ(0, lrc.parse_rule(profile, &cerr)); - EXPECT_EQ("other", lrc.rule_root); - - profile["crush-steps"] = "[]"; - EXPECT_EQ(0, lrc.parse_rule(profile, &cerr)); - EXPECT_TRUE(lrc.rule_steps.empty()); - - profile["crush-steps"] = "0"; - EXPECT_EQ(ERROR_LRC_ARRAY, lrc.parse_rule(profile, &cerr)); - - profile["crush-steps"] = "{"; - EXPECT_EQ(ERROR_LRC_PARSE_JSON, lrc.parse_rule(profile, &cerr)); - - profile["crush-steps"] = "[0]"; - EXPECT_EQ(ERROR_LRC_ARRAY, lrc.parse_rule(profile, &cerr)); - - profile["crush-steps"] = "[[0]]"; - EXPECT_EQ(ERROR_LRC_RULE_OP, lrc.parse_rule(profile, &cerr)); - - profile["crush-steps"] = "[[\"choose\", 0]]"; - EXPECT_EQ(ERROR_LRC_RULE_TYPE, lrc.parse_rule(profile, &cerr)); - - profile["crush-steps"] = "[[\"choose\", \"host\", []]]"; - EXPECT_EQ(ERROR_LRC_RULE_N, lrc.parse_rule(profile, &cerr)); - - profile["crush-steps"] = "[[\"choose\", \"host\", 2]]"; - EXPECT_EQ(0, lrc.parse_rule(profile, &cerr)); - - const ErasureCodeLrc::Step &step = lrc.rule_steps.front(); - EXPECT_EQ("choose", step.op); - EXPECT_EQ("host", step.type); - EXPECT_EQ(2, step.n); - - profile["crush-steps"] = - "[" - " [\"choose\", \"rack\", 2], " - " [\"chooseleaf\", \"host\", 5], " - "]"; - EXPECT_EQ(0, lrc.parse_rule(profile, &cerr)); - EXPECT_EQ(2U, lrc.rule_steps.size()); - { - const ErasureCodeLrc::Step &step = lrc.rule_steps[0]; - EXPECT_EQ("choose", step.op); - EXPECT_EQ("rack", step.type); - EXPECT_EQ(2, step.n); - } - { - const ErasureCodeLrc::Step &step = lrc.rule_steps[1]; - EXPECT_EQ("chooseleaf", step.op); - EXPECT_EQ("host", step.type); - EXPECT_EQ(5, step.n); - } -} - -TEST(ErasureCodeTest, create_rule) -{ - CrushWrapper *c = new CrushWrapper; - c->create(); - int root_type = 3; - c->set_type_name(root_type, "root"); - int rack_type = 2; - c->set_type_name(rack_type, "rack"); - 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"; - - // - // Set all to 10 so that the item number it trivial to decompose - // into rack/host/osd. - // - int num_rack; - int num_host; - int num_osd; - num_rack = num_host = num_osd = 10; - int osd = 0; - for (int r=0; rinsert_item(g_ceph_context, osd, 1.0, string("osd.") + stringify(osd), loc); - } - } - } - - c->finalize(); - - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - EXPECT_EQ(0, lrc.create_rule("rule1", *c, &cerr)); - - ErasureCodeProfile profile; - unsigned int racks = 2; - unsigned int hosts = 5; - profile["crush-steps"] = - "[" - " [\"choose\", \"rack\", " + stringify(racks) + "], " - " [\"chooseleaf\", \"host\", " + stringify(hosts) + "], " - "]"; - const char *rule_name = "rule2"; - EXPECT_EQ(0, lrc.parse_rule(profile, &cerr)); - EXPECT_EQ(1, lrc.create_rule(rule_name, *c, &cerr)); - - vector<__u32> weight; - for (int o = 0; o < c->get_max_devices(); o++) - weight.push_back(0x10000); - int rule = c->get_rule_id(rule_name); - vector out; - unsigned int n = racks * hosts; - c->do_rule(rule, 1, out, n, weight, 0); - EXPECT_EQ(n, out.size()); - // - // check that the first five are in the same rack and the next five - // in the same rack - // - int first_rack = out[0] / num_host / num_osd; - EXPECT_EQ(first_rack, out[1] / num_host / num_osd); - EXPECT_EQ(first_rack, out[2] / num_host / num_osd); - EXPECT_EQ(first_rack, out[3] / num_host / num_osd); - EXPECT_EQ(first_rack, out[4] / num_host / num_osd); - int second_rack = out[5] / num_host / num_osd; - EXPECT_EQ(second_rack, out[6] / num_host / num_osd); - EXPECT_EQ(second_rack, out[7] / num_host / num_osd); - EXPECT_EQ(second_rack, out[8] / num_host / num_osd); - EXPECT_EQ(second_rack, out[9] / num_host / num_osd); -} - -TEST(ErasureCodeLrc, parse_kml) -{ - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - EXPECT_EQ(0, lrc.parse_kml(profile, &cerr)); - profile["k"] = "4"; - EXPECT_EQ(ERROR_LRC_ALL_OR_NOTHING, lrc.parse_kml(profile, &cerr)); - const char *generated[] = { "mapping", - "layers", - "crush-steps" }; - profile["m"] = "2"; - profile["l"] = "3"; - - for (int i = 0; i < 3; i++) { - profile[generated[i]] = "SET"; - EXPECT_EQ(ERROR_LRC_GENERATED, lrc.parse_kml(profile, &cerr)); - profile.erase(profile.find(generated[i])); - } - - profile["k"] = "4"; - profile["m"] = "2"; - profile["l"] = "7"; - EXPECT_EQ(ERROR_LRC_K_M_MODULO, lrc.parse_kml(profile, &cerr)); - - profile["k"] = "3"; - profile["m"] = "3"; - profile["l"] = "3"; - EXPECT_EQ(ERROR_LRC_K_MODULO, lrc.parse_kml(profile, &cerr)); - - profile["k"] = "4"; - profile["m"] = "2"; - profile["l"] = "3"; - EXPECT_EQ(0, lrc.parse_kml(profile, &cerr)); - EXPECT_EQ("[ " - " [ \"DDc_DDc_\", \"\" ]," - " [ \"DDDc____\", \"\" ]," - " [ \"____DDDc\", \"\" ]," - "]", profile["layers"]); - EXPECT_EQ("DD__DD__", profile["mapping"]); - EXPECT_EQ("chooseleaf", lrc.rule_steps[0].op); - EXPECT_EQ("host", lrc.rule_steps[0].type); - EXPECT_EQ(0, lrc.rule_steps[0].n); - EXPECT_EQ(1U, lrc.rule_steps.size()); - profile.erase(profile.find("mapping")); - profile.erase(profile.find("layers")); - - profile["k"] = "4"; - profile["m"] = "2"; - profile["l"] = "3"; - profile["crush-failure-domain"] = "osd"; - EXPECT_EQ(0, lrc.parse_kml(profile, &cerr)); - EXPECT_EQ("chooseleaf", lrc.rule_steps[0].op); - EXPECT_EQ("osd", lrc.rule_steps[0].type); - EXPECT_EQ(0, lrc.rule_steps[0].n); - EXPECT_EQ(1U, lrc.rule_steps.size()); - profile.erase(profile.find("mapping")); - profile.erase(profile.find("layers")); - - profile["k"] = "4"; - profile["m"] = "2"; - profile["l"] = "3"; - profile["crush-failure-domain"] = "osd"; - profile["crush-locality"] = "rack"; - EXPECT_EQ(0, lrc.parse_kml(profile, &cerr)); - EXPECT_EQ("choose", lrc.rule_steps[0].op); - EXPECT_EQ("rack", lrc.rule_steps[0].type); - EXPECT_EQ(2, lrc.rule_steps[0].n); - EXPECT_EQ("chooseleaf", lrc.rule_steps[1].op); - EXPECT_EQ("osd", lrc.rule_steps[1].type); - EXPECT_EQ(4, lrc.rule_steps[1].n); - EXPECT_EQ(2U, lrc.rule_steps.size()); - profile.erase(profile.find("mapping")); - profile.erase(profile.find("layers")); -} - -TEST(ErasureCodeLrc, layers_description) -{ - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - - json_spirit::mArray description; - EXPECT_EQ(ERROR_LRC_DESCRIPTION, - lrc.layers_description(profile, &description, &cerr)); - - { - const char *description_string = "\"not an array\""; - profile["layers"] = description_string; - EXPECT_EQ(ERROR_LRC_ARRAY, - lrc.layers_description(profile, &description, &cerr)); - } - { - const char *description_string = "invalid json"; - profile["layers"] = description_string; - EXPECT_EQ(ERROR_LRC_PARSE_JSON, - lrc.layers_description(profile, &description, &cerr)); - } - { - const char *description_string = "[]"; - profile["layers"] = description_string; - EXPECT_EQ(0, lrc.layers_description(profile, &description, &cerr)); - } -} - -TEST(ErasureCodeLrc, layers_parse) -{ - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - - const char *description_string ="[ 0 ]"; - profile["layers"] = description_string; - json_spirit::mArray description; - EXPECT_EQ(0, lrc.layers_description(profile, &description, &cerr)); - EXPECT_EQ(ERROR_LRC_ARRAY, - lrc.layers_parse(description_string, description, &cerr)); - } - - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - - const char *description_string ="[ [ 0 ] ]"; - profile["layers"] = description_string; - json_spirit::mArray description; - EXPECT_EQ(0, lrc.layers_description(profile, &description, &cerr)); - EXPECT_EQ(ERROR_LRC_STR, - lrc.layers_parse(description_string, description, &cerr)); - } - - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - - const char *description_string ="[ [ \"\", 0 ] ]"; - profile["layers"] = description_string; - json_spirit::mArray description; - EXPECT_EQ(0, lrc.layers_description(profile, &description, &cerr)); - EXPECT_EQ(ERROR_LRC_CONFIG_OPTIONS, - lrc.layers_parse(description_string, description, &cerr)); - } - - // - // The second element can be an object describing the plugin - // profile. - // - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - - const char *description_string ="[ [ \"\", { \"a\": \"b\" }, \"ignored\" ] ]"; - profile["layers"] = description_string; - json_spirit::mArray description; - EXPECT_EQ(0, lrc.layers_description(profile, &description, &cerr)); - EXPECT_EQ(0, lrc.layers_parse(description_string, description, &cerr)); - EXPECT_EQ("b", lrc.layers.front().profile["a"]); - } - - // - // The second element can be a str_map parseable string describing the plugin - // profile. - // - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - - const char *description_string ="[ [ \"\", \"a=b c=d\" ] ]"; - profile["layers"] = description_string; - json_spirit::mArray description; - EXPECT_EQ(0, lrc.layers_description(profile, &description, &cerr)); - EXPECT_EQ(0, lrc.layers_parse(description_string, description, &cerr)); - EXPECT_EQ("b", lrc.layers.front().profile["a"]); - EXPECT_EQ("d", lrc.layers.front().profile["c"]); - } - -} - -TEST(ErasureCodeLrc, layers_sanity_checks) -{ - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["mapping"] = - "__DDD__DD"; - const char *description_string = - "[ " - " [ \"_cDDD_cDD\", \"\" ]," - " [ \"c_DDD____\", \"\" ]," - " [ \"_____cDDD\", \"\" ]," - "]"; - profile["layers"] = description_string; - EXPECT_EQ(0, lrc.init(profile, &cerr)); - } - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - const char *description_string = - "[ " - "]"; - profile["layers"] = description_string; - EXPECT_EQ(ERROR_LRC_MAPPING, lrc.init(profile, &cerr)); - } - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["mapping"] = ""; - const char *description_string = - "[ " - "]"; - profile["layers"] = description_string; - EXPECT_EQ(ERROR_LRC_LAYERS_COUNT, lrc.init(profile, &cerr)); - } - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["mapping"] = - "DD"; - const char *description_string = - "[ " - " [ \"DD??\", \"\" ], " - " [ \"DD\", \"\" ], " - " [ \"DD\", \"\" ], " - "]"; - profile["layers"] = description_string; - EXPECT_EQ(ERROR_LRC_MAPPING_SIZE, lrc.init(profile, &cerr)); - } -} - -TEST(ErasureCodeLrc, layers_init) -{ - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - - const char* env = getenv("CEPH_LIB"); - string directory(env ? env : ".libs"); - string description_string = - "[ " - " [ \"_cDDD_cDD_\", \"directory=" + directory + "\" ]," - "]"; - profile["layers"] = description_string; - json_spirit::mArray description; - EXPECT_EQ(0, lrc.layers_description(profile, &description, &cerr)); - EXPECT_EQ(0, lrc.layers_parse(description_string, description, &cerr)); - EXPECT_EQ(0, lrc.layers_init(&cerr)); - EXPECT_EQ("5", lrc.layers.front().profile["k"]); - EXPECT_EQ("2", lrc.layers.front().profile["m"]); - EXPECT_EQ("jerasure", lrc.layers.front().profile["plugin"]); - EXPECT_EQ("reed_sol_van", lrc.layers.front().profile["technique"]); - } -} - -TEST(ErasureCodeLrc, init) -{ - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["mapping"] = - "__DDD__DD"; - const char *description_string = - "[ " - " [ \"_cDDD_cDD\", \"\" ]," - " [ \"c_DDD____\", \"\" ]," - " [ \"_____cDDD\", \"\" ]," - "]"; - profile["layers"] = description_string; - EXPECT_EQ(0, lrc.init(profile, &cerr)); -} - -TEST(ErasureCodeLrc, init_kml) -{ - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["k"] = "4"; - profile["m"] = "2"; - profile["l"] = "3"; - EXPECT_EQ(0, lrc.init(profile, &cerr)); - EXPECT_EQ((unsigned int)(4 + 2 + (4 + 2) / 3), lrc.get_chunk_count()); -} - -TEST(ErasureCodeLrc, minimum_to_decode) -{ - // trivial : no erasures, the minimum is want_to_read - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["mapping"] = - "__DDD__DD"; - const char *description_string = - "[ " - " [ \"_cDDD_cDD\", \"\" ]," - " [ \"c_DDD____\", \"\" ]," - " [ \"_____cDDD\", \"\" ]," - "]"; - profile["layers"] = description_string; - EXPECT_EQ(0, lrc.init(profile, &cerr)); - set want_to_read; - want_to_read.insert(1); - set available_chunks; - available_chunks.insert(1); - available_chunks.insert(2); - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - EXPECT_EQ(want_to_read, minimum); - } - // locally repairable erasure - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["mapping"] = - "__DDD__DD_"; - const char *description_string = - "[ " - " [ \"_cDDD_cDD_\", \"\" ]," - " [ \"c_DDD_____\", \"\" ]," - " [ \"_____cDDD_\", \"\" ]," - " [ \"_____DDDDc\", \"\" ]," - "]"; - profile["layers"] = description_string; - EXPECT_EQ(0, lrc.init(profile, &cerr)); - EXPECT_EQ(profile["mapping"].length(), - lrc.get_chunk_count()); - { - // want to read the last chunk - set want_to_read; - want_to_read.insert(lrc.get_chunk_count() - 1); - // all chunks are available except the last chunk - set available_chunks; - for (int i = 0; i < (int)lrc.get_chunk_count() - 1; i++) - available_chunks.insert(i); - // _____DDDDc can recover c - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - set expected_minimum; - expected_minimum.insert(5); - expected_minimum.insert(6); - expected_minimum.insert(7); - expected_minimum.insert(8); - EXPECT_EQ(expected_minimum, minimum); - } - { - set want_to_read; - want_to_read.insert(0); - set available_chunks; - for (int i = 1; i < (int)lrc.get_chunk_count(); i++) - available_chunks.insert(i); - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - set expected_minimum; - expected_minimum.insert(2); - expected_minimum.insert(3); - expected_minimum.insert(4); - EXPECT_EQ(expected_minimum, minimum); - } - } - // implicit parity required - { - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["mapping"] = - "__DDD__DD"; - const char *description_string = - "[ " - " [ \"_cDDD_cDD\", \"\" ]," - " [ \"c_DDD____\", \"\" ]," - " [ \"_____cDDD\", \"\" ]," - "]"; - profile["layers"] = description_string; - EXPECT_EQ(0, lrc.init(profile, &cerr)); - EXPECT_EQ(profile["mapping"].length(), - lrc.get_chunk_count()); - set want_to_read; - want_to_read.insert(8); - // - // unable to recover, too many chunks missing - // - { - set available_chunks; - available_chunks.insert(0); - available_chunks.insert(1); - // missing (2) - // missing (3) - available_chunks.insert(4); - available_chunks.insert(5); - available_chunks.insert(6); - // missing (7) - // missing (8) - set minimum; - EXPECT_EQ(-EIO, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - } - // - // We want to read chunk 8 and encoding was done with - // - // _cDDD_cDD - // c_DDD____ - // _____cDDD - // - // First strategy fails: - // - // 012345678 - // xxXXXxxXX initial chunks - // xx.XXxx.. missing (2, 7, 8) - // _____cDDD fail : can recover 1 but 2 are missing - // c_DDD____ ignored because 8 is not used (i.e. _) - // _cDDD_cDD fail : can recover 2 but 3 are missing - // - // Second strategy succeeds: - // - // 012345678 - // xxXXXxxXX initial chunks - // xx.XXxx.. missing (2, 7, 8) - // _____cDDD fail : can recover 1 but 2 are missing - // c_DDD____ success: recovers chunk 2 - // _cDDD_cDD success: recovers chunk 7, 8 - // - { - set available_chunks; - available_chunks.insert(0); - available_chunks.insert(1); - // missing (2) - available_chunks.insert(3); - available_chunks.insert(4); - available_chunks.insert(5); - available_chunks.insert(6); - // missing (7) - // missing (8) - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - EXPECT_EQ(available_chunks, minimum); - } - } -} - -TEST(ErasureCodeLrc, encode_decode) -{ - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["mapping"] = - "__DD__DD"; - const char *description_string = - "[ " - " [ \"_cDD_cDD\", \"\" ]," // global layer - " [ \"c_DD____\", \"\" ]," // first local layer - " [ \"____cDDD\", \"\" ]," // second local layer - "]"; - profile["layers"] = description_string; - EXPECT_EQ(0, lrc.init(profile, &cerr)); - EXPECT_EQ(4U, lrc.get_data_chunk_count()); - unsigned int chunk_size = g_conf->osd_pool_erasure_code_stripe_unit; - unsigned int stripe_width = lrc.get_data_chunk_count() * chunk_size; - EXPECT_EQ(chunk_size, lrc.get_chunk_size(stripe_width)); - set want_to_encode; - map encoded; - for (unsigned int i = 0; i < lrc.get_chunk_count(); ++i) { - want_to_encode.insert(i); - bufferptr ptr(buffer::create_page_aligned(chunk_size)); - encoded[i].push_front(ptr); - } - const vector &mapping = lrc.get_chunk_mapping(); - char c = 'A'; - for (unsigned int i = 0; i < lrc.get_data_chunk_count(); i++) { - int j = mapping[i]; - string s(chunk_size, c); - encoded[j].clear(); - encoded[j].append(s); - c++; - } - EXPECT_EQ(0, lrc.encode_chunks(want_to_encode, &encoded)); - - { - map chunks; - chunks[4] = encoded[4]; - chunks[5] = encoded[5]; - chunks[6] = encoded[6]; - set want_to_read; - want_to_read.insert(7); - set available_chunks; - available_chunks.insert(4); - available_chunks.insert(5); - available_chunks.insert(6); - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - // only need three chunks from the second local layer - EXPECT_EQ(3U, minimum.size()); - EXPECT_EQ(1U, minimum.count(4)); - EXPECT_EQ(1U, minimum.count(5)); - EXPECT_EQ(1U, minimum.count(6)); - map decoded; - EXPECT_EQ(0, lrc.decode(want_to_read, chunks, &decoded)); - string s(chunk_size, 'D'); - EXPECT_EQ(s, string(decoded[7].c_str(), chunk_size)); - } - { - set want_to_read; - want_to_read.insert(2); - map chunks; - chunks[1] = encoded[1]; - chunks[3] = encoded[3]; - chunks[5] = encoded[5]; - chunks[6] = encoded[6]; - chunks[7] = encoded[7]; - set available_chunks; - available_chunks.insert(1); - available_chunks.insert(3); - available_chunks.insert(5); - available_chunks.insert(6); - available_chunks.insert(7); - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - EXPECT_EQ(5U, minimum.size()); - EXPECT_EQ(available_chunks, minimum); - - map decoded; - EXPECT_EQ(0, lrc.decode(want_to_read, encoded, &decoded)); - string s(chunk_size, 'A'); - EXPECT_EQ(s, string(decoded[2].c_str(), chunk_size)); - } - { - set want_to_read; - want_to_read.insert(3); - want_to_read.insert(6); - want_to_read.insert(7); - set available_chunks; - available_chunks.insert(0); - available_chunks.insert(1); - available_chunks.insert(2); - // available_chunks.insert(3); - available_chunks.insert(4); - available_chunks.insert(5); - // available_chunks.insert(6); - // available_chunks.insert(7); - encoded.erase(3); - encoded.erase(6); - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - EXPECT_EQ(4U, minimum.size()); - // only need two chunks from the first local layer - EXPECT_EQ(1U, minimum.count(0)); - EXPECT_EQ(1U, minimum.count(2)); - // the above chunks will rebuild chunk 3 and the global layer only needs - // three more chunks to reach the required amount of chunks (4) to recover - // the last two - EXPECT_EQ(1U, minimum.count(1)); - EXPECT_EQ(1U, minimum.count(2)); - EXPECT_EQ(1U, minimum.count(5)); - - map decoded; - EXPECT_EQ(0, lrc.decode(want_to_read, encoded, &decoded)); - { - string s(chunk_size, 'B'); - EXPECT_EQ(s, string(decoded[3].c_str(), chunk_size)); - } - { - string s(chunk_size, 'C'); - EXPECT_EQ(s, string(decoded[6].c_str(), chunk_size)); - } - { - string s(chunk_size, 'D'); - EXPECT_EQ(s, string(decoded[7].c_str(), chunk_size)); - } - } -} - -TEST(ErasureCodeLrc, encode_decode_2) -{ - ErasureCodeLrc lrc(g_conf->get_val("erasure_code_dir")); - ErasureCodeProfile profile; - profile["mapping"] = - "DD__DD__"; - const char *description_string = - "[ " - " [ \"DDc_DDc_\", \"\" ]," - " [ \"DDDc____\", \"\" ]," - " [ \"____DDDc\", \"\" ]," - "]"; - profile["layers"] = description_string; - EXPECT_EQ(0, lrc.init(profile, &cerr)); - EXPECT_EQ(4U, lrc.get_data_chunk_count()); - unsigned int chunk_size = g_conf->osd_pool_erasure_code_stripe_unit; - unsigned int stripe_width = lrc.get_data_chunk_count() * chunk_size; - EXPECT_EQ(chunk_size, lrc.get_chunk_size(stripe_width)); - set want_to_encode; - map encoded; - for (unsigned int i = 0; i < lrc.get_chunk_count(); ++i) { - want_to_encode.insert(i); - bufferptr ptr(buffer::create_page_aligned(chunk_size)); - encoded[i].push_front(ptr); - } - const vector &mapping = lrc.get_chunk_mapping(); - char c = 'A'; - for (unsigned int i = 0; i < lrc.get_data_chunk_count(); i++) { - int j = mapping[i]; - string s(chunk_size, c); - encoded[j].clear(); - encoded[j].append(s); - c++; - } - EXPECT_EQ(0, lrc.encode_chunks(want_to_encode, &encoded)); - - { - set want_to_read; - want_to_read.insert(0); - map chunks; - chunks[1] = encoded[1]; - chunks[3] = encoded[3]; - chunks[4] = encoded[4]; - chunks[5] = encoded[5]; - chunks[6] = encoded[6]; - chunks[7] = encoded[7]; - set available_chunks; - available_chunks.insert(1); - available_chunks.insert(3); - available_chunks.insert(4); - available_chunks.insert(5); - available_chunks.insert(6); - available_chunks.insert(7); - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - EXPECT_EQ(4U, minimum.size()); - EXPECT_EQ(1U, minimum.count(1)); - EXPECT_EQ(1U, minimum.count(4)); - EXPECT_EQ(1U, minimum.count(5)); - EXPECT_EQ(1U, minimum.count(6)); - - map decoded; - EXPECT_EQ(0, lrc.decode(want_to_read, chunks, &decoded)); - string s(chunk_size, 'A'); - EXPECT_EQ(s, string(decoded[0].c_str(), chunk_size)); - } - { - set want_to_read; - for (unsigned int i = 0; i < lrc.get_chunk_count(); i++) - want_to_read.insert(i); - map chunks; - chunks[1] = encoded[1]; - chunks[3] = encoded[3]; - chunks[5] = encoded[5]; - chunks[6] = encoded[6]; - chunks[7] = encoded[7]; - set available_chunks; - available_chunks.insert(1); - available_chunks.insert(3); - available_chunks.insert(5); - available_chunks.insert(6); - available_chunks.insert(7); - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - EXPECT_EQ(5U, minimum.size()); - EXPECT_EQ(1U, minimum.count(1)); - EXPECT_EQ(1U, minimum.count(3)); - EXPECT_EQ(1U, minimum.count(5)); - EXPECT_EQ(1U, minimum.count(6)); - EXPECT_EQ(1U, minimum.count(7)); - - map decoded; - EXPECT_EQ(0, lrc.decode(want_to_read, chunks, &decoded)); - { - string s(chunk_size, 'A'); - EXPECT_EQ(s, string(decoded[0].c_str(), chunk_size)); - } - { - string s(chunk_size, 'B'); - EXPECT_EQ(s, string(decoded[1].c_str(), chunk_size)); - } - { - string s(chunk_size, 'C'); - EXPECT_EQ(s, string(decoded[4].c_str(), chunk_size)); - } - { - string s(chunk_size, 'D'); - EXPECT_EQ(s, string(decoded[5].c_str(), chunk_size)); - } - } - { - set want_to_read; - for (unsigned int i = 0; i < lrc.get_chunk_count(); i++) - want_to_read.insert(i); - map chunks; - chunks[1] = encoded[1]; - chunks[3] = encoded[3]; - chunks[5] = encoded[5]; - chunks[6] = encoded[6]; - chunks[7] = encoded[7]; - set available_chunks; - available_chunks.insert(1); - available_chunks.insert(3); - available_chunks.insert(5); - available_chunks.insert(6); - available_chunks.insert(7); - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - EXPECT_EQ(5U, minimum.size()); - EXPECT_EQ(1U, minimum.count(1)); - EXPECT_EQ(1U, minimum.count(3)); - EXPECT_EQ(1U, minimum.count(5)); - EXPECT_EQ(1U, minimum.count(6)); - EXPECT_EQ(1U, minimum.count(7)); - - map decoded; - EXPECT_EQ(0, lrc.decode(want_to_read, chunks, &decoded)); - { - string s(chunk_size, 'A'); - EXPECT_EQ(s, string(decoded[0].c_str(), chunk_size)); - } - { - string s(chunk_size, 'B'); - EXPECT_EQ(s, string(decoded[1].c_str(), chunk_size)); - } - { - string s(chunk_size, 'C'); - EXPECT_EQ(s, string(decoded[4].c_str(), chunk_size)); - } - { - string s(chunk_size, 'D'); - EXPECT_EQ(s, string(decoded[5].c_str(), chunk_size)); - } - } - { - set want_to_read; - want_to_read.insert(6); - map chunks; - chunks[0] = encoded[0]; - chunks[1] = encoded[1]; - chunks[3] = encoded[3]; - chunks[5] = encoded[5]; - chunks[7] = encoded[7]; - set available_chunks; - available_chunks.insert(0); - available_chunks.insert(1); - available_chunks.insert(3); - available_chunks.insert(5); - available_chunks.insert(7); - set minimum; - EXPECT_EQ(0, lrc.minimum_to_decode(want_to_read, available_chunks, &minimum)); - EXPECT_EQ(available_chunks, minimum); - - map decoded; - EXPECT_EQ(0, lrc.decode(want_to_read, chunks, &decoded)); - } -} - -/* - * Local Variables: - * compile-command: "cd ../.. ; - * make -j4 unittest_erasure_code_lrc && valgrind --tool=memcheck \ - * ./unittest_erasure_code_lrc \ - * --gtest_filter=*.* --log-to-stderr=true --debug-osd=20" - * End: - */