Motr  M0
machine.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 "lib/assert.h"
33 
34 #include "dtm/dtm.h"
35 #include "dtm/remote.h"
36 #include "dtm/nucleus.h"
37 #include "dtm/history.h"
38 #include "dtm/dtm_internal.h"
39 #include "dtm/machine.h"
40 
41 static void history_balance(struct m0_dtm_history *history);
42 static void history_excite(struct m0_dtm_history *history);
43 static void history_calm(struct m0_dtm_history *history);
44 static void undo_done(struct m0_dtm_update *update);
45 static void sibling_undo (struct m0_dtm_history *history,
46  struct m0_dtm_op *op);
47 static void sibling_persistent(struct m0_dtm_history *history,
48  struct m0_dtm_op *op);
49 static void sibling_reset (struct m0_dtm_history *history,
50  struct m0_dtm_op *op);
51 
52 M0_INTERNAL void m0_dtm_balance(struct m0_dtm *dtm)
53 {
54  while (!exc_tlist_is_empty(&dtm->d_excited)) {
55  struct m0_dtm_history *history;
56 
57  m0_tl_for(exc, &dtm->d_excited, history) {
58  history_balance(history);
59  } m0_tl_endfor;
60  }
61 }
62 
63 M0_INTERNAL void m0_dtm_history_balance(struct m0_dtm_history *history)
64 {
65  history_balance(history);
66  m0_dtm_balance(HISTORY_DTM(history));
67 }
68 
69 M0_INTERNAL void m0_dtm_undo_done(struct m0_dtm_update *update)
70 {
71  undo_done(update);
73 }
74 
75 static void history_balance(struct m0_dtm_history *history)
76 {
77  bool more = false;
78  struct m0_dtm_up *up;
79  struct m0_dtm_update *update;
80 
82 
83  if (history->h_undo != NULL) {
84  up = history_latest(history);
85  update = up_update(up);
86  M0_ASSERT(up != NULL);
87  sibling_undo(history, up->up_op);
88  if (update->upd_ops->updo_undo != NULL)
89  update->upd_ops->updo_undo(update);
90  else {
91  undo_done(update);
92  more = true;
93  }
94  }
95  if (history->h_persistent != NULL) {
96  up = UPDATE_UP(history->h_persistent);
97  do {
98  if (up->up_state >= M0_DOS_PERSISTENT)
99  break;
101  sibling_persistent(history, up->up_op);
102  up = m0_dtm_up_prior(up);
103  } while (up != NULL);
104  if (up_ver(up) != update_ver(history->h_persistent))
105  history->h_ops->hio_persistent(history);
106  if ((history->h_hi.hi_flags & M0_DHF_CLOSED) &&
107  m0_dtm_up_later(&history->h_persistent->upd_up) == NULL)
108  history->h_ops->hio_fixed(history);
109  history->h_persistent = NULL;
110  }
111  if (history->h_reset != NULL) {
112  up = UPDATE_UP(history->h_reset);
113  do {
114  if (up->up_state < M0_DOS_INPROGRESS)
115  break;
117  sibling_reset(history, up->up_op);
118  up = m0_dtm_up_later(up);
119  } while (up != NULL);
120  history->h_known =
122  history->h_reint = history->h_reset;
123  history->h_reset = NULL;
124  more = true;
125  }
126  if (history->h_reint != NULL) {
127  up = UPDATE_UP(history->h_reint);
128  do {
129  if (up->up_state < M0_DOS_INPROGRESS)
130  break;
131  update_reint(up_update(up));
132  up = m0_dtm_up_later(up);
133  } while (up != NULL);
134  history->h_reint = NULL;
135  }
136  more ? history_excite(history) : history_calm(history);
138 }
139 
140 static void sibling_undo(struct m0_dtm_history *history, struct m0_dtm_op *op)
141 {
142  up_for(op, up) {
143  struct m0_dtm_history *other = UP_HISTORY(up);
144  struct m0_dtm_update *update = up_update(up);
145 
146  M0_ASSERT(up == hi_latest(up->up_hi));
147  M0_ASSERT(up->up_state >= M0_DOS_VOLATILE);
148 
149  if (other != history && other->h_epoch < history->h_epoch &&
150  (other->h_undo == NULL || update_is_earlier(update,
151  other->h_undo))) {
152  other->h_undo = update;
153  other->h_epoch = history->h_epoch;
154  history_excite(other);
155  }
156  } up_endfor;
157 }
158 
159 static void sibling_persistent(struct m0_dtm_history *history,
160  struct m0_dtm_op *op)
161 {
162  up_for(op, up) {
163  struct m0_dtm_history *other = UP_HISTORY(up);
164  struct m0_dtm_update *update = up_update(up);
165 
166  if (up->up_state < M0_DOS_PERSISTENT && other != history &&
167  other->h_rem == history->h_rem &&
168  (other->h_persistent == NULL ||
169  update_is_earlier(other->h_persistent, update))) {
170  other->h_persistent = update;
171  history_excite(other);
172  }
173  } up_endfor;
174 }
175 
176 static void sibling_reset(struct m0_dtm_history *history, struct m0_dtm_op *op)
177 {
178  up_for(op, up) {
179  struct m0_dtm_history *other = UP_HISTORY(up);
180  struct m0_dtm_update *update = up_update(up);
181 
182  if (other != history && other->h_rem == history->h_rem &&
183  other->h_epoch < history->h_epoch &&
184  (other->h_reset == NULL ||
185  update_is_earlier(update, other->h_reset))) {
186  other->h_reset = update;
187  other->h_epoch = history->h_epoch;
188  history_excite(other);
189  }
190  } up_endfor;
191 }
192 
193 static void undo_done(struct m0_dtm_update *update)
194 {
195  struct m0_dtm_up *up = UPDATE_UP(update);
196  struct m0_dtm_history *history = UP_HISTORY(up);
197  struct m0_dtm_up *prior = m0_dtm_up_prior(up);
198  m0_dtm_ver_t pver = up_ver(prior);
199 
201  M0_PRE(up == history_latest(history));
202  M0_ASSERT(history->h_persistent == NULL);
203  M0_ASSERT(history->h_reint == NULL);
204  M0_ASSERT(history->h_known == NULL);
205  M0_ASSERT(history->h_reset == NULL);
206 
207  if (history->h_max_ver == up->up_ver)
208  history->h_max_ver = pver;
209  if (history->h_hi.hi_ver == up->up_ver)
210  history->h_hi.hi_ver = pver;
211  if (history->h_undo == update)
212  history->h_undo = NULL;
213 
215 }
216 
217 static void dtm_excitement_start(struct m0_dtm *dtm)
218 {
219 }
220 
221 static void history_excite(struct m0_dtm_history *history)
222 {
223  struct m0_dtm *dtm = HISTORY_DTM(history);
224  struct m0_tl *excited = &dtm->d_excited;
225 
226  if (!exc_tlink_is_in(history)) {
227  bool empty = exc_tlist_is_empty(excited);
228 
229  exc_tlist_add_tail(excited, history);
230  if (empty)
232  }
233 }
234 
235 static void history_calm(struct m0_dtm_history *history)
236 {
237  exc_tlist_remove(history);
238 }
239 
240 #undef M0_TRACE_SUBSYSTEM
241 
244 /*
245  * Local variables:
246  * c-indentation-style: "K&R"
247  * c-basic-offset: 8
248  * tab-width: 8
249  * fill-column: 80
250  * scroll-step: 1
251  * End:
252  */
253 /*
254  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
255  */
struct m0_dtm_up upd_up
Definition: update.h:72
struct m0_dtm_update * h_known
Definition: history.h:63
int(* updo_undo)(struct m0_dtm_update *updt)
Definition: update.h:85
M0_INTERNAL struct m0_dtm_up * m0_dtm_up_later(struct m0_dtm_up *up)
Definition: nucleus.c:380
#define M0_PRE(cond)
enum m0_dtm_state up_state
Definition: nucleus.h:94
M0_INTERNAL m0_dtm_ver_t up_ver(const struct m0_dtm_up *up)
Definition: nucleus.c:405
#define NULL
Definition: misc.h:38
static bool more
Definition: sm.c:36
uint64_t hi_flags
Definition: nucleus.h:65
struct m0_dtm_remote * h_rem
Definition: history.h:59
#define UPDATE_UP(update)
Definition: dtm_internal.h:97
#define UP_HISTORY(up)
Definition: dtm_internal.h:103
void(* hio_persistent)(struct m0_dtm_history *history)
Definition: history.h:81
struct m0_dtm_update * h_reint
Definition: history.h:62
struct m0_dtm_hi h_hi
Definition: history.h:56
M0_INTERNAL struct m0_dtm_update * up_update(struct m0_dtm_up *up)
Definition: update.c:228
m0_dtm_ver_t up_ver
Definition: nucleus.h:96
const struct m0_dtm_update_ops * upd_ops
Definition: update.h:74
struct m0_dtm_op * up_op
Definition: nucleus.h:100
#define m0_tl_endfor
Definition: tlist.h:700
op
Definition: libdemo.c:64
M0_INTERNAL void m0_dtm_history_balance(struct m0_dtm_history *history)
Definition: machine.c:63
M0_INTERNAL bool update_is_earlier(struct m0_dtm_update *update0, struct m0_dtm_update *update1)
Definition: update.c:234
static void history_excite(struct m0_dtm_history *history)
Definition: machine.c:221
struct m0_dtm_update * h_persistent
Definition: history.h:60
#define UPDATE_HISTORY(update)
Definition: dtm_internal.h:104
static void history_balance(struct m0_dtm_history *history)
Definition: machine.c:75
#define M0_ASSERT(cond)
uint64_t m0_dtm_ver_t
Definition: nucleus.h:48
struct m0_dtm_update * h_reset
Definition: history.h:64
struct m0_fid pver
Definition: idx_dix.c:74
#define HISTORY_DTM(history)
Definition: dtm_internal.h:106
Definition: tlist.h:251
#define up_endfor
Definition: dtm_internal.h:54
static void history_calm(struct m0_dtm_history *history)
Definition: machine.c:235
static void sibling_undo(struct m0_dtm_history *history, struct m0_dtm_op *op)
Definition: machine.c:140
M0_INTERNAL void update_reint(struct m0_dtm_update *update)
Definition: update.c:240
#define M0_POST(cond)
M0_INTERNAL m0_dtm_ver_t update_ver(const struct m0_dtm_update *update)
Definition: history.c:194
struct m0_tl d_excited
Definition: dtm.h:543
M0_INTERNAL void m0_dtm_undo_done(struct m0_dtm_update *update)
Definition: machine.c:69
static void undo_done(struct m0_dtm_update *update)
Definition: machine.c:193
M0_INTERNAL bool m0_dtm_history_invariant(const struct m0_dtm_history *history)
Definition: history.c:71
M0_INTERNAL struct m0_dtm_up * m0_dtm_up_prior(struct m0_dtm_up *up)
Definition: nucleus.c:375
m0_dtm_ver_t hi_ver
Definition: nucleus.h:66
static void sibling_persistent(struct m0_dtm_history *history, struct m0_dtm_op *op)
Definition: machine.c:159
M0_INTERNAL void m0_dtm_balance(struct m0_dtm *dtm)
Definition: machine.c:52
uint64_t h_epoch
Definition: history.h:67
#define up_for(o, up)
Definition: dtm_internal.h:48
struct m0_dtm_update * h_undo
Definition: history.h:61
static void dtm_excitement_start(struct m0_dtm *dtm)
Definition: machine.c:217
Definition: dtm.h:529
static void sibling_reset(struct m0_dtm_history *history, struct m0_dtm_op *op)
Definition: machine.c:176
void(* hio_fixed)(struct m0_dtm_history *history)
Definition: history.h:82
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
m0_dtm_ver_t h_max_ver
Definition: history.h:69
static void empty(void)
Definition: consumer.c:101
const struct m0_dtm_history_ops * h_ops
Definition: history.h:65
M0_INTERNAL struct m0_dtm_up * hi_latest(struct m0_dtm_hi *hi)
Definition: nucleus.c:385
M0_INTERNAL struct m0_dtm_up * history_latest(struct m0_dtm_history *history)
Definition: history.c:205