PERFORCE change 81439 for review

soc-bushman soc-bushman at FreeBSD.org
Thu Aug 4 11:43:21 GMT 2005


http://perforce.freebsd.org/chv.cgi?CH=81439

Change 81439 by soc-bushman at soc-bushman_stinger on 2005/08/04 11:42:58

	cached work in progress

Affected files ...

.. //depot/projects/soc2005/nsswitch_cached/cached/Makefile#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/cached.c#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/config.c#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/config.h#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/debug.c#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/debug.h#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/log.c#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/log.h#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/protocol.c#1 add
.. //depot/projects/soc2005/nsswitch_cached/cached/protocol.h#1 add
.. //depot/projects/soc2005/nsswitch_cached/cached/query.c#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/query.h#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/singletons.c#2 edit
.. //depot/projects/soc2005/nsswitch_cached/cached/singletons.h#2 edit

Differences ...

==== //depot/projects/soc2005/nsswitch_cached/cached/Makefile#2 (text+ko) ====

@@ -4,7 +4,7 @@
 PROGNAME=cached
 MAN=
 
-SRCS=cached.c debug.c log.c config.c query.c singletons.c
+SRCS=cached.c debug.c log.c config.c query.c singletons.c protocol.c
 CFLAGS+= -I${.CURDIR}/../
 WARNS?=2
 LDADD+=${.CURDIR}/../cachelib/libcachelib.a

==== //depot/projects/soc2005/nsswitch_cached/cached/cached.c#2 (text+ko) ====

@@ -1,5 +1,15 @@
 #include <cachelib/include/cachelib.h>
+#include <sys/event.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
+#include <string.h>
+#include <unistd.h>
 #include "config.h"
 #include "debug.h"
 #include "log.h"
@@ -15,7 +25,7 @@
 }
 
 static cache
-init_cache_(void)
+init_cache_(struct configuration *config)
 {
 	struct cache_params	params;
 	cache	retval;
@@ -38,22 +48,201 @@
 	TRACE_OUT(destroy_cache_);
 }
 
+static struct runtime_env *
+init_runtime_env(struct configuration *config)
+{
+	int	serv_addr_len;
+	struct sockaddr_un	serv_addr;		
+	
+	struct kevent eventlist;
+	struct timespec timeout;
+	
+	struct runtime_env	*retval;
+		
+	TRACE_IN(init_runtime_env);
+	retval = (struct runtime_env *)malloc(sizeof(struct runtime_env));
+	assert(retval != NULL);
+	memset(retval, 0, sizeof(struct runtime_env));
+	
+	retval->sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);
+
+	if (config->force_unlink == 1)
+		unlink(config->socket_path);
+
+	memset(&serv_addr, 0, sizeof(struct sockaddr_un));
+	serv_addr.sun_family = PF_LOCAL;
+	strncpy(serv_addr.sun_path, config->socket_path, sizeof(serv_addr.sun_path));
+	serv_addr_len = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path) + 1;
+	
+	if (bind(retval->sockfd, (struct sockaddr *)&serv_addr, serv_addr_len) == -1) {
+		TRACE_INT(errno);
+		close(retval->sockfd);
+		free(retval);
+		
+		TRACE_OUT(init_runtime_env);
+		return (NULL);
+	}
+	chmod(config->socket_path, config->socket_mode);
+	listen(retval->sockfd, 100);
+	fcntl(retval->sockfd, F_SETFL, O_NONBLOCK);
+	
+	retval->queue = kqueue();
+	assert(retval->queue != -1);
+	
+	EV_SET(&eventlist, retval->sockfd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);
+	memset(&timeout, 0, sizeof(struct timespec));
+	kevent(retval->queue, &eventlist, 1, NULL, 0, &timeout);		
+	
+	TRACE_OUT(init_runtime_env);
+	return (retval);
+}
+
 static void
