Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 Nov 2005 13:30:15 GMT
From:      soc-bushman <soc-bushman@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 86904 for review
Message-ID:  <200511181330.jAIDUFvF001544@repoman.freebsd.org>

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

Change 86904 by soc-bushman@soc-bushman_stinger on 2005/11/18 13:29:56

	cache invalidation feature (with -i and -I command line arguments) was added
	libpidfile is now used (through libutil)
	all chages should be tested carefully

Affected files ...

.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/Makefile#7 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/Makefile#12 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agent.c#4 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agent.h#4 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/Makefile.inc#7 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/group.c#4 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/group.h#4 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/hosts.c#7 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/hosts.h#7 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/passwd.c#7 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/passwd.h#7 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/services.c#7 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/services.h#7 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cached.8#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cached.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cached.conf#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cached.conf.5#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cachelib.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cachelib.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cacheplcs.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cacheplcs.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/config.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/config.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/debug.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/debug.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/hashtable.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/log.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/log.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/mp_rs_query.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/mp_rs_query.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/mp_ws_query.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/mp_ws_query.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/parser.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/parser.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/protocol.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/protocol.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/query.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/query.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/singletons.c#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/singletons.h#11 edit
.. //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/startup/cached#6 edit

Differences ...

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/Makefile#7 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/Makefile#12 (text+ko) ====

@@ -5,11 +5,12 @@
 MAN=cached.conf.5 cached.8
 
 WARNS?=2
-SRCS= agent.c cached.c cachelib.c cacheplcs.c debug.c log.c config.c query.c\
-	mp_ws_query.c mp_rs_query.c singletons.c protocol.c parser.c
+SRCS= agent.c cached.c cachedcli.c cachelib.c cacheplcs.c debug.c log.c \
+	config.c query.c mp_ws_query.c mp_rs_query.c singletons.c protocol.c \
+	parser.c
 CFLAGS+= -DCONFIG_PATH="\"${PREFIX}/etc/cached.conf\""
-DPADD+=${LIBM} ${LIBPTHREAD}
-LDADD+=${LIBM} ${LIBPTHREAD}
+DPADD+=${LIBM} ${LIBPTHREAD} ${LIBUTIL}
+LDADD+=${LIBM} ${LIBPTHREAD} ${LIBUTIL}
 LDFLAGS+= -Xlinker --export-dynamic
 
 FILESGROUPS=STARTUP CONF

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agent.c#4 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agent.h#4 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/Makefile.inc#7 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/group.c#4 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/group.h#4 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/hosts.c#7 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/hosts.h#7 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/passwd.c#7 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/passwd.h#7 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/services.c#7 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/agents/services.h#7 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cached.8#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cached.c#11 (text+ko) ====

@@ -29,10 +29,13 @@
 #include <sys/event.h>
 #include <sys/socket.h>
 #include <sys/time.h>
+#include <sys/param.h>
 #include <sys/un.h>
 #include <assert.h>
+#include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <libutil.h>
 #include <pthread.h>
 #include <signal.h>
 #include <stdio.h>
@@ -44,6 +47,7 @@
 #include "agents/group.h"
 #include "agents/services.h"
 #include "agents/hosts.h"
+#include "cachedcli.h"
 #include "cachelib.h"
 #include "config.h"
 #include "debug.h"
@@ -53,7 +57,7 @@
 #include "singletons.h"
 
 #ifndef CONFIG_PATH
-#define CONFIG_PATH "/usr/local/etc/cached.conf"
+#define CONFIG_PATH "/etc/cached.conf"
 #endif
 #define DEFAULT_CONFIG_PATH	"cached.conf"
 
@@ -86,7 +90,6 @@
 static void process_timer_event(struct kevent *, struct runtime_env *,
 	struct configuration *);
 static void *processing_thread(void *);
-static int write_pid_file(const char *);
 static void usage(void);
 
 void get_time_func(struct timeval *);
@@ -128,29 +131,6 @@
 	TRACE_OUT(destroy_global_timer);
 }
 
