corosync  3.0.2-dirty
sam.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2011 Red Hat, Inc.
3  *
4  * All rights reserved.
5  *
6  * Author: Jan Friesse (jfriesse@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 Red Hat, 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 
35 /*
36  * Provides a SAM API
37  */
38 
39 #include <config.h>
40 
41 #include <limits.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include <sys/time.h>
46 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <errno.h>
49 #include <poll.h>
50 
51 #include <corosync/corotypes.h>
52 #include <qb/qbipcc.h>
53 #include <corosync/corodefs.h>
54 #include <corosync/cmap.h>
55 #include <corosync/hdb.h>
56 #include <corosync/quorum.h>
57 
58 #include <corosync/sam.h>
59 
60 #include "util.h"
61 
62 #include <stdio.h>
63 #include <sys/wait.h>
64 #include <signal.h>
65 
66 #define SAM_CMAP_S_FAILED "failed"
67 #define SAM_CMAP_S_REGISTERED "stopped"
68 #define SAM_CMAP_S_STARTED "running"
69 #define SAM_CMAP_S_Q_WAIT "waiting for quorum"
70 
71 #define SAM_RP_MASK_Q(pol) (pol & (~SAM_RECOVERY_POLICY_QUORUM))
72 #define SAM_RP_MASK_C(pol) (pol & (~SAM_RECOVERY_POLICY_CMAP))
73 #define SAM_RP_MASK(pol) (pol & (~(SAM_RECOVERY_POLICY_QUORUM | SAM_RECOVERY_POLICY_CMAP)))
74 
81 };
82 
90 };
91 
95 };
96 
102 };
103 
109 };
110 
111 static struct {
115  unsigned int instance_id;
121 
123  pthread_t cb_thread;
126 
127  void *user_data;
130 
131  pthread_mutex_t lock;
132 
134  uint32_t quorate;
136 
139 } sam_internal_data;
140 
141 extern const char *__progname;
142 
143 static cs_error_t sam_cmap_update_key (enum sam_cmap_key_t key, const char *value)
144 {
145  cs_error_t err;
146  const char *svalue;
147  uint64_t hc_period, last_hc;
148 
149  const char *ssvalue[] = { [SAM_RECOVERY_POLICY_QUIT] = "quit", [SAM_RECOVERY_POLICY_RESTART] = "restart" };
150  char key_name[CMAP_KEYNAME_MAXLEN];
151 
152  switch (key) {
154  svalue = ssvalue[SAM_RP_MASK (sam_internal_data.recovery_policy)];
155 
156  if (snprintf(key_name, CMAP_KEYNAME_MAXLEN, "%s%s", sam_internal_data.cmap_pid_path,
157  "recovery") >= CMAP_KEYNAME_MAXLEN) {
158 
159  err = CS_ERR_NAME_TOO_LONG;
160  goto exit_error;
161  }
162 
163  if ((err = cmap_set_string(sam_internal_data.cmap_handle, key_name, svalue)) != CS_OK) {
164  goto exit_error;
165  }
166  break;
168  hc_period = sam_internal_data.time_interval;
169 
170  if (snprintf(key_name, CMAP_KEYNAME_MAXLEN, "%s%s", sam_internal_data.cmap_pid_path,
171  "poll_period") >= CMAP_KEYNAME_MAXLEN) {
172 
173  err = CS_ERR_NAME_TOO_LONG;
174  goto exit_error;
175  }
176 
177  if ((err = cmap_set_uint64(sam_internal_data.cmap_handle, key_name, hc_period)) != CS_OK) {
178  goto exit_error;
179  }
180  break;
182  last_hc = cs_timestamp_get();
183 
184  if (snprintf(key_name, CMAP_KEYNAME_MAXLEN, "%s%s", sam_internal_data.cmap_pid_path,
185  "last_updated") >= CMAP_KEYNAME_MAXLEN) {
186 
187  err = CS_ERR_NAME_TOO_LONG;
188  goto exit_error;
189  }
190  if ((err = cmap_set_uint64(sam_internal_data.cmap_handle, key_name, last_hc)) != CS_OK) {
191  goto exit_error;
192  }
193  break;
194  case SAM_CMAP_KEY_STATE:
195  svalue = value;
196  if (snprintf(key_name, CMAP_KEYNAME_MAXLEN, "%s%s", sam_internal_data.cmap_pid_path,
197  "state") >= CMAP_KEYNAME_MAXLEN) {
198 
199  err = CS_ERR_NAME_TOO_LONG;
200  goto exit_error;
201  }
202 
203  if ((err = cmap_set_string(sam_internal_data.cmap_handle, key_name, svalue)) != CS_OK) {
204  goto exit_error;
205  }
206  break;
207  }
208 
209  return (CS_OK);
210 
211 exit_error:
212  return (err);
213 }
214 
215 static cs_error_t sam_cmap_destroy_pid_path (void)
216 {
217  cmap_iter_handle_t iter;
218  cs_error_t err;
219  char key_name[CMAP_KEYNAME_MAXLEN + 1];
220 
221  err = cmap_iter_init(sam_internal_data.cmap_handle, sam_internal_data.cmap_pid_path, &iter);
222  if (err != CS_OK) {
223  goto error_exit;
224  }
225 
226  while ((err = cmap_iter_next(sam_internal_data.cmap_handle, iter, key_name, NULL, NULL)) == CS_OK) {
227  cmap_delete(sam_internal_data.cmap_handle, key_name);
228  }
229 
230  err = cmap_iter_finalize(sam_internal_data.cmap_handle, iter);
231 
232 error_exit:
233  return (err);
234 }
235 
236 static cs_error_t sam_cmap_register (void)
237 {
238  cs_error_t err;
240 
241  if ((err = cmap_initialize (&cmap_handle)) != CS_OK) {
242  return (err);
243  }
244 
245  snprintf(sam_internal_data.cmap_pid_path, CMAP_KEYNAME_MAXLEN, "resources.process.%d.", getpid());
246 
247  sam_internal_data.cmap_handle = cmap_handle;
248 
249  if ((err = sam_cmap_update_key (SAM_CMAP_KEY_RECOVERY, NULL)) != CS_OK) {
250  goto destroy_finalize_error;
251  }
252 
253  if ((err = sam_cmap_update_key (SAM_CMAP_KEY_HC_PERIOD, NULL)) != CS_OK) {
254  goto destroy_finalize_error;
255  }
256 
257  return (CS_OK);
258 
259 destroy_finalize_error:
260  sam_cmap_destroy_pid_path ();
261  cmap_finalize (cmap_handle);
262  return (err);
263 }
264 
265 static void quorum_notification_fn (
266  quorum_handle_t handle,
267  uint32_t quorate,
268  uint64_t ring_id,
269  uint32_t view_list_entries,
270  uint32_t *view_list)
271 {
272  sam_internal_data.quorate = quorate;
273 }
274 
276  int time_interval,
278 {
279  quorum_callbacks_t quorum_callbacks;
280  uint32_t quorum_type;
281  cs_error_t err;
282 
283  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_NOT_INITIALIZED) {
284  return (CS_ERR_BAD_HANDLE);
285  }
286 
287  if (SAM_RP_MASK (recovery_policy) != SAM_RECOVERY_POLICY_QUIT &&
288  SAM_RP_MASK (recovery_policy) != SAM_RECOVERY_POLICY_RESTART) {
289  return (CS_ERR_INVALID_PARAM);
290  }
291 
292  if (recovery_policy & SAM_RECOVERY_POLICY_QUORUM) {
293  /*
294  * Initialize quorum
295  */
296  quorum_callbacks.quorum_notify_fn = quorum_notification_fn;
297  if ((err = quorum_initialize (&sam_internal_data.quorum_handle, &quorum_callbacks, &quorum_type)) != CS_OK) {
298  goto exit_error;
299  }
300 
301  if ((err = quorum_trackstart (sam_internal_data.quorum_handle, CS_TRACK_CHANGES)) != CS_OK) {
302  goto exit_error_quorum;
303  }
304 
305  if ((err = quorum_fd_get (sam_internal_data.quorum_handle, &sam_internal_data.quorum_fd)) != CS_OK) {
306  goto exit_error_quorum;
307  }
308 
309  /*
310  * Dispatch initial quorate state
311  */
312  if ((err = quorum_dispatch (sam_internal_data.quorum_handle, CS_DISPATCH_ONE)) != CS_OK) {
313  goto exit_error_quorum;
314  }
315  }
316  sam_internal_data.recovery_policy = recovery_policy;
317 
318  sam_internal_data.time_interval = time_interval;
319 
320  sam_internal_data.internal_status = SAM_INTERNAL_STATUS_INITIALIZED;
321 
322  sam_internal_data.warn_signal = SIGTERM;
323 
324  sam_internal_data.am_i_child = 0;
325 
326  sam_internal_data.user_data = NULL;
327  sam_internal_data.user_data_size = 0;
328  sam_internal_data.user_data_allocated = 0;
329 
330  pthread_mutex_init (&sam_internal_data.lock, NULL);
331 
332  return (CS_OK);
333 
334 exit_error_quorum:
335  quorum_finalize (sam_internal_data.quorum_handle);
336 exit_error:
337  return (err);
338 }
339 
340 /*
341  * Wrapper on top of write(2) function. It handles EAGAIN and EINTR states and sends whole buffer if possible.
342  */
343 static size_t sam_safe_write (
344  int d,
345  const void *buf,
346  size_t nbyte)
347 {
348  ssize_t bytes_write;
349  ssize_t tmp_bytes_write;
350 
351  bytes_write = 0;
352 
353  do {
354  tmp_bytes_write = write (d, (const char *)buf + bytes_write,
355  (nbyte - bytes_write > SSIZE_MAX) ? SSIZE_MAX : nbyte - bytes_write);
356 
357  if (tmp_bytes_write == -1) {
358  if (!(errno == EAGAIN || errno == EINTR))
359  return -1;
360  } else {
361  bytes_write += tmp_bytes_write;
362  }
363  } while (bytes_write != nbyte);
364 
365  return (bytes_write);
366 }
367 
368 /*
369  * Wrapper on top of read(2) function. It handles EAGAIN and EINTR states and reads whole buffer if possible.
370  */
371 static size_t sam_safe_read (
372  int d,
373  void *buf,
374  size_t nbyte)
375 {
376  ssize_t bytes_read;
377  ssize_t tmp_bytes_read;
378 
379  bytes_read = 0;
380 
381  do {
382  tmp_bytes_read = read (d, (char *)buf + bytes_read,
383  (nbyte - bytes_read > SSIZE_MAX) ? SSIZE_MAX : nbyte - bytes_read);
384 
385  if (tmp_bytes_read == -1) {
386  if (!(errno == EAGAIN || errno == EINTR))
387  return -1;
388  } else {
389  bytes_read += tmp_bytes_read;
390  }
391 
392  } while (bytes_read != nbyte && tmp_bytes_read != 0);
393 
394  return (bytes_read);
395 }
396 
397 static cs_error_t sam_read_reply (
398  int child_fd_in)
399 {
400  char reply;
401  cs_error_t err;
402 
403  if (sam_safe_read (sam_internal_data.child_fd_in, &reply, sizeof (reply)) != sizeof (reply)) {
404  return (CS_ERR_LIBRARY);
405  }
406 
407  switch (reply) {
408  case SAM_REPLY_ERROR:
409  /*
410  * Read error and return that
411  */
412  if (sam_safe_read (sam_internal_data.child_fd_in, &err, sizeof (err)) != sizeof (err)) {
413  return (CS_ERR_LIBRARY);
414  }
415 
416  return (err);
417  break;
418  case SAM_REPLY_OK:
419  /*
420  * Everything correct
421  */
422  break;
423  default:
424  return (CS_ERR_LIBRARY);
425  break;
426  }
427 
428  return (CS_OK);
429 }
430 
432 {
433  if (size == NULL) {
434  return (CS_ERR_INVALID_PARAM);
435  }
436 
437  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED &&
438  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED &&
439  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_STARTED) {
440 
441  return (CS_ERR_BAD_HANDLE);
442  }
443 
444  pthread_mutex_lock (&sam_internal_data.lock);
445 
446  *size = sam_internal_data.user_data_size;
447 
448  pthread_mutex_unlock (&sam_internal_data.lock);
449 
450  return (CS_OK);
451 }
452 
454  void *data,
455  size_t size)
456 {
457  cs_error_t err;
458 
459  err = CS_OK;
460 
461  if (data == NULL) {
462  return (CS_ERR_INVALID_PARAM);
463  }
464 
465  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED &&
466  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED &&
467  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_STARTED) {
468 
469  return (CS_ERR_BAD_HANDLE);
470  }
471 
472  pthread_mutex_lock (&sam_internal_data.lock);
473 
474  if (sam_internal_data.user_data_size == 0) {
475  err = CS_OK;
476 
477  goto error_unlock;
478  }
479 
480  if (size < sam_internal_data.user_data_size) {
481  err = CS_ERR_INVALID_PARAM;
482 
483  goto error_unlock;
484  }
485 
486  memcpy (data, sam_internal_data.user_data, sam_internal_data.user_data_size);
487 
488  pthread_mutex_unlock (&sam_internal_data.lock);
489 
490  return (CS_OK);
491 
492 error_unlock:
493  pthread_mutex_unlock (&sam_internal_data.lock);
494 
495  return (err);
496 }
497 
499  const void *data,
500  size_t size)
501 {
502  cs_error_t err;
503  char command;
504  char *new_data;
505 
506  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED &&
507  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED &&
508  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_STARTED) {
509 
510  return (CS_ERR_BAD_HANDLE);
511  }
512 
513 
514  if (data == NULL) {
515  size = 0;
516  }
517 
518  pthread_mutex_lock (&sam_internal_data.lock);
519 
520  if (sam_internal_data.am_i_child) {
521  /*
522  * We are child so we must send data to parent
523  */
524  command = SAM_COMMAND_DATA_STORE;
525  if (sam_safe_write (sam_internal_data.child_fd_out, &command, sizeof (command)) != sizeof (command)) {
526  err = CS_ERR_LIBRARY;
527 
528  goto error_unlock;
529  }
530 
531  if (sam_safe_write (sam_internal_data.child_fd_out, &size, sizeof (size)) != sizeof (size)) {
532  err = CS_ERR_LIBRARY;
533 
534  goto error_unlock;
535  }
536 
537  if (data != NULL && sam_safe_write (sam_internal_data.child_fd_out, data, size) != size) {
538  err = CS_ERR_LIBRARY;
539 
540  goto error_unlock;
541  }
542 
543  /*
544  * And wait for reply
545  */
546  if ((err = sam_read_reply (sam_internal_data.child_fd_in)) != CS_OK) {
547  goto error_unlock;
548  }
549  }
550 
551  /*
552  * We are parent or we received OK reply from parent -> do required action
553  */
554  if (data == NULL) {
555  free (sam_internal_data.user_data);
556  sam_internal_data.user_data = NULL;
557  sam_internal_data.user_data_allocated = 0;
558  sam_internal_data.user_data_size = 0;
559  } else {
560  if (sam_internal_data.user_data_allocated < size) {
561  if ((new_data = realloc (sam_internal_data.user_data, size)) == NULL) {
562  err = CS_ERR_NO_MEMORY;
563 
564  goto error_unlock;
565  }
566 
567  sam_internal_data.user_data_allocated = size;
568  } else {
569  new_data = sam_internal_data.user_data;
570  }
571  sam_internal_data.user_data = new_data;
572  sam_internal_data.user_data_size = size;
573 
574  memcpy (sam_internal_data.user_data, data, size);
575  }
576 
577  pthread_mutex_unlock (&sam_internal_data.lock);
578 
579  return (CS_OK);
580 
581 error_unlock:
582  pthread_mutex_unlock (&sam_internal_data.lock);
583 
584  return (err);
585 }
586 
588 {
589  char command;
590  cs_error_t err;
591  sam_recovery_policy_t recpol;
592 
593  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED) {
594  return (CS_ERR_BAD_HANDLE);
595  }
596 
597  recpol = sam_internal_data.recovery_policy;
598 
599  if (recpol & SAM_RECOVERY_POLICY_QUORUM || recpol & SAM_RECOVERY_POLICY_CMAP) {
600  pthread_mutex_lock (&sam_internal_data.lock);
601  }
602 
603  command = SAM_COMMAND_START;
604 
605  if (sam_safe_write (sam_internal_data.child_fd_out, &command, sizeof (command)) != sizeof (command)) {
606  if (recpol & SAM_RECOVERY_POLICY_QUORUM || recpol & SAM_RECOVERY_POLICY_CMAP) {
607  pthread_mutex_unlock (&sam_internal_data.lock);
608  }
609 
610  return (CS_ERR_LIBRARY);
611  }
612 
613  if (recpol & SAM_RECOVERY_POLICY_QUORUM || recpol & SAM_RECOVERY_POLICY_CMAP) {
614  /*
615  * Wait for parent reply
616  */
617  if ((err = sam_read_reply (sam_internal_data.child_fd_in)) != CS_OK) {
618  pthread_mutex_unlock (&sam_internal_data.lock);
619 
620  return (err);
621  }
622 
623  pthread_mutex_unlock (&sam_internal_data.lock);
624  }
625 
626  if (sam_internal_data.hc_callback)
627  if (sam_safe_write (sam_internal_data.cb_wpipe_fd, &command, sizeof (command)) != sizeof (command))
628  return (CS_ERR_LIBRARY);
629 
630  sam_internal_data.internal_status = SAM_INTERNAL_STATUS_STARTED;
631 
632  return (CS_OK);
633 }
634 
636 {
637  char command;
638  cs_error_t err;
639 
640  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_STARTED) {
641  return (CS_ERR_BAD_HANDLE);
642  }
643 
644  command = SAM_COMMAND_STOP;
645 
646  if (sam_internal_data.recovery_policy & SAM_RECOVERY_POLICY_CMAP) {
647  pthread_mutex_lock (&sam_internal_data.lock);
648  }
649 
650  if (sam_safe_write (sam_internal_data.child_fd_out, &command, sizeof (command)) != sizeof (command)) {
651  if (sam_internal_data.recovery_policy & SAM_RECOVERY_POLICY_CMAP) {
652  pthread_mutex_unlock (&sam_internal_data.lock);
653  }
654 
655  return (CS_ERR_LIBRARY);
656  }
657 
658  if (sam_internal_data.recovery_policy & SAM_RECOVERY_POLICY_CMAP) {
659  /*
660  * Wait for parent reply
661  */
662  if ((err = sam_read_reply (sam_internal_data.child_fd_in)) != CS_OK) {
663  pthread_mutex_unlock (&sam_internal_data.lock);
664 
665  return (err);
666  }
667 
668  pthread_mutex_unlock (&sam_internal_data.lock);
669  }
670 
671  if (sam_internal_data.hc_callback)
672  if (sam_safe_write (sam_internal_data.cb_wpipe_fd, &command, sizeof (command)) != sizeof (command))
673  return (CS_ERR_LIBRARY);
674 
675  sam_internal_data.internal_status = SAM_INTERNAL_STATUS_REGISTERED;
676 
677  return (CS_OK);
678 }
679 
681 {
682  char command;
683 
684  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_STARTED) {
685  return (CS_ERR_BAD_HANDLE);
686  }
687 
688  command = SAM_COMMAND_HB;
689 
690  if (sam_safe_write (sam_internal_data.child_fd_out, &command, sizeof (command)) != sizeof (command))
691  return (CS_ERR_LIBRARY);
692 
693  return (CS_OK);
694 }
695 
697 {
698  cs_error_t error;
699 
700  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED &&
701  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED &&
702  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_STARTED) {
703  return (CS_ERR_BAD_HANDLE);
704  }
705 
706  if (sam_internal_data.internal_status == SAM_INTERNAL_STATUS_STARTED) {
707  error = sam_stop ();
708  if (error != CS_OK)
709  goto exit_error;
710  }
711 
712  sam_internal_data.internal_status = SAM_INTERNAL_STATUS_FINALIZED;
713 
714  free (sam_internal_data.user_data);
715 
716 exit_error:
717  return (CS_OK);
718 }
719 
721 {
722  char command;
723 
724  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_STARTED &&
725  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED) {
726  return (CS_ERR_BAD_HANDLE);
727  }
728 
729  if (!(sam_internal_data.recovery_policy & SAM_RECOVERY_POLICY_CMAP)) {
730  return (CS_ERR_INVALID_PARAM);
731  }
732 
733  command = SAM_COMMAND_MARK_FAILED;
734 
735  if (sam_safe_write (sam_internal_data.child_fd_out, &command, sizeof (command)) != sizeof (command))
736  return (CS_ERR_LIBRARY);
737 
738  return (CS_OK);
739 }
740 
742 {
743  char command;
744  cs_error_t err;
745 
746  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED &&
747  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED &&
748  sam_internal_data.internal_status != SAM_INTERNAL_STATUS_STARTED) {
749  return (CS_ERR_BAD_HANDLE);
750  }
751 
752  pthread_mutex_lock (&sam_internal_data.lock);
753 
754  if (sam_internal_data.am_i_child) {
755  /*
756  * We are child so we must send data to parent
757  */
758  command = SAM_COMMAND_WARN_SIGNAL_SET;
759  if (sam_safe_write (sam_internal_data.child_fd_out, &command, sizeof (command)) != sizeof (command)) {
760  err = CS_ERR_LIBRARY;
761 
762  goto error_unlock;
763  }
764 
765  if (sam_safe_write (sam_internal_data.child_fd_out, &warn_signal, sizeof (warn_signal)) !=
766  sizeof (warn_signal)) {
767  err = CS_ERR_LIBRARY;
768 
769  goto error_unlock;
770  }
771 
772  /*
773  * And wait for reply
774  */
775  if ((err = sam_read_reply (sam_internal_data.child_fd_in)) != CS_OK) {
776  goto error_unlock;
777  }
778  }
779 
780  /*
781  * We are parent or we received OK reply from parent -> do required action
782  */
783  sam_internal_data.warn_signal = warn_signal;
784 
785  pthread_mutex_unlock (&sam_internal_data.lock);
786 
787  return (CS_OK);
788 
789 error_unlock:
790  pthread_mutex_unlock (&sam_internal_data.lock);
791 
792  return (err);
793 }
794 
795 static cs_error_t sam_parent_reply_send (
796  cs_error_t err,
797  int parent_fd_in,
798  int parent_fd_out)
799 {
800  char reply;
801 
802  if (err == CS_OK) {
803  reply = SAM_REPLY_OK;
804 
805  if (sam_safe_write (parent_fd_out, &reply, sizeof (reply)) != sizeof (reply)) {
806  err = CS_ERR_LIBRARY;
807  goto error_reply;
808  }
809 
810  return (CS_OK);
811  }
812 
813 error_reply:
814  reply = SAM_REPLY_ERROR;
815  if (sam_safe_write (parent_fd_out, &reply, sizeof (reply)) != sizeof (reply)) {
816  return (CS_ERR_LIBRARY);
817  }
818  if (sam_safe_write (parent_fd_out, &err, sizeof (err)) != sizeof (err)) {
819  return (CS_ERR_LIBRARY);
820  }
821 
822  return (err);
823 }
824 
825 
826 static cs_error_t sam_parent_warn_signal_set (
827  int parent_fd_in,
828  int parent_fd_out)
829 {
830  int warn_signal;
831  cs_error_t err;
832 
833  err = CS_OK;
834 
835  if (sam_safe_read (parent_fd_in, &warn_signal, sizeof (warn_signal)) != sizeof (warn_signal)) {
836  err = CS_ERR_LIBRARY;
837  goto error_reply;
838  }
839 
840  err = sam_warn_signal_set (warn_signal);
841  if (err != CS_OK) {
842  goto error_reply;
843  }
844 
845 
846  return (sam_parent_reply_send (CS_OK, parent_fd_in, parent_fd_out));
847 
848 error_reply:
849  return (sam_parent_reply_send (err, parent_fd_in, parent_fd_out));
850 }
851 
852 static cs_error_t sam_parent_wait_for_quorum (
853  int parent_fd_in,
854  int parent_fd_out)
855 {
856  cs_error_t err;
857  struct pollfd pfds[2];
858  int poll_err;
859 
860  if (sam_internal_data.recovery_policy & SAM_RECOVERY_POLICY_CMAP) {
861  if ((err = sam_cmap_update_key (SAM_CMAP_KEY_STATE, SAM_CMAP_S_Q_WAIT)) != CS_OK) {
862  goto error_reply;
863  }
864  }
865 
866  /*
867  * Update current quorum
868  */
869  if ((err = quorum_dispatch (sam_internal_data.quorum_handle, CS_DISPATCH_ALL)) != CS_OK) {
870  goto error_reply;
871  }
872 
873  /*
874  * Wait for quorum
875  */
876  while (!sam_internal_data.quorate) {
877  pfds[0].fd = parent_fd_in;
878  pfds[0].events = 0;
879  pfds[0].revents = 0;
880 
881  pfds[1].fd = sam_internal_data.quorum_fd;
882  pfds[1].events = POLLIN;
883  pfds[1].revents = 0;
884 
885  poll_err = poll (pfds, 2, -1);
886 
887  if (poll_err == -1) {
888  /*
889  * Error in poll
890  * If it is EINTR, continue, otherwise QUIT
891  */
892  if (errno != EINTR) {
893  err = CS_ERR_LIBRARY;
894  goto error_reply;
895  }
896  }
897 
898  if (pfds[0].revents != 0) {
899  if (pfds[0].revents == POLLERR || pfds[0].revents == POLLHUP ||pfds[0].revents == POLLNVAL) {
900  /*
901  * Child has exited
902  */
903  return (CS_OK);
904  }
905  }
906 
907  if (pfds[1].revents != 0) {
908  if ((err = quorum_dispatch (sam_internal_data.quorum_handle, CS_DISPATCH_ONE)) != CS_OK) {
909  goto error_reply;
910  }
911  }
912  }
913 
914  if (sam_internal_data.recovery_policy & SAM_RECOVERY_POLICY_CMAP) {
915  if ((err = sam_cmap_update_key (SAM_CMAP_KEY_STATE, SAM_CMAP_S_STARTED)) != CS_OK) {
916  goto error_reply;
917  }
918  }
919 
920  return (sam_parent_reply_send (CS_OK, parent_fd_in, parent_fd_out));
921 
922 error_reply:
923  if (sam_internal_data.recovery_policy & SAM_RECOVERY_POLICY_CMAP) {
924  sam_cmap_update_key (SAM_CMAP_KEY_STATE, SAM_CMAP_S_REGISTERED);
925  }
926 
927  return (sam_parent_reply_send (err, parent_fd_in, parent_fd_out));
928 }
929 
930 static cs_error_t sam_parent_cmap_state_set (
931  int parent_fd_in,
932  int parent_fd_out,
933  int state)
934 {
935  cs_error_t err;
936  const char *state_s;
937 
938  if (state == 1) {
939  state_s = SAM_CMAP_S_STARTED;
940  } else {
941  state_s = SAM_CMAP_S_REGISTERED;
942  }
943 
944  if ((err = sam_cmap_update_key (SAM_CMAP_KEY_STATE, state_s)) != CS_OK) {
945  goto error_reply;
946  }
947 
948  return (sam_parent_reply_send (CS_OK, parent_fd_in, parent_fd_out));
949 
950 error_reply:
951  return (sam_parent_reply_send (err, parent_fd_in, parent_fd_out));
952 }
953 
954 static cs_error_t sam_parent_kill_child (
955  int *action,
956  pid_t child_pid)
957 {
958  /*
959  * Kill child process
960  */
961  if (!sam_internal_data.term_send) {
962  /*
963  * We didn't send warn_signal yet.
964  */
965  kill (child_pid, sam_internal_data.warn_signal);
966 
967  sam_internal_data.term_send = 1;
968  } else {
969  /*
970  * We sent child warning. Now, we will not be so nice
971  */
972  kill (child_pid, SIGKILL);
973  *action = SAM_PARENT_ACTION_RECOVERY;
974  }
975 
976  return (CS_OK);
977 }
978 
979 static cs_error_t sam_parent_mark_child_failed (
980  int *action,
981  pid_t child_pid)
982 {
983  sam_recovery_policy_t recpol;
984 
985  recpol = sam_internal_data.recovery_policy;
986 
987  sam_internal_data.term_send = 1;
988  sam_internal_data.recovery_policy = SAM_RECOVERY_POLICY_QUIT |
989  (SAM_RP_MASK_C (recpol) ? SAM_RECOVERY_POLICY_CMAP : 0) |
990  (SAM_RP_MASK_Q (recpol) ? SAM_RECOVERY_POLICY_QUORUM : 0);
991 
992  return (sam_parent_kill_child (action, child_pid));
993 }
994 
995 static cs_error_t sam_parent_data_store (
996  int parent_fd_in,
997  int parent_fd_out)
998 {
999  char *user_data;
1000  ssize_t size;
1001  cs_error_t err;
1002 
1003  err = CS_OK;
1004  user_data = NULL;
1005 
1006  if (sam_safe_read (parent_fd_in, &size, sizeof (size)) != sizeof (size)) {
1007  err = CS_ERR_LIBRARY;
1008  goto error_reply;
1009  }
1010 
1011  if (size > 0) {
1012  user_data = malloc (size);
1013  if (user_data == NULL) {
1014  err = CS_ERR_NO_MEMORY;
1015  goto error_reply;
1016  }
1017 
1018  if (sam_safe_read (parent_fd_in, user_data, size) != size) {
1019  err = CS_ERR_LIBRARY;
1020  goto free_error_reply;
1021  }
1022  }
1023 
1024  err = sam_data_store (user_data, size);
1025  if (err != CS_OK) {
1026  goto free_error_reply;
1027  }
1028 
1029  free (user_data);
1030 
1031  return (sam_parent_reply_send (CS_OK, parent_fd_in, parent_fd_out));
1032 
1033 free_error_reply:
1034  free (user_data);
1035 error_reply:
1036  return (sam_parent_reply_send (err, parent_fd_in, parent_fd_out));
1037 }
1038 
1039 static enum sam_parent_action_t sam_parent_handler (
1040  int parent_fd_in,
1041  int parent_fd_out,
1042  pid_t child_pid)
1043 {
1044  int poll_error;
1045  int action;
1046  int status;
1047  ssize_t bytes_read;
1048  char command;
1049  int time_interval;
1050  struct pollfd pfds[2];
1051  nfds_t nfds;
1052  cs_error_t err;
1053  sam_recovery_policy_t recpol;
1054 
1055  status = 0;
1056 
1057  action = SAM_PARENT_ACTION_CONTINUE;
1058  recpol = sam_internal_data.recovery_policy;
1059 
1060  while (action == SAM_PARENT_ACTION_CONTINUE) {
1061  pfds[0].fd = parent_fd_in;
1062  pfds[0].events = POLLIN;
1063  pfds[0].revents = 0;
1064  nfds = 1;
1065 
1066  if (status == 1 && sam_internal_data.time_interval != 0) {
1067  time_interval = sam_internal_data.time_interval;
1068  } else {
1069  time_interval = -1;
1070  }
1071 
1072  if (recpol & SAM_RECOVERY_POLICY_QUORUM) {
1073  pfds[nfds].fd = sam_internal_data.quorum_fd;
1074  pfds[nfds].events = POLLIN;
1075  pfds[nfds].revents = 0;
1076  nfds++;
1077  }
1078 
1079  poll_error = poll (pfds, nfds, time_interval);
1080 
1081  if (poll_error == -1) {
1082  /*
1083  * Error in poll
1084  * If it is EINTR, continue, otherwise QUIT
1085  */
1086  if (errno != EINTR) {
1087  action = SAM_PARENT_ACTION_ERROR;
1088  }
1089  }
1090 
1091  if (poll_error == 0) {
1092  /*
1093  * Time limit expires
1094  */
1095  if (status == 0) {
1096  action = SAM_PARENT_ACTION_QUIT;
1097  } else {
1098  sam_parent_kill_child (&action, child_pid);
1099  }
1100  }
1101 
1102  if (poll_error > 0) {
1103  if (pfds[0].revents != 0) {
1104  /*
1105  * We have EOF or command in pipe
1106  */
1107  bytes_read = sam_safe_read (parent_fd_in, &command, 1);
1108 
1109  if (bytes_read == 0) {
1110  /*
1111  * Handle EOF -> Take recovery action or quit if sam_start wasn't called
1112  */
1113  if (status == 0)
1114  action = SAM_PARENT_ACTION_QUIT;
1115  else
1116  action = SAM_PARENT_ACTION_RECOVERY;
1117 
1118  continue;
1119  }
1120 
1121  if (bytes_read == -1) {
1122  action = SAM_PARENT_ACTION_ERROR;
1123  goto action_exit;
1124  }
1125 
1126  if (recpol & SAM_RECOVERY_POLICY_CMAP) {
1127  sam_cmap_update_key (SAM_CMAP_KEY_LAST_HC, NULL);
1128  }
1129 
1130  /*
1131  * We have read command
1132  */
1133  switch (command) {
1134  case SAM_COMMAND_START:
1135  if (status == 0) {
1136  /*
1137  * Not started yet
1138  */
1139  if (recpol & SAM_RECOVERY_POLICY_QUORUM) {
1140  if (sam_parent_wait_for_quorum (parent_fd_in,
1141  parent_fd_out) != CS_OK) {
1142  continue;
1143  }
1144  }
1145 
1146  if (recpol & SAM_RECOVERY_POLICY_CMAP) {
1147  if (sam_parent_cmap_state_set (parent_fd_in,
1148  parent_fd_out, 1) != CS_OK) {
1149  continue;
1150  }
1151  }
1152 
1153  status = 1;
1154  }
1155  break;
1156  case SAM_COMMAND_STOP:
1157  if (status == 1) {
1158  /*
1159  * Started
1160  */
1161  if (recpol & SAM_RECOVERY_POLICY_CMAP) {
1162  if (sam_parent_cmap_state_set (parent_fd_in,
1163  parent_fd_out, 0) != CS_OK) {
1164  continue;
1165  }
1166  }
1167 
1168  status = 0;
1169  }
1170  break;
1172  sam_parent_data_store (parent_fd_in, parent_fd_out);
1173  break;
1175  sam_parent_warn_signal_set (parent_fd_in, parent_fd_out);
1176  break;
1178  status = 1;
1179  sam_parent_mark_child_failed (&action, child_pid);
1180  break;
1181  }
1182  } /* if (pfds[0].revents != 0) */
1183 
1184  if ((sam_internal_data.recovery_policy & SAM_RECOVERY_POLICY_QUORUM) &&
1185  pfds[1].revents != 0) {
1186  /*
1187  * Handle quorum change
1188  */
1189  err = quorum_dispatch (sam_internal_data.quorum_handle, CS_DISPATCH_ALL);
1190 
1191  if (status == 1 &&
1192  (!sam_internal_data.quorate || (err != CS_ERR_TRY_AGAIN && err != CS_OK))) {
1193  sam_parent_kill_child (&action, child_pid);
1194  }
1195  }
1196  } /* select_error > 0 */
1197  } /* action == SAM_PARENT_ACTION_CONTINUE */
1198 
1199 action_exit:
1200  return action;
1201 }
1202 
1204  unsigned int *instance_id)
1205 {
1206  cs_error_t error;
1207  pid_t pid;
1208  int pipe_error;
1209  int pipe_fd_out[2], pipe_fd_in[2];
1210  enum sam_parent_action_t action, old_action;
1211  int child_status;
1212  sam_recovery_policy_t recpol;
1213 
1214  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED) {
1215  return (CS_ERR_BAD_HANDLE);
1216  }
1217 
1218  recpol = sam_internal_data.recovery_policy;
1219 
1220  if (recpol & SAM_RECOVERY_POLICY_CMAP) {
1221  /*
1222  * Register to cmap
1223  */
1224  if ((error = sam_cmap_register ()) != CS_OK) {
1225  goto error_exit;
1226  }
1227  }
1228 
1229  error = CS_OK;
1230 
1231  while (1) {
1232  if ((pipe_error = pipe (pipe_fd_out)) != 0) {
1233  error = CS_ERR_LIBRARY;
1234  goto error_exit;
1235  }
1236 
1237  if ((pipe_error = pipe (pipe_fd_in)) != 0) {
1238  close (pipe_fd_out[0]);
1239  close (pipe_fd_out[1]);
1240 
1241  error = CS_ERR_LIBRARY;
1242  goto error_exit;
1243  }
1244 
1245  if (recpol & SAM_RECOVERY_POLICY_CMAP) {
1246  if ((error = sam_cmap_update_key (SAM_CMAP_KEY_STATE, SAM_CMAP_S_REGISTERED)) != CS_OK) {
1247  goto error_exit;
1248  }
1249  }
1250 
1251  sam_internal_data.instance_id++;
1252 
1253  sam_internal_data.term_send = 0;
1254 
1255  pid = fork ();
1256 
1257  if (pid == -1) {
1258  /*
1259  * Fork error
1260  */
1261  sam_internal_data.instance_id--;
1262 
1263  error = CS_ERR_LIBRARY;
1264  goto error_exit;
1265  }
1266 
1267  if (pid == 0) {
1268  /*
1269  * Child process
1270  */
1271  close (pipe_fd_out[0]);
1272  close (pipe_fd_in[1]);
1273 
1274  sam_internal_data.child_fd_out = pipe_fd_out[1];
1275  sam_internal_data.child_fd_in = pipe_fd_in[0];
1276 
1277  if (instance_id)
1278  *instance_id = sam_internal_data.instance_id;
1279 
1280  sam_internal_data.am_i_child = 1;
1281  sam_internal_data.internal_status = SAM_INTERNAL_STATUS_REGISTERED;
1282 
1283  pthread_mutex_init (&sam_internal_data.lock, NULL);
1284 
1285  goto error_exit;
1286  } else {
1287  /*
1288  * Parent process
1289  */
1290  close (pipe_fd_out[1]);
1291  close (pipe_fd_in[0]);
1292 
1293  action = sam_parent_handler (pipe_fd_out[0], pipe_fd_in[1], pid);
1294 
1295  close (pipe_fd_out[0]);
1296  close (pipe_fd_in[1]);
1297 
1298  if (action == SAM_PARENT_ACTION_ERROR) {
1299  error = CS_ERR_LIBRARY;
1300  goto error_exit;
1301  }
1302 
1303  /*
1304  * We really don't like zombies
1305  */
1306  while (waitpid (pid, &child_status, 0) == -1 && errno == EINTR)
1307  ;
1308 
1309  old_action = action;
1310 
1311  if (action == SAM_PARENT_ACTION_RECOVERY) {
1312  if (SAM_RP_MASK (sam_internal_data.recovery_policy) == SAM_RECOVERY_POLICY_QUIT)
1313  action = SAM_PARENT_ACTION_QUIT;
1314  }
1315 
1316 
1317  if (action == SAM_PARENT_ACTION_QUIT) {
1318  if (recpol & SAM_RECOVERY_POLICY_QUORUM) {
1319  quorum_finalize (sam_internal_data.quorum_handle);
1320  }
1321 
1322  if (recpol & SAM_RECOVERY_POLICY_CMAP) {
1323  if (old_action == SAM_PARENT_ACTION_RECOVERY) {
1324  /*
1325  * Mark as failed
1326  */
1327  sam_cmap_update_key (SAM_CMAP_KEY_STATE, SAM_CMAP_S_FAILED);
1328  } else {
1329  sam_cmap_destroy_pid_path ();
1330  }
1331  }
1332 
1333  exit (WEXITSTATUS (child_status));
1334  }
1335 
1336 
1337  }
1338  }
1339 
1340 error_exit:
1341  return (error);
1342 }
1343 
1344 static void *hc_callback_thread (void *unused_param)
1345 {
1346  int poll_error;
1347  int status;
1348  ssize_t bytes_readed;
1349  char command;
1350  int time_interval, tmp_time_interval;
1351  int counter;
1352  struct pollfd pfds;
1353 
1354  status = 0;
1355  counter = 0;
1356 
1357  time_interval = sam_internal_data.time_interval >> 2;
1358 
1359  while (1) {
1360  pfds.fd = sam_internal_data.cb_rpipe_fd;
1361  pfds.events = POLLIN;
1362  pfds.revents = 0;
1363 
1364  if (status == 1) {
1365  tmp_time_interval = time_interval;
1366  } else {
1367  tmp_time_interval = -1;
1368  }
1369 
1370  poll_error = poll (&pfds, 1, tmp_time_interval);
1371 
1372  if (poll_error == 0) {
1373  if (sam_hc_send () == CS_OK) {
1374  counter++;
1375  }
1376 
1377  if (counter >= 4) {
1378  if (sam_internal_data.hc_callback () != 0) {
1379  status = 3;
1380  }
1381 
1382  counter = 0;
1383  }
1384  }
1385 
1386  if (poll_error > 0) {
1387  bytes_readed = sam_safe_read (sam_internal_data.cb_rpipe_fd, &command, 1);
1388 
1389  if (bytes_readed > 0) {
1390  if (status == 0 && command == SAM_COMMAND_START)
1391  status = 1;
1392 
1393  if (status == 1 && command == SAM_COMMAND_STOP)
1394  status = 0;
1395 
1396  }
1397  }
1398  }
1399 
1400  /*
1401  * This makes compiler happy, it's same as return (NULL);
1402  */
1403  return (unused_param);
1404 }
1405 
1407 {
1408  cs_error_t error = CS_OK;
1409  pthread_attr_t thread_attr;
1410  int pipe_error;
1411  int pipe_fd[2];
1412 
1413  if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_REGISTERED) {
1414  return (CS_ERR_BAD_HANDLE);
1415  }
1416 
1417  if (sam_internal_data.time_interval == 0) {
1418  return (CS_ERR_INVALID_PARAM);
1419  }
1420 
1421  if (sam_internal_data.cb_registered) {
1422  sam_internal_data.hc_callback = cb;
1423 
1424  return (CS_OK);
1425  }
1426 
1427  /*
1428  * We know, this is first registration
1429  */
1430 
1431  if (cb == NULL) {
1432  return (CS_ERR_INVALID_PARAM);
1433  }
1434 
1435  pipe_error = pipe (pipe_fd);
1436 
1437  if (pipe_error != 0) {
1438  /*
1439  * Pipe creation error
1440  */
1441  error = CS_ERR_LIBRARY;
1442  goto error_exit;
1443  }
1444 
1445  sam_internal_data.cb_rpipe_fd = pipe_fd[0];
1446  sam_internal_data.cb_wpipe_fd = pipe_fd[1];
1447 
1448  /*
1449  * Create thread attributes
1450  */
1451  error = pthread_attr_init (&thread_attr);
1452  if (error != 0) {
1453  error = CS_ERR_LIBRARY;
1454  goto error_close_fd_exit;
1455  }
1456 
1457 
1458  pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);
1459  pthread_attr_setstacksize (&thread_attr, 32768);
1460 
1461  /*
1462  * Create thread
1463  */
1464  error = pthread_create (&sam_internal_data.cb_thread, &thread_attr, hc_callback_thread, NULL);
1465 
1466  if (error != 0) {
1467  error = CS_ERR_LIBRARY;
1468  goto error_attr_destroy_exit;
1469  }
1470 
1471  /*
1472  * Cleanup
1473  */
1474  pthread_attr_destroy(&thread_attr);
1475 
1476  sam_internal_data.cb_registered = 1;
1477  sam_internal_data.hc_callback = cb;
1478 
1479  return (CS_OK);
1480 
1481 error_attr_destroy_exit:
1482  pthread_attr_destroy(&thread_attr);
1483 error_close_fd_exit:
1484  sam_internal_data.cb_rpipe_fd = sam_internal_data.cb_wpipe_fd = 0;
1485  close (pipe_fd[0]);
1486  close (pipe_fd[1]);
1487 error_exit:
1488  return (error);
1489 }
cs_error_t cmap_set_uint64(cmap_handle_t handle, const char *key_name, uint64_t value)
Definition: lib/cmap.c:482
int child_fd_out
Definition: sam.c:116
int time_interval
Definition: sam.c:112
enum sam_internal_status_t internal_status
Definition: sam.c:114
uint32_t value
#define SAM_RP_MASK_Q(pol)
Definition: sam.c:71
#define SAM_RP_MASK(pol)
Definition: sam.c:73
cs_error_t sam_hc_callback_register(sam_hc_callback_t cb)
Register healtcheck callback.
Definition: sam.c:1406
sam_hc_callback_t hc_callback
Definition: sam.c:122
unsigned int instance_id
Definition: sam.c:115
#define SAM_CMAP_S_STARTED
Definition: sam.c:68
cs_error_t quorum_dispatch(quorum_handle_t handle, cs_dispatch_flags_t dispatch_types)
Dispatch messages and configuration changes.
Definition: lib/quorum.c:351
int(* sam_hc_callback_t)(void)
Callback definition for event driven checking.
Definition: sam.h:59
cs_error_t cmap_iter_next(cmap_handle_t handle, cmap_iter_handle_t iter_handle, char key_name[], size_t *value_len, cmap_value_types_t *type)
Return next item in iterator iter.
Definition: lib/cmap.c:878
int cb_registered
Definition: sam.c:125
cmap_handle_t cmap_handle
Definition: sam.c:137
cs_error_t cmap_initialize(cmap_handle_t *handle)
Create a new cmap connection.
Definition: lib/cmap.c:89
The quorum_callbacks_t struct.
const char * __progname
int term_send
Definition: sam.c:118
cs_error_t sam_initialize(int time_interval, sam_recovery_policy_t recovery_policy)
Create a new SAM connection.
Definition: sam.c:275
quorum_handle_t quorum_handle
Definition: sam.c:133
#define CMAP_KEYNAME_MAXLEN
Definition: cmap.h:69
pthread_t cb_thread
Definition: sam.c:123
cs_error_t cmap_iter_init(cmap_handle_t handle, const char *prefix, cmap_iter_handle_t *cmap_iter_handle)
Initialize iterator with given prefix.
Definition: lib/cmap.c:823
int am_i_child
Definition: sam.c:120
#define SAM_CMAP_S_REGISTERED
Definition: sam.c:67
cs_error_t sam_finalize(void)
Close the SAM handle.
Definition: sam.c:696
sam_recovery_policy_t recovery_policy
Definition: sam.c:113
cs_error_t cmap_iter_finalize(cmap_handle_t handle, cmap_iter_handle_t iter_handle)
Finalize iterator.
Definition: lib/cmap.c:938
#define CS_TRACK_CHANGES
Definition: corotypes.h:88
cs_error_t sam_register(unsigned int *instance_id)
Register application.
Definition: sam.c:1203
cs_error_t sam_hc_send(void)
Send healthcheck confirmation.
Definition: sam.c:680
#define SAM_CMAP_S_Q_WAIT
Definition: sam.c:69
size_t user_data_allocated
Definition: sam.c:129
sam_cmap_key_t
Definition: sam.c:104
cs_error_t sam_mark_failed(void)
Marks child as failed.
Definition: sam.c:720
pthread_mutex_t lock
Definition: sam.c:131
void * user_data
Definition: sam.c:127
char cmap_pid_path[CMAP_KEYNAME_MAXLEN]
Definition: sam.c:138
size_t user_data_size
Definition: sam.c:128
cs_error_t
The cs_error_t enum.
Definition: corotypes.h:94
sam_internal_status_t
Definition: sam.c:75
int cb_wpipe_fd
Definition: sam.c:124
cs_error_t sam_data_getsize(size_t *size)
Return size of stored data.
Definition: sam.c:431
cs_error_t cmap_set_string(cmap_handle_t handle, const char *key_name, const char *value)
Definition: lib/cmap.c:497
cs_error_t sam_stop(void)
Stop healthchecking.
Definition: sam.c:635
uint32_t quorate
Definition: sam.c:134
uint64_t quorum_handle_t
quorum_handle_t
sam_reply_t
Definition: sam.c:92
cs_error_t sam_data_store(const void *data, size_t size)
Store user data.
Definition: sam.c:498
cs_error_t sam_warn_signal_set(int warn_signal)
Set warning signal to be sent.
Definition: sam.c:741
cs_error_t cmap_delete(cmap_handle_t handle, const char *key_name)
Deletes key from cmap database.
Definition: lib/cmap.c:507
int cb_rpipe_fd
Definition: sam.c:124
int warn_signal
Definition: sam.c:119
cs_error_t sam_data_restore(void *data, size_t size)
Return stored data.
Definition: sam.c:453
uint64_t cmap_iter_handle_t
Definition: cmap.h:59
cs_error_t quorum_fd_get(quorum_handle_t handle, int *fd)
Get a file descriptor on which to poll.
Definition: lib/quorum.c:212
quorum_notification_fn_t quorum_notify_fn
int child_fd_in
Definition: sam.c:117
sam_recovery_policy_t
sam_recovery_policy_t enum
Definition: sam.h:46
sam_command_t
Definition: sam.c:83
cs_error_t quorum_trackstart(quorum_handle_t handle, unsigned int flags)
Track node and quorum changes.
Definition: lib/quorum.c:271
cs_error_t cmap_finalize(cmap_handle_t handle)
Close the cmap handle.
Definition: lib/cmap.c:173
int quorum_fd
Definition: sam.c:135
struct memb_ring_id ring_id
Definition: totemsrp.c:264
cs_error_t quorum_finalize(quorum_handle_t handle)
Close the quorum handle.
Definition: lib/quorum.c:142
#define SAM_CMAP_S_FAILED
Definition: sam.c:66
cs_error_t sam_start(void)
Start healthchecking.
Definition: sam.c:587
#define SAM_RP_MASK_C(pol)
Definition: sam.c:72
uint64_t cmap_handle_t
Definition: cmap.h:54
cs_error_t quorum_initialize(quorum_handle_t *handle, quorum_callbacks_t *callbacks, uint32_t *quorum_type)
Create a new quorum connection.
Definition: lib/quorum.c:69
sam_parent_action_t
Definition: sam.c:97