corosync  2.3.5-dirty
sync.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2012 Red Hat, Inc.
3  *
4  * All rights reserved.
5  *
6  * Author: Steven Dake (sdake@redhat.com)
7  *
8  * This software licensed under BSD license, the text of which follows:
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * - Redistributions of source code must retain the above copyright notice,
14  * this list of conditions and the following disclaimer.
15  * - Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  * - Neither the name of the MontaVista Software, Inc. nor the names of its
19  * contributors may be used to endorse or promote products derived from this
20  * software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 #include <config.h>
35 
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/un.h>
39 #include <sys/ioctl.h>
40 #include <netinet/in.h>
41 #include <sys/uio.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <errno.h>
47 #include <time.h>
48 #include <unistd.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 
52 #include <corosync/corotypes.h>
53 #include <corosync/swab.h>
54 #include <corosync/totem/totempg.h>
55 #include <corosync/totem/totem.h>
56 #include <corosync/logsys.h>
57 #include <qb/qbipc_common.h>
58 #include "schedwrk.h"
59 #include "quorum.h"
60 #include "sync.h"
61 #include "main.h"
62 
63 LOGSYS_DECLARE_SUBSYS ("SYNC");
64 
65 #define MESSAGE_REQ_SYNC_BARRIER 0
66 #define MESSAGE_REQ_SYNC_SERVICE_BUILD 1
67 #define MESSAGE_REQ_SYNC_MEMB_DETERMINE 2
68 
73 };
74 
75 enum sync_state {
79 };
80 
81 struct service_entry {
83  void (*sync_init) (
84  const unsigned int *trans_list,
85  size_t trans_list_entries,
86  const unsigned int *member_list,
87  size_t member_list_entries,
88  const struct memb_ring_id *ring_id);
89  void (*sync_abort) (void);
90  int (*sync_process) (void);
91  void (*sync_activate) (void);
93  char name[128];
94 };
95 
97  int nodeid;
98  int received;
99 };
100 
102  struct qb_ipc_request_header header __attribute__((aligned(8)));
103  struct memb_ring_id ring_id __attribute__((aligned(8)));
104 };
105 
107  struct qb_ipc_request_header header __attribute__((aligned(8)));
108  struct memb_ring_id ring_id __attribute__((aligned(8)));
109  int service_list_entries __attribute__((aligned(8)));
110  int service_list[128] __attribute__((aligned(8)));
111 };
112 
114  struct qb_ipc_request_header header __attribute__((aligned(8)));
115  struct memb_ring_id ring_id __attribute__((aligned(8)));
116 };
117 
118 static enum sync_state my_state = SYNC_BARRIER;
119 
120 static struct memb_ring_id my_ring_id;
121 
122 static struct memb_ring_id my_memb_determine_ring_id;
123 
124 static int my_memb_determine = 0;
125 
126 static unsigned int my_memb_determine_list[PROCESSOR_COUNT_MAX];
127 
128 static unsigned int my_memb_determine_list_entries = 0;
129 
130 static int my_processing_idx = 0;
131 
132 static hdb_handle_t my_schedwrk_handle;
133 
134 static struct processor_entry my_processor_list[PROCESSOR_COUNT_MAX];
135 
136 static unsigned int my_member_list[PROCESSOR_COUNT_MAX];
137 
138 static unsigned int my_trans_list[PROCESSOR_COUNT_MAX];
139 
140 static size_t my_member_list_entries = 0;
141 
142 static size_t my_trans_list_entries = 0;
143 
144 static int my_processor_list_entries = 0;
145 
146 static struct service_entry my_service_list[SERVICES_COUNT_MAX];
147 
148 static int my_service_list_entries = 0;
149 
150 static const struct memb_ring_id sync_ring_id;
151 
152 static void (*sync_synchronization_completed) (void);
153 
154 static void sync_deliver_fn (
155  unsigned int nodeid,
156  const void *msg,
157  unsigned int msg_len,
158  int endian_conversion_required);
159 
160 static int schedwrk_processor (const void *context);
161 
162 static void sync_process_enter (void);
163 
164 static struct totempg_group sync_group = {
165  .group = "sync",
166  .group_len = 4
167 };
168 
169 static void *sync_group_handle;
170 
172  int service_id,
173  struct sync_callbacks *callbacks);
174 
176  int (*sync_callbacks_retrieve) (
177  int service_id,
178  struct sync_callbacks *callbacks),
179  void (*synchronization_completed) (void))
180 {
181  unsigned int res;
182 
184  &sync_group_handle,
185  sync_deliver_fn,
186  NULL);
187  if (res == -1) {
189  "Couldn't initialize groups interface.");
190  return (-1);
191  }
192 
193  res = totempg_groups_join (
194  sync_group_handle,
195  &sync_group,
196  1);
197  if (res == -1) {
198  log_printf (LOGSYS_LEVEL_ERROR, "Couldn't join group.");
199  return (-1);
200  }
201 
202  sync_synchronization_completed = synchronization_completed;
203  my_sync_callbacks_retrieve = sync_callbacks_retrieve;
204 
205  return (0);
206 }
207 
208 static void sync_barrier_handler (unsigned int nodeid, const void *msg)
209 {
211  int i;
212  int barrier_reached = 1;
213 
214  if (memcmp (&my_ring_id, &req_exec_barrier_message->ring_id,
215  sizeof (struct memb_ring_id)) != 0) {
216 
217  log_printf (LOGSYS_LEVEL_DEBUG, "barrier for old ring - discarding");
218  return;
219  }
220  for (i = 0; i < my_processor_list_entries; i++) {
221  if (my_processor_list[i].nodeid == nodeid) {
222  my_processor_list[i].received = 1;
223  }
224  }
225  for (i = 0; i < my_processor_list_entries; i++) {
226  if (my_processor_list[i].received == 0) {
227  barrier_reached = 0;
228  }
229  }
230  if (barrier_reached) {
231  log_printf (LOGSYS_LEVEL_DEBUG, "Committing synchronization for %s",
232  my_service_list[my_processing_idx].name);
233  my_service_list[my_processing_idx].state = ACTIVATE;
234 
235  if (my_sync_callbacks_retrieve(my_service_list[my_processing_idx].service_id, NULL) != -1) {
236  my_service_list[my_processing_idx].sync_activate ();
237  }
238 
239  my_processing_idx += 1;
240  if (my_service_list_entries == my_processing_idx) {
241  my_memb_determine_list_entries = 0;
242  sync_synchronization_completed ();
243  } else {
244  sync_process_enter ();
245  }
246  }
247 }
248 
249 static void dummy_sync_init (
250  const unsigned int *trans_list,
251  size_t trans_list_entries,
252  const unsigned int *member_list,
253  size_t member_list_entries,
254  const struct memb_ring_id *ring_id)
255 {
256 }
257 
258 static void dummy_sync_abort (void)
259 {
260 }
261 
262 static int dummy_sync_process (void)
263 {
264  return (0);
265 }
266 
267 static void dummy_sync_activate (void)
268 {
269 }
270 
271 static int service_entry_compare (const void *a, const void *b)
272 {
273  const struct service_entry *service_entry_a = a;
274  const struct service_entry *service_entry_b = b;
275 
276  return (service_entry_a->service_id > service_entry_b->service_id);
277 }
278 
279 static void sync_memb_determine (unsigned int nodeid, const void *msg)
280 {
282  int found = 0;
283  int i;
284 
285  if (memcmp (&req_exec_memb_determine_message->ring_id,
286  &my_memb_determine_ring_id, sizeof (struct memb_ring_id)) != 0) {
287 
288  log_printf (LOGSYS_LEVEL_DEBUG, "memb determine for old ring - discarding");
289  return;
290  }
291 
292  my_memb_determine = 1;
293  for (i = 0; i < my_memb_determine_list_entries; i++) {
294  if (my_memb_determine_list[i] == nodeid) {
295  found = 1;
296  }
297  }
298  if (found == 0) {
299  my_memb_determine_list[my_memb_determine_list_entries] = nodeid;
300  my_memb_determine_list_entries += 1;
301  }
302 }
303 
304 static void sync_service_build_handler (unsigned int nodeid, const void *msg)
305 {
307  int i, j;
308  int barrier_reached = 1;
309  int found;
310  int qsort_trigger = 0;
311 
312  if (memcmp (&my_ring_id, &req_exec_service_build_message->ring_id,
313  sizeof (struct memb_ring_id)) != 0) {
314  log_printf (LOGSYS_LEVEL_DEBUG, "service build for old ring - discarding");
315  return;
316  }
317  for (i = 0; i < req_exec_service_build_message->service_list_entries; i++) {
318 
319  found = 0;
320  for (j = 0; j < my_service_list_entries; j++) {
321  if (req_exec_service_build_message->service_list[i] ==
322  my_service_list[j].service_id) {
323  found = 1;
324  break;
325  }
326  }
327  if (found == 0) {
328  my_service_list[my_service_list_entries].state =
329  INIT;
330  my_service_list[my_service_list_entries].service_id =
331  req_exec_service_build_message->service_list[i];
332  sprintf (my_service_list[my_service_list_entries].name,
333  "Uknown External Service (id = %d)\n",
334  req_exec_service_build_message->service_list[i]);
335  my_service_list[my_service_list_entries].sync_init =
336  dummy_sync_init;
337  my_service_list[my_service_list_entries].sync_abort =
338  dummy_sync_abort;
339  my_service_list[my_service_list_entries].sync_process =
340  dummy_sync_process;
341  my_service_list[my_service_list_entries].sync_activate =
342  dummy_sync_activate;
343  my_service_list_entries += 1;
344 
345  qsort_trigger = 1;
346  }
347  }
348  if (qsort_trigger) {
349  qsort (my_service_list, my_service_list_entries,
350  sizeof (struct service_entry), service_entry_compare);
351  }
352  for (i = 0; i < my_processor_list_entries; i++) {
353  if (my_processor_list[i].nodeid == nodeid) {
354  my_processor_list[i].received = 1;
355  }
356  }
357  for (i = 0; i < my_processor_list_entries; i++) {
358  if (my_processor_list[i].received == 0) {
359  barrier_reached = 0;
360  }
361  }
362  if (barrier_reached) {
363  sync_process_enter ();
364  }
365 }
366 
367 static void sync_deliver_fn (
368  unsigned int nodeid,
369  const void *msg,
370  unsigned int msg_len,
371  int endian_conversion_required)
372 {
373  struct qb_ipc_request_header *header = (struct qb_ipc_request_header *)msg;
374 
375  switch (header->id) {
377  sync_barrier_handler (nodeid, msg);
378  break;
380  sync_service_build_handler (nodeid, msg);
381  break;
383  sync_memb_determine (nodeid, msg);
384  break;
385  }
386 }
387 
388 static void memb_determine_message_transmit (void)
389 {
390  struct iovec iovec;
391  struct req_exec_memb_determine_message req_exec_memb_determine_message;
392 
393  req_exec_memb_determine_message.header.size = sizeof (struct req_exec_memb_determine_message);
394  req_exec_memb_determine_message.header.id = MESSAGE_REQ_SYNC_MEMB_DETERMINE;
395 
396  memcpy (&req_exec_memb_determine_message.ring_id,
397  &my_memb_determine_ring_id,
398  sizeof (struct memb_ring_id));
399 
400  iovec.iov_base = (char *)&req_exec_memb_determine_message;
401  iovec.iov_len = sizeof (req_exec_memb_determine_message);
402 
403  (void)totempg_groups_mcast_joined (sync_group_handle,
404  &iovec, 1, TOTEMPG_AGREED);
405 }
406 
407 static void barrier_message_transmit (void)
408 {
409  struct iovec iovec;
410  struct req_exec_barrier_message req_exec_barrier_message;
411 
412  req_exec_barrier_message.header.size = sizeof (struct req_exec_barrier_message);
413  req_exec_barrier_message.header.id = MESSAGE_REQ_SYNC_BARRIER;
414 
415  memcpy (&req_exec_barrier_message.ring_id, &my_ring_id,
416  sizeof (struct memb_ring_id));
417 
418  iovec.iov_base = (char *)&req_exec_barrier_message;
419  iovec.iov_len = sizeof (req_exec_barrier_message);
420 
421  (void)totempg_groups_mcast_joined (sync_group_handle,
422  &iovec, 1, TOTEMPG_AGREED);
423 }
424 
425 static void service_build_message_transmit (struct req_exec_service_build_message *service_build_message)
426 {
427  struct iovec iovec;
428 
429  service_build_message->header.size = sizeof (struct req_exec_service_build_message);
430  service_build_message->header.id = MESSAGE_REQ_SYNC_SERVICE_BUILD;
431 
432  memcpy (&service_build_message->ring_id, &my_ring_id,
433  sizeof (struct memb_ring_id));
434 
435  iovec.iov_base = (void *)service_build_message;
436  iovec.iov_len = sizeof (struct req_exec_service_build_message);
437 
438  (void)totempg_groups_mcast_joined (sync_group_handle,
439  &iovec, 1, TOTEMPG_AGREED);
440 }
441 
442 static void sync_barrier_enter (void)
443 {
444  my_state = SYNC_BARRIER;
445  barrier_message_transmit ();
446 }
447 
448 static void sync_process_enter (void)
449 {
450  int i;
451 
452  my_state = SYNC_PROCESS;
453 
454  /*
455  * No sync services
456  */
457  if (my_service_list_entries == 0) {
458  my_state = SYNC_SERVICELIST_BUILD;
459  my_memb_determine_list_entries = 0;
460  sync_synchronization_completed ();
461  return;
462  }
463  for (i = 0; i < my_processor_list_entries; i++) {
464  my_processor_list[i].received = 0;
465  }
466  schedwrk_create (&my_schedwrk_handle,
467  schedwrk_processor,
468  NULL);
469 }
470 
471 static void sync_servicelist_build_enter (
472  const unsigned int *member_list,
473  size_t member_list_entries,
474  const struct memb_ring_id *ring_id)
475 {
476  struct req_exec_service_build_message service_build;
477  int i;
478  int res;
480 
481  my_state = SYNC_SERVICELIST_BUILD;
482  for (i = 0; i < member_list_entries; i++) {
483  my_processor_list[i].nodeid = member_list[i];
484  my_processor_list[i].received = 0;
485  }
486  my_processor_list_entries = member_list_entries;
487 
488  memcpy (my_member_list, member_list,
489  member_list_entries * sizeof (unsigned int));
490  my_member_list_entries = member_list_entries;
491 
492  my_processing_idx = 0;
493 
494  memset(my_service_list, 0, sizeof (struct service_entry) * SERVICES_COUNT_MAX);
495  my_service_list_entries = 0;
496 
497  for (i = 0; i < SERVICES_COUNT_MAX; i++) {
499  if (res == -1) {
500  continue;
501  }
502  if (sync_callbacks.sync_init == NULL) {
503  continue;
504  }
505  my_service_list[my_service_list_entries].state = INIT;
506  my_service_list[my_service_list_entries].service_id = i;
507  strcpy (my_service_list[my_service_list_entries].name,
509  my_service_list[my_service_list_entries].sync_init = sync_callbacks.sync_init;
510  my_service_list[my_service_list_entries].sync_process = sync_callbacks.sync_process;
511  my_service_list[my_service_list_entries].sync_abort = sync_callbacks.sync_abort;
512  my_service_list[my_service_list_entries].sync_activate = sync_callbacks.sync_activate;
513  my_service_list_entries += 1;
514  }
515 
516  for (i = 0; i < my_service_list_entries; i++) {
517  service_build.service_list[i] =
518  my_service_list[i].service_id;
519  }
520  service_build.service_list_entries = my_service_list_entries;
521 
522  service_build_message_transmit (&service_build);
523 }
524 
525 static int schedwrk_processor (const void *context)
526 {
527  int res = 0;
528 
529  if (my_service_list[my_processing_idx].state == INIT) {
530  unsigned int old_trans_list[PROCESSOR_COUNT_MAX];
531  size_t old_trans_list_entries = 0;
532  int o, m;
533  my_service_list[my_processing_idx].state = PROCESS;
534 
535  memcpy (old_trans_list, my_trans_list, my_trans_list_entries *
536  sizeof (unsigned int));
537  old_trans_list_entries = my_trans_list_entries;
538 
539  my_trans_list_entries = 0;
540  for (o = 0; o < old_trans_list_entries; o++) {
541  for (m = 0; m < my_member_list_entries; m++) {
542  if (old_trans_list[o] == my_member_list[m]) {
543  my_trans_list[my_trans_list_entries] = my_member_list[m];
544  my_trans_list_entries++;
545  break;
546  }
547  }
548  }
549 
550  if (my_sync_callbacks_retrieve(my_service_list[my_processing_idx].service_id, NULL) != -1) {
551  my_service_list[my_processing_idx].sync_init (my_trans_list,
552  my_trans_list_entries, my_member_list,
553  my_member_list_entries,
554  &my_ring_id);
555  }
556  }
557  if (my_service_list[my_processing_idx].state == PROCESS) {
558  my_service_list[my_processing_idx].state = PROCESS;
559  if (my_sync_callbacks_retrieve(my_service_list[my_processing_idx].service_id, NULL) != -1) {
560  res = my_service_list[my_processing_idx].sync_process ();
561  } else {
562  res = 0;
563  }
564  if (res == 0) {
565  sync_barrier_enter();
566  } else {
567  return (-1);
568  }
569  }
570  return (0);
571 }
572 
574  const unsigned int *member_list,
575  size_t member_list_entries,
576  const struct memb_ring_id *ring_id)
577 {
578  ENTER();
579  memcpy (&my_ring_id, ring_id, sizeof (struct memb_ring_id));
580 
581  if (my_memb_determine) {
582  my_memb_determine = 0;
583  sync_servicelist_build_enter (my_memb_determine_list,
584  my_memb_determine_list_entries, ring_id);
585  } else {
586  sync_servicelist_build_enter (member_list, member_list_entries,
587  ring_id);
588  }
589 }
590 
592  const unsigned int *member_list,
593  size_t member_list_entries,
594  const struct memb_ring_id *ring_id)
595 {
596  ENTER();
597  memcpy (my_trans_list, member_list, member_list_entries *
598  sizeof (unsigned int));
599  my_trans_list_entries = member_list_entries;
600 }
601 
602 void sync_abort (void)
603 {
604  ENTER();
605  if (my_state == SYNC_PROCESS) {
606  schedwrk_destroy (my_schedwrk_handle);
607  if (my_sync_callbacks_retrieve(my_service_list[my_processing_idx].service_id, NULL) != -1) {
608  my_service_list[my_processing_idx].sync_abort ();
609  }
610  }
611 
612  /* this will cause any "old" barrier messages from causing
613  * problems.
614  */
615  memset (&my_ring_id, 0, sizeof (struct memb_ring_id));
616 }
617 
618 void sync_memb_list_determine (const struct memb_ring_id *ring_id)
619 {
620  ENTER();
621  memcpy (&my_memb_determine_ring_id, ring_id,
622  sizeof (struct memb_ring_id));
623 
624  memb_determine_message_transmit ();
625 }
626 
628 {
629  ENTER();
630  my_memb_determine_list_entries = 0;
631  memset (&my_memb_determine_ring_id, 0, sizeof (struct memb_ring_id));
632 }
Definition: sync.c:71
void sync_start(const unsigned int *member_list, size_t member_list_entries, const struct memb_ring_id *ring_id)
Definition: sync.c:573
void sync_abort(void)
Definition: sync.c:602
void(* sync_abort)(void)
Definition: sync.h:47
Totem Single Ring Protocol.
void(* sync_init)(const unsigned int *trans_list, size_t trans_list_entries, const unsigned int *member_list, size_t member_list_entries, const struct memb_ring_id *ring_id)
Definition: sync.h:39
int sync_init(int(*sync_callbacks_retrieve)(int service_id, struct sync_callbacks *callbacks), void(*synchronization_completed)(void))
Definition: sync.c:175
void(* sync_activate)(void)
Definition: sync.c:91
#define MESSAGE_REQ_SYNC_MEMB_DETERMINE
Definition: sync.c:67
int nodeid
Definition: sync.c:97
struct message_header header
Definition: totemsrp.c:60
int totempg_groups_initialize(void **instance, void(*deliver_fn)(unsigned int nodeid, const void *msg, unsigned int msg_len, int endian_conversion_required), void(*confchg_fn)(enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id))
Initialize a groups instance.
Definition: totempg.c:1124
#define log_printf(level, format, args...)
Definition: logsys.h:217
int service_id
Definition: sync.c:82
void(* sync_activate)(void)
Definition: sync.h:46
void schedwrk_destroy(hdb_handle_t handle)
Definition: schedwrk.c:159
Definition: sync.c:81
Definition: sync.c:72
const char * name
Definition: sync.h:48
sync_process_state
Definition: sync.c:69
sync_state
Definition: sync.c:75
void(* sync_init)(const unsigned int *trans_list, size_t trans_list_entries, const unsigned int *member_list, size_t member_list_entries, const struct memb_ring_id *ring_id)
Definition: sync.c:83
const void * group
Definition: totempg.h:56
#define TOTEMPG_AGREED
Definition: totempg.h:60
#define LOGSYS_LEVEL_ERROR
Definition: logsys.h:70
void sync_save_transitional(const unsigned int *member_list, size_t member_list_entries, const struct memb_ring_id *ring_id)
Definition: sync.c:591
int totempg_groups_mcast_joined(void *instance, const struct iovec *iovec, unsigned int iov_len, int guarantee)
Definition: totempg.c:1222
#define LOGSYS_LEVEL_DEBUG
Definition: logsys.h:74
void(* sync_abort)(void)
Definition: sync.c:89
Definition: sync.c:96
enum sync_process_state state
Definition: sync.c:92
#define ENTER
Definition: logsys.h:218
#define MESSAGE_REQ_SYNC_SERVICE_BUILD
Definition: sync.c:66
#define PROCESSOR_COUNT_MAX
Definition: coroapi.h:83
qb_handle_t hdb_handle_t
Definition: hdb.h:52
Definition: sync.c:70
void sync_memb_list_abort(void)
Definition: sync.c:627
#define MESSAGE_REQ_SYNC_BARRIER
Definition: sync.c:65
#define SERVICES_COUNT_MAX
Definition: coroapi.h:415
int received
Definition: sync.c:98
struct qb_ipc_request_header header __attribute__((aligned(8)))
int(* my_sync_callbacks_retrieve)(int service_id, struct sync_callbacks *callbacks)
Definition: sync.c:171
int totempg_groups_join(void *instance, const struct totempg_group *groups, size_t group_cnt)
Definition: totempg.c:1172
char name[128]
Definition: sync.c:93
LOGSYS_DECLARE_SUBSYS("SYNC")
unsigned int nodeid
Definition: coroapi.h:65
struct memb_ring_id ring_id
Definition: totemsrp.c:64
void sync_memb_list_determine(const struct memb_ring_id *ring_id)
Definition: sync.c:618
int(* sync_process)(void)
Definition: sync.c:90
int schedwrk_create(hdb_handle_t *handle, int(schedwrk_fn)(const void *), const void *context)
Definition: schedwrk.c:143
int(* sync_process)(void)
Definition: sync.h:45