corosync  2.4.1
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 void (*sync_synchronization_completed) (void);
151 
152 static void sync_deliver_fn (
153  unsigned int nodeid,
154  const void *msg,
155  unsigned int msg_len,
156  int endian_conversion_required);
157 
158 static int schedwrk_processor (const void *context);
159 
160 static void sync_process_enter (void);
161 
162 static struct totempg_group sync_group = {
163  .group = "sync",
164  .group_len = 4
165 };
166 
167 static void *sync_group_handle;
168 
170  int service_id,
171  struct sync_callbacks *callbacks);
172 
174  int (*sync_callbacks_retrieve) (
175  int service_id,
176  struct sync_callbacks *callbacks),
177  void (*synchronization_completed) (void))
178 {
179  unsigned int res;
180 
182  &sync_group_handle,
183  sync_deliver_fn,
184  NULL);
185  if (res == -1) {
187  "Couldn't initialize groups interface.");
188  return (-1);
189  }
190 
191  res = totempg_groups_join (
192  sync_group_handle,
193  &sync_group,
194  1);
195  if (res == -1) {
196  log_printf (LOGSYS_LEVEL_ERROR, "Couldn't join group.");
197  return (-1);
198  }
199 
200  sync_synchronization_completed = synchronization_completed;
201  my_sync_callbacks_retrieve = sync_callbacks_retrieve;
202 
203  return (0);
204 }
205 
206 static void sync_barrier_handler (unsigned int nodeid, const void *msg)
207 {
209  int i;
210  int barrier_reached = 1;
211 
212  if (memcmp (&my_ring_id, &req_exec_barrier_message->ring_id,
213  sizeof (struct memb_ring_id)) != 0) {
214 
215  log_printf (LOGSYS_LEVEL_DEBUG, "barrier for old ring - discarding");
216  return;
217  }
218  for (i = 0; i < my_processor_list_entries; i++) {
219  if (my_processor_list[i].nodeid == nodeid) {
220  my_processor_list[i].received = 1;
221  }
222  }
223  for (i = 0; i < my_processor_list_entries; i++) {
224  if (my_processor_list[i].received == 0) {
225  barrier_reached = 0;
226  }
227  }
228  if (barrier_reached) {
229  log_printf (LOGSYS_LEVEL_DEBUG, "Committing synchronization for %s",
230  my_service_list[my_processing_idx].name);
231  my_service_list[my_processing_idx].state = ACTIVATE;
232 
233  if (my_sync_callbacks_retrieve(my_service_list[my_processing_idx].service_id, NULL) != -1) {
234  my_service_list[my_processing_idx].sync_activate ();
235  }
236 
237  my_processing_idx += 1;
238  if (my_service_list_entries == my_processing_idx) {
239  my_memb_determine_list_entries = 0;
240  sync_synchronization_completed ();
241  } else {
242  sync_process_enter ();
243  }
244  }
245 }
246 
247 static void dummy_sync_init (
248  const unsigned int *trans_list,
249  size_t trans_list_entries,
250  const unsigned int *member_list,
251  size_t member_list_entries,
252  const struct memb_ring_id *ring_id)
253 {
254 }
255 
256 static void dummy_sync_abort (void)
257 {
258 }
259 
260 static int dummy_sync_process (void)
261 {
262  return (0);
263 }
264 
265 static void dummy_sync_activate (void)
266 {
267 }
268 
269 static int service_entry_compare (const void *a, const void *b)
270 {
271  const struct service_entry *service_entry_a = a;
272  const struct service_entry *service_entry_b = b;
273 
274  return (service_entry_a->service_id > service_entry_b->service_id);
275 }
276 
277 static void sync_memb_determine (unsigned int nodeid, const void *msg)
278 {
280  int found = 0;
281  int i;
282 
283  if (memcmp (&req_exec_memb_determine_message->ring_id,
284  &my_memb_determine_ring_id, sizeof (struct memb_ring_id)) != 0) {
285 
286  log_printf (LOGSYS_LEVEL_DEBUG, "memb determine for old ring - discarding");
287  return;
288  }
289 
290  my_memb_determine = 1;
291  for (i = 0; i < my_memb_determine_list_entries; i++) {
292  if (my_memb_determine_list[i] == nodeid) {
293  found = 1;
294  }
295  }
296  if (found == 0) {
297  my_memb_determine_list[my_memb_determine_list_entries] = nodeid;
298  my_memb_determine_list_entries += 1;
299  }
300 }
301 
302 static void sync_service_build_handler (unsigned int nodeid, const void *msg)
303 {
305  int i, j;
306  int barrier_reached = 1;
307  int found;
308  int qsort_trigger = 0;
309 
310  if (memcmp (&my_ring_id, &req_exec_service_build_message->ring_id,
311  sizeof (struct memb_ring_id)) != 0) {
312  log_printf (LOGSYS_LEVEL_DEBUG, "service build for old ring - discarding");
313  return;
314  }
315  for (i = 0; i < req_exec_service_build_message->service_list_entries; i++) {
316 
317  found = 0;
318  for (j = 0; j < my_service_list_entries; j++) {
319  if (req_exec_service_build_message->service_list[i] ==
320  my_service_list[j].service_id) {
321  found = 1;
322  break;
323  }
324  }
325  if (found == 0) {
326  my_service_list[my_service_list_entries].state =
327  INIT;
328  my_service_list[my_service_list_entries].service_id =
329  req_exec_service_build_message->service_list[i];
330  sprintf (my_service_list[my_service_list_entries].name,
331  "Unknown External Service (id = %d)\n",
332  req_exec_service_build_message->service_list[i]);
333  my_service_list[my_service_list_entries].sync_init =
334  dummy_sync_init;
335  my_service_list[my_service_list_entries].sync_abort =
336  dummy_sync_abort;
337  my_service_list[my_service_list_entries].sync_process =
338  dummy_sync_process;
339  my_service_list[my_service_list_entries].sync_activate =
340  dummy_sync_activate;
341  my_service_list_entries += 1;
342 
343  qsort_trigger = 1;
344  }
345  }
346  if (qsort_trigger) {
347  qsort (my_service_list, my_service_list_entries,
348  sizeof (struct service_entry), service_entry_compare);
349  }
350  for (i = 0; i < my_processor_list_entries; i++) {
351  if (my_processor_list[i].nodeid == nodeid) {
352  my_processor_list[i].received = 1;
353  }
354  }
355  for (i = 0; i < my_processor_list_entries; i++) {
356  if (my_processor_list[i].received == 0) {
357  barrier_reached = 0;
358  }
359  }
360  if (barrier_reached) {
361  sync_process_enter ();
362  }
363 }
364 
365 static void sync_deliver_fn (
366  unsigned int nodeid,
367  const void *msg,
368  unsigned int msg_len,
369  int endian_conversion_required)
370 {
371  struct qb_ipc_request_header *header = (struct qb_ipc_request_header *)msg;
372 
373  switch (header->id) {
375  sync_barrier_handler (nodeid, msg);
376  break;
378  sync_service_build_handler (nodeid, msg);
379  break;
381  sync_memb_determine (nodeid, msg);
382  break;
383  }
384 }
385 
386 static void memb_determine_message_transmit (void)
387 {
388  struct iovec iovec;
389  struct req_exec_memb_determine_message req_exec_memb_determine_message;
390 
391  req_exec_memb_determine_message.header.size = sizeof (struct req_exec_memb_determine_message);
392  req_exec_memb_determine_message.header.id = MESSAGE_REQ_SYNC_MEMB_DETERMINE;
393 
394  memcpy (&req_exec_memb_determine_message.ring_id,
395  &my_memb_determine_ring_id,
396  sizeof (struct memb_ring_id));
397 
398  iovec.iov_base = (char *)&req_exec_memb_determine_message;
399  iovec.iov_len = sizeof (req_exec_memb_determine_message);
400 
401  (void)totempg_groups_mcast_joined (sync_group_handle,
402  &iovec, 1, TOTEMPG_AGREED);
403 }
404 
405 static void barrier_message_transmit (void)
406 {
407  struct iovec iovec;
408  struct req_exec_barrier_message req_exec_barrier_message;
409 
410  req_exec_barrier_message.header.size = sizeof (struct req_exec_barrier_message);
411  req_exec_barrier_message.header.id = MESSAGE_REQ_SYNC_BARRIER;
412 
413  memcpy (&req_exec_barrier_message.ring_id, &my_ring_id,
414  sizeof (struct memb_ring_id));
415 
416  iovec.iov_base = (char *)&req_exec_barrier_message;
417  iovec.iov_len = sizeof (req_exec_barrier_message);
418 
419  (void)totempg_groups_mcast_joined (sync_group_handle,
420  &iovec, 1, TOTEMPG_AGREED);
421 }
422 
423 static void service_build_message_transmit (struct req_exec_service_build_message *service_build_message)
424 {
425  struct iovec iovec;
426 
427  service_build_message->header.size = sizeof (struct req_exec_service_build_message);
428  service_build_message->header.id = MESSAGE_REQ_SYNC_SERVICE_BUILD;
429 
430  memcpy (&service_build_message->ring_id, &my_ring_id,
431  sizeof (struct memb_ring_id));
432 
433  iovec.iov_base = (void *)service_build_message;
434  iovec.iov_len = sizeof (struct req_exec_service_build_message);
435 
436  (void)totempg_groups_mcast_joined (sync_group_handle,
437  &iovec, 1, TOTEMPG_AGREED);
438 }
439 
440 static void sync_barrier_enter (void)
441 {
442  my_state = SYNC_BARRIER;
443  barrier_message_transmit ();
444 }
445 
446 static void sync_process_enter (void)
447 {
448  int i;
449 
450  my_state = SYNC_PROCESS;
451 
452  /*
453  * No sync services
454  */
455  if (my_service_list_entries == 0) {
456  my_state = SYNC_SERVICELIST_BUILD;
457  my_memb_determine_list_entries = 0;
458  sync_synchronization_completed ();
459  return;
460  }
461  for (i = 0; i < my_processor_list_entries; i++) {
462  my_processor_list[i].received = 0;
463  }
464  schedwrk_create (&my_schedwrk_handle,
465  schedwrk_processor,
466  NULL);
467 }
468 
469 static void sync_servicelist_build_enter (
470  const unsigned int *member_list,
471  size_t member_list_entries,
472  const struct memb_ring_id *ring_id)
473 {
474  struct req_exec_service_build_message service_build;
475  int i;
476  int res;
478 
479  my_state = SYNC_SERVICELIST_BUILD;
480  for (i = 0; i < member_list_entries; i++) {
481  my_processor_list[i].nodeid = member_list[i];
482  my_processor_list[i].received = 0;
483  }
484  my_processor_list_entries = member_list_entries;
485 
486  memcpy (my_member_list, member_list,
487  member_list_entries * sizeof (unsigned int));
488  my_member_list_entries = member_list_entries;
489 
490  my_processing_idx = 0;
491 
492  memset(my_service_list, 0, sizeof (struct service_entry) * SERVICES_COUNT_MAX);
493  my_service_list_entries = 0;
494 
495  for (i = 0; i < SERVICES_COUNT_MAX; i++) {
497  if (res == -1) {
498  continue;
499  }
500  if (sync_callbacks.sync_init == NULL) {
501  continue;
502  }
503  my_service_list[my_service_list_entries].state = INIT;
504  my_service_list[my_service_list_entries].service_id = i;
505  strcpy (my_service_list[my_service_list_entries].name,
507  my_service_list[my_service_list_entries].sync_init = sync_callbacks.sync_init;
508  my_service_list[my_service_list_entries].sync_process = sync_callbacks.sync_process;
509  my_service_list[my_service_list_entries].sync_abort = sync_callbacks.sync_abort;
510  my_service_list[my_service_list_entries].sync_activate = sync_callbacks.sync_activate;
511  my_service_list_entries += 1;
512  }
513 
514  for (i = 0; i < my_service_list_entries; i++) {
515  service_build.service_list[i] =
516  my_service_list[i].service_id;
517  }
518  service_build.service_list_entries = my_service_list_entries;
519 
520  service_build_message_transmit (&service_build);
521 }
522 
523 static int schedwrk_processor (const void *context)
524 {
525  int res = 0;
526 
527  if (my_service_list[my_processing_idx].state == INIT) {
528  unsigned int old_trans_list[PROCESSOR_COUNT_MAX];
529  size_t old_trans_list_entries = 0;
530  int o, m;
531  my_service_list[my_processing_idx].state = PROCESS;
532 
533  memcpy (old_trans_list, my_trans_list, my_trans_list_entries *
534  sizeof (unsigned int));
535  old_trans_list_entries = my_trans_list_entries;
536 
537  my_trans_list_entries = 0;
538  for (o = 0; o < old_trans_list_entries; o++) {
539  for (m = 0; m < my_member_list_entries; m++) {
540  if (old_trans_list[o] == my_member_list[m]) {
541  my_trans_list[my_trans_list_entries] = my_member_list[m];
542  my_trans_list_entries++;
543  break;
544  }
545  }
546  }
547 
548  if (my_sync_callbacks_retrieve(my_service_list[my_processing_idx].service_id, NULL) != -1) {
549  my_service_list[my_processing_idx].sync_init (my_trans_list,
550  my_trans_list_entries, my_member_list,
551  my_member_list_entries,
552  &my_ring_id);
553  }
554  }
555  if (my_service_list[my_processing_idx].state == PROCESS) {
556  my_service_list[my_processing_idx].state = PROCESS;
557  if (my_sync_callbacks_retrieve(my_service_list[my_processing_idx].service_id, NULL) != -1) {
558  res = my_service_list[my_processing_idx].sync_process ();
559  } else {
560  res = 0;
561  }
562  if (res == 0) {
563  sync_barrier_enter();
564  } else {
565  return (-1);
566  }
567  }
568  return (0);
569 }
570 
572  const unsigned int *member_list,
573  size_t member_list_entries,
574  const struct memb_ring_id *ring_id)
575 {
576  ENTER();
577  memcpy (&my_ring_id, ring_id, sizeof (struct memb_ring_id));
578 
579  if (my_memb_determine) {
580  my_memb_determine = 0;
581  sync_servicelist_build_enter (my_memb_determine_list,
582  my_memb_determine_list_entries, ring_id);
583  } else {
584  sync_servicelist_build_enter (member_list, member_list_entries,
585  ring_id);
586  }
587 }
588 
590  const unsigned int *member_list,
591  size_t member_list_entries,
592  const struct memb_ring_id *ring_id)
593 {
594  ENTER();
595  memcpy (my_trans_list, member_list, member_list_entries *
596  sizeof (unsigned int));
597  my_trans_list_entries = member_list_entries;
598 }
599 
600 void sync_abort (void)
601 {
602  ENTER();
603  if (my_state == SYNC_PROCESS) {
604  schedwrk_destroy (my_schedwrk_handle);
605  if (my_sync_callbacks_retrieve(my_service_list[my_processing_idx].service_id, NULL) != -1) {
606  my_service_list[my_processing_idx].sync_abort ();
607  }
608  }
609 
610  /* this will cause any "old" barrier messages from causing
611  * problems.
612  */
613  memset (&my_ring_id, 0, sizeof (struct memb_ring_id));
614 }
615 
616 void sync_memb_list_determine (const struct memb_ring_id *ring_id)
617 {
618  ENTER();
619  memcpy (&my_memb_determine_ring_id, ring_id,
620  sizeof (struct memb_ring_id));
621 
622  memb_determine_message_transmit ();
623 }
624 
626 {
627  ENTER();
628  my_memb_determine_list_entries = 0;
629  memset (&my_memb_determine_ring_id, 0, sizeof (struct memb_ring_id));
630 }
Definition: sync.c:71
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
void sync_start(const unsigned int *member_list, size_t member_list_entries, const struct memb_ring_id *ring_id)
Definition: sync.c:571
void sync_abort(void)
Definition: sync.c:600
Totem Single Ring Protocol.
int sync_init(int(*sync_callbacks_retrieve)(int service_id, struct sync_callbacks *callbacks), void(*synchronization_completed)(void))
Definition: sync.c:173
void(* sync_abort)(void)
Definition: sync.c:89
#define MESSAGE_REQ_SYNC_MEMB_DETERMINE
Definition: sync.c:67
void(* sync_activate)(void)
Definition: sync.c:91
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:1112
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
#define log_printf(level, format, args...)
Definition: logsys.h:319
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:154
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_abort)(void)
Definition: sync.h:47
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:589
int totempg_groups_mcast_joined(void *instance, const struct iovec *iovec, unsigned int iov_len, int guarantee)
Definition: totempg.c:1210
#define LOGSYS_LEVEL_DEBUG
Definition: logsys.h:74
Definition: sync.c:96
enum sync_process_state state
Definition: sync.c:92
#define ENTER
Definition: logsys.h:320
#define MESSAGE_REQ_SYNC_SERVICE_BUILD
Definition: sync.c:66
int(* sync_process)(void)
Definition: sync.c:90
int(* sync_process)(void)
Definition: sync.h:45
#define PROCESSOR_COUNT_MAX
Definition: coroapi.h:96
qb_handle_t hdb_handle_t
Definition: hdb.h:52
The memb_ring_id struct.
Definition: coroapi.h:122
Definition: sync.c:70
void sync_memb_list_abort(void)
Definition: sync.c:625
#define MESSAGE_REQ_SYNC_BARRIER
Definition: sync.c:65
#define SERVICES_COUNT_MAX
Definition: coroapi.h:463
int received
Definition: sync.c:98
struct qb_ipc_request_header header __attribute__((aligned(8)))
int totempg_groups_join(void *instance, const struct totempg_group *groups, size_t group_cnt)
Definition: totempg.c:1160
char name[128]
Definition: sync.c:93
int(* my_sync_callbacks_retrieve)(int service_id, struct sync_callbacks *callbacks)
Definition: sync.c:169
LOGSYS_DECLARE_SUBSYS("SYNC")
unsigned int nodeid
Definition: coroapi.h:75
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:616
int schedwrk_create(hdb_handle_t *handle, int(schedwrk_fn)(const void *), const void *context)
Definition: schedwrk.c:138