summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2000-01-26 21:25:35 +0000
committerJeremy Allison <jra@samba.org>2000-01-26 21:25:35 +0000
commitace4006c9f7ac16b3c09b1b2222f607bccfa040e (patch)
tree772287462f6eafa8864cc9e4373b759fd5bfcf0d
parentd867b86721e988dee56d5e9382b32c870ccb2790 (diff)
downloadsamba-ace4006c9f7ac16b3c09b1b2222f607bccfa040e.tar.gz
samba-ace4006c9f7ac16b3c09b1b2222f607bccfa040e.tar.bz2
samba-ace4006c9f7ac16b3c09b1b2222f607bccfa040e.zip
Added hash-based stat cache code from Ying Chen.
Jeremy. (This used to be commit b62a1bd6328f5894ae1a2fef3ef6fc66304ade52)
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/include/hash.h75
-rw-r--r--source3/include/includes.h1
-rw-r--r--source3/include/proto.h10
-rw-r--r--source3/lib/hash.c320
-rw-r--r--source3/script/mkproto.awk2
-rw-r--r--source3/smbd/filename.c173
-rw-r--r--source3/smbd/server.c1
-rw-r--r--source3/ubiqx/sys_include.h1
9 files changed, 502 insertions, 83 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 31594bbc8f..fd736fd5d5 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -99,7 +99,7 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
lib/util_array.o lib/util_str.o lib/util_sid.o \
lib/util_unistr.o lib/util_file.o \
lib/util.o lib/util_sock.o lib/util_sec.o smbd/ssl.o lib/fnmatch.o \
- tdb/tdb.o lib/talloc.o
+ tdb/tdb.o lib/talloc.o lib/hash.o
UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.o ubiqx/debugparse.o
diff --git a/source3/include/hash.h b/source3/include/hash.h
new file mode 100644
index 0000000000..2de7031855
--- /dev/null
+++ b/source3/include/hash.h
@@ -0,0 +1,75 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+
+ Copyright (C) Ying Chen 2000.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _HASH_H_
+#define _HASH_H_
+
+#define MAX_HASH_TABLE_SIZE 32768
+#define HASH_TABLE_INCREMENT 2
+
+typedef int (*compare_function)(char *, char *);
+typedef int (*hash_function)(int, char *);
+
+/*
+ * lru_link: links the node to the LRU list.
+ * hash_elem: the pointer to the element that is tied onto the link.
+ */
+typedef struct lru_node {
+ ubi_dlNode lru_link;
+ void *hash_elem;
+} lru_node;
+
+/*
+ * bucket_link: link the hash element to the bucket chain that it belongs to.
+ * lru_link: this element ties the hash element to the lru list.
+ * bucket: a pointer to the hash bucket that this element belongs to.
+ * value: a pointer to the hash element content. It can be anything.
+ * key: stores the string key. The hash_element is always allocated with
+ * more memory space than the structure shown below to accomodate the space
+ * used for the whole string. But the memory is always appended at the
+ * end of the structure, so keep "key" at the end of the structure.
+ * Don't move it.
+ */
+typedef struct hash_element {
+ ubi_dlNode bucket_link;
+ lru_node lru_link;
+ ubi_dlList *bucket;
+ void *value;
+ char key[1];
+} hash_element;
+
+/*
+ * buckets: a list of buckets, implemented as a dLinkList.
+ * lru_chain: the lru list of all the hash elements.
+ * num_elements: the # of elements in the hash table.
+ * size: the hash table size.
+ * comp_func: the compare function used during hash key comparisons.
+ */
+
+typedef struct hash_table {
+ ubi_dlList *buckets;
+ ubi_dlList lru_chain;
+ int num_elements;
+ int size;
+ compare_function comp_func;
+} hash_table;
+
+#endif /* _HASH_H_ */
diff --git a/source3/include/includes.h b/source3/include/includes.h
index a872c1d306..a049b725c4 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -619,6 +619,7 @@ extern int errno;
#include "../tdb/tdb.h"
#include "talloc.h"
#include "interfaces.h"
+#include "hash.h"
#ifdef HAVE_FNMATCH
#include <fnmatch.h>
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 03fc5b1353..205031a2a8 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -97,6 +97,15 @@ void generate_random_buffer( unsigned char *out, int len, BOOL re_seed);
char *getsmbpass(char *prompt) ;
+/*The following definitions come from lib/hash.c */
+
+BOOL hash_table_init(hash_table *table, int num_buckets, compare_function compare_func);
+int string_hash(int hash_size, const char *key);
+hash_element *hash_lookup(hash_table *table, char *key);
+hash_element *hash_insert(hash_table *table, char *value, char *key);
+void hash_remove(hash_table *table, hash_element *hash_elem);
+void hash_clear(hash_table *table);
+
/*The following definitions come from lib/interface.c */
void load_interfaces(void);
@@ -2636,6 +2645,7 @@ void print_stat_cache_statistics(void);
BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
BOOL *bad_path, SMB_STRUCT_STAT *pst);
BOOL check_name(char *name,connection_struct *conn);
+BOOL reset_stat_cache( void );
/*The following definitions come from smbd/files.c */
diff --git a/source3/lib/hash.c b/source3/lib/hash.c
new file mode 100644
index 0000000000..ccaf65b55a
--- /dev/null
+++ b/source3/lib/hash.c
@@ -0,0 +1,320 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+
+ Copyright (C) Ying Chen 2000.
+ Copyright (C) Jeremy Allison 2000.
+ - added some defensive programming.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * NB. We may end up replacing this functionality in a future 2.x
+ * release to reduce the number of hashing/lookup methods we support. JRA.
+ */
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+#define NUM_PRIMES 11
+
+static BOOL enlarge_hash_table(hash_table *table);
+static int primes[NUM_PRIMES] =
+ {17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 16411};
+
+/****************************************************************************
+ * This function initializes the hash table.
+ * This hash function hashes on string keys.
+ * This number of hash buckets is always rounded up to a power of
+ * 2 first, then to a prime number that is large than the power of two.
+ * Input:
+ * table -- the hash table pointer.
+ * num_buckets -- the number of buckets to be allocated. This
+ * hash function can dynamically increase its size when the
+ * the hash table size becomes small. There is a MAX hash table
+ * size defined in hash.h.
+ * compare_func -- the function pointer to a comparison function
+ * used by the hash key comparison.
+ ****************************************************************************
+ */
+
+BOOL hash_table_init(hash_table *table, int num_buckets, compare_function compare_func)
+{
+ int i;
+ ubi_dlList *bucket;
+
+ table->num_elements = 0;
+ table->size = 2;
+ table->comp_func = compare_func;
+ while (table->size < num_buckets)
+ table->size <<= 1;
+ for (i = 0; i < NUM_PRIMES; i++) {
+ if (primes[i] > table->size) {
+ table->size = primes[i];
+ break;
+ }
+ }
+
+ DEBUG(5, ("Hash size = %d.\n", table->size));
+
+ if(!(table->buckets = (ubi_dlList *) malloc(sizeof(ubi_dlList) * table->size))) {
+ DEBUG(0,("hash_table_init: malloc fail !\n"));
+ return False;
+ }
+ ubi_dlInitList(&(table->lru_chain));
+ for (i=0, bucket = table->buckets; i < table->size; i++, bucket++)
+ ubi_dlInitList(bucket);
+
+ return True;
+}
+
+/*
+ **************************************************************
+ * Compute a hash value based on a string key value.
+ * Make the string key into an array of int's if possible.
+ * For the last few chars that cannot be int'ed, use char instead.
+ * The function returns the bucket index number for the hashed
+ * key.
+ **************************************************************
+ */
+
+int string_hash(int hash_size, const char *key)
+{
+ int j=0;
+ while (*key)
+ j = j*10 + *key++;
+ return(((j>=0)?j:(-j)) % hash_size);
+}
+
+/* *************************************************************************
+ * Search the hash table for the entry in the hash chain.
+ * The function returns the pointer to the
+ * element found in the chain or NULL if none is found.
+ * If the element is found, the element is also moved to
+ * the head of the LRU list.
+ *
+ * Input:
+ * table -- The hash table where the element is stored in.
+ * hash_chain -- The pointer to the bucket that stores the
+ * element to be found.
+ * key -- The hash key to be found.
+ ***************************************************************************
+ */
+
+static hash_element *hash_chain_find(hash_table *table, ubi_dlList *hash_chain, char *key)
+{
+ hash_element *hash_elem;
+ ubi_dlNodePtr lru_item;
+ int i = 0;
+
+ for (hash_elem = (hash_element *)(ubi_dlFirst(hash_chain)); i < hash_chain->count;
+ i++, hash_elem = (hash_element *)(ubi_dlNext(hash_elem))) {
+ if ((table->comp_func)(hash_elem->key, key) == 0) {
+ /* Move to the head of the lru List. */
+ lru_item = ubi_dlRemove(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
+ ubi_dlAddHead(&(table->lru_chain), lru_item);
+ return(hash_elem);
+ }
+ }
+ return ((hash_element *) NULL);
+}
+
+/* ***************************************************************************
+ *
+ * Lookup a hash table for an element with key.
+ * The function returns a pointer to the hash element.
+ * If no element is found, the function returns NULL.
+ *
+ * Input:
+ * table -- The hash table to be searched on.
+ * key -- The key to be found.
+ *****************************************************************************
+ */
+
+hash_element *hash_lookup(hash_table *table, char *key)
+{
+ return (hash_chain_find(table, &(table->buckets[string_hash(table->size, key)]), key));
+}
+
+/* ***************************************************************
+ *
+ * This function first checks if an element with key "key"
+ * exists in the hash table. If so, the function moves the
+ * element to the front of the LRU list. Otherwise, a new
+ * hash element corresponding to "value" and "key" is allocated
+ * and inserted into the hash table. The new elements are
+ * always inserted in the LRU order to the LRU list as well.
+ *
+ * Input:
+ * table -- The hash table to be inserted in.
+ * value -- The content of the element to be inserted.
+ * key -- The key of the new element to be inserted.
+ *
+ ****************************************************************
+ */
+
+hash_element *hash_insert(hash_table *table, char *value, char *key)
+{
+ hash_element *hash_elem;
+ ubi_dlNodePtr lru_item;
+ ubi_dlList *bucket;
+
+ /*
+ * If the hash table size has not reached the MAX_HASH_TABLE_SIZE,
+ * the hash table may be enlarged if the current hash table is full.
+ * If the hash table size has reached the MAX_HASH_TABLE_SIZE,
+ * use LRU to remove the oldest element from the hash table.
+ */
+
+ if ((table->num_elements >= table->size) &&
+ (table->num_elements < MAX_HASH_TABLE_SIZE)) {
+ if(!enlarge_hash_table(table))
+ return (hash_element *)NULL;
+ table->num_elements += 1;
+ } else if (table->num_elements >= MAX_HASH_TABLE_SIZE) {
+ /* Do an LRU replacement. */
+ lru_item = ubi_dlLast(&(table->lru_chain));
+ hash_elem = (hash_element *)(((lru_node *)lru_item)->hash_elem);
+ bucket = hash_elem->bucket;
+ ubi_dlRemThis(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
+ ubi_dlRemThis(bucket, (ubi_dlNodePtr)hash_elem);
+ free((char*)(hash_elem->value));
+ free(hash_elem);
+ } else {
+ table->num_elements += 1;
+ }
+
+ bucket = &(table->buckets[string_hash(table->size, key)]);
+
+ /* Since we only have 1-byte for the key string, we need to
+ * allocate extra space in the hash_element to store the entire key
+ * string.
+ */
+
+ if(!(hash_elem = (hash_element *) malloc(sizeof(hash_element) + strlen(key)))) {
+ DEBUG(0,("hash_insert: malloc fail !\n"));
+ return (hash_element *)NULL;
+ }
+
+ safe_strcpy((char *) hash_elem->key, key, strlen(key)+1);
+
+ hash_elem->value = (char *)value;
+ hash_elem->bucket = bucket;
+ /* Insert in front of the lru list and the bucket list. */
+ ubi_dlAddHead(bucket, hash_elem);
+ hash_elem->lru_link.hash_elem = hash_elem;
+ ubi_dlAddHead(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
+
+ return(hash_elem);
+}
+
+/* **************************************************************************
+ *
+ * Remove a hash element from the hash table. The hash element is
+ * removed from both the LRU list and the hash bucket chain.
+ *
+ * Input:
+ * table -- the hash table to be manipulated on.
+ * hash_elem -- the element to be removed.
+ **************************************************************************
+ */
+
+void hash_remove(hash_table *table, hash_element *hash_elem)
+{
+ if (hash_elem) {
+ ubi_dlRemove(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
+ ubi_dlRemove(hash_elem->bucket, (ubi_dlNodePtr) hash_elem);
+ if(hash_elem->value)
+ free((char *)(hash_elem->value));
+ if(hash_elem)
+ free((char *) hash_elem);
+ table->num_elements--;
+ }
+}
+
+/* ******************************************************************
+ * Increase the hash table size if it is too small.
+ * The hash table size is increased by the HASH_TABLE_INCREMENT
+ * ratio.
+ * Input:
+ * table -- the hash table to be enlarged.
+ ******************************************************************
+ */
+
+static BOOL enlarge_hash_table(hash_table *table)
+{
+ hash_element *hash_elem;
+ int size, hash_value;
+ ubi_dlList *buckets;
+ ubi_dlList *old_bucket;
+ ubi_dlList *bucket;
+ ubi_dlList lru_chain;
+
+ buckets = table->buckets;
+ lru_chain = table->lru_chain;
+ size = table->size;
+
+ /* Reinitialize the hash table. */
+ if(!hash_table_init(table, table->size * HASH_TABLE_INCREMENT, table->comp_func))
+ return False;
+
+ for (old_bucket = buckets; size > 0; size--, old_bucket++) {
+ while (old_bucket->count != 0) {
+ hash_elem = (hash_element *) ubi_dlRemHead(old_bucket);
+ ubi_dlRemove(&lru_chain, &(hash_elem->lru_link.lru_link));
+ hash_value = string_hash(table->size, (char *) hash_elem->key);
+ bucket = &(table->buckets[hash_value]);
+ ubi_dlAddHead(bucket, hash_elem);
+ ubi_dlAddHead(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
+ hash_elem->bucket = bucket;
+ hash_elem->lru_link.hash_elem = hash_elem;
+ table->num_elements++;
+ }
+ }
+ if(buckets)
+ free((char *) buckets);
+
+ return True;
+}
+
+/* **********************************************************************
+ *
+ * Remove everything from a hash table and free up the memory it
+ * occupies.
+ * Input:
+ * table -- the hash table to be cleared.
+ *
+ *************************************************************************
+ */
+
+void hash_clear(hash_table *table)
+{
+ int i;
+ ubi_dlList *bucket = table->buckets;
+ hash_element *hash_elem;
+ for (i = 0; i < table->size; bucket++, i++) {
+ while (bucket->count != 0) {
+ hash_elem = (hash_element *) ubi_dlRemHead(bucket);
+ if(hash_elem->value)
+ free((char *)(hash_elem->value));
+ if(hash_elem)
+ free((char *)hash_elem);
+ }
+ }
+ if(table->buckets)
+ free((char *) table->buckets);
+}
diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk
index 8ef414266a..a8c807a10c 100644
--- a/source3/script/mkproto.awk
+++ b/source3/script/mkproto.awk
@@ -98,7 +98,7 @@ END {
gotstart = 1;
}
- if( $0 ~ /^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX/ ) {
+ if( $0 ~ /^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element/ ) {
gotstart = 1;
}
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 64f63805f3..2f8e92d98e 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -3,6 +3,8 @@
Version 1.9.
filename handling routines
Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Jeremy Allison 1999-200
+ Copyright (C) Ying Chen 2000
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,6 +21,10 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/*
+ * New hash table stat cache code added by Ying Chen.
+ */
+
#include "includes.h"
extern int DEBUGLEVEL;
@@ -109,15 +115,12 @@ stat cache was %f%% effective.\n", global_stat_cache_lookups,
}
typedef struct {
- ubi_dlNode link;
int name_len;
- pstring orig_name;
- pstring translated_name;
+ char names[2]; /* This is extended via malloc... */
} stat_cache_entry;
-#define MAX_STAT_CACHE_SIZE 50
-
-static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0};
+#define INIT_STAT_CACHE_SIZE 512
+static hash_table stat_cache;
/****************************************************************************
Compare a pathname to a name in the stat cache - of a given length.
@@ -144,9 +147,11 @@ static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len)
static void stat_cache_add( char *full_orig_name, char *orig_translated_path)
{
stat_cache_entry *scp;
+ stat_cache_entry *found_scp;
pstring orig_name;
pstring translated_path;
int namelen;
+ hash_element *hash_elem;
if (!lp_stat_cache()) return;
@@ -194,39 +199,39 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path)
* add it.
*/
- for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp;
- scp = (stat_cache_entry *)ubi_dlNext( scp )) {
- if((strcmp( scp->orig_name, orig_name) == 0) &&
- (strcmp( scp->translated_name, translated_path) == 0)) {
- /*
- * Name does exist - promote it.
- */
- if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != scp ) {
- ubi_dlRemThis( &stat_cache, scp);
- ubi_dlAddHead( &stat_cache, scp);
- }
+ if (hash_elem = hash_lookup(&stat_cache, orig_name)) {
+ found_scp = (stat_cache_entry *)(hash_elem->value);
+ if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) {
return;
+ } else {
+ hash_remove(&stat_cache, hash_elem);
+ if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) {
+ DEBUG(0,("stat_cache_add: Out of memory !\n"));
+ return;
+ }
+ pstrcpy(scp->names, orig_name);
+ pstrcpy((scp->names+namelen+1), translated_path);
+ scp->name_len = namelen;
+ hash_insert(&stat_cache, (char *)scp, orig_name);
}
- }
-
- if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry))) == NULL) {
- DEBUG(0,("stat_cache_add: Out of memory !\n"));
return;
- }
-
- pstrcpy(scp->orig_name, orig_name);
- pstrcpy(scp->translated_name, translated_path);
- scp->name_len = namelen;
-
- ubi_dlAddHead( &stat_cache, scp);
+ } else {
- DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name ));
+ /*
+ * New entry.
+ */
- if(ubi_dlCount(&stat_cache) > lp_stat_cache_size()) {
- scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache );
- free((char *)scp);
- return;
+ if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) {
+ DEBUG(0,("stat_cache_add: Out of memory !\n"));
+ return;
+ }
+ pstrcpy(scp->names, orig_name);
+ pstrcpy(scp->names+namelen+1, translated_path);
+ scp->name_len = namelen;
+ hash_insert(&stat_cache, (char *)scp, orig_name);
}
+
+ DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1)));
}
/****************************************************************************
@@ -238,10 +243,14 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU
{
stat_cache_entry *scp;
stat_cache_entry *longest_hit = NULL;
+ char *trans_name;
pstring chk_name;
int namelen;
+ hash_element *hash_elem;
+ char *sp;
- if (!lp_stat_cache()) return False;
+ if (!lp_stat_cache())
+ return False;
namelen = strlen(name);
@@ -260,55 +269,44 @@ static BOOL stat_cache_lookup( char *name, char *dirpath, char **start, SMB_STRU
if(!case_sensitive)
strupper( chk_name );
- for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp;
- scp = (stat_cache_entry *)ubi_dlNext( scp )) {
- if(scp->name_len <= namelen) {
- if(stat_name_equal_len(scp->orig_name, chk_name, scp->name_len)) {
- if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len))
- longest_hit = scp;
+ while (1) {
+ hash_elem = hash_lookup(&stat_cache, chk_name);
+ if(hash_elem == NULL) {
+ /*
+ * Didn't find it - remove last component for next try.
+ */
+ sp = strrchr(chk_name, '/');
+ if (sp) {
+ *sp = '\0';
+ } else {
+ /*
+ * We reached the end of the name - no match.
+ */
+ global_stat_cache_misses++;
+ return False;
}
+ if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0)
+ || (strcmp(chk_name, "..") == 0)) {
+ global_stat_cache_misses++;
+ return False;
+ }
+ } else {
+ scp = (stat_cache_entry *)(hash_elem->value);
+ global_stat_cache_hits++;
+ trans_name = scp->names+scp->name_len+1;
+ if(dos_stat( trans_name, pst) != 0) {
+ /* Discard this entry - it doesn't exist in the filesystem. */
+ hash_remove(&stat_cache, hash_elem);
+ return False;
+ }
+ memcpy(name, trans_name, scp->name_len);
+ *start = &name[scp->name_len];
+ if(**start == '/')
+ ++*start;
+ StrnCpy( dirpath, trans_name, name - (*start));
+ return (namelen == scp->name_len);
}
}
-
- if(longest_hit == NULL) {
- DEBUG(10,("stat_cache_lookup: cache miss on %s\n", name));
- global_stat_cache_misses++;
- return False;
- }
-
- global_stat_cache_hits++;
-
- DEBUG(10,("stat_cache_lookup: cache hit for name %s. %s -> %s\n",
- name, longest_hit->orig_name, longest_hit->translated_name ));
-
- /*
- * longest_hit is the longest match we got in the list.
- * Check it exists - if so, overwrite the original name
- * and then promote it to the top.
- */
-
- if(dos_stat( longest_hit->translated_name, pst) != 0) {
- /*
- * Discard this entry.
- */
- ubi_dlRemThis( &stat_cache, longest_hit);
- free((char *)longest_hit);
- return False;
- }
-
- memcpy(name, longest_hit->translated_name, longest_hit->name_len);
- if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != longest_hit ) {
- ubi_dlRemThis( &stat_cache, longest_hit);
- ubi_dlAddHead( &stat_cache, longest_hit);
- }
-
- *start = &name[longest_hit->name_len];
- if(**start == '/')
- ++*start;
-
- StrnCpy( dirpath, longest_hit->translated_name, name - (*start));
-
- return (namelen == longest_hit->name_len);
}
/****************************************************************************
@@ -352,7 +350,7 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
*dirpath = 0;
*bad_path = False;
if(pst) {
- ZERO_STRUCTP(pst);
+ ZERO_STRUCTP(pst);
}
if(saved_last_component)
@@ -744,3 +742,16 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d
CloseDir(cur_dir);
return(False);
}
+
+/*************************************************************************** **
+ * Initializes or clears the stat cache.
+ *
+ * Input: none.
+ * Output: none.
+ *
+ * ************************************************************************** **
+ */
+BOOL reset_stat_cache( void )
+{
+ return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp));
+} /* reset_stat_cache */
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index bd07ed8458..0e9675076f 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -320,6 +320,7 @@ BOOL reload_services(BOOL test)
}
reset_mangled_cache();
+ reset_stat_cache();
/* this forces service parameters to be flushed */
become_service(NULL,True);
diff --git a/source3/ubiqx/sys_include.h b/source3/ubiqx/sys_include.h
index acfa5cdb84..8ff270afe8 100644
--- a/source3/ubiqx/sys_include.h
+++ b/source3/ubiqx/sys_include.h
@@ -40,6 +40,7 @@
*/
#define _PROTO_H_
#define _NAMESERV_H_
+#define _HASH_H_
/* The main Samba system-adaptive header file.
*/