]> arthur.barton.de Git - netatalk.git/commitdiff
Use way faster hashing algorithm for dirs
authorfranklahm <franklahm>
Thu, 19 Nov 2009 10:37:43 +0000 (10:37 +0000)
committerfranklahm <franklahm>
Thu, 19 Nov 2009 10:37:43 +0000 (10:37 +0000)
etc/afpd/.cvsignore
etc/afpd/Makefile.am
etc/afpd/directory.c
etc/afpd/hash.c
include/atalk/directory.h
include/atalk/hash.h

index 6bc5977fe061fc446e4ffd96da4729c8b68a9475..173486987ba1dd00705f2389d9ece08b141dae3f 100644 (file)
@@ -1,6 +1,7 @@
 Makefile
 Makefile.in
 afpd
+hash
 test_parse_mtab
 .deps
 .libs
index 99135ff679990f24a5f70d1ea1bf26eb3e60e369..d7f4596ff3157581b7c31651130059abb9ee1131 100644 (file)
@@ -3,6 +3,7 @@
 pkgconfdir = @PKGCONFDIR@
 
 sbin_PROGRAMS = afpd
+noinst_PROGRAMS = hash
 
 afpd_SOURCES = unix.c ofork.c main.c switch.c auth.c volume.c directory.c \
         file.c enumerate.c desktop.c filedir.c fork.c appl.c gettok.c \
@@ -14,17 +15,9 @@ if USE_NFSv4_ACLS
 afpd_SOURCES += acls.c
 endif
 
-
 afpd_LDADD =  $(top_builddir)/libatalk/cnid/libcnid.la $(top_builddir)/libatalk/libatalk.la
-afpd_LDFLAGS = -export-dynamic
-
-noinst_HEADERS = auth.h afp_config.h desktop.h directory.h file.h \
-        filedir.h fork.h globals.h icon.h mangle.h misc.h status.h switch.h \
-        uam_auth.h uid.h unix.h volume.h hash.h acls.h acl_mappings.h extattrs.h
-
-LIBS = @LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@
-
-AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
+afpd_LDFLAGS = -export-dynamic @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@
+afpd_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
         @SLP_CFLAGS@ \
         -D_PATH_AFPDDEFVOL=\"$(pkgconfdir)/AppleVolumes.default\" \
         -D_PATH_AFPDSYSVOL=\"$(pkgconfdir)/AppleVolumes.system\" \
@@ -34,3 +27,10 @@ AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
         -D_PATH_ACL_LDAPCONF=\"$(pkgconfdir)/ldap.conf\" \
         -DAPPLCNAME \
         -DSERVERTEXT=\"$(SERVERTEXT)/\"
