Motr  M0
ha.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2016-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 
30 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_UT
31 #include "lib/trace.h"
32 
33 #include "ha/ha.h"
34 #include "ut/ut.h"
35 
36 #include "lib/memory.h" /* M0_ALLOC_PTR */
37 #include "lib/mutex.h" /* m0_mutex */
38 #include "lib/chan.h" /* m0_clink */
39 
40 #include "ha/entrypoint.h" /* M0_HEC_AVAILABLE */
41 #include "ha/ut/helper.h" /* m0_ha_ut_rpc_ctx */
42 
45  struct m0_ha huc_ha;
58 };
59 
61  struct m0_ha *huw_ha;
64 };
65 
66 static struct ha_ut_usecase_ctx *ha_ut_ha2usecase_ctx(struct m0_ha *ha)
67 {
68  return container_of(ha, struct ha_ut_usecase_ctx, huc_ha);
69 }
70 
72  struct m0_ha_link *hl)
73 {
74  m0_mutex_lock(&huc->huc_lock);
75  M0_UT_ASSERT(huc->huc_link_in1 == NULL ||
76  huc->huc_link_in2 == NULL ||
77  M0_IN(hl, (huc->huc_link_in1, huc->huc_link_in2, NULL)));
78  if (huc->huc_link_in1 == NULL) {
79  huc->huc_link_in1 = hl;
80  } else if (huc->huc_link_in1 != hl && huc->huc_link_in2 != hl) {
82  huc->huc_link_in2 = hl;
83  }
85 }
86 
88  (struct m0_ha *ha,
89  const struct m0_ha_entrypoint_req *req,
90  const struct m0_uint128 *req_id)
91 {
93  struct ha_ut_usecase_ctx *huc = ha_ut_ha2usecase_ctx(ha);
94  struct m0_ha_link *hl;
95 
98 
100  &req->heq_process_fid));
101  rep = (struct m0_ha_entrypoint_rep){
102  .hae_quorum = 1,
103  .hae_confd_fids = {},
104  .hae_confd_eps = NULL,
105  .hae_active_rm_fid = M0_FID_INIT(5, 6),
106  .hae_active_rm_ep = NULL,
107  .hae_control = M0_HA_ENTRYPOINT_CONSUME,
108  };
109  m0_ha_entrypoint_reply(ha, req_id, &rep, &hl);
110  ha_ut_usecase_link_check(huc, hl);
111 }
112 
114  struct m0_ha_entrypoint_rep *rep)
115 {
116  struct ha_ut_usecase_ctx *huc = ha_ut_ha2usecase_ctx(ha);
117 
120 
121  M0_UT_ASSERT(rep->hae_control == M0_HA_ENTRYPOINT_CONSUME);
122  M0_UT_ASSERT(rep->hae_quorum == 1);
123  M0_UT_ASSERT(m0_fid_eq(&M0_FID_INIT(5, 6), &rep->hae_active_rm_fid));
124 }
125 
126 static void ha_ut_usecase_msg_received(struct m0_ha *ha,
127  struct m0_ha_link *hl,
128  struct m0_ha_msg *msg,
129  uint64_t tag)
130 {
131 }
132 
133 static void ha_ut_usecase_msg_is_delivered(struct m0_ha *ha,
134  struct m0_ha_link *hl,
135  uint64_t tag)
136 {
137 }
138 
140  struct m0_ha_link *hl,
141  uint64_t tag)
142 {
143 }
144 
145 static void ha_ut_usecase_link_connected(struct m0_ha *ha,
146  const struct m0_uint128 *req_id,
147  struct m0_ha_link *hl)
148 {
149  struct ha_ut_usecase_ctx *huc = ha_ut_ha2usecase_ctx(ha);
150 
152  ++huc->huc_link_connected_nr;
153  ha_ut_usecase_link_check(huc, hl);
154 }
155 
156 static void ha_ut_usecase_link_reused(struct m0_ha *ha,
157  const struct m0_uint128 *req_id,
158  struct m0_ha_link *hl)
159 {
160  struct ha_ut_usecase_ctx *huc = ha_ut_ha2usecase_ctx(ha);
161 
162  M0_UT_ASSERT(huc->huc_link_reused_nr == 0);
163  ++huc->huc_link_reused_nr;
164  ha_ut_usecase_link_check(huc, hl);
165 }
166 
168  struct m0_ha_link *hl)
169 {
170  struct ha_ut_usecase_ctx *huc = ha_ut_ha2usecase_ctx(ha);
171 
172  M0_UT_ASSERT(M0_IN(huc->huc_link_is_disconnecting_nr, (0, 1)));
174 
176 }
177 
178 static void ha_ut_usecase_link_disconnected(struct m0_ha *ha,
179  struct m0_ha_link *hl)
180 {
181  struct ha_ut_usecase_ctx *huc = ha_ut_ha2usecase_ctx(ha);
182 
183  M0_UT_ASSERT(M0_IN(huc->huc_link_disconnected_nr, (0, 1)));
185 
186  m0_mutex_lock(&huc->huc_lock);
187  M0_UT_ASSERT(M0_IN(hl, (huc->huc_link_in1, huc->huc_link_in2)));
188  huc->huc_link_in1 = hl == huc->huc_link_in1 ? NULL : huc->huc_link_in1;
189  huc->huc_link_in2 = hl == huc->huc_link_in2 ? NULL : huc->huc_link_in2;
190  m0_mutex_unlock(&huc->huc_lock);
191 }
192 
194 {
195  struct ha_ut_wait_ctx *huw;
196 
197  huw = container_of(clink, struct ha_ut_wait_ctx, huw_clink);
199 }
200 
201 static const struct m0_ha_ops ha_ut_usecase_ha_ops = {
203  .hao_entrypoint_replied = ha_ut_usecase_entrypoint_replied,
204  .hao_msg_received = ha_ut_usecase_msg_received,
205  .hao_msg_is_delivered = ha_ut_usecase_msg_is_delivered,
206  .hao_msg_is_not_delivered = ha_ut_usecase_msg_is_not_delivered,
207  .hao_link_connected = ha_ut_usecase_link_connected,
208  .hao_link_reused = ha_ut_usecase_link_reused,
209  .hao_link_is_disconnecting = ha_ut_usecase_link_is_disconnecting,
210  .hao_link_disconnected = ha_ut_usecase_link_disconnected,
211 };
212 
214 {
215  struct ha_ut_usecase_ctx *ctx;
216  struct m0_ha_ut_rpc_ctx *rpc_ctx;
217  struct ha_ut_wait_ctx wait_ctx;
218  struct m0_ha_msg *msg;
219  struct m0_ha_cfg ha_cfg;
220  struct m0_clink *clink;
221  struct m0_ha *ha;
222  int rc;
223 
224  M0_ALLOC_PTR(msg);
225  M0_UT_ASSERT(msg != NULL);
229  M0_ALLOC_PTR(ctx);
230  M0_UT_ASSERT(ctx != NULL);
231  m0_mutex_init(&ctx->huc_lock);
232  ha = &ctx->huc_ha;
233 
234  ha_cfg = (struct m0_ha_cfg){
236  .hcf_rpc_machine = &rpc_ctx->hurc_rpc_machine,
237  .hcf_reqh = &rpc_ctx->hurc_reqh,
238  .hcf_addr = m0_rpc_machine_ep(&rpc_ctx->hurc_rpc_machine),
239  .hcf_process_fid = M0_FID_TINIT('r', 1, 2),
240  };
241  rc = m0_ha_init(ha, &ha_cfg);
242  M0_UT_ASSERT(rc == 0);
243  rc = m0_ha_start(ha);
244  M0_UT_ASSERT(rc == 0);
245 
246  ctx->huc_link_out = m0_ha_connect(ha);
247  M0_UT_ASSERT(ctx->huc_link_out != NULL);
248  M0_UT_ASSERT(ctx->huc_entrypoint_request_nr == 1);
249  M0_UT_ASSERT(ctx->huc_entrypoint_replied_nr == 1);
250  M0_UT_ASSERT(ctx->huc_link_connected_nr == 1);
251  ctx->huc_entrypoint_request_nr = 0;
252  ctx->huc_entrypoint_replied_nr = 0;
253  ctx->huc_link_connected_nr = 0;
254 
255  /* reconnect: both are alive */
256  wait_ctx = (struct ha_ut_wait_ctx){
257  .huw_ha = ha,
258  .huw_entrypoint_client = &ha->h_entrypoint_client,
259  };
260  clink = &wait_ctx.huw_clink;
263  &ha->h_entrypoint_client),
264  clink);
269  M0_UT_ASSERT(ctx->huc_entrypoint_request_nr == 1);
270  M0_UT_ASSERT(ctx->huc_entrypoint_replied_nr == 1);
271  M0_UT_ASSERT(ctx->huc_link_reused_nr == 1);
272  ctx->huc_entrypoint_request_nr = 0;
273  ctx->huc_entrypoint_replied_nr = 0;
274  ctx->huc_link_reused_nr = 0;
275 
276  /* reconnect: m0d reconnect case */
277  m0_ha_disconnect(ha);
278  ctx->huc_link_out = m0_ha_connect(ha);
279  m0_ha_disconnect(ha);
280  M0_UT_ASSERT(ctx->huc_entrypoint_request_nr == 1);
281  M0_UT_ASSERT(ctx->huc_entrypoint_replied_nr == 1);
282  M0_UT_ASSERT(ctx->huc_link_connected_nr == 1);
283  M0_UT_ASSERT(ctx->huc_link_reused_nr == 0);
284 
285  m0_ha_stop(ha);
286  M0_UT_ASSERT(ctx->huc_link_is_disconnecting_nr == 2);
287  M0_UT_ASSERT(ctx->huc_link_disconnected_nr == 2);
288  m0_ha_fini(ha);
289 
290  M0_UT_ASSERT(ctx->huc_link_in1 == NULL);
291  M0_UT_ASSERT(ctx->huc_link_in2 == NULL);
292  m0_mutex_fini(&ctx->huc_lock);
293  m0_free(ctx);
295  m0_free(rpc_ctx);
296  m0_free(msg);
297 }
298 
299 #undef M0_TRACE_SUBSYSTEM
300 
303 /*
304  * Local variables:
305  * c-indentation-style: "K&R"
306  * c-basic-offset: 8
307  * tab-width: 8
308  * fill-column: 80
309  * scroll-step: 1
310  * End:
311  */
312 /*
313  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
314  */
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
static void ha_ut_usecase_link_disconnected(struct m0_ha *ha, struct m0_ha_link *hl)
Definition: ha.c:178
struct m0_ha_entrypoint_client h_entrypoint_client
Definition: ha.h:303
struct m0_mutex huc_lock
Definition: ha.c:44
static void ha_ut_usecase_link_check(struct ha_ut_usecase_ctx *huc, struct m0_ha_link *hl)
Definition: ha.c:71
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
int huc_msg_received_nr
Definition: ha.c:51
#define NULL
Definition: misc.h:38
M0_INTERNAL struct m0_ha_link * m0_ha_connect(struct m0_ha *ha)
Definition: ha.c:687
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
M0_INTERNAL void m0_ha_fini(struct m0_ha *ha)
Definition: ha.c:679
static struct io_request req
Definition: file.c:100
static uint64_t tag(uint8_t code, uint64_t id)
Definition: addb2.c:1047
#define M0_FID_INIT(container, key)
Definition: fid.h:84
M0_INTERNAL int m0_ha_start(struct m0_ha *ha)
Definition: ha.c:659
static void ha_ut_usecase_msg_is_not_delivered(struct m0_ha *ha, struct m0_ha_link *hl, uint64_t tag)
Definition: ha.c:139
int huc_link_reused_nr
Definition: ha.c:55
M0_INTERNAL void m0_ha_ut_rpc_ctx_init(struct m0_ha_ut_rpc_ctx *ctx)
Definition: helper.c:41
int huc_entrypoint_request_nr
Definition: ha.c:49
struct m0_ha_ops hcf_ops
Definition: ha.h:273
#define container_of(ptr, type, member)
Definition: misc.h:33
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_INTERNAL void m0_ha_entrypoint_client_request(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:708
M0_INTERNAL const char * m0_rpc_machine_ep(const struct m0_rpc_machine *rmach)
Definition: rpc_machine.c:603
struct m0_fop_getxattr_rep * rep
Definition: dir.c:455
static void ha_ut_usecase_msg_is_delivered(struct m0_ha *ha, struct m0_ha_link *hl, uint64_t tag)
Definition: ha.c:133
static void ha_ut_usecase_entrypoint_replied(struct m0_ha *ha, struct m0_ha_entrypoint_rep *rep)
Definition: ha.c:113
void(* hao_entrypoint_request)(struct m0_ha *ha, const struct m0_ha_entrypoint_req *req, const struct m0_uint128 *req_id)
Definition: ha.h:241
M0_INTERNAL void m0_ha_disconnect(struct m0_ha *ha)
Definition: ha.c:707
static void ha_ut_usecase_link_reused(struct m0_ha *ha, const struct m0_uint128 *req_id, struct m0_ha_link *hl)
Definition: ha.c:156
M0_INTERNAL void m0_ha_stop(struct m0_ha *ha)
Definition: ha.c:672
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
int huc_link_disconnected_nr
Definition: ha.c:57
struct m0_ha_link * huc_link_in1
Definition: ha.c:46
struct m0_ha_link * huc_link_in2
Definition: ha.c:47
int huc_msg_is_not_delivered_nr
Definition: ha.c:53
struct m0_ha_link * huc_link_out
Definition: ha.c:48
static void ha_ut_usecase_link_connected(struct m0_ha *ha, const struct m0_uint128 *req_id, struct m0_ha_link *hl)
Definition: ha.c:145
static void ha_ut_usecase_entrypoint_request(struct m0_ha *ha, const struct m0_ha_entrypoint_req *req, const struct m0_uint128 *req_id)
Definition: ha.c:88
struct m0_ha huc_ha
Definition: ha.c:45
struct m0_ha_entrypoint_client * huw_entrypoint_client
Definition: ha.c:62
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
Definition: msg.h:115
static void ha_ut_usecase_link_is_disconnecting(struct m0_ha *ha, struct m0_ha_link *hl)
Definition: ha.c:167
struct m0_clink huw_clink
Definition: ha.c:63
static struct ha_ut_usecase_ctx * ha_ut_ha2usecase_ctx(struct m0_ha *ha)
Definition: ha.c:66
static struct m0_clink clink[RDWR_REQUEST_MAX]
int huc_entrypoint_replied_nr
Definition: ha.c:50
static struct fdmi_ctx ctx
Definition: main.c:80
M0_INTERNAL void m0_ha_disconnect_incoming(struct m0_ha *ha, struct m0_ha_link *hl)
Definition: ha.c:714
Definition: ha.h:289
struct m0_ha * huw_ha
Definition: ha.c:61
M0_INTERNAL void m0_ha_ut_rpc_ctx_fini(struct m0_ha_ut_rpc_ctx *ctx)
Definition: helper.c:73
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
void m0_clink_add_lock(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:255
static bool ha_ut_ha_wait_available(struct m0_clink *clink)
Definition: ha.c:193
void m0_ha_ut_ha_usecase(void)
Definition: ha.c:213
M0_INTERNAL int m0_ha_init(struct m0_ha *ha, struct m0_ha_cfg *ha_cfg)
Definition: ha.c:641
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
int huc_msg_is_delivered_nr
Definition: ha.c:52
int huc_link_is_disconnecting_nr
Definition: ha.c:56
Definition: ha.h:272
Definition: ha.h:239
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
M0_INTERNAL struct m0_chan * m0_ha_entrypoint_client_chan(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:823
static void ha_ut_usecase_msg_received(struct m0_ha *ha, struct m0_ha_link *hl, struct m0_ha_msg *msg, uint64_t tag)
Definition: ha.c:126
static const struct m0_ha_ops ha_ut_usecase_ha_ops
Definition: ha.c:201
int huc_link_connected_nr
Definition: ha.c:54
void m0_ha_entrypoint_reply(struct m0_ha *ha, const struct m0_uint128 *req_id, const struct m0_ha_entrypoint_rep *rep, struct m0_ha_link **hl_ptr)
Definition: ha.c:844
Definition: nucleus.c:42
void m0_free(void *data)
Definition: memory.c:146
Definition: mutex.h:47
uint32_t sm_state
Definition: sm.h:307
int32_t rc
Definition: trigger_fop.h:47
#define M0_UT_ASSERT(a)
Definition: ut.h:46