-processing_loop(cache the_cache)
+destroy_runtime_env(struct runtime_env *env)
+{
+	TRACE_IN(destroy_runtime_env);
+	close(env->queue);
+	close(env->sockfd);
+	free(env);
+	TRACE_OUT(destroy_runtime_env);
+}
+
+static void
+accept_connection(struct kevent *event_data, struct runtime_env *env,
+	struct configuration *config)
+{
+	struct kevent	eventlist[2];
+	struct timespec	timeout;
+	struct query_state	*qstate;
+	
+	struct sockaddr	addr;
+	size_t			addr_len;
+	int				fd;
+		
+	TRACE_IN(accept_connection);
+	addr_len = sizeof(struct sockaddr);
+	fd = accept(event_data->ident, &addr, &addr_len);
+	if (fd == -1) {
+		/* do something */
+	}
+	
+	qstate = init_query_state(fd, sizeof(int));
+	memset(&timeout, 0, sizeof(struct timespec));
+	
+	EV_SET(&eventlist[0], fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 
+		NOTE_LOWAT, qstate->kevent_watermark, qstate);
+	EV_SET(&eventlist[1], fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
+		0, config->query_timeout, qstate);
+	kevent(env->queue, eventlist, 2, NULL, 0, &timeout);	
+	
+	TRACE_OUT(accept_connection);
+}
+
+static void
+process_socket_event(struct kevent *event_data, struct runtime_env *env,
+	struct configuration *config)
+{
+	struct kevent	eventlist[1];
+	struct timespec	timeout;
+	int				nevents;
+		
+	TRACE_IN(process_socket_event);
+	memset(&timeout, 0, sizeof(struct timespec));
+	EV_SET(&eventlist[0], event_data->ident, EVFILT_TIMER, EV_DELETE,
+		0, 0, NULL);
+	nevents = kevent(env->queue, eventlist, 1, NULL, 0, &timeout);
+	if (nevents == -1) {
+		if (errno == ENOENT) {
+			/* the timer is already handling this event */
+			return;
+		} else {
+			/* some other error happened */
+			return;
+		}
+	}
+	
+	TRACE_OUT(process_socket_event);
+}
+
+static void
+process_timer_event(struct kevent *event_data, struct runtime_env *env,
+	struct configuration *config)
+{
+	struct query_state	*qstate;
+		
+	TRACE_IN(process_timer_event);
+	qstate = (struct query_state *)event_data->udata;
+	destroy_query_state(qstate);
+	TRACE_OUT(process_timer_event);
+}
+
+static void
+processing_loop(cache the_cache, struct runtime_env *env,
+	struct configuration *config)
 {
+	struct timespec timeout;
+	const int eventlist_size = 1;
+	struct kevent eventlist[eventlist_size];
+	int nevents;
+	
 	TRACE_IN(processing_loop);
+	memset(&timeout, 0, sizeof(struct timespec));
+	memset(&eventlist, 0, sizeof(struct kevent) * eventlist_size);
+	
+	for (;;) {
+		nevents = kevent(env->queue, NULL, 0, eventlist, eventlist_size, NULL);
+		
+		if (nevents == 1) {
+			struct kevent *event_data;
+			event_data = &eventlist[0];
+			
+			if (event_data->ident == env->sockfd)
+				accept_connection(event_data, env, config);
+			else {
+				switch (event_data->filter) {
+				case EVFILT_READ:
+				case EVFILT_WRITE:
+					process_socket_event(event_data, env, config);
+					break;
+				case EVFILT_TIMER:
+					process_timer_event(event_data, env, config);
+					break;
+				default:
+					break;
+				}
+			}
+		} else {
+			/* this branch shouldn't be currently executed */
+		}
+	}
+	
 	TRACE_OUT(processing_loop);
 }
 
 int main(int argc, char *argv[])
 {
+	/* startup output */
 	print_version_info();	
+
+	/* configuration initialization */	
 	s_configuration = init_configuration();
-	s_cache = init_cache_();
+	fill_configuration_defaults(s_configuration);
+	
+	/* cache initialization */
+	s_cache = init_cache_(s_configuration);
+	
+	/* runtime environment initialization */
+	s_runtime_env = init_runtime_env(s_configuration);
+	
+	processing_loop(s_cache, s_runtime_env, s_configuration);
 	
-	processing_loop(s_cache);
+	/* runtime environment destruction */
+	destroy_runtime_env(s_runtime_env);
 	
+	/* cache destruction */
 	destroy_cache_(s_cache);
+	
+	/* configuration destruction */
 	destroy_configuration(s_configuration);
 	return (0);
 }

==== //depot/projects/soc2005/nsswitch_cached/cached/config.c#2 (text+ko) ====

@@ -5,7 +5,7 @@
 #include <string.h>
 #include "debug.h"
 
-#define DEFAULT_SOCKET_PATH "/var/run/cached"
+#define DEFAULT_SOCKET_PATH "/tmp/cached"
 
 struct configuration *
 init_configuration(void)
@@ -36,6 +36,13 @@
 	assert(config->socket_path != NULL);
 	memset(config->socket_path, 0, def_sockpath_len);
 	memcpy(config->socket_path, DEFAULT_SOCKET_PATH, def_sockpath_len);