-static int
-write_pid_file(const char *filename)
-{
-	char	*pid_string;
-	FILE	*pidfile;
-        
-	pidfile = fopen(filename, "w");
-	if (pidfile == NULL) {
-		LOG_ERR_2("write_pid_file", "can't write to pidfile %s", 
-			filename);
-		return (-1);
-	}
-        
-	asprintf(&pid_string,"%u",getpid());
-	assert(pid_string != NULL);
-	
-	fwrite(pid_string,strlen(pid_string), 1, pidfile);
-	free(pid_string);
-	fclose(pidfile);
-	
-	return (0);
-}
-
 static void
 print_version_info(void)
 {
@@ -162,7 +142,7 @@
 static void
 usage(void)
 {
-	fprintf(stderr,"usage: cached [-nst]\n");	
+	fprintf(stderr,"usage: cached [-nstiId]\n");	
 	exit(1);
 }
 
@@ -190,9 +170,18 @@
 	    	 * would be registered automatically during the queries.
 	    	 */
 		res = register_cache_entry(retval, (struct cache_entry_params *)
-			&config_entry->positive_cache_params);		
+			&config_entry->positive_cache_params);
+		config_entry->positive_cache_entry = find_cache_entry(retval, 
+			config_entry->positive_cache_params.entry_name);
+		assert(config_entry->positive_cache_entry != 
+			INVALID_CACHE_ENTRY);
+		
 		res = register_cache_entry(retval, (struct cache_entry_params *)
 			&config_entry->negative_cache_params);
+		config_entry->negative_cache_entry = find_cache_entry(retval,
+			config_entry->negative_cache_params.entry_name);
+		assert(config_entry->negative_cache_entry !=
+			INVALID_CACHE_ENTRY);
 	}
 	
 	LOG_MSG_2("cache", "cache was successfully initialized");
