Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Nov 2006 15:46:05 GMT
From:      Michael Bushkov <bushman@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 109931 for review
Message-ID:  <200611141546.kAEFk5cF066684@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=109931

Change 109931 by bushman@bushman_nss_ldap_cached on 2006/11/14 15:45:42

	+ cached and libc's caching part modified to properly handle nsswitch requests with very large responses. Now client side (i.e. libc) must confirm if it can or cannot receive the cached's answer. If it cannot, cached will not send the data to the socket. While processing multipart requests, cached won't also move to the next result if the client doesn't confirm that it can handle current result.
	+ some bug fixing in use_alternate_io part of the cached.c - now we can properly send/receive buffers of any size. Fixes are quite dirty - hard-coded integer constants (0, 1, and 2) should be replaced with macro definitions.
	+ some minor fixes

Affected files ...

.. //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/include/nscache.h#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/include/nscachedcli.h#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/net/nscache.c#5 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/net/nscachedcli.c#3 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/group.c#7 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cached.c#9 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachedcli.c#5 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachelib.c#6 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachelib.h#4 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/config.c#6 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/config.h#6 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/debug.h#6 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/log.h#5 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/mp_rs_query.c#7 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/protocol.c#4 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/protocol.h#4 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/query.c#7 edit

Differences ...

==== //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/include/nscache.h#2 (text) ====

@@ -43,6 +43,9 @@
 typedef void (*nss_set_mp_rs_func_t)(cached_mp_read_session);
 typedef cached_mp_read_session	(*nss_get_mp_rs_func_t)(void);
 
+typedef void (*nss_set_mp_buffer_func_t)(char *, size_t);
+typedef char *(*nss_get_mp_buffer_func_t)(size_t *);
+
 typedef struct _nss_cache_info {
 	char	*entry_name;
 	void	*mdata;
@@ -64,6 +67,9 @@
 
 	nss_set_mp_rs_func_t set_mp_rs_func; /* sets current read session */
 	nss_get_mp_rs_func_t get_mp_rs_func; /* gets current read session */
+	
+	nss_set_mp_buffer_func_t set_mp_buffer_func;
+	nss_get_mp_buffer_func_t get_mp_buffer_func;
 } nss_cache_info;
 
 /*
@@ -75,6 +81,8 @@
 struct name##_mp_state {						\
 	cached_mp_write_session	mp_write_session;			\
 	cached_mp_read_session	mp_read_session;			\
+	char *mp_buffer;						\
+	size_t mp_bufsize;						\
 };									\
 									\
 static void								\
@@ -87,6 +95,8 @@
 									\
 	if (mp_state->mp_read_session != INVALID_CACHED_MP_READ_SESSION)\
 		__close_cached_mp_read_session(mp_state->mp_read_session);\
+									\
+	free(mp_state->mp_buffer);					\
 }									\
 NSS_TLS_HANDLING(name##_mp);						\
 									\
@@ -140,18 +150,48 @@
 		return (INVALID_CACHED_MP_READ_SESSION);		\
 									\
 	return (mp_state->mp_read_session);				\
+}									\
+									\
+static void								\
+name##_set_mp_buffer(char *buf, size_t bufsize)				\
+{									\
+	struct name##_mp_state	*mp_state;				\
+	int	res;							\
+									\
+	res = name##_mp_getstate(&mp_state);				\
+	if (res != 0)							\
+		return;							\
+									\
+	mp_state->mp_buffer = buf;					\
+	mp_state->mp_bufsize = bufsize;					\
+}									\
+									\
+static char *								\
+name##_get_mp_buffer(size_t *bufsize)					\
+{									\
+	struct name##_mp_state	*mp_state;				\
+	int	res;							\
+									\
+	res = name##_mp_getstate(&mp_state);				\
+	if (res != 0)							\
+		return (NULL);						\
+									\
+	*bufsize = mp_state->mp_bufsize;				\
+	return (mp_state->mp_buffer);					\
 }
 
+
 /*
  * These macros should be used to initialize _nss_cache_info structure. For
  * multipart queries in setXXXent and getXXXent functions mf and uf
  * (marshal function and unmarshal function) should be both NULL.
  */
 #define NS_COMMON_CACHE_INFO_INITIALIZER(name, mdata, if, mf, uf)	\