+
+noinst_HEADERS = auth.h afp_config.h desktop.h directory.h file.h \
+        filedir.h fork.h globals.h icon.h mangle.h misc.h status.h switch.h \
+        uam_auth.h uid.h unix.h volume.h hash.h acls.h acl_mappings.h extattrs.h
+
+hash_SOURCES = hash.c
+hash_CFLAGS = -DKAZLIB_TEST_MAIN -I$(top_srcdir)/include
index d2e6519e37dd0b696bc9b667c52a3a3b07289e07..87767c57b1005ffe0c14094e6f991172be0bb2cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.117 2009-11-13 00:27:35 didg Exp $
+ * $Id: directory.c,v 1.118 2009-11-19 10:37:43 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -68,10 +68,10 @@ int             afp_errno;
 #define SENTINEL (&sentinel)
 static struct dir sentinel = { SENTINEL, SENTINEL, NULL, DIRTREE_COLOR_BLACK,
                                  NULL, NULL, NULL, NULL, NULL, 0, 0, 
-                                 0, 0, NULL, NULL, NULL};
+                               0, 0, NULL, NULL, 0, NULL};
 static struct dir rootpar  = { SENTINEL, SENTINEL, NULL, 0,
                                  NULL, NULL, NULL, NULL, NULL, 0, 0, 
-                                 0, 0, NULL, NULL, NULL};
+                               0, 0, NULL, NULL, 0, NULL};
 
 /* (from IM: Toolbox Essentials)
  * dirFinderInfo (DInfo) fields:
@@ -149,7 +149,7 @@ int get_afp_errno(const int param)
 struct dir *
 dirsearch_byname( const struct vol *vol, struct dir *cdir, char *name)
 {
-struct dir *dir = NULL;
+    struct dir *dir = NULL;
 
     if ((cdir->d_did != DIRDID_ROOT_PARENT) && (cdir->d_child)) {
         struct dir key;
@@ -157,13 +157,14 @@ struct dir *dir = NULL;
         
         key.d_parent = cdir;
         key.d_u_name = name;
-       hn = hash_lookup(vol->v_hash, &key);
-       if (hn) {
-           dir = hnode_get(hn);
-       }
+        key.d_u_name_len = strlen(name);
+        hn = hash_lookup(vol->v_hash, &key);
+        if (hn) {
+            dir = hnode_get(hn);
+        }
     }
     return dir;
-}            
+}        
 
 /* -----------------------------------------
  * if did is not in the cache resolve it with cnid 
@@ -1062,6 +1063,7 @@ struct dir *dirnew(const char *m_name, const char *u_name)
         return NULL;
     }
 
+    dir->d_u_name_len = strlen(dir->d_u_name);
     dir->d_m_name_ucs2 = NULL;
     dir->d_left = dir->d_right = SENTINEL;
     dir->d_next = dir->d_prev = dir;
@@ -1094,6 +1096,63 @@ const struct dir *k = key;
     return acc;
 }
 
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
+    || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+                      +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+
+static hash_val_t hash_fun2_dir(const void *key)
+{
+    const struct dir *k = key;
+    const char *data = k->d_u_name;
+    int len = k->d_u_name_len;
+    hash_val_t hash = k->d_parent->d_did, tmp;
+
+    int rem = len & 3;
+    len >>= 2;
+
+    /* Main loop */
+    for (;len > 0; len--) {
+        hash  += get16bits (data);
+        tmp    = (get16bits (data+2) << 11) ^ hash;
+        hash   = (hash << 16) ^ tmp;
+        data  += 2*sizeof (uint16_t);
+        hash  += hash >> 11;
+    }
+
+    /* Handle end cases */
+    switch (rem) {
+    case 3: hash += get16bits (data);
+        hash ^= hash << 16;
+        hash ^= data[sizeof (uint16_t)] << 18;
+        hash += hash >> 11;
+        break;
+    case 2: hash += get16bits (data);
+        hash ^= hash << 11;
+        hash += hash >> 17;
+        break;
+    case 1: hash += *data;
+        hash ^= hash << 10;
+        hash += hash >> 1;
+    }
+
+    /* Force "avalanching" of final 127 bits */
+    hash ^= hash << 3;
+    hash += hash >> 5;
+    hash ^= hash << 4;
+    hash += hash >> 17;
+    hash ^= hash << 25;
+    hash += hash >> 6;
+
+    return hash;
+}
+
 /* ---------------- */
 static int hash_comp_dir(const void *key1, const void *key2)
 {
@@ -1107,7 +1166,7 @@ const struct dir *k2 = key2;
 hash_t *
 dirhash(void)
 {
-    return hash_create(HASHCOUNT_T_MAX, hash_comp_dir, hash_fun_dir);
+    return hash_create(HASHCOUNT_T_MAX, hash_comp_dir, hash_fun2_dir);
 }
 
 /* ------------------ */
index 24bfb403e664df46e19c40706d530f910fdfa092..fd69d284ea61b3f82f8a43900a354139cf3e6f07 100644 (file)
@@ -14,7 +14,7 @@
  * into proprietary software; there is no requirement for such software to
  * contain a copyright notice related to this source.
  *
- * $Id: hash.c,v 1.3 2009-11-19 09:18:28 franklahm Exp $
+ * $Id: hash.c,v 1.4 2009-11-19 10:37:43 franklahm Exp $
  * $Name:  $
  */
 #define NDEBUG
@@ -26,7 +26,7 @@
 #include "hash.h"
 
 #ifdef KAZLIB_RCSID
-static const char rcsid[] = "$Id: hash.c,v 1.3 2009-11-19 09:18:28 franklahm Exp $";
+static const char rcsid[] = "$Id: hash.c,v 1.4 2009-11-19 10:37:43 franklahm Exp $";
 #endif
 
 #define INIT_BITS   6
@@ -58,6 +58,7 @@ static const char rcsid[] = "$Id: hash.c,v 1.3 2009-11-19 09:18:28 franklahm Exp
 static hnode_t *hnode_alloc(void *context);
 static void hnode_free(hnode_t *node, void *context);
 static hash_val_t hash_fun_default(const void *key);
+static hash_val_t hash_fun2(const void *key);
 static int hash_comp_default(const void *key1, const void *key2);
 
 int hash_val_t_bit;
@@ -837,6 +838,65 @@ static hash_val_t hash_fun_default(const void *key)
     return acc;
 }
 