@@ -642,6 +631,12 @@
 int 
 main(int argc, char *argv[])
 {
+	struct processing_thread_args *thread_args;
+	pthread_t *threads;
+
+	struct pidfh *pidfile;
+	pid_t pid;
+	
 	char const *config_file;
 	char const *error_str;
 	int error_line;
@@ -650,9 +645,11 @@
 	int trace_mode_enabled;
 	int force_single_threaded;
 	int do_not_daemonize;
+	int clear_user_cache_entries, clear_all_cache_entries;
+	char *user_config_entry_name, *global_config_entry_name;
+	int show_statistics;
+	int daemon_mode, interactive_mode;
 	
-	struct processing_thread_args *thread_args;
-	pthread_t *threads;
 	
 	/* by default all debug messages are omitted */	
 	TRACE_OFF();	
@@ -664,7 +661,12 @@
 	trace_mode_enabled = 0;
 	force_single_threaded = 0;
 	do_not_daemonize = 0;
-	while ((res = getopt(argc, argv, "nst")) != -1) {
+	clear_user_cache_entries = 0;
+	clear_all_cache_entries = 0;
+	show_statistics = 0;
+	user_config_entry_name = NULL;
+	global_config_entry_name = NULL;
+	while ((res = getopt(argc, argv, "nstdi:I:")) != -1) {
 		switch (res) {
 		case 'n':
 			do_not_daemonize = 1;
@@ -675,6 +677,22 @@
 		case 't':
 			trace_mode_enabled = 1;
 			break;
+		case 'i':
+			clear_user_cache_entries = 1;
+			if (optarg != NULL)
+				if (strcmp(optarg, "all") != 0)
+					user_config_entry_name = strdup(optarg);
+			break;
+		case 'I':
+			clear_all_cache_entries = 1;
+			if (optarg != NULL)
+				if (strcmp(optarg, "all") != 0)
+					global_config_entry_name = 
+						strdup(optarg);
+			break;
+		case 'd':
+			show_statistics = 1;
+			break;
 		case '?':
 		default:
 			usage();
@@ -682,6 +700,92 @@
 		}
 	}
 	
+	daemon_mode = do_not_daemonize | force_single_threaded |
+		trace_mode_enabled;
+	interactive_mode = clear_user_cache_entries | clear_all_cache_entries |
+		show_statistics;
+	
+	if ((daemon_mode != 0) && (interactive_mode != 0)) {
+		LOG_ERR_1("main", "daemon mode and interactive_mode arguments "
+			"can't be used together");
+		usage();		
+	}
+	
+	if (interactive_mode != 0) {
+		FILE *pidfin = fopen(DEFAULT_PIDFILE_PATH, "r");
+		char pidbuf[256];
+		
+		struct cached_connection_params connection_params;
+		cached_connection connection;
+		
+		int result;
+		
+		if (pidfin == NULL)
+			errx(EXIT_FAILURE, "There is no daemon running.");
+		
+		memset(pidbuf, 0, sizeof(pidbuf));
+		fread(pidbuf, sizeof(pidbuf) - 1, 1, pidfin);
+		fclose(pidfin);
+		
+		if (ferror(pidfin) != 0)
+			errx(EXIT_FAILURE, "Can't read from pidfile.");
+		
+		if (sscanf(pidbuf, "%d", &pid) != 1)
+			errx(EXIT_FAILURE, "Invalid pidfile.");		
+		LOG_MSG_1("main", "daemon PID is %d", pid);
+		
+		
+		memset(&connection_params, 0, 
+			sizeof(struct cached_connection_params));
+		connection_params.socket_path = DEFAULT_SOCKET_PATH;
+		connection = open_cached_connection(&connection_params);
+		if (connection == INVALID_CACHED_CONNECTION)
+			errx(EXIT_FAILURE, "Can't connect to the daemon.");
+		
+		if (clear_user_cache_entries != 0) {		
+			result = cached_transform(connection, 
+				user_config_entry_name, TT_USER);
+			if (result != 0)
+				LOG_MSG_1("main",
+					"user cache transformation failed");
+			else
+				LOG_MSG_1("main",
+					"user cache_transformation "
+					"succeeded");
+		}
+		
+		if (clear_all_cache_entries != 0) {
+			if (geteuid() != 0)
+				errx(EXIT_FAILURE, "Only root can initiate "
+					"global cache transformation.");
+			
+			result = cached_transform(connection, 
+				global_config_entry_name, TT_ALL);
+			if (result != 0)
+				LOG_MSG_1("main",
+					"global cache transformation "
+					"failed");
+			else
+				LOG_MSG_1("main",
+					"global cache transformation "
+					"succeeded");
+		}
+		
+		close_cached_connection(connection);
+		
+		free(user_config_entry_name);
+		free(global_config_entry_name);
+		return (EXIT_SUCCESS);
+	}
+	
+	pidfile = pidfile_open(DEFAULT_PIDFILE_PATH, 0600, &pid);
+	if (pidfile == NULL) {
+		if (errno == EEXIST)
+			errx(EXIT_FAILURE, "Daemon already running, pid: %d.", 
+				pid);
+		warn("Cannot open or create pidfile");
+	}
+	
 	if (trace_mode_enabled == 1)
 		TRACE_ON();
 	
@@ -694,11 +798,14 @@
 		if (res != 0) {
 			LOG_ERR_1("main", "can't daemonize myself: %s", 
 		    		strerror(errno));
+			pidfile_remove(pidfile);
 			goto fin;
 		} else
 			LOG_MSG_1("main", "successfully daemonized");
 	}
 	
+	pidfile_write(pidfile);
+	
 	/* global timer initialization */
 	res = init_global_timer();
 	if (res != 0) {
@@ -770,16 +877,8 @@
 		destroy_configuration(s_configuration);
 		destroy_cache_(s_cache);
 		return (-1);
-	}
-	
-	/* writing PID file */
-	res = write_pid_file(s_configuration->pidfile_path);
-	if (res != 0) {
-		LOG_ERR_1("main", "can't write the pid file into the %s", 
-			s_configuration->pidfile_path);
-		goto fin;
-	}
-		
+	}	
+
 	if (s_configuration->threads_num > 1) {
 		threads = (pthread_t *)malloc(sizeof(pthread_t) * 
 			s_configuration->threads_num);
@@ -823,5 +922,6 @@
 	/* global timer destruction */
 	destroy_global_timer();
 	
-	return (0);
+	pidfile_remove(pidfile);
+	return (EXIT_SUCCESS);
 }

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cached.conf#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cached.conf.5#11 (text+ko) ====