-	{#name, mdata, if, mf, uf, NULL, NULL, NULL, NULL}
+	{#name, mdata, if, mf, uf, NULL, NULL, NULL, NULL, NULL, NULL}
 #define NS_MP_CACHE_INFO_INITIALIZER(name, mdata, mf, uf)		\
 	{#name, mdata, NULL, mf, uf, name##_set_mp_ws, name##_get_mp_ws,\
-		name##_set_mp_rs, name##_get_mp_rs }
+		name##_set_mp_rs, name##_get_mp_rs, name##_set_mp_buffer,\
+		name##_get_mp_buffer }
 
 /*
  * Analog of other XXX_CB macros. Has the pointer to _nss_cache_info

==== //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/include/nscachedcli.h#2 (text) ====


==== //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/net/nscache.c#5 (text) ====

@@ -122,9 +122,13 @@
 		    cache_data->key, cache_data->key_size, buffer,
 		    &buffer_size);
 		__close_cached_connection(connection);
-		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
-			free(buffer);
-			buffer = (char *)malloc(buffer_size);
+		if (res == -2) {
+ 			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT) {
+				free(buffer);
+				buffer = NULL;
+			} else
+				buffer = (char *)reallocf(buffer, buffer_size);
+
 			if (buffer == NULL)
 				return (NS_UNAVAIL);
 		}
@@ -293,6 +297,12 @@
 
 	if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION)
 		return (NS_UNAVAIL);
+	
+	buffer = cache_info->get_mp_buffer_func(&buffer_size);
+	if (buffer != NULL) {
+		res = 0;
+		goto unmarsh;
+	}
 
 	rs = cache_info->get_mp_rs_func();
 	if (rs == INVALID_CACHED_MP_READ_SESSION) {
@@ -318,16 +328,22 @@
 
 	do {
 		res = __cached_mp_read(rs, buffer, &buffer_size);
-		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
-			free(buffer);
-			buffer = (char *)malloc(buffer_size);
-			if (buffer == NULL) {
+		if (res == -2) {
+			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT) {
+				free(buffer);
 				res = -1;
-				break;
+			} else {
+				buffer = (char *)reallocf(buffer, buffer_size);
+				if (buffer == NULL) {
+					res = -1;
+					break;
+				}
 			}
 		}
 	} while (res == -2);
 
+unmarsh:
+	cache_info->set_mp_buffer_func(NULL, 0);
 	if (res == 0) {
 		va_copy(ap_new, ap);
 		res = cache_info->unmarshal_func(buffer, buffer_size, retval,
@@ -335,7 +351,11 @@
 		va_end(ap_new);
 
 		if (res != NS_SUCCESS) {
-			free(buffer);
+			if (res == NS_RETURN)
+				cache_info->set_mp_buffer_func(buffer,
+					buffer_size);
+			else
+				free(buffer);
 			return (res);
 		} else
 			res = 0;

==== //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/net/nscachedcli.c#3 (text) ====

@@ -43,7 +43,7 @@
 #include "un-namespace.h"
 #include "nscachedcli.h"
 
-#define NS_DEFAULT_CACHED_IO_TIMEOUT	4
+#define NS_DEFAULT_CACHED_IO_TIMEOUT	60
 
 static int safe_write(struct cached_connection_ *, const void *, size_t);
 static int safe_read(struct cached_connection_ *, void *, size_t);
@@ -126,7 +126,7 @@
 				result += s_result;
 
 			if (eventlist.flags & EV_EOF)
-				return (result < data_size ? -1 : 0);
+				return (result < data_size ? -1 : 0);			
 		} else
 			return (-1);
 	} while (result < data_size);
@@ -360,13 +360,22 @@
 	result = safe_read(connection, &result_size, sizeof(size_t));
 	if (result != 0)
 		goto fin;
-
-	 if (result_size > *data_size) {
-		 *data_size = result_size;
-		 error_code = -2;
-		 goto fin;
-	 }
-
+	
+	if (result_size > *data_size) {
+		error_code = -1;
+		result = safe_write(connection, &error_code, sizeof(int));
+		if (result == 0) {
+			*data_size = result_size;
+			error_code = -2;
+		}
+		goto fin;
+	}
+	
+	rec_error_code = 0;
+	result = safe_write(connection, &rec_error_code, sizeof(int));
+	if (result != 0)
+		goto fin;
+	
 	result = safe_read(connection, data, result_size);
 	if (result != 0)
 		goto fin;
@@ -563,10 +572,19 @@
 		goto fin;
 
 	if (result_size > *data_size) {
-		*data_size = result_size;
-		error_code = -2;
+		error_code = -1;
+		result = safe_write(rs, &error_code, sizeof(int));
+		if (result == 0) {
+			*data_size = result_size;
+			error_code = -2;
+		}
 		goto fin;
 	}
+	
+	rec_error_code = 0;
+	result = safe_write(rs, &rec_error_code, sizeof(int));
+	if (result != 0)
+		goto fin;
 
 	result = safe_read(rs, data, result_size);
 	if (result != 0)

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/group.c#7 (text) ====


==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cached.c#9 (text) ====

@@ -428,7 +428,7 @@
 		(qstate->kevent_watermark <= event_data->data)) ||
 		((qstate->use_alternate_io != 0) &&
 		(qstate->io_buffer_watermark <= event_data->data))) {
-		if (qstate->use_alternate_io != 0) {
+		if (qstate->use_alternate_io == 1) {
 			switch (qstate->io_buffer_filter) {
 			case EVFILT_READ:
 				io_res = query_socket_read(qstate,
@@ -453,10 +453,10 @@
 			}
 		}
 
-		if (qstate->use_alternate_io == 0) {
-			do {
+		if ((qstate->use_alternate_io == 0) || (qstate->use_alternate_io == 2)) {
+			do
 				res = qstate->process_func(qstate);
-			} while ((qstate->kevent_watermark == 0) &&
+			while ((qstate->kevent_watermark == 0) &&
 					(qstate->process_func != NULL) &&
 					(res == 0));
 
@@ -464,7 +464,7 @@
 				qstate->process_func = NULL;
 		}
 
-		if ((qstate->use_alternate_io != 0) &&
+		if ((qstate->use_alternate_io == 1) &&
 			(qstate->io_buffer_filter == EVFILT_WRITE)) {
 			io_res = query_socket_write(qstate, qstate->io_buffer_p,
 				qstate->io_buffer_watermark);
@@ -481,7 +481,7 @@
 	}
 
 	if (((qstate->process_func == NULL) &&
-	    	(qstate->use_alternate_io == 0)) ||
+	    	((qstate->use_alternate_io == 0) || (qstate->use_alternate_io == 2))) ||
 		(eof_res != 0) || (res != 0)) {
 		destroy_query_state(qstate);
 		close(event_data->ident);
@@ -499,7 +499,7 @@
 		query_timeout.tv_sec = qstate->timeout.tv_sec -
 			query_timeout.tv_sec;
 
-	if ((qstate->use_alternate_io != 0) && (qstate->io_buffer_p ==
+	if ((qstate->use_alternate_io == 1) && (qstate->io_buffer_p ==
 		qstate->io_buffer + qstate->io_buffer_size))
 		qstate->use_alternate_io = 0;
 
@@ -534,6 +534,8 @@
 
 			if (qstate->kevent_filter == EVFILT_READ)
 				qstate->use_alternate_io = 1;
+			else
+				qstate->use_alternate_io = 2;
 
 			qstate->io_buffer_watermark = MAX_SOCKET_IO_SIZE;
 			EV_SET(&eventlist[1], event_data->ident,

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachedcli.c#5 (text) ====

@@ -44,21 +44,27 @@
 #include "cachedcli.h"
 #include "protocol.h"
 
-#define DEFAULT_CACHED_IO_TIMEOUT	4
+#define DEFAULT_CACHED_IO_TIMEOUT	60
 
 static int safe_write(struct cached_connection_ *, const void *, size_t);
 static int safe_read(struct cached_connection_ *, void *, size_t);
 static int send_credentials(struct cached_connection_ *, int);
 
+/*
+ * safe_write writes data to the specified connection and tries to do it in
+ * the very safe manner. We ensure, that we can write to the socket with
+ * kevent. If the data_size can't be sent in one piece, then it would be
+ * splitted.
+ */
 static int
 safe_write(struct cached_connection_ *connection, const void *data,
-	size_t data_size)
+    size_t data_size)
 {
 	struct kevent eventlist;
-	int	nevents;
+	int nevents;
 	size_t result;
 	ssize_t s_result;
-	struct timespec	timeout;
+	struct timespec timeout;
 
 	if (data_size == 0)
 		return (0);
@@ -68,11 +74,11 @@
 	result = 0;
 	do {
 		nevents = kevent(connection->write_queue, NULL, 0, &eventlist,
-	    		1, &timeout);
+		    1, &timeout);
 		if ((nevents == 1) && (eventlist.filter == EVFILT_WRITE)) {
 			s_result = write(connection->sockfd, data + result,
-				eventlist.data < data_size - result ?
-		    		eventlist.data : data_size - result);
+			    eventlist.data < data_size - result ?
+			    eventlist.data : data_size - result);
 			if (s_result == -1)
 				return (-1);
 			else
@@ -87,6 +93,12 @@
 	return (0);
 }
 
+/*
+ * safe_read reads data from connection and tries to do it in the very safe
+ * and stable way. It uses kevent to ensure, that the data are availabe for
+ * reading. If the amount of data to be read is too large, then they would
+ * be splitted.
+ */
 static int
 safe_read(struct cached_connection_ *connection, void *data, size_t data_size)
 {
@@ -103,19 +115,19 @@
 	timeout.tv_nsec = 0;
 	result = 0;
 	do {
-		nevents = kevent(connection->read_queue, NULL, 0, &eventlist, 1,
-			&timeout);
-		if ((nevents == 1) && (eventlist.filter == EVFILT_READ)) {
+		nevents = kevent(connection->read_queue, NULL, 0, &eventlist,
+		    1, &timeout);
+		if (nevents == 1 && eventlist.filter == EVFILT_READ) {
 			s_result = read(connection->sockfd, data + result,
-			eventlist.data <= data_size - result ? eventlist.data :
-				data_size - result);
+			    eventlist.data <= data_size - result ?
+			    eventlist.data : data_size - result);
 			if (s_result == -1)
 				return (-1);
 			else
 				result += s_result;
 
 			if (eventlist.flags & EV_EOF)
-				return (result < data_size ? -1 : 0);
+				return (result < data_size ? -1 : 0);			
 		} else
 			return (-1);
 	} while (result < data_size);
@@ -123,6 +135,10 @@
 	return (0);
 }
 
+/*
+ * Sends the credentials information to the connection along with the
+ * communication element type.
+ */
 static int
 send_credentials(struct cached_connection_ *connection, int type)
 {
@@ -131,79 +147,77 @@
 	ssize_t result;
 	int res;
 
-	struct msghdr	cred_hdr;
-	struct iovec	iov;
+	struct msghdr cred_hdr;
+	struct iovec iov;
 
 	struct {
-		struct cmsghdr	hdr;
-		struct cmsgcred	creds;
+		struct cmsghdr hdr;
+		char cred[CMSG_SPACE(sizeof(struct cmsgcred))];
 	} cmsg;
 
-	TRACE_IN(send_credentials);
 	memset(&cmsg, 0, sizeof(cmsg));
-	cmsg.hdr.cmsg_len = sizeof(cmsg);
+	cmsg.hdr.cmsg_len =  CMSG_LEN(sizeof(struct cmsgcred));
 	cmsg.hdr.cmsg_level = SOL_SOCKET;
 	cmsg.hdr.cmsg_type = SCM_CREDS;
 
 	memset(&cred_hdr, 0, sizeof(struct msghdr));
 	cred_hdr.msg_iov = &iov;
 	cred_hdr.msg_iovlen = 1;
-	cred_hdr.msg_control = &cmsg;
-	cred_hdr.msg_controllen = sizeof(cmsg);
+	cred_hdr.msg_control = (caddr_t)&cmsg;
+	cred_hdr.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred));
 
 	iov.iov_base = &type;
 	iov.iov_len = sizeof(int);
 
 	EV_SET(&eventlist, connection->sockfd, EVFILT_WRITE, EV_ADD,
-		NOTE_LOWAT, sizeof(int), NULL);
+	    NOTE_LOWAT, sizeof(int), NULL);
 	res = kevent(connection->write_queue, &eventlist, 1, NULL, 0, NULL);
 
