1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2014,2015 FUJITSU LIMITED
8 * Author: Shotaro Kawaguchi <kawaguchi.s@jp.fujitsu.com>
9 * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
10 * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
19 // SUMMARY: TestErasureCodeShec combination of k,m,c by 301 patterns
24 #include "crush/CrushWrapper.h"
25 #include "osd/osd_types.h"
26 #include "include/stringify.h"
27 #include "global/global_init.h"
28 #include "erasure-code/shec/ErasureCodeShec.h"
29 #include "erasure-code/ErasureCodePlugin.h"
30 #include "common/ceph_argparse.h"
31 #include "global/global_context.h"
32 #include "gtest/gtest.h"
43 struct Param_d param
[301];
45 unsigned int g_recover
= 0;
46 unsigned int g_cannot_recover
= 0;
54 struct std::vector
<Recover_d
> cannot_recover
;
56 class ParameterTest
: public ::testing::TestWithParam
<struct Param_d
> {
60 TEST_P(ParameterTest
, parameter_all
)
64 char* k
= GetParam().k
;
65 char* m
= GetParam().m
;
66 char* c
= GetParam().c
;
67 unsigned c_size
= GetParam().ch_size
;
73 ErasureCodeShecTableCache tcache
;
74 ErasureCodeShec
* shec
= new ErasureCodeShecReedSolomonVandermonde(
76 ErasureCodeShec::MULTIPLE
);
77 ErasureCodeProfile
*profile
= new ErasureCodeProfile();
78 (*profile
)["plugin"] = "shec";
79 (*profile
)["technique"] = "";
80 (*profile
)["crush-failure-domain"] = "osd";
85 result
= shec
->init(*profile
, &cerr
);
88 EXPECT_EQ(i_k
, shec
->k
);
89 EXPECT_EQ(i_m
, shec
->m
);
90 EXPECT_EQ(i_c
, shec
->c
);
91 EXPECT_EQ(8, shec
->w
);
92 EXPECT_EQ(ErasureCodeShec::MULTIPLE
, shec
->technique
);
93 EXPECT_STREQ("default", shec
->rule_root
.c_str());
94 EXPECT_STREQ("osd", shec
->rule_failure_domain
.c_str());
95 EXPECT_TRUE(shec
->matrix
!= NULL
);
99 //want_to_decode will be a combination that chooses 1~c from k+m
100 set
<int> want_to_decode
, available_chunks
, minimum_chunks
;
101 int array_want_to_decode
[shec
->get_chunk_count()];
102 struct Recover_d comb
;
104 for (int w
= 1; w
<= i_c
; w
++) {
105 const unsigned int r
= w
; // combination(k+m,r)
107 for (unsigned int i
= 0; i
< r
; ++i
) {
108 array_want_to_decode
[i
] = 1;
110 for (unsigned int i
= r
; i
< shec
->get_chunk_count(); ++i
) {
111 array_want_to_decode
[i
] = 0;
115 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
116 available_chunks
.insert(i
);
118 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
119 if (array_want_to_decode
[i
]) {
120 want_to_decode
.insert(i
);
121 available_chunks
.erase(i
);
125 result
= shec
->minimum_to_decode(want_to_decode
, available_chunks
,
129 EXPECT_EQ(0, result
);
130 EXPECT_TRUE(minimum_chunks
.size());
133 EXPECT_EQ(-EIO
, result
);
134 EXPECT_EQ(0u, minimum_chunks
.size());
139 comb
.want
= want_to_decode
;
140 comb
.avail
= available_chunks
;
141 cannot_recover
.push_back(comb
);
144 want_to_decode
.clear();
145 available_chunks
.clear();
146 minimum_chunks
.clear();
147 } while (std::prev_permutation(
148 array_want_to_decode
,
149 array_want_to_decode
+ shec
->get_chunk_count()));
152 //minimum_to_decode_with_cost
153 set
<int> want_to_decode_with_cost
, minimum_chunks_with_cost
;
154 map
<int, int> available_chunks_with_cost
;
156 for (unsigned int i
= 0; i
< 1; i
++) {
157 want_to_decode_with_cost
.insert(i
);
159 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
160 available_chunks_with_cost
[i
] = i
;
163 result
= shec
->minimum_to_decode_with_cost(
164 want_to_decode_with_cost
,
165 available_chunks_with_cost
,
166 &minimum_chunks_with_cost
);
167 EXPECT_EQ(0, result
);
168 EXPECT_TRUE(minimum_chunks_with_cost
.size());
172 set
<int> want_to_encode
;
173 map
<int, bufferlist
> encoded
;
175 in
.append("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"//length = 62
176 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"//124
177 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"//186
180 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
181 want_to_encode
.insert(i
);
184 result
= shec
->encode(want_to_encode
, in
, &encoded
);
185 EXPECT_EQ(0, result
);
186 EXPECT_EQ(i_k
+i_m
, (int)encoded
.size());
187 EXPECT_EQ(c_size
, encoded
[0].length());
190 int want_to_decode2
[i_k
+ i_m
];
191 map
<int, bufferlist
> decoded
;
193 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
194 want_to_decode2
[i
] = i
;
197 result
= shec
->decode(set
<int>(want_to_decode2
, want_to_decode2
+ 2),
199 EXPECT_EQ(0, result
);
200 EXPECT_EQ(2u, decoded
.size());
201 EXPECT_EQ(c_size
, decoded
[0].length());
203 //check encoded,decoded
204 bufferlist out1
, out2
, usable
;
207 for (unsigned int i
= 0; i
< encoded
.size(); i
++) {
208 out1
.append(encoded
[i
]);
212 shec
->decode_concat(encoded
, &out2
);
213 usable
.substr_of(out2
, 0, in
.length());
215 EXPECT_FALSE(out1
== in
);
216 EXPECT_TRUE(usable
== in
);
220 CrushWrapper
*crush
= new CrushWrapper
;
222 crush
->set_type_name(2, "root");
223 crush
->set_type_name(1, "host");
224 crush
->set_type_name(0, "osd");
227 crush
->add_bucket(0, CRUSH_BUCKET_STRAW
, CRUSH_HASH_RJENKINS1
, 2, 0, NULL
,
229 crush
->set_item_name(rootno
, "default");
231 map
< string
, string
> loc
;
232 loc
["root"] = "default";
237 for (int h
= 0; h
< num_host
; ++h
) {
238 loc
["host"] = string("host-") + stringify(h
);
239 for (int o
= 0; o
< num_osd
; ++o
, ++osd
) {
240 crush
->insert_item(g_ceph_context
, osd
, 1.0,
241 string("osd.") + stringify(osd
), loc
);
245 result
= shec
->create_rule("myrule", *crush
, &ss
);
246 EXPECT_EQ(0, result
);
247 EXPECT_STREQ("myrule", crush
->rule_name_map
[0].c_str());
250 EXPECT_EQ(i_k
+i_m
, (int)shec
->get_chunk_count());
252 //get_data_chunk_count
253 EXPECT_EQ(i_k
, (int)shec
->get_data_chunk_count());
256 EXPECT_EQ(c_size
, shec
->get_chunk_size(192));
263 INSTANTIATE_TEST_CASE_P(Test
, ParameterTest
, ::testing::ValuesIn(param
));
265 int main(int argc
, char **argv
)
269 const int kObjectSize
= 192;
270 unsigned alignment
, tail
, padded_length
;
271 float recovery_percentage
;
274 for (unsigned int k
= 1; k
<= 12; k
++) {
275 for (unsigned int m
= 1; (m
<= k
) && (k
+ m
<= 20); m
++) {
276 for (unsigned int c
= 1; c
<= m
; c
++) {
277 sprintf(param
[i
].sk
, "%u", k
);
278 sprintf(param
[i
].sm
, "%u", m
);
279 sprintf(param
[i
].sc
, "%u", c
);
281 param
[i
].k
= param
[i
].sk
;
282 param
[i
].m
= param
[i
].sm
;
283 param
[i
].c
= param
[i
].sc
;
285 alignment
= k
* 8 * sizeof(int);
286 tail
= kObjectSize
% alignment
;
287 padded_length
= kObjectSize
+ (tail
? (alignment
- tail
) : 0);
288 param
[i
].ch_size
= padded_length
/ k
;
294 vector
<const char*> args
;
295 argv_to_vec(argc
, (const char **) argv
, args
);
297 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
298 CODE_ENVIRONMENT_UTILITY
, 0);
299 common_init_finish(g_ceph_context
);
301 const char* env
= getenv("CEPH_LIB");
302 string
directory(env
? env
: ".libs");
303 g_conf
->set_val("erasure_code_dir", directory
, false);
305 ::testing::InitGoogleTest(&argc
, argv
);
309 std::cout
<< "minimum_to_decode:recover_num = " << g_recover
<< std::endl
;
310 std::cout
<< "minimum_to_decode:cannot_recover_num = " << g_cannot_recover
312 recovery_percentage
= 100.0
313 - (float) (100.0 * g_cannot_recover
/ (g_recover
+ g_cannot_recover
));
314 printf("recovery_percentage:%f\n",recovery_percentage
);
315 if (recovery_percentage
> 99.0) {
316 std::cout
<< "[ OK ] Recovery percentage is more than 99.0%"
319 std::cout
<< "[ NG ] Recovery percentage is less than 99.0%"
322 std::cout
<< "cannot recovery patterns:" << std::endl
;
323 for (std::vector
<Recover_d
>::const_iterator i
= cannot_recover
.begin();
324 i
!= cannot_recover
.end(); ++i
) {
325 std::cout
<< "---" << std::endl
;
326 std::cout
<< "k = " << i
->k
<< ", m = " << i
->m
<< ", c = " << i
->c
328 std::cout
<< "want_to_decode :" << i
->want
<< std::endl
;
329 std::cout
<< "available_chunks:" << i
->avail
<< std::endl
;
331 std::cout
<< "---" << std::endl
;