@@ -38,10 +38,9 @@
 see them below.
 .Pp
 Each line specifies either an attribute and a value, or an attribute,
-a cachename and a value. Valid cachenames are passwd, groups, hosts,
-services, protocols and rpc. If you need to use some other cachename for
-your own needs (for example, if some third-party application uses nsswitch),
-you can simply use it without any restrictions.
+a cachename and a value. Usual cachenames are passwd, groups, hosts,
+services, protocols and rpc. You can also use any other cachename 
+(for example, if some third-party application uses nsswitch).
 .Pp
 .Bl -tag -width Pair
 .It Sy threads [value]

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cachelib.c#11 (text+ko) ====

@@ -61,6 +61,7 @@
 		int (*)(struct cache_common_entry_ *, 
 		struct cache_policy_item_ *));
 static int ht_items_cmp_func(const void *, const void *);
+static int ht_items_fixed_size_left_cmp_func(const void *, const void *);
 static hashtable_index_t ht_item_hash_func(const void *, size_t);	
 		
 /*
@@ -70,6 +71,8 @@
 ht_items_cmp_func(const void *p1, const void *p2)
 {	
     	struct cache_ht_item_data_ *hp1, *hp2;
+	size_t min_size;
+	int result;
     
 	hp1 = (struct cache_ht_item_data_ *)p1;
 	hp2 = (struct cache_ht_item_data_ *)p2;
@@ -77,10 +80,46 @@
 	assert(hp1->key != NULL);
 	assert(hp2->key != NULL);
 		
-	if (hp1->key_size != hp2->key_size)
-	    return (-1);
+	if (hp1->key_size != hp2->key_size) {
+		min_size = (hp1->key_size < hp2->key_size) ? hp1->key_size :
+			hp2->key_size;
+		result = memcmp(hp1->key, hp2->key, min_size);
+		
+		if (result == 0)
+			return ((hp1->key_size < hp2->key_size) ? -1 : 1);
+		else
+			return (result);
+	} else
+		return (memcmp(hp1->key, hp2->key, hp1->key_size));
+}
+
+static int
+ht_items_fixed_size_left_cmp_func(const void *p1, const void *p2)
+{
+    	struct cache_ht_item_data_ *hp1, *hp2;
+	size_t min_size;
+	int result;		
+    
+	hp1 = (struct cache_ht_item_data_ *)p1;
+	hp2 = (struct cache_ht_item_data_ *)p2;
+	
+	assert(hp1->key != NULL);
+	assert(hp2->key != NULL);
 	
-	return (memcmp(hp1->key, hp2->key, hp1->key_size));
+	if (hp1->key_size != hp2->key_size) {
+		min_size = (hp1->key_size < hp2->key_size) ? hp1->key_size :
+			hp2->key_size;
+		result = memcmp(hp1->key, hp2->key, min_size);
+		
+		if (result == 0)
+			if (min_size == hp1->key_size)
+			    return (0);
+			else
+			    return ((hp1->key_size < hp2->key_size) ? -1 : 1);
+		else
+			return (result);
+	} else
+		return (memcmp(hp1->key, hp2->key, hp1->key_size));
 }
 
 static hashtable_index_t 
@@ -361,6 +400,7 @@
 		HASHTABLE_ENTRY_REMOVE(cache_ht_, ht_item, ht_item_data);
 		free(ht_item_data->key);
 		free(ht_item_data->value);
+		free(ht_item_data);
 		--entry->items_size;
 
 		policy->destroy_item_func(item);
@@ -1105,44 +1145,89 @@
 	TRACE_OUT(close_cache_mp_read_session);
 }
 
-/*
- * Transforms all cache entries, by applying the specified transformation.
- */
-int 
-transform_cache(struct cache_ *the_cache, 
-	enum cache_transformation_t transformation)
-{
-	int cur_retval;
-	int retval;
-	size_t i;
-
-	retval = 0;	
-	for (i = 0; i < the_cache->entries_size; ++i) {
-		cur_retval = transform_cache_entry(the_cache->entries[i], 
-			transformation);
-		if ((cur_retval != 0) && (retval == 0))
-			retval = -2;
-		
-		if ((cur_retval == 0) && (retval == -2))
-			retval = -1;
-	}
-	
-	return (retval);
-}
-
 int 
 transform_cache_entry(struct cache_entry_ *entry, 
 	enum cache_transformation_t transformation)
 {
 	
+	TRACE_IN(transform_cache_entry);
 	switch (transformation) {
 	case CTT_CLEAR:
 		clear_cache_entry(entry);
+		TRACE_OUT(transform_cache_entry);
 		return (0);
 	case CTT_FLUSH:
 		flush_cache_entry(entry);
+		TRACE_OUT(transform_cache_entry);
 		return (0);
 	default:
+		TRACE_OUT(transform_cache_entry);
 		return (-1);
+	}	
+}
+
+int 
+transform_cache_entry_part(struct cache_entry_ *entry, 
+	enum cache_transformation_t transformation, const char *key_part, 
+	size_t key_part_size, enum part_position_t part_position)
+{
+	struct cache_common_entry_ *common_entry;
+	struct cache_ht_item_ *ht_item;
+	struct cache_ht_item_data_ *ht_item_data, ht_key;
+		
+	struct cache_policy_item_ *item, *connected_item;
+	
+	TRACE_IN(transform_cache_entry_part);
+	if (entry->params->entry_type != CET_COMMON) {
+		TRACE_OUT(transform_cache_entry_part);
+		return (-1);
+	}
+	
+	if (transformation != CTT_FLUSH) {
+		TRACE_OUT(transform_cache_entry_part);
+		return (-1);
+	}
+	
+	memset(&ht_key, 0, sizeof(struct cache_ht_item_data_));
+	ht_key.key = (char *)key_part;	/* can't avoid casting here */
+	ht_key.key_size = key_part_size;	
+	
+	common_entry = (struct cache_common_entry_ *)entry;
+	HASHTABLE_FOREACH(&(common_entry->items), ht_item) {				
+		do {
+			ht_item_data = HASHTABLE_ENTRY_FIND_SPECIAL(cache_ht_, 
+				ht_item, &ht_key, 
+				ht_items_fixed_size_left_cmp_func);
+		
+			if (ht_item_data != NULL) {
+			    item = ht_item_data->fifo_policy_item;
+			    connected_item = item->connected_item;
+			
+						
+			    common_entry->policies[0]->remove_item_func(
+				common_entry->policies[0],
+				item);
+			
+			    HASHTABLE_ENTRY_REMOVE(cache_ht_, ht_item, 
+				ht_item_data);
+			    free(ht_item_data->key);
+			    free(ht_item_data->value);
+			    free(ht_item_data);
+			    --common_entry->items_size;
+			
+			    common_entry->policies[0]->destroy_item_func(
+				item);
+			    if (common_entry->policies_size == 2) {
+				common_entry->policies[1]->remove_item_func(
+				    common_entry->policies[1],
+				    connected_item);
+				common_entry->policies[1]->destroy_item_func(
+				    connected_item);
+			    }
+			}
+		} while (ht_item_data != NULL);			
 	}
+	
+	TRACE_OUT(transform_cache_entry_part);	
+	return (0);
 }

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cachelib.h#11 (text+ko) ====