-	nevents = kevent(connection->write_queue, NULL, 0, &eventlist, 1, NULL);
-	if ((nevents == 1) && (eventlist.filter == EVFILT_WRITE)) {
-		result = (sendmsg(connection->sockfd, &cred_hdr, 0) == -1) ? -1
-	    		: 0;
+	nevents = kevent(connection->write_queue, NULL, 0, &eventlist, 1,
+	    NULL);
+	if (nevents == 1 && eventlist.filter == EVFILT_WRITE) {
+		result = (sendmsg(connection->sockfd, &cred_hdr, 0) == -1) ?
+		    -1 : 0;
 		EV_SET(&eventlist, connection->sockfd, EVFILT_WRITE, EV_ADD,
-			0, 0, NULL);
+		    0, 0, NULL);
 		kevent(connection->write_queue, &eventlist, 1, NULL, 0, NULL);
-		TRACE_OUT(send_credentials);
 		return (result);
-	} else {
-		TRACE_OUT(send_credentials);
+	} else
 		return (-1);
-	}
 }
 
+/*
+ * Opens the connection with the specified params. Initializes all kqueues.
+ */
 struct cached_connection_ *
 open_cached_connection__(struct cached_connection_params const *params)
 {
 	struct cached_connection_ *retval;
 	struct kevent eventlist;
-	struct sockaddr_un	client_address;
+	struct sockaddr_un client_address;
 	int client_address_len, client_socket;
 	int res;
 
-	TRACE_IN(open_cached_connection);
 	assert(params != NULL);
 
 	client_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
 	client_address.sun_family = PF_LOCAL;
 	strncpy(client_address.sun_path, params->socket_path,
-		sizeof(client_address.sun_path));
+	    sizeof(client_address.sun_path));
 	client_address_len = sizeof(client_address.sun_family) +
