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