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>