Motr  M0
dtx.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
29 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_DTM
30 
31 #include "lib/trace.h"
32 #include "ut/ut.h"
33 #include "lib/misc.h" /* M0_SET0 */
34 
35 #include "dtm/dtm.h"
36 #include "dtm/fol.h"
37 #include "dtm/dtx.h"
38 #include "dtm/dtm_internal.h"
39 #include "dtm/remote.h"
40 
41 enum {
42  OPER_NR = 3,
43  UPDATE_NR = 15,
44  REM_NR = 7,
45  DTM_NR = REM_NR + 1,
47 };
48 
49 static struct m0_dtm dtm_local;
50 static struct m0_dtm dtm_remote[REM_NR];
53 static struct m0_dtm_dtx dx;
57 static struct m0_uint128 id0[UPDATE_NR * DTM_NR];
64 static struct m0_dtm_fol fol_remote[REM_NR];
65 static struct m0_tl uu;
70 
71 static void noop(struct m0_dtm_op *op)
72 {}
73 
74 static void never(struct m0_dtm_op *op)
75 {
76  M0_IMPOSSIBLE("Never.");
77 }
78 
79 static int undo_redo(struct m0_dtm_update *updt)
80 {
81  return 0;
82 }
83 
84 static const struct m0_dtm_update_type test_utype = {
85  .updtt_id = 0,
86  .updtt_name = "test"
87 };
88 
89 static const struct m0_dtm_update_ops test_ops = {
90  .updo_redo = &undo_redo,
91  .updo_undo = &undo_redo,
92  .updo_type = &test_utype
93 };
94 
95 static int update_init(struct m0_dtm_history *history, uint8_t id,
96  struct m0_dtm_update *update)
97 {
98  M0_ASSERT(id == 0);
99  update->upd_ops = &test_ops;
100  return 0;
101 }
102 
103 static void test_persistent(struct m0_dtm_history *history)
104 {}
105 
106 static const struct m0_dtm_op_ops op_ops = {
107  .doo_ready = noop,
108  .doo_late = never,
109  .doo_miser = never
110 };
111 
112 static const struct m0_dtm_history_ops hops;
113 
114 static int hfind(struct m0_dtm *dtm, const struct m0_dtm_history_type *ht,
115  const struct m0_uint128 *id, struct m0_dtm_history **out)
116 {
117  unsigned idx = id->u_lo + dtm->d_id.u_lo * UPDATE_NR;
118  M0_UT_ASSERT(id->u_hi == 0 && IS_IN_ARRAY(idx, history0));
119  *out = &history0[idx];
120  if ((*out)->h_hi.hi_ups.t_magic == 0) {
121  m0_dtm_history_init(*out, dtm);
122  (*out)->h_ops = &hops;
123  }
124  return 0;
125 }
126 
127 static const struct m0_dtm_history_type_ops htype_ops = {
128  .hito_find = hfind
129 };
130 
131 static const struct m0_dtm_history_type htype = {
132  .hit_id = 1,
133  .hit_rem_id = 1,
134  .hit_name = "test-histories",
135  .hit_ops = &htype_ops
136 };
137 
138 static const struct m0_uint128 *hid(const struct m0_dtm_history *history)
139 {
140  int idx = history - history0;
141 
143  id0[idx].u_hi = 0;
144  id0[idx].u_lo = idx % UPDATE_NR;
145  return &id0[idx];
146 }
147 
148 static const struct m0_dtm_history_ops hops = {
149  .hio_type = &htype,
150  .hio_id = &hid,
151  .hio_persistent = &test_persistent,
152  .hio_update = &update_init
153 };
154 
155 static void init0(void)
156 {
157  int i;
158  int j;
159  struct m0_tl uu;
160 
167  M0_SET0(&history0);
169  for (i = 0; i < REM_NR; ++i)
170  history_remote[i] = &history0[(i + 1) * UPDATE_NR];
171  m0_dtm_init(&dtm_local, &M0_UINT128(0, 0));
175  for (i = 0; i < ARRAY_SIZE(dtm_remote); ++i) {
176  m0_dtm_init(&dtm_remote[i], &M0_UINT128(1, i + 1));
183  &dtm_remote[i].d_id, &dtm_local, NULL);
186  }
187  for (i = 0; i < UPDATE_NR; ++i) {
188  struct m0_dtm_history *history = &history_local[i];
189 
190  m0_dtm_history_init(history, &dtm_local);
191  history->h_hi.hi_ver = 1;
192  history->h_hi.hi_flags |= M0_DHF_OWNED;
193  history->h_ops = &hops;
194  history->h_rem =
196  }
197  for (i = 0; i < OPER_NR; ++i) {
202  }
203  for (i = 0; i < REM_NR; ++i) {
205  for (j = 0; j < OPER_NR; ++j) {
206  ode[i][j].od_updates.ou_update = udescr[i][j];
211  &dtm_remote[i], &uu);
213  }
214  }
215 }
216 
217 static void fini0(void)
218 {
219  int i;
220  int j;
221 
222  for (i = 0; i < REM_NR; ++i) {
223  for (j = 0; j < OPER_NR; ++j)
226  }
227  for (i = 0; i < OPER_NR; ++i)
229 
230  for (i = 0; i < UPDATE_NR; ++i)
232 
233  for (i = 0; i < ARRAY_SIZE(dtm_remote); ++i) {
242  }
247 }
248 
249 static void init1(void)
250 {
251  int result;
252 
253  init0();
254  result = m0_dtm_dtx_init(&dx, &M0_UINT128(0, 0), &dtm_local, REM_NR);
255  M0_UT_ASSERT(result == 0);
256 }
257 
258 static void fini1(void)
259 {
261  fini0();
262 }
263 
264 static void init2(void)
265 {
266  int i;
267  int j;
268 
269  init1();
270  for (i = 0; i < OPER_NR; ++i) {
272  for (j = 0; j < UPDATE_NR; ++j) {
275  &history_local[j], &oper_local[i],
277  M0_DUR_INC, 2 + i, 1 + i));
278  }
283  for (j = 0; j < REM_NR; ++j)
285  &remote_local[j].lre_rem);
286  M0_UT_ASSERT(op_state(&oper_local[i].oprt_op,
288  }
290 }
291 
292 static void fini2(void)
293 {
294  fini1();
295 }
296 
297 static void init3(void)
298 {
299  int i;
300  int j;
301  int result;
302 
303  init2();
304  for (i = 0; i < OPER_NR; ++i) {
305  for (j = 0; j < REM_NR; ++j) {
306  struct m0_dtm_oper *oper = &oper_remote[j][i];
307  struct m0_dtm_oper_descr *o = &ode[j][i];
308 
309  o->od_updates.ou_nr = UPDATE_NR + 2 * REM_NR;
311  &remote_local[j].lre_rem, o);
314  result = m0_dtm_oper_build(oper, &uu, o);
315  M0_UT_ASSERT(result == 0);
316  }
317  }
318 }
319 
320 static void fini3(void)
321 {
322  fini2();
323 };
324 
325 struct m0_dtm_dtx_party {
326  /* pa_dtx is unused currently but reserved for future use */
327  struct m0_dtm_dtx *pa_dtx;
328  struct m0_dtm_controlh pa_ch;
329 };
330 
331 static void init4(void)
332 {
333  int i;
334  int j;
335  bool progress;
336  int done = 0;
337 
338  init3();
339  do {
340  progress = false;
341  for (i = 0; i < REM_NR; ++i) {
342  for (j = 0; j < OPER_NR; ++j) {
343  struct m0_dtm_oper *oper;
344 
345  oper = &oper_remote[i][j];
346  if (op_state(&oper->oprt_op, M0_DOS_LIMBO)) {
347  m0_dtm_oper_close(oper);
348  progress = true;
349  }
350  if (op_state(&oper->oprt_op, M0_DOS_PREPARE)) {
351  m0_dtm_oper_prepared(oper, NULL);
352  progress = true;
353  }
354  if (op_state(&oper->oprt_op, M0_DOS_INPROGRESS)) {
355  m0_dtm_oper_done(oper, NULL);
356  m0_dtm_oper_done(oper,
357  &remote_remote[i].lre_rem);
358  progress = true;
359  done++;
360  }
361  }
362  }
363  } while (progress && done < OPER_NR);
364  for (i = 0; i < REM_NR; ++i) {
365  for (j = 0; j < OPER_NR; ++j) {
366  struct m0_dtm_oper *oper = &oper_remote[i][j];
367  struct m0_dtm_oper *loper = &oper_local[j];
368 
371  m0_dtm_reply_pack(oper, &ode[i][j], &ode_reply[i][j]);
372  m0_dtm_reply_unpack(loper, &ode_reply[i][j]);
373  m0_dtm_oper_done(loper, &remote_local[i].lre_rem);
374  }
375  }
377  M0_DOS_VOLATILE)));
378 /*
379  for (i = 0; i < OPER_NR; ++i) {
380  M0_LOG(M0_FATAL, "l%i", i);
381  oper_print(&oper_local[i]);
382  }
383  for (i = 0; i < REM_NR; ++i) {
384  M0_LOG(M0_FATAL, "d%i", i);
385  history_print(&dx.dt_party[i].pa_ch.ch_history);
386  }
387 */
388 }
389 
390 static void fini4(void)
391 {
392  fini3();
393 }
394 
395 static void init5(void)
396 {
397  int i;
398 
399  init4();
400  for (i = 0; i < REM_NR; ++i) {
402  m0_dtm_history_persistent(&dtm_remote[i].d_fol.fo_ch.ch_history,
403  ~0ULL);
404  M0_UT_ASSERT(dx.dt_nr_fixed == i + 1);
405  }
407 }
408 
409 static void fini5(void)
410 {
411  fini4();
412 }
413 
414 static void dtm_setup(void)
415 {
416  init0();
417  fini0();
418 }
419 
420 static void dtx_setup(void)
421 {
422  init1();
423  fini1();
424 }
425 
426 static void dtx_populate(void)
427 {
428  init2();
429  fini2();
430 }
431 
432 static void dtx_pack(void)
433 {
434  init3();
435  fini3();
436 }
437 
438 static void dtx_reply(void)
439 {
440  init4();
441  fini4();
442 }
443 
444 static void dtx_fix(void)
445 {
446  init5();
447  fini5();
448 }
449 
451  .ts_name = "dtm-dtx-ut",
452  .ts_tests = {
453  { "dtm-setup", dtm_setup },
454  { "dtx-setup", dtx_setup },
455  { "dtx-populate", dtx_populate },
456  { "dtx-pack", dtx_pack },
457  { "dtx-reply", dtx_reply },
458  { "dtx-fix", dtx_fix },
459  { NULL, NULL }
460  }
461 };
462 M0_EXPORTED(dtm_dtx_ut);
463 
464 #undef M0_TRACE_SUBSYSTEM
465 
468 /*
469  * Local variables:
470  * c-indentation-style: "K&R"
471  * c-basic-offset: 8
472  * tab-width: 8
473  * fill-column: 80
474  * scroll-step: 1
475  * End:
476  */
477 /*
478  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
479  */
#define M0_DTM_UPDATE_DATA(label, rule, ver, orig_ver)
Definition: update.h:102
uint64_t id
Definition: cob.h:2380
static void fini4(void)
Definition: dtx.c:390
static void dtx_pack(void)
Definition: dtx.c:432
static const struct m0_dtm_op_ops op_ops
Definition: dtx.c:106
M0_INTERNAL void m0_dtm_fini(struct m0_dtm *dtm)
Definition: dtm.c:54
#define NULL
Definition: misc.h:38
static int update_init(struct m0_dtm_history *history, uint8_t id, struct m0_dtm_update *update)
Definition: dtx.c:95
M0_INTERNAL const struct m0_dtm_history_type m0_dtm_dtx_htype
Definition: dtx.c:125
static struct m0_dtm_oper_descr ode[REM_NR][OPER_NR]
Definition: dtx.c:68
static void init0(void)
Definition: dtx.c:155
uint64_t hi_flags
Definition: nucleus.h:65
struct m0_dtm_remote * h_rem
Definition: history.h:59
static void dtx_reply(void)
Definition: dtx.c:438
Definition: dtx.c:45
static void noop(struct m0_dtm_op *op)
Definition: dtx.c:71
M0_INTERNAL void m0_dtm_oper_init(struct m0_dtm_oper *oper, struct m0_dtm *dtm, struct m0_tl *uu)
Definition: operation.c:44
uint8_t hit_id
Definition: history.h:88
M0_INTERNAL const struct m0_dtm_history_type m0_dtm_dtx_srv_htype
Definition: dtx.c:199
struct m0_dtm_op oprt_op
Definition: operation.h:48
static struct m0_dtm_fol fol_remote[REM_NR]
Definition: dtx.c:64
M0_INTERNAL void m0_dtm_oper_prepared(const struct m0_dtm_oper *oper, const struct m0_dtm_remote *rem)
Definition: operation.c:122
static void fini3(void)
Definition: dtx.c:320
static struct m0_dtm dtm_local
Definition: dtx.c:49
static struct m0_dtm_update control_local[OPER_NR][2 *DTM_NR]
Definition: dtx.c:55
struct m0_dtm_hi h_hi
Definition: history.h:56
M0_INTERNAL void m0_dtm_oper_done(const struct m0_dtm_oper *oper, const struct m0_dtm_remote *rem)
Definition: operation.c:144
M0_INTERNAL int m0_dtm_oper_build(struct m0_dtm_oper *oper, struct m0_tl *uu, const struct m0_dtm_oper_descr *ode)
Definition: operation.c:183
static struct m0_dtm_oper oper_remote[REM_NR][OPER_NR]
Definition: dtx.c:59
static struct m0_dtm dtm_remote[REM_NR]
Definition: dtx.c:50
#define M0_SET0(obj)
Definition: misc.h:64
Definition: ut.h:77
M0_INTERNAL void dtm_lock(struct m0_dtm *dtm)
Definition: dtm.c:159
static void dtx_setup(void)
Definition: dtx.c:420
M0_INTERNAL void m0_dtm_history_fini(struct m0_dtm_history *history)
Definition: history.c:63
const struct m0_dtm_update_ops * upd_ops
Definition: update.h:74
struct m0_dtm_dtx * pa_dtx
Definition: dtx.c:44
static struct m0_uint128 id0[UPDATE_NR *DTM_NR]
Definition: dtx.c:57
static struct m0_dtm_history history0[UPDATE_NR *DTM_NR]
Definition: dtx.c:54
op
Definition: libdemo.c:64
static void never(struct m0_dtm_op *op)
Definition: dtx.c:74
static void fini1(void)
Definition: dtx.c:258
M0_INTERNAL void m0_dtm_update_link(struct m0_tl *list, struct m0_dtm_update *update, uint32_t nr)
Definition: update.c:221
M0_INTERNAL void m0_dtm_history_type_register(struct m0_dtm *dtm, const struct m0_dtm_history_type *ht)
Definition: history.c:216
static void init4(void)
Definition: dtx.c:331
int i
Definition: dir.c:1033
static void init2(void)
Definition: dtx.c:264
const struct m0_dtm_op_ops * op_ops
Definition: nucleus.h:108
M0_INTERNAL void m0_dtm_history_persistent(struct m0_dtm_history *history, m0_dtm_ver_t upto)
Definition: history.c:107
static const struct m0_dtm_history_ops hops
Definition: dtx.c:112
uint32_t dt_nr
Definition: dtx.h:47
Definition: dtx.c:42
Definition: dtx.h:44
Definition: dtx.c:46
M0_INTERNAL void m0_dtm_oper_pack(struct m0_dtm_oper *oper, const struct m0_dtm_remote *rem, struct m0_dtm_oper_descr *ode)
Definition: operation.c:161
#define M0_ASSERT(cond)
static void fini5(void)
Definition: dtx.c:409
static const struct m0_dtm_history_type_ops htype_ops
Definition: dtx.c:127
struct m0_uint128 d_id
Definition: dtm.h:540
Definition: dtx.c:43
Definition: tlist.h:251
Definition: dtx.c:44
struct m0_dtm_update_descr * ou_update
Definition: operation.h:62
static int hfind(struct m0_dtm *dtm, const struct m0_dtm_history_type *ht, const struct m0_uint128 *id, struct m0_dtm_history **out)
Definition: dtx.c:114
M0_INTERNAL void m0_dtm_fol_init(struct m0_dtm_fol *fol, struct m0_dtm *dtm)
Definition: fol.c:46
struct m0_ut_suite dtm_dtx_ut
Definition: dtx.c:450
Definition: fol.h:44
uint64_t u_hi
Definition: types.h:36
M0_INTERNAL void m0_dtm_dtx_close(struct m0_dtm_dtx *dtx)
Definition: dtx.c:90
struct m0_dtm_controlh pa_ch
Definition: dtx.c:45
M0_INTERNAL int m0_dtm_dtx_init(struct m0_dtm_dtx *dtx, const struct m0_uint128 *id, struct m0_dtm *dtm, uint32_t nr_max)
Definition: dtx.c:57
static struct m0_dtm_update control_remote[REM_NR][OPER_NR][1]
Definition: dtx.c:56
static void init3(void)
Definition: dtx.c:297
M0_INTERNAL void m0_dtm_history_type_deregister(struct m0_dtm *dtm, const struct m0_dtm_history_type *ht)
Definition: history.c:225
static struct m0_dtm_history * history_local
Definition: dtx.c:62
void(* doo_ready)(struct m0_dtm_op *op)
Definition: nucleus.h:113
static void fini0(void)
Definition: dtx.c:217
static void dtx_populate(void)
Definition: dtx.c:426
static struct m0_dtm_update_descr udescr[REM_NR][OPER_NR][FAN_NR]
Definition: dtx.c:66
static const struct m0_dtm_update_ops test_ops
Definition: dtx.c:89
#define m0_forall(var, nr,...)
Definition: misc.h:112
M0_INTERNAL void m0_dtm_init(struct m0_dtm *dtm, struct m0_uint128 *id)
Definition: dtm.c:41
M0_INTERNAL const struct m0_dtm_history_type m0_dtm_fol_remote_htype
Definition: fol.c:173
const char * ts_name
Definition: ut.h:99
static void dtm_setup(void)
Definition: dtx.c:414
M0_INTERNAL void m0_dtm_reply_unpack(struct m0_dtm_oper *oper, const struct m0_dtm_oper_descr *reply)
Definition: operation.c:236
M0_INTERNAL void m0_dtm_update_init(struct m0_dtm_update *update, struct m0_dtm_history *history, struct m0_dtm_oper *oper, const struct m0_dtm_update_data *data)
Definition: update.c:47
uint32_t dt_nr_fixed
Definition: dtx.h:49
static void init5(void)
Definition: dtx.c:395
static struct m0_dtm_dtx dx
Definition: dtx.c:53
static struct m0_dtm_oper_descr ode_reply[REM_NR][OPER_NR]
Definition: dtx.c:69
static const struct m0_dtm_update_type test_utype
Definition: dtx.c:84
int(* hito_find)(struct m0_dtm *dtm, const struct m0_dtm_history_type *ht, const struct m0_uint128 *id, struct m0_dtm_history **out)
Definition: history.h:95
const struct m0_dtm_history_type * hio_type
Definition: history.h:79
m0_dtm_ver_t hi_ver
Definition: nucleus.h:66
static struct m0_dtm_update_descr ureply[REM_NR][OPER_NR][FAN_NR]
Definition: dtx.c:67
static void test_persistent(struct m0_dtm_history *history)
Definition: dtx.c:103
static void dtx_fix(void)
Definition: dtx.c:444
M0_INTERNAL void m0_dtm_oper_close(struct m0_dtm_oper *oper)
Definition: operation.c:83
M0_INTERNAL bool op_state(const struct m0_dtm_op *op, enum m0_dtm_state state)
Definition: nucleus.c:511
M0_INTERNAL void dtm_unlock(struct m0_dtm *dtm)
Definition: dtm.c:164
#define IS_IN_ARRAY(idx, array)
Definition: misc.h:311
static struct m0_dtm_history * history_remote[REM_NR]
Definition: dtx.c:63
static const struct m0_dtm_history_type htype
Definition: dtx.c:131
M0_INTERNAL void m0_dtm_history_init(struct m0_dtm_history *history, struct m0_dtm *dtm)
Definition: history.c:51
M0_INTERNAL void m0_dtm_local_remote_fini(struct m0_dtm_local_remote *lre)
Definition: remote.c:276
#define M0_UINT128(hi, lo)
Definition: types.h:40
static struct m0_dtm_local_remote remote_remote[REM_NR]
Definition: dtx.c:52
Definition: dtm.h:529
M0_INTERNAL void m0_dtm_oper_fini(struct m0_dtm_oper *oper)
Definition: operation.c:58
static struct m0_tl uu
Definition: dtx.c:65
static unsigned done
Definition: storage.c:91
M0_INTERNAL void m0_dtm_update_list_init(struct m0_tl *list)
Definition: update.c:177
static struct m0_dtm_update update_local[OPER_NR][UPDATE_NR]
Definition: dtx.c:60
uint8_t updtt_id
Definition: update.h:91
#define out(...)
Definition: gen.c:41
static void init1(void)
Definition: dtx.c:249
M0_INTERNAL void m0_dtm_local_remote_init(struct m0_dtm_local_remote *lre, struct m0_uint128 *id, struct m0_dtm *local, struct m0_reqh *reqh)
Definition: remote.c:266
struct m0_dtm_remote lre_rem
Definition: remote.h:104
uint64_t u_lo
Definition: types.h:37
struct m0_dtm_oper_updates od_updates
Definition: operation.h:66
static const struct m0_uint128 * hid(const struct m0_dtm_history *history)
Definition: dtx.c:138
static int undo_redo(struct m0_dtm_update *updt)
Definition: dtx.c:79
M0_INTERNAL void m0_dtm_dtx_fini(struct m0_dtm_dtx *dtx)
Definition: dtx.c:69
static struct m0_dtm_oper oper_local[OPER_NR]
Definition: dtx.c:58
static struct m0_dtm_local_remote remote_local[REM_NR]
Definition: dtx.c:51
M0_INTERNAL void m0_dtm_dtx_add(struct m0_dtm_dtx *dtx, struct m0_dtm_oper *oper)
Definition: dtx.c:80
static void fini2(void)
Definition: dtx.c:292
#define ARRAY_SIZE(a)
Definition: misc.h:45
M0_INTERNAL void m0_dtm_fol_fini(struct m0_dtm_fol *fol)
Definition: fol.c:56
#define M0_UT_ASSERT(a)
Definition: ut.h:46
M0_INTERNAL void m0_dtm_reply_pack(const struct m0_dtm_oper *oper, const struct m0_dtm_oper_descr *request, struct m0_dtm_oper_descr *reply)
Definition: operation.c:209
static struct m0_dtm_update update_remote[REM_NR][OPER_NR][FAN_NR]
Definition: dtx.c:61
const struct m0_dtm_history_ops * h_ops
Definition: history.h:65
#define M0_IMPOSSIBLE(fmt,...)
int(* updo_redo)(struct m0_dtm_update *updt)
Definition: update.h:84