-		strlen(client_address.sun_path) + 1;
+	    strlen(client_address.sun_path) + 1;
 
 	res = connect(client_socket, (struct sockaddr *)&client_address,
-		client_address_len);
+	    client_address_len);
 	if (res == -1) {
 		close(client_socket);
-		TRACE_OUT(open_cached_connection);
 		return (NULL);
 	}
 	fcntl(client_socket, F_SETFL, O_NONBLOCK);
 
 	retval = malloc(sizeof(struct cached_connection_));
 	if (retval == NULL) {
-		TRACE_OUT(open_cached_connection);
+		close(client_socket);
 		return (NULL);
 	}
 	memset(retval, 0, sizeof(struct cached_connection_));
@@ -212,45 +226,38 @@
 
 	retval->write_queue = kqueue();
 	if (retval->write_queue == -1) {
-		close(retval->sockfd);
-		free(retval);		
-		TRACE_OUT(open_cached_connection);
+		close(client_socket);
+		free(retval);
 		return (NULL);
 	}
 
-	EV_SET(&eventlist, retval->sockfd, EVFILT_WRITE, EV_ADD,
-		0, 0, NULL);
+	EV_SET(&eventlist, retval->sockfd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
 	res = kevent(retval->write_queue, &eventlist, 1, NULL, 0, NULL);
 
 	retval->read_queue = kqueue();
-	if (retval->read_queue != -1) {
+	if (retval->read_queue == -1) {
+		close(client_socket);
 		close(retval->write_queue);
-		close(retval->sockfd);
-		free(retval);		
-		TRACE_OUT(open_cached_connection);
+		free(retval);
 		return (NULL);
 	}
 
-	EV_SET(&eventlist, retval->sockfd, EVFILT_READ, EV_ADD,
-		0, 0, NULL);
+	EV_SET(&eventlist, retval->sockfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
 	res = kevent(retval->read_queue, &eventlist, 1, NULL, 0, NULL);
 
-	TRACE_OUT(open_cached_connection);
 	return (retval);
 }
 
 void
 close_cached_connection__(struct cached_connection_ *connection)
 {
-
-	TRACE_IN(close_cached_connection);
+	
 	assert(connection != NULL);
 
 	close(connection->sockfd);
 	close(connection->read_queue);
 	close(connection->write_queue);
 	free(connection);
-	TRACE_OUT(close_cached_connection);
 }
 
 int

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachelib.c#6 (text) ====

@@ -322,6 +322,12 @@
 	} else {
 		mp_entry = (struct cache_mp_entry_ *)entry;
 
+		/*
+		 * NOTE: currently multipart entries are cleared only if 
+		 * there are no opened read sessions. It leads to possible
+		 * failues of cache clearing requests. Possibly, some simple
+		 * reference counting should be used to avoid this
+		 */
 		if (mp_entry->rs_size == 0) {
 			if (mp_entry->completed_write_session != NULL) {
 				destroy_cache_mp_write_session(
@@ -1168,6 +1174,9 @@
  * Returns 0 on success, -1 on error (when there are no more data), and -2 if
  * the data_size is too small.  In the last case, data_size would be filled
  * the proper value.
+ *
+ * NOTE: cache_mp_read() doesn't move read pointer to the next element of the
+ * session - this is done by cache_mp_read_next()
  */
 int
 cache_mp_read(struct cache_mp_read_session_ *rs, char *data, size_t *data_size)
@@ -1194,12 +1203,22 @@
 
 	*data_size = rs->current_item->value_size;
 	memcpy(data, rs->current_item->value, rs->current_item->value_size);
-	rs->current_item = TAILQ_NEXT(rs->current_item, entries);
 
 	TRACE_OUT(cache_mp_read);
 	return (0);
 }
 
+void 
+cache_mp_read_next(struct cache_mp_read_session_ *rs)
+{
+	
+	TRACE_IN(cache_mp_read_next);
+	assert(rs != NULL);
+	assert(rs->current_item != NULL);
+	rs->current_item = TAILQ_NEXT(rs->current_item, entries);
+	TRACE_OUT(cache_mp_read_next);
+}
+
 /*
  * Closes the read session. If there are no more read sessions and there is
  * a pending write session, it will be committed and old

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachelib.h#4 (text) ====

@@ -271,6 +271,7 @@
 
 extern cache_mp_read_session open_cache_mp_read_session(cache_entry);
 extern int cache_mp_read(cache_mp_read_session, char *, size_t *);
+extern void cache_mp_read_next(cache_mp_read_session);
 extern void close_cache_mp_read_session(cache_mp_read_session);
 
 /* transformation routines */

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/config.c#6 (text) ====


==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/config.h#6 (text) ====

@@ -39,8 +39,8 @@
 #define DEFAULT_QUERY_TIMEOUT		8
 #define DEFAULT_THREADS_NUM		8
 
-#define DEFAULT_COMMON_ENTRY_TIMEOUT	10
-#define DEFAULT_MP_ENTRY_TIMEOUT	60
+#define DEFAULT_COMMON_ENTRY_TIMEOUT	60
+#define DEFAULT_MP_ENTRY_TIMEOUT	120
 #define DEFAULT_CACHE_HT_SIZE		257
 
 #define INITIAL_ENTRIES_CAPACITY	8

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/debug.h#6 (text) ====

@@ -32,7 +32,7 @@
 #define TRACE_WANTED 32
 
 /* #ifndef NDEBUG */
-#if 0
+#if 1
 #define TRACE_IN(x)	__trace_in(#x, __FILE__, __LINE__)
 #define TRACE_POINT()	__trace_point(__FILE__, __LINE__)
 #define TRACE_MSG(x)	__trace_msg(x, __FILE__, __LINE__)

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/log.h#5 (text) ====

@@ -31,7 +31,7 @@
 
 #define LOG_MSG_1(sender, msg, ...) __log_msg(1, sender, msg, ##__VA_ARGS__)
 #define LOG_MSG_2(sender, msg, ...) __log_msg(2, sender, msg, ##__VA_ARGS__)
-#define LOG_MSG_3(sender, msg, ...) __log_msg(3, sedner, msg, ##__VA_ARGS__)
+#define LOG_MSG_3(sender, msg, ...) __log_msg(3, sender, msg, ##__VA_ARGS__)
 
 #define LOG_ERR_1(sender, err, ...) __log_err(1, sender, err, ##__VA_ARGS__)
 #define LOG_ERR_2(sender, err, ...) __log_err(2, sender, err, ##__VA_ARGS__)

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/mp_rs_query.c#7 (text) ====

@@ -56,6 +56,8 @@
 static int on_mp_read_session_response_write1(struct query_state *);
 static int on_mp_read_session_read_request_process(struct query_state *);
 static int on_mp_read_session_read_response_write1(struct query_state *);
+static int on_mp_read_session_read_response_confirm_read1(
+	struct query_state *);
 static int on_mp_read_session_read_response_write2(struct query_state *);
 
 /*
@@ -426,6 +428,16 @@
 	struct cache_mp_read_session_read_response	*read_response;
 
 	TRACE_IN(on_mp_read_session_response_process);
+	if (get_comm_element_type(&qstate->response) ==
+		CET_MP_READ_SESSION_READ_RESPONSE) {
+		qstate->kevent_watermark = sizeof(size_t) + sizeof(int);
+		qstate->process_func = 
+			on_mp_read_session_read_response_write1;			
+		qstate->kevent_filter = EVFILT_WRITE;
+		TRACE_OUT(on_mp_read_session_response_process);
+		return (0);
+	}
+		
 	init_comm_element(&qstate->response, CET_MP_READ_SESSION_READ_RESPONSE);
 	read_response = get_cache_mp_read_session_read_response(
 		&qstate->response);
@@ -482,8 +494,10 @@
 			return (-1);
 		}
 
-		qstate->kevent_watermark = read_response->data_size;
-		qstate->process_func = on_mp_read_session_read_response_write2;
+		qstate->kevent_watermark = sizeof(int);
+		qstate->process_func = 
+			on_mp_read_session_read_response_confirm_read1;
+		qstate->kevent_filter = EVFILT_READ;
 	} else {
 		if (result != qstate->kevent_watermark) {
 			LOG_ERR_3("on_mp_read_session_read_response_write1",
@@ -501,6 +515,51 @@
 }
 
 static int
+on_mp_read_session_read_response_confirm_read1(struct query_state *qstate)
+{
+	struct cache_mp_read_session_read_response	*read_response;
+	ssize_t result;
+	int confirmation;	
+	
+	TRACE_IN(on_mp_read_session_read_response_confirm_read1);
+	result = qstate->read_func(qstate, &confirmation, sizeof(int));
+	
+	if (result != sizeof(int)) {
+		LOG_ERR_3("on_mp_read_session_read_response_confirm_read1",
+			"read failed");
+		TRACE_OUT(on_mp_read_session_read_response_confirm_read1);
+		return (-1);
+	}
+	
+	if (confirmation == 0) {
+		configuration_lock_entry(qstate->config_entry, CELT_MULTIPART);
+		cache_mp_read_next(
+			(cache_mp_read_session)qstate->mdata);
+		configuration_unlock_entry(qstate->config_entry,
+			CELT_MULTIPART);
+
+		read_response = get_cache_mp_read_session_read_response(
+			&qstate->response);
+		
+		qstate->kevent_watermark = read_response->data_size;
+		qstate->process_func = on_mp_read_session_read_response_write2;
+		qstate->kevent_filter = EVFILT_WRITE;		
+	} else {
+		finalize_comm_element(&qstate->request);
+		finalize_comm_element(&qstate->response);
+
+		qstate->kevent_watermark = sizeof(int);
+		qstate->process_func = on_mp_read_session_mapper;
+		
+		LOG_MSG_3("on_mp_read_session_read_response_confirm_read1",
+			"other side can't read requested data");
+	}
+	
+	TRACE_OUT(on_mp_read_session_read_response_confirm_read1);
+	return (0);
+}
+
+static int
 on_mp_read_session_read_response_write2(struct query_state *qstate)
 {
 	struct cache_mp_read_session_read_response *read_response;

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/protocol.c#4 (text) ====

@@ -100,6 +100,14 @@
 	TRACE_OUT(init_comm_element);
 }
 
+enum comm_element_t 
+get_comm_element_type(struct comm_element *element)
+{
+	
+	assert(element != NULL);
+	return (element->type);
+}
+
 void
 finalize_comm_element(struct comm_element *element)
 {

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/protocol.h#4 (text) ====

@@ -174,6 +174,7 @@
 };
 
 extern void init_comm_element(struct comm_element *, enum comm_element_t type);
+extern enum comm_element_t get_comm_element_type(struct comm_element *);
 extern void finalize_comm_element(struct comm_element *);
 
 /*

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/query.c#7 (text) ====

@@ -61,6 +61,7 @@
 static	int on_read_request_read2(struct query_state *);
 static	int on_read_request_process(struct query_state *);
 static	int on_read_response_write1(struct query_state *);
+static	int on_read_response_confirm_read1(struct query_state *);
 static	int on_read_response_write2(struct query_state *);
 
 static	int on_rw_mapper(struct query_state *);
@@ -867,8 +868,9 @@
 			return (-1);
 		}
 
-		qstate->kevent_watermark = read_response->data_size;
-		qstate->process_func = on_read_response_write2;
+		qstate->kevent_watermark = sizeof(int);
+		qstate->process_func = on_read_response_confirm_read1;
+		qstate->kevent_filter = EVFILT_READ;
 	} else {
 		if (result != qstate->kevent_watermark) {
 			TRACE_OUT(on_read_response_write1);
@@ -884,6 +886,44 @@
 }
 
 static int
+on_read_response_confirm_read1(struct query_state *qstate)
+{
+	struct cache_read_response *read_response;
+	ssize_t result;
+	int confirmation;	
+	
+	TRACE_IN(on_read_response_confirm_read1);
+	result = qstate->read_func(qstate, &confirmation, sizeof(int));
+	
+	if (result != sizeof(int)) {
+		LOG_ERR_3("on_read_response_confirm_read1",
+			"read failed");
+		TRACE_OUT(on_read_response_confirm_read1);
+		return (-1);
+	}
+	
+	if (confirmation == 0) {
+		read_response = get_cache_read_response(&qstate->response);
+		
+		qstate->kevent_watermark = read_response->data_size;
+		qstate->process_func = on_read_response_write2;
+		qstate->kevent_filter = EVFILT_WRITE;		
+	} else {
+		finalize_comm_element(&qstate->request);
+		finalize_comm_element(&qstate->response);
+		
+		qstate->kevent_watermark = sizeof(int);
+		qstate->process_func = on_rw_mapper;
+		
+		LOG_MSG_3("on_mp_read_session_read_response_confirm_read1",
+			"other side can't read requested data");
+	}
+	
+	TRACE_OUT(on_read_response_confirm_read2);
+	return (0);
+}
+
+static int
 on_read_response_write2(struct query_state *qstate)
 {
 	struct cache_read_response	*read_response;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611141546.kAEFk5cF066684>