This sort of directory hash is very easy to implement in Cyrus; a
better directory hash than the one included wasn't chosen since we
wanted something simple that worked well enough for us.

Unfortunately, due to extreme laziness on my part, the directory hash
function used is used in multiple places.  While any one place can be
replaced without the others, you probably will want to replace them
all.

In 2.0, look for

mailbox.c:
  mailbox_hash_mbox()
  mailbox_hash_quota()

mboxlist.c:
  mboxlist_hash_usersubs()

seen_db.c:
  getpath()

It's similar functions in 1.6.

If you'd like to consolidate things into one macro in a header file
that can be used from each of these, I'd gladly accept the patch and
we'd be able to change the hash function (at compile time) more
easily.

Larry

   From: [EMAIL PROTECTED]
   Date: Mon, 27 Nov 2000 19:33:03 -0600 (CST)

   I'm in the process of setting up a cyrus server for about 40,000 users.
   Of these, about 3/4 have userids that begin with the string `um',
   followed by an abbreviation of the person's last name, possibly
   followed by a 1 to 3 digit number.  The rest have userids derived
   from their last names and initials.  Now, cyrus 2.0.x uses the first
   character of the userid to select a hash directory in a variety of
   places in the file tree, in order to avoid degrading UFS performance
   by having a large number of files in a directory.  This clearly will
   not work well with my set of userids, and may be less than optimal
   at other sites as well.

   I did a bit of searching, and found a better directory hashing
   algorithm described by Nick Christenson on the qpopper mailing list.
   Like many good things, it originates from Knuth.  A test program
   that illustrates this algorithm is appended below.  Nick said that
   X and Y should be small primes.  I chose 3 and 5 for them.  I chose
   a value of 23 for PRIME to give a valid comparison to the existing
   cyrus hash scheme.  The algorithm is simple and seems reasonably
   fast.  Here is a comparison of the distribution of userid files for
   the two hash schemes:

   First Character:

           u    m       s       ...     i       x       q
           34652        869     767     ...     86      47      29

   New Algorithm:

           N    U       T       ...     I       G       F
           1997 1946    1944    ...     1845    1822    1787

   Even disregarding the `um' userids, the existing scheme yields quite
   an uneven distribution.  The new one, in contrast, has only about 10%
   difference between the highest and lowest categories.

   Below is the test program.  I did not experiment with altering the
   three prime numbers, although increasing PRIME would likely improve
   performance with a larger number of users by creating more hash
   directories.  I'd like to suggest that a scheme like this be added to
   cyrus 2.0.x.  In addition, if functions that need read-only access to
   the files below the hash directories could fail silently if the hash
   directory did not exist, and if functions that create the files below
   the hash directories could silently create the hash directories, there
   would be no need to pre-allocate all of them.


   ================================================================
   /* dirhash: directory hash scheme */
   /* Suggested by Nick Christenson <[EMAIL PROTECTED]> */

   #include <stdio.h>

   enum {
       X = 3,
       Y = 5,
       PRIME = 23
   }

   dirhash(char *name) {
       unsigned char *pt;
       unsigned int n;

       n = 0;
       pt = (unsigned char *)name;
       while (*pt) {
           n = ((n << X) ^ (n >> Y)) ^ *pt;
           ++pt;
       }
       return n % PRIME;
   }

   main(int argc, char **argv) {
       char buf[255];

       if (argc > 1) {
           printf("%c/%s\n", dirhash(argv[1]) + '@', argv[1]);
       }
       else {
           while (gets(buf)) {
               printf("%c/%s\n", dirhash(buf) + '@', buf);
           }
       }
       return 0;
   }

   /**/
   ================================================================



   -- 
   -Gary Mills-    -Unix Support-    -U of M Academic Computing and Networking-

Reply via email to