Motr  M0
crate_index.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2017-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 #include <errno.h>
24 #include "lib/bitmap.h"
25 #include "lib/trace.h"
26 #include "lib/time.h"
27 #include "motr/m0crate/logger.h"
30 
32 extern struct crate_conf *conf;
33 
34 /* @nefgroup crate Crate
35  * Utility for executing simple performance tests.
36  */
37 
147 #define LOG_PREFIX "dix: "
148 
149 /* XXX: Disable tracking system to increase performance. */
150 #ifdef NTRACK
151 # undef M0_RC
152 # define M0_RC(X) (X)
153 # undef M0_ERR
154 # define M0_ERR(X) (X)
155 # undef M0_PRE
156 # define M0_PRE(X)
157 # undef M0_POST
158 # define M0_POST(X)
159 # undef M0_ASSERT
160 # define M0_ASSERT(X)
161 #endif
162 
164 enum {
168  CR_MIN_KEY_SIZE = sizeof(struct m0_fid),
172  CR_MAX_NEXT_RECORDS = (1 << 30),
173 };
174 
180 };
181 
182 /* RANDOM */
184 static int cr_rand_pos_range(int end)
185 {
186  return rand() % end;
187 }
188 
190 static size_t cr_rand_pos_range_l(size_t end)
191 {
192  size_t val_h;
193  size_t val_l;
194  size_t res;
195 
196  val_l = rand();
197  val_h = rand();
198 
199  res = (val_h << 32) | val_l;
200 
201  return res % end;
202 }
203 
205 static bool cr_rand_bool()
206 {
207  return rand() % 2 == 1;
208 }
209 
211 static void cr_get_random_string(char *dest, size_t length)
212 {
213  char set[] = "0123456789"
214  "abcdefghijklmnopqrstuvwxyz"
215  "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
216  const size_t set_len = strlen(set);
217  int index;
218  int i;
219 
220  for (i = 0; i < length - 1; i++)
221  {
222  index = cr_rand_pos_range(set_len);
223  dest[i] = set[index];
224  }
225 
226  dest[length - 1] = '\0';
227 }
228 
229 
230 /* TIME MEASUREMENTS */
237  double elapsed;
238 };
239 
240 /* CLIENT INDEX RESULT MEASUREMENTS */
242  "PUT",
243  "GET",
244  "NEXT",
245  "DEL"
246 };
249  const char *cior_op_label;
260 };
261 
271 };
272 
273 static double cr_time_in_seconds(m0_time_t mtime)
274 {
275  return (m0_time_seconds(mtime)) +
276  ( m0_time_nanoseconds(mtime) / (double) M0_TIME_ONE_SECOND );
277 }
278 
280 {
281  *t = (struct cr_time_measure_ctx) {};
282  t->ts = m0_time_now();
283 }
284 
286 {
287  m0_time_t d = m0_time_sub(m0_time_now(), t->ts);
288  return (m0_time_seconds(d)) +
289  ( m0_time_nanoseconds(d) / (double) M0_TIME_ONE_SECOND );
290 }
291 
293 {
294  t->elapsed = cr_time_measure_elapsed_now(t);
295  t->ts_next = m0_time_now();
296 }
297 
298 /* BITMAP */
299 static void m0_bitmap_print(struct m0_bitmap *bm)
300 {
301  int i;
302  int nr = bm->b_nr;
303 
304  if (nr <= 1024) {
305  cr_log_ex(CLL_DEBUG, LOG_PREFIX, "", "len = %d, map = {", nr);
306  for (i = 0; i < nr; i++)
307  cr_log_ex(CLL_SAME, "", "", "%d", m0_bitmap_get(bm, i));
308  cr_log_ex(CLL_SAME, "", "", "}\n");
309  } else
310  crlog(CLL_DEBUG, "Bitmap is too large to print.");
311 }
312 
313 /* WATCHDOG */
315 static int cr_watchdog_init(struct m0_workload_index *wt);
316 static void cr_watchdog_fini();
317 static void cr_watchdog_touch();
318 
319 
320 /* CLIENT OPCODES UTILS */
321 static const char *crate_op_to_string(enum cr_opcode op);
322 static bool cr_opcode_valid(enum cr_opcode opcode);
323 
324 
325 /* CLIENT INDEX WORKLOAD */
328  int nr;
330  bool pending;
332  int prev_key;
335 };
336 
338 struct cr_idx_w {
340  struct m0_bitmap bm;
347  int nr_keys;
351  size_t exec_time;
354 };
355 
356 static int cr_idx_w_init(struct cr_idx_w *ciw,
357  struct m0_workload_index *wit);
358 static void cr_idx_w_fini(struct cr_idx_w *ciw);
359 static void cr_idx_w_seq_keys_init(struct cr_idx_w *w, int keys_nr);
360 static void cr_idx_w_seq_keys_fini(struct cr_idx_w *w);
361 static int cr_idx_w_seq_keys_get_last(struct cr_idx_w *w,
362  int nr, enum cr_opcode op);
363 static bool cr_idx_w_seq_keys_enabled(struct cr_idx_w *w);
364 static void cr_idx_w_seq_keys_save(struct cr_idx_w *w,
365  int *keys, size_t keys_nr,
366  enum cr_opcode op);
367 static size_t cr_idx_w_get_value_size(struct cr_idx_w *w);
368 static int cr_idx_w_get_nr_keys_per_op(struct cr_idx_w *w, enum cr_opcode op);
369 static int cr_idx_w_find_seq_k(struct cr_idx_w *w,
370  enum cr_opcode opcode,
371  int *keys, size_t nr_keys);
372 static int cr_idx_w_find_rnd_k(struct cr_idx_w *w,
373  enum cr_opcode opcode,
374  int *keys, size_t nr_keys);
375 static bool cr_idx_w_timeout_expired(struct cr_idx_w *w);
376 static int cr_idx_w_execute(struct cr_idx_w *w,
377  enum cr_opcode opcode,
378  bool random,
379  size_t nr_keys,
380  bool *missing_key);
381 static int cr_idx_w_get_nr_remained_ops(struct cr_idx_w *w);
382 static enum cr_opcode cr_idx_w_select_op(struct cr_idx_w *w);
383 static int cr_idx_w_get_nr_remained_op_types(struct cr_idx_w *w);
384 static void cr_idx_w_print_ops_table(struct cr_idx_w *w);
385 static bool cr_idx_w_rebalance_ops(struct cr_idx_w *w, enum cr_opcode op);
386 static int cr_idx_w_common(struct cr_idx_w *w);
387 static int cr_idx_w_warmup(struct cr_idx_w *w);
388 
391  struct cr_idx_w *ciw)
392 {
393  int i = 0;
394  struct cr_idx_ops_result *op_results = ciw->ciw_results.ciwr_ops_result;
395  ciw->ciw_results.ciwr_total_time_s = t->elapsed;
396  ciw->ciw_results.ciwr_total_time_m0 = m0_time_sub(t->ts_next, t->ts);
399 
400  /* Calculate Results for each op (PUT, GET, NEXT and DEL) */
401  for (i = 0; i < CRATE_OP_NR; i++) {
402  if (op_results[i].cior_op_count) {
403  op_results[i].cior_ops_total_time_s =
406  op_results[i].cior_ops_total_time_m0 /
407  op_results[i].cior_op_count);
408  }
409  }
410 
411 }
414  struct cr_idx_w w)
415 {
416  int i = 0;
417  struct cr_idx_ops_result *op_results = w.ciw_results.ciwr_ops_result;
418 
419  /* Results in parsable format */
420  fprintf(stdout, "result: total_s, %f, avg_time_per_op_ns, %.1f,"
421  " key_size_bytes, %d, value_size_bytes, %d, ops, %d\n",
422  t->elapsed, w.ciw_results.ciwr_time_per_op_ns,
424 
425  for (i = 0; i < CRATE_OP_NR; i++) {
426  fprintf(stdout, "result: %s, total_time_s, %f, avg_time_per_op_ns, "
427  "%.1f, ops, %d\n",
428  op_results[i].cior_op_label,
429  op_results[i].cior_ops_total_time_s,
430  op_results[i].cior_time_per_op_ns,
431  op_results[i].cior_op_count);
432  }
433 
434  /* Results in m0crate format */
435  fprintf(stdout, "\nTotal: time="TIME_F" ("TIME_F" per op) ops=%d\n",
438  w.nr_ops_total),
439  w.nr_ops_total);
440 
441  for (i = 0; i < CRATE_OP_NR; i++) {
442  if (op_results[i].cior_op_count) {
443  fprintf(stdout, "%s: "TIME_F" ("TIME_F" per op) ops=%d\n",
444  op_results[i].cior_op_label,
445  TIME_P(op_results[i].cior_ops_total_time_m0),
446  TIME_P(op_results[i].cior_ops_total_time_m0 /
447  op_results[i].cior_op_count),
448  op_results[i].cior_op_count);
449  }
450  }
451 }
452 
453 
454 /* IMPLEMENTATION */
455 
456 static int cr_idx_w_init(struct cr_idx_w *ciw,
457  struct m0_workload_index *wit)
458 {
459  int rc;
460  int i;
461 
465 
466  *ciw = (typeof(*ciw)) {};
467 
468  ciw->wit = wit;
469  ciw->nr_ops_total = 0;
470 
471  /* Setting up min_key_size default to MIN_KEY_SIZE */
473 
474  /* Init crate index result */
475  for (i = 0; i < CRATE_OP_NR; i++) {
482  }
483 
484  /* XXX: If opcount is unlimited, then make it limited */
485  if (wit->op_count < 0) {
486  wit->op_count = INT_MAX / (128 * wit->num_kvs);
487  }
488 
489  for (i = 0; i < ARRAY_SIZE(ciw->nr_ops); i++) {
490  ciw->nr_ops[i].nr = wit->op_count *
491  ((double) wit->opcode_prcnt[i] / 100);
492  ciw->nr_ops_total += ciw->nr_ops[i].nr;
494  ciw->nr_ops[i].nr;
495  }
496  if (wit->warmup_put_cnt == -1) {
497  ciw->warmup_put_cnt = ciw->nr_ops_total;
498  ciw->nr_keys = ciw->nr_ops_total;
499  } else {
500  ciw->warmup_put_cnt = wit->warmup_put_cnt;
501  ciw->nr_keys = ciw->warmup_put_cnt > ciw->nr_ops_total ?
502  ciw->warmup_put_cnt : ciw->nr_ops_total;
503  }
504 
505  ciw->nr_kv_per_op = wit->num_kvs;
506  ciw->nr_keys *= ciw->nr_kv_per_op;
507  ciw->ordered_keys = wit->keys_ordered;
508 
509  /* If key size is random, generate it using rand(). */
510  if (ciw->wit->key_size < 0)
511  ciw->wit->key_size = ciw->wit->min_key_size +
513 
514  if (wit->warmup_del_ratio > 0)
515  ciw->warmup_del_cnt =
516  ciw->warmup_put_cnt / wit->warmup_del_ratio;
517  else
518  ciw->warmup_del_cnt = 0;
519 
520  rc = m0_bitmap_init(&ciw->bm, ciw->nr_keys);
521  if (rc != 0)
522  return M0_ERR(rc);
523 
524  srand(wit->seed);
525 
526  ciw->key_prefix = wit->key_prefix;
527 
528  if (ciw->key_prefix.f_container == -1)
530 
532  ciw->exec_time = wit->exec_time;
533 
535  ciw->op_selector = CR_OP_SEL_RND;
536  else
537  ciw->op_selector = CR_OP_SEL_RR;
538 
539  /* if DEL or GET or NEXT and PUT given, then we have to
540  * use round-robin selector to avoid cases when
541  * we perform GET/DEL/NEXT on empty index.
542  */
543  if ((ciw->nr_ops[CRATE_OP_DEL].nr != 0 || ciw->nr_ops[CRATE_OP_GET].nr != 0 ||
544  ciw->nr_ops[CRATE_OP_NEXT].nr != 0) && ciw->nr_ops[CRATE_OP_PUT].nr != 0) {
545  ciw->op_selector = CR_OP_SEL_RR;
546  }
547 
548  M0_POST(ciw->nr_kv_per_op < ciw->nr_keys);
549  M0_POST(ciw->nr_kv_per_op > 0);
550  M0_POST(ciw->nr_keys > 0);
551 
552  return M0_RC(0);
553 }
554 
555 static void cr_idx_w_fini(struct cr_idx_w *ciw)
556 {
557  m0_bitmap_fini(&ciw->bm);
558 }
559 
560 /* Seq keys */
561 static void cr_idx_w_seq_keys_init(struct cr_idx_w *w, int keys_nr)
562 {
563  int i;
564 
565  w->prev_key_used = true;
566 
567  for (i = 0; i < ARRAY_SIZE(w->nr_ops); i++)
568  w->nr_ops[i].prev_key = -1;
569 }
570 
571 static void cr_idx_w_seq_keys_fini(struct cr_idx_w *w)
572 {
573  w->prev_key_used = false;
574 }
575 
577  int nr, enum cr_opcode op)
578 {
579  M0_PRE(nr > 0);
581 
582  return (w->nr_ops[op].prev_key + nr > w->nr_keys) ?
583  0 : w->nr_ops[op].prev_key + 1;
584 }
585 
586 static bool cr_idx_w_seq_keys_enabled(struct cr_idx_w *w)
587 {
588  return w->prev_key_used;
589 }
590 
591 static void cr_idx_w_seq_keys_save(struct cr_idx_w *w,
592  int *keys, size_t keys_nr,
593  enum cr_opcode op)
594 {
596 
597  if (w->prev_key_used) {
598  w->nr_ops[op].prev_key = keys[keys_nr - 1];
599  w->nr_ops[op].prev_key_nr = keys_nr;
600  }
601 }
602 
603 
604 /* Key-Value pairs (records) */
605 struct kv_pair {
606  struct m0_bufvec *k;
607  struct m0_bufvec *v;
608 };
609 
610 static void idx_bufvec_free(struct m0_bufvec *bv)
611 {
612  uint32_t i;
613 
614  if (bv == NULL)
615  return;
616 
617  if (bv->ov_buf != NULL) {
618  for (i = 0; i < bv->ov_vec.v_nr; ++i)
619  free(bv->ov_buf[i]);
620  free(bv->ov_buf);
621  }
622  free(bv->ov_vec.v_count);
623  free(bv);
624 }
625 
626 static void kv_pair_fini(struct kv_pair *p)
627 {
628  idx_bufvec_free(p->k);
629  idx_bufvec_free(p->v);
630 }
631 
632 static struct m0_bufvec* idx_bufvec_alloc(int nr)
633 {
634  struct m0_bufvec *bv;
635 
636  M0_ALLOC_PTR(bv);
637  if (bv == NULL)
638  return NULL;
639 
640  bv->ov_vec.v_nr = nr;
641 
643  if (bv->ov_vec.v_count == NULL)
644  goto do_free;
645 
646  M0_ALLOC_ARR(bv->ov_buf, nr);
647  if (bv->ov_buf == NULL)
648  goto do_free;
649 
650  return bv;
651 
652 do_free:
653  m0_bufvec_free(bv);
654  return NULL;
655 }
656 
657 static size_t cr_idx_w_get_value_size(struct cr_idx_w *w)
658 {
659  int vlen;
660  /* If value_size is random, generate it using rand() */
661  if (w->wit->value_size < 0)
662  vlen = w->wit->key_size +
664  else
665  vlen = w->wit->value_size;
666 
668  M0_POST(vlen > 0);
669  return vlen;
670 }
671 
673 {
674  size_t result;
675 
676  if (op == CRATE_OP_NEXT && w->wit->next_records > 0) {
677  result = 1 + cr_rand_pos_range(w->wit->next_records);
678  M0_POST(result < CR_MAX_NEXT_RECORDS);
679  } else
680  result = w->nr_kv_per_op;
681 
682  return result;
683 }
684 
685 static int fill_kv_del(struct cr_idx_w *w,
686  struct m0_fid *k, struct kv_pair *p, size_t nr,
687  int kpart_one_size, char *kpart_one)
688 {
689  int i;
690 
691  p->k = idx_bufvec_alloc(nr);
692  if (p->k == NULL)
693  return M0_ERR(-ENOMEM);
694 
695  p->v = NULL;
696 
697  M0_ASSERT(p->k->ov_vec.v_nr == nr);
698 
699  for (i = 0; i < nr; i++) {
700  p->k->ov_vec.v_count[i] = w->wit->key_size;
701  p->k->ov_buf[i] = m0_alloc(w->wit->key_size);
702  memcpy(p->k->ov_buf[i], (void*)kpart_one, kpart_one_size);
703  memcpy(p->k->ov_buf[i] + kpart_one_size, &k[i], sizeof(*k));
704 
705  crlog(CLL_DEBUG, "Generated k=%s:" FID_F, kpart_one, FID_P(&k[i]));
706  }
707  return M0_RC(0);
708 }
709 
710 static int fill_kv_next(struct cr_idx_w *w,
711  struct m0_fid *k, struct kv_pair *p, size_t nr,
712  int kpart_one_size, char *kpart_one)
713 {
714  p->k = idx_bufvec_alloc(nr);
715  if (p->k == NULL)
716  return M0_ERR(-ENOMEM);
717 
718  p->v = idx_bufvec_alloc(nr);
719  if (p->v == NULL) {
720  idx_bufvec_free(p->k);
721  return M0_ERR(-ENOMEM);
722  }
723 
724  M0_ASSERT(p->k->ov_vec.v_nr == nr);
725  M0_ASSERT(p->v->ov_vec.v_nr == nr);
726 
727  p->k->ov_vec.v_count[0] = w->wit->key_size;
728  p->k->ov_buf[0] = m0_alloc(w->wit->key_size);
729  memcpy(p->k->ov_buf[0], (void*)kpart_one, kpart_one_size);
730  memcpy(p->k->ov_buf[0] + kpart_one_size, &k[0], sizeof(*k));
731  crlog(CLL_DEBUG, "Generated next k=%s:" FID_F, kpart_one, FID_P(&k[0]));
732 
733  return M0_RC(0);
734 }
735 
736 static int fill_kv_get(struct cr_idx_w *w,
737  struct m0_fid *k, struct kv_pair *p, size_t nr,
738  int kpart_one_size, char *kpart_one)
739 {
740  int i;
741 
742  p->k = idx_bufvec_alloc(nr);
743  if (p->k == NULL)
744  return M0_ERR(-ENOMEM);
745 
746  p->v = idx_bufvec_alloc(nr);
747  if (p->v == NULL) {
748  idx_bufvec_free(p->k);
749  return M0_ERR(-ENOMEM);
750  }
751 
752  M0_ASSERT(p->k->ov_vec.v_nr == nr);
753  M0_ASSERT(p->v->ov_vec.v_nr == nr);
754 
755  for (i = 0; i < nr; i++) {
756  p->k->ov_vec.v_count[i] = w->wit->key_size;
757  p->k->ov_buf[i] = m0_alloc(w->wit->key_size);
758  memcpy(p->k->ov_buf[i], (void*)kpart_one, kpart_one_size);
759  memcpy(p->k->ov_buf[i] + kpart_one_size, &k[i], sizeof(*k));
760  crlog(CLL_DEBUG, "Generated k=%s:" FID_F, kpart_one, FID_P(&k[i]));
761  }
762 
763  return M0_RC(0);
764 }
765 static int fill_kv_put(struct cr_idx_w *w,
766  struct m0_fid *k, struct kv_pair *p, size_t nr,
767  int kpart_one_size, char *kpart_one)
768 {
769  int vlen;
770  int i;
771 
772  p->k = idx_bufvec_alloc(nr);
773  if (p->k == NULL)
774  return M0_ERR(-ENOMEM);
775 
776  p->v = idx_bufvec_alloc(nr);
777  if (p->v == NULL) {
778  idx_bufvec_free(p->k);
779  return M0_ERR(-ENOMEM);
780  }
781 
782  M0_ASSERT(p->k->ov_vec.v_nr == nr);
783  M0_ASSERT(p->v->ov_vec.v_nr == nr);
784 
785  for (i = 0; i < nr; i++) {
786  p->k->ov_vec.v_count[i] = w->wit->key_size;
787  p->k->ov_buf[i] = m0_alloc_aligned(w->wit->key_size,
788  m0_pageshift_get());
789  memcpy(p->k->ov_buf[i], (void*)kpart_one, kpart_one_size);
790  memcpy(p->k->ov_buf[i] + kpart_one_size, &k[i], sizeof(*k));
791  vlen = cr_idx_w_get_value_size(w);
792  p->v->ov_vec.v_count[i] = vlen;
793  p->v->ov_buf[i] = m0_alloc_aligned(vlen, m0_pageshift_get());
794  cr_get_random_string(p->v->ov_buf[i], vlen);
795  crlog(CLL_DEBUG, "Generated k=%s:" FID_F ",v=%s",
796  kpart_one,
797  FID_P(&k[i]),
798  vlen > 128 ? "<...>": (char *) p->v->ov_buf[i]);
799  }
800 
801  return M0_RC(0);
802 }
803 
804 typedef int (*cr_idx_w_find_k_t)(struct cr_idx_w *w, enum cr_opcode opcode,
805  int *keys, size_t nr_keys);
806 
807 struct cr_idx_w_ops {
808  enum cr_opcode op;
810  bool empty_bit;
812  int (*fill_kv)(struct cr_idx_w *w,
813  struct m0_fid *k,
814  struct kv_pair *p,
815  size_t nr,
816  int kpart_one_size,
817  char *kpart_one);
819  bool readonly;
821  bool is_set_op;
825  const char *name;
826 };
827 
829  [CRATE_OP_PUT] = {
830  .op = CRATE_OP_PUT,
831  .empty_bit = false,
832  .fill_kv = fill_kv_put,
833  .readonly = false,
834  .is_set_op = true,
835  .m0_op = M0_IC_PUT,
836  .name = "put",
837  },
838  [CRATE_OP_DEL] = {
839  .op = CRATE_OP_DEL,
840  .empty_bit = true,
841  .fill_kv = fill_kv_del,
842  .readonly = false,
843  .is_set_op = false,
844  .m0_op = M0_IC_DEL,
845  .name = "del",
846  },
847  [CRATE_OP_GET] = {
848  .op = CRATE_OP_GET,
849  .empty_bit = true,
850  .fill_kv = fill_kv_get,
851  .readonly = true,
852  .is_set_op = false,
853  .m0_op = M0_IC_GET,
854  .name = "get",
855  },
856  [CRATE_OP_NEXT] = {
857  .op = CRATE_OP_NEXT,
858  .empty_bit = true,
859  .fill_kv = fill_kv_next,
860  .readonly = true,
861  .is_set_op = false,
862  .m0_op = M0_IC_NEXT,
863  .name = "next",
864  },
865 };
866 
867 static const char *crate_op_to_string(enum cr_opcode op)
868 {
869  return cr_idx_w_ops[op].name;
870 }
871 
873 {
874  return opcode != CRATE_OP_INVALID;
875 }
876 
878 static M0_UNUSED bool int_array_is_set(int *vals, size_t nr)
879 {
880  int i;
881  int j;
882 
883  for (i = 0; i < nr; i++) {
884  for (j = 0; j < nr; j++) {
885  if (i != j && vals[i] == vals[j])
886  return false;
887  }
888  }
889 
890  return true;
891 }
892 
893 static int cr_idx_w_find_seq_k(struct cr_idx_w *w,
894  enum cr_opcode opcode,
895  int *keys, size_t nr_keys)
896 {
897  struct cr_idx_w_ops *op = &cr_idx_w_ops[opcode];
898  int key_iter = 0;
899  int start_key = 0;
900  int rc = 0;
901  int i;
902 
903  M0_PRE(w->nr_keys > 0);
904  M0_PRE(nr_keys != 0);
905 
906  if (cr_idx_w_seq_keys_enabled(w)) {
907  start_key = cr_idx_w_seq_keys_get_last(w, nr_keys, opcode);
908  crlog(CLL_DEBUG, "starting_key_num=%d", start_key);
909  }
910 
911  for (i = start_key; i < w->nr_keys; i++) {
912  if (m0_bitmap_get(&w->bm, i) == op->empty_bit) {
913  keys[key_iter++] = i;
914  if (key_iter == nr_keys)
915  break;
916  }
917  }
918 
919  if (key_iter != nr_keys) {
920  crlog(CLL_ERROR, "Unable to find enough keys for opcode '%s'",
922  m0_bitmap_print(&w->bm);
923  rc = M0_ERR(-ENOENT);
924  } else
925  M0_POST(int_array_is_set(keys, nr_keys));
926 
927  return M0_RC(rc);
928 }
929 
930 static bool m0_bitmap_is_fulfilled(struct m0_bitmap *bm, bool fill)
931 {
932  return (m0_forall(i, bm->b_nr, fill == m0_bitmap_get(bm, i)));
933 }
934 
935 static int cr_idx_w_find_rnd_k(struct cr_idx_w *w,
936  enum cr_opcode opcode,
937  int *keys, size_t nr_keys)
938 {
939  struct cr_idx_w_ops *op = &cr_idx_w_ops[opcode];
940  int rc = 0;
941  int r;
942  int key_iter = 0;
943  size_t attempts = 0;
944 
945  M0_PRE(w->nr_keys > 0);
946 
947  while (key_iter != nr_keys) {
948  if (attempts > w->bm.b_nr &&
949  m0_bitmap_is_fulfilled(&w->bm, !op->empty_bit)) {
950  crlog(CLL_ERROR, "Map hasn't available bits.");
951  rc = M0_ERR(-ENOENT);
952  break;
953  }
954 
956  M0_ASSERT(r < w->nr_keys);
957  attempts++;
958 
959  /* skip key if it already present in 'keys' or
960  * or if it can not be used for op */
961  if (!m0_exists(i, key_iter, keys[i] == r) &&
962  m0_bitmap_get(&w->bm, r) == op->empty_bit) {
963  attempts = 0;
964  keys[key_iter] = r;
965  key_iter++;
966  }
967  }
968 
969  if (rc != 0) {
970  crlog(CLL_ERROR, "Unable to find key for opcode '%s'",
972  m0_bitmap_print(&w->bm);
973  } else
974  M0_POST(int_array_is_set(keys, nr_keys));
975 
976  return M0_RC(rc);
977 }
978 
979 static int cr_execute_query(struct m0_fid *id,
980  struct kv_pair *p,
981  enum cr_opcode opcode)
982 {
983  struct m0_op *ops[1] = { [0] = NULL };
984  int32_t *rcs;
985  int rc;
986  struct m0_idx idx = {};
987  int kv_nr;
988  int flags = 0;
989  int kv_index;
990  struct cr_idx_w_ops *op = &cr_idx_w_ops[opcode];
991 
992  kv_nr = p->k->ov_vec.v_nr;
993 
994  if (NULL == M0_ALLOC_ARR(rcs, kv_nr))
995  return M0_ERR(-ENOMEM);
996 
997  m0_idx_init(&idx, crate_uber_realm(), (struct m0_uint128 *) id);
998 
999  if (conf->is_enf_meta && m0_fid_is_valid(&dix_pool_ver) &&
1004  crlog(CLL_DEBUG, "DIX pool version: "FID_F"",
1005  FID_P(&idx.in_attr.idx_pver));
1006  }
1007 
1008  rc = m0_idx_op(&idx, op->m0_op, p->k, p->v, rcs, flags, &ops[0]);
1009  if (rc != 0) {
1010  crlog(CLL_ERROR, "Unable to init Client idx op: %s",
1011  strerror(-rc));
1012  goto end;
1013  }
1014 
1015  m0_op_launch(ops, 1);
1016 
1018  M0_TIME_NEVER);
1019  if (rc != 0) {
1020  crlog(CLL_ERROR, "Client op failed: %s", strerror(-rc));
1021  goto end;
1022  }
1023 
1024  if (m0_exists(i, kv_nr, (kv_index = i, (rc = rcs[i]) != 0))) {
1025  /* XXX: client destroys keys, if NEXT op failed */
1026  if (op->m0_op == M0_IC_NEXT) {
1027  crlog(CLL_ERROR,
1028  "Failed to perform client operation %s: k="
1029  FID_F " %s (%d), index=%d",
1030  crate_op_to_string(op->op),
1031  FID_P((struct m0_fid *) p->k->ov_buf[0]),
1032  strerror(-rc), rc, kv_index);
1033  } else {
1034  crlog(CLL_ERROR,
1035  "Failed to perform client operation %s: k="
1036  FID_F " %s (%d)",
1037  crate_op_to_string(op->op),
1038  FID_P((struct m0_fid *) p->k->ov_buf[kv_index]),
1039  strerror(-rc), rc);
1040  }
1041  } else
1042  rc = ops[0]->op_sm.sm_rc;
1043 
1044 end:
1045  if (ops[0] != NULL) {
1046  m0_op_fini(ops[0]);
1047  m0_op_free(ops[0]);
1048  }
1049  m0_idx_fini(&idx);
1050  m0_free0(&rcs);
1051 
1052  return M0_RC(rc);
1053 }
1054 
1055 static bool cr_idx_w_timeout_expired(struct cr_idx_w *w)
1056 {
1057  return ergo(w->exec_time > 0,
1059  w->exec_time);
1060 }
1061 
1062 static int cr_idx_w_execute(struct cr_idx_w *w,
1063  enum cr_opcode opcode,
1064  bool random,
1065  size_t nr_keys,
1066  bool *missing_key)
1067 {
1068  struct cr_idx_w_ops *op = &cr_idx_w_ops[opcode];
1069  cr_idx_w_find_k_t find_fn;
1070  int rc;
1071  int *ikeys = NULL;
1072  struct m0_fid *keys = NULL;
1073  struct kv_pair kv = {0};
1074  int i;
1075  /* key will contain <const value:random or sequential generated value> */
1076  int kpart_one_size = w->wit->key_size - w->wit->min_key_size;
1077  char kpart_one[kpart_one_size];
1078  m0_time_t op_start_time;
1079  m0_time_t op_time;
1080 
1081  M0_PRE(nr_keys > 0);
1082 
1084 
1085  if (cr_idx_w_timeout_expired(w)) {
1086  crlog(CLL_ERROR, "Timeout expired.");
1087  return M0_ERR(-ETIME);
1088  }
1089 
1090  if (NULL == M0_ALLOC_ARR(ikeys, nr_keys)) {
1091  rc = M0_ERR(-ENOMEM);
1092  goto do_exit;
1093  }
1094 
1095  if (NULL == M0_ALLOC_ARR(keys, nr_keys)) {
1096  rc = M0_ERR(-ENOMEM);
1097  goto do_exit_ik;
1098  }
1099 
1100  find_fn = (random ? cr_idx_w_find_rnd_k : cr_idx_w_find_seq_k);
1101  rc = find_fn(w, opcode, ikeys, nr_keys);
1102 
1103  if (rc != 0) {
1104  if (missing_key)
1105  *missing_key = true;
1106  rc = M0_ERR(rc);
1107  goto do_exit_keys;
1108  }
1109 
1110  for (i = 0; i < nr_keys; i++) {
1111  keys[i].f_key = ikeys[i];
1112  keys[i].f_container = w->key_prefix.f_container;
1113  }
1114 
1115  /* populating key prefix */
1116  memset(kpart_one, 'A', kpart_one_size);
1117 
1118  rc = op->fill_kv(w, keys, &kv, nr_keys, kpart_one_size, kpart_one);
1119  if (rc != 0) {
1120  rc = M0_ERR(rc);
1121  goto do_exit_kv;
1122  }
1123  /* accumulate time required by each op on opcode basis. */
1124  op_start_time = m0_time_now();
1125  rc = cr_execute_query(&w->wit->index_fid, &kv, opcode);
1126  op_time = m0_time_sub(m0_time_now(), op_start_time);
1129  op_time);
1130  if (rc != 0) {
1131  rc = M0_ERR(rc);
1132  goto do_exit_kv;
1133  }
1134 
1135  if (op->readonly) {
1136  if (!random)
1137  cr_idx_w_seq_keys_save(w, ikeys, nr_keys, opcode);
1138  } else {
1139  for (i = 0; i < nr_keys; i++)
1140  m0_bitmap_set(&w->bm, ikeys[i], op->is_set_op);
1141  }
1142 
1143  crlog(CLL_TRACE, "Executed op: %s", crate_op_to_string(opcode));
1144 
1145 do_exit_kv:
1146  kv_pair_fini(&kv);
1147 do_exit_keys:
1148  m0_free0(&keys);
1149 do_exit_ik:
1150  m0_free0(&ikeys);
1151 do_exit:
1152  return M0_RC(rc);
1153 }
1154 
1155 
1157 {
1158  int result = 0;
1159  int i;
1160 
1161  if (w->nr_ops_total > 0)
1162  for (i = 0; i < ARRAY_SIZE(w->nr_ops); i++)
1163  result += w->nr_ops[i].nr;
1164 
1165  return result;
1166 }
1167 
1168 static enum cr_opcode cr_idx_w_select_op_rr(struct cr_idx_w *w, int depth)
1169 {
1170  enum cr_opcode rc = CRATE_OP_START;
1171  int max_ops_cnt = 0;
1172  int i;
1173 
1175 
1176  /* find opcode, which has max value of ops */
1177  for (i = 0; i < ARRAY_SIZE(w->nr_ops); i++) {
1178  if (w->nr_ops[i].pending)
1179  continue;
1180  if (w->nr_ops[i].nr > max_ops_cnt) {
1181  max_ops_cnt = w->nr_ops[i].nr;
1182  rc = (enum cr_opcode) i;
1183  }
1184  }
1185 
1186  if (max_ops_cnt == 0) {
1187  rc = CRATE_OP_INVALID;
1188  /* try to use pending operations */
1189  for (i = 0; i < ARRAY_SIZE(w->nr_ops); i++) {
1190  if (w->nr_ops[i].pending) {
1191  w->nr_ops[i].pending = false;
1193  if (cr_opcode_valid(rc))
1194  break;
1195  }
1196  }
1197  }
1198 
1199  return rc;
1200 }
1201 
1202 static enum cr_opcode cr_idx_w_select_op(struct cr_idx_w *w)
1203 {
1204  enum cr_opcode rc = CRATE_OP_START;
1205 
1206  if (cr_idx_w_get_nr_remained_ops(w) == 0) {
1207  crlog(CLL_INFO, "End of operations.");
1208  return CRATE_OP_INVALID;
1209  }
1210 
1211  switch (w->op_selector) {
1212  case CR_OP_SEL_RR:
1213  rc = cr_idx_w_select_op_rr(w, 0);
1214  break;
1215 
1216  case CR_OP_SEL_RND:
1217  do {
1219  } while (w->nr_ops[rc].nr == 0);
1220  break;
1221  }
1222 
1223  return rc;
1224 }
1225 
1227 {
1228  int result = 0;
1229  int i;
1230 
1231  for (i = 0; i < ARRAY_SIZE(w->nr_ops); i++) {
1232  if (w->nr_ops[i].nr)
1233  result++;
1234  }
1235 
1236  return result;
1237 
1238 }
1239 
1240 static void cr_idx_w_print_ops_table(struct cr_idx_w *w)
1241 {
1242  M0_PRE(ARRAY_SIZE(w->nr_ops) == 4);
1243  crlog(CLL_TRACE, "ops remaining: [%d, %d, %d, %d]",
1244  w->nr_ops[0].nr,
1245  w->nr_ops[1].nr,
1246  w->nr_ops[2].nr,
1247  w->nr_ops[3].nr);
1248 }
1249 
1250 static bool cr_idx_w_rebalance_ops(struct cr_idx_w *w, enum cr_opcode op)
1251 {
1252  bool result = false;
1253  int i;
1254 
1255  if (cr_idx_w_get_nr_remained_ops(w) > 0
1257  for (i = 0; i < ARRAY_SIZE(w->nr_ops); i++)
1258  w->nr_ops[i].pending = cr_rand_bool();
1259  result = true;
1260  } else
1261  crlog(CLL_WARN, "Reached end of keys.");
1262 
1263  return result;
1264 }
1265 
1266 static int cr_idx_w_common(struct cr_idx_w *w)
1267 {
1268  int rc;
1269  enum cr_opcode op;
1270  bool is_random;
1271  bool missing_key = false;
1272  int nr_kv_per_op;
1273 
1275 
1276  while (true) {
1277  op = cr_idx_w_select_op(w);
1279 
1280  if (!cr_opcode_valid(op)) {
1281  rc = M0_RC(0);
1282  break;
1283  }
1284 
1285  m0_bitmap_print(&w->bm);
1286 
1287  is_random = !w->wit->keys_ordered;
1288 
1289  nr_kv_per_op = cr_idx_w_get_nr_keys_per_op(w, op);
1290  crlog(CLL_DEBUG, "nr_kv_per_op: %d", nr_kv_per_op);
1291 
1292  rc = cr_idx_w_execute(w, op, is_random, nr_kv_per_op,
1293  &missing_key);
1294  if (rc != 0) {
1295  /* try to select another op type */
1296  if (missing_key && (cr_idx_w_rebalance_ops(w, op)))
1297  continue;
1298  break;
1299  }
1300  w->nr_ops[op].nr--;
1301  }
1302 
1303  m0_bitmap_print(&w->bm);
1305 
1306  return M0_RC(rc);
1307 }
1308 
1309 static int cr_idx_w_warmup(struct cr_idx_w *w)
1310 {
1311  int rc = 0;
1312  int i;
1313 
1314  for (i = 0; i < w->warmup_put_cnt && rc == 0; i++) {
1315  m0_bitmap_print(&w->bm);
1316  rc = cr_idx_w_execute(w, CRATE_OP_PUT, false,
1317  w->nr_kv_per_op, NULL);
1318  }
1319 
1320  for (i = 0; i < w->warmup_del_cnt && rc == 0; i++) {
1321  m0_bitmap_print(&w->bm);
1322  rc = cr_idx_w_execute(w, CRATE_OP_DEL, true,
1323  w->nr_kv_per_op, NULL);
1324  }
1325 
1326  return M0_RC(rc);
1327 }
1328 
1329 
1330 static M0_UNUSED int delete_index(struct m0_uint128 id)
1331 {
1332  int rc;
1333  struct m0_op *ops[1] = { NULL };
1334  struct m0_idx idx = {};
1335 
1337  M0_PRE(crate_uber_realm()->re_instance != NULL);
1338 
1339  /* Set an index deletion operation. */
1340  m0_idx_init(&idx, crate_uber_realm(), &id);
1341 
1342  rc = m0_entity_delete(&idx.in_entity, &ops[0]);
1343  if (rc == 0) {
1344  /* Launch and wait for op to complete */
1345  m0_op_launch(ops, 1);
1347  M0_OS_STABLE),
1348  M0_TIME_NEVER);
1349 
1350  if (rc != 0)
1351  crlog(CLL_ERROR, "Unable to perform index del");
1352  else if (ops[0]->op_sm.sm_rc != 0) {
1353  if (ops[0]->op_sm.sm_rc == -ENOENT)
1354  crlog(CLL_ERROR, "Index not found");
1355  else
1356  rc = ops[0]->op_sm.sm_rc;
1357  }
1358  } else
1359  crlog(CLL_ERROR, "Unable to set delete operation.");
1360 
1361  /* fini and release */
1362  if (ops[0] != NULL) {
1363  m0_op_fini(ops[0]);
1364  m0_op_free(ops[0]);
1365  }
1366  m0_idx_fini(&idx);
1367 
1368  return M0_RC(rc);
1369 }
1370 
1371 static int create_index(struct m0_uint128 id)
1372 {
1373  int rc;
1374  struct m0_op *ops[1] = { NULL };
1375  struct m0_idx idx = {};
1376 
1378  M0_PRE(crate_uber_realm()->re_instance != NULL);
1379 
1380  /* Set an index creation operation. */
1381  m0_idx_init(&idx, crate_uber_realm(), &id);
1382 
1383  if (conf->is_enf_meta)
1385 
1386  rc = m0_entity_create(NULL, &idx.in_entity, &ops[0]);
1387  if (rc == 0) {
1388  /* Launch and wait for op to complete */
1389  m0_op_launch(ops, 1);
1391  M0_OS_STABLE),
1392  M0_TIME_NEVER);
1393 
1394  if (rc != 0)
1395  crlog(CLL_ERROR, "Unable to perform index create");
1396  else if (ops[0]->op_sm.sm_rc != 0) {
1397  if (ops[0]->op_sm.sm_rc == -EEXIST)
1398  crlog(CLL_WARN, "Index alredy exists.");
1399  else
1400  rc = ops[0]->op_sm.sm_rc;
1401  }
1402 
1403  if (rc == 0 && conf->is_enf_meta) {
1404  crlog(CLL_DEBUG, "DIX pool version: "FID_F"",
1405  FID_P(&idx.in_attr.idx_pver));
1407  }
1408  } else
1409  crlog(CLL_ERROR, "Unable to set index create operation.");
1410 
1411  /* fini and release */
1412  if (ops[0] != NULL) {
1413  m0_op_fini(ops[0]);
1414  m0_op_free(ops[0]);
1415  }
1416  m0_idx_fini(&idx);
1417 
1418  return M0_RC(rc);
1419 }
1420 
1421 struct cr_watchdog {
1422  struct m0_mutex lock;
1423  uint64_t counter;
1424  uint64_t sleep_sec;
1425  struct m0_thread thr;
1426 };
1427 
1428 static void cr_watchdog_thread(void *arg)
1429 {
1430  struct cr_watchdog *w = arg;
1431 
1432  crlog(CLL_INFO, "Watchdog started");
1433  while (true) {
1434  m0_mutex_lock(&w->lock);
1435  if (w->counter == 0) {
1436  crlog(CLL_ERROR, "watchdog: blocked task detected."
1437  " Exiting.");
1438  m0_nanosleep(m0_time(0, 100000), NULL);
1439  exit(EXIT_FAILURE);
1440  }
1441  w->counter = 0;
1442  m0_mutex_unlock(&w->lock);
1443  sleep(w->sleep_sec);
1444  }
1445 }
1446 
1447 static void cr_watchdog_touch()
1448 {
1449  struct cr_watchdog *w = cr_watchdog;
1450 
1451  /* don't touch wg if it isn't exists */
1452  if (w == NULL)
1453  return;
1454 
1455  m0_mutex_lock(&w->lock);
1456  w->counter++;
1457  m0_mutex_unlock(&w->lock);
1458 }
1459 
1460 static int cr_watchdog_init(struct m0_workload_index *wt)
1461 {
1462  int rc;
1463 
1465  if (cr_watchdog == NULL)
1466  rc = M0_ERR(-ENOMEM);
1467  else {
1469  cr_watchdog->counter = wt->exec_time;
1471 
1473  cr_watchdog, "watchdog");
1474  }
1475 
1476  if (rc != 0) {
1478  crlog(CLL_ERROR, "Unable to init watchdog (%s)", strerror(-rc));
1479  }
1480 
1481  return M0_RC(rc);
1482 }
1483 
1484 static void cr_watchdog_fini()
1485 {
1486  if (cr_watchdog == NULL)
1487  return;
1488  (void) m0_thread_signal(&cr_watchdog->thr, SIGTERM);
1489  (void) m0_thread_join(&cr_watchdog->thr);
1493 }
1494 
1495 static int index_operation(struct workload *wt,
1496  struct m0_workload_task *task)
1497 {
1498  struct cr_idx_w w = {};
1499  struct cr_time_measure_ctx t;
1500  struct m0_workload_index *wit = wt->u.cw_index;
1501  struct m0_uint128 index_fid;
1502  int rc;
1503 
1505  M0_PRE(crate_uber_realm()->re_instance != NULL);
1506 
1507  M0_CASSERT(sizeof(struct m0_uint128) == sizeof(struct m0_fid));
1508  memcpy(&index_fid, &wit->index_fid, sizeof(index_fid));
1509 
1511 
1512  if (wit->exec_time > 0) {
1513  rc = cr_watchdog_init(wit);
1514  if (rc != 0)
1515  goto do_exit;
1516  }
1517 
1518  rc = cr_idx_w_init(&w, wit);
1519  if (rc != 0)
1520  goto do_exit_wg;
1521 
1522  rc = create_index(index_fid);
1523  if (rc != 0)
1524  goto do_exit_idx_w;
1525 
1526  rc = cr_idx_w_warmup(&w);
1527  if (rc != 0)
1528  goto do_del_idx;
1529 
1530  rc = cr_idx_w_common(&w);
1531  if (rc != 0)
1532  goto do_del_idx;
1533 
1534 do_del_idx:
1535  /* XXX: index deletion disabled. */
1536 #if 0
1537  rc = delete_index(index_fid);
1538  M0_ASSERT(rc != 0);
1539 #endif
1540 do_exit_idx_w:
1541  cr_idx_w_fini(&w);
1542 do_exit_wg:
1543  cr_watchdog_fini();
1545  cr_time_capture_results(&t, &w);
1547 do_exit:
1548  return M0_RC(rc);
1549 }
1550 
1551 void run_index(struct workload *w, struct workload_task *tasks)
1552 {
1553  workload_start(w, tasks);
1554  workload_join(w, tasks);
1555 }
1556 
1557 void m0_op_run_index(struct workload *w, struct workload_task *task,
1558  const struct workload_op *op)
1559 {
1560  struct m0_workload_task *m0_task;
1561  int rc;
1562  bool is_m0_thread;
1563 
1565  M0_PRE(crate_uber_realm()->re_instance != NULL);
1566 
1567  if (NULL == M0_ALLOC_PTR(m0_task)) {
1568  crlog(CLL_ERROR, "Out of memory.");
1569  exit(EXIT_FAILURE);
1570  }
1571 
1572  is_m0_thread = m0_thread_tls() != NULL;
1573 
1574  if (!is_m0_thread) {
1575  rc = adopt_motr_thread(m0_task);
1576  if (rc != 0) {
1577  crlog(CLL_ERROR, "Unable to adopt thread (%s)",
1578  strerror(-rc));
1579  goto exit_free;
1580  }
1581  }
1582 
1583  rc = index_operation(w, m0_task);
1584  if (rc != 0) {
1585  crlog(CLL_ERROR,
1586  "Failed to perform index operation (%s)",
1587  strerror(-rc));
1588  }
1589 
1590  if (!is_m0_thread) {
1591  release_motr_thread(m0_task);
1592  }
1593 
1594 exit_free:
1595  m0_free(m0_task);
1596 }
1597 
1598 /*
1599  * Local variables:
1600  * c-indentation-style: "K&R"
1601  * c-basic-offset: 8
1602  * tab-width: 8
1603  * fill-column: 80
1604  * scroll-step: 1
1605  * End:
1606  */
1607 /*
1608  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
1609  */
struct m0_fid idx_pver
Definition: client.h:821
static void cr_idx_w_fini(struct cr_idx_w *ciw)
Definition: crate_index.c:555
struct cr_watchdog * cr_watchdog
Definition: crate_index.c:314
uint64_t sleep_sec
Definition: crate_index.c:1424
static struct m0_addb2_philter p
Definition: consumer.c:40
static size_t nr
Definition: dump.c:1505
void * cw_index
Definition: workload.h:99
static void cr_idx_w_print_ops_table(struct cr_idx_w *w)
Definition: crate_index.c:1240
static size_t cr_rand_pos_range_l(size_t end)
Definition: crate_index.c:190
void m0_op_run_index(struct workload *w, struct workload_task *task, const struct workload_op *op)
Definition: crate_index.c:1557
static int cr_idx_w_warmup(struct cr_idx_w *w)
Definition: crate_index.c:1309
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL int m0_bitmap_init(struct m0_bitmap *map, size_t nr)
Definition: bitmap.c:86
Definition: client.h:841
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
static bool cr_idx_w_rebalance_ops(struct cr_idx_w *w, enum cr_opcode op)
Definition: crate_index.c:1250
static bool m0_bitmap_is_fulfilled(struct m0_bitmap *bm, bool fill)
Definition: crate_index.c:930
int const char const void size_t int flags
Definition: dir.c:328
static void cr_get_random_string(char *dest, size_t length)
Definition: crate_index.c:211
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_bitmap_fini(struct m0_bitmap *map)
Definition: bitmap.c:97
m0_idx_opcode
Definition: client.h:550
uint32_t idx_layout_type
Definition: client.h:819
#define LOG_PREFIX
Definition: crate_index.c:147
struct m0_bufvec * v
Definition: crate_index.c:607
struct m0_workload_index * wit
Definition: crate_index.c:339
#define ergo(a, b)
Definition: misc.h:293
double ciwr_time_per_op_ns
Definition: crate_index.c:268
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
void m0_op_fini(struct m0_op *op)
Definition: client.c:848
struct m0_mutex lock
Definition: crate_index.c:1422
uint64_t m0_time_t
Definition: time.h:37
double cior_time_per_op_ns
Definition: crate_index.c:259
void run_index(struct workload *w, struct workload_task *tasks)
Definition: crate_index.c:1551
#define M0_CASSERT(cond)
static int cr_idx_w_seq_keys_get_last(struct cr_idx_w *w, int nr, enum cr_opcode op)
Definition: crate_index.c:576
bool ordered_keys
Definition: crate_index.c:343
struct m0_vec ov_vec
Definition: vec.h:147
uint64_t m0_time_nanoseconds(const m0_time_t time)
Definition: time.c:89
struct m0_fid index_fid
Definition: crate_client.h:114
struct m0_fid key_prefix
Definition: crate_client.h:102
static int cr_idx_w_init(struct cr_idx_w *ciw, struct m0_workload_index *wit)
Definition: crate_index.c:456
static void cr_time_capture_results(struct cr_time_measure_ctx *t, struct cr_idx_w *ciw)
Definition: crate_index.c:390
Definition: conf.py:1
#define m0_exists(var, nr,...)
Definition: misc.h:134
#define M0_BITS(...)
Definition: misc.h:236
void m0_idx_fini(struct m0_idx *idx)
Definition: idx.c:644
M0_INTERNAL int m0_pageshift_get(void)
Definition: memory.c:238
struct m0_idx_attr in_attr
Definition: client.h:843
int nr_keys
Definition: crate_index.c:347
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
#define TIME_P(t)
Definition: time.h:45
int opcode_prcnt[CRATE_OP_TYPES]
Definition: crate_client.h:84
enum cr_opcode op
Definition: crate_index.c:808
const char * cior_op_label
Definition: crate_index.c:249
m0_time_t m0_time(uint64_t secs, long ns)
Definition: time.c:41
static void cr_watchdog_touch()
Definition: crate_index.c:1447
M0_INTERNAL bool m0_fid_is_set(const struct m0_fid *fid)
Definition: fid.c:106
void ** ov_buf
Definition: vec.h:149
static int cr_rand_pos_range(int end)
Definition: crate_index.c:184
int warmup_put_cnt
Definition: crate_index.c:344
void workload_start(struct workload *w, struct workload_task *task)
Definition: crate.c:340
int adopt_motr_thread(struct m0_workload_task *task)
static int fill_kv_next(struct cr_idx_w *w, struct m0_fid *k, struct kv_pair *p, size_t nr, int kpart_one_size, char *kpart_one)
Definition: crate_index.c:710
int32_t m0_op_wait(struct m0_op *op, uint64_t bits, m0_time_t to)
Definition: client.c:738
int m0_idx_op(struct m0_idx *idx, enum m0_idx_opcode opcode, struct m0_bufvec *keys, struct m0_bufvec *vals, int32_t *rcs, uint32_t flags, struct m0_op **op)
Definition: idx.c:555
return M0_RC(rc)
op
Definition: libdemo.c:64
static enum cr_opcode cr_idx_w_select_op(struct cr_idx_w *w)
Definition: crate_index.c:1202
static int cr_idx_w_find_seq_k(struct cr_idx_w *w, enum cr_opcode opcode, int *keys, size_t nr_keys)
Definition: crate_index.c:893
M0_INTERNAL struct m0_thread_tls * m0_thread_tls(void)
Definition: kthread.c:67
uint64_t counter
Definition: crate_index.c:1423
M0_INTERNAL void m0_bufvec_free(struct m0_bufvec *bufvec)
Definition: vec.c:395
static void cr_idx_w_seq_keys_fini(struct cr_idx_w *w)
Definition: crate_index.c:571
struct m0_entity in_entity
Definition: client.h:842
int(* cr_idx_w_find_k_t)(struct cr_idx_w *w, enum cr_opcode opcode, int *keys, size_t nr_keys)
Definition: crate_index.c:804
cr_opcode
Definition: crate_client.h:66
static int cr_idx_w_get_nr_remained_op_types(struct cr_idx_w *w)
Definition: crate_index.c:1226
union workload::@328 u
int opcode
Definition: crate.c:301
#define TIME_F
Definition: time.h:44
int i
Definition: dir.c:1033
static void cr_watchdog_thread(void *arg)
Definition: crate_index.c:1428
static unsigned depth
Definition: base.c:377
static void cr_idx_w_seq_keys_save(struct cr_idx_w *w, int *keys, size_t keys_nr, enum cr_opcode op)
Definition: crate_index.c:591
static void cr_time_measure_begin(struct cr_time_measure_ctx *t)
Definition: crate_index.c:279
Definition: client.h:647
return M0_ERR(-EOPNOTSUPP)
struct crate_conf * conf
int(* fill_kv)(struct cr_idx_w *w, struct m0_fid *k, struct kv_pair *p, size_t nr, int kpart_one_size, char *kpart_one)
Definition: crate_index.c:812
static double cr_time_measure_elapsed_now(struct cr_time_measure_ctx *t)
Definition: crate_index.c:285
cr_op_selector
Definition: crate_index.c:175
static int create_index(struct m0_uint128 id)
Definition: crate_index.c:1371
void workload_join(struct workload *w, struct workload_task *task)
Definition: crate.c:363
static int cr_idx_w_get_nr_keys_per_op(struct cr_idx_w *w, enum cr_opcode op)
Definition: crate_index.c:672
static size_t cr_idx_w_get_value_size(struct cr_idx_w *w)
Definition: crate_index.c:657
#define m0_free0(pptr)
Definition: memory.h:77
M0_INTERNAL int m0_thread_signal(struct m0_thread *q, int sig)
Definition: kthread.c:192
static int fill_kv_del(struct cr_idx_w *w, struct m0_fid *k, struct kv_pair *p, size_t nr, int kpart_one_size, char *kpart_one)
Definition: crate_index.c:685
#define M0_ASSERT(cond)
m0_time_t m0_time_now(void)
Definition: time.c:134
enum cr_op_selector op_selector
Definition: crate_index.c:352
static void cr_time_measure_end(struct cr_time_measure_ctx *t)
Definition: crate_index.c:292
static int fill_kv_put(struct cr_idx_w *w, struct m0_fid *k, struct kv_pair *p, size_t nr, int kpart_one_size, char *kpart_one)
Definition: crate_index.c:765
static struct m0_thread t[8]
Definition: service_ut.c:1231
struct cr_idx_ops_result ciwr_ops_result[CRATE_OP_NR]
Definition: crate_index.c:270
struct cr_time_measure_ctx exec_time_ctx
Definition: crate_index.c:350
int m0_thread_init(struct m0_thread *q, int(*init)(void *), void(*func)(void *), void *arg, const char *namefmt,...)
Definition: thread.c:41
int rand(void)
static M0_UNUSED bool int_array_is_set(int *vals, size_t nr)
Definition: crate_index.c:878
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
struct m0_fid key_prefix
Definition: crate_index.c:346
void m0_op_launch(struct m0_op **op, uint32_t nr)
Definition: client.c:724
void * m0_alloc(size_t size)
Definition: memory.c:126
static void cr_watchdog_fini()
Definition: crate_index.c:1484
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
uint64_t f_container
Definition: fid.h:39
#define M0_POST(cond)
static bool cr_idx_w_seq_keys_enabled(struct cr_idx_w *w)
Definition: crate_index.c:586
static int index_operation(struct workload *wt, struct m0_workload_task *task)
Definition: crate_index.c:1495
#define UINT64_MAX
Definition: types.h:44
M0_INTERNAL void m0_bitmap_set(struct m0_bitmap *map, size_t idx, bool val)
Definition: bitmap.c:139
uint32_t v_nr
Definition: vec.h:51
m0_bcount_t * v_count
Definition: vec.h:53
m0_time_t m0_time_add(const m0_time_t t1, const m0_time_t t2)
Definition: time.c:47
#define FID_P(f)
Definition: fid.h:77
uint64_t m0_time_seconds(const m0_time_t time)
Definition: time.c:83
static void kv_pair_fini(struct kv_pair *p)
Definition: crate_index.c:626
static bool cr_rand_bool()
Definition: crate_index.c:205
static void cr_idx_w_seq_keys_init(struct cr_idx_w *w, int keys_nr)
Definition: crate_index.c:561
static int cr_idx_w_common(struct cr_idx_w *w)
Definition: crate_index.c:1266
#define m0_forall(var, nr,...)
Definition: misc.h:112
struct m0_bufvec * k
Definition: crate_index.c:606
int m0_entity_create(struct m0_fid *pool, struct m0_entity *entity, struct m0_op **op)
Definition: obj.c:801
int warmup_del_cnt
Definition: crate_index.c:345
struct cr_idx_w_results ciw_results
Definition: crate_index.c:353
static void m0_bitmap_print(struct m0_bitmap *bm)
Definition: crate_index.c:299
Definition: fid.h:38
double ciwr_total_time_s
Definition: crate_index.c:266
uint64_t f_key
Definition: fid.h:40
size_t exec_time
Definition: crate_index.c:351
static int cr_watchdog_init(struct m0_workload_index *wt)
Definition: crate_index.c:1460
m0_time_t cior_ops_total_time_m0
Definition: crate_index.c:255
static enum cr_opcode cr_idx_w_select_op_rr(struct cr_idx_w *w, int depth)
Definition: crate_index.c:1168
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
struct cr_ops_counter nr_ops[CRATE_OP_NR]
Definition: crate_index.c:341
static int r[NR]
Definition: thread.c:46
struct m0_thread thr
Definition: crate_index.c:1425
char * cr_idx_op_labels[CRATE_OP_NR]
Definition: crate_index.c:241
m0_time_t m0_time_sub(const m0_time_t t1, const m0_time_t t2)
Definition: time.c:65
enum m0_idx_opcode m0_op
Definition: crate_index.c:823
M0_INTERNAL bool m0_bitmap_get(const struct m0_bitmap *map, size_t idx)
Definition: bitmap.c:105
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
static M0_UNUSED int delete_index(struct m0_uint128 id)
Definition: crate_index.c:1330
struct m0_bitmap bm
Definition: crate_index.c:340
int nr_ops_total
Definition: crate_index.c:342
int nr_kv_per_op
Definition: crate_index.c:348
static int cr_idx_w_execute(struct cr_idx_w *w, enum cr_opcode opcode, bool random, size_t nr_keys, bool *missing_key)
Definition: crate_index.c:1062
static int cr_execute_query(struct m0_fid *id, struct kv_pair *p, enum cr_opcode opcode)
Definition: crate_index.c:979
static bool cr_idx_w_timeout_expired(struct cr_idx_w *w)
Definition: crate_index.c:1055
Definition: tasks.py:1
double cior_ops_total_time_s
Definition: crate_index.c:257
static int cr_idx_w_find_rnd_k(struct cr_idx_w *w, enum cr_opcode opcode, int *keys, size_t nr_keys)
Definition: crate_index.c:935
int m0_entity_delete(struct m0_entity *entity, struct m0_op **op)
Definition: obj.c:824
static double cr_time_in_seconds(m0_time_t mtime)
Definition: crate_index.c:273
static struct m0_bufvec * idx_bufvec_alloc(int nr)
Definition: crate_index.c:632
uint32_t en_flags
Definition: client.h:744
const char * name
Definition: crate_index.c:825
struct m0_realm * crate_uber_realm()
void m0_op_free(struct m0_op *op)
Definition: client.c:886
#define crlog(level,...)
Definition: logger.h:55
size_t b_nr
Definition: bitmap.h:44
M0_INTERNAL void * m0_alloc_aligned(size_t size, unsigned shift)
Definition: memory.c:168
M0_INTERNAL bool m0_fid_is_valid(const struct m0_fid *fid)
Definition: fid.c:96
struct m0_fom_ops ops
Definition: io_foms.c:623
static void cr_time_measure_report(struct cr_time_measure_ctx *t, struct cr_idx_w w)
Definition: crate_index.c:413
static int cr_idx_w_get_nr_remained_ops(struct cr_idx_w *w)
Definition: crate_index.c:1156
void m0_free(void *data)
Definition: memory.c:146
Definition: mutex.h:47
static void idx_bufvec_free(struct m0_bufvec *bv)
Definition: crate_index.c:610
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
void m0_idx_init(struct m0_idx *idx, struct m0_realm *parent, const struct m0_uint128 *id)
Definition: idx.c:627
struct m0_fid dix_pool_ver
Definition: crate_index.c:31
void release_motr_thread(struct m0_workload_task *task)
static int fill_kv_get(struct cr_idx_w *w, struct m0_fid *k, struct kv_pair *p, size_t nr, int kpart_one_size, char *kpart_one)
Definition: crate_index.c:736
#define FID_F
Definition: fid.h:75
void cr_log_ex(enum cr_log_level lev, const char *pre, const char *post, const char *fmt,...)
Definition: logger.c:69
Definition: vec.h:145
m0_time_t ciwr_total_time_m0
Definition: crate_index.c:264
static bool cr_opcode_valid(enum cr_opcode opcode)
Definition: crate_index.c:872
bool prev_key_used
Definition: crate_index.c:349
static const char * crate_op_to_string(enum cr_opcode op)
Definition: crate_index.c:867
#define M0_UNUSED
Definition: misc.h:380
int m0_nanosleep(const m0_time_t req, m0_time_t *rem)
Definition: ktime.c:73