@@ -57,6 +57,16 @@
 	CMPT_WRITE_SESSION
 };
 
+/* 
+ * When doing partial transformations of entries (which are applied for 
+ * elements with keys, that contain specified buffer in its left or 
+ * right part), this enum will show the needed position of the key part.
+ */
+enum part_position_t {
+	KPPT_LEFT,
+	KPPT_RIGHT
+};
+
 /* num_levels attribute is obsolete, i think - user can always emulate it
  * by using one entry.
  * get_time_func is needed to have the clocks-independent counter
@@ -147,7 +157,7 @@
 	 * user can specify another policy to be applied, when there are too
 	 * many elements in the entry. So policies_size can be 1 or 2.
 	 */
-	struct cache_policy_ ** policies;
+	struct cache_policy_ **policies;
 	size_t policies_size;
 	
 	void	(*get_time_func)(struct timeval *);	
@@ -263,7 +273,8 @@
 extern void close_cache_mp_read_session(cache_mp_read_session);
 
 /* transformation routines */
-extern int transform_cache(cache, enum cache_transformation_t);
 extern int transform_cache_entry(cache_entry, enum cache_transformation_t);
+extern int transform_cache_entry_part(cache_entry, enum cache_transformation_t,
+	const char *, size_t, enum part_position_t);
 
 #endif

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cacheplcs.c#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/cacheplcs.h#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/config.c#11 (text+ko) ====

