Motr  M0
isync.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CLIENT
24 #include "lib/trace.h"
25 #include "lib/finject.h"
26 
27 #include "motr/client.h"
28 #include "motr/st/st.h"
29 #include "motr/st/st_misc.h"
30 #include "motr/st/st_assert.h"
31 
32 #include "lib/memory.h"
33 
34 enum { ST_MAX_KEY_LEN = 64 };
35 
36 #define ST_VAL_STRING ("Client Index Test.")
37 
38 enum {
43 };
44 
46 
47 static void idx_bufvec_free(struct m0_bufvec *bv)
48 {
49  uint32_t i;
50  if (bv == NULL)
51  return;
52 
53  if (bv->ov_buf != NULL) {
54  for (i = 0; i < bv->ov_vec.v_nr; ++i)
55  if (bv->ov_buf[i] != NULL)
56  m0_free(bv->ov_buf[i]);
57  m0_free(bv->ov_buf);
58  }
59  m0_free(bv->ov_vec.v_count);
60  m0_free(bv);
61 }
62 
63 static struct m0_bufvec* idx_bufvec_alloc(int nr)
64 {
65  struct m0_bufvec *bv;
66 
67  bv = m0_alloc(sizeof *bv);
68  if (bv == NULL)
69  return NULL;
70 
71  bv->ov_vec.v_nr = nr;
73  if (bv->ov_vec.v_count == NULL)
74  goto FAIL;
75 
76  M0_ALLOC_ARR(bv->ov_buf, nr);
77  if (bv->ov_buf == NULL)
78  goto FAIL;
79 
80  return bv;
81 
82 FAIL:
83  m0_bufvec_free(bv);
84  return NULL;
85 }
86 
87 static int idx_fill_kv_pairs(struct m0_uint128 id, int start,
88  struct m0_bufvec *keys,
89  struct m0_bufvec *vals)
90 {
91  int i;
92  int rc;
93  int nr_kvp;
94  int klen;
95  int vlen;
96  char *prefix = NULL;
97  char *tmp_str = NULL;
98  char *key_str = NULL;
99  char *val_str = NULL;
100 
101  rc = -ENOMEM;
103  if (prefix == NULL)
104  goto ERROR;
105 
106  tmp_str = m0_alloc(ST_MAX_KEY_LEN);
107  if (tmp_str == NULL)
108  goto ERROR;
109 
110  /*
111  * Keys are flled with this format (index fid:key's serial number).
112  * Values are a dummy string "Client Index Test."
113  */
114  nr_kvp = keys->ov_vec.v_nr;
115  vlen = strlen(ST_VAL_STRING);
116  for (i = 0; i < nr_kvp; i++) {
117  sprintf(tmp_str,
118  "%" PRIx64 ":%" PRIx64 ":%d",
119  id.u_hi, id.u_lo, start + i);
120 
121  klen = strlen(tmp_str);
122  key_str = m0_alloc(klen);
123  if (key_str == NULL)
124  goto ERROR;
125 
126  val_str = m0_alloc(vlen);
127  if (val_str == NULL)
128  goto ERROR;
129 
130  memcpy(key_str, tmp_str, klen);
131  memcpy(val_str, ST_VAL_STRING, vlen);
132 
133  /* Set bufvec's of keys and vals*/
134  keys->ov_vec.v_count[i] = klen;
135  keys->ov_buf[i] = key_str;
136  vals->ov_vec.v_count[i] = vlen;
137  vals->ov_buf[i] = val_str;
138  }
139 
140  if (prefix) m0_free(prefix);
141  if (tmp_str) m0_free(tmp_str);
142  return 0;
143 
144 ERROR:
145  if (prefix) m0_free(prefix);
146  if (tmp_str) m0_free(tmp_str);
147  if (key_str) m0_free(key_str);
148  if (val_str) m0_free(val_str);
149  return rc;
150 }
151 
152 static int idx_add_or_del_kv_pairs(int opcode, struct m0_uint128 id,
153  int nr_kvp, bool dont_fini_op,
154  struct m0_op **op_out,
155  struct m0_idx **idx_out)
156 {
157  int rc = 0;
158  int *rcs;
159  struct m0_bufvec *keys;
160  struct m0_bufvec *vals;
161  struct m0_op *ops[1] = {NULL};
162  struct m0_idx *idx;
163 
164  /* Allocate bufvec's for keys and vals. */
165  keys = idx_bufvec_alloc(nr_kvp);
166  vals = idx_bufvec_alloc(nr_kvp);
167  M0_ALLOC_ARR(rcs, nr_kvp);
168  M0_ALLOC_PTR(idx);
169  if (keys == NULL || vals == NULL || rcs == NULL || idx == NULL) {
170  rc = -ENOMEM;
171  goto exit;
172  }
173 
174  /* Fill keys and values with some data. */
175  rc = idx_fill_kv_pairs(id, 0, keys, vals);
176  if (rc < 0)
177  goto exit;
178 
179  /* Start doing the real job. */
180  ops[0] = NULL;
181  memset(idx, 0, sizeof *idx);
182 
184  if (opcode == IDX_KV_ADD)
185  st_idx_op(idx, M0_IC_PUT, keys, vals, rcs,
186  0, &ops[0]);
187  else
188  st_idx_op(idx, M0_IC_DEL, keys, NULL, rcs, 0,
189  &ops[0]);
190 
191  st_op_launch(ops, 1);
192  rc = st_op_wait(ops[0],
194  M0_OS_STABLE),
195  M0_TIME_NEVER);
196  rc = rc < 0?rc:ops[0]->op_sm.sm_rc;
197 
198  if (rc == 0 && dont_fini_op == true) {
199  *op_out = ops[0];
200  goto exit;
201  }
202 
203  /* fini and release */
204  st_op_fini(ops[0]);
205  st_op_free(ops[0]);
206 
207 exit:
208  if (keys) idx_bufvec_free(keys);
209  if (vals) idx_bufvec_free(vals);
210  if (rcs) m0_free0(&rcs);
211 
212  if (rc != 0 || idx_out == NULL) {
213  st_idx_fini(idx);
214  m0_free(idx);
215  } else
216  *idx_out = idx;
217 
218  return rc;
219 }
220 
221 static int idx_create_or_delete(int opcode, struct m0_uint128 id,
222  bool dont_fini_op, struct m0_op **op_out,
223  struct m0_idx **idx_out)
224 {
225  int rc;
226  struct m0_op *ops[1] = {NULL};
227  struct m0_idx *idx;
228 
229  M0_ALLOC_PTR(idx);
230  if (idx == NULL)
231  return -ENOMEM;
232  memset(idx, 0, sizeof *idx);
233  ops[0] = NULL;
234 
235  /* Set an index creation operation. */
236  st_idx_init(idx,
238  if (opcode == IDX_CREATE)
239  st_entity_create(NULL, &idx->in_entity, &ops[0]);
240  else {
241  st_idx_open(&idx->in_entity);
242  st_entity_delete(&idx->in_entity, &ops[0]);
243  }
244 
245  /* Launch and wait for op to complete */
246  st_op_launch(ops, 1);
247  rc = st_op_wait(ops[0],
249  M0_OS_STABLE),
250  M0_TIME_NEVER);
251  rc = rc < 0?rc:ops[0]->op_sm.sm_rc;
252 
253  if (rc == 0 && dont_fini_op == true) {
254  *op_out = ops[0];
255  goto exit;
256  }
257 
258  /* fini and release */
259  st_op_fini(ops[0]);
260  st_op_free(ops[0]);
261 
262 exit:
263  if (rc != 0 || idx_out == NULL) {
264  st_idx_fini(idx);
265  m0_free(idx);
266  } else
267  *idx_out = idx;
268  return rc;
269 }
270 
275 static void isync_error_handling(void)
276 {
277  int rc;
278  int nr_kvp;
279  struct m0_uint128 id;
280  struct m0_fid idx_fid;
281  struct m0_op *sync_op = NULL;
282  struct m0_idx *idx_to_sync[1] = {NULL};
283 
284  /* get index's fid. */
285  oid_get(&id);
286  idx_fid = M0_FID_TINIT('x', id.u_hi, id.u_lo);
287  id.u_hi = idx_fid.f_container;
288  id.u_lo = idx_fid.f_key;
289 
290  /* Create an index. */
291  rc = idx_create_or_delete(IDX_CREATE, id, false, NULL, NULL);
292  ST_ASSERT_FATAL(rc == 0);
293 
294  /* Insert K-V pairs into index. */
295  nr_kvp = 10;
297  nr_kvp, false, NULL, idx_to_sync);
298  ST_ASSERT_FATAL(rc == 0);
299 
300  /* Launch and wait on sync op. */
301  rc = m0_sync_op_init(&sync_op);
302  M0_ASSERT(rc == 0);
303  rc = m0_sync_entity_add(sync_op, &idx_to_sync[0]->in_entity);
304  M0_ASSERT(rc == 0);
305 
306  m0_fi_enable_once("sync_request_launch", "launch_failed");
307  st_op_launch(&sync_op, 1);
308  rc = st_op_wait(
309  sync_op, M0_BITS(M0_OS_FAILED, M0_OS_STABLE),
310  m0_time_from_now(3,0));
311  ST_ASSERT_FATAL(rc == 0);
312  st_op_fini(sync_op);
313  st_op_free(sync_op);
314 
315  /* Finalise the index. */
316  st_idx_fini(idx_to_sync[0]);
317 }
318 static void isync_by_sync_op(void)
319 {
320  int rc;
321  int nr_kvp;
322  struct m0_uint128 id;
323  struct m0_fid idx_fid;
324  struct m0_op *sync_op = NULL;
325  struct m0_idx *idx_to_sync[1] = {NULL};
326 
327  /* get index's fid. */
328  oid_get(&id);
329  idx_fid = M0_FID_TINIT('x', id.u_hi, id.u_lo);
330  id.u_hi = idx_fid.f_container;
331  id.u_lo = idx_fid.f_key;
332 
333  /* Create an index. */
334  rc = idx_create_or_delete(IDX_CREATE, id, false, NULL, NULL);
335  ST_ASSERT_FATAL(rc == 0);
336 
337  /* Insert K-V pairs into index. */
338  nr_kvp = 10;
340  nr_kvp, false, NULL, idx_to_sync);
341  ST_ASSERT_FATAL(rc == 0);
342 
343  /* Launch and wait on sync op. */
344  rc = m0_sync_op_init(&sync_op);
345  M0_ASSERT(rc == 0);
346  rc = m0_sync_entity_add(sync_op, &idx_to_sync[0]->in_entity);
347  M0_ASSERT(rc == 0);
348 
349  st_op_launch(&sync_op, 1);
350  rc = st_op_wait(
351  sync_op, M0_BITS(M0_OS_FAILED, M0_OS_STABLE),
352  m0_time_from_now(3,0));
353  ST_ASSERT_FATAL(rc == 0);
354  st_op_fini(sync_op);
355  st_op_free(sync_op);
356 
357  /* Finalise the index. */
358  st_idx_fini(idx_to_sync[0]);
359 }
360 
361 static void isync_on_op(void)
362 {
363  int rc;
364  int nr_kvp;
365  struct m0_uint128 id;
366  struct m0_fid idx_fid;
367  struct m0_op *sync_op = NULL;
368  struct m0_op *op_to_sync[1] = {NULL};
369  struct m0_idx *idx_to_sync[1] = {NULL};
370 
371  /* get index's fid. */
372  oid_get(&id);
373  idx_fid = M0_FID_TINIT('x', id.u_hi, id.u_lo);
374  id.u_hi = idx_fid.f_container;
375  id.u_lo = idx_fid.f_key;
376 
377  /* Create an index. */
378  rc = idx_create_or_delete(IDX_CREATE, id, false, NULL, NULL);
379  ST_ASSERT_FATAL(rc == 0);
380 
381  /* Insert K-V pairs into index. */
382  nr_kvp = 10;
383  rc = idx_add_or_del_kv_pairs(IDX_KV_ADD, id, nr_kvp,
384  true, op_to_sync, idx_to_sync);
385  ST_ASSERT_FATAL(rc == 0);
386 
387  /* Launch and wait on sync op. */
388  rc = m0_sync_op_init(&sync_op);
389  M0_ASSERT(rc == 0);
390  rc = m0_sync_op_add(sync_op, op_to_sync[0]);
391  M0_ASSERT(rc == 0);
392 
393  st_op_launch(&sync_op, 1);
394  rc = st_op_wait(
395  sync_op, M0_BITS(M0_OS_FAILED, M0_OS_STABLE),
396  m0_time_from_now(3,0));
397  ST_ASSERT_FATAL(rc == 0);
398  st_op_fini(sync_op);
399  st_op_free(sync_op);
400 
401  /* Finalise the index. */
402  st_idx_fini(idx_to_sync[0]);
403 }
404 
405 static void isync_on_idx_delete(void)
406 {
407  int rc;
408  struct m0_uint128 id;
409  struct m0_fid idx_fid;
410  struct m0_op *sync_op = NULL;
411  struct m0_idx *idx_to_sync[1] = {NULL};
412 
413  /* get index's fid. */
414  oid_get(&id);
415  idx_fid = M0_FID_TINIT('x', id.u_hi, id.u_lo);
416  id.u_hi = idx_fid.f_container;
417  id.u_lo = idx_fid.f_key;
418 
419  /* Create an index. */
420  rc = idx_create_or_delete(IDX_CREATE, id, false, NULL, NULL);
421  ST_ASSERT_FATAL(rc == 0);
422 
423  /* Delete this index. */
424  rc = idx_create_or_delete(IDX_DELETE, id, false, NULL, idx_to_sync);
425  ST_ASSERT_FATAL(rc == 0);
426 
427  /* Launch and wait on sync op. */
428  rc = m0_sync_op_init(&sync_op);
429  M0_ASSERT(rc == 0);
430  rc = m0_sync_entity_add(sync_op, &idx_to_sync[0]->in_entity);
431  M0_ASSERT(rc == 0);
432 
433  st_op_launch(&sync_op, 1);
434  rc = st_op_wait(
435  sync_op, M0_BITS(M0_OS_FAILED, M0_OS_STABLE),
436  m0_time_from_now(3,0));
437  ST_ASSERT_FATAL(rc == 0);
438  st_op_fini(sync_op);
439  st_op_free(sync_op);
440 
441  /* Finalise the index. */
442  st_idx_fini(idx_to_sync[0]);
443 }
444 
445 static void isync_on_kv_delete(void)
446 {
447  int rc;
448  int nr_kvp;
449  struct m0_uint128 id;
450  struct m0_fid idx_fid;
451  struct m0_op *sync_op = NULL;
452  struct m0_op *op_to_sync[1] = {NULL};
453  struct m0_idx *idx_to_sync[1] = {NULL};
454 
455  /* get index's fid. */
456  oid_get(&id);
457  idx_fid = M0_FID_TINIT('x', id.u_hi, id.u_lo);
458  id.u_hi = idx_fid.f_container;
459  id.u_lo = idx_fid.f_key;
460 
461  /* Create an index. */
462  rc = idx_create_or_delete(IDX_CREATE, id, false, NULL, NULL);
463  ST_ASSERT_FATAL(rc == 0);
464 
465  /* Insert K-V pairs into index. */
466  nr_kvp = 10;
467  rc = idx_add_or_del_kv_pairs(IDX_KV_ADD, id, nr_kvp, false, NULL, NULL);
468  ST_ASSERT_FATAL(rc == 0);
469 
470  /* Delete a few K-V pairs. */
471  nr_kvp = 5;
472  rc = idx_add_or_del_kv_pairs(IDX_KV_DEL, id, nr_kvp,
473  true, op_to_sync, idx_to_sync);
474  ST_ASSERT_FATAL(rc == 0);
475 
476  /* Launch and wait on sync op. */
477  rc = m0_sync_op_init(&sync_op);
478  M0_ASSERT(rc == 0);
479  rc = m0_sync_op_add(sync_op, op_to_sync[0]);
480  M0_ASSERT(rc == 0);
481 
482  st_op_launch(&sync_op, 1);
483  rc = st_op_wait(
484  sync_op, M0_BITS(M0_OS_FAILED, M0_OS_STABLE),
485  m0_time_from_now(3,0));
486  ST_ASSERT_FATAL(rc == 0);
487  st_op_fini(sync_op);
488  st_op_free(sync_op);
489 
490  /* Finalise the index. */
491  st_idx_fini(idx_to_sync[0]);
492 }
493 
494 /* Initialises the Client environment.*/
495 static int st_isync_init(void)
496 {
497  int rc = 0;
498 
499  /*
500  * Retrieve the uber realm. We don't need to open this,
501  * as realms are not actually implemented yet
502  */
505  st_get_instance());
507 
508  if (rc != 0)
509  console_printf("Failed to open uber realm\n");
510 
511  return rc;
512 }
513 
514 /* Finalises the Client environment.*/
515 static int st_isync_fini(void)
516 {
517  return 0;
518 }
519 
521  .ss_name = "isync_st",
522  .ss_init = st_isync_init,
523  .ss_fini = st_isync_fini,
524  .ss_tests = {
525  { "isync_error_handling", &isync_error_handling},
526  { "isync_by_sync_op", &isync_by_sync_op},
527  { "isync_on_op", &isync_on_op},
528  { "isync_on_idx_delete", &isync_on_idx_delete},
529  { "isync_on_kv_delete", &isync_on_kv_delete},
530  { NULL, NULL }
531  }
532 };
533 
534 #undef M0_TRACE_SUBSYSTEM
535 
536 /*
537  * Local variables:
538  * c-indentation-style: "K&R"
539  * c-basic-offset: 8
540  * tab-width: 8
541  * fill-column: 80
542  * scroll-step: 1
543  * End:
544  */
uint64_t id
Definition: cob.h:2380
void st_idx_init(struct m0_idx *idx, struct m0_realm *parent, const struct m0_uint128 *id)
Definition: api.c:56
static size_t nr
Definition: dump.c:1505
int st_entity_create(struct m0_fid *pool, struct m0_entity *entity, struct m0_op **op)
Definition: api.c:71
void st_idx_open(struct m0_entity *entity)
Definition: api.c:176
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
static struct m0_bufvec * idx_bufvec_alloc(int nr)
Definition: isync.c:63
Definition: client.h:835
void st_op_free(struct m0_op *op)
Definition: api.c:147
#define ST_VAL_STRING
Definition: isync.c:36
#define NULL
Definition: misc.h:38
static void isync_on_idx_delete(void)
Definition: isync.c:405
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
void st_idx_fini(struct m0_idx *idx)
Definition: api.c:64
struct m0_vec ov_vec
Definition: vec.h:147
static struct m0_uint128 prefix
Definition: extmap.c:45
uint64_t u_lo
Definition: types.h:58
int m0_sync_op_add(struct m0_op *sop, struct m0_op *op)
Definition: sync.c:1020
#define M0_BITS(...)
Definition: misc.h:236
int st_idx_op(struct m0_idx *idx, enum m0_idx_opcode opcode, struct m0_bufvec *keys, struct m0_bufvec *vals, int *rcs, int flag, struct m0_op **op)
Definition: api.c:113
const struct m0_uint128 M0_UBER_REALM
Definition: client.c:85
static int idx_create_or_delete(int opcode, struct m0_uint128 id, bool dont_fini_op, struct m0_op **op_out, struct m0_idx **idx_out)
Definition: isync.c:221
#define ST_ASSERT_FATAL(a)
Definition: st_assert.h:31
void ** ov_buf
Definition: vec.h:149
#define PRIx64
Definition: types.h:61
static void idx_bufvec_free(struct m0_bufvec *bv)
Definition: isync.c:47
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_container st_isync_container
Definition: isync.c:45
int opcode
Definition: crate.c:301
int i
Definition: dir.c:1033
struct m0_realm co_realm
Definition: client.h:881
Definition: client.h:641
static int st_isync_init(void)
Definition: isync.c:495
static void isync_on_op(void)
Definition: isync.c:361
#define ERROR(_fmt,...)
Definition: m0hsm_api.c:66
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
void st_container_init(struct m0_container *con, struct m0_realm *parent, const struct m0_uint128 *id, struct m0_client *instance)
Definition: api.c:34
struct m0_entity re_entity
Definition: client.h:871
int oid_get(struct m0_uint128 *oid)
Definition: oid.c:373
#define FAIL
#define m0_free0(pptr)
Definition: memory.h:77
struct st_suite st_suite_isync
Definition: isync.c:520
#define M0_ASSERT(cond)
Definition: st.h:83
uint64_t u_hi
Definition: types.h:57
int m0_sync_entity_add(struct m0_op *sop, struct m0_entity *ent)
Definition: sync.c:985
void * m0_alloc(size_t size)
Definition: memory.c:126
static void isync_error_handling(void)
Definition: isync.c:275
uint64_t f_container
Definition: fid.h:39
uint32_t v_nr
Definition: vec.h:51
int32_t sm_rc
Definition: sm.h:336
m0_bcount_t * v_count
Definition: vec.h:53
int m0_sync_op_init(struct m0_op **sop)
Definition: sync.c:972
void console_printf(const char *fmt,...)
Definition: st_misc.c:155
static void isync_by_sync_op(void)
Definition: isync.c:318
static void isync_on_kv_delete(void)
Definition: isync.c:445
Definition: fid.h:38
uint64_t f_key
Definition: fid.h:40
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
struct m0_client * st_get_instance()
Definition: st.c:57
static int start(struct m0_fom *fom)
Definition: trigger_fom.c:321
void st_op_launch(struct m0_op **op, uint32_t nr)
Definition: api.c:129
const char * ss_name
Definition: st.h:85
static void m0_fi_enable_once(const char *func, const char *tag)
Definition: finject.h:301
static int idx_fill_kv_pairs(struct m0_uint128 id, int start, struct m0_bufvec *keys, struct m0_bufvec *vals)
Definition: isync.c:87
int st_entity_delete(struct m0_entity *entity, struct m0_op **op)
Definition: api.c:83
struct m0_sm en_sm
Definition: client.h:732
static int idx_add_or_del_kv_pairs(int opcode, struct m0_uint128 id, int nr_kvp, bool dont_fini_op, struct m0_op **op_out, struct m0_idx **idx_out)
Definition: isync.c:152
struct m0_fom_ops ops
Definition: io_foms.c:623
void m0_free(void *data)
Definition: memory.c:146
int32_t st_op_wait(struct m0_op *op, uint64_t bits, m0_time_t to)
Definition: api.c:136
void st_op_fini(struct m0_op *op)
Definition: api.c:142
int32_t rc
Definition: trigger_fop.h:47
static int st_isync_fini(void)
Definition: isync.c:515
Definition: vec.h:145