Motr  M0
client_ut.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2016-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_DIX
24 #include "lib/trace.h"
25 #include "lib/memory.h"
26 #include "lib/finject.h"
27 #include "layout/pdclust.h"
28 #include "layout/linear_enum.h"
29 #include "pool/pool.h"
30 #include "rpc/rpclib.h" /* m0_rpc_server_ctx */
31 #include "conf/helpers.h" /* m0_confc_args */
32 #include "cas/client.h"
33 #include "dix/imask.h"
34 #include "dix/layout.h"
35 #include "dix/meta.h"
36 #include "dix/client.h"
37 #include "dix/fid_convert.h"
38 #include "ut/ut.h"
39 #include "ut/misc.h"
40 
41 enum {
46 };
47 
48 enum {
49  COUNT = 10,
51 };
52 
53 enum {
55  /*
56  * Normally it should be M0_NET_TM_RECV_QUEUE_DEF_LEN, but the bug
57  * MOTR-2177 prevents it. After the bug is fixed, revert it back to
58  * M0_NET_TM_RECV_QUEUE_DEF_LEN.
59  */
61 };
62 
71 };
72 
73 enum ut_pg_unit {
79 };
80 
81 /* Client context */
82 struct cl_ctx {
83  /* Client network domain. */
84  struct m0_net_domain cl_ndom;
86  /* Client rpc context. */
92  struct m0_fid cl_pver;
95  uint32_t *cl_sdev_ids;
96  uint32_t cl_sdev_ids_nr;
97 };
98 
99 struct dix_rep_arr {
100  struct dix_rep *dra_rep;
101  uint32_t dra_nr;
102 };
103 
104 struct dix_rep {
105  int dre_rc;
106  struct m0_buf dre_key;
107  struct m0_buf dre_val;
108 };
109 
110 #define SERVER_LOG_FILE_NAME "dix_ut.errlog"
111 
112 /* Configures motr environment with given parameters. */
113 static char *dix_startup_cmd[] = {
114  "m0d", "-T", "linux",
115  "-D", "cs_sdb", "-S", "cs_stob",
116  "-A", "linuxstob:cs_addb_stob",
117  "-e", M0_NET_XPRT_PREFIX_DEFAULT":0@lo:12345:34:1",
118  "-H", "0@lo:12345:34:1",
119  "-w", "10", "-F",
120  "-f", M0_UT_CONF_PROCESS,
121  "-c", M0_SRC_PATH("dix/ut/conf.xc")
122 };
123 static const char *cdbnames[] = { "dix1" };
124 static const char *cl_ep_addrs[] = { "0@lo:12345:34:2" };
125 static const char *srv_ep_addrs[] = { "0@lo:12345:34:1" };
126 
127 static struct cl_ctx dix_ut_cctx;
130  .rsx_argc = ARRAY_SIZE(dix_startup_cmd),
131  .rsx_log_file_name = SERVER_LOG_FILE_NAME
132 };
133 
134 static const char *ut_profile = "<0x7000000000000001:0>";
135 #define DFID(x, y) M0_FID_TINIT('x', (x), (y))
136 
137 /*
138  * Ranges: (8, 9); (3, 4); (2, 5); (1, 2); (6, 7)
139  * Answer: (1, 5); (6, 7); (8, 9)
140  */
141 void imask(void)
142 {
143  struct m0_dix_imask mask;
144  int rc;
145  struct m0_ext range[] = {
146  { .e_start = 8, .e_end = 9 },
147  { .e_start = 3, .e_end = 4 },
148  { .e_start = 2, .e_end = 5 },
149  { .e_start = 1, .e_end = 2 },
150  { .e_start = 6, .e_end = 7 },
151  };
152 
153  M0_SET0(&mask);
154  rc = m0_dix_imask_init(&mask, range, ARRAY_SIZE(range));
155  M0_UT_ASSERT(rc == 0);
156  M0_UT_ASSERT(mask.im_nr == ARRAY_SIZE(range));
158  mask.im_range[i].e_start == range[i].e_start &&
159  mask.im_range[i].e_end == range[i].e_end));
160  m0_dix_imask_fini(&mask);
161 }
162 
163 #define BYTES(bit) ((bit + 7) / 8)
164 
165 static char get_bit(void *buffer, m0_bcount_t pos)
166 {
167  m0_bcount_t byte_num = BYTES(pos + 1) - 1;
168  char byte_val = *((char*)buffer + byte_num);
169  m0_bcount_t bit_shift = pos % 8;
170  char bit_val = 0x1 & (byte_val >> bit_shift);
171 
172  return bit_val;
173 }
174 
175 void imask_apply(void)
176 {
177  struct m0_dix_imask mask;
178  int rc;
179  char buffer[200];
180  char *result;
181  m0_bcount_t len;
182  int i;
183  struct m0_ext range[] = {
184  { .e_start = 8, .e_end = 9 },
185  { .e_start = 3, .e_end = 4 },
186  { .e_start = 2, .e_end = 5 },
187  { .e_start = 1, .e_end = 2 },
188  { .e_start = 6, .e_end = 7 },
189  };
190 
191  /*
192  * Bit string is (since we are little-endian):
193  * 1110000011100000...
194  */
195  memset(buffer, 7, sizeof(buffer));
196  M0_SET0(&mask);
197  rc = m0_dix_imask_init(&mask, range, ARRAY_SIZE(range));
198  M0_UT_ASSERT(rc == 0);
199  rc = m0_dix_imask_apply(buffer, sizeof(buffer), &mask,
200  (void*)&result, &len);
201  M0_UT_ASSERT(rc == 0);
202  M0_UT_ASSERT(result != NULL);
203  M0_UT_ASSERT(len == 12);
204  for (i = 0; i < len; i++) {
205  char val = get_bit(result, i);
206 
207  if (i == 0 || i == 1 || i == 4 || i == 8 || i == 9)
208  M0_UT_ASSERT(val == 1);
209  else
210  M0_UT_ASSERT(val == 0);
211  }
212  m0_dix_imask_fini(&mask);
213  m0_free(result);
214 }
215 
216 static void imask_empty(void)
217 {
218  struct m0_dix_imask mask;
219  int rc;
220  char buffer[200];
221  char *result;
222  m0_bcount_t len;
223 
224  M0_SET0(&mask);
225  rc = m0_dix_imask_init(&mask, NULL, 0);
226  M0_UT_ASSERT(rc == 0);
227  rc = m0_dix_imask_apply(buffer, sizeof(buffer), &mask,
228  (void*)&result, &len);
229  M0_UT_ASSERT(rc == 0);
230  m0_dix_imask_fini(&mask);
231  M0_UT_ASSERT(result == NULL);
232  M0_UT_ASSERT(len == 0);
233 }
234 
235 static void imask_infini(void)
236 {
237  struct m0_dix_imask mask;
238  int rc;
239  char buffer[200];
240  char *result;
241  m0_bcount_t len;
242  int i;
243  struct m0_ext range[] = {
244  { .e_start = 8, .e_end = 9 },
245  { .e_start = 16, .e_end = IMASK_INF},
246  { .e_start = 2, .e_end = 5 },
247  { .e_start = 8, .e_end = IMASK_INF },
248  };
249  memset(buffer, 0xff, sizeof(buffer));
250  M0_SET0(&mask);
251  rc = m0_dix_imask_init(&mask, range, ARRAY_SIZE(range));
252  M0_UT_ASSERT(rc == 0);
253  rc = m0_dix_imask_apply(buffer, sizeof(buffer), &mask,
254  (void*)&result, &len);
255  M0_UT_ASSERT(rc == 0);
256  M0_UT_ASSERT(result != NULL);
257  M0_UT_ASSERT(len == 2 + sizeof(buffer) * 8 - 16 + 4 +
258  sizeof(buffer) * 8 - 8);
259  for (i = 0; i < len; i++) {
260  char val = get_bit(result, i);
261 
262  M0_UT_ASSERT(val == 1);
263  }
264  m0_dix_imask_fini(&mask);
265  m0_free(result);
266 }
267 
268 static void imask_short(void)
269 {
270  struct m0_dix_imask mask;
271  int rc;
272  char buffer[10];
273  char *result;
274  m0_bcount_t len;
275  int i;
276  struct m0_ext range[] = {
277  { .e_start = 8, .e_end = 600 },
278  };
279 
280  memset(buffer, 0xff, sizeof(buffer));
281  M0_SET0(&mask);
282  rc = m0_dix_imask_init(&mask, range, ARRAY_SIZE(range));
283  M0_UT_ASSERT(rc == 0);
284  rc = m0_dix_imask_apply(buffer, sizeof(buffer), &mask,
285  (void*)&result, &len);
286  M0_UT_ASSERT(rc == 0);
287  M0_UT_ASSERT(result != NULL);
288  M0_UT_ASSERT(len == sizeof(buffer) * 8 - range[0].e_start);
289  for (i = 0; i < len; i++) {
290  char val = get_bit(result, i);
291 
292  M0_UT_ASSERT(val == 1);
293  }
294  m0_dix_imask_fini(&mask);
295  m0_free(result);
296 }
297 
298 static void imask_invalid(void)
299 {
300  struct m0_dix_imask mask;
301  int rc;
302  char buffer[10];
303  char *result;
304  m0_bcount_t len;
305  struct m0_ext range[] = {
306  { .e_start = 100, .e_end = 600 },
307  };
308 
309  memset(buffer, 0xff, sizeof(buffer));
310  M0_SET0(&mask);
311  rc = m0_dix_imask_init(&mask, range, ARRAY_SIZE(range));
312  M0_UT_ASSERT(rc == 0);
313  rc = m0_dix_imask_apply(buffer, sizeof(buffer), &mask,
314  (void*)&result, &len);
315  M0_UT_ASSERT(rc == 0);
316  M0_UT_ASSERT(result == NULL);
317  M0_UT_ASSERT(len == 0);
318  m0_dix_imask_fini(&mask);
319 }
320 
321 static void layout_check(struct m0_dix_linst *dli)
322 {
323  uint32_t W;
324  struct m0_buf key = M0_BUF_INIT0;
325  m0_bcount_t key_len = 200;
326  uint64_t unit;
327  uint64_t id1;
328  uint64_t id2;
329  int rc;
330 
331  rc = m0_buf_alloc(&key, key_len);
332  M0_UT_ASSERT(rc == 0);
333  memset(key.b_addr, 7, key_len);
334  W = dli->li_pl->pl_attr.pa_N +
335  dli->li_pl->pl_attr.pa_K +
336  dli->li_pl->pl_attr.pa_S;
337  for (unit = 0; unit < W; ++unit) {
338  m0_dix_target(dli, unit, &key, &id1);
339  m0_dix_target(dli, unit, &key, &id2);
340  M0_UT_ASSERT(id1 == id2);
341  }
342  m0_buf_free(&key);
343 }
344 
346  struct m0_pool_version *pver)
347 {
348  int rc;
349 
351  M0_UT_ASSERT(rc == 0);
352 }
353 
354 void pdclust_map(void)
355 {
356  struct m0_pool_version pool_ver;
357  uint32_t cache_nr;
358  uint64_t *cache_len;
359  struct m0_pool pool;
360  struct m0_fid fid;
361  struct m0_layout_domain domain;
362  uint64_t id;
363  int rc;
364  struct m0_dix_linst dli;
365  struct m0_dix_ldesc dld;
366  struct m0_ext range[] = {{.e_start = 0, .e_end = 100}};
367 
368  m0_fi_enable("m0_dix_target", "pdcluster-map");
369  fid = DFID(0,1);
370  rc = m0_pool_init(&pool, &M0_FID_TINIT('o', 0, 1), 0);
371  M0_UT_ASSERT(rc == 0);
373  M0_UT_ASSERT(rc == 0);
375  M0_UT_ASSERT(rc == 0);
376  /* Init pool_ver. */
377  cache_nr = 1;
378  M0_ALLOC_ARR(cache_len, cache_nr);
379  M0_UT_ASSERT(cache_len != NULL);
380  pool_ver.pv_id = M0_FID_TINIT('v', 1, 1);
387  cache_len[0] = DIX_M0T1FS_LAYOUT_P;
389  /* Init layout. */
390  m0_dix_ldesc_init(&dld, range, ARRAY_SIZE(range), HASH_FNC_CITY,
391  &pool_ver.pv_id);
392  id = m0_pool_version2layout_id(&pool_ver.pv_id, M0_DEFAULT_LAYOUT_ID);
393  rc = m0_dix_layout_init(&dli, &domain, &fid, id, &pool_ver, &dld);
394  M0_UT_ASSERT(rc == 0);
395  layout_check(&dli);
396  m0_fi_disable("m0_dix_target", "pdcluster-map");
397  m0_dix_layout_fini(&dli);
398  m0_dix_ldesc_fini(&dld);
402  m0_pool_fini(&pool);
403  m0_free(cache_len);
404 }
405 
406 void meta_val_encdec(void)
407 {
408  struct m0_fid fid = DFID(0,1);
409  struct m0_fid fid2 = DFID(0,100);
410  struct m0_fid pfid = DFID(0,1);
411  struct m0_ext range[] = {
412  {.e_start = 0, .e_end = 100},
413  {.e_start = 110, .e_end = 200},
414  {.e_start = 300, .e_end = 400},
415  };
416  int rc;
417  struct m0_bufvec bv;
418  struct m0_dix_ldesc dld;
419  struct m0_dix_ldesc dld2;
420 
421  rc = m0_dix_ldesc_init(&dld, range, ARRAY_SIZE(range),
422  HASH_FNC_CITY, &pfid);
423  M0_UT_ASSERT(rc == 0);
424  rc = m0_dix__meta_val_enc(&fid, &dld, 1, &bv);
425  M0_UT_ASSERT(rc == 0);
426  rc = m0_dix__meta_val_dec(&bv, &fid2, &dld2, 1);
427  m0_bufvec_free(&bv);
428  M0_UT_ASSERT(rc == 0);
429  M0_UT_ASSERT(m0_fid_eq(&fid, &fid2));
431  M0_UT_ASSERT(dld.ld_hash_fnc == dld2.ld_hash_fnc);
432  M0_UT_ASSERT(m0_fid_eq(&dld.ld_pver, &dld2.ld_pver));
435  dld.ld_imask.im_range[i].e_start ==
436  dld2.ld_imask.im_range[i].e_start &&
437  dld.ld_imask.im_range[i].e_end ==
438  dld2.ld_imask.im_range[i].e_end));
439  m0_dix_ldesc_fini(&dld);
440  m0_dix_ldesc_fini(&dld2);
441 }
442 
444 {
445  struct m0_fid fid[COUNT];
446  struct m0_fid fid2[COUNT];
447  struct m0_ext range[] = {
448  {.e_start = 0, .e_end = 100},
449  {.e_start = 110, .e_end = 200},
450  {.e_start = 300, .e_end = 400},
451  };
452  int rc;
453  struct m0_bufvec bv;
454  struct m0_dix_ldesc dld[COUNT];
455  struct m0_dix_ldesc dld2[COUNT];
456  int i;
457 
458  for(i = 0; i < ARRAY_SIZE(fid); i++) {
459  struct m0_fid f = DFID(1,i);
460 
461  fid[i] = DFID(0,i+1);
462  fid2[i] = DFID(1,i);
463  rc = m0_dix_ldesc_init(&dld[i], range, ARRAY_SIZE(range),
464  HASH_FNC_CITY, &f);
465  M0_UT_ASSERT(rc == 0);
466  }
467  rc = m0_dix__meta_val_enc(fid, dld, ARRAY_SIZE(fid), &bv);
468  M0_UT_ASSERT(rc == 0);
469  rc = m0_dix__meta_val_dec(&bv, fid2, dld2, ARRAY_SIZE(fid));
470  m0_bufvec_free(&bv);
471  M0_UT_ASSERT(rc == 0);
472  for (i = 0; i < ARRAY_SIZE(fid); i++) {
473  M0_UT_ASSERT(m0_fid_eq(&fid[i], &fid[i]));
475  M0_UT_ASSERT(dld[i].ld_hash_fnc == dld2[i].ld_hash_fnc);
476  M0_UT_ASSERT(m0_fid_eq(&dld[i].ld_pver, &dld2[i].ld_pver));
477  M0_UT_ASSERT(dld[i].ld_imask.im_nr == dld2[i].ld_imask.im_nr);
479  dld[i].ld_imask.im_range[j].e_start ==
480  dld2[i].ld_imask.im_range[j].e_start &&
481  dld[i].ld_imask.im_range[j].e_end ==
482  dld2[i].ld_imask.im_range[j].e_end));
483  m0_dix_ldesc_fini(&dld[i]);
484  m0_dix_ldesc_fini(&dld2[i]);
485  }
486 }
487 
488 void layout_encdec(void)
489 {
490  struct m0_ext range[] = {
491  {.e_start = 0, .e_end = 100},
492  {.e_start = 110, .e_end = 200},
493  {.e_start = 300, .e_end = 400},
494  };
495  int rc;
496  struct m0_dix_ldesc dld1;
497  struct m0_dix_ldesc dld2;
498  struct m0_dix_ldesc *pdld;
499  struct m0_bufvec key;
500  struct m0_bufvec val;
501  uint64_t lid1 = 1010101;
502  uint64_t lid2;
503  struct m0_fid fid = DFID(0,1);
504  struct m0_fid fid1 = DFID(0,100);
505  struct m0_fid fid2 = DFID(0,101);
506  struct m0_dix_layout dlay1;
507  struct m0_dix_layout dlay2;
508 
509  /*
510  * Encode/decode values that are used to work with 'layout-descriptor'
511  * index.
512  */
513  rc = m0_dix_ldesc_init(&dld1, range, ARRAY_SIZE(range),
514  HASH_FNC_CITY, &fid);
515  M0_UT_ASSERT(rc == 0);
516  rc = m0_dix__ldesc_vals_enc(&lid1, &dld1, 1, &key, &val);
517  M0_UT_ASSERT(rc == 0);
518  rc = m0_dix__ldesc_vals_dec(&key, &val, &lid2, &dld2, 1);
519  M0_UT_ASSERT(rc == 0);
522  M0_UT_ASSERT(lid1 == lid2);
523  M0_UT_ASSERT(m0_fid_eq(&dld1.ld_pver, &dld2.ld_pver));
525  M0_UT_ASSERT(dld1.ld_hash_fnc == dld2.ld_hash_fnc);
526  M0_UT_ASSERT(dld1.ld_imask.im_nr == dld2.ld_imask.im_nr);
528  dld1.ld_imask.im_range[i].e_start ==
529  dld2.ld_imask.im_range[i].e_start &&
530  dld1.ld_imask.im_range[i].e_end ==
531  dld2.ld_imask.im_range[i].e_end));
532  m0_dix_ldesc_fini(&dld1);
533  m0_dix_ldesc_fini(&dld2);
534 
535  /* Encode/decode values that are used to work with 'layout' index. */
536  dlay1.dl_type = DIX_LTYPE_ID;
537  dlay1.u.dl_id = lid1;
538  rc = m0_dix__layout_vals_enc(&fid1, &dlay1, 1, &key, &val);
539  M0_UT_ASSERT(rc == 0);
540  rc = m0_dix__layout_vals_dec(&key, &val, &fid2, &dlay2, 1);
541  M0_UT_ASSERT(rc == 0);
544  M0_UT_ASSERT(m0_fid_eq(&fid1, &fid2));
545  M0_UT_ASSERT(dlay1.dl_type == dlay2.dl_type);
547 
548  rc = m0_dix_ldesc_init(&dld1, range, ARRAY_SIZE(range),
549  HASH_FNC_FNV1, &fid);
550  M0_UT_ASSERT(rc == 0);
551  dlay1.dl_type = DIX_LTYPE_DESCR;
552  m0_dix_ldesc_copy(&dlay1.u.dl_desc, &dld1);
553  rc = m0_dix__layout_vals_enc(&fid1, &dlay1, 1, &key, &val);
554  M0_UT_ASSERT(rc == 0);
555  rc = m0_dix__layout_vals_dec(&key, &val, &fid2, &dlay2, 1);
556  M0_UT_ASSERT(rc == 0);
559  M0_UT_ASSERT(m0_fid_eq(&fid1, &fid2));
560  M0_UT_ASSERT(dlay1.dl_type == dlay2.dl_type);
562  pdld = &dlay2.u.dl_desc;
564  M0_UT_ASSERT(pdld->ld_hash_fnc == dld1.ld_hash_fnc);
565  M0_UT_ASSERT(pdld->ld_imask.im_nr == dld1.ld_imask.im_nr);
567  dld1.ld_imask.im_range[i].e_start ==
568  pdld->ld_imask.im_range[i].e_start &&
569  dld1.ld_imask.im_range[i].e_end ==
570  pdld->ld_imask.im_range[i].e_end));
571  m0_dix_ldesc_fini(&dlay1.u.dl_desc);
572  m0_dix_ldesc_fini(&dlay2.u.dl_desc);
573  m0_dix_ldesc_fini(&dld1);
574 }
575 
576 static uint64_t dix_key(uint32_t seq_num)
577 {
578  return seq_num;
579 }
580 
581 static uint64_t dix_val(uint32_t seq_num)
582 {
583  return 100 + seq_num;
584 }
585 
586 static void dix__vals_check(struct dix_rep_arr *rep,
587  uint32_t start_key,
588  uint32_t first_val,
589  uint32_t last_val)
590 {
591  uint32_t i;
592  uint32_t count = last_val - first_val + 1;
593  uint64_t key;
594  uint64_t val;
595 
596  M0_UT_ASSERT(rep->dra_nr == count);
597  for (i = 0; i < count; i++) {
598  M0_UT_ASSERT(rep->dra_rep[i].dre_rc == 0);
599  key = *(uint64_t *)rep->dra_rep[i].dre_key.b_addr;
600  val = *(uint64_t *)rep->dra_rep[i].dre_val.b_addr;
601  M0_UT_ASSERT(key == dix_key(start_key + i));
602  M0_UT_ASSERT(val == dix_val(start_key + i + first_val * 100));
603  }
604 }
605 
606 static void dix_vals_check(struct dix_rep_arr *rep, uint32_t count)
607 {
608  dix__vals_check(rep, 0, 0, count - 1);
609 }
610 
611 static void dix_index_init(struct m0_dix *index, uint32_t id)
612 {
613  struct m0_ext range = {.e_start = 0, .e_end = IMASK_INF};
614  struct m0_dix_ldesc *ldesc = &index->dd_layout.u.dl_desc;
615  int rc;
616 
617  rc = m0_dix_ldesc_init(ldesc, &range, 1, HASH_FNC_CITY,
619  M0_UT_ASSERT(rc == 0);
620  index->dd_layout.dl_type = DIX_LTYPE_DESCR;
621  index->dd_fid = DFID(1, id);
622 }
623 
624 static void dix_predictable_index_init(struct m0_dix *index, uint32_t id)
625 {
626  struct m0_dix_ldesc *ldesc = &index->dd_layout.u.dl_desc;
627  int rc;
628 
629  /*
630  * Predictable index uses empty identity mask, so all keys have 0 parity
631  * group and distributed over the same nodes in the same order.
632  */
633  rc = m0_dix_ldesc_init(ldesc, NULL, 0, HASH_FNC_NONE,
635  M0_UT_ASSERT(rc == 0);
636  index->dd_layout.dl_type = DIX_LTYPE_DESCR;
637  index->dd_fid = DFID(1, id);
638 }
639 
640 static void dix_index_fini(struct m0_dix *index)
641 {
643 }
644 
645 static void dix__kv_alloc_and_fill(struct m0_bufvec *keys,
646  struct m0_bufvec *vals,
647  uint32_t first,
648  uint32_t last)
649 {
650  uint32_t i;
651  uint32_t count = last - first + 1;
652  int rc;
653 
654  rc = m0_bufvec_alloc(keys, count, sizeof (uint64_t));
655  M0_UT_ASSERT(rc == 0);
656  rc = m0_bufvec_alloc(vals, count, sizeof (uint64_t));
657  M0_UT_ASSERT(rc == 0);
658  for (i = 0; i < count; i++) {
659  *(uint64_t *)keys->ov_buf[i] = dix_key(i);
660  *(uint64_t *)vals->ov_buf[i] = dix_val(i + first * 100);
661  }
662 }
663 
664 static void dix_kv_alloc_and_fill(struct m0_bufvec *keys,
665  struct m0_bufvec *vals,
666  uint32_t count)
667 {
668  dix__kv_alloc_and_fill(keys, vals, 0, count - 1);
669 }
670 
671 static void dix_kv_destroy(struct m0_bufvec *keys,
672  struct m0_bufvec *vals)
673 {
674  m0_bufvec_free(keys);
675  m0_bufvec_free(vals);
676 }
677 
678 static void dix_rep_free(struct dix_rep_arr *rep)
679 {
680  uint32_t i;
681 
682  for (i = 0; i < rep->dra_nr; i++) {
683  if (rep->dra_rep[i].dre_rc == 0) {
684  m0_buf_free(&rep->dra_rep[i].dre_key);
685  m0_buf_free(&rep->dra_rep[i].dre_val);
686  }
687  }
688  m0_free(rep->dra_rep);
689 }
690 
691 static struct m0_pooldev *dix_pm_disk_find(struct m0_poolmach *pm,
692  uint32_t sdev_idx)
693 {
694  struct m0_poolmach_state *pm_state = pm->pm_state;
695  uint32_t i;
696 
697  for (i = 0; i < pm_state->pst_nr_devices; i++) {
698  if (pm_state->pst_devices_array[i].pd_sdev_idx == sdev_idx)
699  return &pm_state->pst_devices_array[i];
700  }
701  return NULL;
702 }
703 
704 static void dix_pm_disk_state_set(struct m0_poolmach *pm, uint32_t sdev_idx,
705  enum m0_pool_nd_state state)
706 {
707  struct m0_poolmach_event event;
708  struct m0_pooldev *pd;
709  int rc;
710 
711  pd = dix_pm_disk_find(pm, sdev_idx);
712  event.pe_type = M0_POOL_DEVICE;
713  event.pe_index = pd->pd_index;
714  event.pe_state = state;
715  rc = m0_poolmach_state_transit(pm, &event);
716  M0_ASSERT(rc == 0);
717 }
718 
719 static struct m0_poolmach *dix_srv_poolmach(void)
720 {
721  struct m0_pool_version *pver;
722  struct m0_reqh *reqh;
723 
726  M0_UT_ASSERT(pver != NULL);
727  return &pver->pv_mach;
728 }
729 
730 static enum m0_pool_nd_state dix_disk_state(uint32_t sdev_idx)
731 {
732  struct m0_poolmach *cli_pm;
733  struct m0_poolmach *srv_pm;
734  struct m0_pooldev *cli_pd;
735  struct m0_pooldev *srv_pd;
736 
737  cli_pm = &dix_ut_cctx.cl_cli.dx_pver->pv_mach;
738  srv_pm = dix_srv_poolmach();
739  cli_pd = dix_pm_disk_find(cli_pm, sdev_idx);
740  srv_pd = dix_pm_disk_find(srv_pm, sdev_idx);
741  M0_UT_ASSERT(cli_pd->pd_state == srv_pd->pd_state);
742  return cli_pd->pd_state;
743 }
744 
745 static void dix_disk_state_set(uint32_t sdev_idx, enum m0_pool_nd_state state)
746 {
747  struct m0_poolmach *cli_pm;
748  struct m0_poolmach *srv_pm;
749 
750  cli_pm = &dix_ut_cctx.cl_cli.dx_pver->pv_mach;
751  srv_pm = dix_srv_poolmach();
752  dix_pm_disk_state_set(cli_pm, sdev_idx, state);
753  dix_pm_disk_state_set(srv_pm, sdev_idx, state);
754 }
755 
756 static void dix_disk_failure_set(uint32_t sdev_idx, enum m0_pool_nd_state state)
757 {
758  M0_PRE(dix_disk_state(sdev_idx) == M0_PNDS_ONLINE);
759  do {
760  switch (dix_disk_state(sdev_idx)) {
761  case M0_PNDS_ONLINE:
763  break;
764  case M0_PNDS_FAILED:
766  break;
769  break;
772  break;
773  default:
774  M0_IMPOSSIBLE("Invalid state");
775  }
776  } while (dix_disk_state(sdev_idx) != state);
777 }
778 
779 static void dix_disk_online_set(uint32_t sdev_idx)
780 {
781  switch (dix_disk_state(sdev_idx)) {
782  case M0_PNDS_FAILED:
784  /* Fall through. */
787  /* Fall through. */
790  /* Fall through. */
793  break;
794  default:
795  M0_IMPOSSIBLE("Disk seems to be not failed.");
796  }
797 }
798 
800 {
801  uint32_t *sdevs;
802  struct m0_pool_version *pver;
803  struct m0_dix_layout_iter iter;
804  struct m0_buf kbuf;
805  uint32_t key = 0;
806  uint32_t P;
807  uint64_t tgt;
808  int rc;
809  uint32_t i;
810 
811  M0_PRE(index->dd_layout.dl_type == DIX_LTYPE_DESCR);
812  M0_PRE(index->dd_layout.u.dl_desc.ld_hash_fnc == HASH_FNC_NONE);
813  M0_PRE(index->dd_layout.u.dl_desc.ld_imask.im_nr == 0);
814 
817  M0_UT_ASSERT(pver != NULL);
818  kbuf = M0_BUF_INIT_PTR(&key);
819  P = pver->pv_attr.pa_P;
820  rc = m0_dix_layout_iter_init(&iter, &index->dd_fid,
822  &index->dd_layout.u.dl_desc, &kbuf);
823  M0_UT_ASSERT(rc == 0);
824  M0_ALLOC_ARR(sdevs, P);
825  M0_UT_ASSERT(sdevs != NULL);
826  for (i = 0; i < m0_dix_liter_W(&iter); i++) {
827  m0_dix_layout_iter_next(&iter, &tgt);
828  sdevs[i] = m0_dix_tgt2sdev(&iter.dit_linst, tgt)->pd_sdev_idx;
829  }
830  dix_ut_cctx.cl_sdev_ids = sdevs;
833 }
834 
835 static uint32_t dix_sdev_id(enum ut_pg_unit unit)
836 {
837  uint32_t *sdevs = dix_ut_cctx.cl_sdev_ids;
838  uint32_t sdevs_nr = dix_ut_cctx.cl_sdev_ids_nr;
839  uint32_t K = (sdevs_nr - 1) / 2;
840  uint32_t parity_offset = 1;
841  uint32_t spare_offset = parity_offset + K;
842 
843  switch (unit) {
844  case PG_UNIT_DATA:
845  return sdevs[0];
846  case PG_UNIT_PARITY0:
847  return sdevs[parity_offset + 0];
848  case PG_UNIT_PARITY1:
849  return sdevs[parity_offset + 1];
850  case PG_UNIT_SPARE0:
851  return sdevs[spare_offset + 0];
852  case PG_UNIT_SPARE1:
853  return sdevs[spare_offset + 1];
854  default:
855  M0_IMPOSSIBLE("Incorrect unit");
856  }
857 }
858 
859 static void dix_cctg_id_fill(struct m0_dix *index, uint32_t sdev_idx,
860  struct m0_cas_id *cctg_id)
861 {
862  int rc;
863 
864  m0_dix_fid_convert_dix2cctg(&index->dd_fid, &cctg_id->ci_fid, sdev_idx);
865 
866  cctg_id->ci_layout.dl_type = index->dd_layout.dl_type;
867  rc = m0_dix_ldesc_copy(&cctg_id->ci_layout.u.dl_desc,
868  &index->dd_layout.u.dl_desc);
869  M0_UT_ASSERT(rc == 0);
870 
871 }
872 
873 static struct m0_rpc_session *cctg_rpc_sess(uint32_t sdev_idx)
874 {
876  struct m0_reqh_service_ctx *cas_svc;
877 
878  cas_svc = pc->pc_dev2svc[sdev_idx].pds_ctx;
879  M0_PRE(cas_svc != NULL);
880  return &cas_svc->sc_rlink.rlk_sess;
881 }
882 
883 static int dix_cctg_records_del(struct m0_dix *index,
884  struct m0_bufvec *keys,
885  uint32_t sdev_idx)
886 {
887  struct m0_cas_req creq = {};
888  struct m0_cas_id cctg_id;
889  struct m0_cas_rec_reply rep;
890  uint32_t keys_nr;
891  uint32_t i;
892  int rc;
893 
894  keys_nr = keys->ov_vec.v_nr;
895  dix_cctg_id_fill(index, sdev_idx, &cctg_id);
896  m0_cas_req_init(&creq, cctg_rpc_sess(sdev_idx),
897  m0_locality0_get()->lo_grp);
898  m0_cas_req_lock(&creq);
899  rc = m0_cas_del(&creq, &cctg_id, keys, NULL, 0);
900  M0_UT_ASSERT(rc == 0);
901  rc = m0_sm_timedwait(&creq.ccr_sm,
903  M0_TIME_NEVER);
904  M0_UT_ASSERT(rc == 0);
906  M0_UT_ASSERT(m0_cas_req_nr(&creq) == keys_nr);
907  rc = m0_cas_req_generic_rc(&creq);
908  for (i = 0; i < keys_nr; i++) {
909  m0_cas_del_rep(&creq, i, &rep);
910  if (rc == 0)
911  rc = rep.crr_rc;
912  }
913  m0_cas_req_unlock(&creq);
914  m0_cas_req_fini_lock(&creq);
915  return rc;
916 }
917 
918 static void dix_cctg_records_put(struct m0_dix *index,
919  struct m0_bufvec *keys,
920  struct m0_bufvec *vals,
921  uint32_t sdev_idx)
922 {
923  struct m0_cas_req creq = {};
924  struct m0_cas_id cctg_id;
925  struct m0_cas_rec_reply rep;
926  uint32_t keys_nr;
927  uint32_t i;
928  int rc;
929 
930  keys_nr = keys->ov_vec.v_nr;
931  dix_cctg_id_fill(index, sdev_idx, &cctg_id);
932  m0_cas_req_init(&creq, cctg_rpc_sess(sdev_idx),
933  m0_locality0_get()->lo_grp);
934  m0_cas_req_lock(&creq);
935  rc = m0_cas_put(&creq, &cctg_id, keys, vals, NULL, 0);
936  M0_UT_ASSERT(rc == 0);
937  rc = m0_sm_timedwait(&creq.ccr_sm,
939  M0_TIME_NEVER);
940  M0_UT_ASSERT(rc == 0);
942  M0_UT_ASSERT(m0_cas_req_nr(&creq) == keys_nr);
943  M0_UT_ASSERT(m0_cas_req_generic_rc(&creq) == 0);
944  for (i = 0; i < keys_nr; i++) {
945  m0_cas_put_rep(&creq, i, &rep);
946  M0_UT_ASSERT(rep.crr_rc == 0);
947  }
948  m0_cas_req_unlock(&creq);
949  m0_cas_req_fini_lock(&creq);
950 }
951 
952 static bool dix_cctg_has_replica(struct m0_dix *index,
953  struct m0_bufvec *keys,
954  struct m0_bufvec *vals,
955  uint32_t sdev_idx)
956 {
957  struct m0_cas_req creq = {};
958  struct m0_cas_id cctg_id;
959  struct m0_cas_get_reply rep;
960  uint32_t keys_nr;
961  uint32_t i;
962  int rc;
963  bool ret = true;
964 
965  keys_nr = keys->ov_vec.v_nr;
966  dix_cctg_id_fill(index, sdev_idx, &cctg_id);
967  m0_cas_req_init(&creq, cctg_rpc_sess(sdev_idx),
968  m0_locality0_get()->lo_grp);
969  m0_cas_req_lock(&creq);
970  rc = m0_cas_get(&creq, &cctg_id, keys);
971  M0_UT_ASSERT(rc == 0);
972  rc = m0_sm_timedwait(&creq.ccr_sm,
974  M0_TIME_NEVER);
975  M0_UT_ASSERT(rc == 0);
977  M0_UT_ASSERT(m0_cas_req_nr(&creq) == keys_nr);
978  M0_UT_ASSERT(m0_cas_req_generic_rc(&creq) == 0);
979  for (i = 0; i < keys_nr; i++) {
980  m0_cas_get_rep(&creq, i, &rep);
981  M0_UT_ASSERT(M0_IN(rep.cge_rc, (0, -ENOENT)));
982  if (rep.cge_rc == -ENOENT) {
983  ret = false;
984  break;
985  } else if (vals != NULL) {
986  M0_UT_ASSERT(vals->ov_vec.v_count[i] ==
987  rep.cge_val.b_nob);
988  M0_UT_ASSERT(!memcmp(vals->ov_buf[i],
989  rep.cge_val.b_addr,
990  rep.cge_val.b_nob));
991  }
992  }
993  m0_cas_req_unlock(&creq);
994  m0_cas_req_fini_lock(&creq);
995  return ret;
996 }
997 
998 static void dix_records_erase(struct m0_dix *index, struct m0_bufvec *keys)
999 {
1000  int i;
1001 
1002  for (i = PG_UNIT_DATA; i <= PG_UNIT_SPARE1; i++)
1003  /* Ignore rc. */
1005 }
1006 
1007 static bool dix_rec_is_deleted(struct m0_dix *index, struct m0_bufvec *keys)
1008 {
1009  uint32_t *sdevs = dix_ut_cctx.cl_sdev_ids;
1010  uint32_t nr = dix_ut_cctx.cl_sdev_ids_nr;
1011 
1012  return m0_forall(i, nr,
1013  !M0_IN(dix_disk_state(sdevs[i]), (M0_PNDS_ONLINE,
1015  !dix_cctg_has_replica(index, keys, NULL, sdevs[i]));
1016 }
1017 
1018 
1019 static int dix_client_init(struct cl_ctx *cctx, const char *cl_ep_addr,
1020  const char *srv_ep_addr, const char* dbname,
1021  struct m0_net_xprt *xprt)
1022 {
1023  int rc;
1024  struct m0_rpc_client_ctx *cl_rpc_ctx;
1025  struct m0_conf_root *root;
1026  struct m0_confc_args *confc_args;
1027  struct m0_pools_common *pc = &cctx->cl_pools_common;
1028 
1029  M0_PRE(cctx != NULL && cl_ep_addr != NULL && srv_ep_addr != NULL &&
1030  dbname != NULL && xprt != NULL);
1031 
1032  /* Initialise layout domain for DIX client. */
1033  rc = m0_layout_domain_init(&cctx->cl_ldom);
1034  M0_UT_ASSERT(rc == 0);
1036  M0_UT_ASSERT(rc == 0);
1037 
1038  /* Start RPC client. */
1039  rc = m0_net_domain_init(&cctx->cl_ndom, xprt);
1040  M0_UT_ASSERT(rc == 0);
1041  cl_rpc_ctx = &cctx->cl_rpc_ctx;
1042  cl_rpc_ctx->rcx_net_dom = &cctx->cl_ndom;
1043  cl_rpc_ctx->rcx_local_addr = cl_ep_addr;
1044  cl_rpc_ctx->rcx_remote_addr = srv_ep_addr;
1046  cl_rpc_ctx->rcx_fid = &g_process_fid;
1047  /*
1048  * The value is used to set a number of buffers
1049  * (m0_rpc_net_buffer_pool_setup()) and queue_len
1050  * (m0_rpc_machine_init()) during m0_rpc_client_start(). Default value
1051  * is M0_NET_TM_RECV_QUEUE_DEF_LEN which equals to 2. Need to set a
1052  * larger value. 10 is enough.
1053  */
1055 
1056  rc = m0_rpc_client_start(cl_rpc_ctx);
1057  M0_UT_ASSERT(rc == 0);
1058 
1059  /*
1060  * Initialise pools common structure, it's necessary for normal DIX
1061  * client functioning.
1062  */
1064  M0_UT_ASSERT(rc == 0);
1065  confc_args = &(struct m0_confc_args) {
1067  .ca_rmach = &cl_rpc_ctx->rcx_rpc_machine,
1068  .ca_group = m0_locality0_get()->lo_grp
1069  };
1070  rc = m0_reqh_conf_setup(&cl_rpc_ctx->rcx_reqh, confc_args);
1071  M0_UT_ASSERT(rc == 0);
1072  rc = m0_rconfc_start_sync(&cl_rpc_ctx->rcx_reqh.rh_rconfc);
1073  M0_UT_ASSERT(rc == 0);
1074  rc = m0_confc_root_open(m0_reqh2confc(&cl_rpc_ctx->rcx_reqh), &root);
1075  M0_UT_ASSERT(rc == 0);
1076  rc = m0_pools_common_init(pc, &cl_rpc_ctx->rcx_rpc_machine);
1077  M0_UT_ASSERT(rc == 0);
1078  rc = m0_pools_setup(pc, m0_reqh2profile(&cl_rpc_ctx->rcx_reqh),
1079  NULL, NULL);
1080  M0_UT_ASSERT(rc == 0);
1082  M0_UT_ASSERT(rc == 0);
1083  /* Wait until all services are connected. */
1085  /*
1086  * Unfortunately pools common structure uses layout domain from request
1087  * handler, so it's necessary to initialise it. Please note, that DIX
1088  * client uses another one (cctx->cl_ldom).
1089  */
1090  rc = m0_layout_domain_init(&cl_rpc_ctx->rcx_reqh.rh_ldom);
1091  M0_UT_ASSERT(rc == 0);
1093  M0_UT_ASSERT(rc == 0);
1094 
1096  M0_UT_ASSERT(rc == 0);
1098  cctx->cl_sdev_ids = NULL;
1099  return rc;
1100 }
1101 
1102 static void dix_client_fini(struct cl_ctx *cctx)
1103 {
1104  struct m0_pools_common *pc = &cctx->cl_pools_common;
1105  struct m0_layout_domain *rpc_client_ldom;
1106  int rc;
1107 
1108  rpc_client_ldom = &cctx->cl_rpc_ctx.rcx_reqh.rh_ldom;
1110  m0_layout_domain_cleanup(rpc_client_ldom);
1111  m0_layout_standard_types_unregister(rpc_client_ldom);
1112  m0_layout_domain_fini(rpc_client_ldom);
1116 
1118  m0_rconfc_fini(&cctx->cl_rpc_ctx.rcx_reqh.rh_rconfc);
1119  rc = m0_rpc_client_stop(&cctx->cl_rpc_ctx);
1120  M0_UT_ASSERT(rc == 0);
1121  m0_layout_domain_cleanup(&cctx->cl_ldom);
1123  m0_layout_domain_fini(&cctx->cl_ldom);
1124  m0_net_domain_fini(&cctx->cl_ndom);
1125  m0_free(cctx->cl_sdev_ids);
1126 }
1127 
1129  struct cl_ctx *cctx)
1130 {
1131  int rc;
1132 
1136  m0_fi_enable_once("m0_rpc_machine_init", "bulk_cutoff_4K");
1138  M0_UT_ASSERT(rc == 0);
1140  srv_ep_addrs[0], cdbnames[0],
1142  M0_UT_ASSERT(rc == 0);
1143 }
1144 
1146  struct cl_ctx *cctx)
1147 {
1150 }
1151 
1152 static int ut_pver_find(struct m0_reqh *reqh, struct m0_fid *out)
1153 {
1154  struct m0_conf_root *root;
1155  int rc;
1156 
1158  if (rc != 0)
1159  return M0_ERR(rc);
1160  *out = root->rt_imeta_pver;
1162  return 0;
1163 }
1164 
1165 /*
1166  * NOTE. Currently, motr/setup creates meta indices. But this behaviour may be
1167  * changed in the future. Therefore, comment duplicated code.
1168  * Uncomment it when DIX initialisation is removed from the motr/setup.
1169  */
1170 static void ut_service_init(void)
1171 {
1172  struct m0_dix_cli *cli = &dix_ut_cctx.cl_cli;
1173 #if 0
1174  struct m0_ext range[] = {
1175  { .e_start = 0, .e_end = IMASK_INF },
1176  };
1177 #endif
1178  int rc;
1179 
1183  &dix_ut_cctx.cl_pver);
1184  M0_UT_ASSERT(rc == 0);
1185  rc = m0_dix_cli_init(cli,
1189  &dix_ut_cctx.cl_pver);
1190  M0_UT_ASSERT(rc == 0);
1191 #if 0
1193 #endif
1195 
1196 #if 0
1197  /* Create meta indices (root, layout, layout-descr). */
1200  M0_UT_ASSERT(rc == 0);
1203  M0_UT_ASSERT(rc == 0);
1207  &dix_ut_cctx.cl_dld2);
1208  M0_UT_ASSERT(rc == 0);
1209 #endif
1211  M0_UT_ASSERT(rc == 0);
1214 }
1215 
1216 static void ut_service_fini(void)
1217 {
1223 }
1224 
1225 static void dix_meta_create(void)
1226 {
1227  ut_service_init();
1228  ut_service_fini();
1229 }
1230 
1231 static int dix_common_idx_flagged_op(const struct m0_dix *indices,
1232  uint32_t indices_nr,
1233  enum ut_dix_req_type type,
1234  uint32_t flags)
1235 {
1236  struct m0_dix_req req;
1237  int rc;
1238  int i;
1239 
1241  m0_dix_req_lock(&req);
1242  switch (type) {
1243  case REQ_CREATE:
1244  rc = m0_dix_create(&req, indices, indices_nr, NULL, flags);
1245  break;
1246  case REQ_DELETE:
1247  rc = m0_dix_delete(&req, indices, indices_nr, NULL, flags);
1248  break;
1249  case REQ_LOOKUP:
1250  rc = m0_dix_cctgs_lookup(&req, indices, indices_nr);
1251  break;
1252  default:
1253  M0_IMPOSSIBLE("Unknown req type %u", type);
1254  }
1255  M0_UT_ASSERT(rc == 0);
1257  M0_TIME_NEVER);
1258  M0_UT_ASSERT(rc == 0);
1259  rc = m0_dix_generic_rc(&req);
1260  if (rc == 0)
1261  for (i = 0; i < m0_dix_req_nr(&req); i++) {
1262  rc = m0_dix_item_rc(&req, i);
1263  if (rc != 0)
1264  break;
1265  }
1268  return rc;
1269 }
1270 
1271 static int dix_common_idx_op(const struct m0_dix *indices, uint32_t indices_nr,
1272  enum ut_dix_req_type type)
1273 {
1274  return dix_common_idx_flagged_op(indices, indices_nr, type, 0);
1275 }
1276 
1277 static int dix_common_rec_op(const struct m0_dix *index,
1278  const struct m0_bufvec *keys,
1279  struct m0_bufvec *vals,
1280  const uint32_t *recs_nr,
1281  uint32_t flags,
1282  struct dix_rep_arr *rep,
1283  enum ut_dix_req_type type)
1284 {
1285  struct m0_dix_req req;
1286  int rc;
1287  int i;
1288  int k = 0;
1289 
1291  m0_dix_req_lock(&req);
1292  switch (type) {
1293  case REQ_PUT:
1294  rc = m0_dix_put(&req, index, keys, vals, NULL, flags);
1295  break;
1296  case REQ_DEL:
1297  rc = m0_dix_del(&req, index, keys, NULL, flags);
1298  break;
1299  case REQ_GET:
1300  rc = m0_dix_get(&req, index, keys);
1301  break;
1302  case REQ_NEXT:
1303  rc = m0_dix_next(&req, index, keys, recs_nr, flags);
1304  break;
1305  default:
1306  M0_IMPOSSIBLE("Unknown req type %u", type);
1307  break;
1308  }
1309  M0_UT_ASSERT(rc == 0);
1311  M0_TIME_NEVER);
1312  M0_UT_ASSERT(rc == 0);
1314  rc = m0_dix_generic_rc(&req);
1315  if (rc != 0) {
1316  rep->dra_nr = 0;
1317  rep->dra_rep = NULL;
1318  goto out;
1319  }
1320  if (type == REQ_NEXT)
1321  rep->dra_nr = m0_reduce(i, keys->ov_vec.v_nr,
1322  0, + (m0_dix_item_rc(&req, i) ?
1323  0 : m0_dix_next_rep_nr(&req, i)));
1324  else
1325  rep->dra_nr = m0_dix_req_nr(&req);
1326  if (rep->dra_nr == 0) {
1327  rep->dra_rep = NULL;
1328  rc = M0_ERR(-ENOENT);
1329  goto out;
1330  }
1331  M0_ALLOC_ARR(rep->dra_rep, rep->dra_nr);
1332  M0_UT_ASSERT(rep->dra_rep != NULL);
1333  switch (type) {
1334  case REQ_PUT:
1335  case REQ_DEL:
1336  for (i = 0; i < rep->dra_nr; i++)
1337  rep->dra_rep[i].dre_rc =
1338  m0_dix_item_rc(&req, i);
1339  break;
1340  case REQ_GET:
1341  for (i = 0; i < rep->dra_nr; i++) {
1342  struct m0_dix_get_reply get_rep;
1343 
1344  m0_dix_get_rep(&req, i, &get_rep);
1345  rep->dra_rep[i].dre_rc = get_rep.dgr_rc;
1346  if (rep->dra_rep[i].dre_rc != 0)
1347  continue;
1348  m0_buf_copy(&rep->dra_rep[i].dre_key,
1349  &(struct m0_buf) {
1350  .b_addr = keys->ov_buf[i],
1351  .b_nob = keys->ov_vec.v_count[i]
1352  });
1353  m0_buf_copy(&rep->dra_rep[i].dre_val,
1354  &get_rep.dgr_val);
1355  }
1356  break;
1357  case REQ_NEXT:
1358  for (i = 0; i < keys->ov_vec.v_nr; i++) {
1359  struct m0_dix_next_reply nrep;
1360  uint32_t j;
1361  int rc2;
1362 
1363  rc2 = m0_dix_item_rc(&req, i);
1364  if (rc2 != 0) {
1365  rep->dra_rep[k++].dre_rc = rc2;
1366  continue;
1367  }
1368  for (j = 0; j < m0_dix_next_rep_nr(&req, i); j++) {
1369  m0_dix_next_rep(&req, i, j, &nrep);
1370  rep->dra_rep[k].dre_rc = 0;
1371  m0_buf_copy(&rep->dra_rep[k].dre_key,
1372  &nrep.dnr_key);
1373  m0_buf_copy(&rep->dra_rep[k].dre_val,
1374  &nrep.dnr_val);
1375  k++;
1376  }
1377  }
1378  break;
1379  default:
1380  M0_IMPOSSIBLE("Unknown req type");
1381  }
1382 out:
1384  return rc;
1385 }
1386 
1387 static int dix_ut_put(const struct m0_dix *index,
1388  const struct m0_bufvec *keys,
1389  struct m0_bufvec *vals,
1390  uint32_t flags,
1391  struct dix_rep_arr *rep)
1392 {
1393  return dix_common_rec_op(index, keys, vals, NULL, flags, rep, REQ_PUT);
1394 }
1395 
1396 static int dix_ut_get(const struct m0_dix *index,
1397  const struct m0_bufvec *keys,
1398  struct dix_rep_arr *rep)
1399 {
1400  return dix_common_rec_op(index, keys, NULL, NULL, 0, rep, REQ_GET);
1401 }
1402 
1403 static int dix_ut_del(const struct m0_dix *index,
1404  const struct m0_bufvec *keys,
1405  struct dix_rep_arr *rep)
1406 {
1407  return dix_common_rec_op(index, keys, NULL, NULL, 0, rep, REQ_DEL);
1408 }
1409 
1410 static int dix_ut_next(const struct m0_dix *index,
1411  const struct m0_bufvec *start_keys,
1412  const uint32_t *recs_nr,
1413  uint32_t flags,
1414  struct dix_rep_arr *rep)
1415 {
1416  return dix_common_rec_op(index, start_keys, NULL, recs_nr, flags,
1417  rep, REQ_NEXT);
1418 }
1419 
1420 static void dix_index_create_and_fill(const struct m0_dix *index,
1421  const struct m0_bufvec *keys,
1422  struct m0_bufvec *vals,
1423  uint32_t flags)
1424 {
1425  uint32_t count = keys->ov_vec.v_nr;
1426  struct dix_rep_arr rep;
1427  int rc;
1428 
1430  M0_UT_ASSERT(rc == 0);
1431  rc = dix_ut_put(index, keys, vals, flags, &rep);
1432  M0_UT_ASSERT(rc == 0);
1433  M0_UT_ASSERT(rep.dra_nr == count);
1434  M0_UT_ASSERT(m0_forall(i, count, rep.dra_rep[i].dre_rc == 0));
1435  dix_rep_free(&rep);
1436 }
1437 
1438 static void dix_create(void)
1439 {
1440  struct m0_dix indices[COUNT_INDEX];
1441  uint32_t indices_nr = ARRAY_SIZE(indices);
1442  int i;
1443  int rc;
1444 
1445  ut_service_init();
1446  for (i = 0; i < indices_nr; i++)
1447  dix_index_init(&indices[i], i);
1448  rc = dix_common_idx_op(indices, indices_nr, REQ_CREATE);
1449  M0_UT_ASSERT(rc == 0);
1450  for (i = 0; i < indices_nr; i++)
1452  ut_service_fini();
1453 }
1454 
1455 static void dix_create_crow(void)
1456 {
1457  struct m0_dix indices[COUNT_INDEX];
1458  uint32_t indices_nr = ARRAY_SIZE(indices);
1459  int i;
1460  int rc;
1461 
1462  ut_service_init();
1463  for (i = 0; i < indices_nr; i++)
1464  dix_index_init(&indices[i], i);
1466  COF_CROW);
1467  M0_UT_ASSERT(rc == 0);
1468  for (i = 0; i < indices_nr; i++)
1470  ut_service_fini();
1471 }
1472 
1473 static void dix_create_dgmode(void)
1474 {
1475  struct m0_dix indices[COUNT_INDEX];
1476  uint32_t indices_nr = ARRAY_SIZE(indices);
1477  int i;
1478  int rc;
1479 
1480  if (ENABLE_DTM0)
1481  return;
1482 
1483  ut_service_init();
1484  for (i = 0; i < indices_nr; i++)
1485  dix_index_init(&indices[i], i);
1487  /*
1488  * Create operation with COF_CROW should succeed, because it's not
1489  * necessary to create all component catalogues during index creation.
1490  */
1492  COF_CROW);
1493  M0_UT_ASSERT(rc == 0);
1495  COF_CROW);
1496  M0_UT_ASSERT(rc == 0);
1497 
1498  /*
1499  * Create operation without COF_CROW should fail, because it's
1500  * impossible to create all component catalogues for any distributed
1501  * index.
1502  */
1503  rc = dix_common_idx_op(indices, indices_nr, REQ_CREATE);
1504  M0_UT_ASSERT(rc == -EIO);
1505  rc = dix_common_idx_op(indices, indices_nr, REQ_DELETE);
1506  M0_UT_ASSERT(rc == -ENOENT);
1507 
1508  dix_disk_online_set(10);
1509  for (i = 0; i < indices_nr; i++)
1511  ut_service_fini();
1512 }
1513 
1514 static void dix_delete(void)
1515 {
1516  struct m0_dix indices[COUNT_INDEX];
1517  uint32_t indices_nr = ARRAY_SIZE(indices);
1518  int i;
1519  int rc;
1520 
1521  ut_service_init();
1522  for (i = 0; i < indices_nr; i++)
1523  dix_index_init(&indices[i], i);
1524  rc = dix_common_idx_op(indices, indices_nr, REQ_CREATE);
1525  M0_UT_ASSERT(rc == 0);
1526  rc = dix_common_idx_op(indices, indices_nr, REQ_DELETE);
1527  M0_UT_ASSERT(rc == 0);
1528  for (i = 0; i < indices_nr; i++)
1530  ut_service_fini();
1531 }
1532 
1533 static void dix_delete_crow(void)
1534 {
1535  struct m0_dix indices[COUNT_INDEX];
1536  uint32_t indices_nr = ARRAY_SIZE(indices);
1537  struct m0_bufvec keys;
1538  struct m0_bufvec vals;
1539  struct dix_rep_arr rep;
1540  int i;
1541  int rc;
1542 
1543  ut_service_init();
1544  for (i = 0; i < indices_nr; i++)
1545  dix_index_init(&indices[i], i);
1546  rc = dix_common_idx_op(indices, indices_nr, REQ_CREATE);
1547  M0_UT_ASSERT(rc == 0);
1548  /* Put some records to actually create component catalogues. */
1549  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
1550  for (i = 0; i < indices_nr; i++) {
1551  rc = dix_ut_put(&indices[0], &keys, &vals, 0, &rep);
1552  M0_UT_ASSERT(rc == 0);
1553  dix_rep_free(&rep);
1554  }
1555  dix_kv_destroy(&keys, &vals);
1556  /*
1557  * Remove the indices and try to create indices with the same fids again
1558  * without CROW flag. Successful return code means that all component
1559  * catalogues were removed.
1560  */
1562  COF_CROW);
1563  M0_UT_ASSERT(rc == 0);
1564  rc = dix_common_idx_op(indices, indices_nr, REQ_CREATE);
1565  M0_UT_ASSERT(rc == 0);
1566  rc = dix_common_idx_op(indices, indices_nr, REQ_DELETE);
1567  M0_UT_ASSERT(rc == 0);
1568  for (i = 0; i < indices_nr; i++)
1570  ut_service_fini();
1571 }
1572 
1573 static void dix_delete_dgmode(void)
1574 {
1575  struct m0_dix indices[COUNT_INDEX];
1576  uint32_t indices_nr = ARRAY_SIZE(indices);
1577  int i;
1578  int rc;
1579 
1580  if (ENABLE_DTM0)
1581  return;
1582 
1583  ut_service_init();
1584  for (i = 0; i < indices_nr; i++)
1585  dix_index_init(&indices[i], i);
1586  /*
1587  * Delete in dgmode for non-existing catalogue.
1588  */
1590  rc = dix_common_idx_op(indices, indices_nr, REQ_DELETE);
1591  M0_UT_ASSERT(rc == -ENOENT);
1592  dix_disk_online_set(10);
1593 
1594  /*
1595  * Create indices in non-degraded mode, then failure one device and
1596  * delete the indices.
1597  */
1598  rc = dix_common_idx_op(indices, indices_nr, REQ_CREATE);
1599  M0_UT_ASSERT(rc == 0);
1600 
1602  rc = dix_common_idx_op(indices, indices_nr, REQ_DELETE);
1603  M0_UT_ASSERT(rc == 0);
1604  dix_disk_online_set(10);
1605 
1606  for (i = 0; i < indices_nr; i++)
1608  ut_service_fini();
1609 }
1610 
1611 static int dix_list_op(const struct m0_fid *start_fid,
1612  uint32_t indices_nr,
1613  struct m0_fid *out_fids,
1614  uint32_t *out_fids_nr)
1615 {
1616  struct m0_dix_meta_req mreq;
1617  struct m0_clink clink;
1618  uint32_t i;
1619  int rc;
1620 
1623  m0_clink_add_lock(&mreq.dmr_chan, &clink);
1624  m0_dix_meta_lock(&mreq);
1625  rc = m0_dix_index_list(&mreq, start_fid, indices_nr);
1626  m0_dix_meta_unlock(&mreq);
1627  M0_UT_ASSERT(rc == 0);
1628  m0_chan_wait(&clink);
1629  rc = m0_dix_meta_generic_rc(&mreq) ?:
1630  m0_dix_meta_item_rc(&mreq, 0);
1631  if (rc == 0) {
1632  *out_fids_nr = m0_dix_index_list_rep_nr(&mreq);
1633  for (i = 0; i < *out_fids_nr; i++)
1634  m0_dix_index_list_rep(&mreq, i, &out_fids[i]);
1635  }
1638  return rc;
1639 }
1640 
1641 static void dix_list(void)
1642 {
1643  enum {
1644  LIST_INDEX_REQ_NR = 100,
1645  };
1646 
1647  struct m0_dix indices[COUNT_INDEX];
1648  uint32_t indices_nr = ARRAY_SIZE(indices);
1649  struct m0_fid start_fid;
1650  struct m0_fid res[LIST_INDEX_REQ_NR];
1651  uint32_t res_nr = 0;
1652  int i;
1653  int rc;
1654 
1655  ut_service_init();
1656  for (i = 0; i < indices_nr; i++)
1657  dix_index_init(&indices[i], i);
1658  rc = dix_common_idx_op(indices, indices_nr, REQ_CREATE);
1659  M0_UT_ASSERT(rc == 0);
1660 
1661  /* List indices from the beginning. */
1662  start_fid = M0_FID_INIT(0, 0);
1663  rc = dix_list_op(&start_fid, LIST_INDEX_REQ_NR, res, &res_nr);
1664  M0_UT_ASSERT(rc == 0);
1665  M0_UT_ASSERT(res_nr == indices_nr);
1666  M0_UT_ASSERT(m0_forall(i, indices_nr,
1667  m0_fid_eq(&res[i], &DFID(1, i))));
1668 
1669  for (i = 0; i < indices_nr; i++)
1671  ut_service_fini();
1672 }
1673 
1674 static void dix_cctgs_lookup(void)
1675 {
1676  struct m0_dix indices[COUNT_INDEX];
1677  uint32_t indices_nr = ARRAY_SIZE(indices);
1678  struct m0_dix lookup_indices[COUNT_INDEX];
1679  struct m0_dix unknown_indices[COUNT_INDEX];
1680  int i;
1681  int rc;
1682 
1683  ut_service_init();
1684  for (i = 0; i < indices_nr; i++)
1685  dix_index_init(&indices[i], i);
1686  rc = dix_common_idx_op(indices, indices_nr, REQ_CREATE);
1687  M0_UT_ASSERT(rc == 0);
1688  for (i = 0; i < indices_nr; i++) {
1689  lookup_indices[i] = (struct m0_dix) { .dd_fid = DFID(1, i) };
1690  unknown_indices[i] =
1691  (struct m0_dix) { .dd_fid = DFID(1, 100 + i) };
1692  }
1693  /* Lookup existing indices. */
1694  rc = dix_common_idx_op(lookup_indices, indices_nr, REQ_LOOKUP);
1695  M0_UT_ASSERT(rc == 0);
1696  /* Lookup unknown indices. */
1697  rc = dix_common_idx_op(unknown_indices, indices_nr, REQ_LOOKUP);
1698  M0_UT_ASSERT(rc == -ENOENT);
1699  /* Delete all indices. */
1700  rc = dix_common_idx_op(indices, indices_nr, REQ_DELETE);
1701  M0_UT_ASSERT(rc == 0);
1702  /* Try to lookup deleted items. */
1703  rc = dix_common_idx_op(lookup_indices, indices_nr, REQ_LOOKUP);
1704  M0_UT_ASSERT(rc == -ENOENT);
1705  for (i = 0; i < indices_nr; i++)
1707  ut_service_fini();
1708 }
1709 
1710 static void dix_put(void)
1711 {
1712  struct m0_dix index;
1713  struct m0_bufvec keys;
1714  struct m0_bufvec vals;
1715  struct dix_rep_arr rep;
1716  int rc;
1717 
1718  ut_service_init();
1719  dix_index_init(&index, 1);
1720  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
1722  M0_UT_ASSERT(rc == 0);
1723  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
1724  M0_UT_ASSERT(rc == 0);
1725  M0_UT_ASSERT(rep.dra_nr == COUNT);
1726  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
1727  dix_rep_free(&rep);
1728  dix_kv_destroy(&keys, &vals);
1730  ut_service_fini();
1731 }
1732 
1733 static void dix_put_overwrite(void)
1734 {
1735  struct m0_dix index;
1736  struct m0_bufvec keys;
1737  struct m0_bufvec vals;
1738  struct dix_rep_arr rep;
1739  uint32_t recs_nr = COUNT;
1740  struct m0_bufvec start_key;
1741  int rc;
1742 
1743  ut_service_init();
1744  dix_index_init(&index, 1);
1745  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
1747  M0_UT_ASSERT(rc == 0);
1748  /* If there are no records, than they should be created. */
1749  rc = dix_ut_put(&index, &keys, &vals, COF_OVERWRITE, &rep);
1750  M0_UT_ASSERT(rc == 0);
1751  M0_UT_ASSERT(rep.dra_nr == COUNT);
1752  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
1753  dix_rep_free(&rep);
1754  rc = dix_ut_get(&index, &keys, &rep);
1755  M0_UT_ASSERT(rc == 0);
1757  dix_rep_free(&rep);
1758  dix_kv_destroy(&keys, &vals);
1759 
1760  /* If there are records, than they should be overwritten. */
1761  dix__kv_alloc_and_fill(&keys, &vals, 10, 10 + COUNT - 1);
1762  rc = dix_ut_put(&index, &keys, &vals, COF_OVERWRITE, &rep);
1763  M0_UT_ASSERT(rc == 0);
1764  M0_UT_ASSERT(rep.dra_nr == COUNT);
1765  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
1766  dix_rep_free(&rep);
1767  rc = dix_ut_get(&index, &keys, &rep);
1768  M0_UT_ASSERT(rc == 0);
1769  dix__vals_check(&rep, 0, 10, 10 + COUNT - 1);
1770  dix_rep_free(&rep);
1771 
1772  /* Removing records should clear the index. */
1773  rc = dix_ut_del(&index, &keys, &rep);
1774  M0_UT_ASSERT(rc == 0);
1775  M0_UT_ASSERT(rep.dra_nr == COUNT);
1776  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
1777  dix_rep_free(&rep);
1778 
1779  m0_bufvec_alloc(&start_key, 1, sizeof(uint64_t));
1780  *(uint64_t *)start_key.ov_buf[0] = 0;
1781  rc = dix_ut_next(&index, &start_key, &recs_nr, 0, &rep);
1782  M0_UT_ASSERT(rc == -ENOENT);
1783  dix_rep_free(&rep);
1784  dix_kv_destroy(&keys, &vals);
1785 
1787  ut_service_fini();
1788 }
1789 
1790 static void dix_put_crow(void)
1791 {
1792  struct m0_dix index;
1793  struct m0_bufvec keys;
1794  struct m0_bufvec vals;
1795  struct dix_rep_arr rep;
1796  int rc;
1797 
1798  ut_service_init();
1799  dix_index_init(&index, 1);
1800  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
1802  M0_UT_ASSERT(rc == 0);
1803  rc = dix_ut_put(&index, &keys, &vals, COF_CROW, &rep);
1804  M0_UT_ASSERT(rc == 0);
1805  M0_UT_ASSERT(rep.dra_nr == COUNT);
1806  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
1807  dix_rep_free(&rep);
1808  rc = dix_ut_get(&index, &keys, &rep);
1809  M0_UT_ASSERT(rc == 0);
1811  dix_rep_free(&rep);
1812  dix_kv_destroy(&keys, &vals);
1814  ut_service_fini();
1815 }
1816 
1817 static void dix_put_dgmode(void)
1818 {
1819  struct m0_dix index;
1820  struct m0_bufvec keys;
1821  struct m0_bufvec vals;
1822  struct dix_rep_arr rep;
1823  uint32_t sdev_id;
1824  int rc;
1825 
1826  if (ENABLE_DTM0)
1827  return;
1828 
1829  ut_service_init();
1831  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
1833  M0_UT_ASSERT(rc == 0);
1834 
1836 
1837  /*
1838  * Put record when one drive is failed.
1839  * The record should be inserted in a spare unit.
1840  */
1841  sdev_id = dix_sdev_id(PG_UNIT_DATA);
1843  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
1844  M0_UT_ASSERT(rc == 0);
1845  M0_UT_ASSERT(rep.dra_nr == COUNT);
1846  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
1847  M0_UT_ASSERT(dix_cctg_has_replica(&index, &keys, &vals,
1849  dix_rep_free(&rep);
1850  rc = dix_ut_del(&index, &keys, &rep);
1851  M0_UT_ASSERT(rc == 0);
1852  dix_rep_free(&rep);
1853  dix_disk_online_set(sdev_id);
1854  dix_records_erase(&index, &keys);
1855 
1856  /*
1857  * Put record when the drive with data unit is in repairing state.
1858  * Spare slot should be used instead of this drive.
1859  */
1860  sdev_id = dix_sdev_id(PG_UNIT_DATA);
1862  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
1863  M0_UT_ASSERT(rc == 0);
1864  M0_UT_ASSERT(rep.dra_nr == COUNT);
1865  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
1866  M0_UT_ASSERT(dix_cctg_has_replica(&index, &keys, &vals,
1868  dix_rep_free(&rep);
1869  dix_disk_online_set(sdev_id);
1870  M0_UT_ASSERT(!dix_cctg_has_replica(&index, &keys, &vals,
1872  dix_records_erase(&index, &keys);
1873 
1874  /*
1875  * Put record when the drive with data unit is in re-balancing state.
1876  * Spare slot and re-balance target should both be updated.
1877  */
1878  sdev_id = dix_sdev_id(PG_UNIT_DATA);
1880  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
1881  M0_UT_ASSERT(rc == 0);
1882  M0_UT_ASSERT(rep.dra_nr == COUNT);
1883  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
1884  M0_UT_ASSERT(dix_cctg_has_replica(&index, &keys, &vals,
1886  M0_UT_ASSERT(dix_cctg_has_replica(&index, &keys, &vals,
1888  dix_rep_free(&rep);
1889  dix_records_erase(&index, &keys);
1890  dix_disk_online_set(sdev_id);
1891 
1892  dix_kv_destroy(&keys, &vals);
1894  ut_service_fini();
1895 }
1896 
1897 static void dix_get(void)
1898 {
1899  struct m0_dix index;
1900  struct m0_bufvec keys;
1901  struct m0_bufvec vals;
1902  struct m0_bufvec ret_vals;
1903  struct dix_rep_arr rep;
1904  int rc;
1905 
1906  ut_service_init();
1907  dix_index_init(&index, 1);
1908  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
1909  dix_index_create_and_fill(&index, &keys, &vals, 0);
1910  /* Get values by existing keys. */
1911  rc = m0_bufvec_alloc(&ret_vals, COUNT, sizeof (uint64_t));
1912  M0_UT_ASSERT(rc == 0);
1913  rc = dix_ut_get(&index, &keys, &rep);
1914  M0_UT_ASSERT(rc == 0);
1916  dix_rep_free(&rep);
1917  /* Get values by non-existing keys. */
1918  rc = dix_ut_del(&index, &keys, &rep);
1919  M0_UT_ASSERT(rc == 0);
1920  dix_rep_free(&rep);
1921  rc = dix_ut_get(&index, &keys, &rep);
1922  M0_UT_ASSERT(rc == 0);
1923  M0_UT_ASSERT(rep.dra_nr == COUNT);
1924  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == -ENOENT));
1925  dix_rep_free(&rep);
1926  m0_bufvec_free(&ret_vals);
1927  dix_kv_destroy(&keys, &vals);
1929  ut_service_fini();
1930 }
1931 
1932 static void dix_dgmode_disks_prep(enum ut_pg_unit unit1,
1933  enum m0_pool_nd_state state1,
1934  enum ut_pg_unit unit2,
1935  enum m0_pool_nd_state state2,
1936  struct m0_dix *index,
1937  struct m0_bufvec *keys,
1938  struct m0_bufvec *vals)
1939 {
1940  int rc;
1941 
1942  M0_PRE(unit1 < unit2);
1943  if (unit1 < PG_UNIT_SPARE0) {
1944  rc = dix_cctg_records_del(index, keys, dix_sdev_id(unit1));
1945  M0_UT_ASSERT(rc == 0);
1946  }
1947 
1948  if (unit2 < PG_UNIT_SPARE0) {
1949  rc = dix_cctg_records_del(index, keys, dix_sdev_id(unit2));
1950  M0_UT_ASSERT(rc == 0);
1951  }
1952 
1953  if (M0_IN(state1, (M0_PNDS_SNS_REPAIRED, M0_PNDS_SNS_REBALANCING)) &&
1954  unit1 < PG_UNIT_SPARE0) {
1955  if (unit2 == PG_UNIT_SPARE0 &&
1956  M0_IN(state2, (M0_PNDS_SNS_REPAIRED,
1958  dix_cctg_records_put(index, keys, vals,
1960  } else {
1961  dix_cctg_records_put(index, keys, vals,
1963 
1964  }
1965  }
1966 
1967  if (M0_IN(state2, (M0_PNDS_SNS_REPAIRED, M0_PNDS_SNS_REBALANCING)) &&
1968  unit2 < PG_UNIT_SPARE0)
1969  dix_cctg_records_put(index, keys, vals,
1971 }
1972 
1973 static void dix_dgmode_disks_unprep(enum ut_pg_unit unit1,
1974  enum m0_pool_nd_state state1,
1975  enum ut_pg_unit unit2,
1976  enum m0_pool_nd_state state2,
1977  struct m0_dix *index,
1978  struct m0_bufvec *keys,
1979  struct m0_bufvec *vals)
1980 {
1981  int rc;
1982 
1983  if (unit1 < PG_UNIT_SPARE0)
1984  dix_cctg_records_put(index, keys, vals, dix_sdev_id(unit1));
1985 
1986  if (unit2 < PG_UNIT_SPARE0)
1987  dix_cctg_records_put(index, keys, vals, dix_sdev_id(unit2));
1988 
1989  if (M0_IN(state1, (M0_PNDS_SNS_REPAIRED, M0_PNDS_SNS_REBALANCING)) &&
1990  unit1 < PG_UNIT_SPARE0) {
1991  if (unit2 == PG_UNIT_SPARE0 &&
1992  M0_IN(state2, (M0_PNDS_SNS_REPAIRED,
1994  rc = dix_cctg_records_del(index, keys,
1996  M0_UT_ASSERT(rc == 0);
1997  } else {
1998  rc = dix_cctg_records_del(index, keys,
2000  M0_UT_ASSERT(rc == 0);
2001  }
2002  }
2003 
2004  if (M0_IN(state2, (M0_PNDS_SNS_REPAIRED, M0_PNDS_SNS_REBALANCING)) &&
2005  unit2 < PG_UNIT_SPARE0) {
2006  rc = dix_cctg_records_del(index, keys,
2008  M0_UT_ASSERT(rc == 0);
2009  }
2010 }
2011 
2012 static void dix_get_dgmode(void)
2013 {
2014  struct m0_dix index;
2015  struct m0_bufvec keys;
2016  struct m0_bufvec vals;
2017  enum ut_pg_unit i;
2018  enum ut_pg_unit j;
2019  enum m0_pool_nd_state s1;
2020  enum m0_pool_nd_state s2;
2021  struct dix_rep_arr rep;
2022  int rc;
2023 
2024  if (ENABLE_DTM0)
2025  return;
2026 
2027  ut_service_init();
2029  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
2031  M0_UT_ASSERT(rc == 0);
2032  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
2033  M0_UT_ASSERT(rc == 0);
2034  dix_rep_free(&rep);
2035 
2037 
2038  /*
2039  * Get record when drive is failed.
2040  * The drive should be skipped.
2041  */
2043  rc = dix_ut_get(&index, &keys, &rep);
2045  M0_UT_ASSERT(rc == 0);
2046  dix_rep_free(&rep);
2048 
2049  /*
2050  * Get should work for every combination of two failed devices.
2051  * If a failed drive is not repaired yet, then it should be skipped.
2052  * Otherwise, spare unit is used instead of the failed one.
2053  */
2054  for (i = PG_UNIT_DATA; i < PG_UNIT_SPARE1; i++) {
2055  for (s1 = M0_PNDS_FAILED; s1 <= M0_PNDS_SNS_REBALANCING; s1++) {
2056  for (j = i + 1; j <= PG_UNIT_SPARE1; j++) {
2057  for (s2 = M0_PNDS_FAILED;
2058  s2 <= M0_PNDS_SNS_REBALANCING; s2++) {
2059  if (s1 == M0_PNDS_OFFLINE ||
2060  s2 == M0_PNDS_OFFLINE)
2061  continue;
2062  dix_dgmode_disks_prep(i, s1, j, s2,
2063  &index, &keys,
2064  &vals);
2066  s1);
2068  s2);
2069  rc = dix_ut_get(&index, &keys, &rep);
2070  M0_UT_ASSERT(rc == 0);
2072  dix_rep_free(&rep);
2075  dix_dgmode_disks_unprep(i, s1, j, s2,
2076  &index, &keys,
2077  &vals);
2078  }
2079  }
2080  }
2081  }
2082 
2083 
2084  dix_kv_destroy(&keys, &vals);
2086  ut_service_fini();
2087 }
2088 
2089 static void dix_get_resend(void)
2090 {
2091  struct m0_dix index;
2092  struct m0_bufvec keys;
2093  struct m0_bufvec vals;
2094  struct dix_rep_arr rep;
2095  int rc;
2096 
2097  ut_service_init();
2098  dix_index_init(&index, 1);
2099  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
2100  dix_index_create_and_fill(&index, &keys, &vals, 0);
2101 
2102  /*
2103  * Imitate one failure during GET operation, the record should be
2104  * re-requested from parity unit.
2105  */
2106  m0_fi_enable_once("cas_place", "place_fail");
2107  rc = dix_ut_get(&index, &keys, &rep);
2108  M0_UT_ASSERT(rc == 0);
2110  dix_rep_free(&rep);
2111 
2112  /*
2113  * Imitate many failures during GET operation, so retrieval from data
2114  * and parity unit locations fails.
2115  */
2116  m0_fi_enable("cas_place", "place_fail");
2117  rc = dix_ut_get(&index, &keys, &rep);
2118  M0_UT_ASSERT(rc == -EHOSTUNREACH);
2119  dix_rep_free(&rep);
2120  m0_fi_disable("cas_place", "place_fail");
2121 
2122  dix_kv_destroy(&keys, &vals);
2124  ut_service_fini();
2125 }
2126 
2127 static void dix_next(void)
2128 {
2129  struct m0_dix index;
2130  struct m0_bufvec keys;
2131  struct m0_bufvec next_keys;
2132  struct m0_bufvec vals;
2133  struct dix_rep_arr rep;
2134  uint32_t recs_nr[COUNT/2];
2135  int i;
2136  int rc;
2137 
2138  /* Usual case. */
2139  ut_service_init();
2140  dix_index_init(&index, 1);
2141  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
2142  dix_index_create_and_fill(&index, &keys, &vals, 0);
2143  /* Get values by operation NEXT for existing keys. */
2144  rc = m0_bufvec_alloc(&next_keys, COUNT/2, sizeof (uint64_t));
2145  M0_UT_ASSERT(rc == 0);
2146  /* Request NEXT for all keys. */
2147  for (i = 0; i < COUNT/2; i++) {
2148  *(uint64_t *)next_keys.ov_buf[i] = dix_key(2 * i);
2149  recs_nr[i] = 2;
2150  }
2151  rc = dix_ut_next(&index, &next_keys, recs_nr, 0, &rep);
2152  M0_UT_ASSERT(rc == 0);
2154  dix_rep_free(&rep);
2155  dix_kv_destroy(&keys, &vals);
2157 
2158  ut_service_fini();
2159 
2160  /* 'Exclude start key' case. */
2161  ut_service_init();
2162  dix_index_init(&index, 1);
2163  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
2164  dix_index_create_and_fill(&index, &keys, &vals, 0);
2165  /* Get values by operation NEXT for existing keys. */
2166  rc = m0_bufvec_alloc(&next_keys, COUNT/2, sizeof (uint64_t));
2167  M0_UT_ASSERT(rc == 0);
2168  /* Request NEXT for all keys excluding start key. */
2169  for (i = 0; i < COUNT/2; i++) {
2170  *(uint64_t *)next_keys.ov_buf[i] = dix_key(2 * i);
2171  recs_nr[i] = 2;
2172  }
2173  rc = dix_ut_next(&index, &next_keys, recs_nr, COF_EXCLUDE_START_KEY,
2174  &rep);
2175  M0_UT_ASSERT(rc == 0);
2176  dix__vals_check(&rep, 1, 0, COUNT - 2);
2177  dix_rep_free(&rep);
2178  dix_kv_destroy(&keys, &vals);
2180 
2181  ut_service_fini();
2182 }
2183 
2184 static void dix_next_crow(void)
2185 {
2186  struct m0_dix index;
2187  struct m0_bufvec keys;
2188  struct m0_bufvec next_keys;
2189  struct m0_bufvec vals;
2190  struct dix_rep_arr rep;
2191  uint32_t recs_nr[1];
2192  int rc;
2193 
2194  ut_service_init();
2195  dix_index_init(&index, 1);
2196  dix_kv_alloc_and_fill(&keys, &vals, 1);
2197 
2198  /* Create index with CROW flag. */
2200  M0_UT_ASSERT(rc == 0);
2201 
2202  /* Get values by operation NEXT from empty index. */
2203  rc = m0_bufvec_alloc(&next_keys, 1, sizeof (uint64_t));
2204  M0_UT_ASSERT(rc == 0);
2205  *(uint64_t *)next_keys.ov_buf[0] = dix_key(0);
2206  recs_nr[0] = 3;
2207  rc = dix_ut_next(&index, &next_keys, recs_nr, 0, &rep);
2208  M0_UT_ASSERT(rc == -ENOENT);
2209  dix_rep_free(&rep);
2210 
2211  /* Put one key with CROW flag. */
2212  rc = dix_ut_put(&index, &keys, &vals, COF_CROW, &rep);
2213  M0_UT_ASSERT(rc == 0);
2214  M0_UT_ASSERT(rep.dra_nr == 1);
2215  M0_UT_ASSERT(rep.dra_rep[0].dre_rc == 0);
2216  dix_rep_free(&rep);
2217 
2218  /* Get one record by operation NEXT for existing key. */
2219  recs_nr[0] = 1;
2220  rc = dix_ut_next(&index, &next_keys, recs_nr, 0, &rep);
2221  M0_UT_ASSERT(rc == 0);
2222  dix_vals_check(&rep, 1);
2223  dix_rep_free(&rep);
2224 
2225  /* Get three records by operation NEXT for existing key. */
2226  recs_nr[0] = 3;
2227  rc = dix_ut_next(&index, &next_keys, recs_nr, 0, &rep);
2228  M0_UT_ASSERT(rc == 0);
2229  dix_vals_check(&rep, 1);
2230  dix_rep_free(&rep);
2231 
2232  dix_kv_destroy(&keys, &vals);
2234  ut_service_fini();
2235 }
2236 
2237 static void dix_next_dgmode(void)
2238 {
2239  struct m0_dix index;
2240  struct m0_bufvec keys;
2241  struct m0_bufvec start_key;
2242  struct m0_bufvec vals;
2243  struct dix_rep_arr rep;
2244  uint32_t recs_nr = COUNT;
2245  int rc;
2246 
2247  if (ENABLE_DTM0)
2248  return;
2249 
2250  ut_service_init();
2251  dix_index_init(&index, 1);
2252  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
2253  dix_index_create_and_fill(&index, &keys, &vals, 0);
2254  rc = m0_bufvec_alloc(&start_key, 1, sizeof (uint64_t));
2255  M0_UT_ASSERT(rc == 0);
2256  *(uint64_t *)start_key.ov_buf[0] = dix_key(0);
2257 
2258  /* Fetch all records when one drive is failed. */
2260  rc = dix_ut_next(&index, &start_key, &recs_nr, 0, &rep);
2261  M0_UT_ASSERT(rc == 0);
2263  dix_rep_free(&rep);
2264  dix_disk_online_set(10);
2265 
2266  /* Fetch all records when 2 drives are failed. */
2269  rc = dix_ut_next(&index, &start_key, &recs_nr, 0, &rep);
2270  M0_UT_ASSERT(rc == 0);
2272  dix_rep_free(&rep);
2273  dix_disk_online_set(10);
2274  dix_disk_online_set(11);
2275 
2276  /*
2277  * Try to fetch all records when 3 drives are failed.
2278  * The maximum number of drive failures supported is 2, so DIX client
2279  * should return an IO error.
2280  */
2284  rc = dix_ut_next(&index, &start_key, &recs_nr, 0, &rep);
2285  M0_UT_ASSERT(rc == -EIO);
2286  dix_rep_free(&rep);
2287  dix_disk_online_set(10);
2288  dix_disk_online_set(11);
2289  dix_disk_online_set(12);
2290 
2291  m0_bufvec_free(&start_key);
2292  dix_kv_destroy(&keys, &vals);
2294  ut_service_fini();
2295 }
2296 
2297 static void dix_del(void)
2298 {
2299  struct m0_dix index;
2300  struct m0_bufvec keys;
2301  struct m0_bufvec vals;
2302  struct dix_rep_arr rep;
2303  int rc;
2304 
2305  ut_service_init();
2306  dix_index_init(&index, 1);
2307  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
2309  M0_UT_ASSERT(rc == 0);
2310  rc = dix_ut_del(&index, &keys, &rep);
2311  M0_UT_ASSERT(rc == 0);
2312  M0_UT_ASSERT(rep.dra_nr == COUNT);
2313  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == -ENOENT));
2314  dix_rep_free(&rep);
2315  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
2316  M0_UT_ASSERT(rc == 0);
2317  dix_rep_free(&rep);
2318  rc = dix_ut_del(&index, &keys, &rep);
2319  M0_UT_ASSERT(rc == 0);
2320  M0_UT_ASSERT(rep.dra_nr == COUNT);
2321  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2322  dix_rep_free(&rep);
2323  rc = dix_ut_del(&index, &keys, &rep);
2324  M0_UT_ASSERT(rc == 0);
2325  M0_UT_ASSERT(rep.dra_nr == COUNT);
2326  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == -ENOENT));
2327  dix_rep_free(&rep);
2328  dix_kv_destroy(&keys, &vals);
2330  ut_service_fini();
2331 }
2332 
2333 static void dix_records_restore(struct m0_dix *index, struct m0_bufvec *keys,
2334  struct m0_bufvec *vals)
2335 {
2336  struct dix_rep_arr rep;
2337  int rc;
2338 
2339  rc = dix_ut_del(index, keys, &rep);
2340  M0_UT_ASSERT(rc == 0);
2341  dix_rep_free(&rep);
2342  rc = dix_ut_put(index, keys, vals, 0, &rep);
2343  M0_UT_ASSERT(rc == 0);
2344  dix_rep_free(&rep);
2345 }
2346 
2347 static void dix_del_dgmode(void)
2348 {
2349  struct m0_dix index;
2350  struct m0_bufvec keys;
2351  struct m0_bufvec vals;
2352  struct dix_rep_arr rep;
2353  uint32_t sdev_id;
2354  int rc;
2355 
2356  if (ENABLE_DTM0)
2357  return;
2358 
2359  ut_service_init();
2361  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
2363  M0_UT_ASSERT(rc == 0);
2364  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
2365  M0_UT_ASSERT(rc == 0);
2366  dix_rep_free(&rep);
2367 
2369 
2370  /*
2371  * Delete record when one drive is failed.
2372  * The drive should simply be skipped.
2373  */
2374  sdev_id = dix_sdev_id(PG_UNIT_DATA);
2375  rc = dix_cctg_records_del(&index, &keys, sdev_id);
2376  M0_UT_ASSERT(rc == 0);
2378  rc = dix_ut_del(&index, &keys, &rep);
2379  M0_UT_ASSERT(rc == 0);
2380  M0_UT_ASSERT(rep.dra_nr == COUNT);
2381  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2382  dix_rep_free(&rep);
2383  dix_disk_online_set(sdev_id);
2384  dix_records_restore(&index, &keys, &vals);
2385 
2386  /*
2387  * Delete record when the drive with data unit is in repairing state.
2388  * Spare slot should be used instead of this drive.
2389  * Check two cases: when spare slot was empty and when it wasn't.
2390  */
2391  sdev_id = dix_sdev_id(PG_UNIT_DATA);
2392  rc = dix_cctg_records_del(&index, &keys, sdev_id);
2393  M0_UT_ASSERT(rc == 0);
2395  rc = dix_ut_del(&index, &keys, &rep);
2396  M0_UT_ASSERT(rc == 0);
2397  M0_UT_ASSERT(rep.dra_nr == COUNT);
2398  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2400  dix_rep_free(&rep);
2401  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
2402  M0_UT_ASSERT(rc == 0);
2403  M0_UT_ASSERT(rep.dra_nr == COUNT);
2404  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2405  M0_UT_ASSERT(dix_cctg_has_replica(&index, &keys, &vals,
2407  dix_rep_free(&rep);
2408  rc = dix_ut_del(&index, &keys, &rep);
2409  M0_UT_ASSERT(rc == 0);
2410  M0_UT_ASSERT(rep.dra_nr == COUNT);
2411  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2413  dix_rep_free(&rep);
2414  dix_disk_online_set(sdev_id);
2415  dix_records_restore(&index, &keys, &vals);
2416 
2417  /*
2418  * Delete record when the drive with data unit is in re-balancing state.
2419  * Spare slot and re-balance target should both be updated.
2420  * Check two cases: when re-balance target was empty and when it wasn't.
2421  */
2422  sdev_id = dix_sdev_id(PG_UNIT_DATA);
2423  rc = dix_cctg_records_del(&index, &keys, sdev_id);
2424  M0_UT_ASSERT(rc == 0);
2427  rc = dix_ut_del(&index, &keys, &rep);
2428  M0_UT_ASSERT(rc == 0);
2429  M0_UT_ASSERT(rep.dra_nr == COUNT);
2430  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2432  dix_rep_free(&rep);
2433  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
2434  M0_UT_ASSERT(rc == 0);
2435  M0_UT_ASSERT(rep.dra_nr == COUNT);
2436  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2437  M0_UT_ASSERT(dix_cctg_has_replica(&index, &keys, &vals,
2439  dix_rep_free(&rep);
2440  rc = dix_ut_del(&index, &keys, &rep);
2441  M0_UT_ASSERT(rc == 0);
2442  M0_UT_ASSERT(rep.dra_nr == COUNT);
2443  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2445  dix_rep_free(&rep);
2446  dix_disk_online_set(sdev_id);
2447  dix_records_restore(&index, &keys, &vals);
2448 
2449  dix_kv_destroy(&keys, &vals);
2451  ut_service_fini();
2452 }
2453 
2454 static void dix_null_value(void)
2455 {
2456  struct m0_dix index;
2457  struct m0_bufvec keys;
2458  struct m0_bufvec vals;
2459  struct m0_bufvec start_key;
2460  uint32_t recs_nr = COUNT;
2461  struct dix_rep_arr rep;
2462  uint64_t key;
2463  int i;
2464  int rc;
2465 
2466  ut_service_init();
2467  dix_index_init(&index, 1);
2468  rc = m0_bufvec_alloc(&keys, COUNT, sizeof (uint64_t));
2469  M0_UT_ASSERT(rc == 0);
2470  rc = m0_bufvec_empty_alloc(&vals, COUNT);
2471  M0_UT_ASSERT(rc == 0);
2472  for (i = 0; i < keys.ov_vec.v_nr; i++)
2473  *(uint64_t *)keys.ov_buf[i] = dix_key(i);
2475  M0_UT_ASSERT(rc == 0);
2476  /* Put records with empty values. */
2477  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
2478  M0_UT_ASSERT(rc == 0);
2479  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2480  dix_rep_free(&rep);
2481  /* Get records using GET request. */
2482  rc = dix_ut_get(&index, &keys, &rep);
2483  M0_UT_ASSERT(rc == 0);
2484  for (i = 0; i < keys.ov_vec.v_nr; i++) {
2485  M0_UT_ASSERT(rep.dra_rep[i].dre_rc == 0);
2486  key = *(uint64_t *)rep.dra_rep[i].dre_key.b_addr;
2487  M0_UT_ASSERT(key == dix_key(i));
2488  M0_UT_ASSERT(rep.dra_rep[i].dre_val.b_nob == 0);
2489  M0_UT_ASSERT(rep.dra_rep[i].dre_val.b_addr == NULL);
2490  }
2491  dix_rep_free(&rep);
2492 
2493  /* Get records using NEXT request. */
2494  m0_bufvec_alloc(&start_key, 1, sizeof(uint64_t));
2495  *(uint64_t *)start_key.ov_buf[0] = dix_key(0);
2496  rc = dix_ut_next(&index, &start_key, &recs_nr, 0, &rep);
2497  M0_UT_ASSERT(rc == 0);
2498  for (i = 0; i < keys.ov_vec.v_nr; i++) {
2499  M0_UT_ASSERT(rep.dra_rep[i].dre_rc == 0);
2500  key = *(uint64_t *)rep.dra_rep[i].dre_key.b_addr;
2501  M0_UT_ASSERT(key == dix_key(i));
2502  M0_UT_ASSERT(rep.dra_rep[i].dre_val.b_nob == 0);
2503  M0_UT_ASSERT(rep.dra_rep[i].dre_val.b_addr == NULL);
2504  }
2505  dix_rep_free(&rep);
2506  m0_bufvec_free(&start_key);
2507 
2508  /* Delete records. */
2509  rc = dix_ut_del(&index, &keys, &rep);
2510  M0_UT_ASSERT(rc == 0);
2511  M0_UT_ASSERT(rep.dra_nr == COUNT);
2512  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2513  dix_rep_free(&rep);
2514 
2515  dix_kv_destroy(&keys, &vals);
2517  ut_service_fini();
2518 }
2519 
2520 static void local_failures(void)
2521 {
2522  struct m0_dix index;
2523  struct m0_bufvec keys;
2524  struct m0_bufvec vals;
2525  struct dix_rep_arr rep;
2526  int rc;
2527 
2528  ut_service_init();
2529  dix_index_init(&index, 1);
2530  dix_kv_alloc_and_fill(&keys, &vals, COUNT);
2532  M0_UT_ASSERT(rc == 0);
2533  /*
2534  * Consider DIX request to be successful if there is at least
2535  * one successful CAS request. Here two cas requests can be
2536  * sent successfully.
2537  */
2538  m0_fi_enable_off_n_on_m("cas_req_replied_cb", "send-failure", 2, 3);
2539  rc = dix_ut_put(&index, &keys, &vals, 0, &rep);
2540  m0_fi_disable("cas_req_replied_cb", "send-failure");
2541  M0_UT_ASSERT(rc == 0);
2542  M0_UT_ASSERT(rep.dra_nr == COUNT);
2543  M0_UT_ASSERT(m0_forall(i, COUNT, rep.dra_rep[i].dre_rc == 0));
2544  dix_rep_free(&rep);
2545  dix_kv_destroy(&keys, &vals);
2547  ut_service_fini();
2548 }
2549 
2550 enum {
2555 };
2556 
2557 static void keys_alloc(struct m0_bufvec *cas_reps,
2558  struct m0_bufvec *dix_reps)
2559 {
2560  int rc;
2561  int i;
2562  int j;
2563  struct m0_bufvec *reps;
2564  struct m0_cas_next_reply *crep;
2565  struct m0_dix_next_reply *drep;
2566 
2567  for (i = 0; i < cas_reps->ov_vec.v_nr; i++ ) {
2568  reps = cas_reps->ov_buf[i];
2569  for (j = 0; j < reps->ov_vec.v_nr; j++) {
2570  crep = (struct m0_cas_next_reply *)reps->ov_buf[j];
2571  M0_SET0(crep);
2572  rc = m0_buf_alloc(&crep->cnp_key, sizeof(uint64_t));
2573  M0_UT_ASSERT(rc == 0);
2574  rc = m0_buf_alloc(&crep->cnp_val, sizeof(uint64_t));
2575  M0_UT_ASSERT(rc == 0);
2576  }
2577  }
2578  for (i = 0; i < dix_reps->ov_vec.v_nr; i++ ) {
2579  reps = dix_reps->ov_buf[i];
2580  for (j = 0; j < reps->ov_vec.v_nr; j++) {
2581  drep = (struct m0_dix_next_reply *)reps->ov_buf[j];
2582  M0_SET0(drep);
2583  rc = m0_buf_alloc(&drep->dnr_key, sizeof(uint64_t));
2584  M0_UT_ASSERT(rc == 0);
2585  rc = m0_buf_alloc(&drep->dnr_val, sizeof(uint64_t));
2586  M0_UT_ASSERT(rc == 0);
2587  }
2588  }
2589 
2590 }
2591 
2592 static void crep_val_set(struct m0_bufvec *reps, uint32_t idx, uint64_t val)
2593 {
2594  struct m0_cas_next_reply *crep;
2595 
2596  crep = (struct m0_cas_next_reply *)reps->ov_buf[idx];
2597  *(uint64_t *)crep->cnp_key.b_addr = val;
2598  *(uint64_t *)crep->cnp_val.b_addr = *(uint64_t *)crep->cnp_key.b_addr;
2599 }
2600 
2601 static void drep_val_set(struct m0_bufvec *reps, uint32_t idx, uint64_t val)
2602 {
2603  struct m0_dix_next_reply *drep;
2604 
2605  drep = (struct m0_dix_next_reply *)reps->ov_buf[idx];
2606  *(uint64_t *)drep->dnr_key.b_addr = val;
2607  *(uint64_t *)drep->dnr_val.b_addr = *(uint64_t *)drep->dnr_key.b_addr;
2608 }
2609 
2610 /*
2611  * keys[] = {1, 4};
2612  * nrs[] = {4, 5};
2613  * arr1[] = {1, 3, 4, 7, 4, 7, 100};
2614  * arr2[] = {NO, 8, 101, 102};
2615  * arr3[] = {1, 2, 3, 5, 6, 7, 10, 101};
2616  * Result must be:
2617  * start key "1" (cnt 4): 1 2 3 4
2618  * start key "4" (cnt 5): 4 6 7 8 10
2619  */
2620 static int case_1_data(struct m0_bufvec *cas_reps,
2621  struct m0_bufvec *dix_reps,
2622  uint32_t **recs_nr,
2623  struct m0_bufvec *start_keys,
2624  uint32_t *ctx_nr)
2625 {
2626  int rc;
2627  uint32_t start_keys_nr = 2;
2628  struct m0_bufvec *reps;
2629 
2630  *ctx_nr = 3;
2631  /* Allocate array with start keys. */
2632  rc = m0_bufvec_alloc(start_keys, start_keys_nr, sizeof (uint64_t));
2633  M0_UT_ASSERT(rc == 0);
2634  /* Allocate recs_nr arrays. */
2635  M0_ALLOC_ARR(*recs_nr, start_keys_nr);
2636  M0_UT_ASSERT(*recs_nr != NULL);
2637  /*
2638  * Allocate cas_reply. There are three arrays with items - simulate
2639  * CAS service responses from three CAS services.
2640  */
2641  rc = m0_bufvec_alloc(cas_reps, *ctx_nr, sizeof (struct m0_bufvec));
2642  M0_UT_ASSERT(rc == 0);
2643  rc = m0_bufvec_alloc(cas_reps->ov_buf[0], 7,
2644  sizeof (struct m0_cas_next_reply));
2645  M0_UT_ASSERT(rc == 0);
2646  rc = m0_bufvec_alloc(cas_reps->ov_buf[1], 4,
2647  sizeof (struct m0_cas_next_reply));
2648  M0_UT_ASSERT(rc == 0);
2649  rc = m0_bufvec_alloc(cas_reps->ov_buf[2], 8,
2650  sizeof (struct m0_cas_next_reply));
2651  M0_UT_ASSERT(rc == 0);
2652  /* Allocate dix_reply - entities for results. */
2653  rc = m0_bufvec_alloc(dix_reps, start_keys_nr,
2654  sizeof (struct m0_bufvec));
2655  M0_UT_ASSERT(rc == 0);
2656  rc = m0_bufvec_alloc(dix_reps->ov_buf[0], 4,
2657  sizeof (struct m0_dix_next_reply));
2658  M0_UT_ASSERT(rc == 0);
2659  rc = m0_bufvec_alloc(dix_reps->ov_buf[1], 5,
2660  sizeof (struct m0_dix_next_reply));
2661  M0_UT_ASSERT(rc == 0);
2662  /* Allocate key and val in CAS and DIX reply. */
2663  keys_alloc(cas_reps, dix_reps);
2664  /* Put data into recs_nr. */
2665  (*recs_nr)[0] = 4;
2666  (*recs_nr)[1] = 5;
2667 
2668  /* Put data into start_keys. */
2669  *(uint64_t *)start_keys->ov_buf[0] = 1;
2670  *(uint64_t *)start_keys->ov_buf[1] = 4;
2671 
2672  /* Put data into CAS relpy. */
2673  reps = cas_reps->ov_buf[0];
2674  crep_val_set(reps, 0, 1);
2675  crep_val_set(reps, 1, 3);
2676  crep_val_set(reps, 2, 4);
2677  crep_val_set(reps, 3, 7);
2678  crep_val_set(reps, 4, 4);
2679  crep_val_set(reps, 5, 7);
2680  crep_val_set(reps, 6, 100);
2681 
2682  reps = cas_reps->ov_buf[1];
2683  ((struct m0_cas_next_reply *)reps->ov_buf[0])->cnp_rc = -ENOENT;
2684  crep_val_set(reps, 1, 8);
2685  crep_val_set(reps, 2, 101);
2686  crep_val_set(reps, 3, 102);
2687 
2688  reps = cas_reps->ov_buf[2];
2689  crep_val_set(reps, 0, 1);
2690  crep_val_set(reps, 1, 2);
2691  crep_val_set(reps, 2, 3);
2692  crep_val_set(reps, 3, 5);
2693  crep_val_set(reps, 4, 6);
2694  crep_val_set(reps, 5, 7);
2695  crep_val_set(reps, 6, 10);
2696  crep_val_set(reps, 7, 101);
2697 
2698  /* Put data into DIX relpy. */
2699  reps = dix_reps->ov_buf[0];
2700  drep_val_set(reps, 0, 1);
2701  drep_val_set(reps, 1, 2);
2702  drep_val_set(reps, 2, 3);
2703  drep_val_set(reps, 3, 4);
2704 
2705  reps = dix_reps->ov_buf[1];
2706  drep_val_set(reps, 0, 4);
2707  drep_val_set(reps, 1, 6);
2708  drep_val_set(reps, 2, 7);
2709  drep_val_set(reps, 3, 8);
2710  drep_val_set(reps, 4, 10);
2711  return 0;
2712 }
2713 
2714 /*
2715  * int keys[] = {1, 10};
2716  * int nrs[] = {3, 5};
2717  * int arr1[] = {1, 3, 4, 100, 110, 120, 130};
2718  * int arr2[] = {2, 3, 5, 10, 11, 200, 210, 400};
2719  * int arr3[] = {1, 2, 5, 6, 7, 10, 101, 200};
2720  * Result must be:
2721  * start key "1" (cnt 3) : 1 2 3
2722  * start key "10" (cnt 5): 6 7 10 11 100
2723  */
2724 static int case_2_data(struct m0_bufvec *cas_reps,
2725  struct m0_bufvec *dix_reps,
2726  uint32_t **recs_nr,
2727  struct m0_bufvec *start_keys,
2728  uint32_t *ctx_nr)
2729 {
2730  int rc;
2731  uint32_t start_keys_nr = 2;
2732  struct m0_bufvec *reps;
2733 
2734  *ctx_nr = 3;
2735  /* Allocate array with start keys. */
2736  rc = m0_bufvec_alloc(start_keys, start_keys_nr, sizeof (uint64_t));
2737  M0_UT_ASSERT(rc == 0);
2738  /* Allocate recs_nr arrays. */
2739  M0_ALLOC_ARR(*recs_nr, start_keys_nr);
2740  M0_UT_ASSERT(*recs_nr != NULL);
2741  /*
2742  * Allocate cas_reply. There are three arrays with items - simulate
2743  * CAS service responses from three CAS services.
2744  */
2745  rc = m0_bufvec_alloc(cas_reps, *ctx_nr, sizeof (struct m0_bufvec));
2746  M0_UT_ASSERT(rc == 0);
2747  rc = m0_bufvec_alloc(cas_reps->ov_buf[0], 7,
2748  sizeof (struct m0_cas_next_reply));
2749  M0_UT_ASSERT(rc == 0);
2750  rc = m0_bufvec_alloc(cas_reps->ov_buf[1], 8,
2751  sizeof (struct m0_cas_next_reply));
2752  M0_UT_ASSERT(rc == 0);
2753  rc = m0_bufvec_alloc(cas_reps->ov_buf[2], 8,
2754  sizeof (struct m0_cas_next_reply));
2755  M0_UT_ASSERT(rc == 0);
2756  /* Allocate dix_reply - entities for results. */
2757  rc = m0_bufvec_alloc(dix_reps, start_keys_nr,
2758  sizeof (struct m0_bufvec));
2759  M0_UT_ASSERT(rc == 0);
2760  rc = m0_bufvec_alloc(dix_reps->ov_buf[0], 3,
2761  sizeof (struct m0_dix_next_reply));
2762  M0_UT_ASSERT(rc == 0);
2763  rc = m0_bufvec_alloc(dix_reps->ov_buf[1], 5,
2764  sizeof (struct m0_dix_next_reply));
2765  M0_UT_ASSERT(rc == 0);
2766  /* Allocate key and val in CAS and DIX reply. */
2767  keys_alloc(cas_reps, dix_reps);
2768  /* Put data into recs_nr. */
2769  (*recs_nr)[0] = 3;
2770  (*recs_nr)[1] = 5;
2771 
2772  /* Put data into start_keys. */
2773  *(uint64_t *)start_keys->ov_buf[0] = 1;
2774  *(uint64_t *)start_keys->ov_buf[1] = 10;
2775 
2776  /* Put data into CAS relpy. */
2777  reps = cas_reps->ov_buf[0];
2778  crep_val_set(reps, 0, 1);
2779  crep_val_set(reps, 1, 3);
2780  crep_val_set(reps, 2, 4);
2781  crep_val_set(reps, 3, 100);
2782  crep_val_set(reps, 4, 110);
2783  crep_val_set(reps, 5, 120);
2784  crep_val_set(reps, 6, 130);
2785 
2786  reps = cas_reps->ov_buf[1];
2787  crep_val_set(reps, 0, 2);
2788  crep_val_set(reps, 1, 3);
2789  crep_val_set(reps, 2, 5);
2790  crep_val_set(reps, 3, 10);
2791  crep_val_set(reps, 4, 11);
2792  crep_val_set(reps, 5, 200);
2793  crep_val_set(reps, 6, 210);
2794  crep_val_set(reps, 7, 400);
2795 
2796  reps = cas_reps->ov_buf[2];
2797  crep_val_set(reps, 0, 1);
2798  crep_val_set(reps, 1, 2);
2799  crep_val_set(reps, 2, 5);
2800  crep_val_set(reps, 3, 6);
2801  crep_val_set(reps, 4, 7);
2802  crep_val_set(reps, 5, 10);
2803  crep_val_set(reps, 6, 101);
2804  crep_val_set(reps, 7, 200);
2805 
2806  /* Put data into DIX relpy. */
2807  reps = dix_reps->ov_buf[0];
2808  drep_val_set(reps, 0, 1);
2809  drep_val_set(reps, 1, 2);
2810  drep_val_set(reps, 2, 3);
2811 
2812  reps = dix_reps->ov_buf[1];
2813  drep_val_set(reps, 0, 6);
2814  drep_val_set(reps, 1, 7);
2815  drep_val_set(reps, 2, 10);
2816  drep_val_set(reps, 3, 11);
2817  drep_val_set(reps, 4, 100);
2818  return 0;
2819 }
2820 
2821 /*
2822  * int keys[] = {1, 7};
2823  * int nrs[] = {3, 5};
2824  * int arr1[] = {1, 3, 4, 100, 110, 120};
2825  * int arr2[] = {2, 3, 5, 110};
2826  * int arr3[] = {1, 2, 6, 7, 100};
2827  * Result must be:
2828  * start key "1" (cnt 3) : 1 2 3
2829  * start key "10" (cnt 5): 7 100 110 120
2830  */
2831 static int case_3_data(struct m0_bufvec *cas_reps,
2832  struct m0_bufvec *dix_reps,
2833  uint32_t **recs_nr,
2834  struct m0_bufvec *start_keys,
2835  uint32_t *ctx_nr)
2836 {
2837  int rc;
2838  uint32_t start_keys_nr = 2;
2839  struct m0_bufvec *reps;
2840 
2841  *ctx_nr = 3;
2842  /* Allocate array with start keys. */
2843  rc = m0_bufvec_alloc(start_keys, start_keys_nr, sizeof (uint64_t));
2844  M0_UT_ASSERT(rc == 0);
2845  /* Allocate recs_nr arrays. */
2846  M0_ALLOC_ARR(*recs_nr, start_keys_nr);
2847  M0_UT_ASSERT(*recs_nr != NULL);
2848  /*
2849  * Allocate cas_reply. There are three arrays with items - simulate
2850  * CAS service responses from three CAS services.
2851  */
2852  rc = m0_bufvec_alloc(cas_reps, *ctx_nr, sizeof (struct m0_bufvec));
2853  M0_UT_ASSERT(rc == 0);
2854  rc = m0_bufvec_alloc(cas_reps->ov_buf[0], 6,
2855  sizeof (struct m0_cas_next_reply));
2856  M0_UT_ASSERT(rc == 0);
2857  rc = m0_bufvec_alloc(cas_reps->ov_buf[1], 4,
2858  sizeof (struct m0_cas_next_reply));
2859  M0_UT_ASSERT(rc == 0);
2860  rc = m0_bufvec_alloc(cas_reps->ov_buf[2], 5,
2861  sizeof (struct m0_cas_next_reply));
2862  M0_UT_ASSERT(rc == 0);
2863  /* Allocate dix_reply - entities for results. */
2864  rc = m0_bufvec_alloc(dix_reps, start_keys_nr,
2865  sizeof (struct m0_bufvec));
2866  M0_UT_ASSERT(rc == 0);
2867  rc = m0_bufvec_alloc(dix_reps->ov_buf[0], 3,
2868  sizeof (struct m0_dix_next_reply));
2869  M0_UT_ASSERT(rc == 0);
2870  rc = m0_bufvec_alloc(dix_reps->ov_buf[1], 4,
2871  sizeof (struct m0_dix_next_reply));
2872  M0_UT_ASSERT(rc == 0);
2873  /* Allocate key and val in CAS and DIX reply. */
2874  keys_alloc(cas_reps, dix_reps);
2875  /* Put data into recs_nr. */
2876  (*recs_nr)[0] = 3;
2877  (*recs_nr)[1] = 5;
2878 
2879  /* Put data into start_keys. */
2880  *(uint64_t *)start_keys->ov_buf[0] = 1;
2881  *(uint64_t *)start_keys->ov_buf[1] = 7;
2882 
2883  /* Put data into CAS relpy. */
2884  reps = cas_reps->ov_buf[0];
2885  crep_val_set(reps, 0, 1);
2886  crep_val_set(reps, 1, 3);
2887  crep_val_set(reps, 2, 4);
2888  crep_val_set(reps, 3, 100);
2889  crep_val_set(reps, 4, 110);
2890  crep_val_set(reps, 5, 120);
2891 
2892  reps = cas_reps->ov_buf[1];
2893  crep_val_set(reps, 0, 2);
2894  crep_val_set(reps, 1, 3);
2895  crep_val_set(reps, 2, 5);
2896  crep_val_set(reps, 3, 110);
2897 
2898  reps = cas_reps->ov_buf[2];
2899  crep_val_set(reps, 0, 1);
2900  crep_val_set(reps, 1, 2);
2901  crep_val_set(reps, 2, 6);
2902  crep_val_set(reps, 3, 7);
2903  crep_val_set(reps, 4, 100);
2904 
2905  /* Put data into DIX relpy. */
2906  reps = dix_reps->ov_buf[0];
2907  drep_val_set(reps, 0, 1);
2908  drep_val_set(reps, 1, 2);
2909  drep_val_set(reps, 2, 3);
2910 
2911  reps = dix_reps->ov_buf[1];
2912  drep_val_set(reps, 0, 7);
2913  drep_val_set(reps, 1, 100);
2914  drep_val_set(reps, 2, 110);
2915  drep_val_set(reps, 3, 120);
2916  return 0;
2917 }
2918 
2919 /*
2920  * int keys[] = {1, 3, 5, 7, 9 };
2921  * int nrs[] = {2, 2, 2, 2, 2 };
2922  * int arr1[] = {1, 2, 3, 4, 5, 6, 7 ,8 ,9, 10};
2923  * int arr2[] = {1, 2, 3, 4, 5, 6, 7 ,8 ,9, 10};
2924  * int arr3[] = {1, 2, 3, 4, 5, 6, 7 ,8 ,9, 10};
2925  * Result must be:
2926  * 1 : 1 2
2927  * 3 : 3 4
2928  * 5 : 5 6
2929  * 7 : 7 8
2930  * 9 : 9 10
2931  */
2932 static int case_4_data(struct m0_bufvec *cas_reps,
2933  struct m0_bufvec *dix_reps,
2934  uint32_t **recs_nr,
2935  struct m0_bufvec *start_keys,
2936  uint32_t *ctx_nr)
2937 {
2938  int rc;
2939  int i;
2940  int j;
2941  uint32_t start_keys_nr = 5;
2942  struct m0_bufvec *reps;
2943 
2944  *ctx_nr = 3;
2945  /* Allocate array with start keys. */
2946  rc = m0_bufvec_alloc(start_keys, start_keys_nr, sizeof (uint64_t));
2947  M0_UT_ASSERT(rc == 0);
2948  /* Allocate recs_nr arrays. */
2949  M0_ALLOC_ARR(*recs_nr, start_keys_nr);
2950  M0_UT_ASSERT(*recs_nr != NULL);
2951  /*
2952  * Allocate cas_reply. There are three arrays with items - simulate
2953  * CAS service responses from three CAS services.
2954  */
2955  rc = m0_bufvec_alloc(cas_reps, *ctx_nr, sizeof (struct m0_bufvec));
2956  M0_UT_ASSERT(rc == 0);
2957  for (i = 0; i < *ctx_nr; i++) {
2958  rc = m0_bufvec_alloc(cas_reps->ov_buf[i], 10,
2959  sizeof (struct m0_cas_next_reply));
2960  M0_UT_ASSERT(rc == 0);
2961  }
2962  /* Allocate dix_reply - entities for results. */
2963  rc = m0_bufvec_alloc(dix_reps, start_keys_nr,
2964  sizeof (struct m0_bufvec));
2965  M0_UT_ASSERT(rc == 0);
2966  for (i = 0; i < start_keys_nr; i++) {
2967  rc = m0_bufvec_alloc(dix_reps->ov_buf[i], 2,
2968  sizeof (struct m0_dix_next_reply));
2969  M0_UT_ASSERT(rc == 0);
2970  }
2971  /* Allocate key and val in CAS and DIX reply. */
2972  keys_alloc(cas_reps, dix_reps);
2973  /* Put data into recs_nr. */
2974  for (i = 0; i < start_keys_nr; i++)
2975  (*recs_nr)[i] = 2;
2976 
2977  /* Put data into start_keys. */
2978  *(uint64_t *)start_keys->ov_buf[0] = 1;
2979  *(uint64_t *)start_keys->ov_buf[1] = 3;
2980  *(uint64_t *)start_keys->ov_buf[2] = 5;
2981  *(uint64_t *)start_keys->ov_buf[3] = 7;
2982  *(uint64_t *)start_keys->ov_buf[4] = 9;
2983 
2984  /* Put data into CAS relpy. */
2985  for (i = 0; i < *ctx_nr; i++) {
2986  reps = cas_reps->ov_buf[i];
2987  for (j = 0; j < 10; j++)
2988  crep_val_set(reps, j, j + 1);
2989  }
2990 
2991  /* Put data into DIX relpy. */
2992  reps = dix_reps->ov_buf[0];
2993  drep_val_set(reps, 0, 1);
2994  drep_val_set(reps, 1, 2);
2995 
2996  reps = dix_reps->ov_buf[1];
2997  drep_val_set(reps, 0, 3);
2998  drep_val_set(reps, 1, 4);
2999 
3000  reps = dix_reps->ov_buf[2];
3001  drep_val_set(reps, 0, 5);
3002  drep_val_set(reps, 1, 6);
3003 
3004  reps = dix_reps->ov_buf[3];
3005  drep_val_set(reps, 0, 7);
3006  drep_val_set(reps, 1, 8);
3007 
3008  reps = dix_reps->ov_buf[4];
3009  drep_val_set(reps, 0, 9);
3010  drep_val_set(reps, 1, 10);
3011  return 0;
3012 }
3013 
3014 static int dix_rep_cmp(struct m0_dix_next_reply *a, struct m0_dix_next_reply *b)
3015 {
3016  if (a == NULL && b == NULL)
3017  return 0;
3018  if (a == NULL)
3019  return -1;
3020  if (b == NULL)
3021  return 1;
3022  return memcmp(a->dnr_key.b_addr, b->dnr_key.b_addr,
3023  min64(a->dnr_key.b_nob, b->dnr_key.b_nob)) ?:
3024  M0_3WAY(a->dnr_key.b_nob, b->dnr_key.b_nob);
3025 }
3026 
3027 static void case_data_free(struct m0_bufvec *cas_reps,
3028  struct m0_bufvec *dix_reps,
3029  uint32_t *recs_nr,
3030  struct m0_bufvec *start_keys)
3031 {
3032  int i;
3033  int j;
3034  struct m0_bufvec *reps;
3035  struct m0_cas_next_reply *crep;
3036  struct m0_dix_next_reply *drep;
3037 
3038  m0_free(recs_nr);
3039  for (i = 0; i < cas_reps->ov_vec.v_nr; i++) {
3040  reps = cas_reps->ov_buf[i];
3041  for (j = 0; j < reps->ov_vec.v_nr; j++) {
3042  crep = (struct m0_cas_next_reply *)reps->ov_buf[j];
3043  m0_buf_free(&crep->cnp_key);
3044  m0_buf_free(&crep->cnp_val);
3045  }
3046  m0_bufvec_free(cas_reps->ov_buf[i]);
3047  }
3048  m0_bufvec_free(cas_reps);
3049  for (i = 0; i < dix_reps->ov_vec.v_nr; i++) {
3050  reps = dix_reps->ov_buf[i];
3051  for (j = 0; j < reps->ov_vec.v_nr; j++) {
3052  drep = (struct m0_dix_next_reply *)reps->ov_buf[j];
3053  m0_buf_free(&drep->dnr_key);
3054  m0_buf_free(&drep->dnr_val);
3055  }
3056  m0_bufvec_free(dix_reps->ov_buf[i]);
3057  }
3058  m0_bufvec_free(dix_reps);
3059  m0_bufvec_free(start_keys);
3060 }
3061 
3062 /* cas_reps - bufvec[ctx_nr] is an array of m0_cas_next_reply. */
3063 static int (*cases[]) (struct m0_bufvec *cas_reps,
3064  struct m0_bufvec *dix_reps,
3065  uint32_t **recs_nr,
3066  struct m0_bufvec *start_keys,
3067  uint32_t *ctx_nr) = {
3068  [CASE_1] = case_1_data,
3069  [CASE_2] = case_2_data,
3070  [CASE_3] = case_3_data,
3071  [CASE_4] = case_4_data,
3072 };
3073 
3074 void static results_check(struct m0_dix_req *req, struct m0_bufvec *dix_reps)
3075 {
3076  uint64_t key_idx;
3077  uint64_t val_idx;
3078  uint64_t rep_nr;
3079  struct m0_dix_next_reply *drep;
3080  struct m0_dix_next_reply rep;
3081  struct m0_bufvec *reps;
3082 
3083  for (key_idx = 0; key_idx < dix_reps->ov_vec.v_nr; key_idx++) {
3084  rep_nr = m0_dix_next_rep_nr(req, key_idx);
3085  reps = (struct m0_bufvec *)dix_reps->ov_buf[key_idx];
3086  for (val_idx = 0; val_idx < rep_nr; val_idx++) {
3087  drep = reps->ov_buf[val_idx];
3088  m0_dix_next_rep(req, key_idx, val_idx, &rep);
3089  M0_UT_ASSERT(dix_rep_cmp(drep, &rep) == 0);
3090  }
3091  }
3092 }
3093 
3094 void next_merge(void)
3095 {
3096  struct m0_dix_next_resultset *rs;
3097  struct m0_dix_req req;
3098  struct m0_bufvec cas_reps;
3099  struct m0_bufvec dix_reps;
3100  struct m0_bufvec start_keys;
3101  int rc;
3102  struct m0_dix_next_sort_ctx *ctx;
3103  uint32_t ctx_id;
3104  uint32_t key_id;
3105  uint32_t ctx_nr;
3106  uint32_t *recs_nr;
3107  uint32_t start_keys_nr;
3108  int it;
3109 
3110  m0_fi_enable("m0_dix_next_result_prepare", "mock_data_load");
3111  m0_fi_enable("sc_result_add", "mock_data_load");
3112  m0_fi_enable("m0_dix_rs_fini", "mock_data_load");
3113  for (it = 0; it < ARRAY_SIZE(cases); it++) {
3114  /* Create test data. */
3115  cases[it](&cas_reps, &dix_reps, &recs_nr,
3116  &start_keys, &ctx_nr);
3117  req.dr_recs_nr = recs_nr;
3118  start_keys_nr = req.dr_items_nr = start_keys.ov_vec.v_nr;
3119  rs = &req.dr_rs;
3120  rc = m0_dix_rs_init(rs, start_keys_nr, ctx_nr);
3121  M0_UT_ASSERT(rc == 0);
3122  for (ctx_id = 0; ctx_id < ctx_nr; ctx_id++) {
3123  struct m0_cas_next_reply *crep;
3124  struct m0_bufvec *creps;
3125 
3126  ctx = &rs->nrs_sctx_arr.sca_ctx[ctx_id];
3127  /* Array with cas reps for ctx_id. */
3128  creps = cas_reps.ov_buf[ctx_id];
3129  ctx->sc_reps_nr = creps->ov_vec.v_nr;
3130  M0_ALLOC_ARR(ctx->sc_reps, ctx->sc_reps_nr);
3131  for (key_id = 0; key_id < ctx->sc_reps_nr; key_id++) {
3132  crep = (struct m0_cas_next_reply *)
3133  creps->ov_buf[key_id];
3134  ctx->sc_reps[key_id] = *crep;
3135  }
3136  }
3138  M0_UT_ASSERT(rc == 0);
3139  /* Check results. */
3140  results_check(&req, &dix_reps);
3141  m0_dix_rs_fini(rs);
3142  case_data_free(&cas_reps, &dix_reps, recs_nr, &start_keys);
3143  }
3144  m0_fi_disable("m0_dix_next_result_prepare", "mock_data_load");
3145  m0_fi_disable("sc_result_add", "mock_data_load");
3146  m0_fi_disable("m0_dix_rs_fini", "mock_data_load");
3147 }
3148 
3149 static void server_is_down(void)
3150 {
3151  struct m0_dix index;
3152  int rc;
3153 
3154  ut_service_init();
3155  dix_index_init(&index, 1);
3156  m0_fi_enable("cas_sdev_state", "sdev_fail");
3158  m0_fi_disable("cas_sdev_state", "sdev_fail");
3159  M0_UT_ASSERT(rc == -EBADFD);
3161  ut_service_fini();
3162 }
3163 
3165  .ts_name = "dix-client-ut",
3166  .ts_tests = {
3167  { "imask", imask },
3168  { "imask-apply", imask_apply },
3169  { "imask-empty", imask_empty },
3170  { "imask-infini", imask_infini },
3171  { "imask-short", imask_short },
3172  { "imask-invalid", imask_invalid },
3173  { "pdclust-map", pdclust_map },
3174  { "meta-val-encdec", meta_val_encdec },
3175  { "meta-val-encdec-n", meta_val_encdec_n },
3176  { "layout-encdec", layout_encdec },
3177  { "meta-create", dix_meta_create },
3178  { "create", dix_create },
3179  { "create-crow", dix_create_crow },
3180  { "create-dgmode", dix_create_dgmode },
3181  { "delete", dix_delete },
3182  { "delete-crow", dix_delete_crow },
3183  { "delete-dgmode", dix_delete_dgmode },
3184  { "list", dix_list },
3185  { "put", dix_put },
3186  { "put-overwrite", dix_put_overwrite },
3187  { "put-crow", dix_put_crow },
3188  { "put-dgmode", dix_put_dgmode },
3189  { "get", dix_get },
3190  { "get-resend", dix_get_resend },
3191  { "get-dgmode", dix_get_dgmode },
3192  { "next", dix_next },
3193  { "next-crow", dix_next_crow },
3194  { "next-dgmode", dix_next_dgmode },
3195  { "del", dix_del },
3196  { "del-dgmode", dix_del_dgmode },
3197  { "null-value", dix_null_value },
3198  { "cctgs-lookup", dix_cctgs_lookup },
3199  { "local-failures", local_failures },
3200  { "next-merge", next_merge },
3201  { "server-is-down", server_is_down },
3202  { NULL, NULL }
3203  }
3204 };
3205 
3206 #undef M0_TRACE_SUBSYSTEM
3207 
3208 /*
3209  * Local variables:
3210  * c-indentation-style: "K&R"
3211  * c-basic-offset: 8
3212  * tab-width: 8
3213  * fill-column: 80
3214  * scroll-step: 1
3215  * End:
3216  */
3217 /*
3218  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
3219  */
static const char * srv_ep_addr
Definition: idx_dix.c:72
static void imask_invalid(void)
Definition: client_ut.c:298
uint32_t * cl_sdev_ids
Definition: client_ut.c:95
struct m0_poolmach_state * pm_state
Definition: pool_machine.h:169
uint64_t id
Definition: cob.h:2380
void meta_val_encdec_n(void)
Definition: client_ut.c:443
static m0_bindex_t indices[ZEROVEC_UT_SEGS_NR]
Definition: zerovec.c:38
#define DFID(x, y)
Definition: client_ut.c:135
#define SERVER_LOG_FILE_NAME
Definition: client_ut.c:110
static size_t nr
Definition: dump.c:1505
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
M0_INTERNAL void m0_pools_common_fini(struct m0_pools_common *pc)
Definition: pool.c:1549
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
static int dix_client_init(struct cl_ctx *cctx, const char *cl_ep_addr, const char *srv_ep_addr, const char *dbname, struct m0_net_xprt *xprt)
Definition: client_ut.c:1019
M0_INTERNAL void m0_dix_get_rep(const struct m0_dix_req *req, uint64_t idx, struct m0_dix_get_reply *rep)
Definition: req.c:2378
M0_INTERNAL void m0_pool_fini(struct m0_pool *pool)
Definition: pool.c:322
static char get_bit(void *buffer, m0_bcount_t pos)
Definition: client_ut.c:165
static void dix_create(void)
Definition: client_ut.c:1438
void m0_net_domain_fini(struct m0_net_domain *dom)
Definition: domain.c:71
struct m0_fid ld_pver
Definition: layout.h:324
static void server_is_down(void)
Definition: client_ut.c:3149
M0_INTERNAL int m0_poolmach_state_transit(struct m0_poolmach *pm, const struct m0_poolmach_event *event)
Definition: pool_machine.c:554
static void dix_create_dgmode(void)
Definition: client_ut.c:1473
struct m0_ut_suite dix_client_ut
Definition: client_ut.c:3164
m0_bindex_t e_end
Definition: ext.h:40
static int dix_ut_put(const struct m0_dix *index, const struct m0_bufvec *keys, struct m0_bufvec *vals, uint32_t flags, struct dix_rep_arr *rep)
Definition: client_ut.c:1387
int const char const void size_t int flags
Definition: dir.c:328
static void dix_get_resend(void)
Definition: client_ut.c:2089
static void dix_delete_crow(void)
Definition: client_ut.c:1533
M0_INTERNAL int m0_dix_meta_create(struct m0_dix_cli *cli, struct m0_sm_group *grp, struct m0_dix_ldesc *dld_layout, struct m0_dix_ldesc *dld_ldescr)
Definition: meta.c:326
#define NULL
Definition: misc.h:38
uint32_t pst_nr_devices
Definition: pool_machine.h:108
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
#define BYTES(bit)
Definition: client_ut.c:163
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
M0_INTERNAL int m0_dix_imask_init(struct m0_dix_imask *mask, struct m0_ext *range, uint64_t nr)
Definition: imask.c:97
Definition: idx_mock.c:52
struct m0_dix_next_sort_ctx_arr nrs_sctx_arr
Definition: req.h:168
struct m0_ext * im_range
Definition: imask.h:66
#define M0_3WAY(v0, v1)
Definition: arith.h:199
static struct m0_rpc_server_ctx dix_ut_sctx
Definition: client_ut.c:128
M0_INTERNAL int m0_layout_domain_init(struct m0_layout_domain *dom)
Definition: layout.c:610
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
void * b_addr
Definition: buf.h:39
M0_INTERNAL struct m0_pool_version * m0_pool_version_find(struct m0_pools_common *pc, const struct m0_fid *id)
Definition: pool.c:586
static FILE * f
Definition: adieu.c:79
static struct io_request req
Definition: file.c:100
uint32_t pa_N
Definition: pdclust.h:104
struct m0_conf_obj rt_obj
Definition: obj.h:372
static bool dix_cctg_has_replica(struct m0_dix *index, struct m0_bufvec *keys, struct m0_bufvec *vals, uint32_t sdev_idx)
Definition: client_ut.c:952
struct m0_poolmach pv_mach
Definition: pool.h:133
char ** rsx_argv
Definition: rpclib.h:77
m0_bindex_t e_start
Definition: ext.h:96
static enum m0_pool_nd_state dix_disk_state(uint32_t sdev_idx)
Definition: client_ut.c:730
static void dix_client_fini(struct cl_ctx *cctx)
Definition: client_ut.c:1102
int m0_rpc_server_start(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:50
#define M0_FID_INIT(container, key)
Definition: fid.h:84
struct m0_dix_linst dit_linst
Definition: layout.h:135
struct m0_dix_cli cl_cli
Definition: client_ut.c:90
M0_INTERNAL int m0_dix_next_result_prepare(struct m0_dix_req *req)
Definition: next_merge.c:252
uint32_t pa_K
Definition: pdclust.h:107
struct m0_vec ov_vec
Definition: vec.h:147
M0_INTERNAL int m0_dix_delete(struct m0_dix_req *req, const struct m0_dix *indices, uint64_t indices_nr, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:1190
M0_INTERNAL void m0_layout_domain_fini(struct m0_layout_domain *dom)
Definition: layout.c:633
M0_INTERNAL void m0_dix_meta_req_init(struct m0_dix_meta_req *req, struct m0_dix_cli *cli, struct m0_sm_group *grp)
Definition: meta.c:259
struct m0_pool_version pool_ver
Definition: fd.c:111
static int dix_cctg_records_del(struct m0_dix *index, struct m0_bufvec *keys, uint32_t sdev_idx)
Definition: client_ut.c:883
struct m0_dix_next_sort_ctx * sca_ctx
Definition: req.h:143
static void dix__kv_alloc_and_fill(struct m0_bufvec *keys, struct m0_bufvec *vals, uint32_t first, uint32_t last)
Definition: client_ut.c:645
M0_INTERNAL int m0_dix_index_list_rep_nr(struct m0_dix_meta_req *req)
Definition: meta.c:699
M0_INTERNAL void m0_cas_get_rep(const struct m0_cas_req *req, uint64_t idx, struct m0_cas_get_reply *rep)
Definition: client.c:1755
int dre_rc
Definition: client_ut.c:105
struct m0_rpc_client_ctx cl_rpc_ctx
Definition: client_ut.c:77
M0_INTERNAL int m0_dix_item_rc(const struct m0_dix_req *req, uint64_t idx)
Definition: req.c:2475
static void dix_next(void)
Definition: client_ut.c:2127
struct m0_dix_layout ci_layout
Definition: cas.h:120
M0_INTERNAL int m0_dix_imask_apply(void *buffer, m0_bcount_t buf_len_bytes, struct m0_dix_imask *mask, void **res, m0_bcount_t *res_len_bits)
Definition: imask.c:135
M0_INTERNAL int m0_dix_layout_iter_init(struct m0_dix_layout_iter *iter, const struct m0_fid *index, struct m0_layout_domain *ldom, struct m0_pool_version *pver, struct m0_dix_ldesc *ldesc, struct m0_buf *key)
Definition: layout.c:203
M0_INTERNAL void m0_rconfc_stop_sync(struct m0_rconfc *rconfc)
Definition: rconfc.c:2995
static void ut_service_fini(void)
Definition: client_ut.c:1216
static int ut_pver_find(struct m0_reqh *reqh, struct m0_fid *out)
Definition: client_ut.c:1152
M0_INTERNAL void m0_dix_target(struct m0_dix_linst *inst, uint64_t unit, struct m0_buf *key, uint64_t *out_id)
Definition: layout.c:144
static struct m0_rpc_client_ctx cctx
Definition: rconfc.c:69
static struct m0_be_emap_cursor it
Definition: extmap.c:46
static void dix_pm_disk_state_set(struct m0_poolmach *pm, uint32_t sdev_idx, enum m0_pool_nd_state state)
Definition: client_ut.c:704
static void dix_del(void)
Definition: client_ut.c:2297
static void dix_get_dgmode(void)
Definition: client_ut.c:2012
static void results_check(struct m0_dix_req *req, struct m0_bufvec *dix_reps)
Definition: client_ut.c:3074
#define M0_BITS(...)
Definition: misc.h:236
uint32_t pa_S
Definition: pdclust.h:110
uint64_t m0_bcount_t
Definition: types.h:77
static void dix_list(void)
Definition: client_ut.c:1641
struct m0_pool_version * dx_pver
Definition: client.h:190
#define M0_SRC_PATH(name)
Definition: misc.h:48
#define M0_SET0(obj)
Definition: misc.h:64
Definition: ut.h:77
M0_INTERNAL int m0_pools_setup(struct m0_pools_common *pc, const struct m0_fid *profile, struct m0_sm_group *sm_grp, struct m0_dtm *dtm)
Definition: pool.c:1810
static int case_4_data(struct m0_bufvec *cas_reps, struct m0_bufvec *dix_reps, uint32_t **recs_nr, struct m0_bufvec *start_keys, uint32_t *ctx_nr)
Definition: client_ut.c:2932
struct m0_fop_getxattr_rep * rep
Definition: dir.c:455
struct m0_pdclust_attr pl_attr
Definition: pdclust.h:150
static void dix_index_init(struct m0_dix *index, uint32_t id)
Definition: client_ut.c:611
M0_INTERNAL void m0_dix_rs_fini(struct m0_dix_next_resultset *rs)
Definition: next_merge.c:356
void ** ov_buf
Definition: vec.h:149
M0_INTERNAL int m0_cas_get(struct m0_cas_req *req, struct m0_cas_id *index, const struct m0_bufvec *keys)
Definition: client.c:1741
static struct m0_rpc_session * cctg_rpc_sess(uint32_t sdev_idx)
Definition: client_ut.c:873
static void imask_short(void)
Definition: client_ut.c:268
static void dix_delete_dgmode(void)
Definition: client_ut.c:1573
static void dixc_ut_init(struct m0_rpc_server_ctx *sctx, struct cl_ctx *cctx)
Definition: client_ut.c:1128
struct m0_buf dnr_val
Definition: req.h:280
static m0_bcount_t count
Definition: xcode.c:167
static const char * cl_ep_addrs[]
Definition: client_ut.c:124
static struct m0_pools_common pc
Definition: iter_ut.c:59
static const char * cl_ep_addr
Definition: pool_trigger.c:49
struct m0_buf cnp_val
Definition: client.h:223
M0_INTERNAL void m0_dix_layout_fini(struct m0_dix_linst *li)
Definition: layout.c:102
M0_INTERNAL void m0_cas_req_unlock(struct m0_cas_req *req)
Definition: client.c:229
M0_INTERNAL int m0_pool_init(struct m0_pool *pool, const struct m0_fid *id, enum m0_pver_policy_code pver_policy)
Definition: pool.c:307
M0_INTERNAL void m0_dix_layout_iter_fini(struct m0_dix_layout_iter *iter)
Definition: layout.c:315
M0_INTERNAL int m0_dix_ldesc_copy(struct m0_dix_ldesc *dst, const struct m0_dix_ldesc *src)
Definition: layout.c:189
M0_INTERNAL int m0_dix__layout_vals_dec(const struct m0_bufvec *keys, const struct m0_bufvec *vals, struct m0_fid *out_fid, struct m0_dix_layout *out_dlay, uint32_t nr)
Definition: encdec.c:157
static int dix_list_op(const struct m0_fid *start_fid, uint32_t indices_nr, struct m0_fid *out_fids, uint32_t *out_fids_nr)
Definition: client_ut.c:1611
M0_INTERNAL int m0_sm_timedwait(struct m0_sm *mach, uint64_t states, m0_time_t deadline)
Definition: sm.c:387
static int dix_common_idx_op(const struct m0_dix *indices, uint32_t indices_nr, enum ut_dix_req_type type)
Definition: client_ut.c:1271
struct m0_pooldev * pst_devices_array
Definition: pool_machine.h:111
struct m0_fid fid
Definition: di.c:46
M0_INTERNAL int m0_bufvec_alloc(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size)
Definition: vec.c:220
M0_INTERNAL void m0_cas_req_lock(struct m0_cas_req *req)
Definition: client.c:223
M0_INTERNAL int m0_confc_root_open(struct m0_confc *confc, struct m0_conf_root **root)
Definition: helpers.c:219
static int dix_ut_del(const struct m0_dix *index, const struct m0_bufvec *keys, struct dix_rep_arr *rep)
Definition: client_ut.c:1403
M0_INTERNAL uint64_t m0_dix_req_nr(const struct m0_dix_req *req)
Definition: req.c:2504
struct m0_sm ccr_sm
Definition: client.h:125
static void dix_disk_failure_set(uint32_t sdev_idx, enum m0_pool_nd_state state)
Definition: client_ut.c:756
Definition: buf.h:37
M0_INTERNAL void m0_bufvec_free(struct m0_bufvec *bufvec)
Definition: vec.c:395
struct m0_dix_imask ld_imask
Definition: layout.h:325
M0_INTERNAL struct m0_fid * m0_reqh2profile(struct m0_reqh *reqh)
Definition: reqh.c:758
static int dix_ut_next(const struct m0_dix *index, const struct m0_bufvec *start_keys, const uint32_t *recs_nr, uint32_t flags, struct dix_rep_arr *rep)
Definition: client_ut.c:1410
M0_INTERNAL void m0_dix_cli_unlock(struct m0_dix_cli *cli)
Definition: client.c:99
uint32_t dra_nr
Definition: client_ut.c:101
int i
Definition: dir.c:1033
M0_INTERNAL int m0_dix__ldesc_vals_enc(const uint64_t *lid, const struct m0_dix_ldesc *ldesc, uint32_t nr, struct m0_bufvec *keys, struct m0_bufvec *vals)
Definition: encdec.c:195
M0_INTERNAL int m0_dix__layout_vals_enc(const struct m0_fid *fid, const struct m0_dix_layout *dlay, uint32_t nr, struct m0_bufvec *keys, struct m0_bufvec *vals)
Definition: encdec.c:111
M0_INTERNAL int m0_dix_next(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *start_keys, const uint32_t *recs_nr, uint32_t flags)
Definition: req.c:2415
uint32_t ld_hash_fnc
Definition: layout.h:323
struct m0_conf_root * root
Definition: note.c:50
return M0_ERR(-EOPNOTSUPP)
static void dix_delete(void)
Definition: client_ut.c:1514
struct dix_rep * dra_rep
Definition: client_ut.c:100
M0_INTERNAL int m0_cas_req_generic_rc(const struct m0_cas_req *req)
Definition: client.c:457
static void keys_alloc(struct m0_bufvec *cas_reps, struct m0_bufvec *dix_reps)
Definition: client_ut.c:2557
static void layout_create(struct m0_layout_domain *domain, struct m0_pool_version *pver)
Definition: client_ut.c:345
M0_INTERNAL void m0_cas_req_init(struct m0_cas_req *req, struct m0_rpc_session *sess, struct m0_sm_group *grp)
Definition: client.c:195
static int key
Definition: locality.c:283
static void imask_infini(void)
Definition: client_ut.c:235
static int dix_common_rec_op(const struct m0_dix *index, const struct m0_bufvec *keys, struct m0_bufvec *vals, const uint32_t *recs_nr, uint32_t flags, struct dix_rep_arr *rep, enum ut_dix_req_type type)
Definition: client_ut.c:1277
M0_INTERNAL uint64_t m0_pool_version2layout_id(const struct m0_fid *pv_fid, uint64_t lid)
Definition: pool.c:1900
M0_INTERNAL struct m0_confc * m0_reqh2confc(struct m0_reqh *reqh)
Definition: reqh.c:753
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
struct m0_fid pv_id
Definition: pool.h:113
struct m0_fid rt_imeta_pver
Definition: obj.h:403
M0_INTERNAL void m0_cas_put_rep(struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1685
static const char * cdbnames[]
Definition: client_ut.c:123
Definition: cas.h:264
void imask_apply(void)
Definition: client_ut.c:175
M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
Definition: finject.c:485
struct m0_fd_tree pv_fd_tree
Definition: pool.h:139
#define M0_NET_XPRT_PREFIX_DEFAULT
Definition: net.h:98
#define ENABLE_DTM0
Definition: config.h:36
static void local_failures(void)
Definition: client_ut.c:2520
static void m0_fi_enable(const char *func, const char *tag)
Definition: finject.h:276
M0_INTERNAL int m0_reqh_conf_setup(struct m0_reqh *reqh, struct m0_confc_args *args)
Definition: reqh.c:729
struct m0_fid dd_fid
Definition: req.h:111
M0_INTERNAL void m0_dix_cli_lock(struct m0_dix_cli *cli)
Definition: client.c:93
void pdclust_map(void)
Definition: client_ut.c:354
m0_bcount_t b_nob
Definition: buf.h:38
static void dix_cctgs_lookup(void)
Definition: client_ut.c:1674
#define M0_ASSERT(cond)
uint64_t im_nr
Definition: imask.h:64
static struct m0_poolmach * dix_srv_poolmach(void)
Definition: client_ut.c:719
void meta_val_encdec(void)
Definition: client_ut.c:406
M0_INTERNAL int m0_dix_get(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys)
Definition: req.c:2357
static void dix_index_create_and_fill(const struct m0_dix *index, const struct m0_bufvec *keys, struct m0_bufvec *vals, uint32_t flags)
Definition: client_ut.c:1420
M0_INTERNAL void m0_dix_layout_iter_next(struct m0_dix_layout_iter *iter, uint64_t *tgt)
Definition: layout.c:249
M0_INTERNAL int m0_dix_cli_start_sync(struct m0_dix_cli *cli)
Definition: client.c:221
M0_INTERNAL void m0_pools_common_service_ctx_connect_sync(struct m0_pools_common *pc)
Definition: pool.c:1608
static uint64_t dix_key(uint32_t seq_num)
Definition: client_ut.c:576
struct m0_fid pver
Definition: idx_dix.c:74
m0_pool_nd_state
Definition: pool_machine.h:57
static void dix_disk_online_set(uint32_t sdev_idx)
Definition: client_ut.c:779
M0_INTERNAL int m0_dix_meta_item_rc(const struct m0_dix_meta_req *req, uint64_t idx)
Definition: meta.c:314
struct m0_buf dgr_val
Definition: req.h:269
struct m0_sm_group * cl_grp
Definition: client_ut.c:91
static void dix_create_crow(void)
Definition: client_ut.c:1455
struct m0_fd_cache_info ft_cache_info
Definition: fd.h:209
static int dix_rep_cmp(struct m0_dix_next_reply *a, struct m0_dix_next_reply *b)
Definition: client_ut.c:3014
M0_INTERNAL void m0_dix_req_lock(struct m0_dix_req *req)
Definition: req.c:184
struct m0_net_domain cl_ndom
Definition: client_ut.c:75
struct m0_reqh rc_reqh
Definition: setup.h:312
struct m0_buf dre_key
Definition: client_ut.c:106
M0_INTERNAL void m0_dix_req_init(struct m0_dix_req *req, struct m0_dix_cli *cli, struct m0_sm_group *grp)
Definition: req.c:228
M0_INTERNAL int m0_dix_req_wait(struct m0_dix_req *req, uint64_t states, m0_time_t to)
Definition: req.c:201
#define M0_BUF_INIT0
Definition: buf.h:71
int m0_net_xprt_nr(void)
Definition: net.c:168
M0_INTERNAL int m0_dix_ldesc_init(struct m0_dix_ldesc *ld, struct m0_ext *range, m0_bcount_t range_nr, enum m0_dix_hash_fnc_type htype, struct m0_fid *pver)
Definition: layout.c:171
struct m0_fid cl_pver
Definition: client_ut.c:92
static int case_1_data(struct m0_bufvec *cas_reps, struct m0_bufvec *dix_reps, uint32_t **recs_nr, struct m0_bufvec *start_keys, uint32_t *ctx_nr)
Definition: client_ut.c:2620
int m0_rpc_client_stop(struct m0_rpc_client_ctx *cctx)
Definition: rpclib.c:217
M0_INTERNAL void m0_dix_meta_unlock(struct m0_dix_meta_req *req)
Definition: meta.c:304
M0_INTERNAL int m0_cas_del(struct m0_cas_req *req, struct m0_cas_id *index, struct m0_bufvec *keys, struct m0_dtx *dtx, uint32_t flags)
Definition: client.c:1842
struct m0_net_xprt * m0_net_xprt_default_get(void)
Definition: net.c:151
M0_INTERNAL void m0_pools_service_ctx_destroy(struct m0_pools_common *pc)
Definition: pool.c:1617
static void dix_put_crow(void)
Definition: client_ut.c:1790
int m0_rpc_client_start(struct m0_rpc_client_ctx *cctx)
Definition: rpclib.c:160
struct m0_net_xprt ** rsx_xprts
Definition: rpclib.h:69
M0_INTERNAL int m0_buf_alloc(struct m0_buf *buf, size_t size)
Definition: buf.c:43
static int dix_ut_get(const struct m0_dix *index, const struct m0_bufvec *keys, struct dix_rep_arr *rep)
Definition: client_ut.c:1396
static void dix_del_dgmode(void)
Definition: client_ut.c:2347
static struct m0_rpc_server_ctx sctx
Definition: console.c:88
uint32_t rcx_recv_queue_min_length
Definition: rpclib.h:153
static int m0_rconfc_start_sync(struct m0_rconfc *rconfc)
Definition: rconfc.h:502
uint32_t pd_sdev_idx
Definition: pool.h:437
M0_INTERNAL int m0_layout_init_by_pver(struct m0_layout_domain *dom, struct m0_pool_version *pv, int *count)
Definition: layout_pver.c:118
static struct cl_ctx dix_ut_cctx
Definition: client_ut.c:127
uint64_t fci_nr
Definition: fd.h:188
Definition: reqh.h:94
M0_INTERNAL uint32_t m0_dix_liter_W(struct m0_dix_layout_iter *iter)
Definition: layout.c:265
struct m0_layout_domain rh_ldom
Definition: reqh.h:153
uint32_t dl_type
Definition: layout.h:100
uint32_t v_nr
Definition: vec.h:51
struct m0_sm_group * lo_grp
Definition: locality.h:67
M0_INTERNAL void m0_dix_req_fini_lock(struct m0_dix_req *req)
Definition: req.c:2577
static uint32_t dix_sdev_id(enum ut_pg_unit unit)
Definition: client_ut.c:835
struct m0_dix_imask ld_imask
Definition: layout.h:79
struct m0_fid ci_fid
Definition: cas.h:113
static void ut_service_init(void)
Definition: client_ut.c:1170
static int dix_common_idx_flagged_op(const struct m0_dix *indices, uint32_t indices_nr, enum ut_dix_req_type type, uint32_t flags)
Definition: client_ut.c:1231
M0_INTERNAL void m0_buf_free(struct m0_buf *buf)
Definition: buf.c:55
static void dix_null_value(void)
Definition: client_ut.c:2454
M0_INTERNAL int m0_dix__ldesc_vals_dec(const struct m0_bufvec *keys, const struct m0_bufvec *vals, uint64_t *out_lid, struct m0_dix_ldesc *out_ldesc, uint32_t nr)
Definition: encdec.c:234
m0_bcount_t * v_count
Definition: vec.h:53
static void dix_cctg_records_put(struct m0_dix *index, struct m0_bufvec *keys, struct m0_bufvec *vals, uint32_t sdev_idx)
Definition: client_ut.c:918
struct m0_pool_device_to_service * pc_dev2svc
Definition: pool.h:207
static struct m0_clink clink[RDWR_REQUEST_MAX]
static int case_2_data(struct m0_bufvec *cas_reps, struct m0_bufvec *dix_reps, uint32_t **recs_nr, struct m0_bufvec *start_keys, uint32_t *ctx_nr)
Definition: client_ut.c:2724
M0_INTERNAL int m0_fid_sscanf(const char *s, struct m0_fid *fid)
Definition: fid.c:227
struct m0_fid * rcx_fid
Definition: rpclib.h:161
static void dix_records_restore(struct m0_dix *index, struct m0_bufvec *keys, struct m0_bufvec *vals)
Definition: client_ut.c:2333
M0_INTERNAL int m0_dix_create(struct m0_dix_req *req, const struct m0_dix *indices, uint32_t indices_nr, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:990
union m0_dix_layout::@145 u
M0_INTERNAL int m0_dix_index_list(struct m0_dix_meta_req *req, const struct m0_fid *start_fid, uint32_t indices_nr)
Definition: meta.c:669
struct m0_net_domain * rcx_net_dom
Definition: rpclib.h:128
struct m0_fid ld_pver
Definition: layout.h:78
static void dix_predictable_index_init(struct m0_dix *index, uint32_t id)
Definition: client_ut.c:624
M0_INTERNAL int m0_buf_copy(struct m0_buf *dest, const struct m0_buf *src)
Definition: buf.c:104
M0_INTERNAL int m0_layout_standard_types_register(struct m0_layout_domain *dom)
Definition: layout.c:671
static struct fdmi_ctx ctx
Definition: main.c:80
M0_INTERNAL int m0_dix_index_list_rep(struct m0_dix_meta_req *req, uint32_t idx, struct m0_fid *fid)
Definition: meta.c:704
M0_INTERNAL int m0_dix_cli_init(struct m0_dix_cli *cli, struct m0_sm_group *sm_group, struct m0_pools_common *pc, struct m0_layout_domain *ldom, const struct m0_fid *pver)
Definition: client.c:130
void imask(void)
Definition: client_ut.c:141
static void dix_disk_state_set(uint32_t sdev_idx, enum m0_pool_nd_state state)
Definition: client_ut.c:745
ut_dix_req_type
Definition: client_ut.c:63
M0_INTERNAL void m0_rconfc_fini(struct m0_rconfc *rconfc)
Definition: rconfc.c:3009
static struct m0_pool pool
Definition: iter_ut.c:58
static void m0_fi_enable_off_n_on_m(const char *func, const char *tag, uint32_t n, uint32_t m)
Definition: finject.h:346
static int(* cases[])(struct m0_bufvec *cas_reps, struct m0_bufvec *dix_reps, uint32_t **recs_nr, struct m0_bufvec *start_keys, uint32_t *ctx_nr)
Definition: client_ut.c:3063
struct m0_reqh_service_ctx * pds_ctx
Definition: pool.h:74
void next_merge(void)
Definition: client_ut.c:3094
M0_INTERNAL void m0_dix_ldesc_fini(struct m0_dix_ldesc *ld)
Definition: layout.c:197
struct m0_dix_ldesc cl_dld1
Definition: client_ut.c:93
static void imask_empty(void)
Definition: client_ut.c:216
uint64_t rcx_max_rpcs_in_flight
Definition: rpclib.h:136
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
#define m0_forall(var, nr,...)
Definition: misc.h:112
void m0_clink_add_lock(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:255
M0_INTERNAL void m0_dix_meta_req_fini_lock(struct m0_dix_meta_req *req)
Definition: meta.c:291
const char * ts_name
Definition: ut.h:99
static void dix_index_fini(struct m0_dix *index)
Definition: client_ut.c:640
M0_INTERNAL void m0_dix_cli_bootstrap_lock(struct m0_dix_cli *cli)
Definition: client.c:245
static void dix_cctg_id_fill(struct m0_dix *index, uint32_t sdev_idx, struct m0_cas_id *cctg_id)
Definition: client_ut.c:859
static void dix_dgmode_disks_prep(enum ut_pg_unit unit1, enum m0_pool_nd_state state1, enum ut_pg_unit unit2, enum m0_pool_nd_state state2, struct m0_dix *index, struct m0_bufvec *keys, struct m0_bufvec *vals)
Definition: client_ut.c:1932
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
M0_INTERNAL void m0_cas_req_fini_lock(struct m0_cas_req *req)
Definition: client.c:295
struct m0_reqh reqh
Definition: rm_foms.c:48
M0_INTERNAL int m0_dix__meta_val_dec(const struct m0_bufvec *vals, struct m0_fid *out_fid, struct m0_dix_ldesc *out_dld, uint32_t nr)
Definition: encdec.c:74
M0_INTERNAL void m0_cas_del_rep(struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1873
static void crep_val_set(struct m0_bufvec *reps, uint32_t idx, uint64_t val)
Definition: client_ut.c:2592
int m0_net_domain_init(struct m0_net_domain *dom, const struct m0_net_xprt *xprt)
Definition: domain.c:36
#define M0_BUF_INIT_PTR(p)
Definition: buf.h:69
M0_INTERNAL int m0_pools_common_init(struct m0_pools_common *pc, struct m0_rpc_machine *rmach)
Definition: pool.c:1425
int rsx_xprts_nr
Definition: rpclib.h:71
M0_INTERNAL struct m0_locality * m0_locality0_get(void)
Definition: locality.c:169
static void dix_kv_destroy(struct m0_bufvec *keys, struct m0_bufvec *vals)
Definition: client_ut.c:671
struct m0_buf dre_val
Definition: client_ut.c:107
struct m0_reqh_context cc_reqh_ctx
Definition: setup.h:361
M0_INTERNAL void m0_layout_domain_cleanup(struct m0_layout_domain *dom)
Definition: layout.c:653
M0_INTERNAL uint64_t m0_cas_req_nr(const struct m0_cas_req *req)
Definition: client.c:1308
Definition: ext.h:37
Definition: fid.h:38
m0_bindex_t e_start
Definition: ext.h:39
static const char * ut_profile
Definition: client_ut.c:134
M0_INTERNAL int m0_dix_rs_init(struct m0_dix_next_resultset *rs, uint32_t start_keys_nr, uint32_t sctx_nr)
Definition: next_merge.c:342
static void dix_meta_create(void)
Definition: client_ut.c:1225
static void dix_get(void)
Definition: client_ut.c:1897
static uint64_t dix_val(uint32_t seq_num)
Definition: client_ut.c:581
#define M0_UT_CONF_PROCESS
Definition: misc.h:45
M0_INTERNAL int m0_dix_del(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:2388
M0_INTERNAL int m0_pools_service_ctx_create(struct m0_pools_common *pc)
Definition: pool.c:1535
static int64_t min64(int64_t a, int64_t b)
Definition: arith.h:46
struct m0_net_xprt ** m0_net_all_xprt_get(void)
Definition: net.c:161
ut_pg_unit
Definition: client_ut.c:73
M0_INTERNAL int m0_dix_meta_generic_rc(const struct m0_dix_meta_req *req)
Definition: meta.c:309
M0_INTERNAL int m0_cas_put(struct m0_cas_req *req, struct m0_cas_id *index, const struct m0_bufvec *keys, const struct m0_bufvec *values, struct m0_dtx *dtx, uint32_t flags)
Definition: client.c:1643
Definition: addb2.c:200
uint32_t pa_P
Definition: pdclust.h:115
static void dixc_ut_fini(struct m0_rpc_server_ctx *sctx, struct cl_ctx *cctx)
Definition: client_ut.c:1145
const char * rcx_remote_addr
Definition: rpclib.h:134
static void dix__vals_check(struct dix_rep_arr *rep, uint32_t start_key, uint32_t first_val, uint32_t last_val)
Definition: client_ut.c:586
M0_INTERNAL void m0_dix_imask_fini(struct m0_dix_imask *mask)
Definition: imask.c:118
uint32_t ld_hash_fnc
Definition: layout.h:77
static void dix_put_overwrite(void)
Definition: client_ut.c:1733
static void dix_rep_free(struct dix_rep_arr *rep)
Definition: client_ut.c:678
struct m0_pools_common * rh_pools
Definition: reqh.h:118
M0_INTERNAL void m0_dix_req_unlock(struct m0_dix_req *req)
Definition: req.c:190
M0_INTERNAL void m0_layout_standard_types_unregister(struct m0_layout_domain *dom)
Definition: layout.c:697
static void layout_check(struct m0_dix_linst *dli)
Definition: client_ut.c:321
static void drep_val_set(struct m0_bufvec *reps, uint32_t idx, uint64_t val)
Definition: client_ut.c:2601
static void m0_fi_enable_once(const char *func, const char *tag)
Definition: finject.h:301
const char * rcx_local_addr
Definition: rpclib.h:131
uint64_t * fci_info
Definition: fd.h:196
static char * dix_startup_cmd[]
Definition: client_ut.c:113
struct m0_pdclust_layout * li_pl
Definition: layout.h:115
M0_INTERNAL void m0_confc_close(struct m0_conf_obj *obj)
Definition: confc.c:921
struct m0_rconfc rh_rconfc
Definition: reqh.h:166
void m0_rpc_server_stop(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:85
struct m0_rpc_machine rcx_rpc_machine
Definition: rpclib.h:145
static void dix_predictable_sdev_ids_fill(struct m0_dix *index)
Definition: client_ut.c:799
static int case_3_data(struct m0_bufvec *cas_reps, struct m0_bufvec *dix_reps, uint32_t **recs_nr, struct m0_bufvec *start_keys, uint32_t *ctx_nr)
Definition: client_ut.c:2831
Definition: pool.h:80
static void dix_next_crow(void)
Definition: client_ut.c:2184
static bool dix_rec_is_deleted(struct m0_dix *index, struct m0_bufvec *keys)
Definition: client_ut.c:1007
Definition: finject.c:60
M0_INTERNAL void m0_dix_cli_fini_lock(struct m0_dix_cli *cli)
Definition: client.c:278
static void dix_records_erase(struct m0_dix *index, struct m0_bufvec *keys)
Definition: client_ut.c:998
Definition: nucleus.c:42
static void dix_vals_check(struct dix_rep_arr *rep, uint32_t count)
Definition: client_ut.c:606
#define out(...)
Definition: gen.c:41
int type
Definition: dir.c:1031
M0_INTERNAL int m0_pool_versions_setup(struct m0_pools_common *pc)
Definition: pool.c:1640
struct m0_net_xprt * xprt
Definition: module.c:61
uint32_t cl_sdev_ids_nr
Definition: client_ut.c:96
static void dix_put_dgmode(void)
Definition: client_ut.c:1817
static void dix_put(void)
Definition: client_ut.c:1710
M0_INTERNAL void m0_pool_versions_destroy(struct m0_pools_common *pc)
Definition: pool.c:1876
struct m0_rpc_link sc_rlink
Definition: reqh_service.h:759
struct m0_pools_common cl_pools_common
Definition: client_ut.c:88
struct m0_chan dmr_chan
Definition: meta.h:97
M0_INTERNAL void m0_dix_next_rep(const struct m0_dix_req *req, uint64_t key_idx, uint64_t val_idx, struct m0_dix_next_reply *rep)
Definition: req.c:2449
const char * ca_profile
Definition: helpers.h:34
struct m0_reqh rcx_reqh
Definition: rpclib.h:144
static void dix_kv_alloc_and_fill(struct m0_bufvec *keys, struct m0_bufvec *vals, uint32_t count)
Definition: client_ut.c:664
static struct m0_layout_domain domain
Definition: layout.c:49
void m0_free(void *data)
Definition: memory.c:146
static void dix_next_dgmode(void)
Definition: client_ut.c:2237
M0_INTERNAL uint32_t m0_dix_next_rep_nr(const struct m0_dix_req *req, uint64_t key_idx)
Definition: req.c:2468
static void dix_dgmode_disks_unprep(enum ut_pg_unit unit1, enum m0_pool_nd_state state1, enum ut_pg_unit unit2, enum m0_pool_nd_state state2, struct m0_dix *index, struct m0_bufvec *keys, struct m0_bufvec *vals)
Definition: client_ut.c:1973
struct m0_rpc_machine cl_rpc_machine
Definition: client_ut.c:89
Definition: cas.h:107
M0_INTERNAL int m0_dix_layout_init(struct m0_dix_linst *dli, struct m0_layout_domain *domain, const struct m0_fid *fid, uint64_t layout_id, struct m0_pool_version *pver, struct m0_dix_ldesc *dld)
Definition: layout.c:86
uint32_t sm_state
Definition: sm.h:307
struct m0_pdclust_attr pv_attr
Definition: pool.h:122
static void case_data_free(struct m0_bufvec *cas_reps, struct m0_bufvec *dix_reps, uint32_t *recs_nr, struct m0_bufvec *start_keys)
Definition: client_ut.c:3027
static struct m0_pooldev * dix_pm_disk_find(struct m0_poolmach *pm, uint32_t sdev_idx)
Definition: client_ut.c:691
M0_INTERNAL void m0_dix_cli_stop(struct m0_dix_cli *cli)
Definition: client.c:253
void layout_encdec(void)
Definition: client_ut.c:488
M0_INTERNAL void m0_dix_fid_convert_dix2cctg(const struct m0_fid *dix_fid, struct m0_fid *cctg_fid, uint32_t device_id)
Definition: fid_convert.c:54
int32_t rc
Definition: trigger_fop.h:47
int dgr_rc
Definition: req.h:267
M0_INTERNAL void m0_dix_meta_lock(struct m0_dix_meta_req *req)
Definition: meta.c:299
#define ARRAY_SIZE(a)
Definition: misc.h:45
uint32_t pd_index
Definition: pool.h:432
struct m0_fid g_process_fid
Definition: ut.c:689
struct m0_buf cnp_key
Definition: client.h:219
M0_INTERNAL int m0_dix_cctgs_lookup(struct m0_dix_req *req, const struct m0_dix *indices, uint32_t indices_nr)
Definition: req.c:1214
struct m0_layout_domain cl_ldom
Definition: client_ut.c:85
#define M0_UT_ASSERT(a)
Definition: ut.h:46
struct m0_motr rsx_motr_ctx
Definition: rpclib.h:84
M0_INTERNAL int m0_dix_put(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys, const struct m0_bufvec *vals, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:2326
M0_INTERNAL struct m0_pooldev * m0_dix_tgt2sdev(struct m0_dix_linst *linst, uint64_t tgt)
Definition: layout.c:76
static const char * srv_ep_addrs[]
Definition: client_ut.c:125
static struct m0_addb2_frame_header last
Definition: storage.c:93
M0_INTERNAL void m0_dix_fini(struct m0_dix *dix)
Definition: req.c:2603
M0_INTERNAL int m0_dix__meta_val_enc(const struct m0_fid *fid, const struct m0_dix_ldesc *dld, uint32_t nr, struct m0_bufvec *vals)
Definition: encdec.c:48
Definition: vec.h:145
Definition: req.h:110
M0_INTERNAL int m0_bufvec_empty_alloc(struct m0_bufvec *bufvec, uint32_t num_segs)
Definition: vec.c:213
struct m0_dix_ldesc cl_dld2
Definition: client_ut.c:94
Definition: idx_mock.c:47
M0_INTERNAL int m0_dix_generic_rc(const struct m0_dix_req *req)
Definition: req.c:2483
#define M0_IMPOSSIBLE(fmt,...)
struct m0_buf dnr_key
Definition: req.h:278
M0_INTERNAL void m0_pools_destroy(struct m0_pools_common *pc)
Definition: pool.c:1887