@@ -48,6 +48,9 @@
 
 static int configuration_entry_cmp(const void *, const void *);
 static int configuration_entry_sort_cmp(const void *, const void *);
+static int configuration_entry_cache_mp_sort_cmp(const void *, const void *);
+static int configuration_entry_cache_mp_cmp(const void *, const void *);
+static int configuration_entry_cache_mp_part_cmp(const void *, const void *);
 static struct configuration_entry *create_configuration_entry(const char *,
 	struct timeval const *, struct timeval const *,
 	struct common_cache_entry_params const *,
@@ -70,6 +73,31 @@
 		));
 }
 
+static int
+configuration_entry_cache_mp_sort_cmp(const void *e1, const void *e2)
+{
+	return (strcmp((*((cache_entry *)e1))->params->entry_name,
+		(*((cache_entry *)e2))->params->entry_name
+		));
+}
+
+static int
+configuration_entry_cache_mp_cmp(const void *e1, const void *e2)
+{
+	return (strcmp((const char *)e1,
+		(*((cache_entry *)e2))->params->entry_name
+		));
+}
+
+static int
+configuration_entry_cache_mp_part_cmp(const void *e1, const void *e2)
+{
+	return (strncmp((const char *)e1,
+		(*((cache_entry *)e2))->params->entry_name,
+		strlen((const char *)e1)
+		));
+}
+
 static struct configuration_entry *
 create_configuration_entry(const char *name, 
 	struct timeval const *common_timeout, 
@@ -248,7 +276,7 @@
 	}
 	
 	if (config->entries_size == config->entries_capacity) {
-		struct configuration_entry	**new_entries;
+		struct configuration_entry **new_entries;
 			
 		config->entries_capacity *= 2;
 		new_entries = (struct configuration_entry **)malloc(
@@ -308,6 +336,108 @@
 	return ((retval != NULL) ? *retval : NULL);
 }
 
+/*
+ * All multipart cache entries are stored in the configuration_entry in the
+ * sorted array (sorted by names). The 3 functions below manage this array.
+ */
+
+int 
+configuration_entry_add_mp_cache_entry(struct configuration_entry *config_entry,
+	cache_entry c_entry)
+{
+	cache_entry *new_mp_entries, *old_mp_entries;
+	
+	TRACE_IN(configuration_entry_add_mp_cache_entry);
+	++config_entry->mp_cache_entries_size;
+	new_mp_entries = (cache_entry *)malloc(sizeof(cache_entry) *
+		config_entry->mp_cache_entries_size);
+	assert(new_mp_entries != NULL);
+	new_mp_entries[0] = c_entry;
+	if (config_entry->mp_cache_entries_size - 1 > 0) {
+		memcpy(new_mp_entries + 1, 
+		    config_entry->mp_cache_entries,
+		    config_entry->mp_cache_entries_size - 1);
+	}
+
+	old_mp_entries = config_entry->mp_cache_entries;
+	config_entry->mp_cache_entries = new_mp_entries;
+	free(old_mp_entries);
+	
+	qsort(config_entry->mp_cache_entries, 
+		config_entry->mp_cache_entries_size,
+		sizeof(cache_entry), 
+		configuration_entry_cache_mp_sort_cmp);
+	
+	TRACE_OUT(configuration_entry_add_mp_cache_entry);
+
+	return (0);
+}
+
+cache_entry 
+configuration_entry_find_mp_cache_entry(
+	struct configuration_entry *config_entry, const char *mp_name)
+{
+	cache_entry *result;
+	
+	TRACE_IN(configuration_entry_find_mp_cache_entry);
+	result = bsearch(mp_name, config_entry->mp_cache_entries, 
+		config_entry->mp_cache_entries_size,
+		sizeof(cache_entry), configuration_entry_cache_mp_cmp);
+	
+	if (result == NULL) {
+		TRACE_OUT(configuration_entry_find_mp_cache_entry);
+		return (NULL);
+	} else {
+		TRACE_OUT(configuration_entry_find_mp_cache_entry);
+		return (*result);
+	}	
+}
+
+/* 
+ * Searches for all multipart entries with names starting with mp_name.
+ * Needed for cache flushing.
+ */
+int 
+configuration_entry_find_mp_cache_entries(
+	struct configuration_entry *config_entry, const char *mp_name,
+	cache_entry **start, cache_entry **finish)
+{
+	cache_entry *result;
+	
+	TRACE_IN(configuration_entry_find_mp_cache_entries);
+	result = bsearch(mp_name, config_entry->mp_cache_entries, 
+		config_entry->mp_cache_entries_size,
+		sizeof(cache_entry), configuration_entry_cache_mp_part_cmp);	
+	
+	if (result == NULL) {
+		TRACE_OUT(configuration_entry_find_mp_cache_entries);
+		return (-1);
+	}
+	
+	*start = result;
+	*finish = result + 1;
+	
+	while (*start != config_entry->mp_cache_entries) {
+	    if (configuration_entry_cache_mp_part_cmp(mp_name, *start - 1) == 0)
+		*start = *start - 1;
+	    else
+		break;
+	}
+	
+	while (*finish != config_entry->mp_cache_entries + 
+		config_entry->mp_cache_entries_size) {
+	    
+	    if (configuration_entry_cache_mp_part_cmp(
+		mp_name, *finish) == 0)
+	    	*finish = *finish + 1;
+	    else
+		break;
+	}
+	
+	TRACE_OUT(configuration_entry_find_mp_cache_entries);
+	return (0);
+}
+
 /* 
  * Configuration entry uses rwlock to handle access to its fields.
  */

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/config.h#11 (text+ko) ====

@@ -133,6 +133,15 @@
 	struct configuration *, size_t);
 extern struct configuration_entry *configuration_find_entry(
 	struct configuration *, const char *);
