1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <errno.h> 33 34 #include "hast.h" 35 #include "hast_proto.h" 36 #include "hooks.h" 37 #include "nv.h" 38 #include "pjdlog.h" 39 #include "proto.h" 40 #include "subr.h" 41 42 #include "event.h" 43 44 void 45 event_send(const struct hast_resource *res, int event) 46 { 47 struct nv *nvin, *nvout; 48 int error; 49 50 PJDLOG_ASSERT(res != NULL); 51 PJDLOG_ASSERT(event >= EVENT_MIN && event <= EVENT_MAX); 52 53 nvin = nvout = NULL; 54 55 /* 56 * Prepare and send event to parent process. 57 */ 58 nvout = nv_alloc(); 59 nv_add_uint8(nvout, (uint8_t)event, "event"); 60 error = nv_error(nvout); 61 if (error != 0) { 62 pjdlog_common(LOG_ERR, 0, error, 63 "Unable to prepare event header"); 64 goto done; 65 } 66 if (hast_proto_send(res, res->hr_event, nvout, NULL, 0) == -1) { 67 pjdlog_errno(LOG_ERR, "Unable to send event header"); 68 goto done; 69 } 70 if (hast_proto_recv_hdr(res->hr_event, &nvin) == -1) { 71 pjdlog_errno(LOG_ERR, "Unable to receive event header"); 72 goto done; 73 } 74 /* 75 * Do nothing with the answer. We only wait for it to be sure not 76 * to exit too quickly after sending an event and exiting immediately. 77 */ 78 done: 79 if (nvin != NULL) 80 nv_free(nvin); 81 if (nvout != NULL) 82 nv_free(nvout); 83 } 84 85 int 86 event_recv(const struct hast_resource *res) 87 { 88 struct nv *nvin, *nvout; 89 const char *evstr; 90 uint8_t event; 91 int error; 92 93 PJDLOG_ASSERT(res != NULL); 94 95 nvin = nvout = NULL; 96 97 if (hast_proto_recv_hdr(res->hr_event, &nvin) == -1) { 98 /* 99 * First error log as debug. This is because worker process 100 * most likely exited. 101 */ 102 pjdlog_common(LOG_DEBUG, 1, errno, 103 "Unable to receive event header"); 104 goto fail; 105 } 106 107 event = nv_get_uint8(nvin, "event"); 108 if (event == EVENT_NONE) { 109 pjdlog_error("Event header is missing 'event' field."); 110 goto fail; 111 } 112 113 switch (event) { 114 case EVENT_CONNECT: 115 evstr = "connect"; 116 break; 117 case EVENT_DISCONNECT: 118 evstr = "disconnect"; 119 break; 120 case EVENT_SYNCSTART: 121 evstr = "syncstart"; 122 break; 123 case EVENT_SYNCDONE: 124 evstr = "syncdone"; 125 break; 126 case EVENT_SYNCINTR: 127 evstr = "syncintr"; 128 break; 129 case EVENT_SPLITBRAIN: 130 evstr = "split-brain"; 131 break; 132 default: 133 pjdlog_error("Event header contain invalid event number (%hhu).", 134 event); 135 goto fail; 136 } 137 138 pjdlog_prefix_set("[%s] (%s) ", res->hr_name, role2str(res->hr_role)); 139 hook_exec(res->hr_exec, evstr, res->hr_name, NULL); 140 pjdlog_prefix_set("%s", ""); 141 142 nvout = nv_alloc(); 143 nv_add_int16(nvout, 0, "error"); 144 error = nv_error(nvout); 145 if (error != 0) { 146 pjdlog_common(LOG_ERR, 0, error, 147 "Unable to prepare event header"); 148 goto fail; 149 } 150 if (hast_proto_send(res, res->hr_event, nvout, NULL, 0) == -1) { 151 pjdlog_errno(LOG_ERR, "Unable to send event header"); 152 goto fail; 153 } 154 nv_free(nvin); 155 nv_free(nvout); 156 return (0); 157 fail: 158 if (nvin != NULL) 159 nv_free(nvin); 160 if (nvout != NULL) 161 nv_free(nvout); 162 return (-1); 163 } 164