corosync 3.1.7
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
103
109};
110
111static struct {
115 unsigned int instance_id;
121
123 pthread_t cb_thread;
126
130
131 pthread_mutex_t lock;
132
134 uint32_t quorate;
136
139} sam_internal_data;
140
141extern const char *__progname;
142
143static 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
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
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
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;
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
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
211exit_error:
212 return (err);
213}
214
215static cs_error_t sam_cmap_destroy_pid_path (void)
216{
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
232error_exit:
233 return (err);
234}
235
236static 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
259destroy_finalize_error:
260 sam_cmap_destroy_pid_path ();
262 return (err);
263}
264
265static 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
289 return (CS_ERR_INVALID_PARAM);
290 }
291
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
334exit_error_quorum:
335 quorum_finalize (sam_internal_data.quorum_handle);
336exit_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 */
343static 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 */
371static 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
397static 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) {
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
492error_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
581error_unlock:
582 pthread_mutex_unlock (&sam_internal_data.lock);
583
584 return (err);
585}
586
588{
589 char command;
590 cs_error_t err;
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
716exit_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 */
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
789error_unlock:
790 pthread_mutex_unlock (&sam_internal_data.lock);
791
792 return (err);
793}
794
795static 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
813error_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
826static 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
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
848error_reply:
849 return (sam_parent_reply_send (err, parent_fd_in, parent_fd_out));
850}
851
852static 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
922error_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
930static 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
950error_reply:
951 return (sam_parent_reply_send (err, parent_fd_in, parent_fd_out));
952}
953
954static 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);
974 }
975
976 return (CS_OK);
977}
978
979static cs_error_t sam_parent_mark_child_failed (
980 int *action,
981 pid_t child_pid)
982{
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) |
991
992 return (sam_parent_kill_child (action, child_pid));
993}
994
995static 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
1033free_error_reply:
1034 free (user_data);
1035error_reply:
1036 return (sam_parent_reply_send (err, parent_fd_in, parent_fd_out));
1037}
1038
1039static 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
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
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
1199action_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
1340error_exit:
1341 return (error);
1342}
1343
1344static 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
1481error_attr_destroy_exit:
1482 pthread_attr_destroy(&thread_attr);
1483error_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]);
1487error_exit:
1488 return (error);
1489}
@ CS_DISPATCH_ONE
Definition: corotypes.h:85
@ CS_DISPATCH_ALL
Definition: corotypes.h:86
#define CS_TRACK_CHANGES
Definition: corotypes.h:92
cs_error_t
The cs_error_t enum.
Definition: corotypes.h:98
@ CS_ERR_NAME_TOO_LONG
Definition: corotypes.h:111
@ CS_ERR_NO_MEMORY
Definition: corotypes.h:106
@ CS_ERR_BAD_HANDLE
Definition: corotypes.h:107
@ CS_ERR_TRY_AGAIN
Definition: corotypes.h:104
@ CS_OK
Definition: corotypes.h:99
@ CS_ERR_INVALID_PARAM
Definition: corotypes.h:105
@ CS_ERR_LIBRARY
Definition: corotypes.h:100
uint32_t value
uint64_t cmap_iter_handle_t
Definition: cmap.h:59
cs_error_t cmap_finalize(cmap_handle_t handle)
Close the cmap handle.
Definition: lib/cmap.c:173
#define CMAP_KEYNAME_MAXLEN
Definition: cmap.h:69
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
uint64_t cmap_handle_t
Definition: cmap.h:54
cs_error_t cmap_delete(cmap_handle_t handle, const char *key_name)
Deletes key from cmap database.
Definition: lib/cmap.c:507
cs_error_t cmap_initialize(cmap_handle_t *handle)
Create a new cmap connection.
Definition: lib/cmap.c:89
cs_error_t cmap_iter_finalize(cmap_handle_t handle, cmap_iter_handle_t iter_handle)
Finalize iterator.
Definition: lib/cmap.c:938
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
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 cmap_set_uint64(cmap_handle_t handle, const char *key_name, uint64_t value)
Definition: lib/cmap.c:482
uint64_t quorum_handle_t
quorum_handle_t
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:73
cs_error_t quorum_fd_get(quorum_handle_t handle, int *fd)
Get a file descriptor on which to poll.
Definition: lib/quorum.c:279
cs_error_t quorum_trackstart(quorum_handle_t handle, unsigned int flags)
Track node and quorum changes.
Definition: lib/quorum.c:338
cs_error_t quorum_finalize(quorum_handle_t handle)
Close the quorum handle.
Definition: lib/quorum.c:209
cs_error_t quorum_dispatch(quorum_handle_t handle, cs_dispatch_flags_t dispatch_types)
Dispatch messages and configuration changes.
Definition: lib/quorum.c:418
cs_error_t sam_warn_signal_set(int warn_signal)
Set warning signal to be sent.
Definition: sam.c:741
pthread_mutex_t lock
Definition: sam.c:131
void * user_data
Definition: sam.c:127
#define SAM_CMAP_S_FAILED
Definition: sam.c:66
cs_error_t sam_finalize(void)
Close the SAM handle.
Definition: sam.c:696
#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
int cb_wpipe_fd
Definition: sam.c:124
#define SAM_CMAP_S_STARTED
Definition: sam.c:68
#define SAM_CMAP_S_Q_WAIT
Definition: sam.c:69
cs_error_t sam_data_store(const void *data, size_t size)
Store user data.
Definition: sam.c:498
int time_interval
Definition: sam.c:112
unsigned int instance_id
Definition: sam.c:115
sam_command_t
Definition: sam.c:83
@ SAM_COMMAND_MARK_FAILED
Definition: sam.c:89
@ SAM_COMMAND_DATA_STORE
Definition: sam.c:87
@ SAM_COMMAND_HB
Definition: sam.c:86
@ SAM_COMMAND_WARN_SIGNAL_SET
Definition: sam.c:88
@ SAM_COMMAND_START
Definition: sam.c:84
@ SAM_COMMAND_STOP
Definition: sam.c:85
sam_hc_callback_t hc_callback
Definition: sam.c:122
sam_reply_t
Definition: sam.c:92
@ SAM_REPLY_OK
Definition: sam.c:93
@ SAM_REPLY_ERROR
Definition: sam.c:94
quorum_handle_t quorum_handle
Definition: sam.c:133
#define SAM_CMAP_S_REGISTERED
Definition: sam.c:67
int child_fd_out
Definition: sam.c:116
cs_error_t sam_mark_failed(void)
Marks child as failed.
Definition: sam.c:720
#define SAM_RP_MASK_C(pol)
Definition: sam.c:72
int quorum_fd
Definition: sam.c:135
#define SAM_RP_MASK_Q(pol)
Definition: sam.c:71
pthread_t cb_thread
Definition: sam.c:123
cs_error_t sam_data_restore(void *data, size_t size)
Return stored data.
Definition: sam.c:453
sam_recovery_policy_t recovery_policy
Definition: sam.c:113
int cb_registered
Definition: sam.c:125
enum sam_internal_status_t internal_status
Definition: sam.c:114
int term_send
Definition: sam.c:118
sam_cmap_key_t
Definition: sam.c:104
@ SAM_CMAP_KEY_RECOVERY
Definition: sam.c:105
@ SAM_CMAP_KEY_STATE
Definition: sam.c:108
@ SAM_CMAP_KEY_HC_PERIOD
Definition: sam.c:106
@ SAM_CMAP_KEY_LAST_HC
Definition: sam.c:107
sam_internal_status_t
Definition: sam.c:75
@ SAM_INTERNAL_STATUS_STARTED
Definition: sam.c:79
@ SAM_INTERNAL_STATUS_NOT_INITIALIZED
Definition: sam.c:76
@ SAM_INTERNAL_STATUS_FINALIZED
Definition: sam.c:80
@ SAM_INTERNAL_STATUS_REGISTERED
Definition: sam.c:78
@ SAM_INTERNAL_STATUS_INITIALIZED
Definition: sam.c:77
cs_error_t sam_register(unsigned int *instance_id)
Register application.
Definition: sam.c:1203
cs_error_t sam_data_getsize(size_t *size)
Return size of stored data.
Definition: sam.c:431
int warn_signal
Definition: sam.c:119
int cb_rpipe_fd
Definition: sam.c:124
uint32_t quorate
Definition: sam.c:134
cs_error_t sam_stop(void)
Stop healthchecking.
Definition: sam.c:635
int child_fd_in
Definition: sam.c:117
int am_i_child
Definition: sam.c:120
cs_error_t sam_initialize(int time_interval, sam_recovery_policy_t recovery_policy)
Create a new SAM connection.
Definition: sam.c:275
cs_error_t sam_hc_send(void)
Send healthcheck confirmation.
Definition: sam.c:680
char cmap_pid_path[CMAP_KEYNAME_MAXLEN]
Definition: sam.c:138
sam_parent_action_t
Definition: sam.c:97
@ SAM_PARENT_ACTION_ERROR
Definition: sam.c:98
@ SAM_PARENT_ACTION_QUIT
Definition: sam.c:100
@ SAM_PARENT_ACTION_CONTINUE
Definition: sam.c:101
@ SAM_PARENT_ACTION_RECOVERY
Definition: sam.c:99
cs_error_t sam_start(void)
Start healthchecking.
Definition: sam.c:587
const char * __progname
cmap_handle_t cmap_handle
Definition: sam.c:137
size_t user_data_size
Definition: sam.c:128
size_t user_data_allocated
Definition: sam.c:129
sam_recovery_policy_t
sam_recovery_policy_t enum
Definition: sam.h:46
@ SAM_RECOVERY_POLICY_CMAP
Definition: sam.h:52
@ SAM_RECOVERY_POLICY_QUORUM
Definition: sam.h:49
@ SAM_RECOVERY_POLICY_QUIT
Definition: sam.h:47
@ SAM_RECOVERY_POLICY_RESTART
Definition: sam.h:48
int(* sam_hc_callback_t)(void)
Callback definition for event driven checking.
Definition: sam.h:59
The quorum_callbacks_t struct.
quorum_notification_fn_t quorum_notify_fn
struct memb_ring_id ring_id
Definition: totemsrp.c:4