+	
+	config->socket_mode =  S_IFSOCK | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
+		S_IROTH | S_IWOTH;
+	config->force_unlink = 1;
+	
+	config->query_timeout = 8000;
+	
 	TRACE_OUT(fill_configuration_defaults);
 }
 

==== //depot/projects/soc2005/nsswitch_cached/cached/config.h#2 (text+ko) ====

@@ -1,9 +1,15 @@
 #ifndef __CACHED_CONFIG_H__
 #define __CACHED_CONFIG_H__
 
+#include <sys/stat.h>
+
 /* the cached configuration parameters */
 struct configuration {
-	char	*socket_path;
+	char	*socket_path;	
+	mode_t	socket_mode;
+	int		force_unlink;
+	
+	int		query_timeout;
 };
 
 struct configuration	*init_configuration(void);

==== //depot/projects/soc2005/nsswitch_cached/cached/debug.c#2 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/cached/debug.h#2 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/cached/log.c#2 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/cached/log.h#2 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/cached/query.c#2 (text+ko) ====

@@ -1,1 +1,315 @@
 #include "query.h"
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "debug.h"
+#include "log.h"
+
+static	int		on_query_startup(struct query_state *);
+static	void	on_query_destroy(struct query_state *);
+	
+static	int		on_write_request_read1(struct query_state *);
+static	int		on_write_request_read2(struct query_state *);
+static	int		on_write_request_process(struct query_state *);
+static	int		on_write_response_write1(struct query_state *);
+	
+static	int		on_read_request_read1(struct query_state *);
+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_write2(struct query_state *);
+	
+static	int		on_transform_request_read1(struct query_state *);
+//static	int		on_transform_request_process(struct query_state *);
+//static	int		on_transform_response_write(struct query_state *);
+
+static int
+on_query_startup(struct query_state *qstate)
+{
+	struct msghdr	cred_hdr;
+	struct iovec	iov;
+	int				elem_type;
+
+	struct {
+		struct cmsghdr	hdr;
+		struct cmsgcred	creds;
+	} cmsg;	
+	
+	TRACE_IN(on_query_startup);
+	assert(qstate != NULL);
+	assert(qstate != NULL);
+	
+	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);
+
+	memset(&iov, 0, sizeof(struct iovec));
+	iov.iov_base = &elem_type;
+	iov.iov_len = sizeof(int);
+
+	if (recvmsg(qstate->sockfd, &cred_hdr, 0) == -1) {
+		TRACE_OUT(on_query_startup);
+		return (-1);
+	}
+    
+	if (cmsg.hdr.cmsg_len != sizeof cmsg
+		|| cmsg.hdr.cmsg_level != SOL_SOCKET
+		|| cmsg.hdr.cmsg_type != SCM_CREDS) {
+		TRACE_OUT(on_query_startup);
+		return (-1);
+	}
+    
+	qstate->uid = cmsg.creds.cmcred_uid;
+	qstate->euid = cmsg.creds.cmcred_euid;
+	qstate->pid = cmsg.creds.cmcred_pid;
+	
+	switch (elem_type) {
+	case CET_WRITE_REQUEST:
+		qstate->process_func = on_write_request_read1;
+		break;
+	case CET_READ_REQUEST:
+		qstate->process_func = on_read_request_read1;
+		break;
+	case CET_TRANSFORM_REQUEST:
+		qstate->process_func = on_transform_request_read1;
+		break;
+	default:
+		elem_type = -1;
+	break;
+	}
+
+	qstate->kevent_watermark = 0;
+	TRACE_OUT(on_query_startup);
+	return (0);
+}
+
+static void
+on_query_destroy(struct query_state *qstate)
+{
+	TRACE_IN(on_query_destroy);
+	finalize_comm_element(&qstate->response);
+	finalize_comm_element(&qstate->request);
+	TRACE_OUT(on_query_destroy);
+}
+
+static int
+on_write_request_read1(struct query_state *qstate)
+{
+	struct cache_write_request	*write_request;
+	ssize_t	result;
+	
+	TRACE_IN(on_write_request_read1);
+	if (qstate->kevent_watermark == 0)
+		qstate->kevent_watermark = sizeof(size_t) * 3;
+	else {
+		init_comm_element(&qstate->request, CET_WRITE_REQUEST);
+		write_request = get_cache_write_request(&qstate->request);
+		
+		result = qstate->read_func(qstate, &write_request->entry_length, sizeof(size_t));		
+		result += qstate->read_func(qstate, &write_request->cache_key_length, sizeof(size_t));		
+		result += qstate->read_func(qstate, &write_request->data_size, sizeof(size_t));
+		
+		if (result != sizeof(size_t) * 3) {
+			TRACE_OUT(on_write_request_read1);
+			return (-1);
+		}
+		
+		if ((write_request->entry_length == 0) ||
+			(write_request->cache_key_length == 0) ||
+			(write_request->data_size == 0)) {
+			TRACE_OUT(on_write_request_read1);
+			return (-1);
+		}
+		
+		write_request->entry = (char *)malloc(write_request->entry_length + 1);
+		assert(write_request->entry != NULL);
+		memset(write_request->entry, 0, write_request->entry_length + 1);
+		
+		write_request->cache_key = (char *)malloc(write_request->cache_key_length + 1);
+		assert(write_request->cache_key != NULL);
+		memset(write_request->cache_key, 0, write_request->cache_key_length + 1);
+		
+		write_request->data = (char *)malloc(write_request->data_size);
+		assert(write_request->data != NULL);
+		memset(write_request->data, 0, write_request->data_size);
+
+		qstate->kevent_watermark = write_request->entry_length +
+			write_request->cache_key_length + write_request->data_size;
+		qstate->process_func = on_write_request_read2;
+	}
+	
+	TRACE_OUT(on_write_request_read1);
+	return (0);
+}
+
+static int
+on_write_request_read2(struct query_state *qstate)
+{
+	struct cache_write_request	*write_request;
+	ssize_t	result;
+	
+	TRACE_IN(on_write_request_read2);
+	write_request = get_cache_write_request(&qstate->request);
+	
+	result = qstate->read_func(qstate, write_request->entry, write_request->entry_length);
+	result += qstate->read_func(qstate, write_request->cache_key, write_request->cache_key_length);
+	result += qstate->read_func(qstate, write_request->data, write_request->data_size);
+	
+	if (result != qstate->kevent_watermark) {
+		TRACE_OUT(on_write_request_read2);
+		return (-1);
+	}
+	
+	qstate->kevent_watermark = 0;
+	qstate->process_func = on_write_request_process;
+	TRACE_OUT(on_write_request_read2);
+	return (0);
+}
+
+static	int
+on_write_request_process(struct query_state *qstate)
+{
+	TRACE_IN(on_write_request_process);
+	init_comm_element(&qstate->response, CET_WRITE_RESPONSE);
+	
+	qstate->kevent_watermark = sizeof(int);
+	qstate->process_func = on_write_response_write1;
+	TRACE_OUT(on_write_request_process);
+	return (0);
+}
+
+static int
+on_write_response_write1(struct query_state *qstate)
+{
+	struct cache_write_response	*write_response;
+	ssize_t	result;
+	
+	TRACE_IN(on_write_response_write1);
+	write_response = get_cache_write_response(&qstate->response);
+	result = qstate->write_func(qstate, &write_response->error_code, sizeof(int));
+	if (result != sizeof(int)) {
+		TRACE_OUT(on_write_response_write1);
+		return (-1);
+	}
+	
+	qstate->kevent_watermark = 0;
+	qstate->process_func = NULL;
+	TRACE_OUT(on_write_response_write1);
+	return (0);
+}
+
+static int
+on_read_request_read1(struct query_state *qstate)
+{
+	struct cache_read_request	*read_request;
+	ssize_t	result;
+	
+	TRACE_IN(on_read_request_read1);
+	if (qstate->kevent_watermark == 0)
+		qstate->kevent_watermark = sizeof(size_t) * 2;
+	else {
+		init_comm_element(&qstate->request, CET_READ_REQUEST);
+		read_request = get_cache_read_request(&qstate->request);
+		
+		result = qstate->read_func(qstate, &read_request->entry_length, sizeof(size_t));
+		result += qstate->read_func(qstate, &read_request->cache_key_length, sizeof(size_t));
+		
+		if (result != sizeof(size_t) * 2) {
+			TRACE_OUT(on_read_request_read1);
+			return (-1);
+		}
+		
+		read_request->entry = (char *)malloc(read_request->entry_length + 1);
+		assert(read_request->entry != NULL);
+		memset(read_request->entry, 0, read_request->entry_length + 1);
+		
+		read_request->cache_key = (char *)malloc(read_request->cache_key_length + 1);
+		assert(read_request->cache_key != NULL);
+		memset(read_request->cache_key, 0, read_request->cache_key_length + 1);
+		
+		qstate->kevent_watermark = read_request->entry_length + 
+			read_request->cache_key_length;
+		qstate->process_func = on_read_request_read2;
+	}
+	
+	TRACE_OUT(on_read_request_read1);
+	return (0);
+}
+
+static int
+on_read_request_read2(struct query_state *qstate)
+{
+	return (-1);
+}
+
+static int
+on_transform_request_read1(struct query_state *qstate)
+{
+	TRACE_IN(on_transform_request_read1);
+	TRACE_OUT(on_transform_request_read1);
+	return (-1);
+}
+
+ssize_t	
+query_socket_read(struct query_state *qstate, void *buf, size_t nbytes)
+{
+	ssize_t	result;
+	
+	TRACE_IN(query_socket_read);
+	result = read(qstate->sockfd, buf, nbytes);
+	TRACE_OUT(query_socket_read);
+	
+	return (result);
+}
+
+ssize_t	
+query_socket_write(struct query_state *qstate, const void *buf, size_t nbytes)
+{
+	ssize_t	result;
+	
+	TRACE_IN(query_socket_write);
+	result = write(qstate->sockfd, buf, nbytes);
+	TRACE_OUT(query_socket_write);
+	
+	return (result);
+}
+
+struct query_state	*
+init_query_state(int sockfd, size_t kevent_watermark)
+{
+	struct query_state	*retval;
+		
+	TRACE_IN(init_query_state);
+	retval = (struct query_state *)malloc(sizeof(struct query_state));
+	assert(retval != NULL);
+	memset(retval, 0, sizeof(struct query_state));
+		
+	retval->sockfd = sockfd;
+	retval->kevent_filter = EVFILT_READ;
+	retval->kevent_watermark = kevent_watermark;
+	
+	init_comm_element(&retval->request, CET_UNDEFINED);
+	init_comm_element(&retval->response, CET_UNDEFINED);
+	retval->process_func = on_query_startup;
+	retval->destroy_func = on_query_destroy;
+	
+	retval->write_func = query_socket_write;
+	retval->read_func = query_socket_read;
+	
+	TRACE_OUT(init_query_state);
+	return (retval);
+}
+
+void	
+destroy_query_state(struct query_state *qstate)
+{
+	TRACE_IN(destroy_query_state);
+	free(qstate);
+	TRACE_OUT(destroy_query_state);
+}

