Motr  M0
idx_dix.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2016-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 
24 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CLIENT
25 #include "lib/trace.h"
26 #include "lib/assert.h"
27 #include "lib/tlist.h" /* m0_tl */
28 #include "lib/memory.h"
29 #include "fid/fid.h" /* m0_fid */
30 #include "pool/pool.h" /* pools_common_svc_ctx */
31 #include "conf/helpers.h" /* m0_confc_root_open */
32 #include "motr/client_internal.h"
33 #include "motr/layout.h"
34 #include "motr/idx.h"
35 #include "motr/sync.h"
36 #include "dix/fid_convert.h"
37 #include "dix/meta.h"
38 #include "dix/req.h"
39 #include "dix/client.h"
40 #include "motr/addb.h"
41 #include "dtm0/dtx.h"
42 
49 #define OI_IFID(oi) (struct m0_fid *)&(oi)->oi_idx->in_entity.en_id
50 
54 struct dix_inst {
68 };
69 
70 struct dix_req {
71  struct m0_op_idx *idr_oi;
89  bool idr_meta;
90 };
91 
92 static bool dixreq_clink_cb(struct m0_clink *cl);
93 static bool dixreq_clink_dtx_cb(struct m0_clink *cl);
94 static bool dix_meta_req_clink_cb(struct m0_clink *cl);
95 static void dix_req_immed_failure(struct dix_req *req, int rc);
96 static void dixreq_completed_post(struct dix_req *req, int rc);
97 
98 static bool idx_is_distributed(const struct m0_op_idx *oi)
99 {
100  uint8_t ifid_type = m0_fid_tget(OI_IFID(oi));
101 
104  return ifid_type == m0_dix_fid_type.ft_id;
105 }
106 
107 static void idx_sync_record_update(struct m0_op *op,
108  struct m0_rpc_session *rpc_session,
109  struct m0_be_tx_remid *remid)
110 {
111  struct m0_entity *ent;
112  struct m0_op_common *oc;
113  struct m0_op_idx *oi;
114  struct m0_op_layout *ol;
115 
116  oc = bob_of(op, struct m0_op_common, oc_op, &oc_bobtype);
117 
118  if (M0_IN(op->op_code,
121  /* Check and ensure oi is valid here. */
122  oi = bob_of(oc, struct m0_op_idx, oi_oc, &oi_bobtype);
124  ent = &oi->oi_idx->in_entity;
125  } else if (op->op_code == M0_EO_LAYOUT_SET) {
126  ol = bob_of(oc, struct m0_op_layout, ol_oc, &ol_bobtype);
127  ent = ol->ol_entity;
128  } else
129  M0_IMPOSSIBLE("Wrong opcode for index sync record update.");
130 
132  ent, op, remid);
133 }
134 
135 static void cas_sync_record_update(struct m0_cas_req *creq,
136  struct m0_rpc_session *rpc_session,
137  struct m0_be_tx_remid *remid)
138 {
139  struct dix_req *dix_req;
140 
141  dix_req = M0_AMB(dix_req, creq, idr_creq);
142  if (M0_IN(dix_req->idr_oi->oi_oc.oc_op.op_code,
144  M0_IC_PUT, M0_IC_DEL)))
146  rpc_session, remid);
147 }
148 
149 static void dix_sync_record_update(struct m0_dix_req *dreq,
150  struct m0_rpc_session *rpc_session,
151  struct m0_be_tx_remid *remid)
152 {
153  struct m0_op *op;
154 
155  /* Ignores non-update dix requests. */
156  if (M0_IN(dreq->dr_type, (DIX_CCTGS_LOOKUP, DIX_NEXT, DIX_GET)))
157  return;
158 
159  /*
160  * `op` is needed to recover info on client op and entity, so SYNC
161  * records can be updated. `op` is stored in each dreq issued from
162  * Client (and is passed further down to lower dreq if meta dreq is
163  * required for some index ops, for example dix_index_create).
164  */
165  op = (struct m0_op *)dreq->dr_sync_datum;
166  idx_sync_record_update(op, rpc_session, remid);
167 }
168 
169 
170 static struct dix_inst *dix_inst(const struct m0_op_idx *oi)
171 {
172  struct m0_client *m0c;
173 
175  return (struct dix_inst *)m0c->m0c_idx_svc_ctx.isc_svc_inst;
176 }
177 
178 static struct m0_dix_cli *op_dixc(const struct m0_op_idx *oi)
179 {
180  return &dix_inst(oi)->di_dixc;
181 }
182 
183 M0_INTERNAL struct dix_inst *ent_dix_inst(const struct m0_entity *ent)
184 {
185  struct m0_client *m0c;
186 
188  return (struct dix_inst *)m0c->m0c_idx_svc_ctx.isc_svc_inst;
189 }
190 
191 M0_INTERNAL struct m0_dix_cli *ent_dixc(const struct m0_entity *ent)
192 {
193  return &ent_dix_inst(ent)->di_dixc;
194 }
195 
196 M0_INTERNAL struct m0_dix_cli *ol_dixc(const struct m0_op_layout *ol)
197 {
198  return &ent_dix_inst(ol->ol_oc.oc_op.op_entity)->di_dixc;
199 }
200 
201 /*--------------------------------------------------------------------------*
202  * Non-distributed (CAS) indices routines *
203  *--------------------------------------------------------------------------*/
212 static struct m0_reqh_service_ctx *svc_find(const struct m0_op_idx *oi)
213 {
214  struct m0_client *m0c;
215 
217  return m0_tl_find(pools_common_svc_ctx, ctx,
218  &m0c->m0c_pools_common.pc_svc_ctxs,
219  ctx->sc_type == M0_CST_CAS);
220 }
221 
222 static void cas_list_reply_copy(struct m0_cas_req *req,
223  int32_t *rcs,
224  struct m0_bufvec *bvec)
225 {
226  uint64_t rep_count = m0_cas_req_nr(req);
227  struct m0_cas_ilist_reply rep;
228  uint64_t i;
229 
230  /* Assertion is guaranteed by CAS client. */
231  M0_PRE(bvec->ov_vec.v_nr == rep_count);
232  for (i = 0; i < rep_count; i++) {
234  rcs[i] = rep.clr_rc;
235  if (rep.clr_rc == 0) {
236  /* User should allocate buffer of appropriate size */
238  sizeof(struct m0_fid));
239  *(struct m0_fid *)bvec->ov_buf[i] = rep.clr_fid;
240  }
241  }
242 }
243 
244 static void cas_get_reply_copy(struct m0_cas_req *req,
245  int32_t *rcs,
246  struct m0_bufvec *bvec)
247 {
248  uint64_t rep_count = m0_cas_req_nr(req);
249  struct m0_cas_get_reply rep;
250  uint64_t i;
251 
252  /* Assertion is guaranteed by CAS client. */
253  M0_PRE(bvec->ov_vec.v_nr >= rep_count);
254  for (i = 0; i < rep_count; i++) {
255  m0_cas_get_rep(req, i, &rep);
256  M0_ASSERT(bvec->ov_vec.v_count[i] == 0);
257  M0_ASSERT(bvec->ov_buf[i] == NULL);
258  rcs[i] = rep.cge_rc;
259  if (rep.cge_rc == 0) {
261  bvec->ov_vec.v_count[i] = rep.cge_val.b_nob;
262  bvec->ov_buf[i] = rep.cge_val.b_addr;
263  }
264  }
265 }
266 
267 static void cas_next_reply_copy(struct m0_cas_req *req,
268  int32_t *rcs,
269  struct m0_bufvec *keys,
270  struct m0_bufvec *vals)
271 {
272  uint64_t rep_count = m0_cas_req_nr(req);
273  struct m0_cas_next_reply rep;
274  uint64_t i;
275 
276  /* Assertions are guaranteed by CAS client. */
277  M0_PRE(keys->ov_vec.v_nr == rep_count);
278  M0_PRE(vals->ov_vec.v_nr >= rep_count);
279  for (i = 0; i < rep_count; i++) {
280  m0_cas_next_rep(req, i, &rep);
281  rcs[i] = rep.cnp_rc;
282  if (rep.cnp_rc == 0) {
284  keys->ov_vec.v_count[i] = rep.cnp_key.b_nob;
285  keys->ov_buf[i] = rep.cnp_key.b_addr;
286  vals->ov_vec.v_count[i] = rep.cnp_val.b_nob;
287  vals->ov_buf[i] = rep.cnp_val.b_addr;
288  }
289  }
290 }
291 
292 static bool casreq_clink_cb(struct m0_clink *cl)
293 {
294  struct dix_req *dix_req = M0_AMB(dix_req, cl, idr_clink);
295  struct m0_op_idx *oi = dix_req->idr_oi;
296  struct m0_sm *req_sm = M0_AMB(req_sm, cl->cl_chan, sm_chan);
297  struct m0_cas_req *creq = M0_AMB(creq, req_sm, ccr_sm);
298  uint32_t state = creq->ccr_sm.sm_state;
299  struct m0_op *op;
300  int rc;
301  struct m0_cas_rec_reply rep;
302  uint64_t i;
303 
304  if (!M0_IN(state, (CASREQ_FAILURE, CASREQ_FINAL)))
305  return false;
306 
307  m0_clink_del(cl);
308  op = &oi->oi_oc.oc_op;
309 
310  rc = m0_cas_req_generic_rc(creq);
311  if (rc == 0) {
312  /*
313  * Response from CAS service is validated by CAS client,
314  * including number of records in response.
315  */
316  switch (op->op_code) {
317  case M0_EO_CREATE:
318  M0_ASSERT(m0_cas_req_nr(creq) == 1);
319  m0_cas_index_create_rep(creq, 0, &rep);
320  rc = rep.crr_rc;
321  break;
322  case M0_EO_DELETE:
323  M0_ASSERT(m0_cas_req_nr(creq) == 1);
324  m0_cas_index_delete_rep(creq, 0, &rep);
325  rc = rep.crr_rc;
326  break;
327  case M0_IC_LOOKUP:
328  M0_ASSERT(m0_cas_req_nr(creq) == 1);
329  m0_cas_index_lookup_rep(creq, 0, &rep);
330  rc = rep.crr_rc;
331  break;
332  case M0_IC_LIST:
333  cas_list_reply_copy(creq, oi->oi_rcs, oi->oi_keys);
334  break;
335  case M0_IC_PUT:
336  for (i = 0; i < m0_cas_req_nr(creq); i++) {
337  m0_cas_put_rep(creq, 0, &rep);
338  oi->oi_rcs[i] = rep.crr_rc;
339  }
340  break;
341  case M0_IC_GET:
342  cas_get_reply_copy(creq, oi->oi_rcs, oi->oi_vals);
343  break;
344  case M0_IC_DEL:
345  for (i = 0; i < m0_cas_req_nr(creq); i++) {
346  m0_cas_del_rep(creq, 0, &rep);
347  oi->oi_rcs[i] = rep.crr_rc;
348  }
349  break;
350  case M0_IC_NEXT:
351  cas_next_reply_copy(creq, oi->oi_rcs, oi->oi_keys,
352  oi->oi_vals);
353  break;
354  default:
355  M0_IMPOSSIBLE("Invalid op code");
356  }
357  }
358 
359  /* Update TXID. */
360  cas_sync_record_update(creq, creq->ccr_sess, &creq->ccr_remid);
361 
363  return false;
364 }
365 
366 static void cas_req_prepare(struct dix_req *req,
367  struct m0_cas_id *cid,
368  struct m0_op_idx *oi)
369 {
370  M0_SET0(cid);
371  cid->ci_fid = *OI_IFID(oi);
372  m0_clink_add(&req->idr_creq.ccr_sm.sm_chan, &req->idr_clink);
373 }
374 
375 static void cas_index_cancel(struct dix_req *dix_req)
376 {
377  struct m0_cas_req *creq = &dix_req->idr_creq;
378  struct m0_fop *fop;
379 
380  fop = creq->ccr_fop;
381  if (fop != NULL)
383 }
384 
385 static void cas_index_create_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
386 {
387  struct dix_req *dix_req = ast->sa_datum;
388  struct m0_op_idx *oi = dix_req->idr_oi;
389  struct m0_cas_req *creq = &dix_req->idr_creq;
390  struct m0_cas_id cid;
391  int rc;
392 
393  M0_ENTRY();
394  cas_req_prepare(dix_req, &cid, oi);
395  rc = m0_cas_index_create(creq, &cid, 1, NULL);
396  if (rc != 0)
398  M0_LEAVE();
399 }
400 
401 static void cas_index_delete_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
402 {
403  struct dix_req *dix_req = ast->sa_datum;
404  struct m0_op_idx *oi = dix_req->idr_oi;
405  struct m0_cas_req *creq = &dix_req->idr_creq;
406  struct m0_cas_id cid;
407  int rc;
408 
409  M0_ENTRY();
410  cas_req_prepare(dix_req, &cid, oi);
411  rc = m0_cas_index_delete(creq, &cid, 1, NULL, 0);
412  if (rc != 0)
414  M0_LEAVE();
415 }
416 
417 static void cas_index_lookup_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
418 {
419  struct dix_req *dix_req = ast->sa_datum;
420  struct m0_op_idx *oi = dix_req->idr_oi;
421  struct m0_cas_req *creq = &dix_req->idr_creq;
422  struct m0_cas_id cid;
423  int rc;
424 
425  M0_ENTRY();
426  cas_req_prepare(dix_req, &cid, oi);
427  rc = m0_cas_index_lookup(creq, &cid, 1);
428  if (rc != 0)
430  M0_LEAVE();
431 }
432 
433 static void cas_index_list_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
434 {
435  struct dix_req *dix_req = ast->sa_datum;
436  struct m0_op_idx *oi = dix_req->idr_oi;
437  struct m0_cas_req *creq = &dix_req->idr_creq;
438  int rc;
439 
440  M0_ENTRY();
442  rc = m0_cas_index_list(creq, OI_IFID(oi), oi->oi_keys->ov_vec.v_nr, 0);
443  if (rc != 0)
445  M0_LEAVE();
446 }
447 
448 static void cas_put_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
449 {
450  struct dix_req *dix_req = ast->sa_datum;
451  struct m0_op_idx *oi = dix_req->idr_oi;
452  struct m0_cas_id idx;
453  struct m0_cas_req *creq = &dix_req->idr_creq;
454  uint32_t flags = 0;
455  int rc;
456 
457  M0_ENTRY();
458  cas_req_prepare(dix_req, &idx, oi);
459  /*
460  * FIXME: why don't we call `flags = dix_set_cas_flags(oi);`
461  * instead of the following code?
462  */
463  if (oi->oi_flags & M0_OIF_OVERWRITE)
464  flags |= COF_OVERWRITE;
465  if (oi->oi_flags & M0_OIF_SYNC_WAIT)
466  flags |= COF_SYNC_WAIT;
467  if (oi->oi_flags & M0_OIF_NO_DTM)
468  flags |= COF_NO_DTM;
469 
470  rc = m0_cas_put(creq, &idx, oi->oi_keys, oi->oi_vals, NULL, flags);
471  if (rc != 0)
473  M0_LEAVE();
474 }
475 
476 static void cas_get_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
477 {
478  struct dix_req *dix_req = ast->sa_datum;
479  struct m0_op_idx *oi = dix_req->idr_oi;
480  struct m0_cas_id idx;
481  struct m0_cas_req *creq = &dix_req->idr_creq;
482  int rc;
483 
484  M0_ENTRY();
485  cas_req_prepare(dix_req, &idx, oi);
486  rc = m0_cas_get(creq, &idx, oi->oi_keys);
487  if (rc != 0)
489  M0_LEAVE();
490 }
491 
492 static void cas_del_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
493 {
494  struct dix_req *dix_req = ast->sa_datum;
495  struct m0_op_idx *oi = dix_req->idr_oi;
496  struct m0_cas_id idx;
497  struct m0_cas_req *creq = &dix_req->idr_creq;
498  uint32_t flags = 0;
499  int rc;
500 
501  M0_ENTRY();
502  cas_req_prepare(dix_req, &idx, oi);
503  if (oi->oi_flags & M0_OIF_SYNC_WAIT)
504  flags |= COF_SYNC_WAIT;
505  rc = m0_cas_del(creq, &idx, oi->oi_keys, NULL, flags);
506  if (rc != 0)
508  M0_LEAVE();
509 }
510 
511 static void cas_next_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
512 {
513  struct dix_req *dix_req = ast->sa_datum;
514  struct m0_op_idx *oi = dix_req->idr_oi;
515  struct m0_cas_id idx;
516  struct m0_cas_req *creq = &dix_req->idr_creq;
517  m0_bcount_t ksize;
518  struct m0_bufvec *start_key = &dix_req->idr_start_key;
519  uint32_t flags = COF_SLANT;
520  int rc;
521 
522  M0_ENTRY();
523  cas_req_prepare(dix_req, &idx, oi);
529  ksize = oi->oi_keys->ov_vec.v_count[0];
530  if (ksize == 0) {
531  M0_ASSERT(oi->oi_keys->ov_buf[0] == NULL);
532  /*
533  * Request records from the index beginning. Use the smallest
534  * key (1-byte zero key).
535  */
536  m0_bufvec_alloc(start_key, 1, sizeof(uint8_t));
537  *(uint8_t *)start_key->ov_buf[0] = 0;
538  } else {
539  m0_bufvec_alloc(start_key, 1, ksize);
540  memcpy(start_key->ov_buf[0], oi->oi_keys->ov_buf[0], ksize);
541  }
544  rc = m0_cas_next(creq, &idx, start_key, &oi->oi_keys->ov_vec.v_nr,
545  flags);
546  if (rc != 0)
548  M0_LEAVE();
549 }
550 
551 /*--------------------------------------------------------------------------*
552  * Distributed (DIX) indices routines *
553  *--------------------------------------------------------------------------*/
554 static void dix_build(const struct m0_op_idx *oi,
555  struct m0_dix *out)
556 {
557  unsigned int opcode = OP_IDX2CODE(oi);
558  struct m0_idx *idx = oi->oi_idx;
559 
560  M0_SET0(out);
561  out->dd_fid = *OI_IFID(oi);
562  /* Pool version and layout type which are passed by consumers like S3 */
563  if (M0_IN(opcode, (M0_IC_GET, M0_IC_PUT, M0_IC_DEL, M0_IC_NEXT))) {
565  && (m0_fid_is_set(&idx->in_attr.idx_pver))
566  && (m0_fid_is_valid(&idx->in_attr.idx_pver))) {
567  M0_LOG(M0_DEBUG, "Opcode: %u, DIX pool version:"FID_F"",
568  opcode, FID_P(&idx->in_attr.idx_pver));
569 
570  out->dd_layout.dl_type = DIX_LTYPE_DESCR;
571  m0_dix_ldesc_init(&out->dd_layout.u.dl_desc,
572  &(struct m0_ext) { .e_start = 0,
573  .e_end = IMASK_INF }, 1,
575  &idx->in_attr.idx_pver);
576  }
577  } else if (M0_IN(opcode, (M0_EO_CREATE)) ||
578  (oi->oi_flags & M0_OIF_SKIP_LAYOUT)) {
579  /*
580  * Use default layout for all indices:
581  * - city hash function;
582  * - infinity identity mask (use key as is);
583  * - default pool version (the same as for root index).
584  * In future client user will be able to pass layout as an
585  * argument.
586  */
587  out->dd_layout.dl_type = DIX_LTYPE_DESCR;
588 
589  m0_dix_ldesc_init(&out->dd_layout.u.dl_desc,
590  &(struct m0_ext) { .e_start = 0,
591  .e_end = IMASK_INF }, 1, HASH_FNC_CITY,
592  (idx->in_entity.en_flags & M0_ENF_META) ?
593  &idx->in_attr.idx_pver :
594  &dix_inst(oi)->di_index_pver);
595  }
596 }
597 
598 static void cas_req_init(struct dix_req *req,
599  struct m0_op_idx *oi)
600 {
601  struct m0_reqh_service_ctx *svc;
602 
603  svc = svc_find(oi);
604  M0_ASSERT(svc != NULL);
605  m0_cas_req_init(&req->idr_creq, &svc->sc_rlink.rlk_sess, oi->oi_sm_grp);
606  m0_clink_init(&req->idr_clink, casreq_clink_cb);
607 }
608 
609 static int dix_mreq_create(struct m0_op_idx *oi,
610  struct dix_req **out)
611 {
612  struct dix_req *req;
613 
614  M0_ALLOC_PTR(req);
615  if (req == NULL)
616  return M0_ERR(-ENOMEM);
617  if (idx_is_distributed(oi)) {
618  m0_dix_meta_req_init(&req->idr_mreq, op_dixc(oi),
619  oi->oi_sm_grp);
621 
622  /*
623  * Currently only LOOKUP and LIST create meta request, so
624  * don't need to set callback datum here.
625  */
626  } else {
627  cas_req_init(req, oi);
628  }
629 
630  req->idr_oi = oi;
631  oi->oi_dix_req = req;
632  req->idr_meta = true;
633  *out = req;
634  return M0_RC(0);
635 }
636 
637 static void to_dix_map(const struct m0_op *op,
638  const struct m0_dix_req *req)
639 {
640  uint64_t cid = m0_sm_id_get(&op->op_sm);
641  uint64_t did = m0_sm_id_get(&req->dr_sm);
643 }
644 
645 static int dix_req_create(struct m0_op_idx *oi,
646  struct dix_req **out)
647 {
648  struct dix_req *req;
649  int rc = 0;
650  M0_ENTRY();
651 
652  M0_ALLOC_PTR(req);
653  if (req != NULL) {
654  if (idx_is_distributed(oi)) {
655  m0_dix_req_init(&req->idr_dreq, op_dixc(oi),
656  oi->oi_sm_grp);
657  to_dix_map(&oi->oi_oc.oc_op, &req->idr_dreq);
658  req->idr_dreq.dr_dtx = oi->oi_dtx;
659  m0_clink_init(&req->idr_clink,
660  oi->oi_dtx != NULL ?
662 
663  /* Store oi for dix callbacks to update SYNC records. */
664  if (M0_IN(oi->oi_oc.oc_op.op_code,
666  M0_IC_PUT, M0_IC_DEL)))
667  req->idr_dreq.dr_sync_datum =
668  (void *)&oi->oi_oc.oc_op;
669  } else {
670  cas_req_init(req, oi);
671  }
672  req->idr_oi = oi;
673  oi->oi_dix_req = req;
674  *out = req;
675  } else
676  rc = M0_ERR(-ENOMEM);
677  return M0_RC(rc);
678 }
679 
680 static void dix_req_destroy(struct dix_req *req)
681 {
682  M0_ENTRY();
683  m0_clink_fini(&req->idr_clink);
684  m0_bufvec_free(&req->idr_start_key);
685  if (idx_is_distributed(req->idr_oi)) {
686  if (req->idr_meta)
687  m0_dix_meta_req_fini(&req->idr_mreq);
688  else
689  m0_dix_req_fini(&req->idr_dreq);
690  } else {
691  m0_cas_req_fini(&req->idr_creq);
692  }
693  m0_free(req);
694  M0_LEAVE();
695 }
696 
697 static void dixreq_completed_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
698 {
699  struct dix_req *req = ast->sa_datum;
700  struct m0_op_idx *oi = req->idr_oi;
701  int rc = oi->oi_ar.ar_rc;
702 
703  M0_ENTRY();
704  oi->oi_ar.ar_ast.sa_cb = (rc == 0) ? idx_op_ast_complete :
706  oi->oi_in_completion = true;
707  /* XXX: it looks like there is no need to set up an ast for that.
708  * The groups are the same. We can just call the callback right here?
709  * oi->oi_ar.ar_ast.sa_cb(oi->oi_sm_grp, &oi->oi_ar.ar_ast)
710  */
713  M0_LEAVE();
714 }
715 
716 static void dixreq_completed_post(struct dix_req *req, int rc)
717 {
718  struct m0_op_idx *oi = req->idr_oi;
719 
720  M0_ENTRY();
721  oi->oi_ar.ar_rc = rc;
722  req->idr_ast.sa_cb = dixreq_completed_ast;
723  req->idr_ast.sa_datum = req;
724  m0_sm_ast_post(oi->oi_sm_grp, &req->idr_ast);
725  M0_LEAVE();
726 }
727 
729  int32_t *rcs,
730  struct m0_bufvec *bvec)
731 {
732  uint64_t rep_count = m0_dix_index_list_rep_nr(req);
733  uint64_t i;
734 
735  /* Assertion is guaranteed by DIX/CAS client. */
736  M0_PRE(bvec->ov_vec.v_nr >= rep_count);
737  for (i = 0; i < rep_count; i++) {
738  /* User should allocate buffer of appropriate size */
739  M0_ASSERT(bvec->ov_vec.v_count[i] == sizeof(struct m0_fid));
740  rcs[i] = m0_dix_index_list_rep(req, i,
741  (struct m0_fid *)bvec->ov_buf[i]);
742  }
743 
744  /*
745  * If number of listed indices is less than was requested by user, then
746  * there are no more indices to list. Fill tail of return codes array
747  * with -ENOENT for non-existing indices.
748  */
749  for (i = rep_count; i < bvec->ov_vec.v_nr; i++)
750  rcs[i] = -ENOENT;
751  return M0_RC(0);
752 }
753 
754 static void dix_get_reply_copy(struct m0_dix_req *dreq,
755  int32_t *rcs,
756  struct m0_bufvec *bvec)
757 {
758  uint64_t rep_count = m0_dix_req_nr(dreq);
759  struct m0_dix_get_reply rep;
760  uint64_t i;
761 
762  /* Assertion is guaranteed by DIX client. */
763  M0_PRE(bvec->ov_vec.v_nr >= rep_count);
764  for (i = 0; i < rep_count; i++) {
765  m0_dix_get_rep(dreq, i, &rep);
766  M0_ASSERT(bvec->ov_vec.v_count[i] == 0);
767  M0_ASSERT(bvec->ov_buf[i] == NULL);
768  rcs[i] = rep.dgr_rc;
769  if (rep.dgr_rc == 0) {
770  m0_dix_get_rep_mlock(dreq, i);
771  bvec->ov_vec.v_count[i] = rep.dgr_val.b_nob;
772  bvec->ov_buf[i] = rep.dgr_val.b_addr;
773  }
774  }
775 }
776 
777 static void dix_next_reply_copy(struct m0_dix_req *req,
778  int32_t *rcs,
779  struct m0_bufvec *keys,
780  struct m0_bufvec *vals)
781 {
782  uint64_t rep_count = m0_dix_next_rep_nr(req, 0);
783  struct m0_dix_next_reply rep;
784  uint64_t i;
785  uint64_t k = 0;
786 
787  /* Assertions are guaranteed by DIX client. */
788  M0_PRE(keys->ov_vec.v_nr >= rep_count);
789  M0_PRE(vals->ov_vec.v_nr >= rep_count);
790  for (i = 0; i < rep_count; i++) {
791  rcs[i] = 0;
792  m0_dix_next_rep(req, 0, i, &rep);
794  keys->ov_vec.v_count[k] = rep.dnr_key.b_nob;
795  keys->ov_buf[k] = rep.dnr_key.b_addr;
796  vals->ov_vec.v_count[k] = rep.dnr_val.b_nob;
797  vals->ov_buf[k] = rep.dnr_val.b_addr;
798  k++;
799  }
800  /*
801  * If number of retrieved records is less than was requested by user,
802  * then there are no more records in the index. Fill tail of return
803  * codes array with -ENOENT for non-existing records.
804  */
805  for (i = rep_count; i < keys->ov_vec.v_nr; i++)
806  rcs[i] = -ENOENT;
807 }
808 
809 static bool dix_meta_req_clink_cb(struct m0_clink *cl)
810 {
811  struct dix_req *dix_req = M0_AMB(dix_req, cl, idr_clink);
812  struct m0_op_idx *oi = dix_req->idr_oi;
813  struct m0_dix_meta_req *mreq = &dix_req->idr_mreq;
814  struct m0_op *op;
815  int rc;
816 
817  m0_clink_del(cl);
818  op = &oi->oi_oc.oc_op;
820  M0_ASSERT(M0_IN(op->op_code,(M0_IC_LIST, M0_IC_LOOKUP)));
821  rc = m0_dix_meta_generic_rc(mreq) ?:
822  (op->op_code == M0_IC_LIST) ?
823  dix_list_reply_copy(mreq, oi->oi_rcs, oi->oi_keys) :
824  m0_dix_layout_rep_get(mreq, 0, NULL);
826  return false;
827 }
828 
829 static void dixreq_stable_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
830 {
831  struct dix_req *req = ast->sa_datum;
832  struct m0_op_idx *oi = req->idr_oi;
833  int rc = oi->oi_ar.ar_rc;
834 
835  M0_ENTRY();
836  oi->oi_ar.ar_ast.sa_cb = (rc == 0) ? idx_op_ast_stable : NULL;
837  M0_ASSERT(grp == oi->oi_sm_grp);
840  M0_LEAVE();
841 }
842 
843 static void dixreq_stable_post(struct dix_req *req, int rc)
844 {
845  struct m0_op_idx *oi = req->idr_oi;
846 
847  M0_ENTRY();
848  oi->oi_ar.ar_rc = rc;
849  req->idr_ast.sa_cb = dixreq_stable_ast;
850  req->idr_ast.sa_datum = req;
851  M0_ASSERT_INFO(req->idr_ast.sa_next == NULL,
852  "Stable() ast cannot be armed before Executed() "
853  "is completed. Ensure EXECUTED_ALL -> STABLE transition"
854  "does not happen within the same ast tick");
855  m0_sm_ast_post(oi->oi_sm_grp, &req->idr_ast);
856  M0_LEAVE();
857 }
858 
859 static void dixreq_executed_post(struct dix_req *req, int rc)
860 {
861  struct m0_op_idx *oi = req->idr_oi;
862 
863  M0_ENTRY();
864 
865  M0_ASSERT_INFO(rc == 0, "TODO: Failures are not handled here.");
866  oi->oi_ar.ar_rc = rc;
867 
868  /* XXX: DTX cannot be canceled (as per the current design),
869  * so that once we got a reply, we prohibit any kind of cancelation.
870  * The originator should m0_panic itself in case if something needs
871  * to be canceled. It will be re-started and continue its execution.
872  */
873  oi->oi_in_completion = true;
875  M0_ASSERT(req->idr_dreq.dr_dtx->tx_dtx->dd_sm.sm_grp == oi->oi_sm_grp);
878  M0_LEAVE();
879 }
880 
881 static bool dixreq_clink_dtx_cb(struct m0_clink *cl)
882 {
883  struct dix_req *dix_req = M0_AMB(dix_req, cl, idr_clink);
884  struct m0_op_idx *oi = dix_req->idr_oi;
885  struct m0_sm *req_sm = M0_AMB(req_sm, cl->cl_chan, sm_chan);
886  struct m0_dix_req *dreq = &dix_req->idr_dreq;
887  struct m0_dtx *dtx = oi->oi_dtx;
888  enum m0_dtm0_dtx_state state;
889  int i;
890 
891  M0_PRE(M0_IN(oi->oi_oc.oc_op.op_code, (M0_IC_PUT, M0_IC_DEL)));
892  M0_PRE(dtx != NULL);
893 
894  state = m0_dtx0_sm_state(dtx);
895 
896  if (!M0_IN(state, (M0_DDS_EXECUTED_ALL, M0_DDS_STABLE, M0_DDS_FAILED)))
897  return false;
898 
899  switch (state) {
900  case M0_DDS_EXECUTED_ALL:
901  /* TODO: we have a single kv pair; probably, it does not have
902  * to be a loop.
903  */
904  for (i = 0; i < m0_dix_req_nr(dreq); i++) {
905  oi->oi_rcs[i] = dreq->dr_items[i].dxi_rc;
906  }
907  /* XXX: We cannot use m0_dix_generic_rc here because the
908  * precondition fails in this case. At this point error
909  * handling is not covered here, and probably the error
910  * code needs to be first propogated from DIX to DTX and
911  * then it needs to be passed here as dtx.dd_sm.sm_rc.
912  */
914  break;
915  case M0_DDS_STABLE:
917  "TODO: DIX failures are not supported.");
918 
920  m0_dix_item_rc(dreq, idx) == 0),
921  "TODO: failed executions of individual items "
922  "are not supported yet.");
923 
925  m0_clink_del(cl);
926  break;
927  case M0_DDS_FAILED:
928  M0_IMPOSSIBLE("DTX failures are not supported so far.");
929  default:
930  M0_IMPOSSIBLE("Only Executed and Stable are allowed so far.");
931  }
932 
933  return false;
934 }
935 
936 static bool dixreq_clink_cb(struct m0_clink *cl)
937 {
938  struct dix_req *dix_req = M0_AMB(dix_req, cl, idr_clink);
939  struct m0_op_idx *oi = dix_req->idr_oi;
940  struct m0_sm *req_sm = M0_AMB(req_sm, cl->cl_chan, sm_chan);
941  struct m0_dix_req *dreq = M0_AMB(dreq, req_sm, dr_sm);
942  uint32_t state = dreq->dr_sm.sm_state;
943  struct m0_op *op;
944  int i;
945  int rc;
946 
947  if (!M0_IN(state, (DIXREQ_FAILURE, DIXREQ_FINAL)))
948  return false;
949 
950  m0_clink_del(cl);
951  op = &oi->oi_oc.oc_op;
952 
953  rc = m0_dix_generic_rc(dreq);
954  if (rc == 0) {
955  /*
956  * Response from CAS service is validated by CAS/DIX client,
957  * including number of records in response.
958  */
959  switch (op->op_code) {
960  case M0_EO_CREATE:
961  case M0_EO_DELETE:
962  M0_ASSERT(m0_dix_req_nr(dreq) == 1);
963  rc = m0_dix_item_rc(dreq, 0);
964  break;
965  case M0_IC_PUT:
966  case M0_IC_DEL:
967  for (i = 0; i < m0_dix_req_nr(dreq); i++)
968  oi->oi_rcs[i] = m0_dix_item_rc(dreq, i);
969  break;
970  case M0_IC_GET:
971  dix_get_reply_copy(dreq, oi->oi_rcs, oi->oi_vals);
972  break;
973  case M0_IC_NEXT:
974  dix_next_reply_copy(dreq, oi->oi_rcs, oi->oi_keys,
975  oi->oi_vals);
976  break;
977  case M0_IC_LOOKUP:
978  if (oi->oi_flags & M0_OIF_SKIP_LAYOUT) {
979  M0_ASSERT(m0_dix_req_nr(dreq) == 1);
980  rc = m0_dix_item_rc(dreq, 0);
981  }
982  break;
983  default:
984  M0_IMPOSSIBLE("Invalid op code");
985  }
986  }
987 
989  return false;
990 }
991 
992 static void dix_req_immed_failure(struct dix_req *req, int rc)
993 {
994  M0_ENTRY();
995  M0_PRE(rc != 0);
996  m0_clink_del(&req->idr_clink);
998  M0_LEAVE();
999 }
1000 
1001 static void dix_req_exec(struct dix_req *req,
1002  void (*exec_fn)(struct m0_sm_group *grp,
1003  struct m0_sm_ast *ast))
1004 {
1005  M0_ENTRY();
1006  req->idr_ast.sa_cb = exec_fn;
1007  req->idr_ast.sa_datum = req;
1008  m0_sm_ast_post(req->idr_oi->oi_sm_grp, &req->idr_ast);
1009  M0_LEAVE();
1010 }
1011 
1012 static uint32_t dix_set_cas_flags(struct m0_op_idx *oi)
1013 {
1014  uint32_t flags = 0;
1015  if (oi->oi_flags & M0_OIF_OVERWRITE)
1016  flags |= COF_OVERWRITE;
1017  if (oi->oi_flags & M0_OIF_SYNC_WAIT)
1018  flags |= COF_SYNC_WAIT;
1019  if (oi->oi_flags & M0_OIF_CROW)
1020  flags |= COF_CROW;
1021  if (oi->oi_flags & M0_OIF_SKIP_LAYOUT)
1023  if (oi->oi_flags & M0_OIF_NO_DTM)
1024  flags |= COF_NO_DTM;
1025  return flags;
1026 }
1027 
1028 static void dix_index_create_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1029 {
1030  struct dix_req *dix_req = ast->sa_datum;
1031  struct m0_op_idx *oi = dix_req->idr_oi;
1032  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1033  struct m0_dix dix;
1034  int rc;
1035  uint32_t flags;
1036 
1037  M0_ENTRY();
1038  dix_build(oi, &dix);
1039  flags = dix_set_cas_flags(oi);
1040 
1042  rc = m0_dix_create(dreq, &dix, 1, NULL, flags);
1043  if (rc != 0)
1045  m0_dix_fini(&dix);
1046  M0_LEAVE();
1047 }
1048 
1049 static bool dix_iname_args_are_valid(const struct m0_op_idx *oi)
1050 {
1051  struct m0_fid *ifid = OI_IFID(oi);
1052 
1055 }
1056 
1057 static void dix_index_delete_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1058 {
1059  struct dix_req *dix_req = ast->sa_datum;
1060  struct m0_op_idx *oi = dix_req->idr_oi;
1061  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1062  struct m0_dix dix;
1063  int rc;
1064  uint32_t flags;
1065 
1066  M0_ENTRY();
1067  dix_build(oi, &dix);
1068  flags = dix_set_cas_flags(oi);
1069 
1071  rc = m0_dix_delete(dreq, &dix, 1, NULL, flags);
1072  if (rc != 0)
1074  M0_LEAVE();
1075 }
1076 
1077 static void dix_index_lookup_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1078 {
1079  struct dix_req *dix_req = ast->sa_datum;
1080  struct m0_op_idx *oi = dix_req->idr_oi;
1081  struct m0_dix_meta_req *mreq = &dix_req->idr_mreq;
1082  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1083  struct m0_dix dix = {};
1084  int rc;
1085 
1086  M0_ENTRY();
1087  if (oi->oi_flags & M0_OIF_SKIP_LAYOUT) {
1088  dix_build(oi, &dix);
1090  rc = m0_dix_cctgs_lookup(dreq, &dix, 1);
1091  } else {
1093  rc = m0_dix_layout_get(mreq, OI_IFID(oi), 1);
1094  }
1095  if (rc != 0)
1097  M0_LEAVE();
1098 }
1099 
1100 static void dix_index_list_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1101 {
1102  struct dix_req *dix_req = ast->sa_datum;
1103  struct m0_op_idx *oi = dix_req->idr_oi;
1104  struct m0_dix dix;
1105  struct m0_dix_meta_req *mreq = &dix_req->idr_mreq;
1106  int rc;
1107 
1108  M0_ENTRY();
1109  dix_build(oi, &dix);
1111  rc = m0_dix_index_list(mreq, OI_IFID(oi), oi->oi_keys->ov_vec.v_nr);
1112  if (rc != 0)
1114  M0_LEAVE();
1115 }
1116 
1117 static void dix_dreq_prepare(struct dix_req *req,
1118  struct m0_dix *dix,
1119  struct m0_op_idx *oi)
1120 {
1121  dix_build(oi, dix);
1122  m0_clink_add(oi->oi_dtx != NULL ?
1123  &oi->oi_dtx->tx_dtx->dd_sm.sm_chan :
1124  &req->idr_dreq.dr_sm.sm_chan, &req->idr_clink);
1125 }
1126 
1127 static void dix_put_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1128 {
1129  struct dix_req *dix_req = ast->sa_datum;
1130  struct m0_op_idx *oi = dix_req->idr_oi;
1131  struct m0_dix dix;
1132  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1133  uint32_t flags;
1134  int rc;
1135 
1136  M0_ENTRY();
1137  dix_dreq_prepare(dix_req, &dix, oi);
1138  flags = dix_set_cas_flags(oi);
1139 
1140  rc = m0_dix_put(dreq, &dix, oi->oi_keys, oi->oi_vals, oi->oi_dtx,
1141  flags);
1142  if (rc != 0)
1144  M0_LEAVE();
1145 }
1146 
1147 static void dix_get_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1148 {
1149  struct dix_req *dix_req = ast->sa_datum;
1150  struct m0_op_idx *oi = dix_req->idr_oi;
1151  struct m0_dix dix;
1152  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1153  int rc;
1154 
1155  M0_ENTRY();
1156  dix_dreq_prepare(dix_req, &dix, oi);
1157  rc = m0_dix_get(dreq, &dix, oi->oi_keys);
1158  if (rc != 0)
1160  M0_LEAVE();
1161 }
1162 
1163 static void dix_del_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1164 {
1165  struct dix_req *dix_req = ast->sa_datum;
1166  struct m0_op_idx *oi = dix_req->idr_oi;
1167  struct m0_dix dix;
1168  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1169  uint32_t flags = 0;
1170  int rc;
1171 
1172  M0_ENTRY();
1173  dix_dreq_prepare(dix_req, &dix, oi);
1174  if (oi->oi_flags & M0_OIF_SYNC_WAIT)
1175  flags |= COF_SYNC_WAIT;
1176  rc = m0_dix_del(dreq, &dix, oi->oi_keys, oi->oi_dtx, flags);
1177  if (rc != 0)
1179  M0_LEAVE();
1180 }
1181 
1182 static void dix_next_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1183 {
1184  struct dix_req *dix_req = ast->sa_datum;
1185  struct m0_op_idx *oi = dix_req->idr_oi;
1186  m0_bcount_t ksize;
1187  struct m0_bufvec *start_key = &dix_req->idr_start_key;
1188  struct m0_dix dix;
1189  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1190  uint32_t flags = 0;
1191  int rc;
1192 
1193  M0_ENTRY();
1194  dix_dreq_prepare(dix_req, &dix, oi);
1200  ksize = oi->oi_keys->ov_vec.v_count[0];
1201  if (ksize == 0) {
1202  M0_ASSERT(oi->oi_keys->ov_buf[0] == NULL);
1203  /*
1204  * Request records from the index beginning. Use the smallest
1205  * key (1-byte zero key).
1206  */
1207  m0_bufvec_alloc(start_key, 1, sizeof(uint8_t));
1208  *(uint8_t *)start_key->ov_buf[0] = 0;
1209  } else {
1210  m0_bufvec_alloc(start_key, 1, ksize);
1211  memcpy(start_key->ov_buf[0], oi->oi_keys->ov_buf[0], ksize);
1212  }
1215  rc = m0_dix_next(dreq, &dix, start_key, &oi->oi_keys->ov_vec.v_nr,
1216  flags);
1217  if (rc != 0)
1219  M0_LEAVE();
1220 }
1221 
1222 /* Cancels launched index operation by cancelling rpc items. */
1223 static void idx_op_cancel_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1224 {
1225  struct m0_op_idx *oi = ast->sa_datum;
1226  struct dix_req *req;
1227  struct m0_dix_req *dreq;
1228 
1229  M0_ENTRY();
1230  if (oi->oi_in_completion)
1231  return;
1232 
1233  req = oi->oi_dix_req;
1234  if (idx_is_distributed(oi)) {
1235  dreq = req->idr_meta ? &req->idr_mreq.dmr_req :
1236  &req->idr_dreq;
1237  m0_dix_req_cancel(dreq);
1238  } else {
1240  }
1241  M0_LEAVE();
1242 }
1243 
1244 M0_INTERNAL int m0__idx_cancel(struct m0_op_idx *oi)
1245 {
1246  struct m0_sm_ast *op_ast;
1247  struct dix_req *req;
1248  struct m0_dix_req *dreq;
1249 
1250  M0_ENTRY();
1251  M0_PRE(oi != NULL);
1252 
1253  op_ast = &oi->oi_ast;
1254  op_ast->sa_cb = idx_op_cancel_ast;
1255  op_ast->sa_datum = oi;
1256 
1257  req = oi->oi_dix_req;
1258  dreq = req->idr_meta ? &req->idr_mreq.dmr_req :
1259  &req->idr_dreq;
1260  /*
1261  * Do no post cancel ast when oi completion/fail
1262  * already called and for not handled types.
1263  */
1264  if (!M0_IN(dreq->dr_type, (DIX_CREATE,
1265  DIX_DELETE,
1266  DIX_CCTGS_LOOKUP)) &&
1267  !oi->oi_in_completion)
1268  m0_sm_ast_post(oi->oi_sm_grp, op_ast);
1269 
1270  return M0_RC(0);
1271 }
1272 
1273 static void dix_set_idx_flags(struct m0_op_idx *oi)
1274 {
1275  if (ENABLE_DTM0)
1277 
1278  if (!(oi->oi_flags & M0_OIF_SKIP_LAYOUT))
1279  oi->oi_flags |= M0_OIF_CROW;
1280 }
1281 
1282 /*--------------------------------------------------------------------------*
1283  * Index query operations *
1284  *--------------------------------------------------------------------------*/
1285 
1286 static int dix_index_create(struct m0_op_idx *oi)
1287 {
1288  struct dix_req *req;
1289  int rc;
1290 
1292  /*
1293  * @todo: User application (S3) need to set M0_OIF_CROW and
1294  * M0_OIF_SKIP_LAYOUT index flags as a configurable parameter.
1295  * Remove this logic once configuration option is available in S3.
1296  */
1297  dix_set_idx_flags(oi);
1298  rc = dix_req_create(oi, &req);
1299  if (rc != 0)
1300  return M0_ERR(rc);
1303  return 1;
1304 }
1305 
1306 static int dix_index_delete(struct m0_op_idx *oi)
1307 {
1308  struct dix_req *req;
1309  int rc;
1310 
1312  /*
1313  * @todo: User application (S3) need to set M0_OIF_CROW and
1314  * M0_OIF_SKIP_LAYOUT index flags as a configurable parameter.
1315  * Remove this logic once configuration option is available in S3.
1316  */
1317  dix_set_idx_flags(oi);
1318  rc = dix_req_create(oi, &req);
1319  if (rc != 0)
1320  return M0_ERR(rc);
1323  return 1;
1324 }
1325 
1326 static int dix_index_lookup(struct m0_op_idx *oi)
1327 {
1328  struct dix_req *req;
1329  int rc;
1330 
1332  /*
1333  * @todo: User application (S3) need to set M0_OIF_CROW and
1334  * M0_OIF_SKIP_LAYOUT index flags as a configurable parameter.
1335  * Remove this logic once configuration option is available in S3.
1336  */
1337  dix_set_idx_flags(oi);
1338  if (oi->oi_flags & M0_OIF_SKIP_LAYOUT)
1339  rc = dix_req_create(oi, &req);
1340  else
1341  rc = dix_mreq_create(oi, &req);
1342  if (rc != 0)
1343  return M0_ERR(rc);
1346  return 1;
1347 }
1348 
1349 static int dix_index_list(struct m0_op_idx *oi)
1350 {
1351  struct dix_req *req;
1352  int rc;
1353 
1355  rc = dix_mreq_create(oi, &req);
1356  if (rc != 0)
1357  return M0_ERR(rc);
1360  return 1;
1361 }
1362 
1363 static int dix_put(struct m0_op_idx *oi)
1364 {
1365  struct dix_req *req;
1366  int rc;
1367 
1368  /*
1369  * @todo: User application (S3) need to set M0_OIF_CROW and
1370  * M0_OIF_SKIP_LAYOUT index flags as a configurable parameter.
1371  * Remove this logic once configuration option is available in S3.
1372  */
1373  dix_set_idx_flags(oi);
1374 
1375  rc = dix_req_create(oi, &req);
1376  if (rc != 0)
1377  return M0_ERR(rc);
1379  return 1;
1380 }
1381 
1382 static int dix_get(struct m0_op_idx *oi)
1383 {
1384  struct dix_req *req;
1385  int rc;
1386 
1387  M0_ASSERT_INFO(oi->oi_keys->ov_vec.v_nr != 0,
1388  "At least one key should be specified");
1390  oi->oi_keys->ov_buf[i] == NULL),
1391  "NULL key is not allowed");
1392  rc = dix_req_create(oi, &req);
1393  if (rc != 0)
1394  return M0_ERR(rc);
1396  return 1;
1397 }
1398 
1399 static int dix_del(struct m0_op_idx *oi)
1400 {
1401  struct dix_req *req;
1402  int rc;
1403 
1404  rc = dix_req_create(oi, &req);
1405  if (rc != 0)
1406  return M0_ERR(rc);
1408  return 1;
1409 }
1410 
1411 static int dix_next(struct m0_op_idx *oi)
1412 {
1413  struct dix_req *req;
1414  int rc;
1415 
1416  rc = dix_req_create(oi, &req);
1417  if (rc != 0)
1418  return M0_ERR(rc);
1420  return 1;
1421 }
1422 
1425  .iqo_namei_delete = dix_index_delete,
1426  .iqo_namei_lookup = dix_index_lookup,
1427  .iqo_namei_list = dix_index_list,
1428 
1429  .iqo_get = dix_get,
1430  .iqo_put = dix_put,
1431  .iqo_del = dix_del,
1432  .iqo_next = dix_next,
1433 };
1434 
1435 /*--------------------------------------------------------------------------*
1436  * Index back-end initialisation and finalisation *
1437  *--------------------------------------------------------------------------*/
1438 
1439 static int dix_root_idx_pver(struct m0_client *m0c, struct m0_fid *out)
1440 {
1441  struct m0_reqh *reqh = &m0c->m0c_reqh;
1442  struct m0_conf_root *root;
1443  int rc;
1444 
1445  /*
1446  * Client will release the lock on confc
1447  * before calling idx_dix_init().
1448  */
1450  if (rc != 0)
1451  return M0_RC(rc);
1452 
1453  *out = root->rt_imeta_pver;
1455 
1456  return 0;
1457 }
1458 
1459 static int dix_client_init(struct dix_inst *inst,
1460  struct m0_client *m0c,
1461  struct m0_idx_dix_config *config)
1462 {
1463  struct m0_dix_cli *dixc = &inst->di_dixc;
1464  struct m0_sm_group *grp = m0_locality0_get()->lo_grp;
1465  struct m0_fid root_pver;
1466  int rc;
1467 
1468  /*
1469  * dix_init() is called from client initialisation machine.
1470  * DIX client start is synchronoush operation that uses it's own
1471  * machine internally. These two state machines should belong to
1472  * different state machine groups, otherwise DIX client start will hang.
1473  */
1474  M0_ASSERT(grp != m0c->m0c_initlift_sm.sm_grp);
1475 
1476  rc = dix_root_idx_pver(m0c, &root_pver) ?:
1477  m0_dix_cli_init(dixc, grp, &m0c->m0c_pools_common,
1478  &m0c->m0c_reqh.rh_ldom, &root_pver);
1479  if (rc != 0)
1480  return M0_ERR(rc);
1481 
1482  dixc->dx_dtms = m0c->m0c_dtms;
1483 
1484  if (config->kc_create_meta) {
1486  rc = m0_dix_meta_create(dixc, grp, &config->kc_layout_ldesc,
1487  &config->kc_ldescr_ldesc);
1488  if (rc != 0) {
1489  m0_dix_cli_stop_lock(dixc);
1490  goto cli_fini;
1491  }
1492  }
1493 
1494  rc = m0_dix_cli_start_sync(&inst->di_dixc);
1495  if (rc != 0)
1496  goto cli_fini;
1497 
1498  /* Set the callback funtion to update FSYNC records. */
1500 
1501  /*
1502  * Use pool version of root index as default pool version for all
1503  * distributed indices. It is temporary until client interface is
1504  * extended to allow user providing pool version for new indices.
1505  */
1506  inst->di_index_pver = root_pver;
1507  return M0_RC(0);
1508 
1509 cli_fini:
1510  m0_dix_cli_fini_lock(&inst->di_dixc);
1511  return M0_ERR(rc);
1512 }
1513 
1514 static int idx_dix_init(void *svc)
1515 {
1516  struct m0_idx_service_ctx *ctx;
1517  struct dix_inst *inst;
1518  struct m0_client *m0c;
1519  int rc;
1520 
1521  M0_ENTRY();
1522  ctx = (struct m0_idx_service_ctx *)svc;
1523  M0_PRE(ctx->isc_svc_conf != NULL);
1524 
1525  M0_ALLOC_PTR(inst);
1526  if (inst == NULL)
1527  return M0_ERR(-ENOMEM);
1528  m0c = M0_AMB(m0c, ctx, m0c_idx_svc_ctx);
1529 
1530  rc = dix_client_init(inst, m0c,
1531  (struct m0_idx_dix_config *)ctx->isc_svc_conf);
1532  if (rc != 0) {
1533  m0_free(inst);
1534  return M0_ERR(rc);
1535  }
1536  ctx->isc_svc_inst = inst;
1537 
1538  M0_POST(ctx->isc_svc_inst != NULL);
1539  return M0_RC(0);
1540 }
1541 
1542 static int idx_dix_fini(void *svc)
1543 {
1544  struct m0_idx_service_ctx *ctx;
1545  struct dix_inst *inst;
1546 
1547  M0_ENTRY();
1548  ctx = (struct m0_idx_service_ctx *)svc;
1549  M0_PRE(ctx->isc_svc_inst != NULL);
1550  inst = ctx->isc_svc_inst;
1551  m0_dix_cli_stop_lock(&inst->di_dixc);
1552  m0_dix_cli_fini_lock(&inst->di_dixc);
1553  m0_free0(&inst);
1554  return M0_RC(0);
1555 }
1556 
1559  .iso_fini = idx_dix_fini
1560 };
1561 
1562 M0_INTERNAL void m0_idx_dix_register(void)
1563 {
1565  &dix_query_ops);
1566 
1567 }
1568 
1569 #undef M0_TRACE_SUBSYSTEM
1570 
1573 /*
1574  * Local variables:
1575  * c-indentation-style: "K&R"
1576  * c-basic-offset: 8
1577  * tab-width: 8
1578  * fill-column: 80
1579  * scroll-step: 1
1580  * End:
1581  */
1582 /*
1583  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
1584  */
static void dixreq_completed_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:697
struct m0_entity * ol_entity
Definition: layout.h:183
M0_INTERNAL void m0_cas_req_fini(struct m0_cas_req *req)
Definition: client.c:291
bool idr_meta
Definition: idx_dix.c:89
static struct dix_inst * dix_inst(const struct m0_op_idx *oi)
Definition: idx_dix.c:170
struct m0_fid idx_pver
Definition: client.h:821
struct m0_dtx * oi_dtx
struct m0_be_tx_remid ccr_remid
Definition: client.h:166
struct m0_dtm0_dtx * tx_dtx
Definition: dtm.h:563
static bool casreq_clink_cb(struct m0_clink *cl)
Definition: idx_dix.c:292
M0_INTERNAL int m0_dix_layout_get(struct m0_dix_meta_req *req, const struct m0_fid *fid, uint32_t nr)
Definition: meta.c:626
#define M0_PRE(cond)
static bool dix_iname_args_are_valid(const struct m0_op_idx *oi)
Definition: idx_dix.c:1049
Definition: dtm.h:554
M0_INTERNAL void m0_dix_get_rep(const struct m0_dix_req *req, uint64_t idx, struct m0_dix_get_reply *rep)
Definition: req.c:2455
M0_INTERNAL bool m0_dix_fid_validate_dix(const struct m0_fid *dix_fid)
Definition: fid_convert.c:88
Definition: client.h:841
M0_INTERNAL void m0_dix_cli_stop_lock(struct m0_dix_cli *cli)
Definition: client.c:261
struct m0_rpc_session * ccr_sess
Definition: client.h:130
struct m0_fid di_index_pver
Definition: idx_dix.c:67
static int dix_list_reply_copy(struct m0_dix_meta_req *req, int32_t *rcs, struct m0_bufvec *bvec)
Definition: idx_dix.c:728
int const char const void size_t int flags
Definition: dir.c:328
M0_INTERNAL int m0_dix_meta_create(struct m0_dix_cli *cli, struct m0_sm_group *grp, struct m0_dix_ldesc *dld_layout, struct m0_dix_ldesc *dld_ldescr)
Definition: meta.c:326
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
Definition: req.h:179
M0_INTERNAL void m0_clink_del(struct m0_clink *link)
Definition: chan.c:267
static struct m0_idx_service_ops dix_svc_ops
Definition: idx_dix.c:1557
static void cas_index_delete_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:401
uint32_t idx_layout_type
Definition: client.h:819
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:1438
M0_INTERNAL void idx_op_ast_complete(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx.c:312
void(* sa_cb)(struct m0_sm_group *grp, struct m0_sm_ast *)
Definition: sm.h:506
static void idx_op_cancel_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1223
static void dix_req_immed_failure(struct dix_req *req, int rc)
Definition: idx_dix.c:992
static struct io_request req
Definition: file.c:100
static struct m0_sm_group * grp
Definition: bytecount.c:38
struct m0_conf_obj rt_obj
Definition: obj.h:372
#define M0_LOG(level,...)
Definition: trace.h:167
static void cas_get_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:476
struct dix_req * oi_dix_req
M0_LEAVE()
uint8_t ft_id
Definition: fid.h:101
M0_INTERNAL void m0_sm_ast_post(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:135
static void dixreq_stable_post(struct dix_req *req, int rc)
Definition: idx_dix.c:843
M0_INTERNAL void idx_op_ast_fail(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx.c:368
struct m0_cas_req idr_creq
Definition: idx_dix.c:82
M0_INTERNAL void m0_idx_service_register(int svc_id, struct m0_idx_service_ops *sops, struct m0_idx_query_ops *qops)
Definition: idx.c:671
Definition: cas.h:247
struct m0_vec ov_vec
Definition: vec.h:147
M0_INTERNAL int m0_dix_delete(struct m0_dix_req *req, const struct m0_dix *indices, uint64_t indices_nr, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:1190
M0_INTERNAL void m0_dix_meta_req_init(struct m0_dix_meta_req *req, struct m0_dix_cli *cli, struct m0_sm_group *grp)
Definition: meta.c:259
void m0_dix_req_cancel(struct m0_dix_req *dreq)
Definition: req.c:1152
static bool idx_is_distributed(const struct m0_op_idx *oi)
Definition: idx_dix.c:98
Definition: idx.h:70
M0_INTERNAL int m0_dix_index_list_rep_nr(struct m0_dix_meta_req *req)
Definition: meta.c:699
M0_INTERNAL void m0_cas_get_rep(const struct m0_cas_req *req, uint64_t idx, struct m0_cas_get_reply *rep)
Definition: client.c:1764
M0_INTERNAL int m0_dix_item_rc(const struct m0_dix_req *req, uint64_t idx)
Definition: req.c:2552
const struct m0_bob_type oi_bobtype
Definition: idx.c:44
static struct m0_clovis * m0c
Definition: main.c:25
struct m0_op oc_op
M0_INTERNAL const struct m0_fid_type m0_cas_index_fid_type
Definition: cas.c:159
static uint32_t dix_set_cas_flags(struct m0_op_idx *oi)
Definition: idx_dix.c:1012
M0_INTERNAL struct m0_dix_cli * ent_dixc(const struct m0_entity *ent)
Definition: idx_dix.c:191
M0_INTERNAL uint8_t m0_fid_tget(const struct m0_fid *fid)
Definition: fid.c:133
static int dix_index_create(struct m0_op_idx *oi)
Definition: idx_dix.c:1286
struct m0_dix_req idr_dreq
Definition: idx_dix.c:80
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:1360
#define m0_exists(var, nr,...)
Definition: misc.h:134
uint64_t m0_bcount_t
Definition: types.h:77
Definition: sm.h:504
static void cas_del_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:492
struct m0_idx_attr in_attr
Definition: client.h:843
static void dix_index_lookup_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1077
struct m0_dix_cli di_dixc
Definition: idx_dix.c:56
#define M0_SET0(obj)
Definition: misc.h:64
M0_ADDB2_ADD(M0_AVI_FS_CREATE, new_fid.f_container, new_fid.f_key, mode, rc)
static bool dixreq_clink_cb(struct m0_clink *cl)
Definition: idx_dix.c:936
struct m0_op_common oi_oc
Definition: config.py:1
static void to_dix_map(const struct m0_op *op, const struct m0_dix_req *req)
Definition: idx_dix.c:637
void(* dx_sync_rec_update)(struct m0_dix_req *, struct m0_rpc_session *, struct m0_be_tx_remid *)
Definition: client.h:202
static struct m0_idx_query_ops dix_query_ops
Definition: idx_dix.c:1423
struct m0_bufvec * oi_keys
M0_INTERNAL bool m0_fid_is_set(const struct m0_fid *fid)
Definition: fid.c:106
struct m0_fop_getxattr_rep * rep
Definition: dir.c:455
static void dixreq_stable_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:829
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:1750
M0_INTERNAL void m0_dix_req_fini(struct m0_dix_req *req)
Definition: req.c:2630
struct m0_sm dd_sm
Definition: dtx.h:61
M0_INTERNAL int m0_bufvec_alloc(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size)
Definition: vec.c:220
uint32_t oi_flags
M0_INTERNAL int m0_confc_root_open(struct m0_confc *confc, struct m0_conf_root **root)
Definition: helpers.c:219
return M0_RC(rc)
op
Definition: libdemo.c:64
unsigned int op_code
Definition: client.h:656
M0_INTERNAL uint64_t m0_dix_req_nr(const struct m0_dix_req *req)
Definition: req.c:2581
struct m0_sm ccr_sm
Definition: client.h:125
#define M0_ENTRY(...)
Definition: trace.h:170
int(* iqo_namei_create)(struct m0_op_idx *oi)
Definition: idx.h:129
static struct m0_sm_ast ast[NR]
Definition: locality.c:44
M0_INTERNAL void m0_bufvec_free(struct m0_bufvec *bufvec)
Definition: vec.c:395
struct m0_entity in_entity
Definition: client.h:842
struct m0_dtm0_service * dx_dtms
Definition: client.h:195
int opcode
Definition: crate.c:301
static void cas_put_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:448
int i
Definition: dir.c:1033
static int dix_index_delete(struct m0_op_idx *oi)
Definition: idx_dix.c:1306
M0_INTERNAL int m0_dix_layout_rep_get(struct m0_dix_meta_req *req, uint64_t idx, struct m0_dix_layout *dlay)
Definition: meta.c:650
Definition: client.h:647
M0_INTERNAL int m0_dix_next(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *start_keys, const uint32_t *recs_nr, uint32_t flags)
Definition: req.c:2492
struct m0_conf_root * root
Definition: note.c:50
static int dix_req_create(struct m0_op_idx *oi, struct dix_req **out)
Definition: idx_dix.c:645
const struct m0_bob_type oc_bobtype
Definition: client.c:44
static void dix_dreq_prepare(struct dix_req *req, struct m0_dix *dix, struct m0_op_idx *oi)
Definition: idx_dix.c:1117
return M0_ERR(-EOPNOTSUPP)
void * sa_datum
Definition: sm.h:508
M0_INTERNAL int m0_cas_req_generic_rc(const struct m0_cas_req *req)
Definition: client.c:460
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:198
struct m0_idx * oi_idx
struct m0_sm dr_sm
Definition: req.h:190
void m0_rpc_item_cancel(struct m0_rpc_item *item)
Definition: item.c:932
M0_INTERNAL struct m0_confc * m0_reqh2confc(struct m0_reqh *reqh)
Definition: reqh.c:753
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
struct m0_fid rt_imeta_pver
Definition: obj.h:403
M0_INTERNAL void m0_cas_put_rep(struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1694
Definition: cas.h:264
static void dix_next_reply_copy(struct m0_dix_req *req, int32_t *rcs, struct m0_bufvec *keys, struct m0_bufvec *vals)
Definition: idx_dix.c:777
#define ENABLE_DTM0
Definition: config.h:36
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:1784
#define m0_free0(pptr)
Definition: memory.h:77
struct m0_sm_ast idr_ast
Definition: idx_dix.c:72
M0_INTERNAL const struct m0_fid_type m0_dix_fid_type
Definition: cas.c:169
#define M0_ASSERT(cond)
m0_dtm0_dtx_state
Definition: dtx.h:31
M0_INTERNAL int m0_dix_get(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys)
Definition: req.c:2434
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:1834
M0_INTERNAL int m0_dix_cli_start_sync(struct m0_dix_cli *cli)
Definition: client.c:221
struct m0_dix_item * dr_items
Definition: req.h:228
static void cas_req_init(struct dix_req *req, struct m0_op_idx *oi)
Definition: idx_dix.c:598
static int dix_del(struct m0_op_idx *oi)
Definition: idx_dix.c:1399
#define bob_of(ptr, type, field, bt)
Definition: bob.h:140
static struct m0_bufvec bvec
Definition: xcode.c:169
M0_INTERNAL void m0_dix_req_init(struct m0_dix_req *req, struct m0_dix_cli *cli, struct m0_sm_group *grp)
Definition: req.c:228
struct m0_clink idr_clink
Definition: idx_dix.c:73
static void dixreq_executed_post(struct dix_req *req, int rc)
Definition: idx_dix.c:859
M0_INTERNAL int m0_dix_ldesc_init(struct m0_dix_ldesc *ld, struct m0_ext *range, m0_bcount_t range_nr, enum m0_dix_hash_fnc_type htype, struct m0_fid *pver)
Definition: layout.c:171
struct m0_op_common ol_oc
Definition: layout.h:175
static void cas_index_cancel(struct dix_req *dix_req)
Definition: idx_dix.c:375
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:1851
struct m0_ast_rc oi_ar
M0_INTERNAL struct dix_inst * ent_dix_inst(const struct m0_entity *ent)
Definition: idx_dix.c:183
M0_INTERNAL void m0_dix_meta_req_fini(struct m0_dix_meta_req *req)
Definition: meta.c:285
static void cas_sync_record_update(struct m0_cas_req *creq, struct m0_rpc_session *rpc_session, struct m0_be_tx_remid *remid)
Definition: idx_dix.c:135
M0_INTERNAL int m0__idx_cancel(struct m0_op_idx *oi)
Definition: idx_dix.c:1244
static int dix_get(struct m0_op_idx *oi)
Definition: idx_dix.c:1382
int(* iso_init)(void *svc)
Definition: idx.h:143
#define M0_POST(cond)
#define OI_IFID(oi)
Definition: idx_dix.c:49
struct m0_fop * ccr_fop
Definition: client.h:132
Definition: reqh.h:94
uint32_t v_nr
Definition: vec.h:51
struct m0_sm_group * lo_grp
Definition: locality.h:67
int32_t sm_rc
Definition: sm.h:336
struct m0_fid ci_fid
Definition: cas.h:113
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:1324
int32_t * oi_rcs
static void cas_next_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:511
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:1491
M0_INTERNAL bool m0__idx_op_invariant(struct m0_op_idx *oi)
Definition: idx.c:74
m0_bcount_t * v_count
Definition: vec.h:53
static int dix_next(struct m0_op_idx *oi)
Definition: idx_dix.c:1411
M0_INTERNAL int m0_dix_create(struct m0_dix_req *req, const struct m0_dix *indices, uint32_t indices_nr, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:990
M0_INTERNAL int m0_dix_index_list(struct m0_dix_meta_req *req, const struct m0_fid *start_fid, uint32_t indices_nr)
Definition: meta.c:669
static struct fdmi_ctx ctx
Definition: main.c:80
static int idx_dix_init(void *svc)
Definition: idx_dix.c:1514
#define FID_P(f)
Definition: fid.h:77
Definition: req.h:181
M0_INTERNAL int m0_dix_index_list_rep(struct m0_dix_meta_req *req, uint32_t idx, struct m0_fid *fid)
Definition: meta.c:704
M0_INTERNAL void idx_op_ast_executed(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx.c:300
static void dix_next_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1182
M0_INTERNAL int m0_dix_cli_init(struct m0_dix_cli *cli, struct m0_sm_group *sm_group, struct m0_pools_common *pc, struct m0_layout_domain *ldom, const struct m0_fid *pver)
Definition: client.c:130
static void cas_index_lookup_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:417
static void cas_list_reply_copy(struct m0_cas_req *req, int32_t *rcs, struct m0_bufvec *bvec)
Definition: idx_dix.c:222
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:1369
bool oi_in_completion
#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 dix_index_create_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1028
struct m0_sm_ast ar_ast
const struct m0_bob_type ol_bobtype
Definition: layout.c:37
static void dix_del_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1163
M0_INTERNAL void m0_dix_cli_bootstrap_lock(struct m0_dix_cli *cli)
Definition: client.c:245
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:1397
struct m0_sm_group * oi_sm_grp
struct m0_reqh reqh
Definition: rm_foms.c:48
M0_INTERNAL void m0_cas_del_rep(struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1882
static int dix_mreq_create(struct m0_op_idx *oi, struct dix_req **out)
Definition: idx_dix.c:609
M0_INTERNAL struct m0_locality * m0_locality0_get(void)
Definition: locality.c:169
void * dr_sync_datum
Definition: req.h:260
M0_INTERNAL uint64_t m0_cas_req_nr(const struct m0_cas_req *req)
Definition: client.c:1311
M0_INTERNAL struct m0_dix_cli * ol_dixc(const struct m0_op_layout *ol)
Definition: idx_dix.c:196
Definition: ext.h:37
struct m0_op_idx * idr_oi
Definition: idx_dix.c:71
Definition: fid.h:38
static struct m0_dix_cli * op_dixc(const struct m0_op_idx *oi)
Definition: idx_dix.c:178
#define OP_IDX2CODE(op_idx)
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:1406
static void dix_get_reply_copy(struct m0_dix_req *dreq, int32_t *rcs, struct m0_bufvec *bvec)
Definition: idx_dix.c:754
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
struct m0_chan sm_chan
Definition: sm.h:331
M0_INTERNAL void m0_clink_add(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:228
static void idx_sync_record_update(struct m0_op *op, struct m0_rpc_session *rpc_session, struct m0_be_tx_remid *remid)
Definition: idx_dix.c:107
struct m0_entity * op_entity
Definition: client.h:666
static int dix_index_list(struct m0_op_idx *oi)
Definition: idx_dix.c:1349
M0_INTERNAL int m0_dix_del(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:2465
struct m0_bufvec * oi_vals
static void cas_next_reply_copy(struct m0_cas_req *req, int32_t *rcs, struct m0_bufvec *keys, struct m0_bufvec *vals)
Definition: idx_dix.c:267
M0_INTERNAL int m0_dix_meta_generic_rc(const struct m0_dix_meta_req *req)
Definition: meta.c:309
static void dix_get_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1147
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:1652
static bool dixreq_clink_dtx_cb(struct m0_clink *cl)
Definition: idx_dix.c:881
struct m0_sm_ast oi_ast
static struct m0_net_test_service svc
Definition: service.c:34
Definition: sm.h:301
M0_INTERNAL enum m0_dtm0_dtx_state m0_dtx0_sm_state(const struct m0_dtx *dtx)
Definition: dtx.c:556
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
static struct m0_fop * fop
Definition: item.c:57
static void cas_req_prepare(struct dix_req *req, struct m0_cas_id *cid, struct m0_op_idx *oi)
Definition: idx_dix.c:366
struct m0_bufvec idr_start_key
Definition: idx_dix.c:78
M0_INTERNAL void m0_dix_get_rep_mlock(struct m0_dix_req *req, uint64_t idx)
Definition: req.c:2586
M0_INTERNAL void m0_confc_close(struct m0_conf_obj *obj)
Definition: confc.c:921
#define M0_ASSERT_INFO(cond, fmt,...)
M0_INTERNAL void m0_cas_rep_mlock(const struct m0_cas_req *req, uint64_t idx)
Definition: client.c:1825
M0_INTERNAL void m0_idx_dix_register(void)
Definition: idx_dix.c:1562
uint32_t en_flags
Definition: client.h:744
static bool dix_meta_req_clink_cb(struct m0_clink *cl)
Definition: idx_dix.c:809
M0_INTERNAL void m0_dix_cli_fini_lock(struct m0_dix_cli *cli)
Definition: client.c:278
Definition: nucleus.c:42
enum dix_req_type dr_type
Definition: req.h:248
static void dix_set_idx_flags(struct m0_op_idx *oi)
Definition: idx_dix.c:1273
#define out(...)
Definition: gen.c:41
static void dix_sync_record_update(struct m0_dix_req *dreq, struct m0_rpc_session *rpc_session, struct m0_be_tx_remid *remid)
Definition: idx_dix.c:149
static int dix_root_idx_pver(struct m0_client *m0c, struct m0_fid *out)
Definition: idx_dix.c:1439
static void dix_build(const struct m0_op_idx *oi, struct m0_dix *out)
Definition: idx_dix.c:554
static void dix_index_list_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1100
M0_INTERNAL void idx_op_ast_stable(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx.c:294
struct m0_dirent * ent
Definition: dir.c:1029
static void cas_index_create_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:385
static int dix_client_init(struct dix_inst *inst, struct m0_client *m0c, struct m0_idx_dix_config *config)
Definition: idx_dix.c:1459
M0_INTERNAL void m0_dix_next_rep_mlock(struct m0_dix_req *req, uint32_t key_idx, uint32_t val_idx)
Definition: req.c:2596
M0_INTERNAL bool m0_fid_is_valid(const struct m0_fid *fid)
Definition: fid.c:96
static struct m0_reqh_service_ctx * svc_find(const struct m0_op_idx *oi)
Definition: idx_dix.c:212
static int dix_index_lookup(struct m0_op_idx *oi)
Definition: idx_dix.c:1326
struct m0_chan dmr_chan
Definition: meta.h:97
static uint8_t ifid_type(bool dist)
Definition: idx_dix.c:188
#define m0_tl_find(name, var, head,...)
Definition: tlist.h:757
M0_INTERNAL void m0_dix_next_rep(const struct m0_dix_req *req, uint64_t key_idx, uint64_t val_idx, struct m0_dix_next_reply *rep)
Definition: req.c:2526
M0_INTERNAL uint64_t m0_sm_id_get(const struct m0_sm *sm)
Definition: sm.c:1021
void sync_record_update(struct m0_reqh_service_ctx *service, struct m0_entity *ent, struct m0_op *op, struct m0_be_tx_remid *btr)
Definition: sync.c:788
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL uint32_t m0_dix_next_rep_nr(const struct m0_dix_req *req, uint64_t key_idx)
Definition: req.c:2545
struct m0_rpc_item f_item
Definition: fop.h:84
Definition: cas.h:107
uint32_t sm_state
Definition: sm.h:307
static struct m0_fid ifid
Definition: service_ut.c:66
static void cas_get_reply_copy(struct m0_cas_req *req, int32_t *rcs, struct m0_bufvec *bvec)
Definition: idx_dix.c:244
int32_t rc
Definition: trigger_fop.h:47
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:1429
M0_INTERNAL int m0_dix_cctgs_lookup(struct m0_dix_req *req, const struct m0_dix *indices, uint32_t indices_nr)
Definition: req.c:1214
M0_INTERNAL bool m0_sm_group_is_locked(const struct m0_sm_group *grp)
Definition: sm.c:107
static void dix_index_delete_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1057
static void dix_put_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1127
M0_INTERNAL int m0_dix_put(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys, const struct m0_bufvec *vals, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:2401
static void cas_index_list_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:433
struct m0_dix_meta_req idr_mreq
Definition: idx_dix.c:84
static int idx_dix_fini(void *svc)
Definition: idx_dix.c:1542
static void dix_req_destroy(struct dix_req *req)
Definition: idx_dix.c:680
Definition: fop.h:80
#define FID_F
Definition: fid.h:75
M0_INTERNAL void m0_dix_fini(struct m0_dix *dix)
Definition: req.c:2680
Definition: vec.h:145
static int dix_put(struct m0_op_idx *oi)
Definition: idx_dix.c:1363
Definition: req.h:110
static void dix_req_exec(struct dix_req *req, void(*exec_fn)(struct m0_sm_group *grp, struct m0_sm_ast *ast))
Definition: idx_dix.c:1001
M0_INTERNAL int m0_dix_generic_rc(const struct m0_dix_req *req)
Definition: req.c:2560
#define M0_IMPOSSIBLE(fmt,...)
M0_INTERNAL struct m0_reqh_service_ctx * m0_reqh_service_ctx_from_session(struct m0_rpc_session *session)
M0_INTERNAL struct m0_client * m0__entity_instance(const struct m0_entity *entity)
Definition: client.c:226
static void dixreq_completed_post(struct dix_req *req, int rc)
Definition: idx_dix.c:716