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 
42 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_HA
43 #include "lib/trace.h"
44 
45 #include "ha/ha.h"
46 
47 #include "lib/memory.h" /* M0_ALLOC_PTR */
48 #include "lib/errno.h" /* ENOMEM */
49 #include "lib/misc.h" /* M0_IS0 */
50 #include "lib/semaphore.h" /* m0_semaphore */
51 #include "lib/string.h" /* m0_strdup */
52 
53 #include "module/instance.h" /* m0_get */
54 #include "module/module.h" /* m0_module */
55 
56 #include "ha/link.h" /* m0_ha_link */
57 #include "ha/link_service.h" /* m0_ha_link_service_init */
58 #include "ha/entrypoint.h" /* m0_ha_entrypoint_rep */
59 
60 #include "conf/obj.h" /* M0_CONF_PROCESS_TYPE */
61 
62 enum {
68 };
69 
70 struct m0_ha_module {
72 };
73 
77 };
78 
79 struct ha_link_ctx {
81  /* clink for events */
83  struct m0_ha *hlx_ha;
85  uint64_t hlx_magic;
90  /* protected by m0_ha::h_lock */
92 };
93 
94 M0_TL_DESCR_DEFINE(ha_links, "m0_ha::h_links_{incoming,outgoing}", static,
95  struct ha_link_ctx, hlx_tlink, hlx_magic,
96  7, 8);
97 M0_TL_DEFINE(ha_links, static, struct ha_link_ctx);
98 
99 static bool ha_link_event_cb(struct m0_clink *clink)
100 {
101  enum m0_ha_link_state state;
102  struct ha_link_ctx *hlx;
103  struct m0_ha_link *hl;
104  struct m0_ha_msg *msg;
105  struct m0_ha *ha;
106  uint64_t tag;
107 
108  hlx = container_of(clink, struct ha_link_ctx, hlx_clink);
109  hl = &hlx->hlx_link;
110  ha = hlx->hlx_ha;
111  state = m0_ha_link_state_get(hl);
112  M0_ENTRY("hlx=%p hl=%p ha=%p state=%d state_name=%s",
113  hlx, hl, ha, state, m0_ha_link_state_name(state));
114  switch (state) {
116  while ((msg = m0_ha_link_recv(hl, &tag)) != NULL)
117  ha->h_cfg.hcf_ops.hao_msg_received(ha, hl, msg, tag);
118  break;
120  while ((tag = m0_ha_link_delivered_consume(hl)) !=
122  ha->h_cfg.hcf_ops.hao_msg_is_delivered(ha, hl, tag);
123  }
124  while ((tag = m0_ha_link_not_delivered_consume(hl)) !=
127  }
128  break;
130  if (hl == ha->h_link) {
131  /*
132  * Outgoing HA link reconnect via requesting
133  * an entrypoint.
134  */
136  &ha->h_entrypoint_client);
137  } else {
138  /* XXX */
139  }
140  break;
142  if (hlx == ha->h_link_ctx) {
144  } else {
145  ha->h_cfg.hcf_ops.
146  hao_link_is_disconnecting(ha, &hlx->hlx_link);
147  }
148  break;
150  if (hlx != ha->h_link_ctx) {
152  &hlx->hlx_link);
153  }
154  break;
155  default:
156  /* nothing to do here */
157  break;
158  }
159  M0_LEAVE();
160  return true;
161 }
162 
163 static struct ha_link_ctx *
165  const struct m0_ha_link_params *lp)
166 {
168 
169  return m0_tl_find(ha_links, hlx, &ha->h_links_incoming,
170  m0_uint128_eq(&hlx->hlx_link.hln_conn_cfg.hlcc_params.hlp_id_local,
171  &lp->hlp_id_remote) &&
172  m0_uint128_eq(&hlx->hlx_link.hln_conn_cfg.hlcc_params.hlp_id_remote,
173  &lp->hlp_id_local));
174 }
175 
176 static bool ha_link_stop_cb(struct m0_clink *clink)
177 {
178  struct ha_link_ctx *hlx;
179 
182  return true;
183 }
184 
185 static int ha_link_ctx_init(struct m0_ha *ha,
186  struct ha_link_ctx *hlx,
187  struct m0_ha_link_cfg *hl_cfg,
188  const struct m0_ha_link_conn_cfg *hl_conn_cfg,
189  const struct m0_fid *process_fid,
191 {
192  struct m0_ha_link *hl = &hlx->hlx_link;
193  int rc;
194 
195  M0_ENTRY("ha=%p hlx=%p hlx_type=%d", ha, hlx, hlx_type);
196 
197  M0_PRE(M0_IN(hlx_type, (HLX_INCOMING, HLX_OUTGOING)));
198  M0_PRE(equi(hlx_type == HLX_INCOMING, hl_conn_cfg != NULL));
199 
200  rc = m0_ha_link_init(hl, hl_cfg);
201  M0_ASSERT(rc == 0);
202  rc = m0_semaphore_init(&hlx->hlx_stop_sem, 0);
203  M0_ASSERT(rc == 0); /* XXX */
207  hlx->hlx_stop_clink.cl_is_oneshot = true;
208  hlx->hlx_disconnecting = hlx_type == HLX_OUTGOING;
210 
211  hlx->hlx_ha = ha;
212  hlx->hlx_type = hlx_type;
213  m0_mutex_lock(&ha->h_lock);
214  M0_ASSERT(ergo(hlx_type == HLX_INCOMING,
215  ha_link_incoming_find(ha, &hl_conn_cfg->hlcc_params) ==
216  NULL));
217  ha_links_tlink_init_at_tail(hlx, hlx_type == HLX_INCOMING ?
218  &ha->h_links_incoming :
219  &ha->h_links_outgoing);
220  m0_mutex_unlock(&ha->h_lock);
221 
222  return M0_RC(0);
223 }
224 
225 static void ha_link_ctx_fini(struct m0_ha *ha, struct ha_link_ctx *hlx)
226 {
227  M0_ENTRY("ha=%p hlx=%p", ha, hlx);
228 
231  ha_links_tlist_contains(&ha->h_links_stopping, hlx)));
232 
233  ha_links_tlink_del_fini(hlx);
234 
238  m0_clink_fini(&hlx->hlx_clink);
240  m0_ha_link_fini(&hlx->hlx_link);
241  M0_LEAVE();
242 }
243 
244 static uint64_t ha_generation_next(struct m0_ha *ha)
245 {
246  uint64_t generation;
247 
248  m0_mutex_lock(&ha->h_lock);
249  generation = ha->h_generation_counter++;
250  m0_mutex_unlock(&ha->h_lock);
251  return generation;
252 }
253 
254 static void
256  const struct m0_ha_entrypoint_req *req,
257  const struct m0_uint128 *req_id)
258 {
259  struct m0_ha *ha;
260 
261  ha = container_of(hes, struct m0_ha, h_entrypoint_server);
262  M0_ENTRY("ha=%p hes=%p req=%p", ha, hes, req);
263  ha->h_cfg.hcf_ops.hao_entrypoint_request(ha, req, req_id);
264 }
265 
266 static void ha_link_conn_cfg_make(struct m0_ha_link_conn_cfg *hl_conn_cfg,
267  const char *rpc_endpoint)
268 {
269  *hl_conn_cfg = (struct m0_ha_link_conn_cfg) {
271  .hlcc_rpc_endpoint = rpc_endpoint,
272  .hlcc_max_rpcs_in_flight = HA_MAX_RPCS_IN_FLIGHT,
273  .hlcc_connect_timeout = M0_TIME_NEVER,
274  .hlcc_disconnect_timeout = M0_MKTIME(HA_DISCONNECT_TIMEOUT, 0),
275  .hlcc_resend_interval = M0_MKTIME(HA_RESEND_INTERVAL, 0),
276  .hlcc_reconnect_interval = M0_MKTIME(HA_RECONNECT_INTERVAL, 0),
277  .hlcc_nr_sent_max = HA_NR_SENT_MAX,
278  };
279 }
280 
282 {
284  struct m0_ha_entrypoint_client *ecl;
285  struct m0_ha_entrypoint_req *req;
286  struct m0_ha_entrypoint_rep *rep;
287  struct m0_ha_link_conn_cfg hl_conn_cfg;
288  struct m0_ha_link *hl;
289  struct m0_ha *ha;
290  bool consumed = true;
291 
292  M0_ENTRY();
293 
294  ha = container_of(clink, struct m0_ha, h_clink);
295  ecl = &ha->h_entrypoint_client;
299  M0_LOG(M0_DEBUG, "ha=%p ecl=%p state=%d", ha, ecl, state);
300 
301  switch (state) {
302  case M0_HEC_AVAILABLE:
303  M0_LOG(M0_DEBUG, "ha=%p hae_contol=%d", ha, rep->hae_control);
304  M0_ASSERT_INFO(!rep->hae_disconnected_previously,
305  "HA has already decided that this process has "
306  "failed. There is no good reason to continue "
307  "doing something, and there is no code yet "
308  "to handle graceful shutdown in this case. "
309  "Let's just terminate the process and let HA "
310  "do it's job.");
311  M0_ASSERT(equi(!rep->hae_link_do_reconnect,
315  &rep->hae_cookie_actual)));
316  ha->h_cookie_remote = rep->hae_cookie_actual;
317  ha_link_conn_cfg_make(&hl_conn_cfg, ha->h_cfg.hcf_addr);
318  hl_conn_cfg.hlcc_params = rep->hae_link_params;
319  hl = &ha->h_link_ctx->hlx_link;
320  if (req->heq_first_request) {
321  M0_ASSERT(!rep->hae_link_do_reconnect);
322  m0_ha_link_start(hl, &hl_conn_cfg);
323  ha->h_link_started = true;
324  req->heq_first_request = false;
325  } else {
326  if (rep->hae_link_do_reconnect) {
327  m0_ha_link_reconnect_end(hl, &hl_conn_cfg);
328  } else {
330  }
331  }
332  if (rep->hae_control == M0_HA_ENTRYPOINT_QUERY) {
333  /*
334  * XXX: it looks like delay belongs here, or maybe
335  * m0_ha_entrypoint_client_request() itself should
336  * implement deferred request somehow.
337  */
339  } else {
341  consumed = false;
342  }
343  break;
344  case M0_HEC_UNAVAILABLE:
346  break;
347  case M0_HEC_FILL:
348  req->heq_generation = ha_generation_next(ha);
349  req->heq_cookie_expected = ha->h_cookie_remote;
350  if (!req->heq_first_request) {
352  &req->heq_link_params);
353  }
354  break;
355  default:
356  break;
357  }
358  M0_LEAVE();
359  return consumed;
360 }
361 
362 /* tentative definition, isn't possible in C++ */
363 static const struct m0_modlev ha_levels[];
364 
365 static int ha_level_enter(struct m0_module *module)
366 {
367  struct m0_ha_link_cfg hl_cfg;
368  enum m0_ha_level level = module->m_cur + 1;
369  struct m0_ha *ha;
370  char *addr;
371  int rc;
372 
373  ha = container_of(module, struct m0_ha, h_module);
374  M0_ENTRY("ha=%p level=%d %s", ha, level, ha_levels[level].ml_name);
375  switch (level) {
376  case M0_HA_LEVEL_ASSIGNS:
377  m0_mutex_init(&ha->h_lock);
378  ha_links_tlist_init(&ha->h_links_incoming);
379  ha_links_tlist_init(&ha->h_links_outgoing);
380  ha_links_tlist_init(&ha->h_links_stopping);
385  ha->h_link_id_counter = 1;
386  ha->h_generation_counter = 1;
387  ha->h_link_started = false;
388  ha->h_warn_local_link_disconnect = true;
389  return M0_RC(0);
391  addr = m0_strdup(ha->h_cfg.hcf_addr);
392  if (addr == NULL)
393  return M0_ERR(-ENOMEM);
394  ha->h_cfg.hcf_addr = addr;
395  return M0_RC(0);
398  ha->h_cfg.hcf_reqh));
402  .hesc_reqh = ha->h_cfg.hcf_reqh,
403  .hesc_request_received =&ha_request_received_cb,
404  };
406  &ha->h_entrypoint_server,
411  .hecc_reqh = ha->h_cfg.hcf_reqh,
412  .hecc_rpc_machine = ha->h_cfg.hcf_rpc_machine,
413  .hecc_process_fid = ha->h_cfg.hcf_process_fid,
414  };
416  &ha->h_entrypoint_client,
417  ha->h_cfg.hcf_addr,
419  case M0_HA_LEVEL_INIT:
420  M0_IMPOSSIBLE("can't be here");
421  return M0_ERR(-ENOSYS);
424  return M0_RC(0);
426  return M0_RC(0);
427  case M0_HA_LEVEL_START:
428  M0_IMPOSSIBLE("can't be here");
429  return M0_ERR(-ENOSYS);
432  if (ha->h_link_ctx == NULL)
433  return M0_ERR(-ENOMEM);
434  return M0_RC(0);
436  hl_cfg = (struct m0_ha_link_cfg){
437  .hlc_reqh = ha->h_cfg.hcf_reqh,
438  .hlc_reqh_service = ha->h_hl_service,
439  .hlc_rpc_machine = ha->h_cfg.hcf_rpc_machine,
440  .hlq_q_cfg_in = {},
441  .hlq_q_cfg_out = {},
442  };
443  rc = ha_link_ctx_init(ha, ha->h_link_ctx, &hl_cfg, NULL,
445  return rc == 0 ? M0_RC(rc) : M0_ERR(rc);
451  &ha->h_clink);
453  return M0_RC(0);
455  m0_chan_wait(&ha->h_clink);
456  return M0_RC(0);
458  m0_mutex_lock(&ha->h_lock);
459  ha->h_link = &ha->h_link_ctx->hlx_link;
460  m0_mutex_unlock(&ha->h_lock);
461  return M0_RC(0);
462  case M0_HA_LEVEL_CONNECT:
463  M0_IMPOSSIBLE("can't be here");
464  return M0_ERR(-ENOSYS);
465  }
466  return M0_ERR(-ENOSYS);
467 }
468 
469 static void ha_level_leave(struct m0_module *module)
470 {
471  struct ha_link_ctx *hlx;
472  enum m0_ha_level level = module->m_cur;
473  struct m0_ha *ha;
474  struct m0_tl *list;
475 
476  ha = container_of(module, struct m0_ha, h_module);
477  M0_ENTRY("ha=%p level=%d %s", ha, level, ha_levels[level].ml_name);
478  switch (level) {
479  case M0_HA_LEVEL_ASSIGNS:
482  m0_clink_fini(&ha->h_clink);
483  ha_links_tlist_fini(&ha->h_links_stopping);
484  ha_links_tlist_fini(&ha->h_links_outgoing);
485  ha_links_tlist_fini(&ha->h_links_incoming);
486  m0_mutex_fini(&ha->h_lock);
487  break;
489  /* it's OK to free allocated in ha_level_enter() char * */
490  m0_free((char *)ha->h_cfg.hcf_addr);
491  break;
494  break;
497  break;
500  break;
501  case M0_HA_LEVEL_INIT:
502  M0_IMPOSSIBLE("can't be here");
503  break;
506  break;
508  /*
509  * There is situation when m0_ha_process_failed() disconnects
510  * more than one ha_link. Therefore, we need to empty
511  * h_links_incoming first and then check h_links_stopping.
512  */
513  list = &ha->h_links_incoming;
514  while (true) {
515  m0_mutex_lock(&ha->h_lock);
516  hlx = ha_links_tlist_head(list);
517  m0_mutex_unlock(&ha->h_lock);
518  if (hlx == NULL && list == &ha->h_links_incoming) {
519  list = &ha->h_links_stopping;
520  continue;
521  }
522  if (hlx == NULL && list == &ha->h_links_stopping)
523  break;
524  M0_LOG(M0_DEBUG, "hlx=%p", hlx);
525  if (list == &ha->h_links_incoming)
528  m0_mutex_lock(&ha->h_lock);
529  ha_link_ctx_fini(ha, hlx);
530  m0_mutex_unlock(&ha->h_lock);
531  m0_free(hlx);
532  }
533  break;
534  case M0_HA_LEVEL_START:
535  M0_IMPOSSIBLE("can't be here");
536  break;
538  m0_free(ha->h_link_ctx);
539  break;
541  ha->h_warn_local_link_disconnect = false;
542  /* @see ha_entrypoint_state_cb for m0_ha_link_start() */
543  if (ha->h_link_started) {
546  }
547  m0_mutex_lock(&ha->h_lock);
548  ha_link_ctx_fini(ha, ha->h_link_ctx);
549  m0_mutex_unlock(&ha->h_lock);
550  break;
553  break;
556  break;
558  m0_mutex_lock(&ha->h_lock);
559  ha->h_link = NULL;
560  m0_mutex_unlock(&ha->h_lock);
561  break;
562  case M0_HA_LEVEL_CONNECT:
563  M0_IMPOSSIBLE("can't be here");
564  break;
565  }
566  M0_LEAVE();
567 }
568 
569 static const struct m0_modlev ha_levels[] = {
570  [M0_HA_LEVEL_ASSIGNS] = {
571  .ml_name = "M0_HA_LEVEL_ASSIGNS",
572  .ml_enter = ha_level_enter,
573  .ml_leave = ha_level_leave,
574  },
576  .ml_name = "M0_HA_LEVEL_ADDR_STRDUP",
577  .ml_enter = ha_level_enter,
578  .ml_leave = ha_level_leave,
579  },
581  .ml_name = "M0_HA_LEVEL_LINK_SERVICE",
582  .ml_enter = ha_level_enter,
583  .ml_leave = ha_level_leave,
584  },
586  .ml_name = "M0_HA_LEVEL_ENTRYPOINT_SERVER_INIT",
587  .ml_enter = ha_level_enter,
588  .ml_leave = ha_level_leave,
589  },
591  .ml_name = "M0_HA_LEVEL_ENTRYPOINT_CLIENT_INIT",
592  .ml_enter = ha_level_enter,
593  .ml_leave = ha_level_leave,
594  },
595  [M0_HA_LEVEL_INIT] = {
596  .ml_name = "M0_HA_LEVEL_INIT",
597  },
599  .ml_name = "M0_HA_LEVEL_ENTRYPOINT_SERVER_START",
600  .ml_enter = ha_level_enter,
601  .ml_leave = ha_level_leave,
602  },
604  .ml_name = "M0_HA_LEVEL_INCOMING_LINKS",
605  .ml_enter = ha_level_enter,
606  .ml_leave = ha_level_leave,
607  },
608  [M0_HA_LEVEL_START] = {
609  .ml_name = "M0_HA_LEVEL_START",
610  },
612  .ml_name = "M0_HA_LEVEL_LINK_CTX_ALLOC",
613  .ml_enter = ha_level_enter,
614  .ml_leave = ha_level_leave,
615  },
617  .ml_name = "M0_HA_LEVEL_LINK_CTX_INIT",
618  .ml_enter = ha_level_enter,
619  .ml_leave = ha_level_leave,
620  },
622  .ml_name = "M0_HA_LEVEL_ENTRYPOINT_CLIENT_START",
623  .ml_enter = ha_level_enter,
624  .ml_leave = ha_level_leave,
625  },
627  .ml_name = "M0_HA_LEVEL_ENTRYPOINT_CLIENT_WAIT",
628  .ml_enter = ha_level_enter,
629  .ml_leave = ha_level_leave,
630  },
632  .ml_name = "M0_HA_LEVEL_LINK_ASSIGN",
633  .ml_enter = ha_level_enter,
634  .ml_leave = ha_level_leave,
635  },
636  [M0_HA_LEVEL_CONNECT] = {
637  .ml_name = "M0_HA_LEVEL_CONNECT",
638  },
639 };
640 
641 M0_INTERNAL int m0_ha_init(struct m0_ha *ha, struct m0_ha_cfg *ha_cfg)
642 {
643  int rc;
644 
645  M0_ENTRY("ha=%p hcf_rpc_machine=%p hcf_reqh=%p",
646  ha, ha_cfg->hcf_rpc_machine, ha_cfg->hcf_reqh);
647  M0_PRE(M0_IS0(ha));
648  ha->h_cfg = *ha_cfg;
649  m0_module_setup(&ha->h_module, "m0_ha_module",
652  if (rc != 0) {
654  return M0_ERR(rc);
655  }
656  return M0_RC(0);
657 }
658 
659 M0_INTERNAL int m0_ha_start(struct m0_ha *ha)
660 {
661  int rc;
662 
663  M0_ENTRY("ha=%p", ha);
665  if (rc != 0) {
667  return M0_ERR(rc);
668  }
669  return M0_RC(rc);
670 }
671 
672 M0_INTERNAL void m0_ha_stop(struct m0_ha *ha)
673 {
674  M0_ENTRY("ha=%p", ha);
676  M0_LEAVE();
677 }
678 
679 M0_INTERNAL void m0_ha_fini(struct m0_ha *ha)
680 {
681  M0_ENTRY("ha=%p", ha);
682 
684  M0_LEAVE();
685 }
686 
687 M0_INTERNAL struct m0_ha_link *m0_ha_connect(struct m0_ha *ha)
688 {
689  struct m0_ha_link *hl;
690  int rc;
691 
692  M0_ENTRY("ha=%p hcf_addr=%s", ha, ha->h_cfg.hcf_addr);
694  if (rc == 0) {
695  m0_mutex_lock(&ha->h_lock);
696  hl = ha->h_link;
697  m0_mutex_unlock(&ha->h_lock);
698  } else {
700  M0_LOG(M0_ERROR, "rc=%d", rc);
701  hl = NULL;
702  }
703  M0_LEAVE("ha=%p hcf_addr=%s hl=%p", ha, ha->h_cfg.hcf_addr, hl);
704  return hl;
705 }
706 
707 M0_INTERNAL void m0_ha_disconnect(struct m0_ha *ha)
708 {
709  M0_ENTRY("ha=%p hcf_addr=%s", ha, ha->h_cfg.hcf_addr);
711  M0_LEAVE();
712 }
713 
714 M0_INTERNAL void m0_ha_disconnect_incoming(struct m0_ha *ha,
715  struct m0_ha_link *hl)
716 {
717  struct ha_link_ctx *hlx;
718 
719  hlx = container_of(hl, struct ha_link_ctx, hlx_link);
720  M0_ENTRY("ha=%p hl=%p", ha, hl);
721  M0_PRE(hlx->hlx_type == HLX_INCOMING);
722  m0_mutex_lock(&ha->h_lock);
723  ha_links_tlist_move(&ha->h_links_stopping, hlx);
724  m0_mutex_unlock(&ha->h_lock);
726  M0_LEAVE();
727 }
728 
729 static void ha_link_id_next(struct m0_ha *ha,
730  struct m0_uint128 *id)
731 {
732  *id = M0_UINT128(0, ha->h_link_id_counter++);
733 }
734 
735 static int
737  const struct m0_ha_entrypoint_req *req,
738  struct m0_ha_link_conn_cfg *hl_conn_cfg,
739  struct ha_link_ctx **hlx_ptr)
740 {
741  struct m0_ha_link_cfg hl_cfg;
742  struct ha_link_ctx *hlx;
743  int rc;
744 
745  hl_cfg = (struct m0_ha_link_cfg){
746  .hlc_reqh = ha->h_cfg.hcf_reqh,
747  .hlc_reqh_service = ha->h_hl_service,
748  .hlc_rpc_machine = ha->h_cfg.hcf_rpc_machine,
749  .hlq_q_cfg_in = {},
750  .hlq_q_cfg_out = {},
751  };
752  M0_ALLOC_PTR(hlx);
753  M0_ASSERT(hlx != NULL); /* XXX */
754  rc = ha_link_ctx_init(ha, hlx, &hl_cfg, hl_conn_cfg,
755  &req->heq_process_fid, HLX_INCOMING);
756  M0_ASSERT(rc == 0); /* XXX */
757  m0_ha_link_start(&hlx->hlx_link, hl_conn_cfg);
758  *hlx_ptr = hlx;
759  return 0;
760 }
761 
762 static void ha_link_handle(struct m0_ha *ha,
763  const struct m0_uint128 *req_id,
764  const struct m0_ha_entrypoint_req *req,
765  struct m0_ha_entrypoint_rep *rep,
766  struct m0_ha_link **hl_ptr)
767 {
768  struct m0_ha_link_conn_cfg hl_conn_cfg;
769  struct ha_link_ctx *hlx;
770  struct m0_uint128 id_local;
771  struct m0_uint128 id_remote;
772  struct m0_uint128 id_connection;
773  uint64_t generation;
774  bool add_new_link;
775  int rc;
776 
777  m0_mutex_lock(&ha->h_lock);
778  hlx = ha_link_incoming_find(ha, &req->heq_link_params);
779  m0_mutex_unlock(&ha->h_lock);
780  M0_LOG(M0_DEBUG, "hlx=%p", hlx);
781  rep->hae_link_do_reconnect = false;
782  rep->hae_disconnected_previously = false;
783  if (hlx == NULL) {
784  ha_link_conn_cfg_make(&hl_conn_cfg, req->heq_rpc_endpoint);
785  generation = ha_generation_next(ha);
786  id_connection = M0_UINT128(req->heq_generation, generation);
787  ha_link_id_next(ha, &id_local);
788  ha_link_id_next(ha, &id_remote);
789  if (req->heq_first_request) {
790  M0_LOG(M0_DEBUG, "first connection to HA");
791  hl_conn_cfg.hlcc_params = (struct m0_ha_link_params){
792  .hlp_id_connection = id_connection,
793  .hlp_id_local = id_local,
794  .hlp_id_remote = id_remote,
795  };
797  &hl_conn_cfg.hlcc_params.hlp_tags_local, false);
799  &hl_conn_cfg.hlcc_params.hlp_tags_remote, true);
800  m0_ha_link_params_invert(&rep->hae_link_params,
801  &hl_conn_cfg.hlcc_params);
802  add_new_link = true;
803  } else if (m0_ha_cookie_is_eq(&ha->h_cookie_local,
804  &req->heq_cookie_expected)) {
805  M0_LOG(M0_DEBUG, "link had been disconnected "
806  "previously, a new one shouldn't be created");
807  rep->hae_disconnected_previously = true;
808  add_new_link = false;
809  } else {
810  M0_LOG(M0_DEBUG, "HA has restarted, reconnect case");
811  m0_ha_link_reconnect_params(&req->heq_link_params,
812  &rep->hae_link_params,
813  &hl_conn_cfg.hlcc_params,
814  &id_remote, &id_local,
815  &id_connection);
816  rep->hae_link_do_reconnect = true;
817  add_new_link = true;
818  }
819  if (add_new_link) {
820  rc = ha_link_incoming_create(ha, req, &hl_conn_cfg, &hlx);
821  M0_ASSERT(rc == 0);
822  ha->h_cfg.hcf_ops.hao_link_connected(ha, req_id,
823  &hlx->hlx_link);
824  } else {
825  ha->h_cfg.hcf_ops.hao_link_absent(ha, req_id);
826  }
827  } else {
828  if (req->heq_first_request) {
829  M0_IMPOSSIBLE("m0d has restarted, new link case. "
830  "Link should already be disconnected.");
831  } else {
832  M0_LOG(M0_DEBUG, "everyone is alive, link is reused");
833  ha->h_cfg.hcf_ops.hao_link_reused(ha, req_id,
834  &hlx->hlx_link);
835  }
836  }
837  rep->hae_cookie_actual = ha->h_cookie_local;
838  if (hl_ptr != NULL)
839  *hl_ptr = hlx == NULL ? NULL : &hlx->hlx_link;
840  M0_LEAVE("ha=%p heq_rpc_endpoint=%s hl=%p",
841  ha, req->heq_rpc_endpoint, &hlx->hlx_link);
842 }
843 
845  const struct m0_uint128 *req_id,
846  const struct m0_ha_entrypoint_rep *rep,
847  struct m0_ha_link **hl_ptr)
848 {
849  struct m0_ha_entrypoint_rep rep_copy = *rep;
850  const struct m0_ha_entrypoint_req *req;
851 
852  M0_ENTRY("ha=%p req_id="U128X_F" rep=%p", ha, U128_P(req_id), rep);
854  req_id);
855  M0_ASSERT(req != NULL);
856  ha_link_handle(ha, req_id, req, &rep_copy, hl_ptr);
858  req_id, &rep_copy);
859  M0_LEAVE();
860 }
861 
862 M0_INTERNAL void m0_ha_send(struct m0_ha *ha,
863  struct m0_ha_link *hl,
864  const struct m0_ha_msg *msg,
865  uint64_t *tag)
866 {
867  m0_ha_link_send(hl, msg, tag);
868 }
869 
870 M0_INTERNAL void m0_ha_delivered(struct m0_ha *ha,
871  struct m0_ha_link *hl,
872  struct m0_ha_msg *msg)
873 {
874  m0_ha_link_delivered(hl, msg);
875 }
876 
883 };
884 
885 static const struct m0_modlev ha_mod_levels[];
886 
887 static int ha_mod_level_enter(struct m0_module *module)
888 {
889  enum m0_ha_mod_level level = module->m_cur + 1;
890  struct m0_ha_module *ha_module;
891 
892  ha_module = container_of(module, struct m0_ha_module, hmo_module);
893  M0_ENTRY("ha_module=%p level=%d %s", ha_module, level,
894  ha_mod_levels[level].ml_name);
895  switch (level) {
897  M0_PRE(m0_get()->i_ha_module == NULL);
898  m0_get()->i_ha_module = ha_module;
899  return M0_RC(0);
901  return M0_RC(m0_ha_link_mod_init());
907  M0_IMPOSSIBLE("can't be here");
908  return M0_ERR(-ENOSYS);
909  }
910  return M0_ERR(-ENOSYS);
911 }
912 
913 static void ha_mod_level_leave(struct m0_module *module)
914 {
915  enum m0_ha_mod_level level = module->m_cur;
916  struct m0_ha_module *ha_module;
917 
918  ha_module = container_of(module, struct m0_ha_module, hmo_module);
919  M0_ENTRY("ha_module=%p level=%d", ha_module, level);
920  switch (level) {
922  m0_get()->i_ha_module = NULL;
923  break;
926  break;
929  break;
932  break;
934  M0_IMPOSSIBLE("can't be here");
935  break;
936  }
937  M0_LEAVE();
938 }
939 
940 static const struct m0_modlev ha_mod_levels[] = {
942  .ml_name = "M0_HA_MOD_LEVEL_ASSIGNS",
943  .ml_enter = ha_mod_level_enter,
944  .ml_leave = ha_mod_level_leave,
945  },
947  .ml_name = "M0_HA_MOD_LEVEL_LINK_SERVICE",
948  .ml_enter = ha_mod_level_enter,
949  .ml_leave = ha_mod_level_leave,
950  },
952  .ml_name = "M0_HA_MOD_LEVEL_LINK",
953  .ml_enter = ha_mod_level_enter,
954  .ml_leave = ha_mod_level_leave,
955  },
957  .ml_name = "M0_HA_MOD_LEVEL_ENTRYPOINT",
958  .ml_enter = ha_mod_level_enter,
959  .ml_leave = ha_mod_level_leave,
960  },
962  .ml_name = "M0_HA_MOD_LEVEL_STARTED",
963  },
964 };
965 
966 M0_INTERNAL void m0_ha_flush(struct m0_ha *ha,
967  struct m0_ha_link *hl)
968 {
969  m0_ha_link_flush(hl);
970 }
971 
972 M0_INTERNAL void m0_ha_process_failed(struct m0_ha *ha,
973  const struct m0_fid *process_fid)
974 {
975  struct ha_link_ctx *hlx;
976  bool disconnecting;
977 
978  M0_ENTRY("ha=%p process_fid="FID_F, ha, FID_P(process_fid));
979  /*
980  * XXX Temporary disable the assert as the process fids are not always
981  * valid in Motr ST.
982  */
983  /*
984  M0_PRE(m0_fid_tget(process_fid) ==
985  M0_CONF_PROCESS_TYPE.cot_ftype.ft_id);
986  */
989  M0_LOG(M0_WARN, "disconnecting local link");
990  m0_mutex_lock(&ha->h_lock);
991  m0_tl_for(ha_links, &ha->h_links_incoming, hlx) {
993  continue;
994  disconnecting = hlx->hlx_disconnecting;
995  hlx->hlx_disconnecting = true;
996  if (!disconnecting)
998  M0_LOG(M0_DEBUG, "ha=%p process_fid="FID_F" hlx=%p "
999  "disconnecting=%d", ha, FID_P(process_fid), hlx,
1000  !!disconnecting);
1001  } m0_tl_endfor;
1002  m0_mutex_unlock(&ha->h_lock);
1003  M0_LEAVE("ha=%p process_fid="FID_F, ha, FID_P(process_fid));
1004 }
1005 
1006 M0_INTERNAL struct m0_ha_link *m0_ha_outgoing_link(struct m0_ha *ha)
1007 {
1008  struct m0_ha_link *hl;
1009 
1010  m0_mutex_lock(&ha->h_lock);
1011  hl = ha->h_link;
1012  m0_mutex_unlock(&ha->h_lock);
1013  return hl;
1014 }
1015 
1016 M0_INTERNAL struct m0_rpc_session *m0_ha_outgoing_session(struct m0_ha *ha)
1017 {
1018  struct ha_link_ctx *hlx;
1019 
1020  hlx = ha_links_tlist_head(&ha->h_links_outgoing);
1021  return m0_ha_link_rpc_session(&hlx->hlx_link);
1022 }
1023 
1024 M0_INTERNAL void m0_ha_rpc_endpoint(struct m0_ha *ha,
1025  struct m0_ha_link *hl,
1026  char *buf,
1027  m0_bcount_t buf_len)
1028 {
1029  m0_ha_link_rpc_endpoint(hl, buf, buf_len);
1030 }
1031 
1032 M0_INTERNAL int m0_ha_mod_init(void)
1033 {
1034  struct m0_ha_module *ha_module;
1035  int rc;
1036 
1037  M0_ALLOC_PTR(ha_module);
1038  if (ha_module == NULL)
1039  return M0_ERR(-ENOMEM);
1040 
1041  m0_module_setup(&ha_module->hmo_module, "m0_ha_mod_module",
1044  if (rc != 0) {
1046  m0_free(ha_module);
1047  return M0_ERR(rc);
1048  }
1049  return M0_RC(0);
1050 }
1051 
1052 M0_INTERNAL void m0_ha_mod_fini(void)
1053 {
1054  struct m0_ha_module *ha_module = m0_get()->i_ha_module;
1055 
1056  M0_PRE(ha_module != NULL);
1057 
1059  m0_free(ha_module);
1060 }
1061 
1062 #undef M0_TRACE_SUBSYSTEM
1063 
1066 /*
1067  * Local variables:
1068  * c-indentation-style: "K&R"
1069  * c-basic-offset: 8
1070  * tab-width: 8
1071  * fill-column: 80
1072  * scroll-step: 1
1073  * End:
1074  */
1075 /*
1076  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
1077  */
ha_link_ctx_type
Definition: ha.c:74
struct m0_tl h_links_outgoing
Definition: ha.h:294
struct m0_ha_link_params heq_link_params
uint64_t h_link_id_counter
Definition: ha.h:306
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
#define M0_PRE(cond)
struct m0_ha_entrypoint_client h_entrypoint_client
Definition: ha.h:303
M0_INTERNAL const struct m0_ha_entrypoint_req * m0_ha_entrypoint_server_request_find(struct m0_ha_entrypoint_server *hes, const struct m0_uint128 *req_id)
Definition: entrypoint.c:322
static const struct m0_modlev ha_mod_levels[]
Definition: ha.c:885
static void ha_level_leave(struct m0_module *module)
Definition: ha.c:469
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
static struct m0_list list
Definition: list.c:144
#define m0_strdup(s)
Definition: string.h:43
m0_ha_link_state
Definition: link.h:143
static bool ha_entrypoint_state_cb(struct m0_clink *clink)
Definition: ha.c:281
#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_ha_link_stop(struct m0_ha_link *hl, struct m0_clink *clink)
Definition: link.c:412
struct m0_mutex h_lock
Definition: ha.h:292
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
struct m0_ha_entrypoint_server_cfg hcf_entrypoint_server_cfg
Definition: ha.h:284
static uint64_t ha_generation_next(struct m0_ha *ha)
Definition: ha.c:244
#define ergo(a, b)
Definition: misc.h:293
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
M0_INTERNAL void m0_ha_rpc_endpoint(struct m0_ha *ha, struct m0_ha_link *hl, char *buf, m0_bcount_t buf_len)
Definition: ha.c:1024
static struct io_request req
Definition: file.c:100
M0_INTERNAL bool m0_uint128_eq(const struct m0_uint128 *u0, const struct m0_uint128 *u1)
Definition: misc.c:39
static uint64_t tag(uint8_t code, uint64_t id)
Definition: addb2.c:1047
struct m0_reqh_service * h_hl_service
Definition: ha.h:302
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
M0_INTERNAL struct m0_ha_msg * m0_ha_link_recv(struct m0_ha_link *hl, uint64_t *tag)
Definition: link.c:568
uint64_t h_generation_counter
Definition: ha.h:307
enum m0_trace_level level
Definition: trace.c:111
void(* hao_link_disconnected)(struct m0_ha *ha, struct m0_ha_link *hl)
Definition: ha.h:266
M0_INTERNAL void m0_ha_entrypoint_server_start(struct m0_ha_entrypoint_server *hes)
Definition: entrypoint.c:241
M0_INTERNAL int m0_ha_start(struct m0_ha *ha)
Definition: ha.c:659
struct m0_ha_cfg h_cfg
Definition: ha.h:290
M0_INTERNAL struct m0_ha_link * m0_ha_outgoing_link(struct m0_ha *ha)
Definition: ha.c:1006
M0_INTERNAL void m0_ha_entrypoint_mod_fini(void)
Definition: entrypoint.c:850
M0_INTERNAL const char * m0_ha_link_state_name(enum m0_ha_link_state state)
Definition: link.c:543
M0_INTERNAL void m0_ha_entrypoint_client_stop(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:785
void(* hao_link_connected)(struct m0_ha *ha, const struct m0_uint128 *req_id, struct m0_ha_link *hl)
Definition: ha.h:256
M0_INTERNAL void m0_ha_send(struct m0_ha *ha, struct m0_ha_link *hl, const struct m0_ha_msg *msg, uint64_t *tag)
Definition: ha.c:862
void(* hao_link_absent)(struct m0_ha *ha, const struct m0_uint128 *req_id)
Definition: ha.h:262
M0_INTERNAL enum m0_ha_entrypoint_client_state m0_ha_entrypoint_client_state_get(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:829
const char * ml_name
Definition: module.h:114
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL struct m0 * m0_get(void)
Definition: instance.c:41
struct m0_ha_ops hcf_ops
Definition: ha.h:273
M0_INTERNAL void m0_ha_cookie_init(struct m0_ha_cookie *hc)
Definition: cookie.c:55
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SET0(obj)
Definition: misc.h:64
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 struct m0_chan * m0_ha_link_chan(struct m0_ha_link *hl)
Definition: link.c:532
M0_INTERNAL void m0_ha_entrypoint_server_reply(struct m0_ha_entrypoint_server *hes, const struct m0_uint128 *req_id, const struct m0_ha_entrypoint_rep *rep)
Definition: entrypoint.c:306
struct m0_fop_getxattr_rep * rep
Definition: dir.c:455
M0_INTERNAL void m0_ha_link_flush(struct m0_ha_link *hl)
Definition: link.c:767
Definition: sock.c:887
struct m0_reqh * hcf_reqh
Definition: ha.h:275
M0_INTERNAL void m0_ha_link_start(struct m0_ha_link *hl, struct m0_ha_link_conn_cfg *hl_conn_cfg)
Definition: link.c:382
M0_INTERNAL enum m0_ha_link_state m0_ha_link_state_get(struct m0_ha_link *hl)
Definition: link.c:537
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
struct m0_reqh * hecc_reqh
Definition: entrypoint.h:102
#define m0_tl_endfor
Definition: tlist.h:700
M0_INTERNAL void m0_ha_link_send(struct m0_ha_link *hl, const struct m0_ha_msg *msg, uint64_t *tag)
Definition: link.c:556
return M0_RC(rc)
M0_INTERNAL void m0_ha_disconnect(struct m0_ha *ha)
Definition: ha.c:707
#define equi(a, b)
Definition: misc.h:297
static int ha_link_incoming_create(struct m0_ha *ha, const struct m0_ha_entrypoint_req *req, struct m0_ha_link_conn_cfg *hl_conn_cfg, struct ha_link_ctx **hlx_ptr)
Definition: ha.c:736
#define M0_ENTRY(...)
Definition: trace.h:170
static void ha_request_received_cb(struct m0_ha_entrypoint_server *hes, const struct m0_ha_entrypoint_req *req, const struct m0_uint128 *req_id)
Definition: ha.c:255
static bool ha_link_event_cb(struct m0_clink *clink)
Definition: ha.c:99
static char * addr
Definition: node_k.c:37
M0_INTERNAL void m0_ha_cookie_fini(struct m0_ha_cookie *hc)
Definition: cookie.c:62
M0_INTERNAL bool m0_ha_cookie_is_eq(const struct m0_ha_cookie *a, const struct m0_ha_cookie *b)
Definition: cookie.c:79
M0_INTERNAL int m0_ha_entrypoint_mod_init(void)
Definition: entrypoint.c:835
M0_INTERNAL struct m0_rpc_session * m0_ha_outgoing_session(struct m0_ha *ha)
Definition: ha.c:1016
return M0_ERR(-EOPNOTSUPP)
M0_INTERNAL void m0_ha_flush(struct m0_ha *ha, struct m0_ha_link *hl)
Definition: ha.c:966
M0_INTERNAL void m0_ha_stop(struct m0_ha *ha)
Definition: ha.c:672
M0_INTERNAL int m0_ha_entrypoint_server_init(struct m0_ha_entrypoint_server *hes, struct m0_ha_entrypoint_server_cfg *hes_cfg)
Definition: entrypoint.c:220
M0_INTERNAL void m0_ha_process_failed(struct m0_ha *ha, const struct m0_fid *process_fid)
Definition: ha.c:972
M0_INTERNAL void m0_ha_link_cb_disconnecting(struct m0_ha_link *hl)
Definition: link.c:787
struct m0_ha_module * i_ha_module
Definition: instance.h:107
struct m0_ha_entrypoint_server h_entrypoint_server
Definition: ha.h:304
M0_INTERNAL void m0_ha_delivered(struct m0_ha *ha, struct m0_ha_link *hl, struct m0_ha_msg *msg)
Definition: ha.c:870
struct m0_ha_link * h_link
Definition: ha.h:298
M0_INTERNAL void m0_ha_link_reconnect_cancel(struct m0_ha_link *hl)
Definition: link.c:479
void(* hao_entrypoint_replied)(struct m0_ha *ha, struct m0_ha_entrypoint_rep *rep)
Definition: ha.h:244
#define M0_ASSERT(cond)
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
const struct m0_ha_cookie m0_ha_cookie_no_record
Definition: cookie.c:40
struct m0_tl h_links_stopping
Definition: ha.h:296
M0_INTERNAL void m0_ha_mod_fini(void)
Definition: ha.c:1052
M0_INTERNAL void m0_ha_entrypoint_server_fini(struct m0_ha_entrypoint_server *hes)
Definition: entrypoint.c:234
#define U128_P(x)
Definition: types.h:45
M0_INTERNAL int m0_ha_entrypoint_client_init(struct m0_ha_entrypoint_client *ecl, const char *ep, struct m0_ha_entrypoint_client_cfg *ecl_cfg)
Definition: entrypoint.c:434
Definition: tlist.h:251
struct m0_ha_entrypoint_req ecl_req
Definition: entrypoint.h:111
struct m0_ha_entrypoint_client_cfg hcf_entrypoint_client_cfg
Definition: ha.h:283
static int ha_link_ctx_init(struct m0_ha *ha, struct ha_link_ctx *hlx, struct m0_ha_link_cfg *hl_cfg, const struct m0_ha_link_conn_cfg *hl_conn_cfg, const struct m0_fid *process_fid, enum ha_link_ctx_type hlx_type)
Definition: ha.c:185
M0_INTERNAL void m0_module_setup(struct m0_module *module, const char *name, const struct m0_modlev *level, int level_nr, struct m0 *instance)
Definition: module.c:193
M0_INTERNAL void m0_ha_link_params_invert(struct m0_ha_link_params *dst, const struct m0_ha_link_params *src)
Definition: link_fops.c:67
const char * hcf_addr
Definition: ha.h:277
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
M0_INTERNAL int m0_ha_link_mod_init(void)
Definition: link.c:1726
Definition: msg.h:115
M0_INTERNAL void m0_ha_link_reconnect_begin(struct m0_ha_link *hl, struct m0_ha_link_params *lp)
Definition: link.c:422
Definition: xcode.h:73
struct m0_reqh * hesc_reqh
Definition: entrypoint.h:69
static void ha_link_ctx_fini(struct m0_ha *ha, struct ha_link_ctx *hlx)
Definition: ha.c:225
struct m0_ha_cookie h_cookie_local
Definition: ha.h:316
M0_INTERNAL void m0_ha_link_tags_initial(struct m0_ha_link_tags *tags, bool tag_even)
Definition: link_fops.c:44
M0_INTERNAL void m0_ha_link_reconnect_end(struct m0_ha_link *hl, const struct m0_ha_link_conn_cfg *hl_conn_cfg)
Definition: link.c:441
static struct m0_clink clink[RDWR_REQUEST_MAX]
bool h_warn_local_link_disconnect
Definition: ha.h:308
static bool ha_link_stop_cb(struct m0_clink *clink)
Definition: ha.c:176
struct m0_ha_cookie h_cookie_remote
Definition: ha.h:324
M0_INTERNAL int m0_ha_link_service_init(struct m0_reqh_service **hl_service, struct m0_reqh *reqh)
Definition: link_service.c:290
struct m0_rpc_machine * hcf_rpc_machine
Definition: ha.h:274
#define FID_P(f)
Definition: fid.h:77
M0_INTERNAL uint64_t m0_ha_link_delivered_consume(struct m0_ha_link *hl)
Definition: link.c:606
M0_INTERNAL void m0_ha_disconnect_incoming(struct m0_ha *ha, struct m0_ha_link *hl)
Definition: ha.c:714
M0_INTERNAL void m0_ha_link_delivered(struct m0_ha_link *hl, struct m0_ha_msg *msg)
Definition: link.c:584
M0_INTERNAL int m0_ha_link_service_mod_init(void)
Definition: link_service.c:305
Definition: ha.h:289
m0_ha_mod_level
Definition: ha.c:877
#define U128X_F
Definition: types.h:42
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
bool h_link_started
Definition: ha.h:301
M0_TL_DESCR_DEFINE(ha_links, "m0_ha::h_links_{incoming,outgoing}", static, struct ha_link_ctx, hlx_tlink, hlx_magic, 7, 8)
M0_TL_DEFINE(ha_links, static, struct ha_link_ctx)
M0_INTERNAL void m0_ha_cookie_record(struct m0_ha_cookie *hc)
Definition: cookie.c:67
static int ha_level_enter(struct m0_module *module)
Definition: ha.c:365
M0_INTERNAL void m0_ha_link_mod_fini(void)
Definition: link.c:1738
m0_ha_entrypoint_client_state
Definition: entrypoint.h:86
M0_INTERNAL int m0_ha_mod_init(void)
Definition: ha.c:1032
void(* hao_msg_is_delivered)(struct m0_ha *ha, struct m0_ha_link *hl, uint64_t tag)
Definition: ha.h:250
Definition: fid.h:38
M0_INTERNAL void m0_ha_link_service_fini(struct m0_reqh_service *hl_service)
Definition: link_service.c:298
static void ha_link_conn_cfg_make(struct m0_ha_link_conn_cfg *hl_conn_cfg, const char *rpc_endpoint)
Definition: ha.c:266
#define M0_IS0(obj)
Definition: misc.h:70
struct m0_clink h_clink
Definition: ha.h:305
M0_INTERNAL void m0_ha_entrypoint_client_fini(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:464
void(* hao_msg_received)(struct m0_ha *ha, struct m0_ha_link *hl, struct m0_ha_msg *msg, uint64_t tag)
Definition: ha.h:246
M0_INTERNAL int m0_ha_init(struct m0_ha *ha, struct m0_ha_cfg *ha_cfg)
Definition: ha.c:641
struct m0_module hmo_module
Definition: ha.c:71
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_INTERNAL void m0_semaphore_fini(struct m0_semaphore *semaphore)
Definition: semaphore.c:45
M0_INTERNAL void m0_ha_link_rpc_endpoint(struct m0_ha_link *hl, char *buf, m0_bcount_t buf_len)
Definition: link.c:1716
struct ha_link_ctx * h_link_ctx
Definition: ha.h:300
int m_cur
Definition: module.h:160
Definition: ha.h:272
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
struct m0_module h_module
Definition: ha.h:291
void(* hao_link_reused)(struct m0_ha *ha, const struct m0_uint128 *req_id, struct m0_ha_link *hl)
Definition: ha.h:259
M0_INTERNAL void m0_ha_entrypoint_server_stop(struct m0_ha_entrypoint_server *hes)
Definition: entrypoint.c:258
M0_INTERNAL struct m0_chan * m0_ha_entrypoint_client_chan(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:823
#define M0_UINT128(hi, lo)
Definition: types.h:40
static int ha_mod_level_enter(struct m0_module *module)
Definition: ha.c:887
m0_ha_level
Definition: ha.h:221
#define M0_MKTIME(secs, ns)
Definition: time.h:86
#define M0_ASSERT_INFO(cond, fmt,...)
M0_INTERNAL void m0_ha_link_reconnect_params(const struct m0_ha_link_params *lp_alive, struct m0_ha_link_params *lp_alive_new, struct m0_ha_link_params *lp_dead_new, const struct m0_uint128 *id_alive, const struct m0_uint128 *id_dead, const struct m0_uint128 *id_connection)
Definition: link.c:486
void(* hao_msg_is_not_delivered)(struct m0_ha *ha, struct m0_ha_link *hl, uint64_t tag)
Definition: ha.h:253
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
M0_INTERNAL void m0_semaphore_down(struct m0_semaphore *semaphore)
Definition: semaphore.c:49
static void ha_mod_level_leave(struct m0_module *module)
Definition: ha.c:913
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
#define M0_FID0
Definition: fid.h:93
M0_INTERNAL int m0_ha_link_init(struct m0_ha_link *hl, struct m0_ha_link_cfg *hl_cfg)
Definition: link.c:225
#define M0_PRE_EX(cond)
#define m0_tl_find(name, var, head,...)
Definition: tlist.h:757
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL void m0_ha_entrypoint_client_start(struct m0_ha_entrypoint_client *ecl)
Definition: entrypoint.c:727
M0_INTERNAL void m0_ha_link_fini(struct m0_ha_link *hl)
Definition: link.c:269
static void ha_link_handle(struct m0_ha *ha, const struct m0_uint128 *req_id, const struct m0_ha_entrypoint_req *req, struct m0_ha_entrypoint_rep *rep, struct m0_ha_link **hl_ptr)
Definition: ha.c:762
M0_INTERNAL uint64_t m0_ha_link_not_delivered_consume(struct m0_ha_link *hl)
Definition: link.c:618
struct m0_tl h_links_incoming
Definition: ha.h:293
struct m0_ha_entrypoint_rep ecl_rep
Definition: entrypoint.h:114
static const struct m0_modlev ha_levels[]
Definition: ha.c:363
int32_t rc
Definition: trigger_fop.h:47
static struct ha_link_ctx * ha_link_incoming_find(struct m0_ha *ha, const struct m0_ha_link_params *lp)
Definition: ha.c:164
#define ARRAY_SIZE(a)
Definition: misc.h:45
M0_INTERNAL void m0_module_fini(struct m0_module *module, int level)
Definition: module.c:142
M0_INTERNAL struct m0_rpc_session * m0_ha_link_rpc_session(struct m0_ha_link *hl)
Definition: link.c:1711
struct m0_fid hcf_process_fid
Definition: ha.h:279
static const char * process_fid
Definition: idx_dix.c:73
M0_INTERNAL void m0_ha_link_service_mod_fini(void)
Definition: link_service.c:310
#define FID_F
Definition: fid.h:75
Definition: trace.h:478
static void ha_link_id_next(struct m0_ha *ha, struct m0_uint128 *id)
Definition: ha.c:729
M0_INTERNAL int m0_module_init(struct m0_module *module, int level)
Definition: module.c:131
#define M0_IMPOSSIBLE(fmt,...)