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  if (oi->oi_flags & M0_OIF_OVERWRITE)
460  flags |= COF_OVERWRITE;
461  if (oi->oi_flags & M0_OIF_SYNC_WAIT)
462  flags |= COF_SYNC_WAIT;
463  rc = m0_cas_put(creq, &idx, oi->oi_keys, oi->oi_vals, NULL, flags);
464  if (rc != 0)
466  M0_LEAVE();
467 }
468 
469 static void cas_get_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
470 {
471  struct dix_req *dix_req = ast->sa_datum;
472  struct m0_op_idx *oi = dix_req->idr_oi;
473  struct m0_cas_id idx;
474  struct m0_cas_req *creq = &dix_req->idr_creq;
475  int rc;
476 
477  M0_ENTRY();
478  cas_req_prepare(dix_req, &idx, oi);
479  rc = m0_cas_get(creq, &idx, oi->oi_keys);
480  if (rc != 0)
482  M0_LEAVE();
483 }
484 
485 static void cas_del_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
486 {
487  struct dix_req *dix_req = ast->sa_datum;
488  struct m0_op_idx *oi = dix_req->idr_oi;
489  struct m0_cas_id idx;
490  struct m0_cas_req *creq = &dix_req->idr_creq;
491  uint32_t flags = 0;
492  int rc;
493 
494  M0_ENTRY();
495  cas_req_prepare(dix_req, &idx, oi);
496  if (oi->oi_flags & M0_OIF_SYNC_WAIT)
497  flags |= COF_SYNC_WAIT;
498  rc = m0_cas_del(creq, &idx, oi->oi_keys, NULL, flags);
499  if (rc != 0)
501  M0_LEAVE();
502 }
503 
504 static void cas_next_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
505 {
506  struct dix_req *dix_req = ast->sa_datum;
507  struct m0_op_idx *oi = dix_req->idr_oi;
508  struct m0_cas_id idx;
509  struct m0_cas_req *creq = &dix_req->idr_creq;
510  m0_bcount_t ksize;
511  struct m0_bufvec *start_key = &dix_req->idr_start_key;
512  uint32_t flags = COF_SLANT;
513  int rc;
514 
515  M0_ENTRY();
516  cas_req_prepare(dix_req, &idx, oi);
522  ksize = oi->oi_keys->ov_vec.v_count[0];
523  if (ksize == 0) {
524  M0_ASSERT(oi->oi_keys->ov_buf[0] == NULL);
525  /*
526  * Request records from the index beginning. Use the smallest
527  * key (1-byte zero key).
528  */
529  m0_bufvec_alloc(start_key, 1, sizeof(uint8_t));
530  *(uint8_t *)start_key->ov_buf[0] = 0;
531  } else {
532  m0_bufvec_alloc(start_key, 1, ksize);
533  memcpy(start_key->ov_buf[0], oi->oi_keys->ov_buf[0], ksize);
534  }
537  rc = m0_cas_next(creq, &idx, start_key, &oi->oi_keys->ov_vec.v_nr,
538  flags);
539  if (rc != 0)
541  M0_LEAVE();
542 }
543 
544 /*--------------------------------------------------------------------------*
545  * Distributed (DIX) indices routines *
546  *--------------------------------------------------------------------------*/
547 static void dix_build(const struct m0_op_idx *oi,
548  struct m0_dix *out)
549 {
550  unsigned int opcode = OP_IDX2CODE(oi);
551  struct m0_idx *idx = oi->oi_idx;
552 
553  M0_SET0(out);
554  out->dd_fid = *OI_IFID(oi);
555  /* Pool version and layout type which are passed by consumers like S3 */
556  if (M0_IN(opcode, (M0_IC_GET, M0_IC_PUT, M0_IC_DEL, M0_IC_NEXT))) {
558  && (m0_fid_is_set(&idx->in_attr.idx_pver))
559  && (m0_fid_is_valid(&idx->in_attr.idx_pver))) {
560  M0_LOG(M0_DEBUG, "Opcode: %u, DIX pool version:"FID_F"",
561  opcode, FID_P(&idx->in_attr.idx_pver));
562 
563  out->dd_layout.dl_type = DIX_LTYPE_DESCR;
564  m0_dix_ldesc_init(&out->dd_layout.u.dl_desc,
565  &(struct m0_ext) { .e_start = 0,
566  .e_end = IMASK_INF }, 1,
568  &idx->in_attr.idx_pver);
569  }
570  } else if (M0_IN(opcode, (M0_EO_CREATE)) ||
571  (oi->oi_flags & M0_OIF_SKIP_LAYOUT)) {
572  /*
573  * Use default layout for all indices:
574  * - city hash function;
575  * - infinity identity mask (use key as is);
576  * - default pool version (the same as for root index).
577  * In future client user will be able to pass layout as an
578  * argument.
579  */
580  out->dd_layout.dl_type = DIX_LTYPE_DESCR;
581 
582  m0_dix_ldesc_init(&out->dd_layout.u.dl_desc,
583  &(struct m0_ext) { .e_start = 0,
584  .e_end = IMASK_INF }, 1, HASH_FNC_CITY,
585  (idx->in_entity.en_flags & M0_ENF_META) ?
586  &idx->in_attr.idx_pver :
587  &dix_inst(oi)->di_index_pver);
588  }
589 }
590 
591 static void cas_req_init(struct dix_req *req,
592  struct m0_op_idx *oi)
593 {
594  struct m0_reqh_service_ctx *svc;
595 
596  svc = svc_find(oi);
597  M0_ASSERT(svc != NULL);
598  m0_cas_req_init(&req->idr_creq, &svc->sc_rlink.rlk_sess, oi->oi_sm_grp);
599  m0_clink_init(&req->idr_clink, casreq_clink_cb);
600 }
601 
602 static int dix_mreq_create(struct m0_op_idx *oi,
603  struct dix_req **out)
604 {
605  struct dix_req *req;
606 
607  M0_ALLOC_PTR(req);
608  if (req == NULL)
609  return M0_ERR(-ENOMEM);
610  if (idx_is_distributed(oi)) {
611  m0_dix_meta_req_init(&req->idr_mreq, op_dixc(oi),
612  oi->oi_sm_grp);
614 
615  /*
616  * Currently only LOOKUP and LIST create meta request, so
617  * don't need to set callback datum here.
618  */
619  } else {
620  cas_req_init(req, oi);
621  }
622 
623  req->idr_oi = oi;
624  oi->oi_dix_req = req;
625  req->idr_meta = true;
626  *out = req;
627  return M0_RC(0);
628 }
629 
630 static void to_dix_map(const struct m0_op *op,
631  const struct m0_dix_req *req)
632 {
633  uint64_t cid = m0_sm_id_get(&op->op_sm);
634  uint64_t did = m0_sm_id_get(&req->dr_sm);
636 }
637 
638 static int dix_req_create(struct m0_op_idx *oi,
639  struct dix_req **out)
640 {
641  struct dix_req *req;
642  int rc = 0;
643  M0_ENTRY();
644 
645  M0_ALLOC_PTR(req);
646  if (req != NULL) {
647  if (idx_is_distributed(oi)) {
648  m0_dix_req_init(&req->idr_dreq, op_dixc(oi),
649  oi->oi_sm_grp);
650  to_dix_map(&oi->oi_oc.oc_op, &req->idr_dreq);
651  req->idr_dreq.dr_dtx = oi->oi_dtx;
652  m0_clink_init(&req->idr_clink,
653  oi->oi_dtx != NULL ?
655 
656  /* Store oi for dix callbacks to update SYNC records. */
657  if (M0_IN(oi->oi_oc.oc_op.op_code,
659  M0_IC_PUT, M0_IC_DEL)))
660  req->idr_dreq.dr_sync_datum =
661  (void *)&oi->oi_oc.oc_op;
662  } else {
663  cas_req_init(req, oi);
664  }
665  req->idr_oi = oi;
666  oi->oi_dix_req = req;
667  *out = req;
668  } else
669  rc = M0_ERR(-ENOMEM);
670  return M0_RC(rc);
671 }
672 
673 static void dix_req_destroy(struct dix_req *req)
674 {
675  M0_ENTRY();
676  m0_clink_fini(&req->idr_clink);
677  m0_bufvec_free(&req->idr_start_key);
678  if (idx_is_distributed(req->idr_oi)) {
679  if (req->idr_meta)
680  m0_dix_meta_req_fini(&req->idr_mreq);
681  else
682  m0_dix_req_fini(&req->idr_dreq);
683  } else {
684  m0_cas_req_fini(&req->idr_creq);
685  }
686  m0_free(req);
687  M0_LEAVE();
688 }
689 
690 static void dixreq_completed_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
691 {
692  struct dix_req *req = ast->sa_datum;
693  struct m0_op_idx *oi = req->idr_oi;
694  int rc = oi->oi_ar.ar_rc;
695 
696  M0_ENTRY();
697  oi->oi_ar.ar_ast.sa_cb = (rc == 0) ? idx_op_ast_complete :
699  oi->oi_in_completion = true;
700  /* XXX: it looks like there is no need to set up an ast for that.
701  * The groups are the same. We can just call the callback right here?
702  * oi->oi_ar.ar_ast.sa_cb(oi->oi_sm_grp, &oi->oi_ar.ar_ast)
703  */
706  M0_LEAVE();
707 }
708 
709 static void dixreq_completed_post(struct dix_req *req, int rc)
710 {
711  struct m0_op_idx *oi = req->idr_oi;
712 
713  M0_ENTRY();
714  oi->oi_ar.ar_rc = rc;
715  req->idr_ast.sa_cb = dixreq_completed_ast;
716  req->idr_ast.sa_datum = req;
717  m0_sm_ast_post(oi->oi_sm_grp, &req->idr_ast);
718  M0_LEAVE();
719 }
720 
722  int32_t *rcs,
723  struct m0_bufvec *bvec)
724 {
725  uint64_t rep_count = m0_dix_index_list_rep_nr(req);
726  uint64_t i;
727 
728  /* Assertion is guaranteed by DIX/CAS client. */
729  M0_PRE(bvec->ov_vec.v_nr >= rep_count);
730  for (i = 0; i < rep_count; i++) {
731  /* User should allocate buffer of appropriate size */
732  M0_ASSERT(bvec->ov_vec.v_count[i] == sizeof(struct m0_fid));
733  rcs[i] = m0_dix_index_list_rep(req, i,
734  (struct m0_fid *)bvec->ov_buf[i]);
735  }
736 
737  /*
738  * If number of listed indices is less than was requested by user, then
739  * there are no more indices to list. Fill tail of return codes array
740  * with -ENOENT for non-existing indices.
741  */
742  for (i = rep_count; i < bvec->ov_vec.v_nr; i++)
743  rcs[i] = -ENOENT;
744  return M0_RC(0);
745 }
746 
747 static void dix_get_reply_copy(struct m0_dix_req *dreq,
748  int32_t *rcs,
749  struct m0_bufvec *bvec)
750 {
751  uint64_t rep_count = m0_dix_req_nr(dreq);
752  struct m0_dix_get_reply rep;
753  uint64_t i;
754 
755  /* Assertion is guaranteed by DIX client. */
756  M0_PRE(bvec->ov_vec.v_nr >= rep_count);
757  for (i = 0; i < rep_count; i++) {
758  m0_dix_get_rep(dreq, i, &rep);
759  M0_ASSERT(bvec->ov_vec.v_count[i] == 0);
760  M0_ASSERT(bvec->ov_buf[i] == NULL);
761  rcs[i] = rep.dgr_rc;
762  if (rep.dgr_rc == 0) {
763  m0_dix_get_rep_mlock(dreq, i);
764  bvec->ov_vec.v_count[i] = rep.dgr_val.b_nob;
765  bvec->ov_buf[i] = rep.dgr_val.b_addr;
766  }
767  }
768 }
769 
770 static void dix_next_reply_copy(struct m0_dix_req *req,
771  int32_t *rcs,
772  struct m0_bufvec *keys,
773  struct m0_bufvec *vals)
774 {
775  uint64_t rep_count = m0_dix_next_rep_nr(req, 0);
776  struct m0_dix_next_reply rep;
777  uint64_t i;
778  uint64_t k = 0;
779 
780  /* Assertions are guaranteed by DIX client. */
781  M0_PRE(keys->ov_vec.v_nr >= rep_count);
782  M0_PRE(vals->ov_vec.v_nr >= rep_count);
783  for (i = 0; i < rep_count; i++) {
784  rcs[i] = 0;
785  m0_dix_next_rep(req, 0, i, &rep);
787  keys->ov_vec.v_count[k] = rep.dnr_key.b_nob;
788  keys->ov_buf[k] = rep.dnr_key.b_addr;
789  vals->ov_vec.v_count[k] = rep.dnr_val.b_nob;
790  vals->ov_buf[k] = rep.dnr_val.b_addr;
791  k++;
792  }
793  /*
794  * If number of retrieved records is less than was requested by user,
795  * then there are no more records in the index. Fill tail of return
796  * codes array with -ENOENT for non-existing records.
797  */
798  for (i = rep_count; i < keys->ov_vec.v_nr; i++)
799  rcs[i] = -ENOENT;
800 }
801 
802 static bool dix_meta_req_clink_cb(struct m0_clink *cl)
803 {
804  struct dix_req *dix_req = M0_AMB(dix_req, cl, idr_clink);
805  struct m0_op_idx *oi = dix_req->idr_oi;
806  struct m0_dix_meta_req *mreq = &dix_req->idr_mreq;
807  struct m0_op *op;
808  int rc;
809 
810  m0_clink_del(cl);
811  op = &oi->oi_oc.oc_op;
813  M0_ASSERT(M0_IN(op->op_code,(M0_IC_LIST, M0_IC_LOOKUP)));
814  rc = m0_dix_meta_generic_rc(mreq) ?:
815  (op->op_code == M0_IC_LIST) ?
816  dix_list_reply_copy(mreq, oi->oi_rcs, oi->oi_keys) :
817  m0_dix_layout_rep_get(mreq, 0, NULL);
819  return false;
820 }
821 
822 static void dixreq_stable_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
823 {
824  struct dix_req *req = ast->sa_datum;
825  struct m0_op_idx *oi = req->idr_oi;
826  int rc = oi->oi_ar.ar_rc;
827 
828  M0_ENTRY();
829  oi->oi_ar.ar_ast.sa_cb = (rc == 0) ? idx_op_ast_stable : NULL;
830  M0_ASSERT(grp == oi->oi_sm_grp);
833  M0_LEAVE();
834 }
835 
836 static void dixreq_stable_post(struct dix_req *req, int rc)
837 {
838  struct m0_op_idx *oi = req->idr_oi;
839 
840  M0_ENTRY();
841  oi->oi_ar.ar_rc = rc;
842  req->idr_ast.sa_cb = dixreq_stable_ast;
843  req->idr_ast.sa_datum = req;
844  M0_ASSERT_INFO(req->idr_ast.sa_next == NULL,
845  "Stable() ast cannot be armed before Executed() "
846  "is completed. Ensure EXECUTED_ALL -> STABLE transition"
847  "does not happen within the same ast tick");
848  m0_sm_ast_post(oi->oi_sm_grp, &req->idr_ast);
849  M0_LEAVE();
850 }
851 
852 static void dixreq_executed_post(struct dix_req *req, int rc)
853 {
854  struct m0_op_idx *oi = req->idr_oi;
855 
856  M0_ENTRY();
857 
858  M0_ASSERT_INFO(rc == 0, "TODO: Failures are not handled here.");
859  oi->oi_ar.ar_rc = rc;
860 
861  /* XXX: DTX cannot be canceled (as per the current design),
862  * so that once we got a reply, we prohibit any kind of cancelation.
863  * The originator should m0_panic itself in case if something needs
864  * to be canceled. It will be re-started and continue its execution.
865  */
866  oi->oi_in_completion = true;
868  M0_ASSERT(req->idr_dreq.dr_dtx->tx_dtx->dd_sm.sm_grp == oi->oi_sm_grp);
871  M0_LEAVE();
872 }
873 
874 static bool dixreq_clink_dtx_cb(struct m0_clink *cl)
875 {
876  struct dix_req *dix_req = M0_AMB(dix_req, cl, idr_clink);
877  struct m0_op_idx *oi = dix_req->idr_oi;
878  struct m0_sm *req_sm = M0_AMB(req_sm, cl->cl_chan, sm_chan);
879  struct m0_dix_req *dreq = &dix_req->idr_dreq;
880  struct m0_dtx *dtx = oi->oi_dtx;
881  enum m0_dtm0_dtx_state state;
882  int i;
883 
884  M0_PRE(M0_IN(oi->oi_oc.oc_op.op_code, (M0_IC_PUT, M0_IC_DEL)));
885  M0_PRE(dtx != NULL);
886 
887  state = m0_dtx0_sm_state(dtx);
888 
889  if (!M0_IN(state, (M0_DDS_EXECUTED_ALL, M0_DDS_STABLE, M0_DDS_FAILED)))
890  return false;
891 
892  switch (state) {
893  case M0_DDS_EXECUTED_ALL:
894  /* TODO: we have a single kv pair; probably, it does not have
895  * to be a loop.
896  */
897  for (i = 0; i < m0_dix_req_nr(dreq); i++) {
898  oi->oi_rcs[i] = dreq->dr_items[i].dxi_rc;
899  }
900  /* XXX: We cannot use m0_dix_generic_rc here because the
901  * precondition fails in this case. At this point error
902  * handling is not covered here, and probably the error
903  * code needs to be first propogated from DIX to DTX and
904  * then it needs to be passed here as dtx.dd_sm.sm_rc.
905  */
907  break;
908  case M0_DDS_STABLE:
910  "TODO: DIX failures are not supported.");
911 
913  m0_dix_item_rc(dreq, idx) == 0),
914  "TODO: failed executions of individual items "
915  "are not supported yet.");
916 
918  m0_clink_del(cl);
919  break;
920  case M0_DDS_FAILED:
921  M0_IMPOSSIBLE("DTX failures are not supported so far.");
922  default:
923  M0_IMPOSSIBLE("Only Executed and Stable are allowed so far.");
924  }
925 
926  return false;
927 }
928 
929 static bool dixreq_clink_cb(struct m0_clink *cl)
930 {
931  struct dix_req *dix_req = M0_AMB(dix_req, cl, idr_clink);
932  struct m0_op_idx *oi = dix_req->idr_oi;
933  struct m0_sm *req_sm = M0_AMB(req_sm, cl->cl_chan, sm_chan);
934  struct m0_dix_req *dreq = M0_AMB(dreq, req_sm, dr_sm);
935  uint32_t state = dreq->dr_sm.sm_state;
936  struct m0_op *op;
937  int i;
938  int rc;
939 
940  if (!M0_IN(state, (DIXREQ_FAILURE, DIXREQ_FINAL)))
941  return false;
942 
943  m0_clink_del(cl);
944  op = &oi->oi_oc.oc_op;
945 
946  rc = m0_dix_generic_rc(dreq);
947  if (rc == 0) {
948  /*
949  * Response from CAS service is validated by CAS/DIX client,
950  * including number of records in response.
951  */
952  switch (op->op_code) {
953  case M0_EO_CREATE:
954  case M0_EO_DELETE:
955  M0_ASSERT(m0_dix_req_nr(dreq) == 1);
956  rc = m0_dix_item_rc(dreq, 0);
957  break;
958  case M0_IC_PUT:
959  case M0_IC_DEL:
960  for (i = 0; i < m0_dix_req_nr(dreq); i++)
961  oi->oi_rcs[i] = m0_dix_item_rc(dreq, i);
962  break;
963  case M0_IC_GET:
964  dix_get_reply_copy(dreq, oi->oi_rcs, oi->oi_vals);
965  break;
966  case M0_IC_NEXT:
967  dix_next_reply_copy(dreq, oi->oi_rcs, oi->oi_keys,
968  oi->oi_vals);
969  break;
970  case M0_IC_LOOKUP:
971  if (oi->oi_flags & M0_OIF_SKIP_LAYOUT) {
972  M0_ASSERT(m0_dix_req_nr(dreq) == 1);
973  rc = m0_dix_item_rc(dreq, 0);
974  }
975  break;
976  default:
977  M0_IMPOSSIBLE("Invalid op code");
978  }
979  }
980 
982  return false;
983 }
984 
985 static void dix_req_immed_failure(struct dix_req *req, int rc)
986 {
987  M0_ENTRY();
988  M0_PRE(rc != 0);
989  m0_clink_del(&req->idr_clink);
991  M0_LEAVE();
992 }
993 
994 static void dix_req_exec(struct dix_req *req,
995  void (*exec_fn)(struct m0_sm_group *grp,
996  struct m0_sm_ast *ast))
997 {
998  M0_ENTRY();
999  req->idr_ast.sa_cb = exec_fn;
1000  req->idr_ast.sa_datum = req;
1001  m0_sm_ast_post(req->idr_oi->oi_sm_grp, &req->idr_ast);
1002  M0_LEAVE();
1003 }
1004 
1005 static uint32_t dix_set_cas_flags(struct m0_op_idx *oi)
1006 {
1007  uint32_t flags = 0;
1008  if (oi->oi_flags & M0_OIF_OVERWRITE)
1009  flags |= COF_OVERWRITE;
1010  if (oi->oi_flags & M0_OIF_SYNC_WAIT)
1011  flags |= COF_SYNC_WAIT;
1012  if (oi->oi_flags & M0_OIF_CROW)
1013  flags |= COF_CROW;
1014  if (oi->oi_flags & M0_OIF_SKIP_LAYOUT)
1016  return flags;
1017 }
1018 
1019 static void dix_index_create_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1020 {
1021  struct dix_req *dix_req = ast->sa_datum;
1022  struct m0_op_idx *oi = dix_req->idr_oi;
1023  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1024  struct m0_dix dix;
1025  int rc;
1026  uint32_t flags;
1027 
1028  M0_ENTRY();
1029  dix_build(oi, &dix);
1030  flags = dix_set_cas_flags(oi);
1031 
1033  rc = m0_dix_create(dreq, &dix, 1, NULL, flags);
1034  if (rc != 0)
1036  m0_dix_fini(&dix);
1037  M0_LEAVE();
1038 }
1039 
1040 static bool dix_iname_args_are_valid(const struct m0_op_idx *oi)
1041 {
1042  struct m0_fid *ifid = OI_IFID(oi);
1043 
1046 }
1047 
1048 static void dix_index_delete_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1049 {
1050  struct dix_req *dix_req = ast->sa_datum;
1051  struct m0_op_idx *oi = dix_req->idr_oi;
1052  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1053  struct m0_dix dix;
1054  int rc;
1055  uint32_t flags;
1056 
1057  M0_ENTRY();
1058  dix_build(oi, &dix);
1059  flags = dix_set_cas_flags(oi);
1060 
1062  rc = m0_dix_delete(dreq, &dix, 1, NULL, flags);
1063  if (rc != 0)
1065  M0_LEAVE();
1066 }
1067 
1068 static void dix_index_lookup_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1069 {
1070  struct dix_req *dix_req = ast->sa_datum;
1071  struct m0_op_idx *oi = dix_req->idr_oi;
1072  struct m0_dix_meta_req *mreq = &dix_req->idr_mreq;
1073  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1074  struct m0_dix dix = {};
1075  int rc;
1076 
1077  M0_ENTRY();
1078  if (oi->oi_flags & M0_OIF_SKIP_LAYOUT) {
1079  dix_build(oi, &dix);
1081  rc = m0_dix_cctgs_lookup(dreq, &dix, 1);
1082  } else {
1084  rc = m0_dix_layout_get(mreq, OI_IFID(oi), 1);
1085  }
1086  if (rc != 0)
1088  M0_LEAVE();
1089 }
1090 
1091 static void dix_index_list_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1092 {
1093  struct dix_req *dix_req = ast->sa_datum;
1094  struct m0_op_idx *oi = dix_req->idr_oi;
1095  struct m0_dix dix;
1096  struct m0_dix_meta_req *mreq = &dix_req->idr_mreq;
1097  int rc;
1098 
1099  M0_ENTRY();
1100  dix_build(oi, &dix);
1102  rc = m0_dix_index_list(mreq, OI_IFID(oi), oi->oi_keys->ov_vec.v_nr);
1103  if (rc != 0)
1105  M0_LEAVE();
1106 }
1107 
1108 static void dix_dreq_prepare(struct dix_req *req,
1109  struct m0_dix *dix,
1110  struct m0_op_idx *oi)
1111 {
1112  dix_build(oi, dix);
1113  m0_clink_add(oi->oi_dtx != NULL ?
1114  &oi->oi_dtx->tx_dtx->dd_sm.sm_chan :
1115  &req->idr_dreq.dr_sm.sm_chan, &req->idr_clink);
1116 }
1117 
1118 static void dix_put_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1119 {
1120  struct dix_req *dix_req = ast->sa_datum;
1121  struct m0_op_idx *oi = dix_req->idr_oi;
1122  struct m0_dix dix;
1123  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1124  uint32_t flags;
1125  int rc;
1126 
1127  M0_ENTRY();
1128  dix_dreq_prepare(dix_req, &dix, oi);
1129  flags = dix_set_cas_flags(oi);
1130 
1131  rc = m0_dix_put(dreq, &dix, oi->oi_keys, oi->oi_vals, oi->oi_dtx,
1132  flags);
1133  if (rc != 0)
1135  M0_LEAVE();
1136 }
1137 
1138 static void dix_get_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1139 {
1140  struct dix_req *dix_req = ast->sa_datum;
1141  struct m0_op_idx *oi = dix_req->idr_oi;
1142  struct m0_dix dix;
1143  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1144  int rc;
1145 
1146  M0_ENTRY();
1147  dix_dreq_prepare(dix_req, &dix, oi);
1148  rc = m0_dix_get(dreq, &dix, oi->oi_keys);
1149  if (rc != 0)
1151  M0_LEAVE();
1152 }
1153 
1154 static void dix_del_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1155 {
1156  struct dix_req *dix_req = ast->sa_datum;
1157  struct m0_op_idx *oi = dix_req->idr_oi;
1158  struct m0_dix dix;
1159  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1160  uint32_t flags = 0;
1161  int rc;
1162 
1163  M0_ENTRY();
1164  dix_dreq_prepare(dix_req, &dix, oi);
1165  if (oi->oi_flags & M0_OIF_SYNC_WAIT)
1166  flags |= COF_SYNC_WAIT;
1167  rc = m0_dix_del(dreq, &dix, oi->oi_keys, oi->oi_dtx, flags);
1168  if (rc != 0)
1170  M0_LEAVE();
1171 }
1172 
1173 static void dix_next_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1174 {
1175  struct dix_req *dix_req = ast->sa_datum;
1176  struct m0_op_idx *oi = dix_req->idr_oi;
1177  m0_bcount_t ksize;
1178  struct m0_bufvec *start_key = &dix_req->idr_start_key;
1179  struct m0_dix dix;
1180  struct m0_dix_req *dreq = &dix_req->idr_dreq;
1181  uint32_t flags = 0;
1182  int rc;
1183 
1184  M0_ENTRY();
1185  dix_dreq_prepare(dix_req, &dix, oi);
1191  ksize = oi->oi_keys->ov_vec.v_count[0];
1192  if (ksize == 0) {
1193  M0_ASSERT(oi->oi_keys->ov_buf[0] == NULL);
1194  /*
1195  * Request records from the index beginning. Use the smallest
1196  * key (1-byte zero key).
1197  */
1198  m0_bufvec_alloc(start_key, 1, sizeof(uint8_t));
1199  *(uint8_t *)start_key->ov_buf[0] = 0;
1200  } else {
1201  m0_bufvec_alloc(start_key, 1, ksize);
1202  memcpy(start_key->ov_buf[0], oi->oi_keys->ov_buf[0], ksize);
1203  }
1206  rc = m0_dix_next(dreq, &dix, start_key, &oi->oi_keys->ov_vec.v_nr,
1207  flags);
1208  if (rc != 0)
1210  M0_LEAVE();
1211 }
1212 
1213 /* Cancels launched index operation by cancelling rpc items. */
1214 static void idx_op_cancel_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1215 {
1216  struct m0_op_idx *oi = ast->sa_datum;
1217  struct dix_req *req;
1218  struct m0_dix_req *dreq;
1219 
1220  M0_ENTRY();
1221  if (oi->oi_in_completion)
1222  return;
1223 
1224  req = oi->oi_dix_req;
1225  if (idx_is_distributed(oi)) {
1226  dreq = req->idr_meta ? &req->idr_mreq.dmr_req :
1227  &req->idr_dreq;
1228  m0_dix_req_cancel(dreq);
1229  } else {
1231  }
1232  M0_LEAVE();
1233 }
1234 
1235 M0_INTERNAL int m0__idx_cancel(struct m0_op_idx *oi)
1236 {
1237  struct m0_sm_ast *op_ast;
1238  struct dix_req *req;
1239  struct m0_dix_req *dreq;
1240 
1241  M0_ENTRY();
1242  M0_PRE(oi != NULL);
1243 
1244  op_ast = &oi->oi_ast;
1245  op_ast->sa_cb = idx_op_cancel_ast;
1246  op_ast->sa_datum = oi;
1247 
1248  req = oi->oi_dix_req;
1249  dreq = req->idr_meta ? &req->idr_mreq.dmr_req :
1250  &req->idr_dreq;
1251  /*
1252  * Do no post cancel ast when oi completion/fail
1253  * already called and for not handled types.
1254  */
1255  if (!M0_IN(dreq->dr_type, (DIX_CREATE,
1256  DIX_DELETE,
1257  DIX_CCTGS_LOOKUP)) &&
1258  !oi->oi_in_completion)
1259  m0_sm_ast_post(oi->oi_sm_grp, op_ast);
1260 
1261  return M0_RC(0);
1262 }
1263 
1264 static void dix_set_idx_flags(struct m0_op_idx *oi)
1265 {
1266  if (ENABLE_DTM0)
1268 
1269  if (!(oi->oi_flags & M0_OIF_SKIP_LAYOUT))
1270  oi->oi_flags |= M0_OIF_CROW;
1271 }
1272 
1273 /*--------------------------------------------------------------------------*
1274  * Index query operations *
1275  *--------------------------------------------------------------------------*/
1276 
1277 static int dix_index_create(struct m0_op_idx *oi)
1278 {
1279  struct dix_req *req;
1280  int rc;
1281 
1283  /*
1284  * @todo: User application (S3) need to set M0_OIF_CROW and
1285  * M0_OIF_SKIP_LAYOUT index flags as a configurable parameter.
1286  * Remove this logic once configuration option is available in S3.
1287  */
1288  dix_set_idx_flags(oi);
1289  rc = dix_req_create(oi, &req);
1290  if (rc != 0)
1291  return M0_ERR(rc);
1294  return 1;
1295 }
1296 
1297 static int dix_index_delete(struct m0_op_idx *oi)
1298 {
1299  struct dix_req *req;
1300  int rc;
1301 
1303  /*
1304  * @todo: User application (S3) need to set M0_OIF_CROW and
1305  * M0_OIF_SKIP_LAYOUT index flags as a configurable parameter.
1306  * Remove this logic once configuration option is available in S3.
1307  */
1308  dix_set_idx_flags(oi);
1309  rc = dix_req_create(oi, &req);
1310  if (rc != 0)
1311  return M0_ERR(rc);
1314  return 1;
1315 }
1316 
1317 static int dix_index_lookup(struct m0_op_idx *oi)
1318 {
1319  struct dix_req *req;
1320  int rc;
1321 
1323  /*
1324  * @todo: User application (S3) need to set M0_OIF_CROW and
1325  * M0_OIF_SKIP_LAYOUT index flags as a configurable parameter.
1326  * Remove this logic once configuration option is available in S3.
1327  */
1328  dix_set_idx_flags(oi);
1329  if (oi->oi_flags & M0_OIF_SKIP_LAYOUT)
1330  rc = dix_req_create(oi, &req);
1331  else
1332  rc = dix_mreq_create(oi, &req);
1333  if (rc != 0)
1334  return M0_ERR(rc);
1337  return 1;
1338 }
1339 
1340 static int dix_index_list(struct m0_op_idx *oi)
1341 {
1342  struct dix_req *req;
1343  int rc;
1344 
1346  rc = dix_mreq_create(oi, &req);
1347  if (rc != 0)
1348  return M0_ERR(rc);
1351  return 1;
1352 }
1353 
1354 static int dix_put(struct m0_op_idx *oi)
1355 {
1356  struct dix_req *req;
1357  int rc;
1358 
1359  /*
1360  * @todo: User application (S3) need to set M0_OIF_CROW and
1361  * M0_OIF_SKIP_LAYOUT index flags as a configurable parameter.
1362  * Remove this logic once configuration option is available in S3.
1363  */
1364  dix_set_idx_flags(oi);
1365 
1366  rc = dix_req_create(oi, &req);
1367  if (rc != 0)
1368  return M0_ERR(rc);
1370  return 1;
1371 }
1372 
1373 static int dix_get(struct m0_op_idx *oi)
1374 {
1375  struct dix_req *req;
1376  int rc;
1377 
1378  M0_ASSERT_INFO(oi->oi_keys->ov_vec.v_nr != 0,
1379  "At least one key should be specified");
1381  oi->oi_keys->ov_buf[i] == NULL),
1382  "NULL key is not allowed");
1383  rc = dix_req_create(oi, &req);
1384  if (rc != 0)
1385  return M0_ERR(rc);
1387  return 1;
1388 }
1389 
1390 static int dix_del(struct m0_op_idx *oi)
1391 {
1392  struct dix_req *req;
1393  int rc;
1394 
1395  rc = dix_req_create(oi, &req);
1396  if (rc != 0)
1397  return M0_ERR(rc);
1399  return 1;
1400 }
1401 
1402 static int dix_next(struct m0_op_idx *oi)
1403 {
1404  struct dix_req *req;
1405  int rc;
1406 
1407  rc = dix_req_create(oi, &req);
1408  if (rc != 0)
1409  return M0_ERR(rc);
1411  return 1;
1412 }
1413 
1416  .iqo_namei_delete = dix_index_delete,
1417  .iqo_namei_lookup = dix_index_lookup,
1418  .iqo_namei_list = dix_index_list,
1419 
1420  .iqo_get = dix_get,
1421  .iqo_put = dix_put,
1422  .iqo_del = dix_del,
1423  .iqo_next = dix_next,
1424 };
1425 
1426 /*--------------------------------------------------------------------------*
1427  * Index back-end initialisation and finalisation *
1428  *--------------------------------------------------------------------------*/
1429 
1430 static int dix_root_idx_pver(struct m0_client *m0c, struct m0_fid *out)
1431 {
1432  struct m0_reqh *reqh = &m0c->m0c_reqh;
1433  struct m0_conf_root *root;
1434  int rc;
1435 
1436  /*
1437  * Client will release the lock on confc
1438  * before calling idx_dix_init().
1439  */
1441  if (rc != 0)
1442  return M0_RC(rc);
1443 
1444  *out = root->rt_imeta_pver;
1446 
1447  return 0;
1448 }
1449 
1450 static int dix_client_init(struct dix_inst *inst,
1451  struct m0_client *m0c,
1452  struct m0_idx_dix_config *config)
1453 {
1454  struct m0_dix_cli *dixc = &inst->di_dixc;
1455  struct m0_sm_group *grp = m0_locality0_get()->lo_grp;
1456  struct m0_fid root_pver;
1457  int rc;
1458 
1459  /*
1460  * dix_init() is called from client initialisation machine.
1461  * DIX client start is synchronoush operation that uses it's own
1462  * machine internally. These two state machines should belong to
1463  * different state machine groups, otherwise DIX client start will hang.
1464  */
1465  M0_ASSERT(grp != m0c->m0c_initlift_sm.sm_grp);
1466 
1467  rc = dix_root_idx_pver(m0c, &root_pver) ?:
1468  m0_dix_cli_init(dixc, grp, &m0c->m0c_pools_common,
1469  &m0c->m0c_reqh.rh_ldom, &root_pver);
1470  if (rc != 0)
1471  return M0_ERR(rc);
1472 
1473  dixc->dx_dtms = m0c->m0c_dtms;
1474 
1475  if (config->kc_create_meta) {
1477  rc = m0_dix_meta_create(dixc, grp, &config->kc_layout_ldesc,
1478  &config->kc_ldescr_ldesc);
1479  if (rc != 0) {
1480  m0_dix_cli_stop_lock(dixc);
1481  goto cli_fini;
1482  }
1483  }
1484 
1485  rc = m0_dix_cli_start_sync(&inst->di_dixc);
1486  if (rc != 0)
1487  goto cli_fini;
1488 
1489  /* Set the callback funtion to update FSYNC records. */
1491 
1492  /*
1493  * Use pool version of root index as default pool version for all
1494  * distributed indices. It is temporary until client interface is
1495  * extended to allow user providing pool version for new indices.
1496  */
1497  inst->di_index_pver = root_pver;
1498  return M0_RC(0);
1499 
1500 cli_fini:
1501  m0_dix_cli_fini_lock(&inst->di_dixc);
1502  return M0_ERR(rc);
1503 }
1504 
1505 static int idx_dix_init(void *svc)
1506 {
1507  struct m0_idx_service_ctx *ctx;
1508  struct dix_inst *inst;
1509  struct m0_client *m0c;
1510  int rc;
1511 
1512  M0_ENTRY();
1513  ctx = (struct m0_idx_service_ctx *)svc;
1514  M0_PRE(ctx->isc_svc_conf != NULL);
1515 
1516  M0_ALLOC_PTR(inst);
1517  if (inst == NULL)
1518  return M0_ERR(-ENOMEM);
1519  m0c = M0_AMB(m0c, ctx, m0c_idx_svc_ctx);
1520 
1521  rc = dix_client_init(inst, m0c,
1522  (struct m0_idx_dix_config *)ctx->isc_svc_conf);
1523  if (rc != 0) {
1524  m0_free(inst);
1525  return M0_ERR(rc);
1526  }
1527  ctx->isc_svc_inst = inst;
1528 
1529  M0_POST(ctx->isc_svc_inst != NULL);
1530  return M0_RC(0);
1531 }
1532 
1533 static int idx_dix_fini(void *svc)
1534 {
1535  struct m0_idx_service_ctx *ctx;
1536  struct dix_inst *inst;
1537 
1538  M0_ENTRY();
1539  ctx = (struct m0_idx_service_ctx *)svc;
1540  M0_PRE(ctx->isc_svc_inst != NULL);
1541  inst = ctx->isc_svc_inst;
1542  m0_dix_cli_stop_lock(&inst->di_dixc);
1543  m0_dix_cli_fini_lock(&inst->di_dixc);
1544  m0_free0(&inst);
1545  return M0_RC(0);
1546 }
1547 
1550  .iso_fini = idx_dix_fini
1551 };
1552 
1553 M0_INTERNAL void m0_idx_dix_register(void)
1554 {
1556  &dix_query_ops);
1557 
1558 }
1559 
1560 #undef M0_TRACE_SUBSYSTEM
1561 
1564 /*
1565  * Local variables:
1566  * c-indentation-style: "K&R"
1567  * c-basic-offset: 8
1568  * tab-width: 8
1569  * fill-column: 80
1570  * scroll-step: 1
1571  * End:
1572  */
1573 /*
1574  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
1575  */
static void dixreq_completed_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:690
struct m0_entity * ol_entity
Definition: layout.h:183
M0_INTERNAL void m0_cas_req_fini(struct m0_cas_req *req)
Definition: client.c:288
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:815
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:1040
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:2378
M0_INTERNAL bool m0_dix_fid_validate_dix(const struct m0_fid *dix_fid)
Definition: fid_convert.c:88
Definition: client.h:835
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:721
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:1548
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:813
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
M0_INTERNAL void idx_op_ast_complete(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx.c:311
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:1214
static void dix_req_immed_failure(struct dix_req *req, int rc)
Definition: idx_dix.c:985
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:469
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:836
M0_INTERNAL void idx_op_ast_fail(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx.c:367
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:670
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:1755
M0_INTERNAL int m0_dix_item_rc(const struct m0_dix_req *req, uint64_t idx)
Definition: req.c:2475
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:158
static uint32_t dix_set_cas_flags(struct m0_op_idx *oi)
Definition: idx_dix.c:1005
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:1277
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:1357
#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:485
struct m0_idx_attr in_attr
Definition: client.h:837
static void dix_index_lookup_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1068
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:929
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:630
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:1414
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:822
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
M0_INTERNAL void m0_dix_req_fini(struct m0_dix_req *req)
Definition: req.c:2553
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:650
M0_INTERNAL uint64_t m0_dix_req_nr(const struct m0_dix_req *req)
Definition: req.c:2504
struct m0_sm ccr_sm
Definition: client.h:125
#define M0_ENTRY(...)
Definition: trace.h:170
int(* iqo_namei_create)(struct m0_op_idx *oi)
Definition: idx.h:123
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:836
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:1297
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:641
M0_INTERNAL int m0_dix_next(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *start_keys, const uint32_t *recs_nr, uint32_t flags)
Definition: req.c:2415
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:638
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:1108
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:457
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
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:1685
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:770
#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:1775
#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:168
#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:2357
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
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:591
static int dix_del(struct m0_op_idx *oi)
Definition: idx_dix.c:1390
#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:852
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:1842
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:1235
static int dix_get(struct m0_op_idx *oi)
Definition: idx_dix.c:1373
int(* iso_init)(void *svc)
Definition: idx.h:137
#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:1321
int32_t * oi_rcs
static void cas_next_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:504
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_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:1402
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:1505
#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:299
static void dix_next_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1173
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:1366
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:1019
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:1154
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:1394
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:1873
static int dix_mreq_create(struct m0_op_idx *oi, struct dix_req **out)
Definition: idx_dix.c:602
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:1308
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:1403
static void dix_get_reply_copy(struct m0_dix_req *dreq, int32_t *rcs, struct m0_bufvec *bvec)
Definition: idx_dix.c:747
#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:660
static int dix_index_list(struct m0_op_idx *oi)
Definition: idx_dix.c:1340
M0_INTERNAL int m0_dix_del(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:2388
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:1138
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 bool dixreq_clink_dtx_cb(struct m0_clink *cl)
Definition: idx_dix.c:874
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:522
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:2509
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:1816
M0_INTERNAL void m0_idx_dix_register(void)
Definition: idx_dix.c:1553
uint32_t en_flags
Definition: client.h:738
static bool dix_meta_req_clink_cb(struct m0_clink *cl)
Definition: idx_dix.c:802
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:1264
#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:1430
static void dix_build(const struct m0_op_idx *oi, struct m0_dix *out)
Definition: idx_dix.c:547
static void dix_index_list_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1091
M0_INTERNAL void idx_op_ast_stable(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx.c:293
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:1450
M0_INTERNAL void m0_dix_next_rep_mlock(struct m0_dix_req *req, uint32_t key_idx, uint32_t val_idx)
Definition: req.c:2519
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:1317
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:2449
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:2468
struct m0_rpc_item f_item
Definition: fop.h:83
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:1426
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:1048
static void dix_put_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: idx_dix.c:1118
M0_INTERNAL int m0_dix_put(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys, const struct m0_bufvec *vals, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:2326
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:1533
static void dix_req_destroy(struct dix_req *req)
Definition: idx_dix.c:673
Definition: fop.h:79
#define FID_F
Definition: fid.h:75
M0_INTERNAL void m0_dix_fini(struct m0_dix *dix)
Definition: req.c:2603
Definition: vec.h:145
static int dix_put(struct m0_op_idx *oi)
Definition: idx_dix.c:1354
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:994
M0_INTERNAL int m0_dix_generic_rc(const struct m0_dix_req *req)
Definition: req.c:2483
#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:709