+		
+extern int configuration_entry_add_mp_cache_entry(struct configuration_entry *,
+	cache_entry);
+extern cache_entry configuration_entry_find_mp_cache_entry(
+	struct configuration_entry *,
+	const char *);
+extern int configuration_entry_find_mp_cache_entries(
+	struct configuration_entry *, const char *, cache_entry **,
+	cache_entry **);
 	    
 extern void configuration_lock_rdlock(struct configuration *config);
 extern void configuration_lock_wrlock(struct configuration *config);

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/debug.c#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/debug.h#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/hashtable.h#11 (text+ko) ====

@@ -145,7 +145,9 @@
 hashtable_index_t name##_CALCULATE_HASH(struct name *, type *);		\
 void name##_ENTRY_STORE(struct entry_*, type *);			\
 type *name##_ENTRY_FIND(struct entry_*, type *);			\
-void name##_ENTRY_REMOVE(struct entry_*, type *);			\
+type *name##_ENTRY_FIND_SPECIAL(struct entry_ *, type *,		\
+	int (*) (const void *, const void *));				\
+void name##_ENTRY_REMOVE(struct entry_*, type *);			
 
 /*
  * Generates implementations of the hash table functions
@@ -177,6 +179,13 @@
 		the_entry->field.size, sizeof(type), CMP));		\
 }									\
 									\
+type *name##_ENTRY_FIND_SPECIAL(struct entry_ *the_entry, type *key,	\
+	int (*compar) (const void *, const void *))			\
+{									\
+	return ((type *)bsearch(key, the_entry->field.values,	 	\
+		the_entry->field.size, sizeof(type), compar));		\
+}									\
+									\
 void name##_ENTRY_REMOVE(struct entry_ *the_entry, type *del_elm)	\
 {									\
 									\
@@ -199,6 +208,9 @@
 #define HASHTABLE_ENTRY_FIND(name, entry, key)				\
 	(name##_ENTRY_FIND((entry), (key)))
 
+#define HASHTABLE_ENTRY_FIND_SPECIAL(name, entry, key, cmp)		\
+	(name##_ENTRY_FIND_SPECIAL((entry), (key), (cmp)))
+
 #define HASHTABLE_ENTRY_REMOVE(name, entry, del_elm)			\
 	name##_ENTRY_REMOVE((entry), (del_elm))
 

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/log.c#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/log.h#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/mp_rs_query.c#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/mp_rs_query.h#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/mp_ws_query.c#11 (text+ko) ====

@@ -499,7 +499,7 @@
 cache_entry register_new_mp_cache_entry(struct query_state *qstate, 
 	const char *dec_cache_entry_name)
 {
-	cache_entry c_entry, *new_mp_entries, *old_mp_entries;
+	cache_entry c_entry;
 	char *en_bkp;
 	
 	TRACE_IN(register_new_mp_cache_entry);
@@ -520,21 +520,9 @@
 		dec_cache_entry_name);
 	configuration_unlock(s_configuration);
 
-	++qstate->config_entry->mp_cache_entries_size;
-	new_mp_entries = (cache_entry *)malloc(sizeof(cache_entry) *
-		qstate->config_entry->mp_cache_entries_size);
-	assert(new_mp_entries != NULL);
-	new_mp_entries[0] = c_entry;
-	if (qstate->config_entry->mp_cache_entries_size -1 > 0) {
-		memcpy(new_mp_entries + 1, 
-		    qstate->config_entry->mp_cache_entries,
-		    qstate->config_entry->mp_cache_entries_size - 1);
-	}
-
-	old_mp_entries = qstate->config_entry->mp_cache_entries;
-	qstate->config_entry->mp_cache_entries = new_mp_entries;
-	free(old_mp_entries);
-			
+	configuration_entry_add_mp_cache_entry(qstate->config_entry,
+		c_entry);
+	
 	configuration_unlock_entry(qstate->config_entry, 
 		CELT_MULTIPART);
 		

==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/mp_ws_query.h#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/parser.c#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/parser.h#11 (text+ko) ====


==== //depot/projects/soc2005/nsswitch_cached/release/cached-0.2/cached/protocol.c#11 (text+ko) ====

@@ -38,6 +38,7 @@
 void
 init_comm_element(struct comm_element *element, enum comm_element_t type)
 {
+	
 	TRACE_IN(init_comm_element);
 	memset(element, 0, sizeof(struct comm_element));
 	
@@ -84,6 +85,8 @@
 		init_cache_mp_read_session_read_response(
 			&element->c_mp_rs_read_response);
 		break;
+	case CET_UNDEFINED:
+		break;
 	default:
 		LOG_ERR_2("init_comm_element", "invalid communication element");
 		TRACE_OUT(init_comm_element);
@@ -97,6 +100,7 @@
 void
 finalize_comm_element(struct comm_element *element)
 {
+	
 	TRACE_IN(finalize_comm_element);
 	switch (element->type) {
 	case CET_WRITE_REQUEST:
@@ -146,6 +150,8 @@
 		finalize_cache_mp_read_session_read_response(
 			&element->c_mp_rs_read_response);
 		break;	
+	case CET_UNDEFINED:
+		break;
 	default:
 	break;
 	}
@@ -157,6 +163,7 @@
 void	
 init_cache_write_request(struct cache_write_request *write_request)
 {
+	
 	TRACE_IN(init_cache_write_request);
 	memset(write_request, 0, sizeof(struct cache_write_request));
 	TRACE_OUT(init_cache_write_request);
@@ -165,6 +172,7 @@
 void
 finalize_cache_write_request(struct cache_write_request *write_request)

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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