Motr  M0
rcv_session.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 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_UT
24 #include "lib/trace.h"
25 
26 #include "conf/rconfc_internal.h"
27 #include "conf/helpers.h" /* m0_confc_expired_cb */
28 #include "lib/finject.h"
29 #include "lib/misc.h" /* M0_BITS */
30 #include "lib/memory.h"
31 #include "ut/ut.h"
32 #include "rpc/rpclib.h"
33 #include "rpc/ut/clnt_srv_ctx.c" /* sctx, cctx. NOTE: This is .c file */
34 #include "rpc/ut/fops.h"
35 #include "rpc/rpc_internal.h"
36 
37 static struct m0_rpc_machine *machine;
38 static const char *remote_addr;
39 
40 enum {
41  TIMEOUT = 4 /* second */,
42 };
43 
44 static int ts_rcv_session_init(void) /* ts_ for "test suite" */
45 {
49  return 0;
50 }
51 
52 static int ts_rcv_session_fini(void)
53 {
55  return 0;
56 }
57 
58 struct fp {
59  const char *fn;
60  const char *pt;
61  int erc; /* expected rc */
62 };
63 
65 {
66  int *pcount = data;
67 
68  return ++*pcount > 1;
69 }
70 
71 static void test_conn_establish(void)
72 {
73  struct m0_net_end_point *ep;
74  struct m0_rpc_conn conn;
75  int count;
76  int rc;
77  int i;
78  struct fp fps1[] = {
79  {"session_gen_fom_create", "reply_fop_alloc_failed"},
80  {"m0_rpc_fom_conn_establish_tick", "conn-alloc-failed" },
81  };
82  struct fp fps2[] = {
83  {"rpc_chan_get", "fake_error" },
84  {"session_zero_attach", "out-of-memory"},
85  };
86 
88  M0_UT_ASSERT(rc == 0);
89 
90  /* TEST: Connection established successfully */
93  M0_UT_ASSERT(rc == 0);
95  M0_UT_ASSERT(rc == 0);
96 
97  /* TEST: Duplicate conn-establish requests are accepted but only
98  one of them gets executed and rest of them are ignored.
99  */
100  m0_fi_enable_once("m0_rpc_fom_conn_establish_tick", "sleep-for-resend");
101  m0_fi_enable("m0_rpc_fom_conn_establish_tick", "free-timer");
103  M0_TIME_NEVER);
104  M0_UT_ASSERT(rc == 0);
105 
107  M0_UT_ASSERT(rc == 0);
108 
109  for (i = 0; i < ARRAY_SIZE(fps1); ++i) {
110  m0_fi_enable(fps1[i].fn, fps1[i].pt);
114  m0_fi_disable(fps1[i].fn, fps1[i].pt);
115  M0_UT_ASSERT(rc == -ETIMEDOUT);
116  }
117  for (i = 0; i < ARRAY_SIZE(fps2); ++i) {
118  count = 0;
119  m0_fi_enable_func(fps2[i].fn, fps2[i].pt,
124  m0_fi_disable(fps2[i].fn, fps2[i].pt);
125  M0_UT_ASSERT(rc == -ETIMEDOUT);
126  }
128 }
129 
130 static void test_session_establish(void)
131 {
132  struct m0_net_end_point *ep;
133  struct m0_rpc_session session;
134  struct m0_rpc_conn conn;
135  int rc;
136  int i;
137  struct fp fps[] = {
138  {"session_gen_fom_create", "reply_fop_alloc_failed",
139  -ETIMEDOUT},
140  {"m0_rpc_fom_session_establish_tick",
141  "session-alloc-failed", -ENOMEM},
142  };
144  M0_UT_ASSERT(rc == 0);
145 
146  /* TEST1: Connection established successfully */
149  M0_UT_ASSERT(rc == 0);
152  M0_UT_ASSERT(rc == 0);
154  M0_UT_ASSERT(rc == 0);
155 
156  for (i = 0; i < ARRAY_SIZE(fps); ++i) {
157  m0_fi_enable(fps[i].fn, fps[i].pt);
160  M0_UT_ASSERT(rc == fps[i].erc);
161  m0_fi_disable(fps[i].fn, fps[i].pt);
162  }
163 
165  M0_UT_ASSERT(rc == 0);
166 
168 }
169 
170 static void test_session_terminate(void)
171 {
172  struct m0_net_end_point *ep;
173  struct m0_rpc_session session;
174  struct m0_rpc_conn conn;
175  int rc;
176  int i;
177  struct fp fps[] = {
178  {"session_gen_fom_create", "reply_fop_alloc_failed",
179  -ETIMEDOUT},
180  };
182  M0_UT_ASSERT(rc == 0);
183 
184  /* TEST1: Connection established successfully */
187  M0_UT_ASSERT(rc == 0);
188  for (i = 0; i < ARRAY_SIZE(fps); ++i) {
191  M0_UT_ASSERT(rc == 0);
192 
193  m0_fi_enable(fps[i].fn, fps[i].pt);
196  M0_UT_ASSERT(rc == fps[i].erc);
197  m0_fi_disable(fps[i].fn, fps[i].pt);
198  /*
199  Q: How to handle following scenario:
200  - sender establishes one RPC connection with receiver
201  - sender creates one RPC session
202  - sender wants to terminate session:
203  -- sender sends SESSION_TERMINATE request
204  -- the request fails without any reply (consider
205  because fom alloc failed)
206  - sender side session moves to FAILED state, but
207  receiver side session is still active
208  - sender moves on to terminate conn
209  - sender sends CONN_TERMINATE fop
210  - the CONN_TERMINATE request gets accepted by receiver but
211  conn cannot be terminated because there is still active
212  session; reciever replies as -EBUSY
213  A. One possible way is, while processing CONN_TERMINATE
214  request, receiver simply aborts all sessions within it.
215  Temporarily implemented this behavior.
216  */
217  }
218 
220  M0_UT_ASSERT(rc == 0);
221 
223 }
224 
225 static void test_conn_terminate(void)
226 {
227  struct m0_net_end_point *ep;
228  struct m0_rpc_conn conn;
229  int rc;
230  int i;
231  struct fp fps[] = {
232  {"session_gen_fom_create", "reply_fop_alloc_failed",
233  -ETIMEDOUT},
234  };
235 
237  M0_UT_ASSERT(rc == 0);
238 
239  for (i = 0; i < ARRAY_SIZE(fps); ++i) {
243  M0_UT_ASSERT(rc == 0);
244  m0_fi_enable(fps[i].fn, fps[i].pt);
246  M0_UT_ASSERT(rc == fps[i].erc);
247  m0_fi_disable(fps[i].fn, fps[i].pt);
248  }
250 }
251 
253 
255 {
256  struct m0_net_end_point *ep;
257  struct m0_rpc_conn conn;
258  struct rlock_ctx *rlx;
259  struct m0_rconfc *rconfc;
260  struct m0_fid profile = M0_FID_TINIT('p', 1, 0);
261  struct m0_conf_obj *svc_obj = NULL;
262  int rc;
263 
268  M0_UT_ASSERT(rc == 0);
270  M0_UT_ASSERT(rc == 0);
271  M0_LOG(M0_DEBUG, "rconfc_init %p", rconfc);
273  M0_UT_ASSERT(rc == 0);
275  remote_addr, &svc_obj);
276  M0_UT_ASSERT(rc == 0);
277  M0_ASSERT(svc_obj != NULL);
278  rc = m0_rpc_conn_create(&conn, &svc_obj->co_id, ep, machine,
281  M0_UT_ASSERT(rc == 0);
282  M0_UT_ASSERT(svc_obj->co_ha_chan.ch_waiters == 1);
283  rlx = rconfc->rc_rlock_ctx;
287  M0_TIME_NEVER);
290  /*
291  * Check that conn is still subscribed after fetching new configuration
292  */
294  remote_addr, &svc_obj);
295  M0_UT_ASSERT(rc == 0);
296  M0_ASSERT(svc_obj != NULL);
297  M0_UT_ASSERT(svc_obj->co_ha_chan.ch_waiters == 1);
299  M0_UT_ASSERT(rc == 0);
300  M0_UT_ASSERT(svc_obj->co_ha_chan.ch_waiters == 0);
304 }
305 
307  .ts_name = "rpc-rcv-session-ut",
308  .ts_init = ts_rcv_session_init,
309  .ts_fini = ts_rcv_session_fini,
310  .ts_tests = {
311  { "conn-establish", test_conn_establish },
312  { "session-establish", test_session_establish},
313  { "session-terminate", test_session_terminate},
314  { "conn-terminate", test_conn_terminate },
315  { "conn-ha-subscribe", test_conn_ha_subscribe},
316  { NULL, NULL },
317  }
318 };
319 
320 #undef M0_TRACE_SUBSYSTEM
321 
322 /*
323  * Local variables:
324  * c-indentation-style: "K&R"
325  * c-basic-offset: 8
326  * tab-width: 8
327  * fill-column: 80
328  * scroll-step: 1
329  * End:
330  */
331 /*
332  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
333  */
struct m0_fid co_id
Definition: obj.h:208
struct m0_sm rc_sm
Definition: rconfc.h:247
void(* rio_conflict)(struct m0_rm_incoming *in)
Definition: rm.h:1498
#define NULL
Definition: misc.h:38
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
M0_INTERNAL int m0_rpc_session_create(struct m0_rpc_session *session, struct m0_rpc_conn *conn, m0_time_t abs_timeout)
Definition: session.c:352
#define M0_LOG(level,...)
Definition: trace.h:167
int m0_rpc_session_destroy(struct m0_rpc_session *session, m0_time_t abs_timeout)
Definition: session.c:559
struct m0_bufvec data
Definition: di.c:40
M0_INTERNAL void m0_rconfc_stop_sync(struct m0_rconfc *rconfc)
Definition: rconfc.c:2995
static struct m0_rpc_client_ctx cctx
Definition: rconfc.c:69
#define M0_BITS(...)
Definition: misc.h:236
int erc
Definition: rcv_session.c:61
static struct m0_rpc_session session
Definition: formation2.c:38
static const char * remote_addr
Definition: rcv_session.c:38
Definition: ut.h:77
const char * pt
Definition: rcv_session.c:60
static m0_bcount_t count
Definition: xcode.c:167
M0_INTERNAL int m0_sm_timedwait(struct m0_sm *mach, uint64_t states, m0_time_t deadline)
Definition: sm.c:387
Definition: sock.c:754
M0_INTERNAL int m0_confc_service_find(struct m0_confc *confc, enum m0_conf_service_type stype, const char *ep, struct m0_conf_obj **result)
Definition: helpers.c:304
M0_INTERNAL void m0_sm_group_unlock(struct m0_sm_group *grp)
Definition: sm.c:96
M0_INTERNAL struct m0_fid * m0_reqh2profile(struct m0_reqh *reqh)
Definition: reqh.c:758
int i
Definition: dir.c:1033
M0_INTERNAL int m0_rpc_conn_create(struct m0_rpc_conn *conn, struct m0_fid *svc_fid, struct m0_net_end_point *ep, struct m0_rpc_machine *rpc_machine, uint64_t max_rpcs_in_flight, m0_time_t abs_timeout)
Definition: conn.c:809
static int ts_rcv_session_init(void)
Definition: rcv_session.c:44
M0_INTERNAL struct m0_confc * m0_reqh2confc(struct m0_reqh *reqh)
Definition: reqh.c:753
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
M0_EXTERN struct m0_rm_incoming_ops m0_rconfc_ri_ops
Definition: rcv_session.c:252
M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
Definition: finject.c:485
static void m0_fi_enable(const char *func, const char *tag)
Definition: finject.h:276
static int ts_rcv_session_fini(void)
Definition: rcv_session.c:52
struct m0_net_transfer_mc rm_tm
Definition: rpc_machine.h:88
static void test_session_establish(void)
Definition: rcv_session.c:130
#define M0_ASSERT(cond)
struct m0_rm_incoming rlc_req
static void m0_fi_enable_func(const char *func, const char *tag, m0_fi_fpoint_state_func_t trigger_func, void *data)
Definition: finject.h:387
struct m0_ut_suite rpc_rcv_session_ut
Definition: rcv_session.c:306
int m0_rpc_conn_destroy(struct m0_rpc_conn *conn, m0_time_t abs_timeout)
Definition: conn.c:974
static void test_session_terminate(void)
Definition: rcv_session.c:170
static void stop_rpc_client_and_server(void)
Definition: note.c:126
static struct m0_rpc_machine * machine
Definition: rcv_session.c:37
struct m0_sm_group * sm_grp
Definition: sm.h:321
static int m0_rconfc_start_sync(struct m0_rconfc *rconfc)
Definition: rconfc.h:502
struct m0_chan co_ha_chan
Definition: obj.h:248
static void test_conn_terminate(void)
Definition: rcv_session.c:225
struct m0_rpc_conn conn
Definition: fsync.c:96
static void test_conn_ha_subscribe()
Definition: rcv_session.c:254
M0_INTERNAL void m0_rconfc_fini(struct m0_rconfc *rconfc)
Definition: rconfc.c:3009
void m0_net_end_point_put(struct m0_net_end_point *ep)
Definition: ep.c:98
const char * ts_name
Definition: ut.h:99
static void test_conn_establish(void)
Definition: rcv_session.c:71
static struct m0_fid profile
Definition: rconfc.c:49
char * ep
Definition: sw.h:132
uint32_t ch_waiters
Definition: chan.h:236
M0_INTERNAL struct m0_locality * m0_locality0_get(void)
Definition: locality.c:169
Definition: fid.h:38
const char * fn
Definition: rcv_session.c:59
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
const char * rcx_remote_addr
Definition: rpclib.h:134
void * rc_rlock_ctx
Definition: rconfc.h:353
M0_INTERNAL void m0_sm_group_lock(struct m0_sm_group *grp)
Definition: sm.c:83
static void m0_fi_enable_once(const char *func, const char *tag)
Definition: finject.h:301
static struct m0_rconfc * rconfc(struct m0_client *m0c)
Definition: client_init.c:310
static bool enable_for_all_but_first_call(void *data)
Definition: rcv_session.c:64
struct m0_rconfc rh_rconfc
Definition: reqh.h:166
struct m0_rpc_machine rcx_rpc_machine
Definition: rpclib.h:145
M0_INTERNAL void m0_confc_ready_cb(struct m0_rconfc *rconfc)
Definition: helpers.c:488
M0_INTERNAL int m0_rconfc_init(struct m0_rconfc *rconfc, const struct m0_fid *profile, struct m0_sm_group *sm_group, struct m0_rpc_machine *rmach, m0_rconfc_cb_t expired_cb, m0_rconfc_cb_t ready_cb)
Definition: rconfc.c:2860
Definition: rcv_session.c:58
M0_INTERNAL void m0_confc_expired_cb(struct m0_rconfc *rconfc)
Definition: helpers.c:465
struct m0_reqh rcx_reqh
Definition: rpclib.h:144
uint32_t sm_state
Definition: sm.h:307
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL int m0_net_end_point_create(struct m0_net_end_point **epp, struct m0_net_transfer_mc *tm, const char *addr)
Definition: ep.c:56
#define ARRAY_SIZE(a)
Definition: misc.h:45
static void start_rpc_client_and_server(void)
Definition: note.c:111
#define M0_UT_ASSERT(a)
Definition: ut.h:46