1212049Spjd/*-
2212049Spjd * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3212049Spjd * All rights reserved.
4212049Spjd *
5212049Spjd * Redistribution and use in source and binary forms, with or without
6212049Spjd * modification, are permitted provided that the following conditions
7212049Spjd * are met:
8212049Spjd * 1. Redistributions of source code must retain the above copyright
9212049Spjd *    notice, this list of conditions and the following disclaimer.
10212049Spjd * 2. Redistributions in binary form must reproduce the above copyright
11212049Spjd *    notice, this list of conditions and the following disclaimer in the
12212049Spjd *    documentation and/or other materials provided with the distribution.
13212049Spjd *
14212049Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15212049Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16212049Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17212049Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18212049Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19212049Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20212049Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21212049Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22212049Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23212049Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24212049Spjd * SUCH DAMAGE.
25212049Spjd */
26212049Spjd
27212049Spjd#include <sys/cdefs.h>
28212049Spjd__FBSDID("$FreeBSD$");
29212049Spjd
30212049Spjd#include <errno.h>
31212049Spjd
32212049Spjd#include "hast.h"
33212049Spjd#include "hast_proto.h"
34212049Spjd#include "hooks.h"
35212049Spjd#include "nv.h"
36212049Spjd#include "pjdlog.h"
37212049Spjd#include "proto.h"
38212049Spjd#include "subr.h"
39212049Spjd
40212049Spjd#include "event.h"
41212049Spjd
42212049Spjdvoid
43212049Spjdevent_send(const struct hast_resource *res, int event)
44212049Spjd{
45212049Spjd	struct nv *nvin, *nvout;
46212049Spjd	int error;
47212049Spjd
48229509Strociny	PJDLOG_ASSERT(res != NULL);
49229509Strociny	PJDLOG_ASSERT(event >= EVENT_MIN && event <= EVENT_MAX);
50212049Spjd
51212049Spjd	nvin = nvout = NULL;
52212049Spjd
53212049Spjd	/*
54212049Spjd	 * Prepare and send event to parent process.
55212049Spjd	 */
56212049Spjd	nvout = nv_alloc();
57212049Spjd	nv_add_uint8(nvout, (uint8_t)event, "event");
58212049Spjd	error = nv_error(nvout);
59212049Spjd	if (error != 0) {
60212049Spjd		pjdlog_common(LOG_ERR, 0, error,
61212049Spjd		    "Unable to prepare event header");
62212049Spjd		goto done;
63212049Spjd	}
64231017Strociny	if (hast_proto_send(res, res->hr_event, nvout, NULL, 0) == -1) {
65212049Spjd		pjdlog_errno(LOG_ERR, "Unable to send event header");
66212049Spjd		goto done;
67212049Spjd	}
68231017Strociny	if (hast_proto_recv_hdr(res->hr_event, &nvin) == -1) {
69212049Spjd		pjdlog_errno(LOG_ERR, "Unable to receive event header");
70212049Spjd		goto done;
71212049Spjd	}
72212049Spjd	/*
73212049Spjd	 * Do nothing with the answer. We only wait for it to be sure not
74212049Spjd	 * to exit too quickly after sending an event and exiting immediately.
75212049Spjd	 */
76212049Spjddone:
77212049Spjd	if (nvin != NULL)
78212049Spjd		nv_free(nvin);
79212049Spjd	if (nvout != NULL)
80212049Spjd		nv_free(nvout);
81212049Spjd}
82212049Spjd
83212049Spjdint
84212049Spjdevent_recv(const struct hast_resource *res)
85212049Spjd{
86212049Spjd	struct nv *nvin, *nvout;
87212049Spjd	const char *evstr;
88212049Spjd	uint8_t event;
89212049Spjd	int error;
90212049Spjd
91229509Strociny	PJDLOG_ASSERT(res != NULL);
92212049Spjd
93212049Spjd	nvin = nvout = NULL;
94212049Spjd
95231017Strociny	if (hast_proto_recv_hdr(res->hr_event, &nvin) == -1) {
96212049Spjd		/*
97212049Spjd		 * First error log as debug. This is because worker process
98212049Spjd		 * most likely exited.
99212049Spjd		 */
100212049Spjd		pjdlog_common(LOG_DEBUG, 1, errno,
101212049Spjd		    "Unable to receive event header");
102212049Spjd		goto fail;
103212049Spjd	}
104212049Spjd
105212049Spjd	event = nv_get_uint8(nvin, "event");
106212049Spjd	if (event == EVENT_NONE) {
107212049Spjd		pjdlog_error("Event header is missing 'event' field.");
108212049Spjd		goto fail;
109212049Spjd	}
110212049Spjd
111212049Spjd	switch (event) {
112212049Spjd	case EVENT_CONNECT:
113212049Spjd		evstr = "connect";
114212049Spjd		break;
115212049Spjd	case EVENT_DISCONNECT:
116212049Spjd		evstr = "disconnect";
117212049Spjd		break;
118212049Spjd	case EVENT_SYNCSTART:
119212049Spjd		evstr = "syncstart";
120212049Spjd		break;
121212049Spjd	case EVENT_SYNCDONE:
122212049Spjd		evstr = "syncdone";
123212049Spjd		break;
124212049Spjd	case EVENT_SYNCINTR:
125212049Spjd		evstr = "syncintr";
126212049Spjd		break;
127212049Spjd	case EVENT_SPLITBRAIN:
128212049Spjd		evstr = "split-brain";
129212049Spjd		break;
130212049Spjd	default:
131212049Spjd		pjdlog_error("Event header contain invalid event number (%hhu).",
132212049Spjd		    event);
133212049Spjd		goto fail;
134212049Spjd	}
135212049Spjd
136212049Spjd	pjdlog_prefix_set("[%s] (%s) ", res->hr_name, role2str(res->hr_role));
137212049Spjd	hook_exec(res->hr_exec, evstr, res->hr_name, NULL);
138212049Spjd	pjdlog_prefix_set("%s", "");
139212049Spjd
140212049Spjd	nvout = nv_alloc();
141212049Spjd	nv_add_int16(nvout, 0, "error");
142212049Spjd	error = nv_error(nvout);
143212049Spjd	if (error != 0) {
144212049Spjd		pjdlog_common(LOG_ERR, 0, error,
145212049Spjd		    "Unable to prepare event header");
146212049Spjd		goto fail;
147212049Spjd	}
148231017Strociny	if (hast_proto_send(res, res->hr_event, nvout, NULL, 0) == -1) {
149212049Spjd		pjdlog_errno(LOG_ERR, "Unable to send event header");
150212049Spjd		goto fail;
151212049Spjd	}
152212049Spjd	nv_free(nvin);
153212049Spjd	nv_free(nvout);
154212049Spjd	return (0);
155212049Spjdfail:
156212049Spjd	if (nvin != NULL)
157212049Spjd		nv_free(nvin);
158212049Spjd	if (nvout != NULL)
159212049Spjd		nv_free(nvout);
160212049Spjd	return (-1);
161212049Spjd}
162