event.c revision 212049
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: head/sbin/hastd/event.c 212049 2010-08-31 09:38:43Z pjd $");
29212049Spjd
30212049Spjd#include <assert.h>
31212049Spjd#include <errno.h>
32212049Spjd
33212049Spjd#include "hast.h"
34212049Spjd#include "hast_proto.h"
35212049Spjd#include "hooks.h"
36212049Spjd#include "nv.h"
37212049Spjd#include "pjdlog.h"
38212049Spjd#include "proto.h"
39212049Spjd#include "subr.h"
40212049Spjd
41212049Spjd#include "event.h"
42212049Spjd
43212049Spjdvoid
44212049Spjdevent_send(const struct hast_resource *res, int event)
45212049Spjd{
46212049Spjd	struct nv *nvin, *nvout;
47212049Spjd	int error;
48212049Spjd
49212049Spjd	assert(res != NULL);
50212049Spjd	assert(event >= EVENT_MIN && event <= EVENT_MAX);
51212049Spjd
52212049Spjd	nvin = nvout = NULL;
53212049Spjd
54212049Spjd	/*
55212049Spjd	 * Prepare and send event to parent process.
56212049Spjd	 */
57212049Spjd	nvout = nv_alloc();
58212049Spjd	nv_add_uint8(nvout, (uint8_t)event, "event");
59212049Spjd	error = nv_error(nvout);
60212049Spjd	if (error != 0) {
61212049Spjd		pjdlog_common(LOG_ERR, 0, error,
62212049Spjd		    "Unable to prepare event header");
63212049Spjd		goto done;
64212049Spjd	}
65212049Spjd	if (hast_proto_send(res, res->hr_event, nvout, NULL, 0) < 0) {
66212049Spjd		pjdlog_errno(LOG_ERR, "Unable to send event header");
67212049Spjd		goto done;
68212049Spjd	}
69212049Spjd	if (hast_proto_recv_hdr(res->hr_event, &nvin) < 0) {
70212049Spjd		pjdlog_errno(LOG_ERR, "Unable to receive event header");
71212049Spjd		goto done;
72212049Spjd	}
73212049Spjd	/*
74212049Spjd	 * Do nothing with the answer. We only wait for it to be sure not
75212049Spjd	 * to exit too quickly after sending an event and exiting immediately.
76212049Spjd	 */
77212049Spjddone:
78212049Spjd	if (nvin != NULL)
79212049Spjd		nv_free(nvin);
80212049Spjd	if (nvout != NULL)
81212049Spjd		nv_free(nvout);
82212049Spjd}
83212049Spjd
84212049Spjdint
85212049Spjdevent_recv(const struct hast_resource *res)
86212049Spjd{
87212049Spjd	struct nv *nvin, *nvout;
88212049Spjd	const char *evstr;
89212049Spjd	uint8_t event;
90212049Spjd	int error;
91212049Spjd
92212049Spjd	assert(res != NULL);
93212049Spjd
94212049Spjd	nvin = nvout = NULL;
95212049Spjd
96212049Spjd	if (hast_proto_recv_hdr(res->hr_event, &nvin) < 0) {
97212049Spjd		/*
98212049Spjd		 * First error log as debug. This is because worker process
99212049Spjd		 * most likely exited.
100212049Spjd		 */
101212049Spjd		pjdlog_common(LOG_DEBUG, 1, errno,
102212049Spjd		    "Unable to receive event header");
103212049Spjd		goto fail;
104212049Spjd	}
105212049Spjd
106212049Spjd	event = nv_get_uint8(nvin, "event");
107212049Spjd	if (event == EVENT_NONE) {
108212049Spjd		pjdlog_error("Event header is missing 'event' field.");
109212049Spjd		goto fail;
110212049Spjd	}
111212049Spjd
112212049Spjd	switch (event) {
113212049Spjd	case EVENT_CONNECT:
114212049Spjd		evstr = "connect";
115212049Spjd		break;
116212049Spjd	case EVENT_DISCONNECT:
117212049Spjd		evstr = "disconnect";
118212049Spjd		break;
119212049Spjd	case EVENT_SYNCSTART:
120212049Spjd		evstr = "syncstart";
121212049Spjd		break;
122212049Spjd	case EVENT_SYNCDONE:
123212049Spjd		evstr = "syncdone";
124212049Spjd		break;
125212049Spjd	case EVENT_SYNCINTR:
126212049Spjd		evstr = "syncintr";
127212049Spjd		break;
128212049Spjd	case EVENT_SPLITBRAIN:
129212049Spjd		evstr = "split-brain";
130212049Spjd		break;
131212049Spjd	default:
132212049Spjd		pjdlog_error("Event header contain invalid event number (%hhu).",
133212049Spjd		    event);
134212049Spjd		goto fail;
135212049Spjd	}
136212049Spjd
137212049Spjd	pjdlog_prefix_set("[%s] (%s) ", res->hr_name, role2str(res->hr_role));
138212049Spjd	hook_exec(res->hr_exec, evstr, res->hr_name, NULL);
139212049Spjd	pjdlog_prefix_set("%s", "");
140212049Spjd
141212049Spjd	nvout = nv_alloc();
142212049Spjd	nv_add_int16(nvout, 0, "error");
143212049Spjd	error = nv_error(nvout);
144212049Spjd	if (error != 0) {
145212049Spjd		pjdlog_common(LOG_ERR, 0, error,
146212049Spjd		    "Unable to prepare event header");
147212049Spjd		goto fail;
148212049Spjd	}
149212049Spjd	if (hast_proto_send(res, res->hr_event, nvout, NULL, 0) < 0) {
150212049Spjd		pjdlog_errno(LOG_ERR, "Unable to send event header");
151212049Spjd		goto fail;
152212049Spjd	}
153212049Spjd	nv_free(nvin);
154212049Spjd	nv_free(nvout);
155212049Spjd	return (0);
156212049Spjdfail:
157212049Spjd	if (nvin != NULL)
158212049Spjd		nv_free(nvin);
159212049Spjd	if (nvout != NULL)
160212049Spjd		nv_free(nvout);
161212049Spjd	return (-1);
162212049Spjd}
163