Motr  M0
ms_fom_ut.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * For any questions about this software or licensing,
17  * please email opensource@seagate.com or cortx-questions@seagate.com.
18  *
19  */
20 
21 
22 #include "lib/errno.h"
23 #include "lib/memory.h"
24 #include "lib/semaphore.h"
25 #include "rpc/rpc_opcodes.h"
26 #include "fop/fom.h"
27 #include "fop/fom_generic.h"
28 #include "fop/fom_interpose.h"
29 #include "reqh/reqh.h"
30 #include "reqh/reqh_service.h"
31 #include "ut/ut.h"
32 
33 struct ms_fom {
34  /* Generic m0_fom object. */
35  struct m0_fom msf_fom;
36  /* UT test data. */
38  /* To implement fake sleeping. */
40 };
41 
46 };
47 
53 };
54 
56  [START_FOLLOWER] = {
58  .sd_name = "start-follower",
59  .sd_allowed = M0_BITS(CHECK_RESULT)
60  },
61  [CHECK_RESULT] = {
62  .sd_name = "check-result",
63  .sd_allowed = M0_BITS(FINISH)
64  },
65  [FINISH] = {
66  .sd_name = "finish",
67  .sd_flags = M0_SDF_TERMINAL,
68  }
69 };
70 
72  [FIRST_PHASE] = {
74  .sd_name = "first-phase",
75  .sd_allowed = M0_BITS(SECOND_PHASE)
76  },
77  [SECOND_PHASE] = {
78  .sd_name = "second-phase",
79  .sd_allowed = M0_BITS(THIRD_PHASE)
80  },
81  [THIRD_PHASE] = {
82  .sd_name = "third-phase",
83  .sd_allowed = M0_BITS(FINISH_PHASE)
84  },
85  [FINISH_PHASE] = {
86  .sd_name = "finish-phase",
87  .sd_flags = M0_SDF_TERMINAL,
88  }
89 };
90 
91 static struct m0_sm_conf leader_sm_conf = {
92  .scf_name = "leader_fom",
93  .scf_nr_states = ARRAY_SIZE(leader_fom_phases),
94  .scf_state = leader_fom_phases,
95 };
96 
97 static struct m0_sm_conf follower_sm_conf = {
98  .scf_name = "follower_fom",
99  .scf_nr_states = ARRAY_SIZE(follower_fom_phases),
100  .scf_state = follower_fom_phases,
101 };
102 
103 static struct m0_fom_type leader_fomt;
105 
106 static struct m0_semaphore sem;
107 static struct m0_reqh msreqh;
108 static struct m0_reqh_service *mssvc;
109 uint64_t msfom_id = 0;
111 static int test_counter;
112 static bool use_same_locality = false;
113 
114 
115 static size_t ms_fom_home_locality(const struct m0_fom *fom);
116 
117 static int leader_fom_tick(struct m0_fom *fom);
118 static int follower_fom_tick (struct m0_fom *fom);
119 
120 static void leader_fom_create(struct m0_fom **out, struct m0_reqh *reqh);
121 static void follower_fom_create (struct m0_fom **out, struct m0_reqh *reqh);
122 static void ms_fom_fini (struct m0_fom *fom);
123 
124 
125 /*************************************************/
126 /* UT service */
127 /*************************************************/
128 
129 static int mssvc_start(struct m0_reqh_service *svc);
130 static void mssvc_stop (struct m0_reqh_service *svc);
131 static void mssvc_fini (struct m0_reqh_service *svc);
132 
133 static const struct m0_reqh_service_ops mssvc_ops = {
135  .rso_start = &mssvc_start,
136  .rso_stop = &mssvc_stop,
137  .rso_fini = &mssvc_fini
138 };
139 
140 static int mssvc_start(struct m0_reqh_service *svc)
141 {
142  return 0;
143 }
144 
145 static void mssvc_stop(struct m0_reqh_service *svc)
146 {
147 }
148 
149 static void mssvc_fini(struct m0_reqh_service *svc)
150 {
151  m0_free(svc);
152 }
153 
155  const struct m0_reqh_service_type *stype)
156 {
157  M0_ALLOC_PTR(*svc);
158  M0_ASSERT(*svc != NULL);
159  (*svc)->rs_type = stype;
160  (*svc)->rs_ops = &mssvc_ops;
161  return 0;
162 }
163 
166 };
167 
169  .rst_name = "ms_ut",
170  .rst_ops = &mssvc_type_ops,
171  .rst_level = M0_RS_LEVEL_NORMAL,
172  .rst_typecode = M0_CST_DS1
173 };
174 
175 /*************************************************/
176 /* FOMs description */
177 /*************************************************/
178 
180 static const struct m0_fom_ops leader_fom_ops = {
181  .fo_fini = ms_fom_fini,
182  .fo_tick = leader_fom_tick,
183  .fo_home_locality = ms_fom_home_locality
184 };
186 static const struct m0_fom_ops follower_fom_ops = {
187  .fo_fini = ms_fom_fini,
188  .fo_tick = follower_fom_tick,
189  .fo_home_locality = ms_fom_home_locality
190 };
191 
193  .fto_create = NULL
194 };
195 
196 static size_t ms_fom_home_locality(const struct m0_fom *fom)
197 {
198  static size_t locality = 0;
199 
200  M0_PRE(fom != NULL);
201  return use_same_locality ? 0 : locality++;
202 }
203 
204 static void wakeup(struct m0_sm_group *grp, struct m0_sm_ast *ast)
205 {
206  struct ms_fom *fom = M0_AMB(fom, ast, msf_wakeup);
207  m0_fom_wakeup(&fom->msf_fom);
208 }
209 
210 static void fake_wait(struct ms_fom *fom)
211 {
212  struct m0_sm_group *grp;
213 
214  grp = &fom->msf_fom.fo_loc->fl_group;
215  fom->msf_wakeup.sa_cb = wakeup;
216  m0_sm_ast_post(grp, &fom->msf_wakeup);
217 }
218 
219 static int leader_fom_tick(struct m0_fom *fom0)
220 {
221  struct ms_fom *fom = M0_AMB(fom, fom0, msf_fom);
222  int phase = m0_fom_phase(fom0);
223  int result = M0_FSO_AGAIN;
224  struct m0_fom *follower_fom;
225 
226  switch (phase) {
227  case START_FOLLOWER:
228  *fom->msf_test_counter = 0;
229  follower_fom_create(&follower_fom, &msreqh);
230  m0_fom_enthrall(fom0, follower_fom, &thrall, NULL);
231  m0_fom_queue(follower_fom);
233  result = M0_FSO_WAIT;
234  break;
235  case CHECK_RESULT:
236  M0_ASSERT(*fom->msf_test_counter == 3);
237  m0_fom_phase_set(fom0, FINISH);
238  result = M0_FSO_WAIT;
240  break;
241  }
242  return result;
243 }
244 
245 static int follower_fom_tick(struct m0_fom *fom0)
246 {
247  struct ms_fom *fom = M0_AMB(fom, fom0, msf_fom);
248  int phase = m0_fom_phase(fom0);
249  int result = M0_FSO_AGAIN;
250 
251  switch (phase) {
252  case FIRST_PHASE:
253  (*fom->msf_test_counter)++;
255  /* Imitation of waiting of completion of some opereation. */
256  fake_wait(fom);
257  result = M0_FSO_WAIT;
258  break;
259  case SECOND_PHASE:
260  (*fom->msf_test_counter)++;
262  break;
263  case THIRD_PHASE:
264  (*fom->msf_test_counter)++;
266  result = M0_FSO_WAIT;
267  break;
268  }
269  return result;
270 }
271 
272 static void ms_fom_create(struct m0_fom **out, struct m0_reqh *reqh,
273  bool follower)
274 {
275  struct m0_fom *fom0;
276  struct ms_fom *fom_obj;
277 
278  M0_PRE(out != NULL);
279 
280  M0_ALLOC_PTR(fom_obj);
281  M0_UT_ASSERT(fom_obj != NULL);
282 
283  fom_obj->msf_test_counter = &test_counter;
284  fom0 = &fom_obj->msf_fom;
285  m0_fom_init(fom0,
286  follower ? &follower_fomt : &leader_fomt,
287  follower ? &follower_fom_ops : &leader_fom_ops,
288  NULL, NULL, reqh);
289  *out = fom0;
290 }
291 
292 static void leader_fom_create(struct m0_fom **out, struct m0_reqh *reqh)
293 {
296  &leader_sm_conf);
297  ms_fom_create(out, reqh, false);
298 }
299 
300 static void follower_fom_create(struct m0_fom **out, struct m0_reqh *reqh)
301 {
305  ms_fom_create(out, reqh, true);
306 }
307 
308 static void ms_fom_fini(struct m0_fom *fom)
309 {
310  struct ms_fom *fom_obj;
311 
312  fom_obj = container_of(fom, struct ms_fom, msf_fom);
313  m0_fom_fini(fom);
314  m0_free(fom_obj);
315 }
316 
317 /*************************************************/
318 /* REQH routines */
319 /*************************************************/
320 
321 static void reqh_init(void)
322 {
323  int rc;
324 
326  .rhia_dtm = (void *)1,
327  .rhia_mdstore = (void *)1,
328  .rhia_fid = &g_process_fid);
329  M0_UT_ASSERT(rc == 0);
330 }
331 
332 static void reqh_start(void)
333 {
334  int rc;
335 
337  M0_UT_ASSERT(rc == 0);
341 }
342 
343 static void reqh_stop(void)
344 {
349 }
350 
351 static void reqh_fini(void)
352 {
355 }
356 
357 /*************************************************/
358 /* Leader-Follower UT init/fini */
359 /*************************************************/
360 
361 static void ms_init(void)
362 {
363  reqh_init();
364  reqh_start();
365 }
366 
367 static void ms_fini(void)
368 {
369  reqh_stop();
370  reqh_fini();
371 }
372 
373 /*************************************************/
374 /* Test cases */
375 /*************************************************/
376 
377 static void leader_follower(void)
378 {
379  struct m0_fom *leader_fom;
380 
381  ms_init();
382  m0_semaphore_init(&sem, 0);
383  leader_fom_create(&leader_fom, &msreqh);
384  m0_fom_queue(leader_fom);
387  ms_fini();
388 }
389 
390 static void leader_follower_same_loc(void)
391 {
392  use_same_locality = true;
393  leader_follower();
394 }
395 
396 static void leader_follower_diff_loc(void)
397 {
398  use_same_locality = false;
399  leader_follower();
400 }
401 
403  .ts_name = "ms-fom-ut",
404  .ts_init = NULL,
405  .ts_fini = NULL,
406  .ts_tests = {
407  { "leader-follower-sl", &leader_follower_same_loc, "Sergey" },
408  { "leader-follower-dl", &leader_follower_diff_loc, "Sergey" },
409  { NULL, NULL }
410  }
411 };
412 
413 M0_EXPORTED(ms_fom_ut);
414 
415 /*
416  * Local variables:
417  * c-indentation-style: "K&R"
418  * c-basic-offset: 8
419  * tab-width: 8
420  * fill-column: 80
421  * scroll-step: 1
422  * End:
423  */
static struct m0_fom_type leader_fomt
Definition: ms_fom_ut.c:103
static const struct m0_reqh_service_ops mssvc_ops
Definition: ms_fom_ut.c:133
static void leader_follower_same_loc(void)
Definition: ms_fom_ut.c:390
leader_fom_phase
Definition: ms_fom_ut.c:42
M0_INTERNAL void m0_fom_wakeup(struct m0_fom *fom)
Definition: fom.c:532
#define M0_PRE(cond)
M0_INTERNAL int m0_reqh_service_start(struct m0_reqh_service *service)
Definition: reqh_service.c:343
static struct m0_fom_type follower_fomt
Definition: ms_fom_ut.c:104
M0_INTERNAL void m0_reqh_services_terminate(struct m0_reqh *reqh)
Definition: reqh.c:675
static void reqh_start(void)
Definition: ms_fom_ut.c:332
static void ms_fini(void)
Definition: ms_fom_ut.c:367
M0_INTERNAL void m0_reqh_service_stop(struct m0_reqh_service *service)
Definition: reqh_service.c:402
#define NULL
Definition: misc.h:38
static size_t locality(const struct m0_fom *fom)
Definition: rm_foms.c:269
static const struct m0_fom_ops follower_fom_ops
Definition: ms_fom_ut.c:186
struct m0_fom msf_fom
Definition: ms_fom_ut.c:35
struct m0_ut_suite ms_fom_ut
Definition: ms_fom_ut.c:402
#define M0_REQH_INIT(reqh,...)
Definition: reqh.h:262
Definition: sm.h:350
static size_t ms_fom_home_locality(const struct m0_fom *fom)
Definition: ms_fom_ut.c:196
static struct m0_sm_group * grp
Definition: bytecount.c:38
static struct m0_reqh_service * mssvc
Definition: ms_fom_ut.c:108
M0_INTERNAL void m0_reqh_service_prepare_to_stop(struct m0_reqh_service *service)
Definition: reqh_service.c:375
M0_INTERNAL void m0_sm_ast_post(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:135
static int mssvc_start(struct m0_reqh_service *svc)
Definition: ms_fom_ut.c:140
int(* fto_create)(struct m0_fop *fop, struct m0_fom **out, struct m0_reqh *reqh)
Definition: fom.h:650
follower_fom_phase
Definition: ms_fom_ut.c:48
static void reqh_init(void)
Definition: ms_fom_ut.c:321
#define M0_BITS(...)
Definition: misc.h:236
static void ms_init(void)
Definition: ms_fom_ut.c:361
Definition: sm.h:504
#define container_of(ptr, type, member)
Definition: misc.h:33
Definition: ut.h:77
M0_INTERNAL void m0_reqh_fini(struct m0_reqh *reqh)
Definition: reqh.c:320
m0_fom_phase
Definition: fom.h:372
static struct m0_sm_ast ast[NR]
Definition: locality.c:44
static void leader_fom_create(struct m0_fom **out, struct m0_reqh *reqh)
Definition: ms_fom_ut.c:292
void m0_fom_init(struct m0_fom *fom, const struct m0_fom_type *fom_type, const struct m0_fom_ops *ops, struct m0_fop *fop, struct m0_fop *reply, struct m0_reqh *reqh)
Definition: fom.c:1372
static struct m0_sm_conf follower_sm_conf
Definition: ms_fom_ut.c:97
struct m0_sm_ast msf_wakeup
Definition: ms_fom_ut.c:39
static void fake_wait(struct ms_fom *fom)
Definition: ms_fom_ut.c:210
static int follower_fom_tick(struct m0_fom *fom)
Definition: ms_fom_ut.c:245
static void leader_follower(void)
Definition: ms_fom_ut.c:377
static void ms_fom_create(struct m0_fom **out, struct m0_reqh *reqh, bool follower)
Definition: ms_fom_ut.c:272
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
struct m0_fom_thralldom thrall
Definition: ms_fom_ut.c:110
static const struct socktype stype[]
Definition: sock.c:1156
void m0_fom_fini(struct m0_fom *fom)
Definition: fom.c:1324
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
static const struct m0_reqh_service_type_ops mssvc_type_ops
Definition: ms_fom_ut.c:164
static bool use_same_locality
Definition: ms_fom_ut.c:112
const char * rst_name
Definition: reqh_service.h:447
M0_INTERNAL void m0_reqh_service_fini(struct m0_reqh_service *service)
Definition: reqh_service.c:457
M0_INTERNAL void m0_fom_enthrall(struct m0_fom *leader, struct m0_fom *serf, struct m0_fom_thralldom *thrall, void(*end)(struct m0_fom_thralldom *thrall, struct m0_fom *serf))
M0_INTERNAL void m0_fom_type_init(struct m0_fom_type *type, uint64_t id, const struct m0_fom_type_ops *ops, const struct m0_reqh_service_type *svc_type, const struct m0_sm_conf *sm)
Definition: fom.c:1596
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
static int mssvc_type_allocate(struct m0_reqh_service **svc, const struct m0_reqh_service_type *stype)
Definition: ms_fom_ut.c:154
static int leader_fom_tick(struct m0_fom *fom)
Definition: ms_fom_ut.c:219
M0_INTERNAL int m0_reqh_service_allocate(struct m0_reqh_service **out, const struct m0_reqh_service_type *stype, struct m0_reqh_context *rctx)
Definition: reqh_service.c:185
Definition: reqh.h:94
Definition: dump.c:103
const struct m0_fom_type_ops ms_fom_type_ops
Definition: ms_fom_ut.c:192
M0_INTERNAL void m0_reqh_service_init(struct m0_reqh_service *service, struct m0_reqh *reqh, const struct m0_fid *fid)
Definition: reqh_service.c:428
uint64_t msfom_id
Definition: ms_fom_ut.c:109
static struct m0_sm_conf leader_sm_conf
Definition: ms_fom_ut.c:91
int * msf_test_counter
Definition: ms_fom_ut.c:37
static struct m0_semaphore sem
Definition: ms_fom_ut.c:106
static void reqh_stop(void)
Definition: ms_fom_ut.c:343
int m0_reqh_service_async_start_simple(struct m0_reqh_service_start_async_ctx *asc)
Definition: reqh_service.c:601
uint32_t sd_flags
Definition: sm.h:378
Definition: fom.h:481
static void mssvc_fini(struct m0_reqh_service *svc)
Definition: ms_fom_ut.c:149
const char * ts_name
Definition: ut.h:99
M0_INTERNAL void m0_reqh_start(struct m0_reqh *reqh)
Definition: reqh.c:711
static struct m0_sm_state_descr leader_fom_phases[]
Definition: ms_fom_ut.c:55
struct m0_reqh reqh
Definition: rm_foms.c:48
int(* rsto_service_allocate)(struct m0_reqh_service **service, const struct m0_reqh_service_type *stype)
Definition: reqh_service.h:435
static int test_counter
Definition: ms_fom_ut.c:111
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_INTERNAL void m0_semaphore_fini(struct m0_semaphore *semaphore)
Definition: semaphore.c:45
static void follower_fom_create(struct m0_fom **out, struct m0_reqh *reqh)
Definition: ms_fom_ut.c:300
static struct m0_net_test_service svc
Definition: service.c:34
static void ms_fom_fini(struct m0_fom *fom)
Definition: ms_fom_ut.c:308
static struct m0_reqh_service_type ut_ms_service_type
Definition: ms_fom_ut.c:168
static struct m0_sm_state_descr follower_fom_phases[]
Definition: ms_fom_ut.c:71
static void wakeup(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: ms_fom_ut.c:204
M0_INTERNAL void m0_reqh_idle_wait_for(struct m0_reqh *reqh, struct m0_reqh_service *service)
Definition: reqh.c:591
M0_INTERNAL void m0_fom_queue(struct m0_fom *fom)
Definition: fom.c:624
static void mssvc_stop(struct m0_reqh_service *svc)
Definition: ms_fom_ut.c:145
void(* fo_fini)(struct m0_fom *fom)
Definition: fom.h:657
static void reqh_fini(void)
Definition: ms_fom_ut.c:351
static const struct m0_fom_ops leader_fom_ops
Definition: ms_fom_ut.c:180
M0_INTERNAL void m0_semaphore_down(struct m0_semaphore *semaphore)
Definition: semaphore.c:49
#define out(...)
Definition: gen.c:41
void m0_fom_phase_set(struct m0_fom *fom, int phase)
Definition: fom.c:1688
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
static void leader_follower_diff_loc(void)
Definition: ms_fom_ut.c:396
void m0_free(void *data)
Definition: memory.c:146
int32_t rc
Definition: trigger_fop.h:47
int(* rso_start_async)(struct m0_reqh_service_start_async_ctx *asc)
Definition: reqh_service.h:341
#define ARRAY_SIZE(a)
Definition: misc.h:45
struct m0_fid g_process_fid
Definition: ut.c:689
#define M0_UT_ASSERT(a)
Definition: ut.h:46
static struct m0_reqh msreqh
Definition: ms_fom_ut.c:107