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"
45 struct Param_d param
[301];
47 unsigned int g_recover
= 0;
48 unsigned int g_cannot_recover
= 0;
56 struct std::vector
<Recover_d
> cannot_recover
;
58 class ParameterTest
: public ::testing::TestWithParam
<struct Param_d
> {
62 TEST_P(ParameterTest
, parameter_all
)
66 char* k
= GetParam().k
;
67 char* m
= GetParam().m
;
68 char* c
= GetParam().c
;
69 unsigned c_size
= GetParam().ch_size
;
75 ErasureCodeShecTableCache tcache
;
76 ErasureCodeShec
* shec
= new ErasureCodeShecReedSolomonVandermonde(
78 ErasureCodeShec::MULTIPLE
);
79 ErasureCodeProfile
*profile
= new ErasureCodeProfile();
80 (*profile
)["plugin"] = "shec";
81 (*profile
)["technique"] = "";
82 (*profile
)["crush-failure-domain"] = "osd";
87 result
= shec
->init(*profile
, &cerr
);
90 EXPECT_EQ(i_k
, shec
->k
);
91 EXPECT_EQ(i_m
, shec
->m
);
92 EXPECT_EQ(i_c
, shec
->c
);
93 EXPECT_EQ(8, shec
->w
);
94 EXPECT_EQ(ErasureCodeShec::MULTIPLE
, shec
->technique
);
95 EXPECT_STREQ("default", shec
->rule_root
.c_str());
96 EXPECT_STREQ("osd", shec
->rule_failure_domain
.c_str());
97 EXPECT_TRUE(shec
->matrix
!= NULL
);
101 //want_to_decode will be a combination that chooses 1~c from k+m
102 set
<int> want_to_decode
, available_chunks
, minimum_chunks
;
103 int array_want_to_decode
[shec
->get_chunk_count()];
104 struct Recover_d comb
;
106 for (int w
= 1; w
<= i_c
; w
++) {
107 const unsigned int r
= w
; // combination(k+m,r)
109 for (unsigned int i
= 0; i
< r
; ++i
) {
110 array_want_to_decode
[i
] = 1;
112 for (unsigned int i
= r
; i
< shec
->get_chunk_count(); ++i
) {
113 array_want_to_decode
[i
] = 0;
117 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
118 available_chunks
.insert(i
);
120 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
121 if (array_want_to_decode
[i
]) {
122 want_to_decode
.insert(i
);
123 available_chunks
.erase(i
);
127 result
= shec
->_minimum_to_decode(want_to_decode
, available_chunks
,
131 EXPECT_EQ(0, result
);
132 EXPECT_TRUE(minimum_chunks
.size());
135 EXPECT_EQ(-EIO
, result
);
136 EXPECT_EQ(0u, minimum_chunks
.size());
141 comb
.want
= want_to_decode
;
142 comb
.avail
= available_chunks
;
143 cannot_recover
.push_back(comb
);
146 want_to_decode
.clear();
147 available_chunks
.clear();
148 minimum_chunks
.clear();
149 } while (std::prev_permutation(
150 array_want_to_decode
,
151 array_want_to_decode
+ shec
->get_chunk_count()));
154 //minimum_to_decode_with_cost
155 set
<int> want_to_decode_with_cost
, minimum_chunks_with_cost
;
156 map
<int, int> available_chunks_with_cost
;
158 for (unsigned int i
= 0; i
< 1; i
++) {
159 want_to_decode_with_cost
.insert(i
);
161 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
162 available_chunks_with_cost
[i
] = i
;
165 result
= shec
->minimum_to_decode_with_cost(
166 want_to_decode_with_cost
,
167 available_chunks_with_cost
,
168 &minimum_chunks_with_cost
);
169 EXPECT_EQ(0, result
);
170 EXPECT_TRUE(minimum_chunks_with_cost
.size());
174 set
<int> want_to_encode
;
175 map
<int, bufferlist
> encoded
;
177 in
.append("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"//length = 62
178 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"//124
179 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"//186
182 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
183 want_to_encode
.insert(i
);
186 result
= shec
->encode(want_to_encode
, in
, &encoded
);
187 EXPECT_EQ(0, result
);
188 EXPECT_EQ(i_k
+i_m
, (int)encoded
.size());
189 EXPECT_EQ(c_size
, encoded
[0].length());
192 int want_to_decode2
[i_k
+ i_m
];
193 map
<int, bufferlist
> decoded
;
195 for (unsigned int i
= 0; i
< shec
->get_chunk_count(); i
++) {
196 want_to_decode2
[i
] = i
;
199 result
= shec
->_decode(set
<int>(want_to_decode2
, want_to_decode2
+ 2),
201 EXPECT_EQ(0, result
);
202 EXPECT_EQ(2u, decoded
.size());
203 EXPECT_EQ(c_size
, decoded
[0].length());
205 //check encoded,decoded
206 bufferlist out1
, out2
, usable
;
209 for (unsigned int i
= 0; i
< encoded
.size(); i
++) {
210 out1
.append(encoded
[i
]);
214 shec
->decode_concat(encoded
, &out2
);
215 usable
.substr_of(out2
, 0, in
.length());
217 EXPECT_FALSE(out1
== in
);
218 EXPECT_TRUE(usable
== in
);
222 CrushWrapper
*crush
= new CrushWrapper
;
224 crush
->set_type_name(2, "root");
225 crush
->set_type_name(1, "host");
226 crush
->set_type_name(0, "osd");
229 crush
->add_bucket(0, CRUSH_BUCKET_STRAW
, CRUSH_HASH_RJENKINS1
, 2, 0, NULL
,
231 crush
->set_item_name(rootno
, "default");
233 map
< string
, string
> loc
;
234 loc
["root"] = "default";
239 for (int h
= 0; h
< num_host
; ++h
) {
240 loc
["host"] = string("host-") + stringify(h
);
241 for (int o
= 0; o
< num_osd
; ++o
, ++osd
) {
242 crush
->insert_item(g_ceph_context
, osd
, 1.0,
243 string("osd.") + stringify(osd
), loc
);
247 result
= shec
->create_rule("myrule", *crush
, &ss
);
248 EXPECT_EQ(0, result
);
249 EXPECT_STREQ("myrule", crush
->rule_name_map
[0].c_str());
252 EXPECT_EQ(i_k
+i_m
, (int)shec
->get_chunk_count());
254 //get_data_chunk_count
255 EXPECT_EQ(i_k
, (int)shec
->get_data_chunk_count());
258 EXPECT_EQ(c_size
, shec
->get_chunk_size(192));
265 INSTANTIATE_TEST_SUITE_P(Test
, ParameterTest
, ::testing::ValuesIn(param
));
267 int main(int argc
, char **argv
)
271 const int kObjectSize
= 192;
272 unsigned alignment
, tail
, padded_length
;
273 float recovery_percentage
;
276 for (unsigned int k
= 1; k
<= 12; k
++) {
277 for (unsigned int m
= 1; (m
<= k
) && (k
+ m
<= 20); m
++) {
278 for (unsigned int c
= 1; c
<= m
; c
++) {
279 sprintf(param
[i
].sk
, "%u", k
);
280 sprintf(param
[i
].sm
, "%u", m
);
281 sprintf(param
[i
].sc
, "%u", c
);
283 param
[i
].k
= param
[i
].sk
;
284 param
[i
].m
= param
[i
].sm
;
285 param
[i
].c
= param
[i
].sc
;
287 alignment
= k
* 8 * sizeof(int);
288 tail
= kObjectSize
% alignment
;
289 padded_length
= kObjectSize
+ (tail
? (alignment
- tail
) : 0);
290 param
[i
].ch_size
= padded_length
/ k
;
296 auto args
= argv_to_vec(argc
, argv
);
298 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
299 CODE_ENVIRONMENT_UTILITY
,
300 CINIT_FLAG_NO_MON_CONFIG
);
301 common_init_finish(g_ceph_context
);
303 ::testing::InitGoogleTest(&argc
, argv
);
307 std::cout
<< "minimum_to_decode:recover_num = " << g_recover
<< std::endl
;
308 std::cout
<< "minimum_to_decode:cannot_recover_num = " << g_cannot_recover
310 recovery_percentage
= 100.0
311 - (float) (100.0 * g_cannot_recover
/ (g_recover
+ g_cannot_recover
));
312 printf("recovery_percentage:%f\n",recovery_percentage
);
313 if (recovery_percentage
> 99.0) {
314 std::cout
<< "[ OK ] Recovery percentage is more than 99.0%"
317 std::cout
<< "[ NG ] Recovery percentage is less than 99.0%"
320 std::cout
<< "cannot recovery patterns:" << std::endl
;
321 for (std::vector
<Recover_d
>::const_iterator i
= cannot_recover
.begin();
322 i
!= cannot_recover
.end(); ++i
) {
323 std::cout
<< "---" << std::endl
;
324 std::cout
<< "k = " << i
->k
<< ", m = " << i
->m
<< ", c = " << i
->c
326 std::cout
<< "want_to_decode :" << i
->want
<< std::endl
;
327 std::cout
<< "available_chunks:" << i
->avail
<< std::endl
;
329 std::cout
<< "---" << std::endl
;