xref: /dragonfly/usr.sbin/nscd/mp_ws_query.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino  * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3*86d7f5d3SJohn Marino  * All rights reserved.
4*86d7f5d3SJohn Marino  *
5*86d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino  * are met:
8*86d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino  *
14*86d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*86d7f5d3SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*86d7f5d3SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*86d7f5d3SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*86d7f5d3SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*86d7f5d3SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*86d7f5d3SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*86d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*86d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*86d7f5d3SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*86d7f5d3SJohn Marino  * SUCH DAMAGE.
25*86d7f5d3SJohn Marino  *
26*86d7f5d3SJohn Marino  * $FreeBSD: src/usr.sbin/nscd/mp_ws_query.c,v 1.4 2008/10/12 00:44:27 delphij Exp $
27*86d7f5d3SJohn Marino  */
28*86d7f5d3SJohn Marino 
29*86d7f5d3SJohn Marino #include <sys/socket.h>
30*86d7f5d3SJohn Marino #include <sys/time.h>
31*86d7f5d3SJohn Marino #include <sys/types.h>
32*86d7f5d3SJohn Marino #include <sys/event.h>
33*86d7f5d3SJohn Marino #include <assert.h>
34*86d7f5d3SJohn Marino #include <errno.h>
35*86d7f5d3SJohn Marino #include <stdlib.h>
36*86d7f5d3SJohn Marino #include <string.h>
37*86d7f5d3SJohn Marino #include <stdio.h>
38*86d7f5d3SJohn Marino 
39*86d7f5d3SJohn Marino #include "cachelib.h"
40*86d7f5d3SJohn Marino #include "config.h"
41*86d7f5d3SJohn Marino #include "debug.h"
42*86d7f5d3SJohn Marino #include "log.h"
43*86d7f5d3SJohn Marino #include "query.h"
44*86d7f5d3SJohn Marino #include "mp_ws_query.h"
45*86d7f5d3SJohn Marino #include "singletons.h"
46*86d7f5d3SJohn Marino 
47*86d7f5d3SJohn Marino static int on_mp_write_session_abandon_notification(struct query_state *);
48*86d7f5d3SJohn Marino static int on_mp_write_session_close_notification(struct query_state *);
49*86d7f5d3SJohn Marino static void on_mp_write_session_destroy(struct query_state *);
50*86d7f5d3SJohn Marino static int on_mp_write_session_mapper(struct query_state *);
51*86d7f5d3SJohn Marino /* int on_mp_write_session_request_read1(struct query_state *); */
52*86d7f5d3SJohn Marino static int on_mp_write_session_request_read2(struct query_state *);
53*86d7f5d3SJohn Marino static int on_mp_write_session_request_process(struct query_state *);
54*86d7f5d3SJohn Marino static int on_mp_write_session_response_write1(struct query_state *);
55*86d7f5d3SJohn Marino static int on_mp_write_session_write_request_read1(struct query_state *);
56*86d7f5d3SJohn Marino static int on_mp_write_session_write_request_read2(struct query_state *);
57*86d7f5d3SJohn Marino static int on_mp_write_session_write_request_process(struct query_state *);
58*86d7f5d3SJohn Marino static int on_mp_write_session_write_response_write1(struct query_state *);
59*86d7f5d3SJohn Marino 
60*86d7f5d3SJohn Marino /*
61*86d7f5d3SJohn Marino  * This function is used as the query_state's destroy_func to make the
62*86d7f5d3SJohn Marino  * proper cleanup in case of errors.
63*86d7f5d3SJohn Marino  */
64*86d7f5d3SJohn Marino static void
on_mp_write_session_destroy(struct query_state * qstate)65*86d7f5d3SJohn Marino on_mp_write_session_destroy(struct query_state *qstate)
66*86d7f5d3SJohn Marino {
67*86d7f5d3SJohn Marino 
68*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_destroy);
69*86d7f5d3SJohn Marino 	finalize_comm_element(&qstate->request);
70*86d7f5d3SJohn Marino 	finalize_comm_element(&qstate->response);
71*86d7f5d3SJohn Marino 
72*86d7f5d3SJohn Marino 	if (qstate->mdata != NULL) {
73*86d7f5d3SJohn Marino 		configuration_lock_entry(qstate->config_entry, CELT_MULTIPART);
74*86d7f5d3SJohn Marino 		abandon_cache_mp_write_session(
75*86d7f5d3SJohn Marino 			(cache_mp_write_session)qstate->mdata);
76*86d7f5d3SJohn Marino 		configuration_unlock_entry(qstate->config_entry,
77*86d7f5d3SJohn Marino 			CELT_MULTIPART);
78*86d7f5d3SJohn Marino 	}
79*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_destroy);
80*86d7f5d3SJohn Marino }
81*86d7f5d3SJohn Marino 
82*86d7f5d3SJohn Marino /*
83*86d7f5d3SJohn Marino  * The functions below are used to process multipart write session initiation
84*86d7f5d3SJohn Marino  * requests.
85*86d7f5d3SJohn Marino  * - on_mp_write_session_request_read1 and on_mp_write_session_request_read2
86*86d7f5d3SJohn Marino  *   read the request itself
87*86d7f5d3SJohn Marino  * - on_mp_write_session_request_process processes it
88*86d7f5d3SJohn Marino  * - on_mp_write_session_response_write1 sends the response
89*86d7f5d3SJohn Marino  */
90*86d7f5d3SJohn Marino int
on_mp_write_session_request_read1(struct query_state * qstate)91*86d7f5d3SJohn Marino on_mp_write_session_request_read1(struct query_state *qstate)
92*86d7f5d3SJohn Marino {
93*86d7f5d3SJohn Marino 	struct cache_mp_write_session_request	*c_mp_ws_request;
94*86d7f5d3SJohn Marino 	ssize_t	result;
95*86d7f5d3SJohn Marino 
96*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_request_read1);
97*86d7f5d3SJohn Marino 	if (qstate->kevent_watermark == 0)
98*86d7f5d3SJohn Marino 		qstate->kevent_watermark = sizeof(size_t);
99*86d7f5d3SJohn Marino 	else {
100*86d7f5d3SJohn Marino 		init_comm_element(&qstate->request,
101*86d7f5d3SJohn Marino 			CET_MP_WRITE_SESSION_REQUEST);
102*86d7f5d3SJohn Marino 		c_mp_ws_request = get_cache_mp_write_session_request(
103*86d7f5d3SJohn Marino 			&qstate->request);
104*86d7f5d3SJohn Marino 
105*86d7f5d3SJohn Marino 		result = qstate->read_func(qstate,
106*86d7f5d3SJohn Marino 			&c_mp_ws_request->entry_length, sizeof(size_t));
107*86d7f5d3SJohn Marino 
108*86d7f5d3SJohn Marino 		if (result != sizeof(size_t)) {
109*86d7f5d3SJohn Marino 			LOG_ERR_3("on_mp_write_session_request_read1",
110*86d7f5d3SJohn Marino 				"read failed");
111*86d7f5d3SJohn Marino 			TRACE_OUT(on_mp_write_session_request_read1);
112*86d7f5d3SJohn Marino 			return (-1);
113*86d7f5d3SJohn Marino 		}
114*86d7f5d3SJohn Marino 
115*86d7f5d3SJohn Marino 		if (BUFSIZE_INVALID(c_mp_ws_request->entry_length)) {
116*86d7f5d3SJohn Marino 			LOG_ERR_3("on_mp_write_session_request_read1",
117*86d7f5d3SJohn Marino 				"invalid entry_length value");
118*86d7f5d3SJohn Marino 			TRACE_OUT(on_mp_write_session_request_read1);
119*86d7f5d3SJohn Marino 			return (-1);
120*86d7f5d3SJohn Marino 		}
121*86d7f5d3SJohn Marino 
122*86d7f5d3SJohn Marino 		c_mp_ws_request->entry = (char *)calloc(1,
123*86d7f5d3SJohn Marino 			c_mp_ws_request->entry_length + 1);
124*86d7f5d3SJohn Marino 		assert(c_mp_ws_request->entry != NULL);
125*86d7f5d3SJohn Marino 
126*86d7f5d3SJohn Marino 		qstate->kevent_watermark = c_mp_ws_request->entry_length;
127*86d7f5d3SJohn Marino 		qstate->process_func = on_mp_write_session_request_read2;
128*86d7f5d3SJohn Marino 	}
129*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_request_read1);
130*86d7f5d3SJohn Marino 	return (0);
131*86d7f5d3SJohn Marino }
132*86d7f5d3SJohn Marino 
133*86d7f5d3SJohn Marino static int
on_mp_write_session_request_read2(struct query_state * qstate)134*86d7f5d3SJohn Marino on_mp_write_session_request_read2(struct query_state *qstate)
135*86d7f5d3SJohn Marino {
136*86d7f5d3SJohn Marino 	struct cache_mp_write_session_request	*c_mp_ws_request;
137*86d7f5d3SJohn Marino 	ssize_t	result;
138*86d7f5d3SJohn Marino 
139*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_request_read2);
140*86d7f5d3SJohn Marino 	c_mp_ws_request = get_cache_mp_write_session_request(&qstate->request);
141*86d7f5d3SJohn Marino 
142*86d7f5d3SJohn Marino 	result = qstate->read_func(qstate, c_mp_ws_request->entry,
143*86d7f5d3SJohn Marino 		c_mp_ws_request->entry_length);
144*86d7f5d3SJohn Marino 
145*86d7f5d3SJohn Marino 	if (result != qstate->kevent_watermark) {
146*86d7f5d3SJohn Marino 		LOG_ERR_3("on_mp_write_session_request_read2",
147*86d7f5d3SJohn Marino 			"read failed");
148*86d7f5d3SJohn Marino 		TRACE_OUT(on_mp_write_session_request_read2);
149*86d7f5d3SJohn Marino 		return (-1);
150*86d7f5d3SJohn Marino 	}
151*86d7f5d3SJohn Marino 
152*86d7f5d3SJohn Marino 	qstate->kevent_watermark = 0;
153*86d7f5d3SJohn Marino 	qstate->process_func = on_mp_write_session_request_process;
154*86d7f5d3SJohn Marino 
155*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_request_read2);
156*86d7f5d3SJohn Marino 	return (0);
157*86d7f5d3SJohn Marino }
158*86d7f5d3SJohn Marino 
159*86d7f5d3SJohn Marino static int
on_mp_write_session_request_process(struct query_state * qstate)160*86d7f5d3SJohn Marino on_mp_write_session_request_process(struct query_state *qstate)
161*86d7f5d3SJohn Marino {
162*86d7f5d3SJohn Marino 	struct cache_mp_write_session_request	*c_mp_ws_request;
163*86d7f5d3SJohn Marino 	struct cache_mp_write_session_response	*c_mp_ws_response;
164*86d7f5d3SJohn Marino 	cache_mp_write_session	ws;
165*86d7f5d3SJohn Marino 	cache_entry	c_entry;
166*86d7f5d3SJohn Marino 	char	*dec_cache_entry_name;
167*86d7f5d3SJohn Marino 
168*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_request_process);
169*86d7f5d3SJohn Marino 	init_comm_element(&qstate->response, CET_MP_WRITE_SESSION_RESPONSE);
170*86d7f5d3SJohn Marino 	c_mp_ws_response = get_cache_mp_write_session_response(
171*86d7f5d3SJohn Marino 		&qstate->response);
172*86d7f5d3SJohn Marino 	c_mp_ws_request = get_cache_mp_write_session_request(&qstate->request);
173*86d7f5d3SJohn Marino 
174*86d7f5d3SJohn Marino 	qstate->config_entry = configuration_find_entry(
175*86d7f5d3SJohn Marino 		s_configuration, c_mp_ws_request->entry);
176*86d7f5d3SJohn Marino 	if (qstate->config_entry == NULL) {
177*86d7f5d3SJohn Marino 		c_mp_ws_response->error_code = ENOENT;
178*86d7f5d3SJohn Marino 
179*86d7f5d3SJohn Marino 		LOG_ERR_2("write_session_request",
180*86d7f5d3SJohn Marino 			"can't find configuration entry '%s'. "
181*86d7f5d3SJohn Marino 			"aborting request", c_mp_ws_request->entry);
182*86d7f5d3SJohn Marino 		goto fin;
183*86d7f5d3SJohn Marino 	}
184*86d7f5d3SJohn Marino 
185*86d7f5d3SJohn Marino 	if (qstate->config_entry->enabled == 0) {
186*86d7f5d3SJohn Marino 		c_mp_ws_response->error_code = EACCES;
187*86d7f5d3SJohn Marino 
188*86d7f5d3SJohn Marino 		LOG_ERR_2("write_session_request",
189*86d7f5d3SJohn Marino 			"configuration entry '%s' is disabled",
190*86d7f5d3SJohn Marino 			c_mp_ws_request->entry);
191*86d7f5d3SJohn Marino 		goto fin;
192*86d7f5d3SJohn Marino 	}
193*86d7f5d3SJohn Marino 
194*86d7f5d3SJohn Marino 	if (qstate->config_entry->perform_actual_lookups != 0) {
195*86d7f5d3SJohn Marino 		c_mp_ws_response->error_code = EOPNOTSUPP;
196*86d7f5d3SJohn Marino 
197*86d7f5d3SJohn Marino 		LOG_ERR_2("write_session_request",
198*86d7f5d3SJohn Marino 			"entry '%s' performs lookups by itself: "
199*86d7f5d3SJohn Marino 			"can't write to it", c_mp_ws_request->entry);
200*86d7f5d3SJohn Marino 		goto fin;
201*86d7f5d3SJohn Marino 	} else {
202*86d7f5d3SJohn Marino #ifdef NS_NSCD_EID_CHECKING
203*86d7f5d3SJohn Marino 		if (check_query_eids(qstate) != 0) {
204*86d7f5d3SJohn Marino 			c_mp_ws_response->error_code = EPERM;
205*86d7f5d3SJohn Marino 			goto fin;
206*86d7f5d3SJohn Marino 		}
207*86d7f5d3SJohn Marino #endif
208*86d7f5d3SJohn Marino 	}
209*86d7f5d3SJohn Marino 
210*86d7f5d3SJohn Marino 	/*
211*86d7f5d3SJohn Marino 	 * All multipart entries are separated by their name decorations.
212*86d7f5d3SJohn Marino 	 * For one configuration entry there will be a lot of multipart
213*86d7f5d3SJohn Marino 	 * cache entries - each with its own decorated name.
214*86d7f5d3SJohn Marino 	 */
215*86d7f5d3SJohn Marino 	asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str,
216*86d7f5d3SJohn Marino 		qstate->config_entry->mp_cache_params.entry_name);
217*86d7f5d3SJohn Marino 	assert(dec_cache_entry_name != NULL);
218*86d7f5d3SJohn Marino 
219*86d7f5d3SJohn Marino 	configuration_lock_rdlock(s_configuration);
220*86d7f5d3SJohn Marino 	c_entry = find_cache_entry(s_cache,
221*86d7f5d3SJohn Marino 		dec_cache_entry_name);
222*86d7f5d3SJohn Marino 	configuration_unlock(s_configuration);
223*86d7f5d3SJohn Marino 
224*86d7f5d3SJohn Marino 	if (c_entry == INVALID_CACHE_ENTRY)
225*86d7f5d3SJohn Marino 		c_entry = register_new_mp_cache_entry(qstate,
226*86d7f5d3SJohn Marino 			dec_cache_entry_name);
227*86d7f5d3SJohn Marino 
228*86d7f5d3SJohn Marino 	free(dec_cache_entry_name);
229*86d7f5d3SJohn Marino 
230*86d7f5d3SJohn Marino 	assert(c_entry != NULL);
231*86d7f5d3SJohn Marino 	configuration_lock_entry(qstate->config_entry, CELT_MULTIPART);
232*86d7f5d3SJohn Marino 	ws = open_cache_mp_write_session(c_entry);
233*86d7f5d3SJohn Marino 	if (ws == INVALID_CACHE_MP_WRITE_SESSION)
234*86d7f5d3SJohn Marino 		c_mp_ws_response->error_code = -1;
235*86d7f5d3SJohn Marino 	else {
236*86d7f5d3SJohn Marino 		qstate->mdata = ws;
237*86d7f5d3SJohn Marino 		qstate->destroy_func = on_mp_write_session_destroy;
238*86d7f5d3SJohn Marino 
239*86d7f5d3SJohn Marino 		if ((qstate->config_entry->mp_query_timeout.tv_sec != 0) ||
240*86d7f5d3SJohn Marino 		    (qstate->config_entry->mp_query_timeout.tv_usec != 0))
241*86d7f5d3SJohn Marino 			memcpy(&qstate->timeout,
242*86d7f5d3SJohn Marino 				&qstate->config_entry->mp_query_timeout,
243*86d7f5d3SJohn Marino 				sizeof(struct timeval));
244*86d7f5d3SJohn Marino 	}
245*86d7f5d3SJohn Marino 	configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART);
246*86d7f5d3SJohn Marino 
247*86d7f5d3SJohn Marino fin:
248*86d7f5d3SJohn Marino 	qstate->process_func = on_mp_write_session_response_write1;
249*86d7f5d3SJohn Marino 	qstate->kevent_watermark = sizeof(int);
250*86d7f5d3SJohn Marino 	qstate->kevent_filter = EVFILT_WRITE;
251*86d7f5d3SJohn Marino 
252*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_request_process);
253*86d7f5d3SJohn Marino 	return (0);
254*86d7f5d3SJohn Marino }
255*86d7f5d3SJohn Marino 
256*86d7f5d3SJohn Marino static int
on_mp_write_session_response_write1(struct query_state * qstate)257*86d7f5d3SJohn Marino on_mp_write_session_response_write1(struct query_state *qstate)
258*86d7f5d3SJohn Marino {
259*86d7f5d3SJohn Marino 	struct cache_mp_write_session_response	*c_mp_ws_response;
260*86d7f5d3SJohn Marino 	ssize_t	result;
261*86d7f5d3SJohn Marino 
262*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_response_write1);
263*86d7f5d3SJohn Marino 	c_mp_ws_response = get_cache_mp_write_session_response(
264*86d7f5d3SJohn Marino 		&qstate->response);
265*86d7f5d3SJohn Marino 	result = qstate->write_func(qstate, &c_mp_ws_response->error_code,
266*86d7f5d3SJohn Marino 		sizeof(int));
267*86d7f5d3SJohn Marino 	if (result != sizeof(int)) {
268*86d7f5d3SJohn Marino 		LOG_ERR_3("on_mp_write_session_response_write1",
269*86d7f5d3SJohn Marino 			"write failed");
270*86d7f5d3SJohn Marino 		TRACE_OUT(on_mp_write_session_response_write1);
271*86d7f5d3SJohn Marino 		return (-1);
272*86d7f5d3SJohn Marino 	}
273*86d7f5d3SJohn Marino 
274*86d7f5d3SJohn Marino 	if (c_mp_ws_response->error_code == 0) {
275*86d7f5d3SJohn Marino 		qstate->kevent_watermark = sizeof(int);
276*86d7f5d3SJohn Marino 		qstate->process_func = on_mp_write_session_mapper;
277*86d7f5d3SJohn Marino 		qstate->kevent_filter = EVFILT_READ;
278*86d7f5d3SJohn Marino 	} else {
279*86d7f5d3SJohn Marino 		qstate->kevent_watermark = 0;
280*86d7f5d3SJohn Marino 		qstate->process_func = NULL;
281*86d7f5d3SJohn Marino 	}
282*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_response_write1);
283*86d7f5d3SJohn Marino 	return (0);
284*86d7f5d3SJohn Marino }
285*86d7f5d3SJohn Marino 
286*86d7f5d3SJohn Marino /*
287*86d7f5d3SJohn Marino  * Mapper function is used to avoid multiple connections for each session
288*86d7f5d3SJohn Marino  * write or read requests. After processing the request, it does not close
289*86d7f5d3SJohn Marino  * the connection, but waits for the next request.
290*86d7f5d3SJohn Marino  */
291*86d7f5d3SJohn Marino static int
on_mp_write_session_mapper(struct query_state * qstate)292*86d7f5d3SJohn Marino on_mp_write_session_mapper(struct query_state *qstate)
293*86d7f5d3SJohn Marino {
294*86d7f5d3SJohn Marino 	ssize_t	result;
295*86d7f5d3SJohn Marino 	int		elem_type;
296*86d7f5d3SJohn Marino 
297*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_mapper);
298*86d7f5d3SJohn Marino 	if (qstate->kevent_watermark == 0) {
299*86d7f5d3SJohn Marino 		qstate->kevent_watermark = sizeof(int);
300*86d7f5d3SJohn Marino 	} else {
301*86d7f5d3SJohn Marino 		result = qstate->read_func(qstate, &elem_type, sizeof(int));
302*86d7f5d3SJohn Marino 		if (result != sizeof(int)) {
303*86d7f5d3SJohn Marino 			LOG_ERR_3("on_mp_write_session_mapper",
304*86d7f5d3SJohn Marino 				"read failed");
305*86d7f5d3SJohn Marino 			TRACE_OUT(on_mp_write_session_mapper);
306*86d7f5d3SJohn Marino 			return (-1);
307*86d7f5d3SJohn Marino 		}
308*86d7f5d3SJohn Marino 
309*86d7f5d3SJohn Marino 		switch (elem_type) {
310*86d7f5d3SJohn Marino 		case CET_MP_WRITE_SESSION_WRITE_REQUEST:
311*86d7f5d3SJohn Marino 			qstate->kevent_watermark = sizeof(size_t);
312*86d7f5d3SJohn Marino 			qstate->process_func =
313*86d7f5d3SJohn Marino 				on_mp_write_session_write_request_read1;
314*86d7f5d3SJohn Marino 			break;
315*86d7f5d3SJohn Marino 		case CET_MP_WRITE_SESSION_ABANDON_NOTIFICATION:
316*86d7f5d3SJohn Marino 			qstate->kevent_watermark = 0;
317*86d7f5d3SJohn Marino 			qstate->process_func =
318*86d7f5d3SJohn Marino 				on_mp_write_session_abandon_notification;
319*86d7f5d3SJohn Marino 			break;
320*86d7f5d3SJohn Marino 		case CET_MP_WRITE_SESSION_CLOSE_NOTIFICATION:
321*86d7f5d3SJohn Marino 			qstate->kevent_watermark = 0;
322*86d7f5d3SJohn Marino 			qstate->process_func =
323*86d7f5d3SJohn Marino 				on_mp_write_session_close_notification;
324*86d7f5d3SJohn Marino 			break;
325*86d7f5d3SJohn Marino 		default:
326*86d7f5d3SJohn Marino 			qstate->kevent_watermark = 0;
327*86d7f5d3SJohn Marino 			qstate->process_func = NULL;
328*86d7f5d3SJohn Marino 			LOG_ERR_2("on_mp_write_session_mapper",
329*86d7f5d3SJohn Marino 				"unknown element type");
330*86d7f5d3SJohn Marino 			TRACE_OUT(on_mp_write_session_mapper);
331*86d7f5d3SJohn Marino 			return (-1);
332*86d7f5d3SJohn Marino 		}
333*86d7f5d3SJohn Marino 	}
334*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_mapper);
335*86d7f5d3SJohn Marino 	return (0);
336*86d7f5d3SJohn Marino }
337*86d7f5d3SJohn Marino 
338*86d7f5d3SJohn Marino /*
339*86d7f5d3SJohn Marino  * The functions below are used to process multipart write sessions write
340*86d7f5d3SJohn Marino  * requests.
341*86d7f5d3SJohn Marino  * - on_mp_write_session_write_request_read1 and
342*86d7f5d3SJohn Marino  *   on_mp_write_session_write_request_read2 read the request itself
343*86d7f5d3SJohn Marino  * - on_mp_write_session_write_request_process processes it
344*86d7f5d3SJohn Marino  * - on_mp_write_session_write_response_write1 sends the response
345*86d7f5d3SJohn Marino  */
346*86d7f5d3SJohn Marino static int
on_mp_write_session_write_request_read1(struct query_state * qstate)347*86d7f5d3SJohn Marino on_mp_write_session_write_request_read1(struct query_state *qstate)
348*86d7f5d3SJohn Marino {
349*86d7f5d3SJohn Marino 	struct cache_mp_write_session_write_request	*write_request;
350*86d7f5d3SJohn Marino 	ssize_t	result;
351*86d7f5d3SJohn Marino 
352*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_write_request_read1);
353*86d7f5d3SJohn Marino 	init_comm_element(&qstate->request,
354*86d7f5d3SJohn Marino 		CET_MP_WRITE_SESSION_WRITE_REQUEST);
355*86d7f5d3SJohn Marino 	write_request = get_cache_mp_write_session_write_request(
356*86d7f5d3SJohn Marino 		&qstate->request);
357*86d7f5d3SJohn Marino 
358*86d7f5d3SJohn Marino 	result = qstate->read_func(qstate, &write_request->data_size,
359*86d7f5d3SJohn Marino 		sizeof(size_t));
360*86d7f5d3SJohn Marino 
361*86d7f5d3SJohn Marino 	if (result != sizeof(size_t)) {
362*86d7f5d3SJohn Marino 		LOG_ERR_3("on_mp_write_session_write_request_read1",
363*86d7f5d3SJohn Marino 			"read failed");
364*86d7f5d3SJohn Marino 		TRACE_OUT(on_mp_write_session_write_request_read1);
365*86d7f5d3SJohn Marino 		return (-1);
366*86d7f5d3SJohn Marino 	}
367*86d7f5d3SJohn Marino 
368*86d7f5d3SJohn Marino 	if (BUFSIZE_INVALID(write_request->data_size)) {
369*86d7f5d3SJohn Marino 		LOG_ERR_3("on_mp_write_session_write_request_read1",
370*86d7f5d3SJohn Marino 			"invalid data_size value");
371*86d7f5d3SJohn Marino 		TRACE_OUT(on_mp_write_session_write_request_read1);
372*86d7f5d3SJohn Marino 		return (-1);
373*86d7f5d3SJohn Marino 	}
374*86d7f5d3SJohn Marino 
375*86d7f5d3SJohn Marino 	write_request->data = (char *)calloc(1, write_request->data_size);
376*86d7f5d3SJohn Marino 	assert(write_request->data != NULL);
377*86d7f5d3SJohn Marino 
378*86d7f5d3SJohn Marino 	qstate->kevent_watermark = write_request->data_size;
379*86d7f5d3SJohn Marino 	qstate->process_func = on_mp_write_session_write_request_read2;
380*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_write_request_read1);
381*86d7f5d3SJohn Marino 	return (0);
382*86d7f5d3SJohn Marino }
383*86d7f5d3SJohn Marino 
384*86d7f5d3SJohn Marino static int
on_mp_write_session_write_request_read2(struct query_state * qstate)385*86d7f5d3SJohn Marino on_mp_write_session_write_request_read2(struct query_state *qstate)
386*86d7f5d3SJohn Marino {
387*86d7f5d3SJohn Marino 	struct cache_mp_write_session_write_request	*write_request;
388*86d7f5d3SJohn Marino 	ssize_t	result;
389*86d7f5d3SJohn Marino 
390*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_write_request_read2);
391*86d7f5d3SJohn Marino 	write_request = get_cache_mp_write_session_write_request(
392*86d7f5d3SJohn Marino 		&qstate->request);
393*86d7f5d3SJohn Marino 
394*86d7f5d3SJohn Marino 	result = qstate->read_func(qstate, write_request->data,
395*86d7f5d3SJohn Marino 		write_request->data_size);
396*86d7f5d3SJohn Marino 
397*86d7f5d3SJohn Marino 	if (result != qstate->kevent_watermark) {
398*86d7f5d3SJohn Marino 		LOG_ERR_3("on_mp_write_session_write_request_read2",
399*86d7f5d3SJohn Marino 			"read failed");
400*86d7f5d3SJohn Marino 		TRACE_OUT(on_mp_write_session_write_request_read2);
401*86d7f5d3SJohn Marino 		return (-1);
402*86d7f5d3SJohn Marino 	}
403*86d7f5d3SJohn Marino 
404*86d7f5d3SJohn Marino 	qstate->kevent_watermark = 0;
405*86d7f5d3SJohn Marino 	qstate->process_func = on_mp_write_session_write_request_process;
406*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_write_request_read2);
407*86d7f5d3SJohn Marino 	return (0);
408*86d7f5d3SJohn Marino }
409*86d7f5d3SJohn Marino 
410*86d7f5d3SJohn Marino static int
on_mp_write_session_write_request_process(struct query_state * qstate)411*86d7f5d3SJohn Marino on_mp_write_session_write_request_process(struct query_state *qstate)
412*86d7f5d3SJohn Marino {
413*86d7f5d3SJohn Marino 	struct cache_mp_write_session_write_request	*write_request;
414*86d7f5d3SJohn Marino 	struct cache_mp_write_session_write_response	*write_response;
415*86d7f5d3SJohn Marino 
416*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_write_request_process);
417*86d7f5d3SJohn Marino 	init_comm_element(&qstate->response,
418*86d7f5d3SJohn Marino 		CET_MP_WRITE_SESSION_WRITE_RESPONSE);
419*86d7f5d3SJohn Marino 	write_response = get_cache_mp_write_session_write_response(
420*86d7f5d3SJohn Marino 		&qstate->response);
421*86d7f5d3SJohn Marino 	write_request = get_cache_mp_write_session_write_request(
422*86d7f5d3SJohn Marino 		&qstate->request);
423*86d7f5d3SJohn Marino 
424*86d7f5d3SJohn Marino 	configuration_lock_entry(qstate->config_entry, CELT_MULTIPART);
425*86d7f5d3SJohn Marino 	write_response->error_code = cache_mp_write(
426*86d7f5d3SJohn Marino 		(cache_mp_write_session)qstate->mdata,
427*86d7f5d3SJohn Marino 		write_request->data,
428*86d7f5d3SJohn Marino 		write_request->data_size);
429*86d7f5d3SJohn Marino 	configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART);
430*86d7f5d3SJohn Marino 
431*86d7f5d3SJohn Marino 	qstate->kevent_watermark = sizeof(int);
432*86d7f5d3SJohn Marino 	qstate->process_func = on_mp_write_session_write_response_write1;
433*86d7f5d3SJohn Marino 	qstate->kevent_filter = EVFILT_WRITE;
434*86d7f5d3SJohn Marino 
435*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_write_request_process);
436*86d7f5d3SJohn Marino 	return (0);
437*86d7f5d3SJohn Marino }
438*86d7f5d3SJohn Marino 
439*86d7f5d3SJohn Marino static int
on_mp_write_session_write_response_write1(struct query_state * qstate)440*86d7f5d3SJohn Marino on_mp_write_session_write_response_write1(struct query_state *qstate)
441*86d7f5d3SJohn Marino {
442*86d7f5d3SJohn Marino 	struct cache_mp_write_session_write_response	*write_response;
443*86d7f5d3SJohn Marino 	ssize_t	result;
444*86d7f5d3SJohn Marino 
445*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_write_response_write1);
446*86d7f5d3SJohn Marino 	write_response = get_cache_mp_write_session_write_response(
447*86d7f5d3SJohn Marino 		&qstate->response);
448*86d7f5d3SJohn Marino 	result = qstate->write_func(qstate, &write_response->error_code,
449*86d7f5d3SJohn Marino 		sizeof(int));
450*86d7f5d3SJohn Marino 	if (result != sizeof(int)) {
451*86d7f5d3SJohn Marino 		LOG_ERR_3("on_mp_write_session_write_response_write1",
452*86d7f5d3SJohn Marino 			"write failed");
453*86d7f5d3SJohn Marino 		TRACE_OUT(on_mp_write_session_write_response_write1);
454*86d7f5d3SJohn Marino 		return (-1);
455*86d7f5d3SJohn Marino 	}
456*86d7f5d3SJohn Marino 
457*86d7f5d3SJohn Marino 	if (write_response->error_code == 0) {
458*86d7f5d3SJohn Marino 		finalize_comm_element(&qstate->request);
459*86d7f5d3SJohn Marino 		finalize_comm_element(&qstate->response);
460*86d7f5d3SJohn Marino 
461*86d7f5d3SJohn Marino 		qstate->kevent_watermark = sizeof(int);
462*86d7f5d3SJohn Marino 		qstate->process_func = on_mp_write_session_mapper;
463*86d7f5d3SJohn Marino 		qstate->kevent_filter = EVFILT_READ;
464*86d7f5d3SJohn Marino 	} else {
465*86d7f5d3SJohn Marino 		qstate->kevent_watermark = 0;
466*86d7f5d3SJohn Marino 		qstate->process_func = 0;
467*86d7f5d3SJohn Marino 	}
468*86d7f5d3SJohn Marino 
469*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_write_response_write1);
470*86d7f5d3SJohn Marino 	return (0);
471*86d7f5d3SJohn Marino }
472*86d7f5d3SJohn Marino 
473*86d7f5d3SJohn Marino /*
474*86d7f5d3SJohn Marino  * Handles abandon notifications. Destroys the session by calling the
475*86d7f5d3SJohn Marino  * abandon_cache_mp_write_session.
476*86d7f5d3SJohn Marino  */
477*86d7f5d3SJohn Marino static int
on_mp_write_session_abandon_notification(struct query_state * qstate)478*86d7f5d3SJohn Marino on_mp_write_session_abandon_notification(struct query_state *qstate)
479*86d7f5d3SJohn Marino {
480*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_abandon_notification);
481*86d7f5d3SJohn Marino 	configuration_lock_entry(qstate->config_entry, CELT_MULTIPART);
482*86d7f5d3SJohn Marino 	abandon_cache_mp_write_session((cache_mp_write_session)qstate->mdata);
483*86d7f5d3SJohn Marino 	configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART);
484*86d7f5d3SJohn Marino 	qstate->mdata = INVALID_CACHE_MP_WRITE_SESSION;
485*86d7f5d3SJohn Marino 
486*86d7f5d3SJohn Marino 	qstate->kevent_watermark = 0;
487*86d7f5d3SJohn Marino 	qstate->process_func = NULL;
488*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_abandon_notification);
489*86d7f5d3SJohn Marino 	return (0);
490*86d7f5d3SJohn Marino }
491*86d7f5d3SJohn Marino 
492*86d7f5d3SJohn Marino /*
493*86d7f5d3SJohn Marino  * Handles close notifications. Commits the session by calling
494*86d7f5d3SJohn Marino  * the close_cache_mp_write_session.
495*86d7f5d3SJohn Marino  */
496*86d7f5d3SJohn Marino static int
on_mp_write_session_close_notification(struct query_state * qstate)497*86d7f5d3SJohn Marino on_mp_write_session_close_notification(struct query_state *qstate)
498*86d7f5d3SJohn Marino {
499*86d7f5d3SJohn Marino 	TRACE_IN(on_mp_write_session_close_notification);
500*86d7f5d3SJohn Marino 	configuration_lock_entry(qstate->config_entry, CELT_MULTIPART);
501*86d7f5d3SJohn Marino 	close_cache_mp_write_session((cache_mp_write_session)qstate->mdata);
502*86d7f5d3SJohn Marino 	configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART);
503*86d7f5d3SJohn Marino 	qstate->mdata = INVALID_CACHE_MP_WRITE_SESSION;
504*86d7f5d3SJohn Marino 
505*86d7f5d3SJohn Marino 	qstate->kevent_watermark = 0;
506*86d7f5d3SJohn Marino 	qstate->process_func = NULL;
507*86d7f5d3SJohn Marino 	TRACE_OUT(on_mp_write_session_close_notification);
508*86d7f5d3SJohn Marino 	return (0);
509*86d7f5d3SJohn Marino }
510*86d7f5d3SJohn Marino 
register_new_mp_cache_entry(struct query_state * qstate,const char * dec_cache_entry_name)511*86d7f5d3SJohn Marino cache_entry register_new_mp_cache_entry(struct query_state *qstate,
512*86d7f5d3SJohn Marino 	const char *dec_cache_entry_name)
513*86d7f5d3SJohn Marino {
514*86d7f5d3SJohn Marino 	cache_entry c_entry;
515*86d7f5d3SJohn Marino 	char *en_bkp;
516*86d7f5d3SJohn Marino 
517*86d7f5d3SJohn Marino 	TRACE_IN(register_new_mp_cache_entry);
518*86d7f5d3SJohn Marino 	c_entry = INVALID_CACHE_ENTRY;
519*86d7f5d3SJohn Marino 	configuration_lock_entry(qstate->config_entry, CELT_MULTIPART);
520*86d7f5d3SJohn Marino 
521*86d7f5d3SJohn Marino 	configuration_lock_wrlock(s_configuration);
522*86d7f5d3SJohn Marino 	en_bkp = qstate->config_entry->mp_cache_params.entry_name;
523*86d7f5d3SJohn Marino 	qstate->config_entry->mp_cache_params.entry_name =
524*86d7f5d3SJohn Marino 		(char *)dec_cache_entry_name;
525*86d7f5d3SJohn Marino 	register_cache_entry(s_cache, (struct cache_entry_params *)
526*86d7f5d3SJohn Marino 		&qstate->config_entry->mp_cache_params);
527*86d7f5d3SJohn Marino 	qstate->config_entry->mp_cache_params.entry_name = en_bkp;
528*86d7f5d3SJohn Marino 	configuration_unlock(s_configuration);
529*86d7f5d3SJohn Marino 
530*86d7f5d3SJohn Marino 	configuration_lock_rdlock(s_configuration);
531*86d7f5d3SJohn Marino 	c_entry = find_cache_entry(s_cache,
532*86d7f5d3SJohn Marino 		dec_cache_entry_name);
533*86d7f5d3SJohn Marino 	configuration_unlock(s_configuration);
534*86d7f5d3SJohn Marino 
535*86d7f5d3SJohn Marino 	configuration_entry_add_mp_cache_entry(qstate->config_entry,
536*86d7f5d3SJohn Marino 		c_entry);
537*86d7f5d3SJohn Marino 
538*86d7f5d3SJohn Marino 	configuration_unlock_entry(qstate->config_entry,
539*86d7f5d3SJohn Marino 		CELT_MULTIPART);
540*86d7f5d3SJohn Marino 
541*86d7f5d3SJohn Marino 	TRACE_OUT(register_new_mp_cache_entry);
542*86d7f5d3SJohn Marino 	return (c_entry);
543*86d7f5d3SJohn Marino }
544