+/* From http://www.azillionmonkeys.com/qed/hash.html */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__)    \
+    || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)    \
+                      +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+
+static hash_val_t hash_fun2(const void *key)
+{
+    int len, rem;
+    const unsigned char *data = key;
+    hash_val_t hash, tmp;
+
+    len = strlen((char *)data);
+
+    rem = len & 3;
+    len >>= 2;
+
+    /* Main loop */
+    for (;len > 0; len--) {
+        hash  += get16bits (data);
+        tmp    = (get16bits (data+2) << 11) ^ hash;
+        hash   = (hash << 16) ^ tmp;
+        data  += 2*sizeof (uint16_t);
+        hash  += hash >> 11;
+    }
+
+    /* Handle end cases */
+    switch (rem) {
+    case 3: hash += get16bits (data);
+        hash ^= hash << 16;
+        hash ^= data[sizeof (uint16_t)] << 18;
+        hash += hash >> 11;
+        break;
+    case 2: hash += get16bits (data);
+        hash ^= hash << 11;
+        hash += hash >> 17;
+        break;
+    case 1: hash += *data;
+        hash ^= hash << 10;
+        hash += hash >> 1;
+    }
+
+    /* Force "avalanching" of final 127 bits */
+    hash ^= hash << 3;
+    hash += hash >> 5;
+    hash ^= hash << 4;
+    hash += hash >> 17;
+    hash ^= hash << 25;
+    hash += hash >> 6;
+
+    return hash;
+}
+
 static int hash_comp_default(const void *key1, const void *key2)
 {
     return strcmp(key1, key2);
@@ -904,7 +964,7 @@ static void del_node(hnode_t *n, void *c)
 int main(void)
 {
     input_t in;
-    hash_t *h = hash_create(HASHCOUNT_T_MAX, 0, 0);
+    hash_t *h = hash_create(HASHCOUNT_T_MAX, 0, hash_fun2);
     hnode_t *hn;
     hscan_t hs;
     char *tok1, *tok2, *val;
index d02b4f2292d195df5df8ab473eb0023661a89c9f..2de1bf8065ac3f16fd273437d0f083b3f1b52da4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.h,v 1.1 2009-10-02 09:32:40 franklahm Exp $
+ * $Id: directory.h,v 1.2 2009-11-19 10:37:44 franklahm Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -59,6 +59,8 @@ struct dir {
 
     char       *d_m_name;            /* mac name */
     char        *d_u_name;            /* unix name */
+    size_t      d_u_name_len;         /* Length of unix name
+                                         MUST be initialized from d_u_name !!*/
     ucs2_t     *d_m_name_ucs2;       /* mac name as UCS2 */
 };
 
index 9195a4b5c880118d398a2f63a94e2dd7f324ad2d..14cddf669d671287020c6d24585106907789bbdd 100644 (file)
@@ -14,7 +14,7 @@
  * into proprietary software; there is no requirement for such software to
  * contain a copyright notice related to this source.
  *
- * $Id: hash.h,v 1.1 2009-10-02 09:32:40 franklahm Exp $
+ * $Id: hash.h,v 1.2 2009-11-19 10:37:44 franklahm Exp $
  * $Name:  $
  */
 
 #define ATALK_HASH_H
 
 #include <limits.h>
+#include <stdint.h>
 
 typedef unsigned long hashcount_t;
 #define HASHCOUNT_T_MAX ULONG_MAX
 
-typedef unsigned long hash_val_t;
-#define HASH_VAL_T_MAX ULONG_MAX
+typedef uint32_t hash_val_t;
+#define HASH_VAL_T_MAX UINT32_MAX
 
 extern int hash_val_t_bit;