Added hash-based stat cache code from Ying Chen.
authorJeremy Allison <jra@samba.org>
Wed, 26 Jan 2000 21:25:35 +0000 (21:25 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 26 Jan 2000 21:25:35 +0000 (21:25 +0000)
Jeremy.
(This used to be commit b62a1bd6328f5894ae1a2fef3ef6fc66304ade52)

source3/Makefile.in
source3/include/hash.h [new file with mode: 0644]
source3/include/includes.h
source3/include/proto.h
source3/lib/hash.c [new file with mode: 0644]
source3/script/mkproto.awk
source3/smbd/filename.c
source3/smbd/server.c
source3/ubiqx/sys_include.h

index 31594bbc8f40a1e1c674fe9fc31978c489f727b8..fd736fd5d5042c8ab0f5cd2a5a2f76d79088acce 100644 (file)
@@ -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 (file)
index 0000000..2de7031
--- /dev/null
@@ -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_ */
index a872c1d306482751ce0a7e4a2d57368beae9818b..a049b725c448cf50cc8a838335397cc40b6fa37e 100644 (file)
@@ -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>
index 03fc5b13536cabdbdc55c48504a08fcb9a66a67d..205031a2a8efc48a1db633b394e310c1455772f7 100644 (file)
@@ -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 (file)
index 0000000..ccaf65b
--- /dev/null
@@ -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);
+}
index 8ef414266abe9d826c36ed7b44a29102955577f4..a8c807a10ce4e6e86ada58f410c225000da97dca 100644 (file)
@@ -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;
   }
 
index 64f63805f3250dc32b74897f45aaed351599d59b..2f8e92d98e61717c69af2a2442c5cadb4b07ac06 100644 (file)
@@ -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
    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  */
index bd07ed8458e8e463c188eb1de7a2b8e4eb1cf169..0e9675076fbbb228b153c804b73bcae84d8cf191 100644 (file)
@@ -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);
index acfa5cdb849fe9339372987aa27716126099fc2e..8ff270afe85d2b9872cc5f627887ff21b65be7c3 100644 (file)
@@ -40,6 +40,7 @@
  */
 #define _PROTO_H_
 #define _NAMESERV_H_
+#define _HASH_H_
 
 /* The main Samba system-adaptive header file.
  */