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 
29 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CAS
30 #include "lib/trace.h"
31 
32 #include "rpc/rpclib.h" /* m0_rpc_server_ctx */
33 #include "lib/finject.h"
34 #include "lib/memory.h"
35 #include "ut/misc.h" /* M0_UT_PATH */
36 #include "ut/ut.h"
37 #include "cas/client.h"
38 #include "cas/ctg_store.h" /* m0_ctg_recs_nr */
39 #include "lib/finject.h"
40 #include "dtm0/dtx.h" /* m0_dtm0_dtx */
41 #include "cas/cas.h" /* m0_crv */
42 
43 #define SERVER_LOG_FILE_NAME "cas_server.log"
44 #define IFID(x, y) M0_FID_TINIT('i', (x), (y))
45 
46 extern const struct m0_tl_descr ndoms_descr;
47 
48 enum {
53  COUNT = 24,
54  COUNT_TREE = 10,
57 };
58 
62 };
63 
64 M0_BASSERT(COUNT % 2 == 0);
65 
66 struct async_wait {
69  bool aw_done;
70 };
71 
72 /* Client context */
73 struct cl_ctx {
74  /* Client network domain.*/
76  /* Client rpc context.*/
79 };
80 
81 enum { MAX_RPCS_IN_FLIGHT = 10 };
82 /* Configures motr environment with given parameters. */
83 static char *cas_startup_cmd[] = {
84  "m0d", "-T", "linux",
85  "-D", "cs_sdb", "-S", "cs_stob",
86  "-A", "linuxstob:cs_addb_stob",
87  "-e", M0_NET_XPRT_PREFIX_DEFAULT":0@lo:12345:34:1",
88  "-H", "0@lo:12345:34:1",
89  "-w", "10", "-F",
90  "-f", M0_UT_CONF_PROCESS,
91  "-c", M0_SRC_PATH("cas/ut/conf.xc")
92 };
93 
94 static const char *cdbnames[] = { "cas1" };
95 static const char *cl_ep_addrs[] = { "0@lo:12345:34:2" };
96 static const char *srv_ep_addrs[] = { "0@lo:12345:34:1" };
97 
98 static struct cl_ctx casc_ut_cctx;
101  .rsx_argc = ARRAY_SIZE(cas_startup_cmd),
102  .rsx_log_file_name = SERVER_LOG_FILE_NAME
103 };
104 
105 static int bufvec_empty_alloc(struct m0_bufvec *bufvec,
106  uint32_t num_segs)
107 {
108  M0_UT_ASSERT(num_segs > 0);
109  bufvec->ov_buf = NULL;
110  bufvec->ov_vec.v_nr = num_segs;
111  M0_ALLOC_ARR(bufvec->ov_vec.v_count, num_segs);
112  M0_UT_ASSERT(bufvec->ov_vec.v_count != NULL);
113  M0_ALLOC_ARR(bufvec->ov_buf, num_segs);
114  M0_UT_ASSERT(bufvec->ov_buf != NULL);
115  return 0;
116 }
117 
118 static int bufvec_cmp(const struct m0_bufvec *left,
119  const struct m0_bufvec *right)
120 {
121  struct m0_bufvec_cursor rcur;
122  struct m0_bufvec_cursor lcur;
123  m0_bufvec_cursor_init(&lcur, left);
124  m0_bufvec_cursor_init(&rcur, right);
125  return m0_bufvec_cursor_cmp(&lcur, &rcur);
126 }
127 
128 
129 static void value_create(int size, int num, char *buf)
130 {
131  int j;
132 
133  if (size == sizeof(uint64_t))
134  *(uint64_t *)buf = num;
135  else {
136  M0_UT_ASSERT(size > num);
137  for (j = 1; j <= num + 1; j++)
138  *(char *)(buf + size - j) = 0xff & j;
139  memset(buf, 0, size - 1 - num);
140  }
141 }
142 
143 static void vals_create(int count, int size, struct m0_bufvec *vals)
144 {
145  int i;
146  int rc;
147 
148  M0_PRE(vals != NULL);
150  M0_UT_ASSERT(rc == 0);
151  for (i = 0; i < count; i++)
152  value_create(size, i, vals->ov_buf[i]);
153 }
154 
155 static void vals_mix_create(int count, int large_size,
156  struct m0_bufvec *vals)
157 {
158  int rc;
159  int i;
160 
161  rc = bufvec_empty_alloc(vals, count);
162  M0_UT_ASSERT(rc == 0);
163  M0_UT_ASSERT(vals->ov_vec.v_nr == count);
164  for (i = 0; i < count; i++) {
165  vals->ov_vec.v_count[i] = i % 2 ? large_size :
166  sizeof(uint64_t);
167  vals->ov_buf[i] = m0_alloc(vals->ov_vec.v_count[i]);
168  M0_UT_ASSERT(vals->ov_buf[i] != NULL);
169  value_create(vals->ov_vec.v_count[i], i, vals->ov_buf[i]);
170  }
171 }
172 
173 static int cas_client_init(struct cl_ctx *cctx, const char *cl_ep_addr,
174  const char *srv_ep_addr, const char* dbname,
175  struct m0_net_xprt *xprt)
176 {
177  int rc;
178  struct m0_rpc_client_ctx *cl_rpc_ctx;
179 
180  M0_PRE(cctx != NULL && cl_ep_addr != NULL && srv_ep_addr != NULL &&
181  dbname != NULL && xprt != NULL);
182 
183  rc = m0_net_domain_init(&cctx->cl_ndom, xprt);
184  M0_UT_ASSERT(rc == 0);
185 
186  m0_semaphore_init(&cctx->cl_wait.aw_cb_wait, 0);
187  cctx->cl_wait.aw_done = false;
188  cl_rpc_ctx = &cctx->cl_rpc_ctx;
189 
190  cl_rpc_ctx->rcx_net_dom = &cctx->cl_ndom;
191  cl_rpc_ctx->rcx_local_addr = cl_ep_addr;
192  cl_rpc_ctx->rcx_remote_addr = srv_ep_addr;
194  cl_rpc_ctx->rcx_fid = &g_process_fid;
195 
196  m0_fi_enable_once("m0_rpc_machine_init", "bulk_cutoff_4K");
197  rc = m0_rpc_client_start(cl_rpc_ctx);
198  M0_UT_ASSERT(rc == 0);
199 
200  return rc;
201 }
202 
203 static void cas_client_fini(struct cl_ctx *cctx)
204 {
205  int rc;
206 
207  rc = m0_rpc_client_stop(&cctx->cl_rpc_ctx);
208  M0_UT_ASSERT(rc == 0);
209  m0_net_domain_fini(&cctx->cl_ndom);
210  m0_semaphore_fini(&cctx->cl_wait.aw_cb_wait);
211 }
212 
213 static void casc_ut_init(struct m0_rpc_server_ctx *sctx,
214  struct cl_ctx *cctx)
215 {
216  int rc;
221  M0_UT_ASSERT(rc == 0);
223  srv_ep_addrs[0], cdbnames[0],
225  M0_UT_ASSERT(rc == 0);
226 }
227 
228 static void casc_ut_fini(struct m0_rpc_server_ctx *sctx,
229  struct cl_ctx *cctx)
230 {
234 }
235 
236 static bool casc_chan_cb(struct m0_clink *clink)
237 {
238  struct async_wait *aw = container_of(clink, struct async_wait,
239  aw_clink);
240  struct m0_sm *sm = container_of(clink->cl_chan, struct m0_sm,
241  sm_chan);
242 
243  if (sm->sm_state == CASREQ_FINAL) {
244  aw->aw_done = true;
246  }
247  return true;
248 }
249 
251  struct cl_ctx *cctx,
252  const struct m0_fid *ids,
253  uint64_t ids_nr,
254  m0_chan_cb_t cb,
255  struct m0_cas_rec_reply *rep,
256  uint32_t flags)
257 {
258  struct m0_cas_req req;
259  struct m0_cas_id *cids;
260  struct m0_chan *chan;
261  int rc;
262  uint64_t i;
263 
264  /* create cas ids by passed fids */
265  M0_ALLOC_ARR(cids, ids_nr);
266  if (cids == NULL)
267  return M0_ERR(-ENOMEM);
268  m0_forall(i, ids_nr, cids[i].ci_fid = ids[i], true);
269 
270  /* start operation */
271  M0_SET0(&req);
272  m0_cas_req_init(&req, &cctx->cl_rpc_ctx.rcx_session,
273  m0_locality0_get()->lo_grp);
274  chan = &req.ccr_sm.sm_chan;
275  M0_UT_ASSERT(chan != NULL);
276  m0_clink_init(&cctx->cl_wait.aw_clink, cb);
277  m0_clink_add_lock(chan, &cctx->cl_wait.aw_clink);
278 
280  if (op == IDX_CREATE)
281  rc = m0_cas_index_create(&req, cids, ids_nr, NULL);
282  else
283  rc = m0_cas_index_delete(&req, cids, ids_nr, NULL, flags);
284  /* wait results */
285  if (rc == 0) {
286  if (cb != NULL) {
288  m0_semaphore_timeddown(&cctx->cl_wait.aw_cb_wait,
289  m0_time_from_now(5, 0));
290  M0_UT_ASSERT(cctx->cl_wait.aw_done);
291  cctx->cl_wait.aw_done = false;
293  }
294  else
296  M0_TIME_NEVER);
298  if (rc == 0) {
299  M0_UT_ASSERT(m0_cas_req_nr(&req) == ids_nr);
300  for (i = 0; i < ids_nr; i++)
301  if (op == IDX_CREATE)
303  &rep[i]);
304  else
306  &rep[i]);
307  }
308  }
310  m0_clink_del_lock(&cctx->cl_wait.aw_clink);
312  m0_clink_fini(&cctx->cl_wait.aw_clink);
313  m0_free(cids);
314  return rc;
315 }
316 
317 static int ut_idx_create_async(struct cl_ctx *cctx,
318  const struct m0_fid *ids,
319  uint64_t ids_nr,
320  m0_chan_cb_t cb,
321  struct m0_cas_rec_reply *rep)
322 {
323  M0_UT_ASSERT(cb != NULL);
324  return ut_idx_crdel_wrp(IDX_CREATE, cctx, ids, ids_nr, cb, rep, 0);
325 }
326 
327 static int ut_idx_create(struct cl_ctx *cctx,
328  const struct m0_fid *ids,
329  uint64_t ids_nr,
330  struct m0_cas_rec_reply *rep)
331 {
332  return ut_idx_crdel_wrp(IDX_CREATE, cctx, ids, ids_nr, NULL, rep, 0);
333 }
334 
335 static int ut_lookup_idx(struct cl_ctx *cctx,
336  const struct m0_fid *ids,
337  uint64_t ids_nr,
338  struct m0_cas_rec_reply *rep)
339 {
340  struct m0_cas_req req;
341  struct m0_cas_id *cids;
342  struct m0_chan *chan;
343  int rc;
344  uint64_t i;
345 
346  /* create cas ids by passed fids */
347  M0_ALLOC_ARR(cids, ids_nr);
348  if (cids == NULL)
349  return M0_ERR(-ENOMEM);
350  m0_forall(i, ids_nr, cids[i].ci_fid = ids[i], true);
351 
352  /* start operation */
353  M0_SET0(&req);
354  m0_cas_req_init(&req, &cctx->cl_rpc_ctx.rcx_session,
355  m0_locality0_get()->lo_grp);
356  chan = &req.ccr_sm.sm_chan;
357  M0_UT_ASSERT(chan != NULL);
358  m0_clink_init(&cctx->cl_wait.aw_clink, NULL);
359  m0_clink_add_lock(chan, &cctx->cl_wait.aw_clink);
360 
362  rc = m0_cas_index_lookup(&req, cids, ids_nr);
363  if (rc == 0) {
364  /* wait results */
367  if (rc == 0)
368  for (i = 0; i < ids_nr; i++)
370  }
372  m0_clink_del_lock(&cctx->cl_wait.aw_clink);
374  m0_clink_fini(&cctx->cl_wait.aw_clink);
375  m0_free(cids);
376  return rc;
377 }
378 
379 static int ut_idx_flagged_delete(struct cl_ctx *cctx,
380  const struct m0_fid *ids,
381  uint64_t ids_nr,
382  struct m0_cas_rec_reply *rep,
383  uint32_t flags)
384 {
385  return ut_idx_crdel_wrp(IDX_DELETE, cctx, ids, ids_nr, NULL,
386  rep, flags);
387 }
388 
389 static int ut_idx_delete(struct cl_ctx *cctx,
390  const struct m0_fid *ids,
391  uint64_t ids_nr,
392  struct m0_cas_rec_reply *rep)
393 {
394  return ut_idx_flagged_delete(cctx, ids, ids_nr, rep, 0);
395 }
396 
397 static int ut_idx_list(struct cl_ctx *cctx,
398  const struct m0_fid *start_fid,
399  uint64_t ids_nr,
400  uint64_t *rep_count,
401  struct m0_cas_ilist_reply *rep)
402 {
403  struct m0_cas_req req;
404  struct m0_chan *chan;
405  int rc;
406  uint64_t i;
407 
408  /* start operation */
409  M0_SET0(&req);
410  m0_cas_req_init(&req, &cctx->cl_rpc_ctx.rcx_session,
411  m0_locality0_get()->lo_grp);
412  chan = &req.ccr_sm.sm_chan;
413  M0_UT_ASSERT(chan != NULL);
414  m0_clink_init(&cctx->cl_wait.aw_clink, NULL);
415  m0_clink_add_lock(chan, &cctx->cl_wait.aw_clink);
416 
418  rc = m0_cas_index_list(&req, start_fid, ids_nr, 0);
419  if (rc == 0) {
420  /* wait results */
423  if (rc == 0) {
424  *rep_count = m0_cas_req_nr(&req);
425  for (i = 0; i < *rep_count; i++)
427  }
428  }
430  m0_clink_del_lock(&cctx->cl_wait.aw_clink);
432  m0_clink_fini(&cctx->cl_wait.aw_clink);
433  return rc;
434 }
435 
436 static void ut_dtx_init(struct m0_dtx **out, uint64_t version)
437 {
438  struct m0_dtm0_dtx *dtx0;
439  int rc;
440 
441  /* No version => no DTX */
442  if (version == 0) {
443  *out = NULL;
444  return;
445  }
446 
447  M0_ALLOC_PTR(dtx0);
448  M0_UT_ASSERT(dtx0 != NULL);
449 
450  rc = m0_dtm0_tx_desc_init(&dtx0->dd_txd, 1);
451  M0_UT_ASSERT(rc == 0);
452  dtx0->dd_txd.dtd_id = (struct m0_dtm0_tid) {
454  .dti_fid = g_process_fid,
455  };
456 
457  dtx0->dd_ancient_dtx.tx_dtx = dtx0;
458 
459  *out = &dtx0->dd_ancient_dtx;
460 }
461 
462 static void ut_dtx_fini(struct m0_dtx *dtx)
463 {
464  if (dtx != NULL)
465  m0_free(dtx->tx_dtx);
466 }
467 
468 static int ut_rec_common_put(struct cl_ctx *cctx,
469  struct m0_cas_id *index,
470  const struct m0_bufvec *keys,
471  const struct m0_bufvec *values,
472  struct m0_dtx *dtx,
473  struct m0_cas_rec_reply *rep,
474  uint32_t flags)
475 {
476  struct m0_cas_req req;
477  struct m0_chan *chan;
478  int rc;
479  uint64_t i;
480 
481  M0_PRE(ergo(dtx != NULL,
482  (((flags & COF_VERSIONED) != 0) &&
483  keys->ov_vec.v_nr == 1)));
484 
485  /* start operation */
486  M0_SET0(&req);
487  m0_cas_req_init(&req, &cctx->cl_rpc_ctx.rcx_session,
488  m0_locality0_get()->lo_grp);
489  chan = &req.ccr_sm.sm_chan;
490  M0_UT_ASSERT(chan != NULL);
491  m0_clink_init(&cctx->cl_wait.aw_clink, NULL);
492  m0_clink_add_lock(chan, &cctx->cl_wait.aw_clink);
493 
495  rc = m0_cas_put(&req, index, keys, values, dtx, flags);
496  if (rc == 0) {
497  /* wait results */
500  if (rc == 0)
501  for (i = 0; i < keys->ov_vec.v_nr; i++)
502  m0_cas_put_rep(&req, i, &rep[i]);
503  }
505  m0_clink_del_lock(&cctx->cl_wait.aw_clink);
507  m0_clink_fini(&cctx->cl_wait.aw_clink);
508  return rc;
509 }
510 
511 /* Submits CAS requests separately one-by-one for each kv pair */
513  struct m0_cas_id *index,
514  const struct m0_bufvec *keys,
515  const struct m0_bufvec *values,
516  struct m0_dtx *dtx,
517  struct m0_cas_rec_reply *rep,
518  uint32_t flags)
519 {
520  struct m0_bufvec k;
521  struct m0_bufvec v;
522  m0_bcount_t i;
523  int rc = 0;
524 
525  for (i = 0; i < keys->ov_vec.v_nr; i++) {
526  k = M0_BUFVEC_INIT_BUF(&keys->ov_buf[i],
527  &keys->ov_vec.v_count[i]);
528  v = M0_BUFVEC_INIT_BUF(&values->ov_buf[i],
529  &values->ov_vec.v_count[i]);
530  rc |= ut_rec_common_put(cctx, index, &k, &v, dtx, rep + i,
531  flags);
532  if (rc != 0)
533  break;
534  }
535 
536  return rc;
537 }
538 
539 static int ut_rec_put(struct cl_ctx *cctx,
540  struct m0_cas_id *index,
541  const struct m0_bufvec *keys,
542  const struct m0_bufvec *values,
543  struct m0_cas_rec_reply *rep,
544  uint32_t flags)
545 {
546  return ((flags & COF_VERSIONED) != 0 ?
548  (cctx, index, keys, values, NULL, rep, flags);
549 }
550 
551 static void ut_get_rep_clear(struct m0_cas_get_reply *rep, uint32_t nr)
552 {
553  uint32_t i;
554 
555  for (i = 0; i < nr; i++)
556  m0_free(rep[i].cge_val.b_addr);
557 }
558 
559 static int ut_rec__get(struct cl_ctx *cctx,
560  struct m0_cas_id *index,
561  const struct m0_bufvec *keys,
562  struct m0_cas_get_reply *rep,
563  uint64_t flags)
564 {
565  struct m0_cas_req req;
566  struct m0_chan *chan;
567  int rc;
568  uint64_t i;
569 
570  /* start operation */
571  M0_SET0(&req);
572  m0_cas_req_init(&req, &cctx->cl_rpc_ctx.rcx_session,
573  m0_locality0_get()->lo_grp);
574  chan = &req.ccr_sm.sm_chan;
575  M0_UT_ASSERT(chan != NULL);
576  m0_clink_init(&cctx->cl_wait.aw_clink, NULL);
577  m0_clink_add_lock(chan, &cctx->cl_wait.aw_clink);
578 
580  rc = ((flags & COF_VERSIONED) != 0 ?
582  if (rc == 0) {
583  /* wait results */
586  if (rc == 0) {
588  for (i = 0; i < keys->ov_vec.v_nr; i++) {
589  m0_cas_get_rep(&req, i, &rep[i]);
590  /*
591  * Lock value in memory, because it will be
592  * deallocated after m0_cas_req_fini().
593  */
594  if (rep[i].cge_rc == 0)
596  }
597  }
598  }
600  m0_clink_del_lock(&cctx->cl_wait.aw_clink);
602  m0_clink_fini(&cctx->cl_wait.aw_clink);
603  return rc;
604 }
605 
606 static int ut_rec_get(struct cl_ctx *cctx,
607  struct m0_cas_id *index,
608  const struct m0_bufvec *keys,
609  struct m0_cas_get_reply *rep)
610 {
611  return ut_rec__get(cctx, index, keys, rep, 0);
612 }
613 
614 static void ut_next_rep_clear(struct m0_cas_next_reply *rep, uint64_t nr)
615 {
616  uint64_t i;
617 
618  for (i = 0; i < nr; i++) {
619  m0_free(rep[i].cnp_key.b_addr);
620  m0_free(rep[i].cnp_val.b_addr);
621  M0_SET0(&rep[i]);
622  }
623 }
624 
625 static int ut_next_rec(struct cl_ctx *cctx,
626  struct m0_cas_id *index,
627  struct m0_bufvec *start_keys,
628  uint32_t *recs_nr,
629  struct m0_cas_next_reply *rep,
630  uint64_t *count,
631  uint32_t flags)
632 {
633  struct m0_cas_req req;
634  struct m0_chan *chan;
635  int rc;
636  uint64_t i;
637 
638  /* start operation */
639  M0_SET0(&req);
640  m0_cas_req_init(&req, &cctx->cl_rpc_ctx.rcx_session,
641  m0_locality0_get()->lo_grp);
642  chan = &req.ccr_sm.sm_chan;
643  M0_UT_ASSERT(chan != NULL);
644  m0_clink_init(&cctx->cl_wait.aw_clink, NULL);
645  m0_clink_add_lock(chan, &cctx->cl_wait.aw_clink);
646 
648  rc = m0_cas_next(&req, index, start_keys, recs_nr, flags);
649  if (rc == 0) {
650  /* wait results */
653  if (rc == 0) {
654  *count = m0_cas_req_nr(&req);
655  for (i = 0; i < *count; i++) {
656  m0_cas_next_rep(&req, i, &rep[i]);
657  /*
658  * Lock key/value in memory, because they will
659  * be deallocated after m0_cas_req_fini().
660  */
661  if (rep[i].cnp_rc == 0)
663  }
664  }
665  }
667  m0_clink_del_lock(&cctx->cl_wait.aw_clink);
669  m0_clink_fini(&cctx->cl_wait.aw_clink);
670  return rc;
671 }
672 
673 static int ut_rec_common_del(struct cl_ctx *cctx,
674  struct m0_cas_id *index,
675  const struct m0_bufvec *keys,
676  struct m0_dtx *dtx,
677  struct m0_cas_rec_reply *rep,
678  uint64_t flags)
679 {
680  struct m0_cas_req req;
681  struct m0_chan *chan;
682  int rc;
683  uint64_t i;
684 
685  M0_PRE(ergo(dtx != NULL,
686  (((flags & COF_VERSIONED) != 0) &&
687  keys->ov_vec.v_nr == 1)));
688 
689  /* start operation */
690  M0_SET0(&req);
691  m0_cas_req_init(&req, &cctx->cl_rpc_ctx.rcx_session,
692  m0_locality0_get()->lo_grp);
693  chan = &req.ccr_sm.sm_chan;
694  M0_UT_ASSERT(chan != NULL);
695  m0_clink_init(&cctx->cl_wait.aw_clink, NULL);
696  m0_clink_add_lock(chan, &cctx->cl_wait.aw_clink);
697 
699  rc = m0_cas_del(&req, index, (struct m0_bufvec *) keys, dtx, flags);
700  if (rc == 0) {
701  /* wait results */
704  if (rc == 0) {
706  for (i = 0; i < keys->ov_vec.v_nr; i++)
707  m0_cas_del_rep(&req, i, rep);
708  }
709  }
711  m0_clink_del_lock(&cctx->cl_wait.aw_clink);
713  m0_clink_fini(&cctx->cl_wait.aw_clink);
714  return rc;
715 }
716 
717 /* Submits CAS requests separately one-by-one for each key. */
718 static int ut_rec_common_del_seq(struct cl_ctx *cctx,
719  struct m0_cas_id *index,
720  const struct m0_bufvec *keys,
721  struct m0_dtx *dtx,
722  struct m0_cas_rec_reply *rep,
723  uint64_t flags)
724 {
725  struct m0_bufvec k;
726  m0_bcount_t i;
727  int rc = 0;
728 
729  for (i = 0; i < keys->ov_vec.v_nr; i++) {
730  k = M0_BUFVEC_INIT_BUF(&keys->ov_buf[i],
731  &keys->ov_vec.v_count[i]);
732  rc |= ut_rec_common_del(cctx, index, &k, dtx, rep + i, flags);
733  if (rc != 0)
734  break;
735  }
736 
737  return rc;
738 }
739 
740 static int ut_rec_del(struct cl_ctx *cctx,
741  struct m0_cas_id *index,
742  const struct m0_bufvec *keys,
743  struct m0_cas_rec_reply *rep,
744  uint64_t flags)
745 {
746 
747  return ((flags & COF_VERSIONED) != 0 ?
749  (cctx, index, keys, NULL, rep, flags);
750 }
751 
752 static void idx_create(void)
753 {
754  struct m0_cas_rec_reply rep = { 0 };
755  const struct m0_fid ifid = IFID(2, 3);
756  const struct m0_fid ifid_fake = IFID(2, 4);
757  int rc;
758 
760 
761  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
762  M0_UT_ASSERT(rc == 0);
763  M0_UT_ASSERT(rep.crr_rc == 0);
764  rc = ut_lookup_idx(&casc_ut_cctx, &ifid, 1, &rep);
765  M0_UT_ASSERT(rc == 0);
766  M0_UT_ASSERT(rep.crr_rc == 0);
767  rc = ut_lookup_idx(&casc_ut_cctx, &ifid_fake, 1, &rep);
768  M0_UT_ASSERT(rc == 0);
769  M0_UT_ASSERT(rep.crr_rc == -ENOENT);
770 
772 }
773 
774 static void idx_create_fail(void)
775 {
776  struct m0_cas_rec_reply rep = { 0 };
777  const struct m0_fid ifid = IFID(2, 3);
778  int rc;
779 
781  m0_fi_enable_once("creq_op_alloc", "cas_alloc_fail");
782  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
783  M0_UT_ASSERT(rc == -ENOMEM);
784  rc = ut_lookup_idx(&casc_ut_cctx, &ifid, 1, &rep);
785  M0_UT_ASSERT(rc == 0);
786  M0_UT_ASSERT(rep.crr_rc == -ENOENT);
787  m0_fi_enable_once("ctg_kbuf_get", "cas_alloc_fail");
788  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
789  M0_UT_ASSERT(rc == 0);
790  M0_UT_ASSERT(rep.crr_rc == -ENOMEM);
791  rc = ut_lookup_idx(&casc_ut_cctx, &ifid, 1, &rep);
792  M0_UT_ASSERT(rc == 0);
793  M0_UT_ASSERT(rep.crr_rc == -ENOENT);
794  m0_fi_enable_once("creq_op_alloc", "cas_alloc_fail");
795  rc = ut_lookup_idx(&casc_ut_cctx, &ifid, 1, &rep);
796  M0_UT_ASSERT(rc == -ENOMEM);
797  m0_fi_enable_once("ctg_kbuf_get", "cas_alloc_fail");
798  rc = ut_lookup_idx(&casc_ut_cctx, &ifid, 1, &rep);
799  M0_UT_ASSERT(rc == 0);
800  M0_UT_ASSERT(rep.crr_rc == -ENOMEM);
802 }
803 
804 static void idx_create_a(void)
805 {
806  struct m0_cas_rec_reply rep = { 0 };
807  const struct m0_fid ifid = IFID(2, 3);
808  int rc;
809 
811 
813  M0_UT_ASSERT(rc == 0);
814  M0_UT_ASSERT(rep.crr_rc == 0);
815 
817 }
818 
819 static void idx_create_n(void)
820 {
821  struct m0_cas_rec_reply rep[COUNT];
822  struct m0_fid ifid[COUNT];
823  int rc;
824 
826 
827  M0_SET_ARR0(rep);
828  m0_forall(i, COUNT, ifid[i] = IFID(2, 3 + i), true);
829  /* create several indices */
831  M0_UT_ASSERT(rc == 0);
832  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
834  M0_UT_ASSERT(rc == 0);
835  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
836 
838 }
839 
840 static void idx_delete(void)
841 {
842  struct m0_cas_rec_reply rep = { 0 };
843  const struct m0_fid ifid = IFID(2, 3);
844  int rc;
845 
847 
848  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
849  M0_UT_ASSERT(rc == 0);
850  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
851  M0_UT_ASSERT(rc == 0);
852  rc = ut_lookup_idx(&casc_ut_cctx, &ifid, 1, &rep);
853  M0_UT_ASSERT(rc == 0);
854  M0_UT_ASSERT(rep.crr_rc == -ENOENT);
855 
857 }
858 
859 static void idx_delete_fail(void)
860 {
861  struct m0_cas_rec_reply rep = { 0 };
862  const struct m0_fid ifid = IFID(2, 3);
863  int rc;
864 
866 
867  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
868  M0_UT_ASSERT(rc == 0);
869  m0_fi_enable_once("creq_op_alloc", "cas_alloc_fail");
870  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
871  M0_UT_ASSERT(rc == -ENOMEM);
872  rc = ut_lookup_idx(&casc_ut_cctx, &ifid, 1, &rep);
873  M0_UT_ASSERT(rc == 0);
874  M0_UT_ASSERT(rep.crr_rc == 0);
875  m0_fi_enable_once("ctg_kbuf_get", "cas_alloc_fail");
876  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
877  M0_UT_ASSERT(rc == 0);
878  M0_UT_ASSERT(rep.crr_rc == -ENOMEM);
879  rc = ut_lookup_idx(&casc_ut_cctx, &ifid, 1, &rep);
880  M0_UT_ASSERT(rc == 0);
881  M0_UT_ASSERT(rep.crr_rc == 0);
882 
884 }
885 
886 static void idx_delete_non_exist(void)
887 {
888  struct m0_cas_rec_reply rep = {};
889  const struct m0_fid ifid = IFID(2, 3);
890  int rc;
891 
893 
894  /* Try to remove non-existent index. */
895  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
896  M0_UT_ASSERT(rc == 0);
897  M0_UT_ASSERT(rep.crr_rc == -ENOENT);
898 
899  /* Try to remove non-existent index with CROW flag. */
901  M0_UT_ASSERT(rc == 0);
902  M0_UT_ASSERT(rep.crr_rc == 0);
903 
905 }
906 
907 static void idx_delete_n(void)
908 {
909  struct m0_cas_rec_reply rep[COUNT];
910  struct m0_fid ifid[COUNT];
911  int rc;
912 
914 
915  M0_SET_ARR0(rep);
916  m0_forall(i, COUNT, ifid[i] = IFID(2, 3 + i), true);
917  /* create several indices*/
919  M0_UT_ASSERT(rc == 0);
920  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
922  M0_UT_ASSERT(rc == 0);
923  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
924 
926  M0_UT_ASSERT(rc == 0);
927  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
929  M0_UT_ASSERT(rc == 0);
930  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == -ENOENT));
931 
933 }
934 
935 static void idx_tree_insert(void)
936 {
938  struct m0_cas_rec_reply rec_rep[COUNT_TREE];
939  struct m0_fid ifid[COUNT_TREE];
940  struct m0_cas_id index = {};
941  struct m0_bufvec keys;
942  struct m0_bufvec values;
943  int rc;
944  int i;
945 
947 
948  /* initialize data */
949  M0_SET_ARR0(rep);
950  rc = m0_bufvec_alloc(&keys, COUNT_TREE, sizeof(uint64_t));
951  M0_UT_ASSERT(rc == 0);
952  rc = m0_bufvec_alloc(&values, COUNT_TREE, sizeof(uint64_t));
953  M0_UT_ASSERT(rc == 0);
955  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
956  m0_forall(i, COUNT_TREE, ifid[i] = IFID(2, 3 + i), true);
957  /* create several indices */
959  M0_UT_ASSERT(rc == 0);
960  M0_UT_ASSERT(m0_forall(i, COUNT_TREE, rec_rep[i].crr_rc == 0));
962  M0_UT_ASSERT(rc == 0);
963  M0_UT_ASSERT(m0_forall(i, COUNT_TREE, rec_rep[i].crr_rc == 0));
964 
965  /* insert several records into each index */
966  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
967  *(uint64_t*)values.ov_buf[i] = i * i,
968  true));
969  for (i = 0; i < COUNT_TREE; i++) {
970  index.ci_fid = ifid[i];
971  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values,
972  rec_rep, 0);
973  M0_UT_ASSERT(rc == 0);
974  }
975  /* get all data */
976  m0_forall(i, COUNT_TREE, *(uint64_t*)values.ov_buf[i] = 0, true);
977  for (i = 0; i < COUNT_TREE; i++) {
978  index.ci_fid = ifid[i];
979  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, rep);
980  M0_UT_ASSERT(rc == 0);
982  *(uint64_t*)rep[j].cge_val.b_addr == j * j));
984  }
985  m0_bufvec_free(&keys);
986  m0_bufvec_free(&values);
988 }
989 
990 static void idx_tree_delete(void)
991 {
993  struct m0_fid ifid[COUNT_TREE];
994  struct m0_cas_id index = {};
995  struct m0_bufvec keys;
996  struct m0_bufvec values;
997  int rc;
998  int i;
999 
1001 
1002  /* initialize data */
1003  M0_SET_ARR0(rep);
1004  rc = m0_bufvec_alloc(&keys, COUNT_TREE, sizeof(uint64_t));
1005  M0_UT_ASSERT(rc == 0);
1006  rc = m0_bufvec_alloc(&values, COUNT_TREE, sizeof(uint64_t));
1007  M0_UT_ASSERT(rc == 0);
1009  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
1010  m0_forall(i, COUNT_TREE, ifid[i] = IFID(2, 3 + i), true);
1011  /* create several indices */
1013  M0_UT_ASSERT(rc == 0);
1014  M0_UT_ASSERT(m0_forall(i, COUNT_TREE, rep[i].crr_rc == 0));
1016  M0_UT_ASSERT(rc == 0);
1017  M0_UT_ASSERT(m0_forall(i, COUNT_TREE, rep[i].crr_rc == 0));
1018 
1019  /* insert several records into each index */
1020  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
1021  *(uint64_t*)values.ov_buf[i] = i * i,
1022  true));
1023  for (i = 0; i < COUNT_TREE; i++) {
1024  index.ci_fid = ifid[i];
1025  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
1026  M0_UT_ASSERT(rc == 0);
1027  }
1028 
1029  /* delete all trees */
1031  M0_UT_ASSERT(rc == 0);
1032  M0_UT_ASSERT(m0_forall(i, COUNT_TREE, rep[i].crr_rc == 0));
1033 
1035  M0_UT_ASSERT(rc == 0);
1036  M0_UT_ASSERT(m0_forall(i, COUNT_TREE, rep[i].crr_rc == -ENOENT));
1037 
1038  m0_bufvec_free(&keys);
1039  m0_bufvec_free(&values);
1041 }
1042 
1043 static void idx_tree_delete_fail(void)
1044 {
1046  struct m0_cas_get_reply get_rep[COUNT_TREE];
1047  struct m0_fid ifid[COUNT_TREE];
1048  struct m0_cas_id index = {};
1049  struct m0_bufvec keys;
1050  struct m0_bufvec values;
1051  int rc;
1052  int i;
1053 
1055 
1056  /* initialize data */
1057  M0_SET_ARR0(rep);
1058  rc = m0_bufvec_alloc(&keys, COUNT_TREE, sizeof(uint64_t));
1059  M0_UT_ASSERT(rc == 0);
1060  rc = m0_bufvec_alloc(&values, COUNT_TREE, sizeof(uint64_t));
1061  M0_UT_ASSERT(rc == 0);
1063  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
1064  m0_forall(i, COUNT_TREE, ifid[i] = IFID(2, 3 + i), true);
1065  /* create several indices */
1067  M0_UT_ASSERT(rc == 0);
1068  M0_UT_ASSERT(m0_forall(i, COUNT_TREE, rep[i].crr_rc == 0));
1070  M0_UT_ASSERT(rc == 0);
1071  M0_UT_ASSERT(m0_forall(i, COUNT_TREE, rep[i].crr_rc == 0));
1072 
1073  /* insert several records into each index */
1074  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
1075  *(uint64_t*)values.ov_buf[i] = i * i,
1076  true));
1077  for (i = 0; i < COUNT_TREE; i++) {
1078  index.ci_fid = ifid[i];
1079  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
1080  M0_UT_ASSERT(rc == 0);
1081  }
1082 
1083  /* delete all trees */
1084  m0_fi_enable_once("creq_op_alloc", "cas_alloc_fail");
1086  M0_UT_ASSERT(rc == -ENOMEM);
1087 
1089  M0_UT_ASSERT(rc == 0);
1090  M0_UT_ASSERT(m0_forall(i, COUNT_TREE, rep[i].crr_rc == 0));
1091 
1092  /* get all data */
1093  m0_forall(i, COUNT_TREE, *(uint64_t*)values.ov_buf[i] = 0, true);
1094  for (i = 0; i < COUNT_TREE; i++) {
1095  index.ci_fid = ifid[i];
1096  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
1097  M0_UT_ASSERT(rc == 0);
1099  *(uint64_t*)get_rep[j].cge_val.b_addr == j * j));
1100  ut_get_rep_clear(get_rep, COUNT_TREE);
1101  }
1102 
1103  m0_bufvec_free(&keys);
1104  m0_bufvec_free(&values);
1106 }
1107 
1108 static void idx_list(void)
1109 {
1110  struct m0_cas_rec_reply rep[COUNT];
1111  struct m0_cas_ilist_reply rep_list[COUNT + COUNT_META_ENTRIES + 1];
1112  struct m0_fid ifid[COUNT];
1113  uint64_t rep_count;
1114  int rc;
1115  int i;
1116 
1118 
1119  M0_SET_ARR0(rep);
1120  m0_forall(i, COUNT, ifid[i] = IFID(2, 3 + i), true);
1121  /* Create several indices. */
1123  M0_UT_ASSERT(rc == 0);
1124  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
1125  /* Get list of indices from start. */
1126  rc = ut_idx_list(&casc_ut_cctx, &ifid[0], COUNT, &rep_count, rep_list);
1127  M0_UT_ASSERT(rc == 0);
1128  M0_UT_ASSERT(rep_count == COUNT);
1129  M0_UT_ASSERT(m0_forall(i, COUNT, m0_fid_eq(&rep_list[i].clr_fid,
1130  &ifid[i])));
1131  /* Get list of indices from another position. */
1133  &rep_count, rep_list);
1134  M0_UT_ASSERT(rc == 0);
1135  M0_UT_ASSERT(rep_count >= COUNT / 2 + 1); /* 1 for -ENOENT record */
1137  rep_list[i].clr_rc == 0 &&
1138  m0_fid_eq(&rep_list[i].clr_fid,
1139  &ifid[i + COUNT / 2])));
1140  M0_UT_ASSERT(rep_list[COUNT / 2].clr_rc == -ENOENT);
1146  &rep_count, rep_list);
1147  M0_UT_ASSERT(rc == 0);
1148  M0_UT_ASSERT(rep_count >= 2);
1149  M0_UT_ASSERT(m0_fid_eq(&rep_list[0].clr_fid, &ifid[COUNT - 1]));
1150  M0_UT_ASSERT(rep_list[1].clr_rc == -ENOENT);
1151 
1152  /* Get list of indices from start (provide m0_cas_meta_fid). */
1154  /* meta, catalogue-index, dead-index and -ENOENT */
1155  COUNT + COUNT_META_ENTRIES + 1,
1156  &rep_count, rep_list);
1157  M0_UT_ASSERT(rc == 0);
1158  M0_UT_ASSERT(rep_count == COUNT + COUNT_META_ENTRIES + 1);
1159  M0_UT_ASSERT(m0_fid_eq(&rep_list[0].clr_fid, &m0_cas_meta_fid));
1160  M0_UT_ASSERT(m0_fid_eq(&rep_list[1].clr_fid, &m0_cas_ctidx_fid));
1161  M0_UT_ASSERT(m0_fid_eq(&rep_list[2].clr_fid, &m0_cas_dead_index_fid));
1163  M0_UT_ASSERT(m0_fid_eq(&rep_list[i].clr_fid,
1165  M0_UT_ASSERT(rep_list[COUNT + COUNT_META_ENTRIES].clr_rc == -ENOENT);
1166 
1167  /* Delete all indices. */
1169  M0_UT_ASSERT(rc == 0);
1170  M0_UT_ASSERT(m0_forall(j, COUNT, rep[j].crr_rc == 0));
1171  /* Get list - should be empty. */
1172  rc = ut_idx_list(&casc_ut_cctx, &ifid[0], COUNT, &rep_count, rep_list);
1173  M0_UT_ASSERT(rc == 0);
1174  M0_UT_ASSERT(rep_count >= 1);
1175  M0_UT_ASSERT(rep_list[0].clr_rc == -ENOENT);
1176 
1178 }
1179 
1180 static void idx_list_fail(void)
1181 {
1182  struct m0_cas_rec_reply rep[COUNT];
1183  struct m0_cas_ilist_reply rep_list[COUNT];
1184  struct m0_fid ifid[COUNT];
1185  uint64_t rep_count;
1186  int rc;
1187 
1189 
1190  M0_SET_ARR0(rep);
1191  m0_forall(i, COUNT, ifid[i] = IFID(2, 3 + i), true);
1192  /* create several indices */
1194  M0_UT_ASSERT(rc == 0);
1195  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
1196  /* get list of indices from start */
1197  rc = ut_idx_list(&casc_ut_cctx, &ifid[0], COUNT, &rep_count, rep_list);
1198  M0_UT_ASSERT(rc == 0);
1199  M0_UT_ASSERT(rep_count == COUNT);
1200  M0_UT_ASSERT(m0_forall(i, COUNT, m0_fid_eq(&rep_list[i].clr_fid,
1201  &ifid[i])));
1202  /* get failed cases for list */
1203  m0_fi_enable_once("creq_op_alloc", "cas_alloc_fail");
1204  rc = ut_idx_list(&casc_ut_cctx, &ifid[0], COUNT, &rep_count, rep_list);
1205  M0_UT_ASSERT(rc == -ENOMEM);
1206  m0_fi_enable_once("ctg_kbuf_get", "cas_alloc_fail");
1207  rc = ut_idx_list(&casc_ut_cctx, &ifid[0], COUNT, &rep_count, rep_list);
1208  M0_UT_ASSERT(rc == 0);
1209  M0_UT_ASSERT(rep_count == COUNT);
1210  M0_UT_ASSERT(m0_forall(i, COUNT, i == 0 ?
1211  rep_list[i].clr_rc == -ENOMEM :
1212  rep_list[i].clr_rc == -EPROTO));
1213 
1215 }
1216 
1217 static bool next_rep_equals(const struct m0_cas_next_reply *rep,
1218  void *key,
1219  void *val)
1220 {
1221  return memcmp(rep->cnp_key.b_addr, key, rep->cnp_key.b_nob) == 0 &&
1222  memcmp(rep->cnp_val.b_addr, val, rep->cnp_val.b_nob) == 0;
1223 }
1224 
1225 static void next_common(struct m0_bufvec *keys,
1226  struct m0_bufvec *values,
1227  uint32_t flags)
1228 {
1229  struct m0_cas_rec_reply rep[COUNT];
1230  struct m0_cas_next_reply next_rep[COUNT];
1231  const struct m0_fid ifid = IFID(2, 3);
1232  struct m0_cas_id index = {};
1233  struct m0_bufvec start_key;
1234  bool slant;
1235  bool exclude_start_key;
1236  uint32_t recs_nr;
1237  uint64_t rep_count;
1238  int rc;
1239 
1240  slant = flags & COF_SLANT;
1241  exclude_start_key = flags & COF_EXCLUDE_START_KEY;
1242 
1243  M0_SET_ARR0(rep);
1244  M0_SET_ARR0(next_rep);
1245  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
1246  M0_UT_ASSERT(rc == 0);
1247  index.ci_fid = ifid;
1248  rc = ut_rec_put(&casc_ut_cctx, &index, keys, values, rep, 0);
1249  M0_UT_ASSERT(rc == 0);
1250  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
1251  rc = m0_bufvec_alloc(&start_key, 1, keys->ov_vec.v_count[0]);
1252  M0_UT_ASSERT(rc == 0);
1253 
1254  /* perform next for all records */
1255  recs_nr = COUNT;
1256  value_create(start_key.ov_vec.v_count[0], 0, start_key.ov_buf[0]);
1257  rc = ut_next_rec(&casc_ut_cctx, &index, &start_key, &recs_nr, next_rep,
1258  &rep_count, flags);
1259  M0_UT_ASSERT(rc == 0);
1260  M0_UT_ASSERT(rep_count == recs_nr);
1261  M0_UT_ASSERT(m0_forall(i, rep_count, next_rep[i].cnp_rc == 0));
1262  if (!exclude_start_key || slant)
1263  M0_UT_ASSERT(m0_forall(i, rep_count,
1264  next_rep_equals(&next_rep[i],
1265  keys->ov_buf[i],
1266  values->ov_buf[i])));
1267  else
1268  M0_UT_ASSERT(m0_forall(i, rep_count,
1269  next_rep_equals(&next_rep[i],
1270  keys->ov_buf[i + 1],
1271  values->ov_buf[i + 1])));
1272  ut_next_rep_clear(next_rep, rep_count);
1273 
1274  /* perform next for small rep */
1275  recs_nr = COUNT / 2;
1276  rc = ut_next_rec(&casc_ut_cctx, &index, &start_key, &recs_nr, next_rep,
1277  &rep_count, flags);
1278  M0_UT_ASSERT(rc == 0);
1279  M0_UT_ASSERT(rep_count == COUNT / 2);
1280  M0_UT_ASSERT(m0_forall(i, rep_count, next_rep[i].cnp_rc == 0));
1281  if (!exclude_start_key || slant)
1282  M0_UT_ASSERT(m0_forall(i, rep_count,
1283  next_rep_equals(&next_rep[i],
1284  keys->ov_buf[i],
1285  values->ov_buf[i])));
1286  else
1287  M0_UT_ASSERT(m0_forall(i, rep_count,
1288  next_rep_equals(&next_rep[i],
1289  keys->ov_buf[i + 1],
1290  values->ov_buf[i + 1])));
1291  ut_next_rep_clear(next_rep, rep_count);
1292 
1293  /* perform next for half records */
1294  value_create(start_key.ov_vec.v_count[0],
1295  !slant ? COUNT / 2 : COUNT / 2 + 1,
1296  start_key.ov_buf[0]);
1297  recs_nr = COUNT;
1298  rc = ut_next_rec(&casc_ut_cctx, &index, &start_key, &recs_nr, next_rep,
1299  &rep_count, flags);
1300  M0_UT_ASSERT(rc == 0);
1301  M0_UT_ASSERT(rep_count <= recs_nr);
1302  M0_UT_ASSERT(m0_forall(i, COUNT / 2, next_rep[i].cnp_rc == 0));
1303  if (!exclude_start_key)
1304  M0_UT_ASSERT(
1305  m0_forall(i, COUNT / 2,
1307  &next_rep[i],
1308  keys->ov_buf[COUNT / 2 + i],
1309  values->ov_buf[COUNT / 2 + i])));
1310  else
1311  M0_UT_ASSERT(
1312  m0_forall(i, COUNT / 2,
1314  &next_rep[i],
1315  keys->ov_buf[COUNT / 2 + i + 1],
1316  values->ov_buf[COUNT / 2 + i + 1])));
1317  M0_UT_ASSERT(next_rep[COUNT / 2].cnp_rc == -ENOENT);
1318  ut_next_rep_clear(next_rep, rep_count);
1319 
1320  /* perform next for empty result set */
1321  value_create(start_key.ov_vec.v_count[0],
1322  !slant ? COUNT : COUNT + 1,
1323  start_key.ov_buf[0]);
1324  recs_nr = COUNT;
1325  rc = ut_next_rec(&casc_ut_cctx, &index, &start_key, &recs_nr,
1326  next_rep, &rep_count, flags);
1327  M0_UT_ASSERT(rc == 0);
1328  M0_UT_ASSERT(rep_count >= 1);
1329  M0_UT_ASSERT(next_rep[0].cnp_rc == -ENOENT);
1330  ut_next_rep_clear(next_rep, rep_count);
1331 
1332  /* Remove index. */
1333  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
1334  M0_UT_ASSERT(rc == 0);
1335 
1336  m0_bufvec_free(&start_key);
1337 }
1338 
1339 static int get_reply2bufvec(struct m0_cas_get_reply *get_rep, m0_bcount_t nr,
1340  struct m0_bufvec *out)
1341 {
1342  int rc;
1343  m0_bcount_t i;
1344 
1346  if (rc != 0)
1347  return rc;
1348  for (i = 0; i < nr; ++i) {
1349  out->ov_buf[i] = get_rep[i].cge_val.b_addr;
1350  out->ov_vec.v_count[i] = get_rep[i].cge_val.b_nob;
1351  }
1352 
1353  return rc;
1354 }
1355 
1356 /*
1357  * Returns "true" if GET operation successfully returns all expected_values
1358  * (if they have been specified) or all the records exist (if expected_values
1359  * is NULL).
1360  */
1361 static bool has_values(struct m0_cas_id *index,
1362  const struct m0_bufvec *keys,
1363  const struct m0_bufvec *expected_values,
1364  uint64_t flags)
1365 {
1366  int rc;
1367  struct m0_cas_get_reply *get_rep;
1368  bool result;
1369  struct m0_bufvec actual_values;
1370  struct m0_bufvec empty_values;
1371 
1372  M0_ALLOC_ARR(get_rep, keys->ov_vec.v_nr);
1373  M0_UT_ASSERT(get_rep != NULL);
1374 
1375  rc = ut_rec__get(&casc_ut_cctx, index, keys, get_rep, flags);
1376  M0_UT_ASSERT(rc == 0);
1377 
1378  rc = m0_bufvec_empty_alloc(&empty_values, keys->ov_vec.v_nr);
1379  M0_UT_ASSERT(rc == 0);
1380 
1381  if (expected_values == NULL)
1382  expected_values = &empty_values;
1383 
1385  M0_IN(get_rep[i].cge_rc, (0, -ENOENT))));
1386 
1387  if (m0_exists(i, keys->ov_vec.v_nr, get_rep[i].cge_rc == -ENOENT)) {
1389  get_rep[i].cge_rc == -ENOENT));
1390 
1391  rc = get_reply2bufvec(get_rep, keys->ov_vec.v_nr,
1392  &actual_values);
1393  M0_UT_ASSERT(rc == 0);
1394  M0_UT_ASSERT(bufvec_cmp(&actual_values, expected_values) == 0);
1395  m0_bufvec_free2(&actual_values);
1396  result = false;
1397  goto out;
1398  } else {
1399  rc = get_reply2bufvec(get_rep, keys->ov_vec.v_nr,
1400  &actual_values);
1401  M0_UT_ASSERT(rc == 0);
1402  result = bufvec_cmp(&actual_values, expected_values) == 0;
1403  m0_bufvec_free2(&actual_values);
1404  }
1405 
1406 out:
1407  ut_get_rep_clear(get_rep, keys->ov_vec.v_nr);
1408  m0_free(get_rep);
1409  m0_bufvec_free(&empty_values);
1410  return result;
1411 }
1412 
1413 /*
1414  * Returns "true" all values returned by GET operation are the same as
1415  * the specified version.
1416  */
1417 static bool has_versions(struct m0_cas_id *index,
1418  const struct m0_bufvec *keys,
1419  uint64_t version,
1420  uint64_t flags)
1421 {
1422  int rc;
1423  struct m0_cas_get_reply *get_rep;
1424  bool result;
1425 
1426  M0_ALLOC_ARR(get_rep, keys->ov_vec.v_nr);
1427  M0_UT_ASSERT(get_rep != NULL);
1428 
1429  rc = ut_rec__get(&casc_ut_cctx, index, keys, get_rep, flags);
1430  M0_UT_ASSERT(rc == 0);
1431 
1433  M0_IN(get_rep[i].cge_rc, (0, -ENOENT))));
1434 
1435  result = m0_forall(i, keys->ov_vec.v_nr,
1436  m0_crv_ts(&get_rep[i].cge_ver).dts_phys == version);
1437 
1438  ut_get_rep_clear(get_rep, keys->ov_vec.v_nr);
1439  m0_free(get_rep);
1440  return result;
1441 }
1442 
1443 static bool has_tombstones(struct m0_cas_id *index,
1444  const struct m0_bufvec *keys)
1445 {
1446  int rc;
1447  struct m0_cas_get_reply *get_rep;
1448  bool result;
1449 
1450  M0_ALLOC_ARR(get_rep, keys->ov_vec.v_nr);
1451  M0_UT_ASSERT(get_rep != NULL);
1452 
1453  rc = ut_rec__get(&casc_ut_cctx, index, keys, get_rep, COF_VERSIONED);
1454  M0_UT_ASSERT(rc == 0);
1455 
1456  /* Ensure the rcs are within the range of allowed rcs. */
1458  M0_IN(get_rep[i].cge_rc, (0, -ENOENT))));
1459 
1460  /* Ensure all-or-nothing (either all have tbs or there are no tbs). */
1462  m0_crv_tbs(&get_rep[0].cge_ver)==
1463  m0_crv_tbs(&get_rep[i].cge_ver)));
1464 
1465  /* Ensure -ENOENT matches with tombstone flag. */
1467  ergo(!m0_crv_is_none(&get_rep[i].cge_ver),
1468  m0_crv_tbs(&get_rep[i].cge_ver) ==
1469  (get_rep[i].cge_rc == -ENOENT))));
1470 
1471  /* Ensure versions are always present on dead records. */
1473  ergo(m0_crv_tbs(&get_rep[i].cge_ver),
1474  !m0_crv_is_none(&get_rep[i].cge_ver))));
1475 
1476  result = m0_crv_tbs(&get_rep[0].cge_ver);
1477 
1478  ut_get_rep_clear(get_rep, keys->ov_vec.v_nr);
1479  memset(get_rep, 0, sizeof(*get_rep) * keys->ov_vec.v_nr);
1480 
1481  /*
1482  * Additionally, ensure that all the records are visible
1483  * when versioned behavior is disabled.
1484  */
1485  rc = ut_rec__get(&casc_ut_cctx, index, keys, get_rep, 0);
1486  M0_UT_ASSERT(rc == 0);
1487  M0_UT_ASSERT(m0_forall(i, keys->ov_vec.v_nr, get_rep[i].cge_rc == 0));
1488  ut_get_rep_clear(get_rep, keys->ov_vec.v_nr);
1489 
1490 
1491  m0_free(get_rep);
1492  return result;
1493 }
1494 
1495 /*
1496  * Breaks an array of GET replies down into pieces (keys, values, versions).
1497  * In other words, it transmutes a vector of tuples into a tuple of vectors.
1498  */
1499 static void next_reply_breakdown(struct m0_cas_next_reply *next_rep,
1500  m0_bcount_t nr,
1501  struct m0_bufvec *out_key,
1502  struct m0_bufvec *out_val,
1503  struct m0_crv **out_ver)
1504 {
1505  int rc;
1506  m0_bcount_t i;
1507  struct m0_crv *ver;
1508 
1509  rc = m0_bufvec_empty_alloc(out_key, nr);
1510  M0_UT_ASSERT(rc == 0);
1511  rc = m0_bufvec_empty_alloc(out_val, nr);
1512  M0_UT_ASSERT(rc == 0);
1513  M0_ALLOC_ARR(ver, nr);
1514  M0_UT_ASSERT(ver != NULL);
1515 
1516  for (i = 0; i < nr; ++i) {
1517  out_key->ov_buf[i] = next_rep[i].cnp_key.b_addr;
1518  out_key->ov_vec.v_count[i] = next_rep[i].cnp_key.b_nob;
1519 
1520  out_val->ov_buf[i] = next_rep[i].cnp_val.b_addr;
1521  out_val->ov_vec.v_count[i] = next_rep[i].cnp_val.b_nob;
1522 
1523  ver[i] = next_rep[i].cnp_ver;
1524  }
1525 
1526  *out_ver = ver;
1527 }
1528 
1529 
1530 /*
1531  * Ensures that NEXT yields the expected keys, values and versions.
1532  * Values and version are optional (ignored when set to NULL).
1533  */
1535  struct m0_bufvec *start_key,
1536  uint32_t requested_keys_nr,
1537  struct m0_bufvec *expected_keys,
1538  struct m0_bufvec *expected_values,
1539  struct m0_crv *expected_versions,
1540  int flags)
1541 {
1542  struct m0_cas_next_reply *next_rep;
1543  uint64_t rep_count;
1544  int rc;
1545  struct m0_bufvec actual_keys;
1546  struct m0_bufvec actual_values;
1547  struct m0_crv *actual_versions;
1548 
1549  M0_ALLOC_ARR(next_rep, requested_keys_nr);
1550  M0_UT_ASSERT(next_rep != NULL);
1551 
1552  rc = ut_next_rec(&casc_ut_cctx, index, start_key, &requested_keys_nr,
1553  next_rep, &rep_count, flags);
1554  M0_UT_ASSERT(rc == 0);
1555  M0_UT_ASSERT(rep_count == requested_keys_nr);
1556 
1557  if (expected_keys == NULL) {
1558  M0_UT_ASSERT(expected_values == NULL);
1559  M0_UT_ASSERT(expected_versions == NULL);
1560  M0_UT_ASSERT(m0_forall(i, rep_count,
1561  next_rep[i].cnp_rc == -ENOENT));
1562  } else {
1563  M0_UT_ASSERT(m0_forall(i, rep_count, next_rep[i].cnp_rc == 0));
1564  M0_UT_ASSERT(rep_count == expected_keys->ov_vec.v_nr);
1565  next_reply_breakdown(next_rep, rep_count,
1566  &actual_keys,
1567  &actual_values,
1568  &actual_versions);
1569  M0_UT_ASSERT(bufvec_cmp(expected_keys,
1570  &actual_keys) == 0);
1571 
1572  if (expected_values != NULL)
1573  M0_UT_ASSERT(bufvec_cmp(expected_values,
1574  &actual_values) == 0);
1575  if (expected_versions != NULL)
1576  M0_UT_ASSERT(memcmp(expected_versions,
1577  actual_versions,
1578  rep_count *
1579  sizeof(expected_versions[0])) == 0);
1580 
1581  m0_bufvec_free2(&actual_keys);
1582  m0_bufvec_free2(&actual_values);
1583  m0_free(actual_versions);
1584  }
1585 
1586  ut_next_rep_clear(next_rep, rep_count);
1587  m0_free(next_rep);
1588 }
1589 
1590 /*
1591  * Ensures that NEXT yields the expected keys.
1592  */
1593 static void next_keys_verified(struct m0_cas_id *index,
1594  struct m0_bufvec *start_key,
1595  uint32_t requested_keys_nr,
1596  struct m0_bufvec *expected_keys,
1597  int flags)
1598 {
1599  return next_records_verified(index, start_key, requested_keys_nr,
1600  expected_keys, NULL, NULL, flags);
1601 }
1602 
1603 
1605  const struct m0_bufvec *keys,
1606  const struct m0_bufvec *values,
1607  uint64_t version,
1608  uint64_t flags)
1609 {
1610  struct m0_cas_rec_reply *rep;
1611  struct m0_dtx *dtx;
1612  int rc;
1613 
1614  M0_UT_ASSERT(keys != NULL && values != NULL);
1615  M0_ALLOC_ARR(rep, keys->ov_vec.v_nr);
1616  M0_UT_ASSERT(rep != NULL);
1617 
1618  ut_dtx_init(&dtx, version);
1619  rc = ut_rec_common_put_seq(&casc_ut_cctx, index, keys, values, dtx,
1620  rep, flags);
1621  ut_dtx_fini(dtx);
1622  M0_UT_ASSERT(rc == 0);
1623  M0_UT_ASSERT(m0_forall(i, keys->ov_vec.v_nr, rep[i].crr_rc == 0));
1624  m0_free(rep);
1625 }
1626 
1628  const struct m0_bufvec *keys,
1629  uint64_t version,
1630  uint64_t flags)
1631 {
1632  struct m0_cas_rec_reply *rep;
1633  struct m0_dtx *dtx;
1634  int rc;
1635 
1636  M0_UT_ASSERT(keys != NULL);
1637  M0_ALLOC_ARR(rep, keys->ov_vec.v_nr);
1638  M0_UT_ASSERT(rep != NULL);
1639 
1640  ut_dtx_init(&dtx, version);
1641  rc = ut_rec_common_del_seq(&casc_ut_cctx, index, keys, dtx, rep, flags);
1642  ut_dtx_fini(dtx);
1643  M0_UT_ASSERT(rc == 0);
1644  M0_UT_ASSERT(m0_forall(i, keys->ov_vec.v_nr, rep[i].crr_rc == 0));
1645  m0_free(rep);
1646 }
1647 
1648 /*
1649  * PUTs (keys, values) and then ensures that expected_values are visible
1650  * via GET operation.
1651  */
1652 static void put_get_verified(struct m0_cas_id *index,
1653  struct m0_bufvec *keys,
1654  struct m0_bufvec *values,
1655  struct m0_bufvec *expected_values,
1656  uint64_t version,
1657  int put_flags,
1658  int get_flags)
1659 {
1660  ut_rec_common_put_verified(index, keys, values, version, put_flags);
1661  if (expected_values != NULL)
1662  M0_UT_ASSERT(has_values(index, keys, expected_values,
1663  get_flags));
1664 }
1665 
1666 /*
1667  * DELetes (keys, values) and then ensures that the values are not visible
1668  * via GET operation.
1669  */
1670 static void del_get_verified(struct m0_cas_id *index,
1671  struct m0_bufvec *keys,
1672  uint64_t version,
1673  uint64_t del_flags,
1674  uint64_t get_flags)
1675 {
1676  ut_rec_common_del_verified(index, keys, version, del_flags);
1677  M0_UT_ASSERT(!has_values(index, keys, NULL, get_flags));
1678 
1679  /*
1680  * When version is set to zero, the value actually gets removed, so
1681  * that tombstones are not available. Still, we can ensure that
1682  * versions were wiped out.
1683  */
1684  if (version == 0)
1686  else
1688 }
1689 
1690 
1691 /*
1692  * Initialise a single-element bufvec using an element taken from
1693  * the target bufvec at position specified by __idx:
1694  * @verbatim
1695  * bufvec target = [buf A, buf B, buf C]
1696  * bufvec slice = target.slice(1)
1697  * assert slice == [buf B]
1698  * slice = target.slice(2)
1699  * assert slice == [buf C]
1700  * @endverbatim
1701  */
1702 #define M0_BUFVEC_SLICE(__bufvec, __idx) \
1703  M0_BUFVEC_INIT_BUF((__bufvec)->ov_buf + (__idx), \
1704  (__bufvec)->ov_vec.v_count + (__idx))
1705 
1706 /*
1707  * A test case where we are verifying that NEXT works well with
1708  * combinations of PUT and DEL.
1709  */
1710 static void next_ver(void)
1711 {
1712  enum { V_PAST, V_FUTURE, V_NR };
1713  struct m0_bufvec keys;
1714  struct m0_bufvec values;
1715  struct m0_bufvec kodd;
1716  struct m0_bufvec keven;
1717  int rc;
1718  uint64_t version[V_NR] = { 2, 3 };
1719  int i;
1720  struct m0_cas_id index = {};
1721  struct m0_cas_rec_reply rep;
1722  const struct m0_fid ifid = IFID(2, 3);
1723 
1725  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
1726  M0_UT_ASSERT(rc == 0);
1727  index.ci_fid = ifid;
1728 
1729  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
1730  M0_UT_ASSERT(rc == 0);
1731  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
1732  rc = m0_bufvec_alloc(&values, keys.ov_vec.v_nr, sizeof(uint64_t));
1733  M0_UT_ASSERT(rc == 0);
1734  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
1735  rc = m0_bufvec_alloc(&kodd, keys.ov_vec.v_nr / 2, sizeof(uint64_t));
1736  M0_UT_ASSERT(rc == 0);
1737  rc = m0_bufvec_alloc(&keven, keys.ov_vec.v_nr / 2, sizeof(uint64_t));
1738  M0_UT_ASSERT(rc == 0);
1739 
1740  for (i = 0; i < keys.ov_vec.v_nr; i++) {
1741  *(uint64_t*)keys.ov_buf[i] = i;
1742  *(uint64_t*)values.ov_buf[i] = i;
1743  memcpy(((i & 0x01) == 0 ? &keven : &kodd)->ov_buf[i / 2],
1744  keys.ov_buf[i], keys.ov_vec.v_count[i]);
1745  }
1746 
1747  /* Insert all the keys. */
1748  put_get_verified(&index, &keys, &values, &values, version[V_PAST],
1750  COF_VERSIONED);
1752  version[V_PAST], COF_VERSIONED));
1753 
1754  /* Only even records will be alive in the future. */
1755  del_get_verified(&index, &kodd, version[V_FUTURE],
1758  version[V_FUTURE], COF_VERSIONED));
1759  M0_UT_ASSERT(has_versions(&index, &keven,
1760  version[V_PAST], COF_VERSIONED));
1761 
1762  /*
1763  * Case:
1764  * NEXT with the first alive key and the number records equal to
1765  * (number_of_alive_keys - 1) should return all the alive keys.
1766  */
1768  keys.ov_vec.v_nr / 2, &keven, COF_VERSIONED);
1769 
1770  /*
1771  * Case:
1772  * Requesting one record with NEXT with the first dead key
1773  * should return nothing (ENOENT).
1774  */
1775  next_keys_verified(&index, &M0_BUFVEC_SLICE(&kodd, 0), 1, NULL,
1776  COF_VERSIONED);
1777 
1778  /*
1779  * Case:
1780  * Requesting one record with NEXT(SLANT) with the first dead key
1781  * should return the second alive key.
1782  */
1783  next_keys_verified(&index, &M0_BUFVEC_SLICE(&kodd, 0), 1,
1784  &M0_BUFVEC_SLICE(&keven, 1),
1786 
1787  /*
1788  * Case:
1789  * Requesting NEXT(SLANT) record with with last dead key should
1790  * return -ENOENT.
1791  */
1793  &M0_BUFVEC_SLICE(&kodd, kodd.ov_vec.v_nr - 1), 1,
1795 
1796  /*
1797  * Case:
1798  * Requesting one record with NEXT(SLANT|EXECLUDE_START_KEY) with
1799  * start key equal to the first alive record should return one single
1800  * pair with the next alive record.
1801  */
1802  next_keys_verified(&index, &M0_BUFVEC_SLICE(&keven, 0), 1,
1803  &M0_BUFVEC_SLICE(&keven, 1),
1805 
1806  /* Now the index should have no keys. */
1807  del_get_verified(&index, &keven, version[V_FUTURE],
1809 
1810  /*
1811  * Case:
1812  * Requesting one record with NEXT(SLANT) should yield no keys at all
1813  * (ENOENT) on an index that does not have alive records.
1814  */
1815  next_keys_verified(&index, &M0_BUFVEC_SLICE(&keys, 0), 1, NULL,
1816  COF_VERSIONED);
1817 
1818  /*
1819  * Case:
1820  * When version-awre behavior is disabled (no COF_VERSIONED),
1821  * NEXT should yield all the keys that were inserted initially even
1822  * if all of them have tombstones.
1823  */
1825  keys.ov_vec.v_nr, &keys, 0);
1826 
1827  /* Now insert a non-versioned record at the "end". */
1828  del_get_verified(&index, &M0_BUFVEC_SLICE(&keys, keys.ov_vec.v_nr - 1),
1829  0, 0, 0);
1830  put_get_verified(&index, &M0_BUFVEC_SLICE(&keys, keys.ov_vec.v_nr - 1),
1831  &M0_BUFVEC_SLICE(&values, values.ov_vec.v_nr - 1),
1832  &M0_BUFVEC_SLICE(&values, values.ov_vec.v_nr - 1),
1833  0, 0, 0);
1834  /*
1835  * Case:
1836  * A record without version should be treaten as an alive record.
1837  * Requesting one record with NEXT(SLANT) with start key equal to the
1838  * last dead record should yield the non-versioned record.
1839  * However, if SLANT was not set it should still return ENOENT.
1840  */
1842  &M0_BUFVEC_SLICE(&keys, keys.ov_vec.v_nr - 2), 1,
1843  &M0_BUFVEC_SLICE(&keys, keys.ov_vec.v_nr - 1),
1846  &M0_BUFVEC_SLICE(&keys, keys.ov_vec.v_nr - 2), 1,
1847  NULL , COF_VERSIONED);
1848 
1849  m0_bufvec_free(&keys);
1850  m0_bufvec_free(&values);
1851  m0_bufvec_free(&keven);
1852  m0_bufvec_free(&kodd);
1853 
1854  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
1855  M0_UT_ASSERT(rc == 0);
1857 }
1858 
1859 /*
1860  * A test case where we are verifying that version and tombstones exposed
1861  * by CAS API (see COF_VERSIONED and COF_SHOW_DEAD) show expected
1862  * behavior with combinations of PUT, DEL and NEXT.
1863  */
1864 static void next_ver_exposed(void)
1865 {
1866  enum { V_PAST, V_FUTURE, V_NR };
1867  struct m0_bufvec keys;
1868  struct m0_bufvec values;
1869  struct m0_bufvec expected_values;
1870  struct m0_bufvec kodd;
1871  struct m0_bufvec keven;
1872  int rc;
1873  uint64_t version[V_NR] = { 2, 3 };
1874  int i;
1875  struct m0_cas_id index = {};
1876  struct m0_cas_rec_reply rep;
1877  struct m0_crv *versions;
1878  bool is_even;
1879  const struct m0_fid ifid = IFID(2, 3);
1880 
1882  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
1883  M0_UT_ASSERT(rc == 0);
1884  index.ci_fid = ifid;
1885 
1886 
1887  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
1888  M0_UT_ASSERT(rc == 0);
1889  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
1890  M0_ALLOC_ARR(versions, keys.ov_vec.v_nr);
1891  M0_UT_ASSERT(versions != NULL);
1892  rc = m0_bufvec_alloc(&values, keys.ov_vec.v_nr, sizeof(uint64_t));
1893  M0_UT_ASSERT(rc == 0);
1894  rc = m0_bufvec_alloc(&expected_values,
1895  keys.ov_vec.v_nr, sizeof(uint64_t));
1896  M0_UT_ASSERT(rc == 0);
1897  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
1898  rc = m0_bufvec_alloc(&kodd, keys.ov_vec.v_nr / 2, sizeof(uint64_t));
1899  M0_UT_ASSERT(rc == 0);
1900  rc = m0_bufvec_alloc(&keven, keys.ov_vec.v_nr / 2, sizeof(uint64_t));
1901  M0_UT_ASSERT(rc == 0);
1902 
1903  for (i = 0; i < keys.ov_vec.v_nr; i++) {
1904  is_even = (i & 0x01) == 0 ;
1905 
1906  *(uint64_t*)keys.ov_buf[i] = i;
1907  *(uint64_t*)values.ov_buf[i] = i;
1908  if (is_even)
1909  *(uint64_t*)expected_values.ov_buf[i] = i;
1910  else
1911  expected_values.ov_vec.v_count[i] = 0;
1912 
1913  memcpy((is_even ? &keven : &kodd)->ov_buf[i / 2],
1914  keys.ov_buf[i], keys.ov_vec.v_count[i]);
1915 
1916  m0_crv_init(&versions[i],
1917  &(struct m0_dtm0_ts) {
1918  .dts_phys =
1919  version[!is_even ? V_FUTURE : V_PAST],
1920  },
1921  !is_even);
1922  }
1923 
1924  /* Insert all the keys. */
1925  put_get_verified(&index, &keys, &values, &values, version[V_PAST],
1927  COF_VERSIONED);
1928 
1929  /* Only even records will be alive in the future. */
1930  del_get_verified(&index, &kodd, version[V_FUTURE],
1932 
1933  /*
1934  * Case:
1935  * If even records are alive and odd records are dead then
1936  * NEXT must return all the requested keys if COF_SHOW_DEAD is set.
1937  * The dead records must me "younger" then the alive records,
1938  * and the dead record must have tombstones set.
1939  */
1941  &M0_BUFVEC_SLICE(&keys, 0), keys.ov_vec.v_nr,
1942  &keys, &expected_values, versions,
1944 
1945  /*
1946  * Case:
1947  * When COF_SHOW_DEAD is specified, dead record is not skipped.
1948  */
1950  &M0_BUFVEC_SLICE(&keys, 1), 1,
1951  &M0_BUFVEC_SLICE(&keys, 1),
1952  &expected_values, versions + 1,
1954 
1955  /*
1956  * Case:
1957  * Dead record is not skipped when (SHOW_DEAD | SLANT) is specified.
1958  */
1960  &M0_BUFVEC_SLICE(&keys, 1), 1,
1961  &M0_BUFVEC_SLICE(&keys, 1),
1962  &expected_values, versions + 1,
1964 
1965  m0_bufvec_free(&keys);
1966  m0_bufvec_free(&values);
1967  m0_bufvec_free(&keven);
1968  m0_bufvec_free(&kodd);
1969  m0_free(versions);
1970 
1971  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
1972  M0_UT_ASSERT(rc == 0);
1974 }
1975 #undef M0_BUFVEC_SLICE
1976 
1977 static void next(void)
1978 {
1979  struct m0_bufvec keys;
1980  struct m0_bufvec values;
1981  int rc;
1982 
1984 
1985  /* Usual case. */
1986  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
1987  M0_UT_ASSERT(rc == 0);
1988  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
1989  M0_UT_ASSERT(rc == 0);
1990  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
1991  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
1992  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
1993  *(uint64_t*)values.ov_buf[i] = i * i,
1994  true));
1995  /* Call next_common() with 'slant' disabled. */
1996  next_common(&keys, &values, 0);
1997  m0_bufvec_free(&keys);
1998  m0_bufvec_free(&values);
1999 
2000  /* 'Slant' case. */
2001  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2002  M0_UT_ASSERT(rc == 0);
2003  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2004  M0_UT_ASSERT(rc == 0);
2005  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
2006  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2007  /*
2008  * It is required by next_common() function to fill
2009  * keys/values using shift 1.
2010  */
2011  m0_forall(i, keys.ov_vec.v_nr,
2012  (*(uint64_t*)keys.ov_buf[i] = i + 1,
2013  *(uint64_t*)values.ov_buf[i] = (i + 1) * (i + 1),
2014  true));
2015  /* Call next_common() with 'slant' enabled. */
2016  next_common(&keys, &values, COF_SLANT);
2017  m0_bufvec_free(&keys);
2018  m0_bufvec_free(&values);
2019 
2020  /* 'First key exclude' case. */
2021  rc = m0_bufvec_alloc(&keys, COUNT + 1, sizeof(uint64_t));
2022  M0_UT_ASSERT(rc == 0);
2023  rc = m0_bufvec_alloc(&values, COUNT + 1, sizeof(uint64_t));
2024  M0_UT_ASSERT(rc == 0);
2025  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT + 1);
2026  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2027  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2028  *(uint64_t*)values.ov_buf[i] = i * i,
2029  true));
2030  /* Call next_common() with 'first key exclude' enabled. */
2031  next_common(&keys, &values, COF_EXCLUDE_START_KEY);
2032  m0_bufvec_free(&keys);
2033  m0_bufvec_free(&values);
2034 
2035  /* 'First key exclude' with 'slant' case. */
2036  rc = m0_bufvec_alloc(&keys, COUNT + 1, sizeof(uint64_t));
2037  M0_UT_ASSERT(rc == 0);
2038  rc = m0_bufvec_alloc(&values, COUNT + 1, sizeof(uint64_t));
2039  M0_UT_ASSERT(rc == 0);
2040  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT + 1);
2041  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2042  m0_forall(i, keys.ov_vec.v_nr,
2043  (*(uint64_t*)keys.ov_buf[i] = i + 1,
2044  *(uint64_t*)values.ov_buf[i] = (i + 1) * (i + 1),
2045  true));
2046  /* Call next_common() with 'first key exclude' and 'slant' enabled. */
2047  next_common(&keys, &values, COF_SLANT | COF_EXCLUDE_START_KEY);
2048  m0_bufvec_free(&keys);
2049  m0_bufvec_free(&values);
2050 
2052 }
2053 
2054 static void next_bulk(void)
2055 {
2056  struct m0_bufvec keys;
2057  struct m0_bufvec values;
2058  int rc;
2059 
2061 
2062  /* Bulk keys and values. */
2064  vals_create(COUNT, COUNT_VAL_BYTES, &values);
2065  next_common(&keys, &values, 0);
2066  m0_bufvec_free(&keys);
2067  m0_bufvec_free(&values);
2068 
2069  /* Bulk values. */
2070  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2071  M0_UT_ASSERT(rc == 0);
2072  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i, true));
2073  vals_create(COUNT, COUNT_VAL_BYTES, &values);
2074  next_common(&keys, &values, 0);
2075  m0_bufvec_free(&keys);
2076  m0_bufvec_free(&values);
2077 
2078  /* Bulk keys. */
2080  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2081  M0_UT_ASSERT(rc == 0);
2082  m0_forall(i, values.ov_vec.v_nr, (*(uint64_t*)values.ov_buf[i] = i,
2083  true));
2084  next_common(&keys, &values, 0);
2085  m0_bufvec_free(&keys);
2086  m0_bufvec_free(&values);
2087 
2088  /* Bulk mix. */
2089  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2090  M0_UT_ASSERT(rc == 0);
2091  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2092  true));
2094  next_common(&keys, &values, 0);
2095  m0_bufvec_free(&keys);
2096  m0_bufvec_free(&values);
2097 
2099 }
2100 
2101 static void next_fail(void)
2102 {
2103  struct m0_cas_rec_reply rep[COUNT];
2104  struct m0_cas_next_reply next_rep[COUNT];
2105  const struct m0_fid ifid = IFID(2, 3);
2106  struct m0_cas_id index = {};
2107  struct m0_bufvec keys;
2108  struct m0_bufvec values;
2109  struct m0_bufvec start_key;
2110  uint32_t recs_nr;
2111  uint64_t rep_count;
2112  int rc;
2113 
2115 
2116  M0_SET_ARR0(rep);
2117  M0_SET_ARR0(next_rep);
2118  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2119  M0_UT_ASSERT(rc == 0);
2120  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2121  M0_UT_ASSERT(rc == 0);
2122  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
2123  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2124  /* insert index and records */
2125  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2126  *(uint64_t*)values.ov_buf[i] = i * i,
2127  true));
2128  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
2129  M0_UT_ASSERT(rc == 0);
2130  index.ci_fid = ifid;
2131  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
2132  M0_UT_ASSERT(rc == 0);
2133  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
2134  /* clear result set */
2135  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = 0,
2136  *(uint64_t*)values.ov_buf[i] = 0,
2137  true));
2138  /* perform next for all records */
2139  recs_nr = COUNT;
2140  rc = m0_bufvec_alloc(&start_key, 1, sizeof(uint64_t));
2141  M0_UT_ASSERT(rc == 0);
2142  *(uint64_t *)start_key.ov_buf[0] = 0;
2143  m0_fi_enable_once("creq_op_alloc", "cas_alloc_fail");
2144  rc = ut_next_rec(&casc_ut_cctx, &index, &start_key, &recs_nr, next_rep,
2145  &rep_count, 0);
2146  M0_UT_ASSERT(rc == -ENOMEM);
2147  m0_fi_enable_once("ctg_kbuf_get", "cas_alloc_fail");
2148  rc = ut_next_rec(&casc_ut_cctx, &index, &start_key, &recs_nr,
2149  next_rep, &rep_count, 0);
2150  M0_UT_ASSERT(rc == -ENOMEM);
2151 
2152  m0_bufvec_free(&start_key);
2153  m0_bufvec_free(&keys);
2154  m0_bufvec_free(&values);
2156 }
2157 
2158 static void next_multi_common(struct m0_bufvec *keys, struct m0_bufvec *values)
2159 {
2160  struct m0_cas_rec_reply rep[COUNT];
2161  struct m0_cas_next_reply next_rep[COUNT];
2162  const struct m0_fid ifid = IFID(2, 3);
2163  struct m0_cas_id index = {};
2164  struct m0_bufvec start_keys;
2165  uint32_t recs_nr[3];
2166  uint64_t rep_count;
2167  int rc;
2168  int i;
2169 
2170  M0_SET_ARR0(rep);
2171  M0_SET_ARR0(next_rep);
2172  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
2173  M0_UT_ASSERT(rc == 0);
2174  index.ci_fid = ifid;
2175  rc = ut_rec_put(&casc_ut_cctx, &index, keys, values, rep, 0);
2176  M0_UT_ASSERT(rc == 0);
2177  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
2178  /*
2179  * Perform next for three keys: first, middle and last.
2180  */
2181  rc = m0_bufvec_alloc(&start_keys, 3, keys->ov_vec.v_count[0]);
2182  M0_UT_ASSERT(rc == 0);
2183  value_create(start_keys.ov_vec.v_count[0], 0, start_keys.ov_buf[0]);
2184  value_create(start_keys.ov_vec.v_count[1], COUNT / 2,
2185  start_keys.ov_buf[1]);
2186  value_create(start_keys.ov_vec.v_count[2], COUNT,
2187  start_keys.ov_buf[2]);
2188  recs_nr[0] = COUNT / 2 - 1;
2189  recs_nr[1] = COUNT / 2 - 1;
2190  recs_nr[2] = 1;
2191  rc = ut_next_rec(&casc_ut_cctx, &index, &start_keys, recs_nr, next_rep,
2192  &rep_count, 0);
2193  M0_UT_ASSERT(rc == 0);
2194  M0_UT_ASSERT(rep_count == COUNT - 1);
2195  M0_UT_ASSERT(m0_forall(i, COUNT - 2, next_rep[i].cnp_rc == 0));
2196  M0_UT_ASSERT(next_rep[COUNT - 2].cnp_rc == -ENOENT);
2197  M0_UT_ASSERT(m0_forall(i, COUNT / 2 - 1,
2198  next_rep_equals(&next_rep[i],
2199  keys->ov_buf[i],
2200  values->ov_buf[i])));
2201  for (i = COUNT / 2 - 1; i < COUNT - 2; i++) {
2202  M0_UT_ASSERT(next_rep_equals(&next_rep[i],
2203  keys->ov_buf[i + 1],
2204  values->ov_buf[i + 1]));
2205  }
2206  ut_next_rep_clear(next_rep, rep_count);
2207 
2208  /* Remove index. */
2209  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
2210  M0_UT_ASSERT(rc == 0);
2211 
2212  m0_bufvec_free(&start_keys);
2213 }
2214 
2215 static void next_multi(void)
2216 {
2217  struct m0_bufvec keys;
2218  struct m0_bufvec values;
2219  int rc;
2220 
2222  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2223  M0_UT_ASSERT(rc == 0);
2224  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2225  M0_UT_ASSERT(rc == 0);
2226  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
2227  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2228  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2229  *(uint64_t*)values.ov_buf[i] = i * i,
2230  true));
2231  next_multi_common(&keys, &values);
2232  m0_bufvec_free(&keys);
2233  m0_bufvec_free(&values);
2235 }
2236 
2237 static void next_multi_bulk(void)
2238 {
2239  struct m0_bufvec keys;
2240  struct m0_bufvec values;
2241  int rc;
2242 
2244 
2245  /* Bulk keys and values. */
2247  vals_create(COUNT, COUNT_VAL_BYTES, &values);
2248  next_multi_common(&keys, &values);
2249  m0_bufvec_free(&keys);
2250  m0_bufvec_free(&values);
2251 
2252  /* Bulk values. */
2253  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2254  M0_UT_ASSERT(rc == 0);
2255  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i, true));
2256  vals_create(COUNT, COUNT_VAL_BYTES, &values);
2257  next_multi_common(&keys, &values);
2258  m0_bufvec_free(&keys);
2259  m0_bufvec_free(&values);
2260 
2261  /* Bulk keys. */
2263  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2264  M0_UT_ASSERT(rc == 0);
2265  m0_forall(i, values.ov_vec.v_nr, (*(uint64_t*)values.ov_buf[i] = i,
2266  true));
2267  next_multi_common(&keys, &values);
2268  m0_bufvec_free(&keys);
2269  m0_bufvec_free(&values);
2270 
2271  /* Bulk mix. */
2272  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2273  M0_UT_ASSERT(rc == 0);
2274  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2275  true));
2277  next_multi_common(&keys, &values);
2278  m0_bufvec_free(&keys);
2279  m0_bufvec_free(&values);
2280 
2282 }
2283 
2284 static void put_common_with_ver(struct m0_bufvec *keys,
2285  struct m0_bufvec *values,
2286  uint64_t version)
2287 {
2288  const struct m0_fid ifid = IFID(2, 3);
2289  struct m0_cas_id index = {};
2290  int rc;
2291  struct m0_cas_rec_reply rep;
2292 
2293  M0_UT_ASSERT(keys != NULL && values != NULL);
2294 
2295  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
2296  M0_UT_ASSERT(rc == 0);
2297  index.ci_fid = ifid;
2298 
2299  ut_rec_common_put_verified(&index, keys, values, version,
2300  version == 0 ? 0 : (COF_VERSIONED |
2301  COF_OVERWRITE));
2302 
2303  /* Remove index. */
2304  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
2305  M0_UT_ASSERT(rc == 0);
2306 }
2307 
2308 static void put_common(struct m0_bufvec *keys, struct m0_bufvec *values)
2309 {
2310  put_common_with_ver(keys, values, 0);
2311 }
2312 
2313 /*
2314  * PUTs keys and ensures that "older" keys are overwritten by "newer" keys,
2315  * while "older" keys cannot overwrite "newer" keys.
2316  * The test case is supposed to work in both kinds of environment (DTM
2317  * and non-DTM).
2318  */
2319 static void put_overwrite_ver(void)
2320 {
2321  enum v { V_NONE, V_PAST, V_NOW, V_FUTURE, V_NR};
2322  struct m0_bufvec keys;
2323  struct m0_bufvec vals[V_NR];
2324  uint64_t version[V_NR] = {};
2325  int rc;
2326  int i;
2327  int j;
2328  struct m0_cas_id index = {};
2329  struct m0_cas_rec_reply rep[1];
2330  const struct m0_fid ifid = IFID(2, 3);
2331 
2332  /*
2333  * For every i-th key we have V_NR values from i to i << (V_NR - 1).
2334  * Ensure it will not overflow.
2335  */
2336  M0_CASSERT((UINT64_MAX / COUNT) > (1L << V_NR));
2337 
2339 
2340  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2341  M0_UT_ASSERT(rc == 0);
2342  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2343  for (j = 0; j < V_NR; j++) {
2344  rc = m0_bufvec_alloc(&vals[j], keys.ov_vec.v_nr,
2345  sizeof(uint64_t));
2346  M0_UT_ASSERT(rc == 0);
2347  version[j] = j;
2348  }
2349 
2350  for (i = 0; i < keys.ov_vec.v_nr; i++) {
2351  *(uint64_t*)keys.ov_buf[i] = i;
2352  for (j = 0; j < V_NR; j++)
2353  *(uint64_t*)vals[j].ov_buf[i] = i << j;
2354  }
2355 
2356  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
2357  M0_UT_ASSERT(rc == 0);
2358  index.ci_fid = ifid;
2359 
2360  /* PUT at "now". */
2361  put_get_verified(&index, &keys, &vals[V_NOW], &vals[V_NOW],
2363  COF_VERSIONED);
2365  version[V_NOW], COF_VERSIONED));
2366 
2367  /* PUT at "future" (overwrites "now"). */
2368  put_get_verified(&index, &keys, &vals[V_FUTURE], &vals[V_FUTURE],
2369  version[V_FUTURE], COF_VERSIONED | COF_OVERWRITE,
2370  COF_VERSIONED);
2372  version[V_FUTURE], COF_VERSIONED));
2373 
2374  /* PUT at "past" (values should not be changed) */
2375  put_get_verified(&index, &keys, &vals[V_PAST], &vals[V_FUTURE],
2376  version[V_PAST], COF_VERSIONED | COF_OVERWRITE,
2377  COF_VERSIONED);
2379  version[V_FUTURE], COF_VERSIONED));
2380 
2381  /* However, empty version disables the versioned behavior. */
2382  put_get_verified(&index, &keys, &vals[V_PAST], &vals[V_PAST],
2383  version[V_NONE], COF_VERSIONED | COF_OVERWRITE,
2384  COF_VERSIONED);
2386  version[V_NONE], COF_VERSIONED));
2387 
2388  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
2389  M0_UT_ASSERT(rc == 0);
2390 
2391  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
2392  M0_UT_ASSERT(rc == 0);
2393  index.ci_fid = ifid;
2394 
2395  /*
2396  * Insertion of a pair without COF_OVERWRITE flag set disables
2397  * the versioned behavior even if the version was specified.
2398  * Let's insert some values first.
2399  */
2400  put_get_verified(&index, &keys, &vals[V_FUTURE], &vals[V_FUTURE],
2401  version[V_FUTURE], COF_VERSIONED, COF_VERSIONED);
2402  /*
2403  * And now let's check if they are overwritten. We expect that
2404  * the values will be overwritten because the previous operation
2405  * inserted the records but did not set their versions.
2406  */
2407  put_get_verified(&index, &keys, &vals[V_PAST], &vals[V_PAST],
2408  version[V_PAST], COF_VERSIONED | COF_OVERWRITE,
2409  COF_VERSIONED);
2410 
2411  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
2412  M0_UT_ASSERT(rc == 0);
2413 
2414  for (j = 0; j < V_NR; j++)
2415  m0_bufvec_free(&vals[j]);
2416  m0_bufvec_free(&keys);
2418 }
2419 
2420 /*
2421  * Put a versioned key-value pair.
2422  */
2423 static void put_ver(void)
2424 {
2425  struct m0_bufvec keys;
2426  struct m0_bufvec values;
2427  int rc;
2428 
2430 
2431  rc = m0_bufvec_alloc(&keys, 1, sizeof(uint64_t));
2432  M0_UT_ASSERT(rc == 0);
2433  rc = m0_bufvec_alloc(&values, 1, sizeof(uint64_t));
2434  M0_UT_ASSERT(rc == 0);
2435  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2436  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2437  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2438  *(uint64_t*)values.ov_buf[i] = i * i,
2439  true));
2440  put_common_with_ver(&keys, &values, 1);
2441  m0_bufvec_free(&keys);
2442  m0_bufvec_free(&values);
2443 
2445 }
2446 
2447 /*
2448  * Put small Keys and Values.
2449  */
2450 static void put(void)
2451 {
2452  struct m0_bufvec keys;
2453  struct m0_bufvec values;
2454  int rc;
2455 
2457  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2458  M0_UT_ASSERT(rc == 0);
2459  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2460  M0_UT_ASSERT(rc == 0);
2461  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2462  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2463  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2464  *(uint64_t*)values.ov_buf[i] = i * i,
2465  true));
2466  put_common(&keys, &values);
2467  m0_bufvec_free(&keys);
2468  m0_bufvec_free(&values);
2470 }
2471 
2472 /*
2473  * Test fragmented requests.
2474  */
2475 static void recs_fragm(void)
2476 {
2477  struct m0_cas_rec_reply rep[COUNT];
2478  struct m0_cas_get_reply get_rep[COUNT];
2479  struct m0_cas_next_reply next_rep[60];
2480  const struct m0_fid ifid = IFID(2, 3);
2481  struct m0_cas_id index = {};
2482  struct m0_bufvec keys;
2483  struct m0_bufvec values;
2484  struct m0_bufvec start_keys;
2485  uint64_t rep_count;
2486  uint32_t recs_nr[20];
2487  int i;
2488  int j;
2489  int k;
2490  int rc;
2491 
2493  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2494  M0_UT_ASSERT(rc == 0);
2495  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2496  M0_UT_ASSERT(rc == 0);
2497  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2498  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2499  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2500  *(uint64_t*)values.ov_buf[i] = i * i,
2501  true));
2502 
2503  M0_SET_ARR0(rep);
2504 
2505  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
2506  M0_UT_ASSERT(rc == 0);
2507  index.ci_fid = ifid;
2508 
2509 
2510  /* Test fragmented PUT. */
2511  m0_fi_enable_once("m0_rpc_item_max_payload_exceeded",
2512  "payload_too_large1");
2513  m0_fi_enable_off_n_on_m("m0_rpc_item_max_payload_exceeded",
2514  "payload_too_large2",
2515  10, 1);
2516  //m0_fi_enable_once("cas_req_fragmentation", "fragm_error");
2517  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
2518  M0_UT_ASSERT(rc == 0);
2519  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
2520  m0_fi_disable("m0_rpc_item_max_payload_exceeded", "payload_too_large2");
2521 
2522 
2523  /* Test fragmented GET. */
2524  M0_SET_ARR0(rep);
2525  M0_SET_ARR0(get_rep);
2526  m0_fi_enable_once("m0_rpc_item_max_payload_exceeded",
2527  "payload_too_large1");
2528  m0_fi_enable_off_n_on_m("m0_rpc_item_max_payload_exceeded",
2529  "payload_too_large2",
2530  10, 1);
2531  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
2532  M0_UT_ASSERT(rc == 0);
2534  memcmp(get_rep[i].cge_val.b_addr,
2535  values.ov_buf[i],
2536  values.ov_vec.v_count[i] ) == 0));
2537  m0_fi_disable("m0_rpc_item_max_payload_exceeded", "payload_too_large2");
2538  ut_get_rep_clear(get_rep, keys.ov_vec.v_nr);
2539 
2540 
2541  /* Test fragmented NEXT. */
2542  M0_SET_ARR0(rep);
2543  M0_SET_ARR0(next_rep);
2544  rc = m0_bufvec_alloc(&start_keys, 20, keys.ov_vec.v_count[0]);
2545  M0_UT_ASSERT(rc == 0);
2546  for (i = 0; i < 20; i++) {
2547  value_create(start_keys.ov_vec.v_count[i], i,
2548  start_keys.ov_buf[i]);
2549  recs_nr[i] = 3;
2550  }
2551  m0_fi_enable_once("m0_rpc_item_max_payload_exceeded",
2552  "payload_too_large1");
2553  m0_fi_enable_off_n_on_m("m0_rpc_item_max_payload_exceeded",
2554  "payload_too_large2",
2555  10, 1);
2556  rc = ut_next_rec(&casc_ut_cctx, &index, &start_keys, recs_nr, next_rep,
2557  &rep_count, 0);
2558  M0_UT_ASSERT(rc == 0);
2559  M0_UT_ASSERT(rep_count == 60);
2560  M0_UT_ASSERT(m0_forall(i, rep_count, next_rep[i].cnp_rc == 0));
2561  m0_fi_disable("m0_rpc_item_max_payload_exceeded", "payload_too_large2");
2562 
2563  k = 0;
2564  for (i = 0; i < 20; i++) {
2565  for (j = 0; j < 3; j++) {
2566  M0_UT_ASSERT(next_rep_equals(&next_rep[k++],
2567  keys.ov_buf[i + j],
2568  values.ov_buf[i + j]));
2569  }
2570  }
2571  ut_next_rep_clear(next_rep, rep_count);
2572 
2573 
2574  /* Test fragmented DEL. */
2575  M0_SET_ARR0(rep);
2576  M0_SET_ARR0(get_rep);
2577  m0_fi_enable_once("m0_rpc_item_max_payload_exceeded",
2578  "payload_too_large1");
2579  m0_fi_enable_off_n_on_m("m0_rpc_item_max_payload_exceeded",
2580  "payload_too_large2",
2581  10, 1);
2582  rc = ut_rec_del(&casc_ut_cctx, &index, &keys, rep, 0);
2583  M0_UT_ASSERT(rc == 0);
2584  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
2585  m0_fi_disable("m0_rpc_item_max_payload_exceeded", "payload_too_large2");
2586 
2587 
2588  /* Check selected values - must be empty. */
2589  m0_fi_enable_once("m0_rpc_item_max_payload_exceeded",
2590  "payload_too_large1");
2591  m0_fi_enable_off_n_on_m("m0_rpc_item_max_payload_exceeded",
2592  "payload_too_large2",
2593  10, 1);
2594  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
2595  M0_UT_ASSERT(rc == 0);
2596  M0_UT_ASSERT(m0_forall(i, COUNT, get_rep[i].cge_rc == -ENOENT));
2597  m0_fi_disable("m0_rpc_item_max_payload_exceeded", "payload_too_large2");
2598  ut_get_rep_clear(get_rep, COUNT);
2599 
2600 
2601  /* Remove index. */
2602  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
2603  M0_UT_ASSERT(rc == 0);
2604 
2605  m0_bufvec_free(&start_keys);
2606  m0_bufvec_free(&keys);
2607  m0_bufvec_free(&values);
2609 }
2610 
2611 /*
2612  * Test errors during fragmented requests.
2613  */
2614 static void recs_fragm_fail(void)
2615 {
2616  struct m0_cas_rec_reply rep[COUNT];
2617  const struct m0_fid ifids[2] = {IFID(2, 3), IFID(2, 4)};
2618  struct m0_cas_id index = {};
2619  struct m0_bufvec keys;
2620  struct m0_bufvec values;
2621  int rc;
2622 
2624 
2625  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2626  M0_UT_ASSERT(rc == 0);
2627  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2628  M0_UT_ASSERT(rc == 0);
2629  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2630  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2631  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2632  *(uint64_t*)values.ov_buf[i] = i * i,
2633  true));
2634  M0_SET_ARR0(rep);
2635 
2636  /* Create indices. */
2637  rc = ut_idx_create(&casc_ut_cctx, ifids, 2, rep);
2638  M0_UT_ASSERT(rc == 0);
2639 
2640  index.ci_fid = ifids[0];
2641 
2642  m0_fi_enable_once("m0_rpc_item_max_payload_exceeded",
2643  "payload_too_large1");
2644  m0_fi_enable_off_n_on_m("m0_rpc_item_max_payload_exceeded",
2645  "payload_too_large2",
2646  10, 1);
2647  m0_fi_enable_off_n_on_m("cas_req_fragmentation", "fragm_error", 1, 1);
2648  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
2649  m0_fi_disable("m0_rpc_item_max_payload_exceeded", "payload_too_large2");
2650  m0_fi_disable("cas_req_fragmentation", "fragm_error");
2651  M0_UT_ASSERT(rc == -E2BIG);
2652 
2653  M0_SET_ARR0(rep);
2654 
2655  index.ci_fid = ifids[1];
2656 
2657  m0_fi_enable_once("m0_rpc_item_max_payload_exceeded",
2658  "payload_too_large1");
2659  m0_fi_enable_off_n_on_m("m0_rpc_item_max_payload_exceeded",
2660  "payload_too_large2",
2661  10, 1);
2662  m0_fi_enable_off_n_on_m("cas_req_replied_cb", "send-failure", 1, 1);
2663  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
2664  m0_fi_disable("m0_rpc_item_max_payload_exceeded", "payload_too_large2");
2665  m0_fi_disable("cas_req_replied_cb", "send-failure");
2666  M0_UT_ASSERT(rc == -ENOTCONN);
2667 
2668  /* Remove indices. */
2669  rc = ut_idx_delete(&casc_ut_cctx, ifids, 2, rep);
2670  M0_UT_ASSERT(rc == 0);
2671 
2672  m0_bufvec_free(&keys);
2673  m0_bufvec_free(&values);
2674 
2676 }
2677 
2678 /*
2679  * Put Large Keys and Values.
2680  */
2681 static void put_bulk(void)
2682 {
2683  struct m0_bufvec keys;
2684  struct m0_bufvec values;
2685  int rc;
2686 
2688  /* Bulk keys and values. */
2690  vals_create(COUNT, COUNT_VAL_BYTES, &values);
2691  put_common(&keys, &values);
2692  m0_bufvec_free(&keys);
2693  m0_bufvec_free(&values);
2694 
2695  /* Bulk keys. */
2696  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2697  M0_UT_ASSERT(rc == 0);
2698  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i, true));
2699  vals_create(COUNT, COUNT_VAL_BYTES, &values);
2700  put_common(&keys, &values);
2701  m0_bufvec_free(&keys);
2702  m0_bufvec_free(&values);
2703 
2704  /* Bulk values. */
2706  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2707  M0_UT_ASSERT(rc == 0);
2708  m0_forall(i, values.ov_vec.v_nr, (*(uint64_t*)values.ov_buf[i] = i,
2709  true));
2710 
2711  put_common(&keys, &values);
2712  m0_bufvec_free(&keys);
2713  m0_bufvec_free(&values);
2714 
2715  /* Bulk mix. */
2717  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2718  M0_UT_ASSERT(rc == 0);
2719  m0_forall(i, values.ov_vec.v_nr, (*(uint64_t*)values.ov_buf[i] = i,
2720  true));
2721  put_common(&keys, &values);
2722  m0_bufvec_free(&keys);
2723  m0_bufvec_free(&values);
2724 
2725  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2726  M0_UT_ASSERT(rc == 0);
2727  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2728  true));
2730  put_common(&keys, &values);
2731  m0_bufvec_free(&keys);
2732  m0_bufvec_free(&values);
2734 }
2735 
2736 /*
2737  * Put small Keys and Values with 'create' or 'overwrite' flag.
2738  */
2739 static void put_save_common(uint32_t flags)
2740 {
2741  struct m0_cas_rec_reply rep[1];
2742  struct m0_cas_get_reply grep[1];
2743  const struct m0_fid ifid = IFID(2, 3);
2744  struct m0_cas_id index = {};
2745  struct m0_bufvec keys;
2746  struct m0_bufvec values;
2747  int rc;
2748 
2750  rc = m0_bufvec_alloc(&keys, 1, sizeof(uint64_t));
2751  M0_UT_ASSERT(rc == 0);
2752  rc = m0_bufvec_alloc(&values, 1, sizeof(uint32_t));
2753  M0_UT_ASSERT(rc == 0);
2754  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2755  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2756  *(uint64_t*)keys.ov_buf[0] = 1;
2757  *(uint32_t*)values.ov_buf[0] = 1;
2758 
2759  M0_SET_ARR0(rep);
2760 
2761  /* create index */
2762  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
2763  M0_UT_ASSERT(rc == 0);
2764 
2765  index.ci_fid = ifid;
2766  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
2767 
2768  M0_UT_ASSERT(rc == 0);
2769  M0_UT_ASSERT(rep[0].crr_rc == 0);
2770 
2771  m0_bufvec_free(&values);
2772  /* Allocate value of size greater than size of previous value. */
2773  rc = m0_bufvec_alloc(&values, 1, sizeof(uint64_t));
2774  M0_UT_ASSERT(rc == 0);
2775  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2776 
2777  *(uint64_t*)values.ov_buf[0] = 2;
2778  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, flags);
2779  M0_UT_ASSERT(rc == 0);
2780  M0_UT_ASSERT(rep[0].crr_rc == 0);
2781 
2782  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, grep);
2783  M0_UT_ASSERT(rc == 0);
2784  if (flags & COF_CREATE)
2785  M0_UT_ASSERT(*(uint32_t*)grep[0].cge_val.b_addr == 1);
2786  if (flags & COF_OVERWRITE)
2787  M0_UT_ASSERT(*(uint64_t*)grep[0].cge_val.b_addr == 2);
2788  ut_get_rep_clear(grep, 1);
2789 
2790  *(uint64_t*)values.ov_buf[0] = 3;
2791  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, flags);
2792  M0_UT_ASSERT(rc == 0);
2793  M0_UT_ASSERT(rep[0].crr_rc == 0);
2794 
2795  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, grep);
2796  M0_UT_ASSERT(rc == 0);
2797  if (flags & COF_CREATE)
2798  M0_UT_ASSERT(*(uint32_t*)grep[0].cge_val.b_addr == 1);
2799  if (flags & COF_OVERWRITE)
2800  M0_UT_ASSERT(*(uint64_t*)grep[0].cge_val.b_addr == 3);
2801  ut_get_rep_clear(grep, 1);
2802 
2803  /* Remove index. */
2804  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
2805  M0_UT_ASSERT(rc == 0);
2806 
2807  m0_bufvec_free(&keys);
2808  m0_bufvec_free(&values);
2810 }
2811 
2812 /*
2813  * Put small Keys and Values with 'create' flag.
2814  */
2815 static void put_create(void)
2816 {
2818 }
2819 
2820 /*
2821  * Put small Keys and Values with 'overwrite' flag.
2822  */
2823 static void put_overwrite(void)
2824 {
2826 }
2827 
2828 /*
2829  * Put small Keys and Values with 'create-on-write' flag.
2830  */
2831 static void put_crow(void)
2832 {
2833  struct m0_cas_rec_reply rep[1];
2834  struct m0_cas_get_reply grep[1];
2835  const struct m0_fid ifid = IFID(2, 3);
2836  struct m0_cas_id index = {};
2837  struct m0_bufvec keys;
2838  struct m0_bufvec values;
2839  int rc;
2840 
2842  rc = m0_bufvec_alloc(&keys, 1, sizeof(uint64_t));
2843  M0_UT_ASSERT(rc == 0);
2844  rc = m0_bufvec_alloc(&values, 1, sizeof(uint64_t));
2845  M0_UT_ASSERT(rc == 0);
2846  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2847  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2848  *(uint64_t*)keys.ov_buf[0] = 1;
2849  *(uint64_t*)values.ov_buf[0] = 1;
2850 
2851  M0_SET_ARR0(rep);
2852 
2853  index.ci_fid = ifid;
2854  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, COF_CROW);
2855 
2856  M0_UT_ASSERT(rc == 0);
2857  M0_UT_ASSERT(rep[0].crr_rc == 0);
2858 
2859  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, grep);
2860  M0_UT_ASSERT(rc == 0);
2861  M0_UT_ASSERT(*(uint64_t*)grep[0].cge_val.b_addr == 1);
2862  ut_get_rep_clear(grep, 1);
2863 
2864  /* Remove index. */
2865  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
2866  M0_UT_ASSERT(rc == 0);
2867 
2868  m0_bufvec_free(&keys);
2869  m0_bufvec_free(&values);
2871 }
2872 
2873 /*
2874  * Fail to create catalogue during putting of small Keys and Values with
2875  * 'create-on-write' flag.
2876  */
2877 static void put_crow_fail(void)
2878 {
2879  struct m0_cas_rec_reply rep[1];
2880  struct m0_cas_get_reply grep[1];
2881  const struct m0_fid ifid = IFID(2, 3);
2882  struct m0_cas_id index = {};
2883  struct m0_bufvec keys;
2884  struct m0_bufvec values;
2885  int rc;
2886 
2888  rc = m0_bufvec_alloc(&keys, 1, sizeof(uint64_t));
2889  M0_UT_ASSERT(rc == 0);
2890  rc = m0_bufvec_alloc(&values, 1, sizeof(uint64_t));
2891  M0_UT_ASSERT(rc == 0);
2892  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2893  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2894  *(uint64_t*)keys.ov_buf[0] = 1;
2895  *(uint64_t*)values.ov_buf[0] = 1;
2896 
2897  M0_SET_ARR0(rep);
2898 
2899  m0_fi_enable_off_n_on_m("ctg_kbuf_get", "cas_alloc_fail", 1, 1);
2900  index.ci_fid = ifid;
2901  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, COF_CROW);
2902  M0_UT_ASSERT(rc == -ENOMEM);
2903  m0_fi_disable("ctg_kbuf_get", "cas_alloc_fail");
2904 
2905  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, grep);
2906  M0_UT_ASSERT(rc == -ENOENT);
2907 
2908  /* Try to lookup non-existent index. */
2909  rc = ut_lookup_idx(&casc_ut_cctx, &ifid, 1, rep);
2910  M0_UT_ASSERT(rc == 0);
2911  M0_UT_ASSERT(rep[0].crr_rc == -ENOENT);
2912 
2913  m0_bufvec_free(&keys);
2914  m0_bufvec_free(&values);
2916 }
2917 
2918 static void put_fail_common(struct m0_bufvec *keys, struct m0_bufvec *values)
2919 {
2920  struct m0_cas_rec_reply rep[COUNT];
2921  const struct m0_fid ifid = IFID(2, 3);
2922  struct m0_cas_id index = {};
2923  int rc;
2924 
2926 
2927  M0_SET_ARR0(rep);
2928  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
2929  M0_UT_ASSERT(rc == 0);
2930  index.ci_fid = ifid;
2931 
2932  m0_fi_enable_once("creq_op_alloc", "cas_alloc_fail");
2933  rc = ut_rec_put(&casc_ut_cctx, &index, keys, values, rep, 0);
2934  M0_UT_ASSERT(rc == -ENOMEM);
2935  m0_fi_enable_once("ctg_kbuf_get", "cas_alloc_fail");
2936  rc = ut_rec_put(&casc_ut_cctx, &index, keys, values, rep, 0);
2937  M0_UT_ASSERT(rc == -ENOMEM);
2938 
2940 }
2941 
2942 static void put_fail(void)
2943 {
2944  struct m0_bufvec keys;
2945  struct m0_bufvec values;
2946  int rc;
2947 
2948  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2949  M0_UT_ASSERT(rc == 0);
2950  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2951  M0_UT_ASSERT(rc == 0);
2952  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2953  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2954  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2955  *(uint64_t*)values.ov_buf[i] = i * i,
2956  true));
2957  put_fail_common(&keys, &values);
2958  m0_bufvec_free(&keys);
2959  m0_bufvec_free(&values);
2960 }
2961 
2962 static void put_bulk_fail(void)
2963 {
2964  struct m0_bufvec keys;
2965  struct m0_bufvec values;
2966 
2968  vals_create(COUNT, COUNT_VAL_BYTES, &values);
2969  put_fail_common(&keys, &values);
2970  m0_bufvec_free(&keys);
2971  m0_bufvec_free(&values);
2972 }
2973 
2974 static void upd(void)
2975 {
2976  struct m0_cas_rec_reply rep[COUNT];
2977  struct m0_cas_get_reply get_rep[COUNT];
2978  const struct m0_fid ifid = IFID(2, 3);
2979  struct m0_cas_id index = {};
2980  struct m0_bufvec keys;
2981  struct m0_bufvec values;
2982  int rc;
2983 
2985 
2986  M0_SET_ARR0(rep);
2987  M0_SET_ARR0(get_rep);
2988  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
2989  M0_UT_ASSERT(rc == 0);
2990  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
2991  M0_UT_ASSERT(rc == 0);
2992  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
2993  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
2994  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
2995  *(uint64_t*)values.ov_buf[i] = i * i,
2996  true));
2997  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
2998  M0_UT_ASSERT(rc == 0);
2999  index.ci_fid = ifid;
3000  /* Insert new records */
3001  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
3002  M0_UT_ASSERT(rc == 0);
3003  /* update several records */
3004  m0_forall(i, values.ov_vec.v_nr / 3,
3005  *(uint64_t*)values.ov_buf[i] = COUNT * COUNT, true);
3006  keys.ov_vec.v_nr /= 3;
3007  values.ov_vec.v_nr = keys.ov_vec.v_nr;
3008  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
3009  values.ov_vec.v_nr = keys.ov_vec.v_nr = COUNT;
3010  M0_UT_ASSERT(rc == 0);
3011  M0_UT_ASSERT(m0_forall(i, COUNT, i < values.ov_vec.v_nr / 3 ?
3012  rep[i].crr_rc == -EEXIST : rep[i].crr_rc == 0));
3013 
3014  m0_forall(i, values.ov_vec.v_nr,
3015  (*(uint64_t*)values.ov_buf[i] = 0, true));
3016  /* check selected values*/
3017  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
3018  M0_UT_ASSERT(rc == 0);
3020  *(uint64_t*)get_rep[i].cge_val.b_addr == i * i));
3021  ut_get_rep_clear(get_rep, keys.ov_vec.v_nr);
3022  m0_bufvec_free(&keys);
3023  m0_bufvec_free(&values);
3025 }
3026 
3027 static void del_common(struct m0_bufvec *keys,
3028  struct m0_bufvec *values,
3029  uint64_t version,
3030  uint64_t put_flags,
3031  uint64_t del_flags,
3032  uint64_t get_flags)
3033 {
3034  struct m0_cas_rec_reply rep;
3035  const struct m0_fid ifid = IFID(2, 3);
3036  struct m0_cas_id index = {};
3037  int rc;
3038  uint64_t del_version = version == 0 ? 0 : version + 1;
3039 
3040  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
3041  M0_UT_ASSERT(rc == 0);
3042  index.ci_fid = ifid;
3043 
3044  ut_rec_common_put_verified(&index, keys, values, version, put_flags);
3045  ut_rec_common_del_verified(&index, keys, del_version, del_flags);
3046  M0_UT_ASSERT(!has_values(&index, keys, NULL, get_flags));
3047 
3048  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
3049  M0_UT_ASSERT(rc == 0);
3050 }
3051 
3052 static void del_ver(void)
3053 {
3054  struct m0_bufvec keys;
3055  struct m0_bufvec values;
3056  int rc;
3057 
3059 
3060  rc = m0_bufvec_alloc(&keys, 1, sizeof(uint64_t));
3061  M0_UT_ASSERT(rc == 0);
3062  rc = m0_bufvec_alloc(&values, 1, sizeof(uint64_t));
3063  M0_UT_ASSERT(rc == 0);
3064  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
3065  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
3066  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3067  *(uint64_t*)values.ov_buf[i] = i * i,
3068  true));
3069  del_common(&keys, &values, 1,
3071  COF_VERSIONED,
3072  COF_VERSIONED);
3073  m0_bufvec_free(&keys);
3074  m0_bufvec_free(&values);
3075 
3077 }
3078 
3079 /*
3080  * Ensures that versions exposed by GET are visible.
3081  */
3082 static void get_ver_exposed(void)
3083 {
3084  struct m0_bufvec keys;
3085  struct m0_bufvec values;
3086  struct m0_cas_rec_reply rep;
3087  int rc;
3088  const struct m0_fid ifid = IFID(2, 3);
3089  struct m0_cas_id index = {};
3090  enum v { V_NONE, V_PAST, V_NOW, V_FUTURE, V_NR};
3091  uint64_t version[V_NR] = { 0, 1, 2, 3,};
3092 
3094 
3095  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
3096  M0_UT_ASSERT(rc == 0);
3097  index.ci_fid = ifid;
3098 
3099  rc = m0_bufvec_alloc(&keys, 1, sizeof(uint64_t));
3100  M0_UT_ASSERT(rc == 0);
3101  rc = m0_bufvec_alloc(&values, 1, sizeof(uint64_t));
3102  M0_UT_ASSERT(rc == 0);
3103  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
3104  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
3105  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3106  *(uint64_t*)values.ov_buf[i] = i * i,
3107  true));
3108 
3109  /* Insert @past */
3110  put_get_verified(&index, &keys, &values, &values, version[V_PAST],
3112  COF_VERSIONED);
3114  version[V_PAST], COF_VERSIONED));
3115 
3116  /* Delete @future */
3117  del_get_verified(&index, &keys, version[V_FUTURE],
3120  version[V_FUTURE], COF_VERSIONED));
3121 
3122  /* Cleanup */
3123  del_get_verified(&index, &keys, version[V_NONE], 0, 0);
3124 
3125  /* Delete @now */
3126  del_get_verified(&index, &keys, version[V_NOW],
3129  version[V_NOW], COF_VERSIONED));
3130  M0_UT_ASSERT(has_tombstones(&index, &keys));
3131 
3132  /* Insert @past */
3133  put_get_verified(&index, &keys, &values, NULL, version[V_PAST],
3135  COF_VERSIONED);
3137  version[V_NOW], COF_VERSIONED));
3138  M0_UT_ASSERT(has_tombstones(&index, &keys));
3139 
3140  /* Insert @future */
3141  put_get_verified(&index, &keys, &values, NULL, version[V_FUTURE],
3143  COF_VERSIONED);
3145  version[V_FUTURE], COF_VERSIONED));
3146  M0_UT_ASSERT(!has_tombstones(&index, &keys));
3147 
3148 
3149  m0_bufvec_free(&keys);
3150  m0_bufvec_free(&values);
3151 
3152  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
3153  M0_UT_ASSERT(rc == 0);
3155 }
3156 
3157 static void del(void)
3158 {
3159  struct m0_bufvec keys;
3160  struct m0_bufvec values;
3161  int rc;
3162 
3164  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3165  M0_UT_ASSERT(rc == 0);
3166  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
3167  M0_UT_ASSERT(rc == 0);
3168  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
3169  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
3170  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3171  *(uint64_t*)values.ov_buf[i] = i * i,
3172  true));
3173  del_common(&keys, &values, 0, 0, 0, 0);
3174  m0_bufvec_free(&keys);
3175  m0_bufvec_free(&values);
3177 }
3178 
3179 static void del_bulk(void)
3180 {
3181  struct m0_bufvec keys;
3182  struct m0_bufvec values;
3183 
3185  /* Bulk keys and values. */
3187  vals_create(COUNT, COUNT_VAL_BYTES, &values);
3188  del_common(&keys, &values, 0, 0, 0, 0);
3189  m0_bufvec_free(&keys);
3190  m0_bufvec_free(&values);
3192 }
3193 
3194 static void del_fail(void)
3195 {
3196  struct m0_cas_rec_reply rep[COUNT];
3197  struct m0_cas_get_reply get_rep[COUNT];
3198  const struct m0_fid ifid = IFID(2, 3);
3199  struct m0_cas_id index = {};
3200  struct m0_bufvec keys;
3201  struct m0_bufvec values;
3202  int rc;
3203 
3205 
3206  M0_SET_ARR0(rep);
3207  M0_SET_ARR0(get_rep);
3208  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3209  M0_UT_ASSERT(rc == 0);
3210  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
3211  M0_UT_ASSERT(rc == 0);
3212  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
3213  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
3214  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3215  *(uint64_t*)values.ov_buf[i] = i * i,
3216  true));
3217  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
3218  M0_UT_ASSERT(rc == 0);
3219  index.ci_fid = ifid;
3220  /* Insert new records */
3221  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
3222  M0_UT_ASSERT(rc == 0);
3223  /* Delete all records */
3224  m0_fi_enable_once("creq_op_alloc", "cas_alloc_fail");
3225  rc = ut_rec_del(&casc_ut_cctx, &index, &keys, rep, 0);
3226  M0_UT_ASSERT(rc == -ENOMEM);
3227  m0_fi_enable_once("ctg_kbuf_get", "cas_alloc_fail");
3228  rc = ut_rec_del(&casc_ut_cctx, &index, &keys, rep, 0);
3229  M0_UT_ASSERT(rc == -ENOMEM);
3230  /* check selected values - must be empty*/
3231  m0_forall(i, values.ov_vec.v_nr,
3232  (*(uint64_t*)values.ov_buf[i] = 0, true));
3233  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
3234  M0_UT_ASSERT(rc == 0);
3235  M0_UT_ASSERT(m0_forall(i, COUNT, get_rep[i].cge_rc == 0));
3236  ut_get_rep_clear(get_rep, COUNT);
3237  m0_bufvec_free(&keys);
3238  m0_bufvec_free(&values);
3240 }
3241 
3242 static void del_n(void)
3243 {
3244  struct m0_cas_rec_reply rep[COUNT];
3245  struct m0_cas_get_reply get_rep[COUNT];
3246  const struct m0_fid ifid = IFID(2, 3);
3247  struct m0_cas_id index = {};
3248  struct m0_bufvec keys;
3249  struct m0_bufvec values;
3250  int rc;
3251 
3253 
3254  M0_SET_ARR0(rep);
3255  M0_SET_ARR0(get_rep);
3256  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3257  M0_UT_ASSERT(rc == 0);
3258  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
3259  M0_UT_ASSERT(rc == 0);
3260  M0_UT_ASSERT(keys.ov_vec.v_nr != 0);
3261  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
3262  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
3263  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3264  *(uint64_t*)values.ov_buf[i] = i * i,
3265  true));
3266  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
3267  M0_UT_ASSERT(rc == 0);
3268  index.ci_fid = ifid;
3269  /* Insert new records */
3270  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
3271  M0_UT_ASSERT(rc == 0);
3272  /* Delete several records */
3273  keys.ov_vec.v_nr /= 3;
3274  rc = ut_rec_del(&casc_ut_cctx, &index, &keys, rep, 0);
3275  M0_UT_ASSERT(rc == 0);
3276  /* restore old count value */
3277  keys.ov_vec.v_nr = COUNT;
3278  /* check selected values - some records not found*/
3279  m0_forall(i, values.ov_vec.v_nr,
3280  (*(uint64_t*)values.ov_buf[i] = 0, true));
3281  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
3282  M0_UT_ASSERT(rc == 0);
3284  (i < COUNT / 3) ? get_rep[i].cge_rc == -ENOENT :
3285  rep[i].crr_rc == 0 &&
3286  *(uint64_t*)get_rep[i].cge_val.b_addr == i * i));
3287  ut_get_rep_clear(get_rep, COUNT);
3288  m0_bufvec_free(&keys);
3289  m0_bufvec_free(&values);
3291 }
3292 
3293 static void null_value(void)
3294 {
3295  struct m0_cas_rec_reply rep[COUNT];
3296  struct m0_cas_get_reply get_rep[COUNT];
3297  struct m0_cas_next_reply next_rep[COUNT];
3298  const struct m0_fid ifid = IFID(2, 3);
3299  struct m0_cas_id index = {};
3300  struct m0_bufvec keys;
3301  struct m0_bufvec values;
3302  struct m0_bufvec start_key;
3303  uint32_t recs_nr;
3304  uint64_t rep_count;
3305  int rc;
3306 
3308 
3309  M0_SET_ARR0(rep);
3310  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3311  M0_UT_ASSERT(rc == 0);
3312  rc = m0_bufvec_empty_alloc(&values, COUNT);
3313  M0_UT_ASSERT(rc == 0);
3314  m0_forall(i, keys.ov_vec.v_nr, *(uint64_t*)keys.ov_buf[i] = i, true);
3315  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
3316  M0_UT_ASSERT(rc == 0);
3317  index.ci_fid = ifid;
3318 
3319  /* Insert new records with empty (NULL) values. */
3320  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
3321  M0_UT_ASSERT(rc == 0);
3322 
3323  /* Get inserted records through 'GET' request. */
3324  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
3325  M0_UT_ASSERT(rc == 0);
3327  (get_rep[i].cge_rc == 0 &&
3328  get_rep[i].cge_val.b_addr == NULL &&
3329  get_rep[i].cge_val.b_nob == 0)));
3330 
3331  /* Get inserted records through 'NEXT' request. */
3332  rc = m0_bufvec_alloc(&start_key, 1, keys.ov_vec.v_count[0]);
3333  M0_UT_ASSERT(rc == 0);
3334  recs_nr = COUNT;
3335  value_create(start_key.ov_vec.v_count[0], 0, start_key.ov_buf[0]);
3336  rc = ut_next_rec(&casc_ut_cctx, &index, &start_key, &recs_nr, next_rep,
3337  &rep_count, 0);
3338  M0_UT_ASSERT(rc == 0);
3339  M0_UT_ASSERT(rc == 0);
3340  M0_UT_ASSERT(rep_count == recs_nr);
3341  M0_UT_ASSERT(m0_forall(i, rep_count, next_rep[i].cnp_rc == 0));
3342  M0_UT_ASSERT(m0_forall(i, rep_count,
3343  next_rep_equals(&next_rep[i],
3344  keys.ov_buf[i],
3345  values.ov_buf[i])));
3346  m0_bufvec_free(&start_key);
3347 
3348  /* Delete records. */
3349  rc = ut_rec_del(&casc_ut_cctx, &index, &keys, rep, 0);
3350  M0_UT_ASSERT(rc == 0);
3351  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
3352 
3353  m0_bufvec_free(&keys);
3354  m0_bufvec_free(&values);
3356 }
3357 
3358 static void get_common(struct m0_bufvec *keys, struct m0_bufvec *values)
3359 {
3360  struct m0_cas_rec_reply rep[COUNT];
3361  struct m0_cas_get_reply get_rep[COUNT];
3362  const struct m0_fid ifid = IFID(2, 3);
3363  struct m0_cas_id index = {};
3364  int rc;
3365 
3366  M0_SET_ARR0(rep);
3367  M0_SET_ARR0(get_rep);
3368 
3369  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
3370  M0_UT_ASSERT(rc == 0);
3371  M0_UT_ASSERT(rep[0].crr_rc == 0);
3372  index.ci_fid = ifid;
3373  /* Insert new records */
3374  rc = ut_rec_put(&casc_ut_cctx, &index, keys, values, rep, 0);
3375  M0_UT_ASSERT(rc == 0);
3376  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
3377 
3378  /* check selected values */
3379  rc = ut_rec_get(&casc_ut_cctx, &index, keys, get_rep);
3380  M0_UT_ASSERT(rc == 0);
3382  memcmp(get_rep[i].cge_val.b_addr,
3383  values->ov_buf[i],
3384  values->ov_vec.v_count[i] ) == 0));
3385  ut_get_rep_clear(get_rep, keys->ov_vec.v_nr);
3386 
3387  /* Remove index. */
3388  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
3389  M0_UT_ASSERT(rc == 0);
3390 }
3391 
3392 static void get(void)
3393 {
3394  struct m0_bufvec keys;
3395  struct m0_bufvec values;
3396  int rc;
3397 
3399  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3400  M0_UT_ASSERT(rc == 0);
3401  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
3402  M0_UT_ASSERT(rc == 0);
3403  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
3404  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
3405  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3406  *(uint64_t*)values.ov_buf[i] = i * i,
3407  true));
3408  get_common(&keys, &values);
3409  m0_bufvec_free(&keys);
3410  m0_bufvec_free(&values);
3412 }
3413 
3414 static void get_bulk(void)
3415 {
3416  struct m0_bufvec keys;
3417  struct m0_bufvec values;
3418  int rc;
3419 
3421  /* Bulk keys and values. */
3423  vals_create(COUNT, COUNT_VAL_BYTES, &values);
3424  get_common(&keys, &values);
3425  m0_bufvec_free(&keys);
3426  m0_bufvec_free(&values);
3427 
3428  /* Bulk values. */
3429  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3430  M0_UT_ASSERT(rc == 0);
3431  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i, true));
3432  vals_create(COUNT, COUNT_VAL_BYTES, &values);
3433  get_common(&keys, &values);
3434  m0_bufvec_free(&keys);
3435  m0_bufvec_free(&values);
3436 
3437  /* Bulk keys. */
3439  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
3440  M0_UT_ASSERT(rc == 0);
3441  m0_forall(i, values.ov_vec.v_nr, (*(uint64_t*)values.ov_buf[i] = i,
3442  true));
3443  get_common(&keys, &values);
3444  m0_bufvec_free(&keys);
3445  m0_bufvec_free(&values);
3446 
3447  /* Bulk mix. */
3449  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
3450  M0_UT_ASSERT(rc == 0);
3451  m0_forall(i, values.ov_vec.v_nr, (*(uint64_t*)values.ov_buf[i] = i,
3452  true));
3453  get_common(&keys, &values);
3454  m0_bufvec_free(&keys);
3455  m0_bufvec_free(&values);
3456 
3457  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3458  M0_UT_ASSERT(rc == 0);
3459  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3460  true));
3462  get_common(&keys, &values);
3463  m0_bufvec_free(&keys);
3464  m0_bufvec_free(&values);
3466 }
3467 
3468 static void get_fail(void)
3469 {
3470  struct m0_cas_rec_reply rep[COUNT];
3471  struct m0_cas_get_reply get_rep[COUNT];
3472  const struct m0_fid ifid = IFID(2, 3);
3473  struct m0_cas_id index = {};
3474  struct m0_bufvec keys;
3475  struct m0_bufvec values;
3476  int rc;
3477 
3479 
3480  M0_SET_ARR0(rep);
3481  M0_SET_ARR0(get_rep);
3482  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3483  M0_UT_ASSERT(rc == 0);
3484  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
3485  M0_UT_ASSERT(rc == 0);
3486  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
3487  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
3488  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3489  *(uint64_t*)values.ov_buf[i] = i * i,
3490  true));
3491  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
3492  M0_UT_ASSERT(rc == 0);
3493  index.ci_fid = ifid;
3494  /* Insert new records */
3495  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
3496  M0_UT_ASSERT(rc == 0);
3497 
3498  m0_forall(i, values.ov_vec.v_nr / 3,
3499  (*(uint64_t*)values.ov_buf[i] = 0, true));
3500  /* check selected values */
3501  m0_fi_enable_once("creq_op_alloc", "cas_alloc_fail");
3502  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
3503  M0_UT_ASSERT(rc == -ENOMEM);
3504  m0_fi_enable_once("ctg_kbuf_get", "cas_alloc_fail");
3505  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
3506  M0_UT_ASSERT(rc == -ENOMEM);
3507  m0_bufvec_free(&keys);
3508  m0_bufvec_free(&values);
3510 }
3511 
3512 static void recs_count(void)
3513 {
3514  struct m0_cas_rec_reply rep[COUNT];
3515  const struct m0_fid ifid = IFID(2, 3);
3516  struct m0_cas_id index = {};
3517  struct m0_bufvec keys;
3518  struct m0_bufvec values;
3519  int rc;
3520 
3522  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3523  M0_UT_ASSERT(rc == 0);
3524  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
3525  M0_UT_ASSERT(rc == 0);
3526  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
3527  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
3528  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3529  *(uint64_t*)values.ov_buf[i] = i * i,
3530  true));
3531  M0_SET_ARR0(rep);
3532  M0_UT_ASSERT(m0_ctg_rec_nr() == 0);
3533  M0_UT_ASSERT(m0_ctg_rec_size() == 0);
3534  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
3535  M0_UT_ASSERT(rc == 0);
3536  index.ci_fid = ifid;
3537  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
3538  M0_UT_ASSERT(rc == 0);
3540  M0_UT_ASSERT(m0_ctg_rec_size() == COUNT * 2 * sizeof(uint64_t));
3541  rc = ut_rec_del(&casc_ut_cctx, &index, &keys, rep, 0);
3542  M0_UT_ASSERT(rc == 0);
3543  M0_UT_ASSERT(m0_ctg_rec_nr() == 0);
3544  /* Currently total size of records is not decremented on deletion. */
3545  M0_UT_ASSERT(m0_ctg_rec_size() == COUNT * 2 * sizeof(uint64_t));
3546 
3547  /*
3548  * Check total records size overflow.
3549  * The total records size in this case should stick to ~0ULL.
3550  */
3551  m0_fi_enable_off_n_on_m("ctg_state_update", "test_overflow", 1, 1);
3552  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
3553  m0_fi_disable("ctg_state_update", "test_overflow");
3554  M0_UT_ASSERT(rc == 0);
3556  M0_UT_ASSERT(m0_ctg_rec_size() == ~0ULL);
3557  /* Remove index. */
3558  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
3559  M0_UT_ASSERT(rc == 0);
3560  m0_bufvec_free(&keys);
3561  m0_bufvec_free(&values);
3563 }
3564 
3565 static void reply_too_large(void)
3566 {
3567  struct m0_bufvec keys;
3568  struct m0_bufvec values;
3569  struct m0_cas_rec_reply rep[COUNT];
3570  struct m0_cas_get_reply get_rep[COUNT];
3571  struct m0_cas_next_reply next_rep[COUNT];
3572  const struct m0_fid ifid = IFID(2, 3);
3573  struct m0_bufvec start_key;
3574  uint32_t recs_nr;
3575  uint64_t rep_count;
3576  struct m0_cas_id index = {};
3577  int rc;
3578 
3580  rc = m0_bufvec_alloc(&keys, COUNT, sizeof(uint64_t));
3581  M0_UT_ASSERT(rc == 0);
3582  rc = m0_bufvec_alloc(&values, COUNT, sizeof(uint64_t));
3583  M0_UT_ASSERT(rc == 0);
3584  M0_UT_ASSERT(keys.ov_vec.v_nr == COUNT);
3585  M0_UT_ASSERT(keys.ov_vec.v_nr == values.ov_vec.v_nr);
3586  m0_forall(i, keys.ov_vec.v_nr, (*(uint64_t*)keys.ov_buf[i] = i,
3587  *(uint64_t*)values.ov_buf[i] = i * i,
3588  true));
3589  M0_SET_ARR0(rep);
3590  M0_SET_ARR0(get_rep);
3591 
3592  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, rep);
3593  M0_UT_ASSERT(rc == 0);
3594  M0_UT_ASSERT(rep[0].crr_rc == 0);
3595  index.ci_fid = ifid;
3596  /* Insert new records */
3597  rc = ut_rec_put(&casc_ut_cctx, &index, &keys, &values, rep, 0);
3598  M0_UT_ASSERT(rc == 0);
3599  M0_UT_ASSERT(m0_forall(i, COUNT, rep[i].crr_rc == 0));
3600 
3601  m0_fi_enable_off_n_on_m("m0_rpc_item_max_payload_exceeded",
3602  "payload_too_large1", 1, 1);
3603  rc = ut_rec_get(&casc_ut_cctx, &index, &keys, get_rep);
3604  M0_UT_ASSERT(rc == -E2BIG);
3605 
3606  M0_SET_ARR0(next_rep);
3607  rc = m0_bufvec_alloc(&start_key, 1, keys.ov_vec.v_count[0]);
3608  M0_UT_ASSERT(rc == 0);
3609  /* perform next for all records */
3610  recs_nr = COUNT;
3611  value_create(start_key.ov_vec.v_count[0], 0, start_key.ov_buf[0]);
3612  rc = ut_next_rec(&casc_ut_cctx, &index, &start_key, &recs_nr, next_rep,
3613  &rep_count, 0);
3614  M0_UT_ASSERT(rc == -E2BIG);
3615  m0_fi_disable("m0_rpc_item_max_payload_exceeded", "payload_too_large1");
3616 
3617  /* Remove index. */
3618  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, rep);
3619  M0_UT_ASSERT(rc == 0);
3620 
3621  m0_bufvec_free(&keys);
3622  m0_bufvec_free(&values);
3624 }
3625 
3627  PAST = 2,
3628  FUTURE = 3,
3629 };
3630 
3632  /* No value at all. */
3634  /* New value was not inserted. */
3636  /* Old value was replaced by the new value. */
3638 };
3639 
3640 enum named_op {
3644 };
3645 
3646 /* PUT or DEL operation with a human-readable version description. */
3647 struct cas_ver_op {
3649  enum named_op op;
3650  const struct m0_bufvec *keys;
3651  const struct m0_bufvec *values;
3652 };
3653 
3655  /* An operation to be executed first. */
3657  /* Second operation that happen right after the first one. */
3659 };
3660 
3661 static void cas_ver_op_execute(const struct cas_ver_op *cvop,
3662  struct m0_cas_id *index)
3663 {
3664  switch (cvop->op) {
3665  case PUT:
3667  cvop->ver,
3669  break;
3670  case DEL:
3671  ut_rec_common_del_verified(index, cvop->keys, cvop->ver,
3672  COF_VERSIONED);
3673  break;
3674  case NOP:
3675  /* Nothing to do. */
3676  break;
3677  }
3678 }
3679 
3680 static void put_del_ver_case_execute(const struct put_del_ver_case *c,
3681  struct m0_cas_id *index)
3682 {
3683  cas_ver_op_execute(&c->before, index);
3684  cas_ver_op_execute(&c->after, index);
3685 }
3686 
3687 /*
3688  * The function verifies the following properties:
3689  * Put a tombstone:
3690  * DEL@version
3691  * has_tombstone => true
3692  * Put some old version:
3693  * PUT@(version - 1)
3694  * has_tombstone => true
3695  * Put some new version:
3696  * PUT@(version + 1)
3697  * has_tombstone => false.
3698  */
3700  const struct m0_bufvec *keys,
3701  uint64_t version)
3702 {
3703  int rc;
3704  struct m0_cas_get_reply *get_rep;
3705  struct m0_bufvec values;
3706  bool tombstones;
3707 
3708  M0_ALLOC_ARR(get_rep, keys->ov_vec.v_nr);
3709  M0_UT_ASSERT(get_rep != NULL);
3710 
3711  /* Save the existing values. */
3712  rc = ut_rec__get(&casc_ut_cctx, index, keys, get_rep, 0);
3713  M0_UT_ASSERT(rc == 0);
3715  get_rep[i].cge_rc == 0));
3716  rc = get_reply2bufvec(get_rep, keys->ov_vec.v_nr, &values);
3717  M0_UT_ASSERT(rc == 0);
3718  m0_free(get_rep);
3719  /* Save the existing tombstones (assuming all-or-nothing). */
3720  tombstones = has_tombstones(index, keys);
3721 
3724 
3725  ut_rec_common_put_verified(index, keys, &values, version - 1,
3728 
3729  ut_rec_common_put_verified(index, keys, &values, version + 1,
3732 
3733  /* Restore the existing values. */
3734  ut_rec_common_del_verified(index, keys, 0, 0);
3735  ut_rec_common_put_verified(index, keys, &values, version,
3738  /* Restore the existing tombstones. */
3739  if (tombstones) {
3741  COF_VERSIONED);
3743  }
3744 }
3745 
3746 static enum named_outcome outcome(const struct put_del_ver_case *c)
3747 {
3748  const struct cas_ver_op *before = &c->before;
3749  const struct cas_ver_op *after = &c->after;
3750  const struct cas_ver_op *winner;
3751 
3752  /* Get the operation with the "latest" version. */
3753  if (before->ver == FUTURE)
3754  winner = before;
3755  else if (after->ver == FUTURE)
3756  winner = after;
3757  else
3758  M0_IMPOSSIBLE("Did you forget to add an op with FUTURE?");
3759 
3760  if (winner->op == DEL)
3761  return TOMBSTONE;
3762  else if (winner == before)
3763  return PRESERVED;
3764  else
3765  return OVERWRITTEN;
3766 }
3767 
3768 static void put_del_ver_case_verify(const struct put_del_ver_case *c,
3769  struct m0_cas_id *index)
3770 {
3771  const struct m0_bufvec *keys = c->before.keys;
3772  const struct m0_bufvec *before_values = c->before.values;
3773  const struct m0_bufvec *after_values = c->after.values;
3774 
3775  switch (outcome(c)) {
3776  case TOMBSTONE:
3778  M0_UT_ASSERT(!has_values(index, keys, before_values,
3779  COF_VERSIONED));
3780  M0_UT_ASSERT(!has_values(index, keys, after_values,
3781  COF_VERSIONED));
3782  break;
3783  case OVERWRITTEN:
3785  /*
3786  * The values should be overwritten no matter what behavior we
3787  * have specified.
3788  */
3789  M0_UT_ASSERT(has_values(index, keys, after_values, 0));
3790  M0_UT_ASSERT(has_values(index, keys, after_values,
3791  COF_VERSIONED));
3792  M0_UT_ASSERT(!has_values(index, keys, before_values, 0));
3793  M0_UT_ASSERT(!has_values(index, keys, before_values,
3794  COF_VERSIONED));
3795  break;
3796  case PRESERVED:
3798  /*
3799  * The values should be preserved, and it should be visible
3800  * even if the versioned behavior was not requested by GET
3801  * operation.
3802  */
3803  M0_UT_ASSERT(has_values(index, keys, before_values, 0));
3804  M0_UT_ASSERT(has_values(index, keys, before_values,
3805  COF_VERSIONED));
3806  M0_UT_ASSERT(!has_values(index, keys, after_values, 0));
3807  M0_UT_ASSERT(!has_values(index, keys, after_values,
3808  COF_VERSIONED));
3809  break;
3810  }
3811 
3814 }
3815 
3816 static void put_del_ver(void)
3817 {
3818  const uint64_t key = 1;
3819  const uint64_t before_value = 1;
3820  const uint64_t after_value = 2;
3821  const m0_bcount_t nr_bytes = sizeof(key);
3822  const void *key_data = &key;
3823  const void *before_val_data = &before_value;
3824  const void *after_val_data = &after_value;
3825  const struct m0_bufvec keys =
3826  M0_BUFVEC_INIT_BUF((void **) &key_data,
3827  (m0_bcount_t *) &nr_bytes);
3828  const struct m0_bufvec before_values =
3829  M0_BUFVEC_INIT_BUF((void **) &before_val_data,
3830  (m0_bcount_t *) &nr_bytes);
3831  const struct m0_bufvec after_values =
3832  M0_BUFVEC_INIT_BUF((void **) &after_val_data,
3833  (m0_bcount_t *) &nr_bytes);
3834 
3835 #define BEFORE(_what, _when) \
3836  .before = { \
3837  .ver = _when, \
3838  .op = _what, \
3839  .keys = &keys, \
3840  .values = &before_values, \
3841  },
3842 
3843 #define AFTER(_what, _when) \
3844  .after = { \
3845  .ver = _when, \
3846  .op = _what, \
3847  .keys = &keys, \
3848  .values = &after_values, \
3849  },
3850 
3851  const struct put_del_ver_case cases[] = {
3852  { BEFORE(PUT, PAST) AFTER(DEL, FUTURE) },
3853  { BEFORE(PUT, PAST) AFTER(PUT, FUTURE) },
3854 
3855  { BEFORE(PUT, FUTURE) AFTER(PUT, PAST) },
3856  { BEFORE(PUT, FUTURE) AFTER(DEL, PAST) },
3857 
3858  { BEFORE(DEL, FUTURE) AFTER(DEL, PAST) },
3859  { BEFORE(DEL, FUTURE) AFTER(PUT, PAST) },
3860 
3861  { BEFORE(DEL, PAST) AFTER(DEL, FUTURE) },
3862  { BEFORE(DEL, PAST) AFTER(PUT, FUTURE) },
3863 
3864  { BEFORE(NOP, PAST) AFTER(DEL, FUTURE) },
3865  { BEFORE(NOP, PAST) AFTER(PUT, FUTURE) },
3866  };
3867 #undef BEFORE
3868 #undef AFTER
3869 #undef OUTCOME
3870 
3871  int rc;
3872  int i;
3873  struct m0_cas_id index = {};
3874  struct m0_cas_rec_reply rep;
3875  const struct m0_fid ifid = IFID(2, 3);
3876 
3878  rc = ut_idx_create(&casc_ut_cctx, &ifid, 1, &rep);
3879  M0_UT_ASSERT(rc == 0);
3880  index.ci_fid = ifid;
3881 
3882  for (i = 0; i < ARRAY_SIZE(cases); ++i) {
3885  ut_rec_common_del_verified(&index, cases[i].before.keys, 0, 0);
3886  }
3887 
3888  rc = ut_idx_delete(&casc_ut_cctx, &ifid, 1, &rep);
3889  M0_UT_ASSERT(rc == 0);
3891 }
3892 
3894  .ts_name = "cas-client",
3895  .ts_owners = "Leonid",
3896  .ts_init = NULL,
3897  .ts_fini = NULL,
3898  .ts_tests = {
3899  { "idx-create", idx_create, "Leonid" },
3900  { "idx-create-fail", idx_create_fail, "Leonid" },
3901  { "idx-create-async", idx_create_a, "Leonid" },
3902  { "idx-delete", idx_delete, "Leonid" },
3903  { "idx-delete-fail", idx_delete_fail, "Leonid" },
3904  { "idx-delete-non-exist", idx_delete_non_exist, "Sergey" },
3905  { "idx-createN", idx_create_n, "Leonid" },
3906  { "idx-deleteN", idx_delete_n, "Leonid" },
3907  { "idx-list", idx_list, "Leonid" },
3908  { "idx-list-fail", idx_list_fail, "Leonid" },
3909  { "next", next, "Leonid" },
3910  { "next-fail", next_fail, "Leonid" },
3911  { "next-multi", next_multi, "Egor" },
3912  { "next-bulk", next_bulk, "Leonid" },
3913  { "next-multi-bulk", next_multi_bulk, "Leonid" },
3914  { "put", put, "Leonid" },
3915  { "put-bulk", put_bulk, "Leonid" },
3916  { "put-create", put_create, "Sergey" },
3917  { "put-overwrite", put_overwrite, "Sergey" },
3918  { "put-crow", put_crow, "Sergey" },
3919  { "put-fail", put_fail, "Leonid" },
3920  { "put-bulk-fail", put_bulk_fail, "Leonid" },
3921  { "put-crow-fail", put_crow_fail, "Sergey" },
3922  { "get", get, "Leonid" },
3923  { "get-bulk", get_bulk, "Leonid" },
3924  { "get-fail", get_fail, "Leonid" },
3925  { "upd", upd, "Leonid" },
3926  { "del", del, "Leonid" },
3927  { "del-bulk", del_bulk, "Leonid" },
3928  { "del-fail", del_fail, "Leonid" },
3929  { "delN", del_n, "Leonid" },
3930  { "null-value", null_value, "Egor" },
3931  { "idx-tree-insert", idx_tree_insert, "Leonid" },
3932  { "idx-tree-delete", idx_tree_delete, "Leonid" },
3933  { "idx-tree-delete-fail", idx_tree_delete_fail, "Leonid" },
3934  { "recs-count", recs_count, "Leonid" },
3935  { "reply-too-large", reply_too_large, "Sergey" },
3936  { "recs-fragm", recs_fragm, "Sergey" },
3937  { "recs_fragm_fail", recs_fragm_fail, "Sergey" },
3938  { "put-ver", put_ver, "Ivan" },
3939  { "put-overwrite-ver", put_overwrite_ver, "Ivan" },
3940  { "del-ver", del_ver, "Ivan" },
3941  { "next-ver", next_ver, "Ivan" },
3942  { "put-del-ver", put_del_ver, "Ivan" },
3943  { "next-ver-exposed", next_ver_exposed, "Ivan" },
3944  { "get-ver-exposed", get_ver_exposed, "Ivan" },
3945  { NULL, NULL }
3946  }
3947 };
3948 
3949 #undef M0_TRACE_SUBSYSTEM
3950 
3953 /*
3954  * Local variables:
3955  * c-indentation-style: "K&R"
3956  * c-basic-offset: 8
3957  * tab-width: 8
3958  * fill-column: 80
3959  * scroll-step: 1
3960  * End:
3961  */
3962 /*
3963  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
3964  */
static const char * srv_ep_addr
Definition: idx_dix.c:72
static int ut_rec_common_del(struct cl_ctx *cctx, struct m0_cas_id *index, const struct m0_bufvec *keys, struct m0_dtx *dtx, struct m0_cas_rec_reply *rep, uint64_t flags)
Definition: client_ut.c:673
#define M0_BUFVEC_INIT_BUF(addr_ptr, count_ptr)
Definition: vec.h:165
struct async_wait cl_wait
Definition: client_ut.c:78
bool aw_done
Definition: client_ut.c:69
static void next(void)
Definition: client_ut.c:1977
static void idx_tree_insert(void)
Definition: client_ut.c:935
M0_INTERNAL int m0_dtm0_tx_desc_init(struct m0_dtm0_tx_desc *td, uint32_t nr_pa)
Definition: tx_desc.c:97
static size_t nr
Definition: dump.c:1505
static int ut_idx_delete(struct cl_ctx *cctx, const struct m0_fid *ids, uint64_t ids_nr, struct m0_cas_rec_reply *rep)
Definition: client_ut.c:389
static void put_del_ver_case_execute(const struct put_del_ver_case *c, struct m0_cas_id *index)
Definition: client_ut.c:3680
struct m0_dtm0_dtx * tx_dtx
Definition: dtm.h:563
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
Definition: dtm.h:554
struct m0_clink aw_clink
Definition: client_ut.c:67
struct m0_dtx dd_ancient_dtx
Definition: dtx.h:59
void m0_net_domain_fini(struct m0_net_domain *dom)
Definition: domain.c:71
static void idx_create_n(void)
Definition: client_ut.c:819
static void put_create(void)
Definition: client_ut.c:2815
static void get_fail(void)
Definition: client_ut.c:3468
static void recs_fragm_fail(void)
Definition: client_ut.c:2614
static void put_bulk_fail(void)
Definition: client_ut.c:2962
int const char const void size_t int flags
Definition: dir.c:328
const struct m0_tl_descr ndoms_descr
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
static void put_overwrite(void)
Definition: client_ut.c:2823
static void recs_fragm(void)
Definition: client_ut.c:2475
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
named_version
Definition: client_ut.c:3626
static void idx_list_fail(void)
Definition: client_ut.c:1180
Definition: idx_mock.c:52
M0_INTERNAL int m0_cas_index_list(struct m0_cas_req *req, const struct m0_fid *start_fid, uint32_t indices_nr, uint32_t flags)
Definition: client.c:1435
#define ergo(a, b)
Definition: misc.h:293
static void put_del_ver(void)
Definition: client_ut.c:3816
static void del_get_verified(struct m0_cas_id *index, struct m0_bufvec *keys, uint64_t version, uint64_t del_flags, uint64_t get_flags)
Definition: client_ut.c:1670
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
void * b_addr
Definition: buf.h:39
static void next_multi_common(struct m0_bufvec *keys, struct m0_bufvec *values)
Definition: client_ut.c:2158
static void reply_too_large(void)
Definition: client_ut.c:3565
static void vals_create(int count, int size, struct m0_bufvec *vals)
Definition: client_ut.c:143
static struct io_request req
Definition: file.c:100
M0_INTERNAL bool m0_semaphore_timeddown(struct m0_semaphore *semaphore, const m0_time_t abs_timeout)
Definition: semaphore.c:75
char ** rsx_argv
Definition: rpclib.h:77
static void del_n(void)
Definition: client_ut.c:3242
static enum named_outcome outcome(const struct put_del_ver_case *c)
Definition: client_ut.c:3746
#define M0_CASSERT(cond)
int m0_rpc_server_start(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:50
static void idx_delete_fail(void)
Definition: client_ut.c:859
M0_INTERNAL uint64_t m0_ctg_rec_nr(void)
Definition: ctg_store.c:2145
Definition: cas.h:247
struct m0_vec ov_vec
Definition: vec.h:147
static void put_ver(void)
Definition: client_ut.c:2423
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
struct cas_ver_op after
Definition: client_ut.c:3658
struct m0_rpc_client_ctx cl_rpc_ctx
Definition: client_ut.c:77
static void next_ver_exposed(void)
Definition: client_ut.c:1864
M0_INTERNAL const struct m0_fid m0_cas_meta_fid
Definition: cas.c:146
struct m0_dtm0_ts dti_ts
Definition: tx_desc.h:94
struct m0_fid ci_fid
Definition: cas.h:288
static void put_save_common(uint32_t flags)
Definition: client_ut.c:2739
static struct m0_rpc_client_ctx cctx
Definition: rconfc.c:69
#define AFTER(_what, _when)
static bool has_tombstones(struct m0_cas_id *index, const struct m0_bufvec *keys)
Definition: client_ut.c:1443
static void next_multi(void)
Definition: client_ut.c:2215
M0_INTERNAL void m0_cas_index_create_rep(const struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1357
#define m0_exists(var, nr,...)
Definition: misc.h:134
#define M0_BITS(...)
Definition: misc.h:236
uint64_t m0_bcount_t
Definition: types.h:77
static int left
Definition: locality.c:280
M0_INTERNAL int m0_pageshift_get(void)
Definition: memory.c:238
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SRC_PATH(name)
Definition: misc.h:48
#define M0_SET0(obj)
Definition: misc.h:64
Definition: ut.h:77
struct m0_fop_getxattr_rep * rep
Definition: dir.c:455
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 void put_bulk(void)
Definition: client_ut.c:2681
static void null_value(void)
Definition: client_ut.c:3293
Definition: sock.c:887
static m0_bcount_t count
Definition: xcode.c:167
M0_INTERNAL int m0_bufvec_cursor_cmp(struct m0_bufvec_cursor *c0, struct m0_bufvec_cursor *c1)
Definition: vec.c:639
static void del_fail(void)
Definition: client_ut.c:3194
static const char * cl_ep_addr
Definition: pool_trigger.c:49
struct m0_buf cnp_val
Definition: client.h:223
static bool casc_chan_cb(struct m0_clink *clink)
Definition: client_ut.c:236
M0_INTERNAL void m0_cas_req_unlock(struct m0_cas_req *req)
Definition: client.c:229
int m0_bufvec_alloc_aligned(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size, unsigned shift)
Definition: vec.c:355
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
static void ut_dtx_fini(struct m0_dtx *dtx)
Definition: client_ut.c:462
op
Definition: libdemo.c:64
struct m0_dtm0_tid dtd_id
Definition: tx_desc.h:121
static struct cl_ctx casc_ut_cctx
Definition: client_ut.c:98
M0_INTERNAL void m0_bufvec_free(struct m0_bufvec *bufvec)
Definition: vec.c:395
m0_time_t dts_phys
Definition: clk_src.h:93
static void idx_list(void)
Definition: client_ut.c:1108
named_op
Definition: client_ut.c:3640
static void del_bulk(void)
Definition: client_ut.c:3179
int i
Definition: dir.c:1033
enum named_op op
Definition: client_ut.c:3649
#define M0_SET_ARR0(arr)
Definition: misc.h:72
static void upd(void)
Definition: client_ut.c:2974
static int ut_idx_crdel_wrp(enum idx_operation op, struct cl_ctx *cctx, const struct m0_fid *ids, uint64_t ids_nr, m0_chan_cb_t cb, struct m0_cas_rec_reply *rep, uint32_t flags)
Definition: client_ut.c:250
static int ut_rec_del(struct cl_ctx *cctx, struct m0_cas_id *index, const struct m0_bufvec *keys, struct m0_cas_rec_reply *rep, uint64_t flags)
Definition: client_ut.c:740
return M0_ERR(-EOPNOTSUPP)
static int ut_idx_create_async(struct cl_ctx *cctx, const struct m0_fid *ids, uint64_t ids_nr, m0_chan_cb_t cb, struct m0_cas_rec_reply *rep)
Definition: client_ut.c:317
M0_INTERNAL int m0_cas_req_generic_rc(const struct m0_cas_req *req)
Definition: client.c:457
string version
Definition: conf.py:40
static void get_ver_exposed(void)
Definition: client_ut.c:3082
static void del(void)
Definition: client_ut.c:3157
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 next_bulk(void)
Definition: client_ut.c:2054
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
Definition: cas.h:264
M0_INTERNAL struct m0_dtm0_ts m0_crv_ts(const struct m0_crv *crv)
Definition: cas.c:238
M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
Definition: finject.c:485
static void idx_delete_non_exist(void)
Definition: client_ut.c:886
static void put(void)
Definition: client_ut.c:2450
#define M0_NET_XPRT_PREFIX_DEFAULT
Definition: net.h:98
M0_INTERNAL int m0_cas_next(struct m0_cas_req *req, struct m0_cas_id *index, struct m0_bufvec *start_keys, uint32_t *recs_nr, uint32_t flags)
Definition: client.c:1775
M0_INTERNAL int m0_cas_versioned_get(struct m0_cas_req *req, struct m0_cas_id *index, const struct m0_bufvec *keys)
Definition: client.c:1748
Definition: cas.h:157
static void value_create(int size, int num, char *buf)
Definition: client_ut.c:129
#define M0_BUFVEC_SLICE(__bufvec, __idx)
Definition: client_ut.c:1702
m0_bcount_t b_nob
Definition: buf.h:38
static void ut_next_rep_clear(struct m0_cas_next_reply *rep, uint64_t nr)
Definition: client_ut.c:614
named_outcome
Definition: client_ut.c:3631
const struct m0_bufvec * values
Definition: client_ut.c:3651
M0_INTERNAL void m0_cas_next_rep(const struct m0_cas_req *req, uint32_t idx, struct m0_cas_next_reply *rep)
Definition: client.c:1825
static void casc_ut_init(struct m0_rpc_server_ctx *sctx, struct cl_ctx *cctx)
Definition: client_ut.c:213
static void casc_ut_fini(struct m0_rpc_server_ctx *sctx, struct cl_ctx *cctx)
Definition: client_ut.c:228
static struct m0_addb2_callback c
Definition: consumer.c:41
static void put_get_verified(struct m0_cas_id *index, struct m0_bufvec *keys, struct m0_bufvec *values, struct m0_bufvec *expected_values, uint64_t version, int put_flags, int get_flags)
Definition: client_ut.c:1652
static char * cas_startup_cmd[]
Definition: client_ut.c:83
static void put_common(struct m0_bufvec *keys, struct m0_bufvec *values)
Definition: client_ut.c:2308
static void del_ver(void)
Definition: client_ut.c:3052
struct cas_ver_op before
Definition: client_ut.c:3656
static void next_reply_breakdown(struct m0_cas_next_reply *next_rep, m0_bcount_t nr, struct m0_bufvec *out_key, struct m0_bufvec *out_val, struct m0_crv **out_ver)
Definition: client_ut.c:1499
static void idx_delete_n(void)
Definition: client_ut.c:907
struct m0_net_domain cl_ndom
Definition: client_ut.c:75
struct m0_reqh rc_reqh
Definition: setup.h:312
int m0_net_xprt_nr(void)
Definition: net.c:168
M0_INTERNAL void m0_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
static const char * cl_ep_addrs[]
Definition: client_ut.c:95
int m0_rpc_client_stop(struct m0_rpc_client_ctx *cctx)
Definition: rpclib.c:217
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
static void ut_dtx_init(struct m0_dtx **out, uint64_t version)
Definition: client_ut.c:436
struct m0_net_xprt * m0_net_xprt_default_get(void)
Definition: net.c:151
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
static bool has_values(struct m0_cas_id *index, const struct m0_bufvec *keys, const struct m0_bufvec *expected_values, uint64_t flags)
Definition: client_ut.c:1361
static void next_multi_bulk(void)
Definition: client_ut.c:2237
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
void * m0_alloc(size_t size)
Definition: memory.c:126
static struct m0_rpc_server_ctx sctx
Definition: console.c:88
static void put_crow_fail(void)
Definition: client_ut.c:2877
static int ut_rec__get(struct cl_ctx *cctx, struct m0_cas_id *index, const struct m0_bufvec *keys, struct m0_cas_get_reply *rep, uint64_t flags)
Definition: client_ut.c:559
static void idx_tree_delete_fail(void)
Definition: client_ut.c:1043
#define BEFORE(_what, _when)
static void get_bulk(void)
Definition: client_ut.c:3414
M0_INTERNAL uint64_t m0_ctg_rec_size(void)
Definition: ctg_store.c:2151
struct m0_buf cge_val
Definition: client.h:207
idx_operation
Definition: client_ut.c:59
M0_INTERNAL bool m0_crv_tbs(const struct m0_crv *crv)
Definition: cas.c:225
#define UINT64_MAX
Definition: types.h:44
static int get_reply2bufvec(struct m0_cas_get_reply *get_rep, m0_bcount_t nr, struct m0_bufvec *out)
Definition: client_ut.c:1339
static void next_records_verified(struct m0_cas_id *index, struct m0_bufvec *start_key, uint32_t requested_keys_nr, struct m0_bufvec *expected_keys, struct m0_bufvec *expected_values, struct m0_crv *expected_versions, int flags)
Definition: client_ut.c:1534
uint32_t v_nr
Definition: vec.h:51
#define SERVER_LOG_FILE_NAME
Definition: client_ut.c:43
M0_INTERNAL const struct m0_fid m0_cas_dead_index_fid
Definition: cas.c:156
Definition: chan.h:229
M0_INTERNAL int m0_cas_index_create(struct m0_cas_req *req, const struct m0_cas_id *cids, uint64_t cids_nr, struct m0_dtx *dtx)
Definition: client.c:1321
M0_BASSERT(COUNT % 2==0)
const struct m0_bufvec * keys
Definition: client_ut.c:3650
M0_INTERNAL void m0_cas_index_list_rep(struct m0_cas_req *req, uint32_t idx, struct m0_cas_ilist_reply *rep)
Definition: client.c:1488
m0_bcount_t * v_count
Definition: vec.h:53
static int ut_rec_get(struct cl_ctx *cctx, struct m0_cas_id *index, const struct m0_bufvec *keys, struct m0_cas_get_reply *rep)
Definition: client_ut.c:606
static void put_fail(void)
Definition: client_ut.c:2942
static struct m0_clink clink[RDWR_REQUEST_MAX]
struct m0_fid * rcx_fid
Definition: rpclib.h:161
struct m0_addb2__id_intrp ids[]
Definition: dump.c:1074
struct m0_net_domain * rcx_net_dom
Definition: rpclib.h:128
struct m0_semaphore aw_cb_wait
Definition: client_ut.c:68
static void recs_count(void)
Definition: client_ut.c:3512
bool(* m0_chan_cb_t)(struct m0_clink *link)
Definition: chan.h:176
M0_INTERNAL void m0_reqh_idle_wait(struct m0_reqh *reqh)
Definition: reqh.c:606
static void next_keys_verified(struct m0_cas_id *index, struct m0_bufvec *start_key, uint32_t requested_keys_nr, struct m0_bufvec *expected_keys, int flags)
Definition: client_ut.c:1593
M0_INTERNAL int m0_cas_index_delete(struct m0_cas_req *req, const struct m0_cas_id *cids, uint64_t cids_nr, struct m0_dtx *dtx, uint32_t flags)
Definition: client.c:1366
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
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
static void next_fail(void)
Definition: client_ut.c:2101
static struct m0_rpc_server_ctx casc_ut_sctx
Definition: client_ut.c:99
const char * ts_name
Definition: ut.h:99
struct m0_crv cge_ver
Definition: client.h:209
M0_INTERNAL bool m0_crv_is_none(const struct m0_crv *crv)
Definition: cas.c:282
static bool has_versions(struct m0_cas_id *index, const struct m0_bufvec *keys, uint64_t version, uint64_t flags)
Definition: client_ut.c:1417
M0_INTERNAL void m0_cas_index_delete_rep(const struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1394
int ut_rec_common_put_seq(struct cl_ctx *cctx, struct m0_cas_id *index, const struct m0_bufvec *keys, const struct m0_bufvec *values, struct m0_dtx *dtx, struct m0_cas_rec_reply *rep, uint32_t flags)
Definition: client_ut.c:512
static void next_ver(void)
Definition: client_ut.c:1710
static void put_fail_common(struct m0_bufvec *keys, struct m0_bufvec *values)
Definition: client_ut.c:2918
static int ut_idx_create(struct cl_ctx *cctx, const struct m0_fid *ids, uint64_t ids_nr, struct m0_cas_rec_reply *rep)
Definition: client_ut.c:327
M0_INTERNAL void m0_cas_req_fini_lock(struct m0_cas_req *req)
Definition: client.c:295
static void get_common(struct m0_bufvec *keys, struct m0_bufvec *values)
Definition: client_ut.c:3358
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
int m0_net_domain_init(struct m0_net_domain *dom, const struct m0_net_xprt *xprt)
Definition: domain.c:36
int rsx_xprts_nr
Definition: rpclib.h:71
M0_INTERNAL struct m0_locality * m0_locality0_get(void)
Definition: locality.c:169
static void ut_rec_common_del_verified(struct m0_cas_id *index, const struct m0_bufvec *keys, uint64_t version, uint64_t flags)
Definition: client_ut.c:1627
static const char * srv_ep_addrs[]
Definition: client_ut.c:96
enum named_version ver
Definition: client_ut.c:3648
static void ut_rec_common_put_verified(struct m0_cas_id *index, const struct m0_bufvec *keys, const struct m0_bufvec *values, uint64_t version, uint64_t flags)
Definition: client_ut.c:1604
struct m0_reqh_context cc_reqh_ctx
Definition: setup.h:361
struct m0_rpc_session rcx_session
Definition: rpclib.h:147
static struct m0_chan chan[RDWR_REQUEST_MAX]
M0_INTERNAL uint64_t m0_cas_req_nr(const struct m0_cas_req *req)
Definition: client.c:1308
Definition: fid.h:38
static void next_common(struct m0_bufvec *keys, struct m0_bufvec *values, uint32_t flags)
Definition: client_ut.c:1225
M0_INTERNAL int m0_cas_index_lookup(struct m0_cas_req *req, const struct m0_cas_id *cids, uint64_t cids_nr)
Definition: client.c:1403
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
struct m0_chan sm_chan
Definition: sm.h:331
static int bufvec_cmp(const struct m0_bufvec *left, const struct m0_bufvec *right)
Definition: client_ut.c:118
M0_INTERNAL void m0_semaphore_fini(struct m0_semaphore *semaphore)
Definition: semaphore.c:45
static void del_common(struct m0_bufvec *keys, struct m0_bufvec *values, uint64_t version, uint64_t put_flags, uint64_t del_flags, uint64_t get_flags)
Definition: client_ut.c:3027
#define M0_UT_CONF_PROCESS
Definition: misc.h:45
static void put_common_with_ver(struct m0_bufvec *keys, struct m0_bufvec *values, uint64_t version)
Definition: client_ut.c:2284
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
struct m0_net_xprt ** m0_net_all_xprt_get(void)
Definition: net.c:161
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
static void ut_get_rep_clear(struct m0_cas_get_reply *rep, uint32_t nr)
Definition: client_ut.c:551
Definition: sm.h:301
const char * rcx_remote_addr
Definition: rpclib.h:134
M0_INTERNAL void m0_crv_init(struct m0_crv *crv, const struct m0_dtm0_ts *ts, bool tbs)
Definition: cas.c:251
M0_INTERNAL int m0_cas_req_wait(struct m0_cas_req *req, uint64_t states, m0_time_t to)
Definition: client.c:1313
m0_bcount_t size
Definition: di.c:39
static void cas_ver_op_execute(const struct cas_ver_op *cvop, struct m0_cas_id *index)
Definition: client_ut.c:3661
static void idx_delete(void)
Definition: client_ut.c:840
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
static int ut_lookup_idx(struct cl_ctx *cctx, const struct m0_fid *ids, uint64_t ids_nr, struct m0_cas_rec_reply *rep)
Definition: client_ut.c:335
static const char * cdbnames[]
Definition: client_ut.c:94
static void put_crow(void)
Definition: client_ut.c:2831
static int ut_idx_list(struct cl_ctx *cctx, const struct m0_fid *start_fid, uint64_t ids_nr, uint64_t *rep_count, struct m0_cas_ilist_reply *rep)
Definition: client_ut.c:397
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
static void cas_client_fini(struct cl_ctx *cctx)
Definition: client_ut.c:203
static int bufvec_empty_alloc(struct m0_bufvec *bufvec, uint32_t num_segs)
Definition: client_ut.c:105
m0_time_t dts_phys
Definition: clk_src.h:34
static int ut_rec_common_del_seq(struct cl_ctx *cctx, struct m0_cas_id *index, const struct m0_bufvec *keys, struct m0_dtx *dtx, struct m0_cas_rec_reply *rep, uint64_t flags)
Definition: client_ut.c:718
static void verify_version_properties(struct m0_cas_id *index, const struct m0_bufvec *keys, uint64_t version)
Definition: client_ut.c:3699
#define IFID(x, y)
Definition: client_ut.c:44
void m0_rpc_server_stop(struct m0_rpc_server_ctx *sctx)
Definition: rpclib.c:85
static int ut_rec_common_put(struct cl_ctx *cctx, struct m0_cas_id *index, const struct m0_bufvec *keys, const struct m0_bufvec *values, struct m0_dtx *dtx, struct m0_cas_rec_reply *rep, uint32_t flags)
Definition: client_ut.c:468
struct m0_ut_suite cas_client_ut
Definition: client_ut.c:3893
static void idx_create_a(void)
Definition: client_ut.c:804
M0_INTERNAL void m0_cas_rep_mlock(const struct m0_cas_req *req, uint64_t idx)
Definition: client.c:1816
M0_INTERNAL const struct m0_fid m0_cas_ctidx_fid
Definition: cas.c:151
static int ut_idx_flagged_delete(struct cl_ctx *cctx, const struct m0_fid *ids, uint64_t ids_nr, struct m0_cas_rec_reply *rep, uint32_t flags)
Definition: client_ut.c:379
#define out(...)
Definition: gen.c:41
static int ut_next_rec(struct cl_ctx *cctx, struct m0_cas_id *index, struct m0_bufvec *start_keys, uint32_t *recs_nr, struct m0_cas_next_reply *rep, uint64_t *count, uint32_t flags)
Definition: client_ut.c:625
static void idx_tree_delete(void)
Definition: client_ut.c:990
struct m0_net_xprt * xprt
Definition: module.c:61
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
int num
Definition: bulk_if.c:54
void m0_free(void *data)
Definition: memory.c:146
static int cas_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:173
Definition: cas.h:107
uint32_t sm_state
Definition: sm.h:307
M0_INTERNAL void m0_bufvec_free2(struct m0_bufvec *bufvec)
Definition: vec.c:401
static struct m0_fid ifid
Definition: service_ut.c:66
int32_t rc
Definition: trigger_fop.h:47
static void put_overwrite_ver(void)
Definition: client_ut.c:2319
#define ARRAY_SIZE(a)
Definition: misc.h:45
struct m0_fid g_process_fid
Definition: ut.c:689
M0_INTERNAL void m0_cas_index_lookup_rep(const struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1426
struct m0_crv cnp_ver
Definition: client.h:225
static int ut_rec_put(struct cl_ctx *cctx, struct m0_cas_id *index, const struct m0_bufvec *keys, const struct m0_bufvec *values, struct m0_cas_rec_reply *rep, uint32_t flags)
Definition: client_ut.c:539
struct m0_buf cnp_key
Definition: client.h:219
#define M0_UT_ASSERT(a)
Definition: ut.h:46
static void idx_create_fail(void)
Definition: client_ut.c:774
struct m0_motr rsx_motr_ctx
Definition: rpclib.h:84
Definition: vec.h:145
struct m0_dtm0_tx_desc dd_txd
Definition: dtx.h:62
M0_INTERNAL int m0_bufvec_empty_alloc(struct m0_bufvec *bufvec, uint32_t num_segs)
Definition: vec.c:213
static void idx_create(void)
Definition: client_ut.c:752
static void vals_mix_create(int count, int large_size, struct m0_bufvec *vals)
Definition: client_ut.c:155
static bool next_rep_equals(const struct m0_cas_next_reply *rep, void *key, void *val)
Definition: client_ut.c:1217
Definition: idx_mock.c:47
static void put_del_ver_case_verify(const struct put_del_ver_case *c, struct m0_cas_id *index)
Definition: client_ut.c:3768
#define M0_IMPOSSIBLE(fmt,...)