Motr  M0
nucleus.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/bob.h"
32 #include "lib/misc.h" /* M0_IN */
33 #include "lib/arith.h" /* min_check, max_check */
34 #include "lib/tlist.h"
35 #include "lib/errno.h"
36 #include "lib/assert.h"
37 #include "lib/trace.h"
38 
39 #include "motr/magic.h"
40 #include "dtm/nucleus.h"
41 #include "dtm/dtm_internal.h"
42 
43 M0_TL_DESCR_DEFINE(hi, "nucleus hi updates", M0_INTERNAL, struct m0_dtm_up,
44  up_hi_linkage, up_magix,
46 M0_TL_DEFINE(hi, M0_INTERNAL, struct m0_dtm_up);
47 
48 M0_TL_DESCR_DEFINE(op, "nucleus operation updates", M0_INTERNAL, struct m0_dtm_up,
49  up_op_linkage, up_magix,
51 M0_TL_DEFINE(op, M0_INTERNAL, struct m0_dtm_up);
52 
53 const static struct m0_bob_type hi_bob;
54 const static struct m0_bob_type op_bob;
55 static struct m0_bob_type up_bob;
56 
57 M0_BOB_DEFINE(static, &hi_bob, m0_dtm_hi);
58 M0_BOB_DEFINE(static, &up_bob, m0_dtm_up);
59 M0_BOB_DEFINE(static, &op_bob, m0_dtm_op);
60 
61 static void advance_hi(struct m0_dtm_hi *hi);
62 static void advance_op(struct m0_dtm_op *op);
63 static void up_ready (struct m0_dtm_up *up);
64 static void up_insert (struct m0_dtm_up *up);
65 static int op_cmp (const struct m0_dtm_op *op);
66 static void up_del (struct m0_dtm_up *up);
67 static int up_cmp (const struct m0_dtm_up *up, m0_dtm_ver_t hver);
68 static void up_fini (struct m0_dtm_up *up);
69 
71  LATE = -1,
72  READY = 0,
73  EARLY = +1,
75 };
76 
77 M0_INTERNAL void m0_dtm_op_init(struct m0_dtm_op *op, struct m0_dtm_nu *nu)
78 {
79  m0_dtm_op_bob_init(op);
80  op->op_nu = nu;
81  op_tlist_init(&op->op_ups);
82 }
83 
84 M0_INTERNAL void m0_dtm_op_close(const struct m0_dtm_op *op)
85 {
87 
88  up_for(op, up) {
89  M0_PRE(up->up_state == M0_DOS_LIMBO);
90  hi_tlist_add(&up->up_hi->hi_ups, up);
91  up->up_state = M0_DOS_FUTURE;
92  } up_endfor;
93  advance_try(op);
95 }
96 
97 M0_INTERNAL void m0_dtm_op_prepared(const struct m0_dtm_op *op)
98 {
100 
101  up_for(op, up) {
102  up_prepared(up);
103  } up_endfor;
104  advance_try(op);
106 }
107 
108 M0_INTERNAL void m0_dtm_op_done(const struct m0_dtm_op *op)
109 {
111 
112  up_for(op, up) {
113  M0_PRE(up->up_state == M0_DOS_INPROGRESS);
114  up->up_state = M0_DOS_VOLATILE;
115  } up_endfor;
117 }
118 
119 static void op_del(struct m0_dtm_op *op)
120 {
121  up_for(op, up) {
122  M0_PRE(M0_IN(up->up_state, (M0_DOS_FUTURE, M0_DOS_LIMBO)));
123  up_del(up);
124  up->up_state = M0_DOS_LIMBO;
125  } up_endfor;
126 }
127 
128 M0_INTERNAL void m0_dtm_op_del(struct m0_dtm_op *op)
129 {
131  op_del(op);
133 }
134 
135 M0_INTERNAL void m0_dtm_op_fini(struct m0_dtm_op *op)
136 {
138  up_for(op, up) {
139  up_fini(up);
140  } up_endfor;
141  op_tlist_fini(&op->op_ups);
142  m0_dtm_op_bob_fini(op);
143 }
144 
145 M0_INTERNAL void advance_try(const struct m0_dtm_op *op)
146 {
147  up_for(op, up) {
148  advance_hi(up->up_hi);
149  } up_endfor;
150 }
151 
152 static void advance_hi(struct m0_dtm_hi *hi)
153 {
154  struct m0_dtm_up *last = NULL;
155  hi_for(hi, up) {
156  if (up->up_state > M0_DOS_FUTURE)
157  break;
158  last = up;
159  } hi_endfor;
160  while (last != NULL) {
161  /* because advance_op() can call op_del(). */
162  struct m0_dtm_up *prev = hi_tlist_prev(&hi->hi_ups, last);
163 
164  M0_ASSERT(last->up_state == M0_DOS_FUTURE);
165  advance_op(last->up_op);
166  last = prev;
167  }
168 }
169 
170 static void advance_op(struct m0_dtm_op *op)
171 {
172  const struct m0_dtm_op_ops *op_ops = op->op_ops;
173 
175 
176  if (m0_tl_forall(op, up, &op->op_ups,
177  !(up->up_hi->hi_flags & M0_DHF_BUSY))) {
178  switch (op_cmp(op)) {
179  case READY:
180  up_for(op, up) {
181  up_ready(up);
182  up->up_state = M0_DOS_PREPARE;
183  up->up_hi->hi_flags |= M0_DHF_BUSY;
184  } up_endfor;
185  op_ops->doo_ready(op);
186  break;
187  case EARLY:
188  break;
189  case LATE:
190  op_del(op);
191  op_ops->doo_late(op);
192  break;
193  case MISER:
194  op_del(op);
195  op_ops->doo_miser(op);
196  break;
197  default:
198  M0_IMPOSSIBLE("Wrong op_cmp().");
199  }
200  }
201 }
202 
203 static void up_ready(struct m0_dtm_up *up)
204 {
205  struct m0_dtm_hi *hi = up->up_hi;
206 
207  if (up->up_hi->hi_flags & M0_DHF_OWNED) {
208  if (up->up_orig_ver == 0)
209  up->up_orig_ver = hi->hi_ver;
210  M0_ASSERT(up->up_orig_ver == hi->hi_ver);
211  if (up->up_ver == 0) {
212  if (up->up_rule == M0_DUR_NOT)
213  up->up_ver = up->up_orig_ver;
214  else
215  up->up_ver = up->up_orig_ver + 1;
216  }
217  }
218  hi_tlist_del(up);
219  up_insert(up);
220 }
221 
222 M0_INTERNAL void up_prepared(struct m0_dtm_up *up)
223 {
224  struct m0_dtm_hi *hi = up->up_hi;
225 
227  M0_ASSERT(hi->hi_flags & M0_DHF_BUSY);
228  M0_ASSERT(ergo(hi->hi_flags & M0_DHF_OWNED, up->up_ver != 0));
229  if (up->up_ver != 0)
230  hi->hi_ver = up->up_ver;
231  hi->hi_flags &= ~M0_DHF_BUSY;
233 }
234 
235 static int op_cmp(const struct m0_dtm_op *op)
236 {
237  enum m0_dtm_ver_cmp min = EARLY;
238  enum m0_dtm_ver_cmp max = LATE;
239 
240  /*
241  * Invariants can be violated at the entry: operation can be late,
242  * misordered, etc.
243  */
244 
245  /*
246  * max ^
247  * |
248  * EARLY|MISER EARLY EARLY
249  * READY|MISER READY X
250  * LATE |LATE X X
251  * -----+-----+-----+--------> min
252  * LATE READY EARLY
253  */
254  up_for(op, up) {
255  enum m0_dtm_ver_cmp check;
256 
257  check = up_cmp(up, up->up_hi->hi_ver);
258  min = min_check(min, check);
259  max = max_check(max, check);
260  } up_endfor;
261  return
262  min == LATE && max == LATE ? LATE :
263  min == READY && max == READY ? READY :
264  min >= READY && max == EARLY ? EARLY : MISER;
265 }
266 
267 
268 M0_INTERNAL void m0_dtm_hi_init(struct m0_dtm_hi *hi, struct m0_dtm_nu *nu)
269 {
270  M0_SET0(hi);
271  m0_dtm_hi_bob_init(hi);
272  hi->hi_nu = nu;
273  hi->hi_ver = 1;
274  hi_tlist_init(&hi->hi_ups);
275 }
276 
277 M0_INTERNAL void m0_dtm_hi_fini(struct m0_dtm_hi *hi)
278 {
279  hi_for(hi, up) {
280  up_fini(up);
281  } hi_endfor;
282  hi_tlist_fini(&hi->hi_ups);
283  m0_dtm_hi_bob_fini(hi);
284 }
285 
286 M0_INTERNAL void m0_dtm_up_init(struct m0_dtm_up *up, struct m0_dtm_hi *hi,
287  struct m0_dtm_op *op, enum m0_dtm_up_rule rule,
288  m0_dtm_ver_t ver, m0_dtm_ver_t orig_ver)
289 {
293 
294  m0_dtm_up_bob_init(up);
295  op_tlink_init_at(up, &op->op_ups);
296  hi_tlink_init(up);
297  up->up_hi = hi;
298  up->up_op = op;
299  up->up_rule = rule;
300  up->up_ver = ver;
301  up->up_orig_ver = orig_ver;
305 }
306 
307 static void up_fini(struct m0_dtm_up *up)
308 {
309  if (hi_tlink_is_in(up))
310  hi_tlink_del_fini(up);
311  op_tlink_del_fini(up);
312  m0_dtm_up_bob_fini(up);
313 }
314 
315 static void up_insert(struct m0_dtm_up *up)
316 {
317  struct m0_dtm_hi *hi = up->up_hi;
318 
319  hi_for(hi, scan) {
320  if (scan->up_state > M0_DOS_FUTURE) {
321  hi_tlist_add_before(scan, up);
322  return;
323  }
324  } hi_endfor;
325  hi_tlist_add_tail(&hi->hi_ups, up);
326 }
327 
328 static void up_del(struct m0_dtm_up *up)
329 {
332 
333  if (hi_tlink_is_in(up))
334  hi_tlink_del_fini(up);
335 }
336 
337 static int up_cmp(const struct m0_dtm_up *up, m0_dtm_ver_t hver)
338 {
339  m0_dtm_ver_t uver = up->up_ver;
340  /*
341  * Possible invariant violations on entry: the update is not in the
342  * history, even when the operation is not in LIMBO.
343  */
344  M0_PRE(hver != 0);
345 
346  if (uver == 0)
347  return READY;
348  if (up->up_orig_ver != 0)
349  return M0_3WAY(up->up_orig_ver, hver);
350 
351  switch (up->up_rule) {
352  case M0_DUR_INC:
353  return M0_3WAY(uver, hver + 1);
354  case M0_DUR_SET:
355  return uver <= hver ? LATE : READY;
356  case M0_DUR_NOT:
357  return M0_3WAY(uver, hver);
358  case M0_DUR_APP:
359  default:
360  M0_IMPOSSIBLE("Impossible rule.");
361  return 0;
362  }
363 }
364 
365 M0_INTERNAL void m0_dtm_nu_init(struct m0_dtm_nu *nu)
366 {
367  m0_mutex_init(&nu->nu_lock);
368 }
369 
370 M0_INTERNAL void m0_dtm_nu_fini(struct m0_dtm_nu *nu)
371 {
372  m0_mutex_fini(&nu->nu_lock);
373 }
374 
375 M0_INTERNAL struct m0_dtm_up *m0_dtm_up_prior(struct m0_dtm_up *up)
376 {
377  return hi_tlist_next(&up->up_hi->hi_ups, up);
378 }
379 
380 M0_INTERNAL struct m0_dtm_up *m0_dtm_up_later(struct m0_dtm_up *up)
381 {
382  return hi_tlist_prev(&up->up_hi->hi_ups, up);
383 }
384 
385 M0_INTERNAL struct m0_dtm_up *hi_latest(struct m0_dtm_hi *hi)
386 {
387  return hi_tlist_head(&hi->hi_ups);
388 }
389 
390 M0_INTERNAL struct m0_dtm_up *hi_earliest(struct m0_dtm_hi *hi)
391 {
392  return hi_tlist_tail(&hi->hi_ups);
393 }
394 
395 
396 M0_INTERNAL struct m0_dtm_up *hi_find(struct m0_dtm_hi *hi, m0_dtm_ver_t ver)
397 {
398  hi_for(hi, up) {
399  if (up->up_ver <= ver)
400  return up;
401  } hi_endfor;
402  return NULL;
403 }
404 
405 M0_INTERNAL m0_dtm_ver_t up_ver(const struct m0_dtm_up *up)
406 {
407  return up != NULL ? up->up_ver : 0;
408 }
409 
410 M0_INTERNAL bool up_is_earlier(struct m0_dtm_up *up0, struct m0_dtm_up *up1)
411 {
412  M0_PRE(up0 != NULL);
413  M0_PRE(up1 != NULL);
414  M0_PRE(up0->up_hi == up1->up_hi);
415 
416  if (up0->up_ver < up1->up_ver)
417  return true;
418  while (1) {
419  up0 = m0_dtm_up_later(up0);
420  if (up0 == NULL)
421  return false;
422  if (up1 == up0)
423  return true;
424  }
425 }
426 
427 
428 static bool op_is_locked(const struct m0_dtm_op *op)
429 {
430  return m0_mutex_is_locked(&op->op_nu->nu_lock);
431 }
432 
433 static bool up_pair_invariant(const struct m0_dtm_up *up,
434  const struct m0_dtm_up *next);
435 
436 M0_INTERNAL bool m0_dtm_hi_invariant(const struct m0_dtm_hi *hi)
437 {
438  unsigned prepare = 0;
439  return
440  _0C(m0_dtm_hi_bob_check(hi)) &&
441  m0_tl_forall(hi, up, &hi->hi_ups,
442  m0_dtm_up_invariant(up) &&
443  up_pair_invariant(up, hi_tlist_next(&hi->hi_ups, up)) &&
444  ergo(up->up_state == M0_DOS_PREPARE, ++prepare + 1)) &&
445  prepare == !!(hi->hi_flags & M0_DHF_BUSY);
446 }
447 
448 M0_INTERNAL bool m0_dtm_up_invariant(const struct m0_dtm_up *up)
449 {
450  return
451  _0C(m0_dtm_up_bob_check(up)) &&
452  _0C(0 <= up->up_state && up->up_state < M0_DOS_NR) &&
453  _0C(0 <= up->up_rule && up->up_rule < M0_DUR_NR) &&
454  _0C(up->up_hi != NULL && up->up_op != NULL) &&
455  _0C(up->up_ver >= up->up_orig_ver) &&
456  _0C(ergo(up->up_ver == up->up_orig_ver,
457  up->up_ver == 0 || up->up_rule == M0_DUR_NOT)) &&
458  _0C(ergo(up->up_ver != 0,
459  ergo(up->up_rule == M0_DUR_INC,
460  up->up_ver == up->up_orig_ver + 1))) &&
461  _0C(ergo(up->up_rule == M0_DUR_NOT,
462  up->up_ver == up->up_orig_ver)) &&
464  up->up_orig_ver != 0)) &&
465  _0C(hi_tlist_contains(&up->up_hi->hi_ups, up) ==
466  (up->up_state != M0_DOS_LIMBO)) &&
467  _0C(op_tlist_contains(&up->up_op->op_ups, up));
468 }
469 
470 M0_INTERNAL bool m0_dtm_op_invariant(const struct m0_dtm_op *op)
471 {
472  return
473  _0C(op_is_locked(op)) &&
474  _0C(m0_dtm_op_bob_check(op)) &&
475  m0_tl_forall(op, up, &op->op_ups,
476  m0_dtm_up_invariant(up) && _0C(up->up_op == op) &&
477  _0C(up->up_hi->hi_nu == op->op_nu) &&
478  m0_dtm_hi_invariant(up->up_hi)) &&
479  _0C(({
480  enum m0_dtm_state min = M0_DOS_NR;
481  enum m0_dtm_state max = 0;
482 
483  up_for(op, up) {
484  min = min_check(min, up->up_state);
485  max = max_check(max, up->up_state);
486  } up_endfor;
487  op_tlist_is_empty(&op->op_ups) ||
488  (min == max) || ((min >= M0_DOS_PREPARE) &&
489  (max < M0_DOS_STABLE));
490  })) &&
492  !m0_tl_forall(op, up, &op->op_ups,
493  up->up_rule == M0_DUR_NOT ||
494  up->up_ver == 0)));
495 }
496 
497 static bool up_pair_invariant(const struct m0_dtm_up *up,
498  const struct m0_dtm_up *earlier)
499 {
500  return earlier == NULL || up->up_state < M0_DOS_PREPARE ||
501  (_0C(up->up_state <= earlier->up_state) &&
502  _0C(ergo((up->up_hi->hi_flags & M0_DHF_OWNED) ||
504  up->up_orig_ver != 0 &&
505  up->up_ver != 0 &&
506  up->up_orig_ver >= earlier->up_ver)) &&
508  up->up_orig_ver == earlier->up_ver)));
509 }
510 
511 M0_INTERNAL bool op_state(const struct m0_dtm_op *op, enum m0_dtm_state state)
512 {
513  return m0_tl_forall(op, up, &op->op_ups, up->up_state == state);
514 }
515 
516 const static struct m0_bob_type hi_bob = {
517  .bt_name = "dtm history",
518  .bt_magix_offset = M0_MAGIX_OFFSET(struct m0_dtm_hi, hi_ups.t_magic),
519  .bt_magix = M0_DTM_HI_MAGIX
520 };
521 
522 const static struct m0_bob_type op_bob = {
523  .bt_name = "dtm operation",
524  .bt_magix_offset = M0_MAGIX_OFFSET(struct m0_dtm_op, op_ups.t_magic),
525  .bt_magix = M0_DTM_OP_MAGIX
526 };
527 
528 M0_INTERNAL void m0_dtm_nuclei_init(void)
529 {
530  M0_SET0(&up_bob);
531  m0_bob_type_tlist_init(&up_bob, &hi_tl);
532 }
533 
534 M0_INTERNAL void m0_dtm_nuclei_fini(void)
535 {
536 }
537 
538 M0_INTERNAL void nu_lock(struct m0_dtm_nu *nu)
539 {
540  m0_mutex_lock(&nu->nu_lock);
541 }
542 
543 M0_INTERNAL void nu_unlock(struct m0_dtm_nu *nu)
544 {
545  m0_mutex_unlock(&nu->nu_lock);
546 }
547 
548 M0_INTERNAL void up_print(const struct m0_dtm_up *up)
549 {
550  M0_LOG(M0_FATAL, "\tup: s: %3.3i r: %3.3i v: %7.7lu o: %7.7lu",
551  up->up_state, up->up_rule, (unsigned long)up->up_ver,
552  (unsigned long)up->up_orig_ver);
553 }
554 
555 M0_INTERNAL void op_print(const struct m0_dtm_op *op)
556 {
557  M0_LOG(M0_FATAL, "op");
558  up_for(op, up) {
559  up_print(up);
560  } up_endfor;
561 }
562 
563 M0_INTERNAL void hi_print(const struct m0_dtm_hi *hi)
564 {
565  M0_LOG(M0_FATAL, "hi: f: %3.3lx v: %7.7lu", (unsigned long)hi->hi_flags,
566  (unsigned long)hi->hi_ver);
567  hi_for(hi, up) {
568  up_print(up);
569  } hi_endfor;
570 }
571 
572 #undef M0_TRACE_SUBSYSTEM
573 
576 /*
577  * Local variables:
578  * c-indentation-style: "K&R"
579  * c-basic-offset: 8
580  * tab-width: 8
581  * fill-column: 80
582  * scroll-step: 1
583  * End:
584  */
585 /*
586  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
587  */
M0_INTERNAL void m0_dtm_op_init(struct m0_dtm_op *op, struct m0_dtm_nu *nu)
Definition: nucleus.c:77
static void up_ready(struct m0_dtm_up *up)
Definition: nucleus.c:203
M0_INTERNAL struct m0_dtm_up * m0_dtm_up_later(struct m0_dtm_up *up)
Definition: nucleus.c:380
#define M0_PRE(cond)
static const struct m0_dtm_op_ops op_ops
Definition: nucleus.c:72
enum m0_dtm_state up_state
Definition: nucleus.h:94
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
M0_INTERNAL m0_dtm_ver_t up_ver(const struct m0_dtm_up *up)
Definition: nucleus.c:405
m0_dtm_ver_t up_orig_ver
Definition: nucleus.h:97
M0_INTERNAL void m0_dtm_op_done(const struct m0_dtm_op *op)
Definition: nucleus.c:108
m0_dtm_up_rule
Definition: nucleus.h:84
static const struct m0_bob_type op_bob
Definition: nucleus.c:54
#define NULL
Definition: misc.h:38
#define ergo(a, b)
Definition: misc.h:293
#define M0_3WAY(v0, v1)
Definition: arith.h:199
M0_INTERNAL bool m0_dtm_hi_invariant(const struct m0_dtm_hi *hi)
Definition: nucleus.c:436
static int prepare(struct m0_fom *fom)
Definition: trigger_fom.c:185
uint64_t hi_flags
Definition: nucleus.h:65
static void op(void)
Definition: nucleus.c:105
#define M0_LOG(level,...)
Definition: trace.h:167
#define min_check(a, b)
Definition: arith.h:88
M0_TL_DEFINE(hi, M0_INTERNAL, struct m0_dtm_up)
M0_INTERNAL bool m0_dtm_up_invariant(const struct m0_dtm_up *up)
Definition: nucleus.c:448
M0_INTERNAL void m0_dtm_nuclei_init(void)
Definition: nucleus.c:528
#define max_check(a, b)
Definition: arith.h:95
static void up_del(struct m0_dtm_up *up)
Definition: nucleus.c:328
M0_INTERNAL void up_prepared(struct m0_dtm_up *up)
Definition: nucleus.c:222
M0_INTERNAL struct m0_dtm_up * hi_find(struct m0_dtm_hi *hi, m0_dtm_ver_t ver)
Definition: nucleus.c:396
static void up_insert(struct m0_dtm_up *up)
Definition: nucleus.c:315
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
struct m0_dtm_hi * up_hi
Definition: nucleus.h:98
static bool op_is_locked(const struct m0_dtm_op *op)
Definition: nucleus.c:428
m0_dtm_ver_t up_ver
Definition: nucleus.h:96
const char * bt_name
Definition: bob.h:73
struct m0_dtm_op * up_op
Definition: nucleus.h:100
M0_INTERNAL void m0_dtm_op_del(struct m0_dtm_op *op)
Definition: nucleus.c:128
op
Definition: libdemo.c:64
static struct m0_bob_type up_bob
Definition: nucleus.c:55
M0_INTERNAL void up_print(const struct m0_dtm_up *up)
Definition: nucleus.c:548
struct m0_tl hi_ups
Definition: nucleus.h:68
static void advance_hi(struct m0_dtm_hi *hi)
Definition: nucleus.c:152
M0_INTERNAL void m0_dtm_nu_init(struct m0_dtm_nu *nu)
Definition: nucleus.c:365
static int op_cmp(const struct m0_dtm_op *op)
Definition: nucleus.c:235
Definition: nucleus.c:71
#define M0_ASSERT(cond)
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
uint64_t m0_dtm_ver_t
Definition: nucleus.h:48
#define hi_for(h, up)
Definition: dtm_internal.h:58
M0_INTERNAL void op_print(const struct m0_dtm_op *op)
Definition: nucleus.c:555
Definition: nucleus.c:72
#define up_endfor
Definition: dtm_internal.h:54
static void nu(void)
Definition: nucleus.c:87
M0_INTERNAL bool m0_dtm_op_invariant(const struct m0_dtm_op *op)
Definition: nucleus.c:470
static long long max(long long a, long long b)
Definition: crate.c:196
static int next[]
Definition: cp.c:248
void(* doo_miser)(struct m0_dtm_op *op)
Definition: nucleus.h:115
static bool up_pair_invariant(const struct m0_dtm_up *up, const struct m0_dtm_up *next)
Definition: nucleus.c:497
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
#define M0_POST(cond)
M0_INTERNAL void m0_dtm_hi_fini(struct m0_dtm_hi *hi)
Definition: nucleus.c:277
Definition: nucleus.c:74
struct m0_tl op_ups
Definition: nucleus.h:107
M0_INTERNAL void nu_lock(struct m0_dtm_nu *nu)
Definition: nucleus.c:538
enum m0_dtm_up_rule up_rule
Definition: nucleus.h:95
m0_dtm_ver_cmp
Definition: nucleus.c:70
M0_INTERNAL bool up_is_earlier(struct m0_dtm_up *up0, struct m0_dtm_up *up1)
Definition: nucleus.c:410
M0_INTERNAL void m0_dtm_op_close(const struct m0_dtm_op *op)
Definition: nucleus.c:84
void(* doo_ready)(struct m0_dtm_op *op)
Definition: nucleus.h:113
static int up_cmp(const struct m0_dtm_up *up, m0_dtm_ver_t hver)
Definition: nucleus.c:337
M0_INTERNAL void m0_dtm_nuclei_fini(void)
Definition: nucleus.c:534
M0_INTERNAL void m0_dtm_op_fini(struct m0_dtm_op *op)
Definition: nucleus.c:135
M0_INTERNAL void nu_unlock(struct m0_dtm_nu *nu)
Definition: nucleus.c:543
Definition: nucleus.c:73
static void up_fini(struct m0_dtm_up *up)
Definition: nucleus.c:307
static long long min(long long a, long long b)
Definition: crate.c:191
#define M0_MAGIX_OFFSET(type, field)
Definition: misc.h:356
#define hi_endfor
Definition: dtm_internal.h:64
M0_INTERNAL struct m0_dtm_up * m0_dtm_up_prior(struct m0_dtm_up *up)
Definition: nucleus.c:375
static void op_del(struct m0_dtm_op *op)
Definition: nucleus.c:119
M0_INTERNAL bool op_state(const struct m0_dtm_op *op, enum m0_dtm_state state)
Definition: nucleus.c:511
#define _0C(exp)
Definition: assert.h:311
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
#define up_for(o, up)
Definition: dtm_internal.h:48
void check(struct workload *w)
M0_INTERNAL void hi_print(const struct m0_dtm_hi *hi)
Definition: nucleus.c:563
M0_INTERNAL void m0_dtm_up_init(struct m0_dtm_up *up, struct m0_dtm_hi *hi, struct m0_dtm_op *op, enum m0_dtm_up_rule rule, m0_dtm_ver_t ver, m0_dtm_ver_t orig_ver)
Definition: nucleus.c:286
M0_INTERNAL void m0_dtm_hi_init(struct m0_dtm_hi *hi, struct m0_dtm_nu *nu)
Definition: nucleus.c:268
static const struct m0_bob_type hi_bob
Definition: nucleus.c:53
static void advance_op(struct m0_dtm_op *op)
Definition: nucleus.c:170
M0_INTERNAL struct m0_dtm_up * hi_earliest(struct m0_dtm_hi *hi)
Definition: nucleus.c:390
M0_INTERNAL void m0_dtm_nu_fini(struct m0_dtm_nu *nu)
Definition: nucleus.c:370
static int scan(struct scanner *s)
Definition: beck.c:963
M0_INTERNAL void advance_try(const struct m0_dtm_op *op)
Definition: nucleus.c:145
void(* doo_late)(struct m0_dtm_op *op)
Definition: nucleus.h:114
M0_BOB_DEFINE(static, &hi_bob, m0_dtm_hi)
m0_dtm_state
Definition: nucleus.h:52
M0_INTERNAL void m0_bob_type_tlist_init(struct m0_bob_type *bt, const struct m0_tl_descr *td)
Definition: bob.c:41
static void hi(void)
Definition: nucleus.c:93
M0_INTERNAL void m0_dtm_op_prepared(const struct m0_dtm_op *op)
Definition: nucleus.c:97
static struct m0_addb2_frame_header last
Definition: storage.c:93
M0_TL_DESCR_DEFINE(hi, "nucleus hi updates", M0_INTERNAL, struct m0_dtm_up, up_hi_linkage, up_magix, M0_DTM_UP_MAGIX, M0_DTM_HI_MAGIX)
#define m0_tl_forall(name, var, head,...)
Definition: tlist.h:735
#define M0_IMPOSSIBLE(fmt,...)
M0_INTERNAL struct m0_dtm_up * hi_latest(struct m0_dtm_hi *hi)
Definition: nucleus.c:385