==== //depot/projects/soc2005/nsswitch_cached/cached/query.h#2 (text+ko) ====

@@ -1,17 +1,44 @@
 #ifndef __CACHED_QUERY_H__
 #define __CACHED_QUERY_H__
 
+#include <sys/types.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include "protocol.h"
+
+struct query_state;
 
+typedef	int (*query_process_func)(struct query_state *);
+typedef void (*query_destroy_func)(struct query_state *);
+typedef ssize_t (*query_read_func)(struct query_state *, void *, size_t);
+typedef ssize_t (*query_write_func)(struct query_state *, const void *, size_t);
+
 /* the query state structure contains the information to process all types of
  * requests and to send all types of responses */
 struct query_state {
 	int		sockfd;				/* the unix socket to read/write */
 	int		kevent_filter;		/* EVFILT_READ or EVFILT_WRITE */
 	size_t	kevent_watermark;	/* how many bytes do we want to be sent/received */	
+	
+	query_process_func	process_func;	/* called on each event */
+	query_destroy_func	destroy_func;	/* called on destroy */
+	
+	query_write_func	write_func;		/* data write function */
+	query_read_func		read_func;		/* data read function */
+	
+	struct comm_element	request;
+	struct comm_element	response;
+	void	*mdata;
+	
+	uid_t	euid;				/* euid of the caller, recevied via credentials */
+	uid_t	uid;				/* uid of the caller, recevied via credentials */
+	pid_t	pid;				/* pid of the caller, recevied via credentials */
 };
 
-struct query_state	*init_query_state(int);
+ssize_t	query_socket_read(struct query_state *, void *, size_t);
+ssize_t	query_socket_write(struct query_state *, const void *, size_t);
+
+struct query_state	*init_query_state(int, size_t);
 void	destroy_query_state(struct query_state *);
 
 #endif

==== //depot/projects/soc2005/nsswitch_cached/cached/singletons.c#2 (text+ko) ====

@@ -2,3 +2,4 @@
 
 struct configuration *s_configuration = NULL;
 cache	s_cache; /* TODO: initializer needed? */
+struct runtime_env	 *s_runtime_env = NULL;

==== //depot/projects/soc2005/nsswitch_cached/cached/singletons.h#2 (text+ko) ====

@@ -4,7 +4,13 @@
 #include <cachelib/include/cachelib.h>
 #include "config.h"
 
+struct runtime_env {
+	int	queue;
+	int	sockfd;
+};
+
 extern	struct configuration	*s_configuration;
 extern	cache	s_cache;
+extern	struct runtime_env		*s_runtime_env;
 
 #endif


More information about the p4-projects mailing list