From e7fc5851828477c7158a1db41a355b97077aecb4 Mon Sep 17 00:00:00 2001 From: Paul Park Date: Fri, 26 May 1995 22:42:39 +0000 Subject: [PATCH] Check in Berkeley Database code version 1.85 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5895 dc483132-0cff-0310-8789-dd5450dbe970 --- src/util/berk_db/.Sanitize | 44 + src/util/berk_db/.cvsignore | 1 + src/util/berk_db/ChangeLog | 13 + src/util/berk_db/Makefile.in | 58 ++ src/util/berk_db/PORT/.Sanitize | 35 + src/util/berk_db/PORT/README | 131 +++ src/util/berk_db/PORT/clib/.Sanitize | 35 + src/util/berk_db/PORT/clib/memmove.c | 139 +++ src/util/berk_db/PORT/clib/mktemp.c | 132 +++ src/util/berk_db/PORT/clib/snprintf.c | 54 + src/util/berk_db/PORT/clib/strerror.c | 67 ++ src/util/berk_db/PORT/include/.Sanitize | 35 + src/util/berk_db/PORT/include/cdefs.h | 122 +++ src/util/berk_db/PORT/include/compat.h | 231 +++++ src/util/berk_db/PORT/include/ndbm.h | 77 ++ src/util/berk_db/PORT/include/queue.h | 245 +++++ src/util/berk_db/PORT/krb5/.Sanitize | 33 + src/util/berk_db/PORT/krb5/include/.Sanitize | 32 + src/util/berk_db/PORT/krb5/include/compat.h | 258 +++++ src/util/berk_db/PORT/krb5/sys/.Sanitize | 32 + src/util/berk_db/PORT/krb5/sys/cdefs.h | 122 +++ src/util/berk_db/README | 40 + src/util/berk_db/README.krb5 | 17 + src/util/berk_db/changelog | 103 ++ src/util/berk_db/configure.in | 15 + src/util/berk_db/hash/.Sanitize | 49 + src/util/berk_db/hash/.cvsignore | 1 + src/util/berk_db/hash/Makefile.in | 46 + src/util/berk_db/hash/README | 72 ++ src/util/berk_db/hash/configure.in | 16 + src/util/berk_db/hash/extern.h | 65 ++ src/util/berk_db/hash/hash.c | 994 +++++++++++++++++++ src/util/berk_db/hash/hash.h | 293 ++++++ src/util/berk_db/hash/hash_bigkey.c | 667 +++++++++++++ src/util/berk_db/hash/hash_buf.c | 355 +++++++ src/util/berk_db/hash/hash_func.c | 212 ++++ src/util/berk_db/hash/hash_log2.c | 54 + src/util/berk_db/hash/hash_page.c | 944 ++++++++++++++++++ src/util/berk_db/hash/hsearch.c | 107 ++ src/util/berk_db/hash/krb5_ndbm.c | 245 +++++ src/util/berk_db/hash/ndbm.c | 202 ++++ src/util/berk_db/hash/page.h | 92 ++ src/util/berk_db/hash/search.h | 51 + src/util/berk_db/include/.Sanitize | 33 + src/util/berk_db/include/db.h | 239 +++++ src/util/berk_db/include/mpool.h | 99 ++ src/util/berk_db/man/.Sanitize | 32 + src/util/berk_db/man/hash.3 | 159 +++ src/util/berk_db/test/.Sanitize | 39 + src/util/berk_db/test/.cvsignore | 1 + src/util/berk_db/test/Makefile.in | 30 + src/util/berk_db/test/README | 74 ++ src/util/berk_db/test/configure.in | 6 + src/util/berk_db/test/dbtest.c | 759 ++++++++++++++ src/util/berk_db/test/hash.tests/.Sanitize | 40 + src/util/berk_db/test/hash.tests/driver2.c | 114 +++ src/util/berk_db/test/hash.tests/makedb.sh | 13 + src/util/berk_db/test/hash.tests/tcreat3.c | 105 ++ src/util/berk_db/test/hash.tests/tdel.c | 122 +++ src/util/berk_db/test/hash.tests/testit | 147 +++ src/util/berk_db/test/hash.tests/thash4.c | 132 +++ src/util/berk_db/test/hash.tests/tread2.c | 105 ++ src/util/berk_db/test/hash.tests/tseq.c | 88 ++ src/util/berk_db/test/hash.tests/tverify.c | 107 ++ src/util/berk_db/test/run.test | 705 +++++++++++++ 65 files changed, 9685 insertions(+) create mode 100644 src/util/berk_db/.Sanitize create mode 100644 src/util/berk_db/.cvsignore create mode 100644 src/util/berk_db/ChangeLog create mode 100644 src/util/berk_db/Makefile.in create mode 100644 src/util/berk_db/PORT/.Sanitize create mode 100644 src/util/berk_db/PORT/README create mode 100644 src/util/berk_db/PORT/clib/.Sanitize create mode 100644 src/util/berk_db/PORT/clib/memmove.c create mode 100644 src/util/berk_db/PORT/clib/mktemp.c create mode 100644 src/util/berk_db/PORT/clib/snprintf.c create mode 100644 src/util/berk_db/PORT/clib/strerror.c create mode 100644 src/util/berk_db/PORT/include/.Sanitize create mode 100644 src/util/berk_db/PORT/include/cdefs.h create mode 100644 src/util/berk_db/PORT/include/compat.h create mode 100644 src/util/berk_db/PORT/include/ndbm.h create mode 100644 src/util/berk_db/PORT/include/queue.h create mode 100644 src/util/berk_db/PORT/krb5/.Sanitize create mode 100644 src/util/berk_db/PORT/krb5/include/.Sanitize create mode 100644 src/util/berk_db/PORT/krb5/include/compat.h create mode 100644 src/util/berk_db/PORT/krb5/sys/.Sanitize create mode 100644 src/util/berk_db/PORT/krb5/sys/cdefs.h create mode 100644 src/util/berk_db/README create mode 100644 src/util/berk_db/README.krb5 create mode 100644 src/util/berk_db/changelog create mode 100644 src/util/berk_db/configure.in create mode 100644 src/util/berk_db/hash/.Sanitize create mode 100644 src/util/berk_db/hash/.cvsignore create mode 100644 src/util/berk_db/hash/Makefile.in create mode 100644 src/util/berk_db/hash/README create mode 100644 src/util/berk_db/hash/configure.in create mode 100644 src/util/berk_db/hash/extern.h create mode 100644 src/util/berk_db/hash/hash.c create mode 100644 src/util/berk_db/hash/hash.h create mode 100644 src/util/berk_db/hash/hash_bigkey.c create mode 100644 src/util/berk_db/hash/hash_buf.c create mode 100644 src/util/berk_db/hash/hash_func.c create mode 100644 src/util/berk_db/hash/hash_log2.c create mode 100644 src/util/berk_db/hash/hash_page.c create mode 100644 src/util/berk_db/hash/hsearch.c create mode 100644 src/util/berk_db/hash/krb5_ndbm.c create mode 100644 src/util/berk_db/hash/ndbm.c create mode 100644 src/util/berk_db/hash/page.h create mode 100644 src/util/berk_db/hash/search.h create mode 100644 src/util/berk_db/include/.Sanitize create mode 100644 src/util/berk_db/include/db.h create mode 100644 src/util/berk_db/include/mpool.h create mode 100644 src/util/berk_db/man/.Sanitize create mode 100644 src/util/berk_db/man/hash.3 create mode 100644 src/util/berk_db/test/.Sanitize create mode 100644 src/util/berk_db/test/.cvsignore create mode 100644 src/util/berk_db/test/Makefile.in create mode 100644 src/util/berk_db/test/README create mode 100644 src/util/berk_db/test/configure.in create mode 100644 src/util/berk_db/test/dbtest.c create mode 100644 src/util/berk_db/test/hash.tests/.Sanitize create mode 100644 src/util/berk_db/test/hash.tests/driver2.c create mode 100644 src/util/berk_db/test/hash.tests/makedb.sh create mode 100644 src/util/berk_db/test/hash.tests/tcreat3.c create mode 100644 src/util/berk_db/test/hash.tests/tdel.c create mode 100644 src/util/berk_db/test/hash.tests/testit create mode 100644 src/util/berk_db/test/hash.tests/thash4.c create mode 100644 src/util/berk_db/test/hash.tests/tread2.c create mode 100644 src/util/berk_db/test/hash.tests/tseq.c create mode 100644 src/util/berk_db/test/hash.tests/tverify.c create mode 100644 src/util/berk_db/test/run.test diff --git a/src/util/berk_db/.Sanitize b/src/util/berk_db/.Sanitize new file mode 100644 index 000000000..0f8b39649 --- /dev/null +++ b/src/util/berk_db/.Sanitize @@ -0,0 +1,44 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +.cvsignore +ChangeLog +Makefile.in +PORT +README +README.krb5 +changelog +configure +cofigure.in +hash +include +man +test + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/.cvsignore b/src/util/berk_db/.cvsignore new file mode 100644 index 000000000..e8c05a6b1 --- /dev/null +++ b/src/util/berk_db/.cvsignore @@ -0,0 +1 @@ +configure diff --git a/src/util/berk_db/ChangeLog b/src/util/berk_db/ChangeLog new file mode 100644 index 000000000..be426f5d3 --- /dev/null +++ b/src/util/berk_db/ChangeLog @@ -0,0 +1,13 @@ + +Fri May 26 16:07:52 EDT 1995 Paul Park (pjpark@mit.edu) + Bring in version 1.85 of the Berkeley database code. We only + use the hashed database, so that's all that's here. There are + slight modifications to the code to fix one bug and to tailor + it for usage with Kerberos. + + +Fri May 26 16:06:46 EDT 1995 Paul Park (pjpark@mit.edu) + Bring in version 1.85 of the Berkeley database code. We only + use the hashed database, so that's all that's here. There are + slight modifications which were done to the code. + diff --git a/src/util/berk_db/Makefile.in b/src/util/berk_db/Makefile.in new file mode 100644 index 000000000..3d743a00f --- /dev/null +++ b/src/util/berk_db/Makefile.in @@ -0,0 +1,58 @@ +##DOSBUILDTOP = ..\.. +##DOS!include $(BUILDTOP)\config\windows.in + +TST=if test -n "`cat DONE`" ; then + +LIB_SUBDIRS= hash + +LIBUPDATE= $(BUILDTOP)/util/libupdate + +all:: all-$(WHAT) + +all-unix:: + +all-windows:: + +libdb_ranlib: libdb.a + $(RANLIB) libdb.a + touch $@ + +libdb.a: hash/DONE + if test -f $@ ; then \ + for i in $(LIB_SUBDIRS) ; \ + do \ + $(LIBUPDATE) $@ $$i/DONE $$i ; \ + done ; \ + else \ + for i in $(LIB_SUBDIRS) ; \ + do \ + $(LIBUPDATE) --force $@ $$i/DONE $$i ; \ + done ; \ + fi + touch libdb.stamp + +install:: libdb_ranlib + $(INSTALL_DATA) libdb.a $(DESTDIR)$(KRB5_LIBDIR)/libdb.a + $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libdb.a + +clean:: clean-$(WHAT) + +clean-unix:: + $(RM) libdb.$(LIBEXT) libdb_ranlib libdb.stamp + +clean-windows:: + $(RM) db.lib db.bak + +all-windows:: + cd BERK_DB + @echo Making in berk_db + -$(MAKE) -$(MFLAGS) LIBCMD=$(LIBCMD) + cd .. + +clean-windows:: + cd BERK_DB + @echo Making clean in berk_db + -$(MAKE) -$(MFLAGS) clean + cd .. + @echo Making clean locally + diff --git a/src/util/berk_db/PORT/.Sanitize b/src/util/berk_db/PORT/.Sanitize new file mode 100644 index 000000000..213ab70ce --- /dev/null +++ b/src/util/berk_db/PORT/.Sanitize @@ -0,0 +1,35 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +README +clib +include +krb5 + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/PORT/README b/src/util/berk_db/PORT/README new file mode 100644 index 000000000..6d4728101 --- /dev/null +++ b/src/util/berk_db/PORT/README @@ -0,0 +1,131 @@ +# @(#)README 8.6 (Berkeley) 6/20/94 + +This is the area for building the libdb library. There are a number +of porting directories, for various architecture/OS combinations. Pick +the one that's closest to yours and try "make". For the rest of this +file, I'll use "MACH" as a fake architecture/OS name. + +To PORT to a new system, create the following subdirectories and +symbolic links. + + mkdir MACH (for example: mkdir sunos.4.0) + cd MACH + cp ../Makefile . + chmod 664 Makefile + ln -s ../clib . + mkdir include + ln -s include sys + cd include + ln -s ../../include/*.h . + rm compat.h + cp ../../include/compat.h . + chmod 664 compat.h + cd .. + +The basic idea is that you now have a local area that you can modify. +In particular, you have local copies of the Makefile and the include +file compat.h. Read through the Makefile and compat.h and make whatever +changes are appropriate to your system. If there's an architecture +that's close to yours, you probably should diff the Makefile and +compat.h in that tree against the standard ones and see what changes +were necessary, as they're probably necessary for you as well. Then, +enter "make" and see what happens! + +There are several subroutines that are found in POSIX 1003.2, ANSI +C, or 4.4BSD that you may not have. Once you get libdb.a to compile, +go through the list of undefined routines and add entries to the MISC +line in the Makefile as necessary. + +If you have to add some functions that are missing (and which aren't +in the PORT/clib directory), please don't add them in the PORT/clib +directory. Add them in a MACH/local directory, and add lines of the +form: + + function.o: local/function.o + ${CL} -Ilocal local/function.o + +to your local Makefile. + +Hopefully, over time, we'll develop a set of system directories that +are known to work. If you send me the changes that were necessary to +make your system work, this will happen much more quickly. + +In some of the system directories, you'll see a file named OTHER_PATCHES. +This is a set of patches which you'll have to make from the top-level db +directory to get libdb.a to run on this system: + + cd .. + patch < PORT/MACH/OTHER_PATCHES + +If patch prompts you for the name of the file to modify (some versions +of patch don't figure it out on their own) use the file name which patch +displays. + +Some knobs you may have to turn: + +In include/db.h: + Before attempting to build libdb, you should look through the + db.h file, and adjust it as necessary for your system. The + only adjustments that you should need to make are for the + fixed sized typedef's at the top of the file. Make sure they're + right for your system. + +In include/compat.h: + Before attempting to build libdb, you should look through the + compat.h file, and adjust it as necessary for your system. + It's possible to use the #ifndef construct to figure out if a + #ifdef has been set, but C provides no similar method to figure + out if a typedef has been done. Your compile errors should + give you a good indication of which ones you need. + +You may see warning messages about illegal pointer combinations. You may +also see lots of warning messages about #define's being redefined. These +can mostly be ignored. I usually ignore warning messages until something +doesn't work. Some systems produce thousands of lines of useless warnings, +bless their little hearts. + +The other parts of the PORT directory are as follows: + + The directory PORT/clib is a set of functions that the 4.4BSD + C library had and which your system may not have. They are + added to the MISC line of the Makefile if they aren't defined + when you try and load libdb.a. + + The directory PORT/include is header files that the 4.4BSD + system had which your system may not have. There is also + one really important extra one, named compat.h, which is a + set of compatibility work-arounds that you'll almost certainly + have to copy and modify for a new system. + + The symbolic link PORT/sys points to the PORT/include directory + so that includes of the form work. + +Some of the more common portability problems: + + If you don't have: + + memmove(3): add memmove.o + mkstemp(3): add mktemp.o + + ... to the MISC line in the Makefile. + + If you don't have snprintf/vsnprintf(3), add snprintf.o to the + MISC line in the Makefile. This workaround depends on your + system having vsprintf(3) -- if you don't, there's no workaround + other than changing the source code to not use the snprintf calls. + If you have to make that change, check to see if your vsprintf + returns a length or a char *; if it's the latter, make sure you + set VSPRINTF_CHARSTAR in the MACH/include/compat.h file. + +Installing the DB library: + + The Makefile builds a C library named libdb.a. This file needs + to be installed in a place where the loader will automatically + look for it (or, if you're building it for a single project, + wherever that project's Makefile loads it from). + + In addition, the header file PORT/include/db.h must be copied to + a directory (often /usr/include/) where programs that use the + db package can include it in their source. (If you intend to use + the ndbm interface to libdb, you'll need to copy the header file + PORT/include/ndbm.h as well.) diff --git a/src/util/berk_db/PORT/clib/.Sanitize b/src/util/berk_db/PORT/clib/.Sanitize new file mode 100644 index 000000000..b9d7ef519 --- /dev/null +++ b/src/util/berk_db/PORT/clib/.Sanitize @@ -0,0 +1,35 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +memmove.c +mktemp.c +snprintf.c +strerror.c + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/PORT/clib/memmove.c b/src/util/berk_db/PORT/clib/memmove.c new file mode 100644 index 000000000..f90b09c9b --- /dev/null +++ b/src/util/berk_db/PORT/clib/memmove.c @@ -0,0 +1,139 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +/* + * sizeof(word) MUST BE A POWER OF TWO + * SO THAT wmask BELOW IS ALL ONES + */ +typedef int word; /* "word" used for optimal copy speed */ + +#define wsize sizeof(word) +#define wmask (wsize - 1) + +/* + * Copy a block of memory, handling overlap. + * This is the routine that actually implements + * (the portable versions of) bcopy, memcpy, and memmove. + */ +#ifdef MEMCOPY +void * +memcpy(dst0, src0, length) +#else +#ifdef MEMMOVE +void * +memmove(dst0, src0, length) +#else +void +bcopy(src0, dst0, length) +#endif +#endif + void *dst0; + const void *src0; + register size_t length; +{ + register char *dst = dst0; + register const char *src = src0; + register size_t t; + + if (length == 0 || dst == src) /* nothing to do */ + goto done; + + /* + * Macros: loop-t-times; and loop-t-times, t>0 + */ +#define TLOOP(s) if (t) TLOOP1(s) +#define TLOOP1(s) do { s; } while (--t) + + if ((unsigned long)dst < (unsigned long)src) { + /* + * Copy forward. + */ + t = (int)src; /* only need low bits */ + if ((t | (int)dst) & wmask) { + /* + * Try to align operands. This cannot be done + * unless the low bits match. + */ + if ((t ^ (int)dst) & wmask || length < wsize) + t = length; + else + t = wsize - (t & wmask); + length -= t; + TLOOP1(*dst++ = *src++); + } + /* + * Copy whole words, then mop up any trailing bytes. + */ + t = length / wsize; + TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); + t = length & wmask; + TLOOP(*dst++ = *src++); + } else { + /* + * Copy backwards. Otherwise essentially the same. + * Alignment works as before, except that it takes + * (t&wmask) bytes to align, not wsize-(t&wmask). + */ + src += length; + dst += length; + t = (int)src; + if ((t | (int)dst) & wmask) { + if ((t ^ (int)dst) & wmask || length <= wsize) + t = length; + else + t &= wmask; + length -= t; + TLOOP1(*--dst = *--src); + } + t = length / wsize; + TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src); + t = length & wmask; + TLOOP(*--dst = *--src); + } +done: +#if defined(MEMCOPY) || defined(MEMMOVE) + return (dst0); +#else + return; +#endif +} diff --git a/src/util/berk_db/PORT/clib/mktemp.c b/src/util/berk_db/PORT/clib/mktemp.c new file mode 100644 index 000000000..3cdd5723a --- /dev/null +++ b/src/util/berk_db/PORT/clib/mktemp.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include + +static int _gettemp(); + +#if !HAVE_MKSTEMP +mkstemp(path) + char *path; +{ + int fd; + + return (_gettemp(path, &fd) ? fd : -1); +} +#endif /* !HAVE_MKSTEMP */ + +#if !HAVE_MKTEMP +char * +mktemp(path) + char *path; +{ + return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); +} +#endif /* !HAVE_MKTEMP */ + +#if !HAVE_MKTEMP || !HAVE_MKSTEMP +static +_gettemp(path, doopen) + char *path; + register int *doopen; +{ + extern int errno; + register char *start, *trv; + struct stat sbuf; + u_int pid; + + pid = getpid(); + for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + if (stat(path, &sbuf)) + return(0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return(0); + } + *trv = '/'; + break; + } + } + + for (;;) { + if (doopen) { + if ((*doopen = + open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) + return(1); + if (errno != EEXIST) + return(0); + } + else if (stat(path, &sbuf)) + return(errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return(0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit(*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +} +#endif /* !HAVE_MKTEMP || !HAVE_MKSTEMP */ diff --git a/src/util/berk_db/PORT/clib/snprintf.c b/src/util/berk_db/PORT/clib/snprintf.c new file mode 100644 index 000000000..2863fa28d --- /dev/null +++ b/src/util/berk_db/PORT/clib/snprintf.c @@ -0,0 +1,54 @@ +#include +#include + +#include + +#ifdef __STDC__ +#include +#else +#include +#endif + +int +#ifdef __STDC__ +snprintf(char *str, size_t n, const char *fmt, ...) +#else +snprintf(str, n, fmt, va_alist) + char *str; + size_t n; + const char *fmt; + va_dcl +#endif +{ + va_list ap; + char *rp; + int rval; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif +#ifdef VSPRINTF_CHARSTAR + rp = vsprintf(str, fmt, ap); + va_end(ap); + return (strlen(rp)); +#else + rval = vsprintf(str, fmt, ap); + va_end(ap); + return (rval); +#endif +} + +int +vsnprintf(str, n, fmt, ap) + char *str; + size_t n; + const char *fmt; + va_list ap; +{ +#ifdef VSPRINTF_CHARSTAR + return (strlen(vsprintf(str, fmt, ap))); +#else + return (vsprintf(str, fmt, ap)); +#endif +} diff --git a/src/util/berk_db/PORT/clib/strerror.c b/src/util/berk_db/PORT/clib/strerror.c new file mode 100644 index 000000000..53f374bdf --- /dev/null +++ b/src/util/berk_db/PORT/clib/strerror.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include + +char * +strerror(num) + int num; +{ + extern int sys_nerr; + extern char *sys_errlist[]; +#define UPREFIX "Unknown error: " + static char ebuf[40] = UPREFIX; /* 64-bit number + slop */ + register unsigned int errnum; + register char *p, *t; + char tmp[40]; + + errnum = num; /* convert to unsigned */ + if (errnum < sys_nerr) + return(sys_errlist[errnum]); + + /* Do this by hand, so we don't include stdio(3). */ + t = tmp; + do { + *t++ = "0123456789"[errnum % 10]; + } while (errnum /= 10); + for (p = ebuf + sizeof(UPREFIX) - 1;;) { + *p++ = *--t; + if (t <= tmp) + break; + } + return(ebuf); +} diff --git a/src/util/berk_db/PORT/include/.Sanitize b/src/util/berk_db/PORT/include/.Sanitize new file mode 100644 index 000000000..77efe8cd7 --- /dev/null +++ b/src/util/berk_db/PORT/include/.Sanitize @@ -0,0 +1,35 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +cdefs.h +compat.h +ndbm.h +queue.h + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/PORT/include/cdefs.h b/src/util/berk_db/PORT/include/cdefs.h new file mode 100644 index 000000000..c104b9e96 --- /dev/null +++ b/src/util/berk_db/PORT/include/cdefs.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cdefs.h 8.7 (Berkeley) 1/21/94 + */ + +#ifndef _CDEFS_H_ +#define _CDEFS_H_ + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS }; +#else +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky -- make sure you don't put spaces + * in between its arguments. __CONCAT can also concatenate double-quoted + * strings produced by the __STRING macro, but this only works with ANSI C. + */ +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) +#define __inline inline /* convert to C++ keyword */ +#else +#ifndef __GNUC__ +#define __inline /* delete GCC keyword */ +#endif /* !__GNUC__ */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#ifndef __GNUC__ +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * When using a compiler other than gcc, programs using the ANSI C keywords + * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. + * When using "gcc -traditional", we assume that this is the intent; if + * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. + */ +#ifndef NO_ANSI_KEYWORDS +#define const /* delete ANSI C keywords */ +#define inline +#define signed +#define volatile +#endif +#endif /* !__GNUC__ */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * GCC1 and some versions of GCC2 declare dead (non-returning) and + * pure (no side effects) functions using "volatile" and "const"; + * unfortunately, these then cause warnings under "-ansi -pedantic". + * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of + * these work for GNU C++ (modulo a slight glitch in the C++ grammar + * in the distribution version of 2.5.5). + */ +#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5 +#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#define __dead __volatile +#define __pure __const +#endif +#endif + +/* Delete pseudo-keywords wherever they are not available or needed. */ +#ifndef __dead +#define __dead +#define __pure +#endif + +#endif /* !_CDEFS_H_ */ diff --git a/src/util/berk_db/PORT/include/compat.h b/src/util/berk_db/PORT/include/compat.h new file mode 100644 index 000000000..2bd360af5 --- /dev/null +++ b/src/util/berk_db/PORT/include/compat.h @@ -0,0 +1,231 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)compat.h 8.13 (Berkeley) 2/21/94 + */ + +#ifndef _COMPAT_H_ +#define _COMPAT_H_ + +#include + +/* + * If your system doesn't typedef u_long, u_short, or u_char, change + * the 0 to a 1. + */ +#if 0 +typedef unsigned char u_char; /* 4.[34]BSD names. */ +typedef unsigned int u_int; +typedef unsigned long u_long; +typedef unsigned short u_short; +#endif + +/* If your system doesn't typedef size_t, change the 0 to a 1. */ +#if 0 +typedef unsigned int size_t; /* POSIX, 4.[34]BSD names. */ +#endif + +/* If your system doesn't typedef ssize_t, change the 0 to a 1. */ +#if 0 +typedef int ssize_t; /* POSIX names. */ +#endif + +/* + * If your system doesn't have the POSIX type for a signal mask, + * change the 0 to a 1. + */ +#if 0 /* POSIX 1003.1 signal mask type. */ +typedef unsigned int sigset_t; +#endif + +/* + * If your system's vsprintf returns a char *, not an int, + * change the 0 to a 1. + */ +#if 0 +#define VSPRINTF_CHARSTAR +#endif + +/* + * If you don't have POSIX 1003.1 signals, the signal code surrounding the + * temporary file creation is intended to block all of the possible signals + * long enough to create the file and unlink it. All of this stuff is + * intended to use old-style BSD calls to fake POSIX 1003.1 calls. + */ +#ifdef NO_POSIX_SIGNALS +#define sigemptyset(set) (*(set) = 0) +#define sigfillset(set) (*(set) = ~(sigset_t)0, 0) +#define sigaddset(set,signo) (*(set) |= sigmask(signo), 0) +#define sigdelset(set,signo) (*(set) &= ~sigmask(signo), 0) +#define sigismember(set,signo) ((*(set) & sigmask(signo)) != 0) + +#define SIG_BLOCK 1 +#define SIG_UNBLOCK 2 +#define SIG_SETMASK 3 + +static int __sigtemp; /* For the use of sigprocmask */ + +/* Repeated test of oset != NULL is to avoid "*0". */ +#define sigprocmask(how, set, oset) \ + ((__sigtemp = \ + (((how) == SIG_BLOCK) ? \ + sigblock(0) | *(set) : \ + (((how) == SIG_UNBLOCK) ? \ + sigblock(0) & ~(*(set)) : \ + ((how) == SIG_SETMASK ? \ + *(set) : sigblock(0))))), \ + ((oset) ? (*(oset ? oset : set) = sigsetmask(__sigtemp)) : \ + sigsetmask(__sigtemp)), 0) +#endif + +/* + * If your system doesn't have an include file with the appropriate + * byte order set, make sure you specify the correct one. + */ +#ifndef BYTE_ORDER +#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define BYTE_ORDER BIG_ENDIAN /* Set for your system. */ +#endif + +#if defined(SYSV) || defined(SYSTEM5) +#define index(a, b) strchr(a, b) +#define rindex(a, b) strrchr(a, b) +#define bzero(a, b) memset(a, 0, b) +#define bcmp(a, b, n) memcmp(a, b, n) +#define bcopy(a, b, n) memmove(b, a, n) +#endif + +#if defined(BSD) || defined(BSD4_3) +#define strchr(a, b) index(a, b) +#define strrchr(a, b) rindex(a, b) +#define memcmp(a, b, n) bcmp(a, b, n) +#define memmove(a, b, n) bcopy(b, a, n) +#endif + +/* + * 32-bit machine. The db routines are theoretically independent of + * the size of u_shorts and u_longs, but I don't know that anyone has + * ever actually tried it. At a minimum, change the following #define's + * if you are trying to compile on a different type of system. + */ +#ifndef USHRT_MAX +#define USHRT_MAX 0xFFFF +#define ULONG_MAX 0xFFFFFFFF +#endif + +#ifndef O_ACCMODE /* POSIX 1003.1 access mode mask. */ +#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif + +#ifndef _POSIX2_RE_DUP_MAX /* POSIX 1003.2 RE limit. */ +#define _POSIX2_RE_DUP_MAX 255 +#endif + +/* + * If you can't provide lock values in the open(2) call. Note, this + * allows races to happen. + */ +#ifndef O_EXLOCK /* 4.4BSD extension. */ +#define O_EXLOCK 0 +#endif + +#ifndef O_SHLOCK /* 4.4BSD extension. */ +#define O_SHLOCK 0 +#endif + +#ifndef EFTYPE +#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */ +#endif + +#ifndef WCOREDUMP /* 4.4BSD extension */ +#define WCOREDUMP(a) 0 +#endif + +#ifndef STDERR_FILENO +#define STDIN_FILENO 0 /* ANSI C #defines */ +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#endif + +#ifndef SEEK_END +#define SEEK_SET 0 /* POSIX 1003.1 seek values */ +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + +#ifndef _POSIX_VDISABLE /* POSIX 1003.1 disabling char. */ +#define _POSIX_VDISABLE 0 /* Some systems used 0. */ +#endif + +#ifndef TCSASOFT /* 4.4BSD extension. */ +#define TCSASOFT 0 +#endif + +#ifndef _POSIX2_RE_DUP_MAX /* POSIX 1003.2 values. */ +#define _POSIX2_RE_DUP_MAX 255 +#endif + +#ifndef NULL /* ANSI C #defines NULL everywhere. */ +#define NULL 0 +#endif + +#ifndef MAX /* Usually found in . */ +#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a)) +#endif +#ifndef MIN /* Usually found in . */ +#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) +#endif + +/* Default file permissions. */ +#ifndef DEFFILEMODE /* 4.4BSD extension. */ +#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) +#endif + +#ifndef S_ISDIR /* POSIX 1003.1 file type tests. */ +#define S_ISDIR(m) ((m & 0170000) == 0040000) /* directory */ +#define S_ISCHR(m) ((m & 0170000) == 0020000) /* char special */ +#define S_ISBLK(m) ((m & 0170000) == 0060000) /* block special */ +#define S_ISREG(m) ((m & 0170000) == 0100000) /* regular file */ +#define S_ISFIFO(m) ((m & 0170000) == 0010000) /* fifo */ +#endif +#ifndef S_ISLNK /* BSD POSIX 1003.1 extensions */ +#define S_ISLNK(m) ((m & 0170000) == 0120000) /* symbolic link */ +#define S_ISSOCK(m) ((m & 0170000) == 0140000) /* socket */ +#endif + +/* The type of a va_list. */ +#ifndef _BSD_VA_LIST_ /* 4.4BSD #define. */ +#define _BSD_VA_LIST_ char * +#endif + +#endif /* !_COMPAT_H_ */ diff --git a/src/util/berk_db/PORT/include/ndbm.h b/src/util/berk_db/PORT/include/ndbm.h new file mode 100644 index 000000000..a545bca13 --- /dev/null +++ b/src/util/berk_db/PORT/include/ndbm.h @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ndbm.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _NDBM_H_ +#define _NDBM_H_ + +#include + +/* Map dbm interface onto db(3). */ +#define DBM_RDONLY O_RDONLY + +/* Flags to dbm_store(). */ +#define DBM_INSERT 0 +#define DBM_REPLACE 1 + +/* + * The db(3) support for ndbm(3) always appends this suffix to the + * file name to avoid overwriting the user's original database. + */ +#define DBM_SUFFIX ".db" + +typedef struct { + char *dptr; + int dsize; +} datum; + +typedef DB DBM; +#define dbm_pagfno(a) DBM_PAGFNO_NOT_AVAILABLE + +__BEGIN_DECLS +void dbm_close __P((DBM *)); +int dbm_delete __P((DBM *, datum)); +datum dbm_fetch __P((DBM *, datum)); +datum dbm_firstkey __P((DBM *)); +long dbm_forder __P((DBM *, datum)); +datum dbm_nextkey __P((DBM *)); +DBM *dbm_open __P((const char *, int, int)); +int dbm_store __P((DBM *, datum, datum, int)); +int dbm_dirfno __P((DBM *)); +__END_DECLS + +#endif /* !_NDBM_H_ */ diff --git a/src/util/berk_db/PORT/include/queue.h b/src/util/berk_db/PORT/include/queue.h new file mode 100644 index 000000000..40d32ccb6 --- /dev/null +++ b/src/util/berk_db/PORT/include/queue.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.3 (Berkeley) 12/13/93 + */ + +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +/* + * This file defines three types of data structures: lists, tail queues, + * and circular queues. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list after + * an existing element or at the head of the list. A list may only be + * traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list after + * an existing element, at the head of the list, or at the end of the + * list. A tail queue may only be traversed in the forward direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ +#define LIST_INIT(head) { \ + (head)->lh_first = NULL; \ +} + +#define LIST_INSERT_AFTER(listelm, elm, field) { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} + +#define LIST_INSERT_HEAD(head, elm, field) { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} + +#define LIST_REMOVE(elm, field) { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} + +#define TAILQ_INSERT_HEAD(head, elm, field) { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} + +#define TAILQ_INSERT_TAIL(head, elm, field) { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} + +#define TAILQ_REMOVE(head, elm, field) { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) { \ + (head)->cqh_first = (void *)(head); \ + (head)->cqh_last = (void *)(head); \ +} + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = (void *)(head); \ + if ((head)->cqh_last == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) { \ + (elm)->field.cqe_next = (void *)(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} + +#define CIRCLEQ_REMOVE(head, elm, field) { \ + if ((elm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} +#endif /* !_QUEUE_H_ */ diff --git a/src/util/berk_db/PORT/krb5/.Sanitize b/src/util/berk_db/PORT/krb5/.Sanitize new file mode 100644 index 000000000..0dbbe7d81 --- /dev/null +++ b/src/util/berk_db/PORT/krb5/.Sanitize @@ -0,0 +1,33 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +include +sys + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/PORT/krb5/include/.Sanitize b/src/util/berk_db/PORT/krb5/include/.Sanitize new file mode 100644 index 000000000..2f4e847ff --- /dev/null +++ b/src/util/berk_db/PORT/krb5/include/.Sanitize @@ -0,0 +1,32 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +compat.h + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/PORT/krb5/include/compat.h b/src/util/berk_db/PORT/krb5/include/compat.h new file mode 100644 index 000000000..fde6c38ca --- /dev/null +++ b/src/util/berk_db/PORT/krb5/include/compat.h @@ -0,0 +1,258 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)compat.h 8.13 (Berkeley) 2/21/94 + */ + +#ifndef _COMPAT_H_ +#define _COMPAT_H_ + +#include + +/* + * If your system doesn't typedef u_long, u_short, or u_char, change + * the 0 to a 1. + */ +#if 0 +typedef unsigned char u_char; /* 4.[34]BSD names. */ +typedef unsigned int u_int; +typedef unsigned long u_long; +typedef unsigned short u_short; +#endif + +/* If your system doesn't typedef size_t, change the 0 to a 1. */ +#if 0 +typedef unsigned int size_t; /* POSIX, 4.[34]BSD names. */ +#endif + +/* If your system doesn't typedef ssize_t, change the 0 to a 1. */ +#if 0 +typedef int ssize_t; /* POSIX names. */ +#endif + +/* + * If your system doesn't have the POSIX type for a signal mask, + * change the 0 to a 1. + */ +#if !POSIX_SIGNALS /* POSIX 1003.1 signal mask type. */ +typedef unsigned int sigset_t; +#endif + +/* + * If your system's vsprintf returns a char *, not an int, + * change the 0 to a 1. + */ +#if 0 +#define VSPRINTF_CHARSTAR +#endif + +/* + * If you don't have POSIX 1003.1 signals, the signal code surrounding the + * temporary file creation is intended to block all of the possible signals + * long enough to create the file and unlink it. All of this stuff is + * intended to use old-style BSD calls to fake POSIX 1003.1 calls. + */ +#if !POSIX_SIGNALS +#define sigemptyset(set) (*(set) = 0) +#define sigfillset(set) (*(set) = ~(sigset_t)0, 0) +#define sigaddset(set,signo) (*(set) |= sigmask(signo), 0) +#define sigdelset(set,signo) (*(set) &= ~sigmask(signo), 0) +#define sigismember(set,signo) ((*(set) & sigmask(signo)) != 0) + +#define SIG_BLOCK 1 +#define SIG_UNBLOCK 2 +#define SIG_SETMASK 3 + +static int __sigtemp; /* For the use of sigprocmask */ + +/* Repeated test of oset != NULL is to avoid "*0". */ +#define sigprocmask(how, set, oset) \ + ((__sigtemp = \ + (((how) == SIG_BLOCK) ? \ + sigblock(0) | *(set) : \ + (((how) == SIG_UNBLOCK) ? \ + sigblock(0) & ~(*(set)) : \ + ((how) == SIG_SETMASK ? \ + *(set) : sigblock(0))))), \ + ((oset) ? (*(oset ? oset : set) = sigsetmask(__sigtemp)) : \ + sigsetmask(__sigtemp)), 0) +#endif + +/* + * If your system doesn't have an include file with the appropriate + * byte order set, make sure you specify the correct one. + */ +#ifndef BYTE_ORDER +#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define BYTE_ORDER LITTLE_ENDIAN /* Set for your system. */ +#endif + +#if defined(SYSV) || defined(SYSTEM5) +#define index(a, b) strchr(a, b) +#define rindex(a, b) strrchr(a, b) +#define bzero(a, b) memset(a, 0, b) +#define bcmp(a, b, n) memcmp(a, b, n) +#define bcopy(a, b, n) memmove(b, a, n) +#endif + +#if defined(BSD) || defined(BSD4_3) +#define strchr(a, b) index(a, b) +#define strrchr(a, b) rindex(a, b) +#define memcmp(a, b, n) bcmp(a, b, n) +#define memmove(a, b, n) bcopy(b, a, n) +#endif + +/* + * 32-bit machine. The db routines are theoretically independent of + * the size of u_shorts and u_longs, but I don't know that anyone has + * ever actually tried it. At a minimum, change the following #define's + * if you are trying to compile on a different type of system. + */ +#ifndef USHRT_MAX +#if (SIZEOF_SHORT == 2) +#define USHRT_MAX 0xffff +#elif (SIZEOF_SHORT == 4) +#define USHRT_MAX 0xffffffff +#else +error : dont know how to deal with short size +#endif +#endif /* USHRT_MAX */ + +#ifndef UINT_MAX +#if (SIZEOF_INT == 2) +#define UINT_MAX 0xffff +#elif (SIZEOF_INT == 4) +#define UINT_MAX 0xffffffff +#elif (SIZEOF_INT == 8) +#define UINT_MAX 0xffffffffffffffff +#else +error : dont know how to deal with int size +#endif +#endif /* UINT_MAX */ + +#ifndef ULONG_MAX +#if (SIZEOF_LONG == 4) +#define ULONG_MAX 0xFFFFFFFF +#elif (SIZEOF_LONG == 8) +#define ULONG_MAX 0xffffffffffffffff +#else +error : dont know how to deal with long size +#endif +#endif /* ULONG_MAX */ + +#ifndef O_ACCMODE /* POSIX 1003.1 access mode mask. */ +#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif + +#ifndef _POSIX2_RE_DUP_MAX /* POSIX 1003.2 RE limit. */ +#define _POSIX2_RE_DUP_MAX 255 +#endif + +/* + * If you can't provide lock values in the open(2) call. Note, this + * allows races to happen. + */ +#ifndef O_EXLOCK /* 4.4BSD extension. */ +#define O_EXLOCK 0 +#endif + +#ifndef O_SHLOCK /* 4.4BSD extension. */ +#define O_SHLOCK 0 +#endif + +#ifndef EFTYPE +#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */ +#endif + +#ifndef WCOREDUMP /* 4.4BSD extension */ +#define WCOREDUMP(a) 0 +#endif + +#ifndef STDERR_FILENO +#define STDIN_FILENO 0 /* ANSI C #defines */ +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#endif + +#ifndef SEEK_END +#define SEEK_SET 0 /* POSIX 1003.1 seek values */ +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + +#ifndef _POSIX_VDISABLE /* POSIX 1003.1 disabling char. */ +#define _POSIX_VDISABLE 0 /* Some systems used 0. */ +#endif + +#ifndef TCSASOFT /* 4.4BSD extension. */ +#define TCSASOFT 0 +#endif + +#ifndef _POSIX2_RE_DUP_MAX /* POSIX 1003.2 values. */ +#define _POSIX2_RE_DUP_MAX 255 +#endif + +#ifndef NULL /* ANSI C #defines NULL everywhere. */ +#define NULL 0 +#endif + +#ifndef MAX /* Usually found in . */ +#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a)) +#endif +#ifndef MIN /* Usually found in . */ +#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) +#endif + +/* Default file permissions. */ +#ifndef DEFFILEMODE /* 4.4BSD extension. */ +#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) +#endif + +#ifndef S_ISDIR /* POSIX 1003.1 file type tests. */ +#define S_ISDIR(m) ((m & 0170000) == 0040000) /* directory */ +#define S_ISCHR(m) ((m & 0170000) == 0020000) /* char special */ +#define S_ISBLK(m) ((m & 0170000) == 0060000) /* block special */ +#define S_ISREG(m) ((m & 0170000) == 0100000) /* regular file */ +#define S_ISFIFO(m) ((m & 0170000) == 0010000) /* fifo */ +#endif +#ifndef S_ISLNK /* BSD POSIX 1003.1 extensions */ +#define S_ISLNK(m) ((m & 0170000) == 0120000) /* symbolic link */ +#define S_ISSOCK(m) ((m & 0170000) == 0140000) /* socket */ +#endif + +/* The type of a va_list. */ +#ifndef _BSD_VA_LIST_ /* 4.4BSD #define. */ +#define _BSD_VA_LIST_ char * +#endif + +#endif /* !_COMPAT_H_ */ diff --git a/src/util/berk_db/PORT/krb5/sys/.Sanitize b/src/util/berk_db/PORT/krb5/sys/.Sanitize new file mode 100644 index 000000000..e99e014bf --- /dev/null +++ b/src/util/berk_db/PORT/krb5/sys/.Sanitize @@ -0,0 +1,32 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +cdefs.h + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/PORT/krb5/sys/cdefs.h b/src/util/berk_db/PORT/krb5/sys/cdefs.h new file mode 100644 index 000000000..c104b9e96 --- /dev/null +++ b/src/util/berk_db/PORT/krb5/sys/cdefs.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cdefs.h 8.7 (Berkeley) 1/21/94 + */ + +#ifndef _CDEFS_H_ +#define _CDEFS_H_ + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS }; +#else +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky -- make sure you don't put spaces + * in between its arguments. __CONCAT can also concatenate double-quoted + * strings produced by the __STRING macro, but this only works with ANSI C. + */ +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) +#define __inline inline /* convert to C++ keyword */ +#else +#ifndef __GNUC__ +#define __inline /* delete GCC keyword */ +#endif /* !__GNUC__ */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#ifndef __GNUC__ +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * When using a compiler other than gcc, programs using the ANSI C keywords + * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. + * When using "gcc -traditional", we assume that this is the intent; if + * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. + */ +#ifndef NO_ANSI_KEYWORDS +#define const /* delete ANSI C keywords */ +#define inline +#define signed +#define volatile +#endif +#endif /* !__GNUC__ */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * GCC1 and some versions of GCC2 declare dead (non-returning) and + * pure (no side effects) functions using "volatile" and "const"; + * unfortunately, these then cause warnings under "-ansi -pedantic". + * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of + * these work for GNU C++ (modulo a slight glitch in the C++ grammar + * in the distribution version of 2.5.5). + */ +#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5 +#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#define __dead __volatile +#define __pure __const +#endif +#endif + +/* Delete pseudo-keywords wherever they are not available or needed. */ +#ifndef __dead +#define __dead +#define __pure +#endif + +#endif /* !_CDEFS_H_ */ diff --git a/src/util/berk_db/README b/src/util/berk_db/README new file mode 100644 index 000000000..bed2c92fa --- /dev/null +++ b/src/util/berk_db/README @@ -0,0 +1,40 @@ +# @(#)README 8.27 (Berkeley) 9/1/94 + +This is version 1.85 of the Berkeley DB code. + +For information on compiling and installing this software, see the file +PORT/README. + +Newer versions of this software will periodically be made available by +anonymous ftp from ftp.cs.berkeley.edu. An archive in compressed format +is in ucb/4bsd/db.tar.Z, or in gzip format in ucb/4bsd/db.tar.gz. If +you'd like to receive announcements of future releases of this software, +send email to the contact address below. + +Email questions may be addressed to Keith Bostic at bostic@cs.berkeley.edu. + +============================================ +Distribution contents: + +Makefile.inc Ignore this, it's the 4.4BSD subsystem Makefile. +PORT The per OS/architecture directories to use to build + libdb.a, if you're not running 4.4BSD. See the file + PORT/README for more information. +README This file. +btree The B+tree routines. +changelog List of changes, per version. +db The dbopen(3) interface routine. +docs Various USENIX papers, and the formatted manual pages. +hash The extended linear hashing routines. +man The unformatted manual pages. +mpool The memory pool routines. +recno The fixed/variable length record routines. +test Test package. + +============================================ +Debugging: + +If you're running a memory checker (e.g. Purify) on DB, make sure that +you recompile it with "-DPURIFY" in the CFLAGS, first. By default, +allocated pages are not initialized by the DB code, and they will show +up as reads of uninitialized memory in the buffer write routines. diff --git a/src/util/berk_db/README.krb5 b/src/util/berk_db/README.krb5 new file mode 100644 index 000000000..1f57823d3 --- /dev/null +++ b/src/util/berk_db/README.krb5 @@ -0,0 +1,17 @@ + +Kerberos notes: +--------------- + +What is here is only a small subset of the Berkeley database code. +Only the hashed database code has been kept. + +hash/krb5_ndbm.c has been added to better tune the database code to +Kerberos' large keys. This supercedes hash/ndbm.c. + +A bug in hash/hash_bigkey.c which caused deletion of elements in +collided buckets to fail or discard other collided elements has been +fixed. + + + + diff --git a/src/util/berk_db/changelog b/src/util/berk_db/changelog new file mode 100644 index 000000000..1540ca8e0 --- /dev/null +++ b/src/util/berk_db/changelog @@ -0,0 +1,103 @@ +1.84 -> 1.85 + recno: #ifdef out use of mmap, it's not portable enough. + +1.83 -> 1.84 Thu Aug 18 15:46:07 EDT 1994 + recno: Rework fixed-length records so that closing and reopening + the file now works. Pad short records on input. Never do + signed comparison in recno input reading functions. + +1.82 -> 1.83 Tue Jul 26 15:33:44 EDT 1994 + btree: Rework cursor deletion code yet again; bugs with + deleting empty pages that only contained the cursor + record. + +1.81 -> 1.82 Sat Jul 16 11:01:50 EDT 1994 + btree: Fix bugs introduced by new cursor/deletion code. + Replace return kbuf/dbuf with real DBT's. + +1.80 -> 1.81 + btree: Fix bugs introduced by new cursor/deletion code. + all: Add #defines for Purify. + +1.79 -> 1.80 Wed Jul 13 22:41:54 EDT 1994 + btree Change deletion to coalesce empty pages. This is a major + change, cursors and duplicate pages all had to be reworked. + Return to a fixed stack. + recno: Affected by cursor changes. New cursor structures should + permit multiple cursors in the future. + +1.78 -> 1.79 Mon Jun 20 17:36:47 EDT 1994 + all: Minor cleanups of 1.78 for porting reasons; only + major change was inlining check of NULL pointer + so that __fix_realloc goes away. + +1.77 -> 1.78 Thu Jun 16 19:06:43 EDT 1994 + all: Move "standard" size typedef's into db.h. + +1.76 -> 1.77 Thu Jun 16 16:48:38 EDT 1994 + hash: Delete __init_ routine, has special meaning to OSF 2.0. + +1.74 -> 1.76 + all: Finish up the port to the Alpha. + +1.73 -> 1.74 + recno: Don't put the record if rec_search fails, in rec_rdelete. + Create fixed-length intermediate records past "end" of DB + correctly. + Realloc bug when reading in fixed records. + all: First cut at port to Alpha (64-bit architecture) using + 4.4BSD basic integral types typedef's. + Cast allocation pointers to shut up old compilers. + Rework PORT directory into OS/machine directories. + +1.72 -> 1.73 + btree: If enough duplicate records were inserted and then deleted + that internal pages had references to empty pages of the + duplicate keys, the search function ended up on the wrong + page. + +1.7 -> 1.72 12 Oct 1993 + hash: Support NET/2 hash formats. + +1.7 -> 1.71 16 Sep 1993 + btree/recno: + Fix bug in internal search routines that caused + return of invalid pointers. + +1.6 -> 1.7 07 Sep 1993 + hash: Fixed big key overflow bugs. + test: Portability hacks, rewrite test script, Makefile. + btree/recno: + Stop copying non-overflow key/data pairs. + PORT: Break PORT directory up into per architecture/OS + subdirectories. + +1.5 -> 1.6 06 Jun 1993 + hash: In PAIRFITS, the first comparison should look at (P)[2]. + The hash_realloc function was walking off the end of memory. + The overflow page number was wrong when bumping splitpoint. + +1.4 -> 1.5 23 May 1993 + hash: Set hash default fill factor dynamically. + recno: Fixed bug in sorted page splits. + Add page size parameter support. + Allow recno to specify the name of the underlying btree; + used for vi recovery. + btree/recno: + Support 64K pages. + btree/hash/recno: + Provide access to an underlying file descriptor. + Change sync routines to take a flag argument, recno + uses this to sync out the underlying btree. + +1.3 -> 1.4 10 May 1993 + recno: Delete the R_CURSORLOG flag from the recno interface. + Zero-length record fix for non-mmap reads. + Try and make SIZE_T_MAX test in open portable. + +1.2 -> 1.3 01 May 1993 + btree: Ignore user byte-order setting when reading already + existing database. Fixes to byte-order conversions. + +1.1 -> 1.2 15 Apr 1993 + No bug fixes, only compatibility hacks. diff --git a/src/util/berk_db/configure.in b/src/util/berk_db/configure.in new file mode 100644 index 000000000..03052c673 --- /dev/null +++ b/src/util/berk_db/configure.in @@ -0,0 +1,15 @@ +AC_INIT(configure.in) +AC_SET_BUILDTOP +WITH_CCOPTS +WITH_KRB5ROOT +CONFIG_RULES +CONFIG_DIRS(hash test) +AC_PROG_ARCHIVE +AC_PROG_ARCHIVE_ADD +AC_PROG_RANLIB +AC_PROG_INSTALL +MAKE_SUBDIRS("making",all) +MAKE_SUBDIRS("cleaning",clean) +MAKE_SUBDIRS("checking",check) +AppendRule([all:: libdb.a libdb_ranlib]) +V5_AC_OUTPUT_MAKEFILE diff --git a/src/util/berk_db/hash/.Sanitize b/src/util/berk_db/hash/.Sanitize new file mode 100644 index 000000000..52ccdafef --- /dev/null +++ b/src/util/berk_db/hash/.Sanitize @@ -0,0 +1,49 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +.cvsignore +Makefile.in +README +configure +configure.in +extern.h +hash.c +hash.h +hash_bigkey.c +hash_buf.c +hash_func.c +hash_log2.c +hash_page.c +hsearch.c +krb5_ndbm.c +ndbm.c +page.h +search.h + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/hash/.cvsignore b/src/util/berk_db/hash/.cvsignore new file mode 100644 index 000000000..e8c05a6b1 --- /dev/null +++ b/src/util/berk_db/hash/.cvsignore @@ -0,0 +1 @@ +configure diff --git a/src/util/berk_db/hash/Makefile.in b/src/util/berk_db/hash/Makefile.in new file mode 100644 index 000000000..cdaf4d41f --- /dev/null +++ b/src/util/berk_db/hash/Makefile.in @@ -0,0 +1,46 @@ +HASH_DEBUGOPTS= +# DEBUG4 does not compile +# DEBUG1 does not work +#HASH_DEBUGOPTS= -DHASH_STATISTICS -DDEBUG -DDEBUG2 -DDEBUG3 -DPURIFY + +.c.o: + $(CC) $(CFLAGS) -c $(srcdir)/$*.c + +CFLAGS = $(CCOPTS) $(DEFS) -D__DBINTERFACE_PRIVATE $(LOCALINCLUDE) $(HASH_DEBUGOPTS) + +##DOSBUILDTOP = ..\..\.. +##DOSLIBNAME=..\db.lib +##DOS!include $(BUILDTOP)\config\windows.in + +LOCALINCLUDE=-I$(srcdir)/../PORT/krb5 \ + -I$(srcdir)/../PORT/krb5/include \ + -I$(srcdir)/../PORT/include \ + -I$(srcdir)/../include \ + -I$(srcdir) + +OBJS= hash.$(OBJEXT) \ + hash_bigkey.$(OBJEXT) \ + hash_buf.$(OBJEXT) \ + hash_func.$(OBJEXT) \ + hash_log2.$(OBJEXT) \ + hash_page.$(OBJEXT) \ + hsearch.$(OBJEXT) \ + krb5_ndbm.$(OBJEXT) \ + mktemp.$(OBJEXT) + + +SRCS= $(srcdir)/hash.c \ + $(srcdir)/hash_bigkey.c \ + $(srcdir)/hash_buf.c \ + $(srcdir)/hash_func.c \ + $(srcdir)/hash_log2.c \ + $(srcdir)/hash_page.c \ + $(srcdir)/hsearch.c \ + $(srcdir)/krb5_ndbm.c \ + $(srcdir)/../PORT/clib/mktemp.c + +mktemp.o: $(srcdir)/../PORT/clib/mktemp.c + $(CC) $(CFLAGS) -c $(srcdir)/../PORT/clib/mktemp.c + +all:: $(OBJS) + diff --git a/src/util/berk_db/hash/README b/src/util/berk_db/hash/README new file mode 100644 index 000000000..f29ccf7e1 --- /dev/null +++ b/src/util/berk_db/hash/README @@ -0,0 +1,72 @@ +# @(#)README 8.1 (Berkeley) 6/4/93 + +This package implements a superset of the hsearch and dbm/ndbm libraries. + +Test Programs: + All test programs which need key/data pairs expect them entered + with key and data on separate lines + + tcreat3.c + Takes + bucketsize (bsize), + fill factor (ffactor), and + initial number of elements (nelem). + Creates a hash table named hashtest containing the + keys/data pairs entered from standard in. + thash4.c + Takes + bucketsize (bsize), + fill factor (ffactor), + initial number of elements (nelem) + bytes of cache (ncached), and + file from which to read data (fname) + Creates a table from the key/data pairs on standard in and + then does a read of each key/data in fname + tdel.c + Takes + bucketsize (bsize), and + fill factor (ffactor). + file from which to read data (fname) + Reads each key/data pair from fname and deletes the + key from the hash table hashtest + tseq.c + Reads the key/data pairs in the file hashtest and writes them + to standard out. + tread2.c + Takes + butes of cache (ncached). + Reads key/data pairs from standard in and looks them up + in the file hashtest. + tverify.c + Reads key/data pairs from standard in, looks them up + in the file hashtest, and verifies that the data is + correct. + +NOTES: + +The file search.h is provided for using the hsearch compatible interface +on BSD systems. On System V derived systems, search.h should appear in +/usr/include. + +The man page ../man/db.3 explains the interface to the hashing system. +The file hash.ps is a postscript copy of a paper explaining +the history, implementation, and performance of the hash package. + +"bugs" or idiosyncracies + +If you have a lot of overflows, it is possible to run out of overflow +pages. Currently, this will cause a message to be printed on stderr. +Eventually, this will be indicated by a return error code. + +If you are using the ndbm interface and exit without flushing or closing the +file, you may lose updates since the package buffers all writes. Also, +the db interface only creates a single database file. To avoid overwriting +the user's original file, the suffix ".db" is appended to the file name +passed to dbm_open. Additionally, if your code "knows" about the historic +.dir and .pag files, it will break. + +There is a fundamental difference between this package and the old hsearch. +Hsearch requires the user to maintain the keys and data in the application's +allocated memory while hash takes care of all storage management. The down +side is that the byte strings passed in the ENTRY structure must be null +terminated (both the keys and the data). diff --git a/src/util/berk_db/hash/configure.in b/src/util/berk_db/hash/configure.in new file mode 100644 index 000000000..bac927b85 --- /dev/null +++ b/src/util/berk_db/hash/configure.in @@ -0,0 +1,16 @@ +AC_INIT(configure.in) +WITH_CCOPTS +CONFIG_RULES +AC_SET_BUILDTOP +WITH_NETLIB +AC_PROG_ARCHIVE +AC_PROG_ARCHIVE_ADD +AC_PROG_RANLIB +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +AC_HAVE_FUNCS(mktemp mkstemp) +CHECK_SIGNALS +SubdirLibraryRule([$(OBJS)]) +KRB_INCLUDE +V5_AC_OUTPUT_MAKEFILE diff --git a/src/util/berk_db/hash/extern.h b/src/util/berk_db/hash/extern.h new file mode 100644 index 000000000..3167e6d0f --- /dev/null +++ b/src/util/berk_db/hash/extern.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.4 (Berkeley) 6/16/94 + */ + +BUFHEAD *__add_ovflpage __P((HTAB *, BUFHEAD *)); +int __addel __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); +int __big_delete __P((HTAB *, BUFHEAD *)); +int __big_insert __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); +int __big_keydata __P((HTAB *, BUFHEAD *, DBT *, DBT *, int)); +int __big_return __P((HTAB *, BUFHEAD *, int, DBT *, int)); +int __big_split __P((HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *, + int, u_int32_t, SPLIT_RETURN *)); +int __buf_free __P((HTAB *, int, int)); +void __buf_init __P((HTAB *, int)); +u_int32_t __call_hash __P((HTAB *, char *, int)); +int __delpair __P((HTAB *, BUFHEAD *, int)); +int __expand_table __P((HTAB *)); +int __find_bigpair __P((HTAB *, BUFHEAD *, int, char *, int)); +u_int16_t __find_last_page __P((HTAB *, BUFHEAD **)); +void __free_ovflpage __P((HTAB *, BUFHEAD *)); +BUFHEAD *__get_buf __P((HTAB *, u_int32_t, BUFHEAD *, int)); +int __get_page __P((HTAB *, char *, u_int32_t, int, int, int)); +int __ibitmap __P((HTAB *, int, int, int)); +u_int32_t __log2 __P((u_int32_t)); +int __put_page __P((HTAB *, char *, u_int32_t, int, int)); +void __reclaim_buf __P((HTAB *, BUFHEAD *)); +int __split_page __P((HTAB *, u_int32_t, u_int32_t)); + +/* Default hash routine. */ +extern u_int32_t (*__default_hash) __P((const void *, size_t)); + +#ifdef HASH_STATISTICS +extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows; +#endif diff --git a/src/util/berk_db/hash/hash.c b/src/util/berk_db/hash/hash.c new file mode 100644 index 000000000..4b7b732a8 --- /dev/null +++ b/src/util/berk_db/hash/hash.c @@ -0,0 +1,994 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif + +#include +#include "hash.h" +#include "page.h" +#include "extern.h" + +static int alloc_segs __P((HTAB *, int)); +static int flush_meta __P((HTAB *)); +static int hash_access __P((HTAB *, ACTION, DBT *, DBT *)); +static int hash_close __P((DB *)); +static int hash_delete __P((const DB *, const DBT *, u_int32_t)); +static int hash_fd __P((const DB *)); +static int hash_get __P((const DB *, const DBT *, DBT *, u_int32_t)); +static int hash_put __P((const DB *, DBT *, const DBT *, u_int32_t)); +static void *hash_realloc __P((SEGMENT **, int, int)); +static int hash_seq __P((const DB *, DBT *, DBT *, u_int32_t)); +static int hash_sync __P((const DB *, u_int32_t)); +static int hdestroy __P((HTAB *)); +static HTAB *init_hash __P((HTAB *, const char *, HASHINFO *)); +static int init_htab __P((HTAB *, int)); +#if BYTE_ORDER == LITTLE_ENDIAN +static void swap_header __P((HTAB *)); +static void swap_header_copy __P((HASHHDR *, HASHHDR *)); +#endif + +/* Fast arithmetic, relying on powers of 2, */ +#define MOD(x, y) ((x) & ((y) - 1)) + +#define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; } + +/* Return values */ +#define SUCCESS (0) +#define ERROR (-1) +#define ABNORMAL (1) + +#ifdef HASH_STATISTICS +int hash_accesses, hash_collisions, hash_expansions, hash_overflows; +#endif + +/************************** INTERFACE ROUTINES ***************************/ +/* OPEN/CLOSE */ + +extern DB * +__hash_open(file, flags, mode, info, dflags) + const char *file; + int flags, mode, dflags; + const HASHINFO *info; /* Special directives for create */ +{ + HTAB *hashp; + struct stat statbuf; + DB *dbp; + int bpages, hdrsize, new_table, nsegs, save_errno; + + if ((flags & O_ACCMODE) == O_WRONLY) { + errno = EINVAL; + return (NULL); + } + + if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) + return (NULL); + hashp->fp = -1; + + /* + * Even if user wants write only, we need to be able to read + * the actual file, so we need to open it read/write. But, the + * field in the hashp structure needs to be accurate so that + * we can check accesses. + */ + hashp->flags = flags; + + new_table = 0; + if (!file || (flags & O_TRUNC) || + (stat(file, &statbuf) && (errno == ENOENT))) { + if (errno == ENOENT) + errno = 0; /* Just in case someone looks at errno */ + new_table = 1; + } + if (file) { + if ((hashp->fp = open(file, flags, mode)) == -1) + RETURN_ERROR(errno, error0); + (void)fcntl(hashp->fp, F_SETFD, 1); + } + if (new_table) { + if (!(hashp = init_hash(hashp, file, (HASHINFO *)info))) + RETURN_ERROR(errno, error1); + } else { + /* Table already exists */ + if (info && info->hash) + hashp->hash = info->hash; + else + hashp->hash = __default_hash; + + hdrsize = read(hashp->fp, &hashp->hdr, sizeof(HASHHDR)); +#if BYTE_ORDER == LITTLE_ENDIAN + swap_header(hashp); +#endif + if (hdrsize == -1) + RETURN_ERROR(errno, error1); + if (hdrsize != sizeof(HASHHDR)) + RETURN_ERROR(EFTYPE, error1); + /* Verify file type, versions and hash function */ + if (hashp->MAGIC != HASHMAGIC) + RETURN_ERROR(EFTYPE, error1); +#define OLDHASHVERSION 1 + if (hashp->VERSION != HASHVERSION && + hashp->VERSION != OLDHASHVERSION) + RETURN_ERROR(EFTYPE, error1); + if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY) + RETURN_ERROR(EFTYPE, error1); + /* + * Figure out how many segments we need. Max_Bucket is the + * maximum bucket number, so the number of buckets is + * max_bucket + 1. + */ + nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) / + hashp->SGSIZE; + hashp->nsegs = 0; + if (alloc_segs(hashp, nsegs)) + /* + * If alloc_segs fails, table will have been destroyed + * and errno will have been set. + */ + return (NULL); + /* Read in bitmaps */ + bpages = (hashp->SPARES[hashp->OVFL_POINT] + + (hashp->BSIZE << BYTE_SHIFT) - 1) >> + (hashp->BSHIFT + BYTE_SHIFT); + + hashp->nmaps = bpages; + (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *)); + } + + /* Initialize Buffer Manager */ + if (info && info->cachesize) + __buf_init(hashp, info->cachesize); + else + __buf_init(hashp, DEF_BUFSIZE); + + hashp->new_file = new_table; + hashp->save_file = file && (hashp->flags & O_RDWR); + hashp->cbucket = -1; + if (!(dbp = (DB *)malloc(sizeof(DB)))) { + save_errno = errno; + hdestroy(hashp); + errno = save_errno; + return (NULL); + } + dbp->internal = hashp; + dbp->close = hash_close; + dbp->del = hash_delete; + dbp->fd = hash_fd; + dbp->get = hash_get; + dbp->put = hash_put; + dbp->seq = hash_seq; + dbp->sync = hash_sync; + dbp->type = DB_HASH; + +#ifdef DEBUG + (void)fprintf(stderr, +"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", + "init_htab:", + "TABLE POINTER ", hashp, + "BUCKET SIZE ", hashp->BSIZE, + "BUCKET SHIFT ", hashp->BSHIFT, + "DIRECTORY SIZE ", hashp->DSIZE, + "SEGMENT SIZE ", hashp->SGSIZE, + "SEGMENT SHIFT ", hashp->SSHIFT, + "FILL FACTOR ", hashp->FFACTOR, + "MAX BUCKET ", hashp->MAX_BUCKET, + "OVFL POINT ", hashp->OVFL_POINT, + "LAST FREED ", hashp->LAST_FREED, + "HIGH MASK ", hashp->HIGH_MASK, + "LOW MASK ", hashp->LOW_MASK, + "NSEGS ", hashp->nsegs, + "NKEYS ", hashp->NKEYS); +#endif +#ifdef HASH_STATISTICS + hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0; +#endif + return (dbp); + +error1: + if (hashp != NULL) + (void)close(hashp->fp); + +error0: + free(hashp); + errno = save_errno; + return (NULL); +} + +static int +hash_close(dbp) + DB *dbp; +{ + HTAB *hashp; + int retval; + + if (!dbp) + return (ERROR); + + hashp = (HTAB *)dbp->internal; + retval = hdestroy(hashp); + free(dbp); + return (retval); +} + +static int +hash_fd(dbp) + const DB *dbp; +{ + HTAB *hashp; + + if (!dbp) + return (ERROR); + + hashp = (HTAB *)dbp->internal; + if (hashp->fp == -1) { + errno = ENOENT; + return (-1); + } + return (hashp->fp); +} + +/************************** LOCAL CREATION ROUTINES **********************/ +static HTAB * +init_hash(hashp, file, info) + HTAB *hashp; + const char *file; + HASHINFO *info; +{ + struct stat statbuf; + int nelem; + + nelem = 1; + hashp->NKEYS = 0; + hashp->LORDER = BYTE_ORDER; + hashp->BSIZE = DEF_BUCKET_SIZE; + hashp->BSHIFT = DEF_BUCKET_SHIFT; + hashp->SGSIZE = DEF_SEGSIZE; + hashp->SSHIFT = DEF_SEGSIZE_SHIFT; + hashp->DSIZE = DEF_DIRSIZE; + hashp->FFACTOR = DEF_FFACTOR; + hashp->hash = __default_hash; + memset(hashp->SPARES, 0, sizeof(hashp->SPARES)); + memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS)); + + /* Fix bucket size to be optimal for file system */ + if (file != NULL) { + if (stat(file, &statbuf)) + return (NULL); + hashp->BSIZE = statbuf.st_blksize; + hashp->BSHIFT = __log2(hashp->BSIZE); + } + + if (info) { + if (info->bsize) { + /* Round pagesize up to power of 2 */ + hashp->BSHIFT = __log2(info->bsize); + hashp->BSIZE = 1 << hashp->BSHIFT; + if (hashp->BSIZE > MAX_BSIZE) { + errno = EINVAL; + return (NULL); + } + } + if (info->ffactor) + hashp->FFACTOR = info->ffactor; + if (info->hash) + hashp->hash = info->hash; + if (info->nelem) + nelem = info->nelem; + if (info->lorder) { + if (info->lorder != BIG_ENDIAN && + info->lorder != LITTLE_ENDIAN) { + errno = EINVAL; + return (NULL); + } + hashp->LORDER = info->lorder; + } + } + /* init_htab should destroy the table and set errno if it fails */ + if (init_htab(hashp, nelem)) + return (NULL); + else + return (hashp); +} +/* + * This calls alloc_segs which may run out of memory. Alloc_segs will destroy + * the table and set errno, so we just pass the error information along. + * + * Returns 0 on No Error + */ +static int +init_htab(hashp, nelem) + HTAB *hashp; + int nelem; +{ + register int nbuckets, nsegs; + int l2; + + /* + * Divide number of elements by the fill factor and determine a + * desired number of buckets. Allocate space for the next greater + * power of two number of buckets. + */ + nelem = (nelem - 1) / hashp->FFACTOR + 1; + + l2 = __log2(MAX(nelem, 2)); + nbuckets = 1 << l2; + + hashp->SPARES[l2] = l2 + 1; + hashp->SPARES[l2 + 1] = l2 + 1; + hashp->OVFL_POINT = l2; + hashp->LAST_FREED = 2; + + /* First bitmap page is at: splitpoint l2 page offset 1 */ + if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0)) + return (-1); + + hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1; + hashp->HIGH_MASK = (nbuckets << 1) - 1; + hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >> + hashp->BSHIFT) + 1; + + nsegs = (nbuckets - 1) / hashp->SGSIZE + 1; + nsegs = 1 << __log2(nsegs); + + if (nsegs > hashp->DSIZE) + hashp->DSIZE = nsegs; + return (alloc_segs(hashp, nsegs)); +} + +/********************** DESTROY/CLOSE ROUTINES ************************/ + +/* + * Flushes any changes to the file if necessary and destroys the hashp + * structure, freeing all allocated space. + */ +static int +hdestroy(hashp) + HTAB *hashp; +{ + int i, save_errno; + + save_errno = 0; + +#ifdef HASH_STATISTICS + (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n", + hash_accesses, hash_collisions); + (void)fprintf(stderr, "hdestroy: expansions %ld\n", + hash_expansions); + (void)fprintf(stderr, "hdestroy: overflows %ld\n", + hash_overflows); + (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n", + hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs); + + for (i = 0; i < NCACHED; i++) + (void)fprintf(stderr, + "spares[%d] = %d\n", i, hashp->SPARES[i]); +#endif + /* + * Call on buffer manager to free buffers, and if required, + * write them to disk. + */ + if (__buf_free(hashp, 1, hashp->save_file)) + save_errno = errno; + if (hashp->dir) { + free(*hashp->dir); /* Free initial segments */ + /* Free extra segments */ + while (hashp->exsegs--) + free(hashp->dir[--hashp->nsegs]); + free(hashp->dir); + } + if (flush_meta(hashp) && !save_errno) + save_errno = errno; + /* Free Bigmaps */ + for (i = 0; i < hashp->nmaps; i++) + if (hashp->mapp[i]) + free(hashp->mapp[i]); + + if (hashp->fp != -1) + (void)close(hashp->fp); + + free(hashp); + + if (save_errno) { + errno = save_errno; + return (ERROR); + } + return (SUCCESS); +} +/* + * Write modified pages to disk + * + * Returns: + * 0 == OK + * -1 ERROR + */ +static int +hash_sync(dbp, flags) + const DB *dbp; + u_int32_t flags; +{ + HTAB *hashp; + + if (flags != 0) { + errno = EINVAL; + return (ERROR); + } + + if (!dbp) + return (ERROR); + + hashp = (HTAB *)dbp->internal; + if (!hashp->save_file) + return (0); + if (__buf_free(hashp, 0, 1) || flush_meta(hashp)) + return (ERROR); + hashp->new_file = 0; + return (0); +} + +/* + * Returns: + * 0 == OK + * -1 indicates that errno should be set + */ +static int +flush_meta(hashp) + HTAB *hashp; +{ + HASHHDR *whdrp; +#if BYTE_ORDER == LITTLE_ENDIAN + HASHHDR whdr; +#endif + int fp, i, wsize; + + if (!hashp->save_file) + return (0); + hashp->MAGIC = HASHMAGIC; + hashp->VERSION = HASHVERSION; + hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY)); + + fp = hashp->fp; + whdrp = &hashp->hdr; +#if BYTE_ORDER == LITTLE_ENDIAN + whdrp = &whdr; + swap_header_copy(&hashp->hdr, whdrp); +#endif + if ((lseek(fp, (off_t)0, SEEK_SET) == -1) || + ((wsize = write(fp, whdrp, sizeof(HASHHDR))) == -1)) + return (-1); + else + if (wsize != sizeof(HASHHDR)) { + errno = EFTYPE; + hashp->errno = errno; + return (-1); + } + for (i = 0; i < NCACHED; i++) + if (hashp->mapp[i]) + if (__put_page(hashp, (char *)hashp->mapp[i], + hashp->BITMAPS[i], 0, 1)) + return (-1); + return (0); +} + +/*******************************SEARCH ROUTINES *****************************/ +/* + * All the access routines return + * + * Returns: + * 0 on SUCCESS + * 1 to indicate an external ERROR (i.e. key not found, etc) + * -1 to indicate an internal ERROR (i.e. out of memory, etc) + */ +static int +hash_get(dbp, key, data, flag) + const DB *dbp; + const DBT *key; + DBT *data; + u_int32_t flag; +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + if (flag) { + hashp->errno = errno = EINVAL; + return (ERROR); + } + return (hash_access(hashp, HASH_GET, (DBT *)key, data)); +} + +static int +hash_put(dbp, key, data, flag) + const DB *dbp; + DBT *key; + const DBT *data; + u_int32_t flag; +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_NOOVERWRITE) { + hashp->errno = errno = EINVAL; + return (ERROR); + } + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { + hashp->errno = errno = EPERM; + return (ERROR); + } + return (hash_access(hashp, flag == R_NOOVERWRITE ? + HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data)); +} + +static int +hash_delete(dbp, key, flag) + const DB *dbp; + const DBT *key; + u_int32_t flag; /* Ignored */ +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_CURSOR) { + hashp->errno = errno = EINVAL; + return (ERROR); + } + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { + hashp->errno = errno = EPERM; + return (ERROR); + } + return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL)); +} + +/* + * Assume that hashp has been set in wrapper routine. + */ +static int +hash_access(hashp, action, key, val) + HTAB *hashp; + ACTION action; + DBT *key, *val; +{ + register BUFHEAD *rbufp; + BUFHEAD *bufp, *save_bufp; + register u_int16_t *bp; + register int n, ndx, off, size; + register char *kp; + u_int16_t pageno; + +#ifdef HASH_STATISTICS + hash_accesses++; +#endif + + off = hashp->BSIZE; + size = key->size; + kp = (char *)key->data; + rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0); + if (!rbufp) + return (ERROR); + save_bufp = rbufp; + + /* Pin the bucket chain */ + rbufp->flags |= BUF_PIN; + for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;) + if (bp[1] >= REAL_KEY) { + /* Real key/data pair */ + if (size == off - *bp && + memcmp(kp, rbufp->page + *bp, size) == 0) + goto found; + off = bp[1]; +#ifdef HASH_STATISTICS + hash_collisions++; +#endif + bp += 2; + ndx += 2; + } else if (bp[1] == OVFLPAGE) { + rbufp = __get_buf(hashp, *bp, rbufp, 0); + if (!rbufp) { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } + /* FOR LOOP INIT */ + bp = (u_int16_t *)rbufp->page; + n = *bp++; + ndx = 1; + off = hashp->BSIZE; + } else if (bp[1] < REAL_KEY) { + if ((ndx = + __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0) + goto found; + if (ndx == -2) { + bufp = rbufp; + if (!(pageno = + __find_last_page(hashp, &bufp))) { + ndx = 0; + rbufp = bufp; + break; /* FOR */ + } + rbufp = __get_buf(hashp, pageno, bufp, 0); + if (!rbufp) { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } + /* FOR LOOP INIT */ + bp = (u_int16_t *)rbufp->page; + n = *bp++; + ndx = 1; + off = hashp->BSIZE; + } else { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } + } + + /* Not found */ + switch (action) { + case HASH_PUT: + case HASH_PUTNEW: + if (__addel(hashp, rbufp, key, val)) { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } else { + save_bufp->flags &= ~BUF_PIN; + return (SUCCESS); + } + case HASH_GET: + case HASH_DELETE: + default: + save_bufp->flags &= ~BUF_PIN; + return (ABNORMAL); + } + +found: + switch (action) { + case HASH_PUTNEW: + save_bufp->flags &= ~BUF_PIN; + return (ABNORMAL); + case HASH_GET: + bp = (u_int16_t *)rbufp->page; + if (bp[ndx + 1] < REAL_KEY) { + if (__big_return(hashp, rbufp, ndx, val, 0)) + return (ERROR); + } else { + val->data = (u_char *)rbufp->page + (int)bp[ndx + 1]; + val->size = bp[ndx] - bp[ndx + 1]; + } + break; + case HASH_PUT: + if ((__delpair(hashp, rbufp, ndx)) || + (__addel(hashp, rbufp, key, val))) { + save_bufp->flags &= ~BUF_PIN; + return (ERROR); + } + break; + case HASH_DELETE: + if (__delpair(hashp, rbufp, ndx)) + return (ERROR); + break; + default: + abort(); + } + save_bufp->flags &= ~BUF_PIN; + return (SUCCESS); +} + +static int +hash_seq(dbp, key, data, flag) + const DB *dbp; + DBT *key, *data; + u_int32_t flag; +{ + register u_int32_t bucket; + register BUFHEAD *bufp; + HTAB *hashp; + u_int16_t *bp, ndx; + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_FIRST && flag != R_NEXT) { + hashp->errno = errno = EINVAL; + return (ERROR); + } +#ifdef HASH_STATISTICS + hash_accesses++; +#endif + if ((hashp->cbucket < 0) || (flag == R_FIRST)) { + hashp->cbucket = 0; + hashp->cndx = 1; + hashp->cpage = NULL; + } + + for (bp = NULL; !bp || !bp[0]; ) { + if (!(bufp = hashp->cpage)) { + for (bucket = hashp->cbucket; + bucket <= hashp->MAX_BUCKET; + bucket++, hashp->cndx = 1) { + bufp = __get_buf(hashp, bucket, NULL, 0); + if (!bufp) + return (ERROR); + hashp->cpage = bufp; + bp = (u_int16_t *)bufp->page; + if (bp[0]) + break; + } + hashp->cbucket = bucket; + if (hashp->cbucket > hashp->MAX_BUCKET) { + hashp->cbucket = -1; + return (ABNORMAL); + } + } else + bp = (u_int16_t *)hashp->cpage->page; + +#ifdef DEBUG + assert(bp); + assert(bufp); +#endif + while (bp[hashp->cndx + 1] == OVFLPAGE) { + bufp = hashp->cpage = + __get_buf(hashp, bp[hashp->cndx], bufp, 0); + if (!bufp) + return (ERROR); + bp = (u_int16_t *)(bufp->page); + hashp->cndx = 1; + } + if (!bp[0]) { + hashp->cpage = NULL; + ++hashp->cbucket; + } + } + ndx = hashp->cndx; + if (bp[ndx + 1] < REAL_KEY) { + if (__big_keydata(hashp, bufp, key, data, 1)) + return (ERROR); + } else { + key->data = (u_char *)hashp->cpage->page + bp[ndx]; + key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx]; + data->data = (u_char *)hashp->cpage->page + bp[ndx + 1]; + data->size = bp[ndx] - bp[ndx + 1]; + ndx += 2; + if (ndx > bp[0]) { + hashp->cpage = NULL; + hashp->cbucket++; + hashp->cndx = 1; + } else + hashp->cndx = ndx; + } + return (SUCCESS); +} + +/********************************* UTILITIES ************************/ + +/* + * Returns: + * 0 ==> OK + * -1 ==> Error + */ +extern int +__expand_table(hashp) + HTAB *hashp; +{ + u_int32_t old_bucket, new_bucket; + int dirsize, new_segnum, spare_ndx; + +#ifdef HASH_STATISTICS + hash_expansions++; +#endif + new_bucket = ++hashp->MAX_BUCKET; + old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK); + + new_segnum = new_bucket >> hashp->SSHIFT; + + /* Check if we need a new segment */ + if (new_segnum >= hashp->nsegs) { + /* Check if we need to expand directory */ + if (new_segnum >= hashp->DSIZE) { + /* Reallocate directory */ + dirsize = hashp->DSIZE * sizeof(SEGMENT *); + if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1)) + return (-1); + hashp->DSIZE = dirsize << 1; + } + if ((hashp->dir[new_segnum] = + (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL) + return (-1); + hashp->exsegs++; + hashp->nsegs++; + } + /* + * If the split point is increasing (MAX_BUCKET's log base 2 + * * increases), we need to copy the current contents of the spare + * split bucket to the next bucket. + */ + spare_ndx = __log2(hashp->MAX_BUCKET + 1); + if (spare_ndx > hashp->OVFL_POINT) { + hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT]; + hashp->OVFL_POINT = spare_ndx; + } + + if (new_bucket > hashp->HIGH_MASK) { + /* Starting a new doubling */ + hashp->LOW_MASK = hashp->HIGH_MASK; + hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK; + } + /* Relocate records to the new bucket */ + return (__split_page(hashp, old_bucket, new_bucket)); +} + +/* + * If realloc guarantees that the pointer is not destroyed if the realloc + * fails, then this routine can go away. + */ +static void * +hash_realloc(p_ptr, oldsize, newsize) + SEGMENT **p_ptr; + int oldsize, newsize; +{ + register void *p; + + if (p = malloc(newsize)) { + memmove(p, *p_ptr, oldsize); + memset((char *)p + oldsize, 0, newsize - oldsize); + free(*p_ptr); + *p_ptr = p; + } + return (p); +} + +extern u_int32_t +__call_hash(hashp, k, len) + HTAB *hashp; + char *k; + int len; +{ + int n, bucket; + + n = hashp->hash(k, len); + bucket = n & hashp->HIGH_MASK; + if (bucket > hashp->MAX_BUCKET) + bucket = bucket & hashp->LOW_MASK; + return (bucket); +} + +/* + * Allocate segment table. On error, destroy the table and set errno. + * + * Returns 0 on success + */ +static int +alloc_segs(hashp, nsegs) + HTAB *hashp; + int nsegs; +{ + register int i; + register SEGMENT store; + + int save_errno; + + if ((hashp->dir = + (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) { + save_errno = errno; + (void)hdestroy(hashp); + errno = save_errno; + return (-1); + } + /* Allocate segments */ + if ((store = + (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) { + save_errno = errno; + (void)hdestroy(hashp); + errno = save_errno; + return (-1); + } + for (i = 0; i < nsegs; i++, hashp->nsegs++) + hashp->dir[i] = &store[i << hashp->SSHIFT]; + return (0); +} + +#if BYTE_ORDER == LITTLE_ENDIAN +/* + * Hashp->hdr needs to be byteswapped. + */ +static void +swap_header_copy(srcp, destp) + HASHHDR *srcp, *destp; +{ + int i; + + P_32_COPY(srcp->magic, destp->magic); + P_32_COPY(srcp->version, destp->version); + P_32_COPY(srcp->lorder, destp->lorder); + P_32_COPY(srcp->bsize, destp->bsize); + P_32_COPY(srcp->bshift, destp->bshift); + P_32_COPY(srcp->dsize, destp->dsize); + P_32_COPY(srcp->ssize, destp->ssize); + P_32_COPY(srcp->sshift, destp->sshift); + P_32_COPY(srcp->ovfl_point, destp->ovfl_point); + P_32_COPY(srcp->last_freed, destp->last_freed); + P_32_COPY(srcp->max_bucket, destp->max_bucket); + P_32_COPY(srcp->high_mask, destp->high_mask); + P_32_COPY(srcp->low_mask, destp->low_mask); + P_32_COPY(srcp->ffactor, destp->ffactor); + P_32_COPY(srcp->nkeys, destp->nkeys); + P_32_COPY(srcp->hdrpages, destp->hdrpages); + P_32_COPY(srcp->h_charkey, destp->h_charkey); + for (i = 0; i < NCACHED; i++) { + P_32_COPY(srcp->spares[i], destp->spares[i]); + P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]); + } +} + +static void +swap_header(hashp) + HTAB *hashp; +{ + HASHHDR *hdrp; + int i; + + hdrp = &hashp->hdr; + + M_32_SWAP(hdrp->magic); + M_32_SWAP(hdrp->version); + M_32_SWAP(hdrp->lorder); + M_32_SWAP(hdrp->bsize); + M_32_SWAP(hdrp->bshift); + M_32_SWAP(hdrp->dsize); + M_32_SWAP(hdrp->ssize); + M_32_SWAP(hdrp->sshift); + M_32_SWAP(hdrp->ovfl_point); + M_32_SWAP(hdrp->last_freed); + M_32_SWAP(hdrp->max_bucket); + M_32_SWAP(hdrp->high_mask); + M_32_SWAP(hdrp->low_mask); + M_32_SWAP(hdrp->ffactor); + M_32_SWAP(hdrp->nkeys); + M_32_SWAP(hdrp->hdrpages); + M_32_SWAP(hdrp->h_charkey); + for (i = 0; i < NCACHED; i++) { + M_32_SWAP(hdrp->spares[i]); + M_16_SWAP(hdrp->bitmaps[i]); + } +} +#endif diff --git a/src/util/berk_db/hash/hash.h b/src/util/berk_db/hash/hash.h new file mode 100644 index 000000000..913e82b40 --- /dev/null +++ b/src/util/berk_db/hash/hash.h @@ -0,0 +1,293 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)hash.h 8.3 (Berkeley) 5/31/94 + */ + +/* Operations */ +typedef enum { + HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT +} ACTION; + +/* Buffer Management structures */ +typedef struct _bufhead BUFHEAD; + +struct _bufhead { + BUFHEAD *prev; /* LRU links */ + BUFHEAD *next; /* LRU links */ + BUFHEAD *ovfl; /* Overflow page buffer header */ + u_int32_t addr; /* Address of this page */ + char *page; /* Actual page data */ + char flags; +#define BUF_MOD 0x0001 +#define BUF_DISK 0x0002 +#define BUF_BUCKET 0x0004 +#define BUF_PIN 0x0008 +}; + +#define IS_BUCKET(X) ((X) & BUF_BUCKET) + +typedef BUFHEAD **SEGMENT; + +/* Hash Table Information */ +typedef struct hashhdr { /* Disk resident portion */ + int magic; /* Magic NO for hash tables */ + int version; /* Version ID */ + u_int32_t lorder; /* Byte Order */ + int bsize; /* Bucket/Page Size */ + int bshift; /* Bucket shift */ + int dsize; /* Directory Size */ + int ssize; /* Segment Size */ + int sshift; /* Segment shift */ + int ovfl_point; /* Where overflow pages are being + * allocated */ + int last_freed; /* Last overflow page freed */ + int max_bucket; /* ID of Maximum bucket in use */ + int high_mask; /* Mask to modulo into entire table */ + int low_mask; /* Mask to modulo into lower half of + * table */ + int ffactor; /* Fill factor */ + int nkeys; /* Number of keys in hash table */ + int hdrpages; /* Size of table header */ + int h_charkey; /* value of hash(CHARKEY) */ +#define NCACHED 32 /* number of bit maps and spare + * points */ + int spares[NCACHED];/* spare pages for overflow */ + u_int16_t bitmaps[NCACHED]; /* address of overflow page + * bitmaps */ +} HASHHDR; + +typedef struct htab { /* Memory resident data structure */ + HASHHDR hdr; /* Header */ + int nsegs; /* Number of allocated segments */ + int exsegs; /* Number of extra allocated + * segments */ + u_int32_t /* Hash function */ + (*hash)__P((const void *, size_t)); + int flags; /* Flag values */ + int fp; /* File pointer */ + char *tmp_buf; /* Temporary Buffer for BIG data */ + char *tmp_key; /* Temporary Buffer for BIG keys */ + BUFHEAD *cpage; /* Current page */ + int cbucket; /* Current bucket */ + int cndx; /* Index of next item on cpage */ + int errno; /* Error Number -- for DBM + * compatability */ + int new_file; /* Indicates if fd is backing store + * or no */ + int save_file; /* Indicates whether we need to flush + * file at + * exit */ + u_int32_t *mapp[NCACHED]; /* Pointers to page maps */ + int nmaps; /* Initial number of bitmaps */ + int nbufs; /* Number of buffers left to + * allocate */ + BUFHEAD bufhead; /* Header of buffer lru list */ + SEGMENT *dir; /* Hash Bucket directory */ +} HTAB; + +/* + * Constants + */ +#define MAX_BSIZE 65536 /* 2^16 */ +#define MIN_BUFFERS 6 +#define MINHDRSIZE 512 +#define DEF_BUFSIZE 65536 /* 64 K */ +#define DEF_BUCKET_SIZE 4096 +#define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */ +#define DEF_SEGSIZE 256 +#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */ +#define DEF_DIRSIZE 256 +#define DEF_FFACTOR 65536 +#define MIN_FFACTOR 4 +#define SPLTMAX 8 +#define CHARKEY "%$sniglet^&" +#define NUMKEY 1038583 +#define BYTE_SHIFT 3 +#define INT_TO_BYTE 2 +#define INT_BYTE_SHIFT 5 +#define ALL_SET ((u_int32_t)0xFFFFFFFF) +#define ALL_CLEAR 0 + +#define PTROF(X) ((BUFHEAD *)((ptrdiff_t)(X)&~0x3)) +#define ISMOD(X) ((u_int32_t)(ptrdiff_t)(X)&0x1) +#define DOMOD(X) ((X) = (char *)((ptrdiff_t)(X)|0x1)) +#define ISDISK(X) ((u_int32_t)(ptrdiff_t)(X)&0x2) +#define DODISK(X) ((X) = (char *)((ptrdiff_t)(X)|0x2)) + +#define BITS_PER_MAP 32 + +/* Given the address of the beginning of a big map, clear/set the nth bit */ +#define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP))) +#define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP))) +#define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP))) + +/* Overflow management */ +/* + * Overflow page numbers are allocated per split point. At each doubling of + * the table, we can allocate extra pages. So, an overflow page number has + * the top 5 bits indicate which split point and the lower 11 bits indicate + * which page at that split point is indicated (pages within split points are + * numberered starting with 1). + */ + +#define SPLITSHIFT 11 +#define SPLITMASK 0x7FF +#define SPLITNUM(N) (((u_int32_t)(N)) >> SPLITSHIFT) +#define OPAGENUM(N) ((N) & SPLITMASK) +#define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O)) + +#define BUCKET_TO_PAGE(B) \ + (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0) +#define OADDR_TO_PAGE(B) \ + BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)); + +/* + * page.h contains a detailed description of the page format. + * + * Normally, keys and data are accessed from offset tables in the top of + * each page which point to the beginning of the key and data. There are + * four flag values which may be stored in these offset tables which indicate + * the following: + * + * + * OVFLPAGE Rather than a key data pair, this pair contains + * the address of an overflow page. The format of + * the pair is: + * OVERFLOW_PAGE_NUMBER OVFLPAGE + * + * PARTIAL_KEY This must be the first key/data pair on a page + * and implies that page contains only a partial key. + * That is, the key is too big to fit on a single page + * so it starts on this page and continues on the next. + * The format of the page is: + * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE + * + * KEY_OFF -- offset of the beginning of the key + * PARTIAL_KEY -- 1 + * OVFL_PAGENO - page number of the next overflow page + * OVFLPAGE -- 0 + * + * FULL_KEY This must be the first key/data pair on the page. It + * is used in two cases. + * + * Case 1: + * There is a complete key on the page but no data + * (because it wouldn't fit). The next page contains + * the data. + * + * Page format it: + * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE + * + * KEY_OFF -- offset of the beginning of the key + * FULL_KEY -- 2 + * OVFL_PAGENO - page number of the next overflow page + * OVFLPAGE -- 0 + * + * Case 2: + * This page contains no key, but part of a large + * data field, which is continued on the next page. + * + * Page format it: + * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE + * + * KEY_OFF -- offset of the beginning of the data on + * this page + * FULL_KEY -- 2 + * OVFL_PAGENO - page number of the next overflow page + * OVFLPAGE -- 0 + * + * FULL_KEY_DATA + * This must be the first key/data pair on the page. + * There are two cases: + * + * Case 1: + * This page contains a key and the beginning of the + * data field, but the data field is continued on the + * next page. + * + * Page format is: + * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF + * + * KEY_OFF -- offset of the beginning of the key + * FULL_KEY_DATA -- 3 + * OVFL_PAGENO - page number of the next overflow page + * DATA_OFF -- offset of the beginning of the data + * + * Case 2: + * This page contains the last page of a big data pair. + * There is no key, only the tail end of the data + * on this page. + * + * Page format is: + * DATA_OFF FULL_KEY_DATA + * + * DATA_OFF -- offset of the beginning of the data on + * this page + * FULL_KEY_DATA -- 3 + * OVFL_PAGENO - page number of the next overflow page + * OVFLPAGE -- 0 + * + * OVFL_PAGENO and OVFLPAGE are optional (they are + * not present if there is no next page). + */ + +#define OVFLPAGE 0 +#define PARTIAL_KEY 1 +#define FULL_KEY 2 +#define FULL_KEY_DATA 3 +#define REAL_KEY 4 + +/* Short hands for accessing structure */ +#define BSIZE hdr.bsize +#define BSHIFT hdr.bshift +#define DSIZE hdr.dsize +#define SGSIZE hdr.ssize +#define SSHIFT hdr.sshift +#define LORDER hdr.lorder +#define OVFL_POINT hdr.ovfl_point +#define LAST_FREED hdr.last_freed +#define MAX_BUCKET hdr.max_bucket +#define FFACTOR hdr.ffactor +#define HIGH_MASK hdr.high_mask +#define LOW_MASK hdr.low_mask +#define NKEYS hdr.nkeys +#define HDRPAGES hdr.hdrpages +#define SPARES hdr.spares +#define BITMAPS hdr.bitmaps +#define VERSION hdr.version +#define MAGIC hdr.magic +#define NEXT_FREE hdr.next_free +#define H_CHARKEY hdr.h_charkey diff --git a/src/util/berk_db/hash/hash_bigkey.c b/src/util/berk_db/hash/hash_bigkey.c new file mode 100644 index 000000000..952f385b4 --- /dev/null +++ b/src/util/berk_db/hash/hash_bigkey.c @@ -0,0 +1,667 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * PACKAGE: hash + * DESCRIPTION: + * Big key/data handling for the hashing package. + * + * ROUTINES: + * External + * __big_keydata + * __big_split + * __big_insert + * __big_return + * __big_delete + * __find_last_page + * Internal + * collect_key + * collect_data + */ + +#include + +#include +#include +#include +#include + +#ifdef DEBUG +#include +#endif + +#include +#include "hash.h" +#include "page.h" +#include "extern.h" + +static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int)); +static int collect_data __P((HTAB *, BUFHEAD *, int, int)); + +/* + * Big_insert + * + * You need to do an insert and the key/data pair is too big + * + * Returns: + * 0 ==> OK + *-1 ==> ERROR + */ +extern int +__big_insert(hashp, bufp, key, val) + HTAB *hashp; + BUFHEAD *bufp; + const DBT *key, *val; +{ + register u_int16_t *p; + int key_size, n, val_size; + u_int16_t space, move_bytes, off; + char *cp, *key_data, *val_data; + + cp = bufp->page; /* Character pointer of p. */ + p = (u_int16_t *)cp; + + key_data = (char *)key->data; + key_size = key->size; + val_data = (char *)val->data; + val_size = val->size; + + /* First move the Key */ + for (space = FREESPACE(p) - BIGOVERHEAD; key_size; + space = FREESPACE(p) - BIGOVERHEAD) { + move_bytes = MIN(space, key_size); + off = OFFSET(p) - move_bytes; + memmove(cp + off, key_data, move_bytes); + key_size -= move_bytes; + key_data += move_bytes; + n = p[0]; + p[++n] = off; + p[0] = ++n; + FREESPACE(p) = off - PAGE_META(n); + OFFSET(p) = off; + p[n] = PARTIAL_KEY; + bufp = __add_ovflpage(hashp, bufp); + if (!bufp) + return (-1); + n = p[0]; + if (!key_size) + if (FREESPACE(p)) { + move_bytes = MIN(FREESPACE(p), val_size); + off = OFFSET(p) - move_bytes; + p[n] = off; + memmove(cp + off, val_data, move_bytes); + val_data += move_bytes; + val_size -= move_bytes; + p[n - 2] = FULL_KEY_DATA; + FREESPACE(p) = FREESPACE(p) - move_bytes; + OFFSET(p) = off; + } else + p[n - 2] = FULL_KEY; + p = (u_int16_t *)bufp->page; + cp = bufp->page; + bufp->flags |= BUF_MOD; + } + + /* Now move the data */ + for (space = FREESPACE(p) - BIGOVERHEAD; val_size; + space = FREESPACE(p) - BIGOVERHEAD) { + move_bytes = MIN(space, val_size); + /* + * Here's the hack to make sure that if the data ends on the + * same page as the key ends, FREESPACE is at least one. + */ + if (space == val_size && val_size == val->size) + move_bytes--; + off = OFFSET(p) - move_bytes; + memmove(cp + off, val_data, move_bytes); + val_size -= move_bytes; + val_data += move_bytes; + n = p[0]; + p[++n] = off; + p[0] = ++n; + FREESPACE(p) = off - PAGE_META(n); + OFFSET(p) = off; + if (val_size) { + p[n] = FULL_KEY; + bufp = __add_ovflpage(hashp, bufp); + if (!bufp) + return (-1); + cp = bufp->page; + p = (u_int16_t *)cp; + } else + p[n] = FULL_KEY_DATA; + bufp->flags |= BUF_MOD; + } + return (0); +} + +/* + * Called when bufp's page contains a partial key (index should be 1) + * + * All pages in the big key/data pair except bufp are freed. We cannot + * free bufp because the page pointing to it is lost and we can't get rid + * of its pointer. + * + * Returns: + * 0 => OK + *-1 => ERROR + */ +extern int +__big_delete(hashp, bufp) + HTAB *hashp; + BUFHEAD *bufp; +{ + register BUFHEAD *last_bfp, *rbufp; + u_int16_t *bp, pageno; + int key_done, n; + + rbufp = bufp; + last_bfp = NULL; + bp = (u_int16_t *)bufp->page; + pageno = 0; + key_done = 0; + + while (!key_done || (bp[2] != FULL_KEY_DATA)) { + if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) + key_done = 1; + + /* + * If there is freespace left on a FULL_KEY_DATA page, then + * the data is short and fits entirely on this page, and this + * is the last page. + */ + if (bp[2] == FULL_KEY_DATA && FREESPACE(bp)) + break; + pageno = bp[bp[0] - 1]; + rbufp->flags |= BUF_MOD; + rbufp = __get_buf(hashp, pageno, rbufp, 0); + if (last_bfp) + __free_ovflpage(hashp, last_bfp); + last_bfp = rbufp; + if (!rbufp) + return (-1); /* Error. */ + bp = (u_int16_t *)rbufp->page; + } + + /* + * If we get here then rbufp points to the last page of the big + * key/data pair. Bufp points to the first one -- it should now be + * empty pointing to the next page after this pair. Can't free it + * because we don't have the page pointing to it. + */ + + /* This is information from the last page of the pair. */ + n = bp[0]; + pageno = bp[n - 1]; + + /* Now, bp is the first page of the pair. */ + bp = (u_int16_t *)bufp->page; + if (n > 2) { + /* There is an overflow page. */ + bp[1] = pageno; + bp[2] = OVFLPAGE; + bufp->ovfl = rbufp->ovfl; + } else + /* This is the last page. */ + bufp->ovfl = NULL; + n -= 2; + bp[0] = n; + FREESPACE(bp) = hashp->BSIZE - PAGE_META(n); + OFFSET(bp) = hashp->BSIZE - 1; + + bufp->flags |= BUF_MOD; + if (rbufp && (rbufp != bufp)) + __free_ovflpage(hashp, rbufp); + if (last_bfp && (last_bfp != rbufp)) + __free_ovflpage(hashp, last_bfp); + + hashp->NKEYS--; + return (0); +} +/* + * Returns: + * 0 = key not found + * -1 = get next overflow page + * -2 means key not found and this is big key/data + * -3 error + */ +extern int +__find_bigpair(hashp, bufp, ndx, key, size) + HTAB *hashp; + BUFHEAD *bufp; + int ndx; + char *key; + int size; +{ + register u_int16_t *bp; + register char *p; + int ksize; + u_int16_t bytes; + char *kkey; + + bp = (u_int16_t *)bufp->page; + p = bufp->page; + ksize = size; + kkey = key; + + for (bytes = hashp->BSIZE - bp[ndx]; + bytes <= size && bp[ndx + 1] == PARTIAL_KEY; + bytes = hashp->BSIZE - bp[ndx]) { + if (memcmp(p + bp[ndx], kkey, bytes)) + return (-2); + kkey += bytes; + ksize -= bytes; + bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0); + if (!bufp) + return (-3); + p = bufp->page; + bp = (u_int16_t *)p; + ndx = 1; + } + + if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) { +#ifdef HASH_STATISTICS + ++hash_collisions; +#endif + return (-2); + } else + return (ndx); +} + +/* + * Given the buffer pointer of the first overflow page of a big pair, + * find the end of the big pair + * + * This will set bpp to the buffer header of the last page of the big pair. + * It will return the pageno of the overflow page following the last page + * of the pair; 0 if there isn't any (i.e. big pair is the last key in the + * bucket) + */ +extern u_int16_t +__find_last_page(hashp, bpp) + HTAB *hashp; + BUFHEAD **bpp; +{ + BUFHEAD *bufp; + u_int16_t *bp, pageno; + int n; + + bufp = *bpp; + bp = (u_int16_t *)bufp->page; + for (;;) { + n = bp[0]; + + /* + * This is the last page if: the tag is FULL_KEY_DATA and + * either only 2 entries OVFLPAGE marker is explicit there + * is freespace on the page. + */ + if (bp[2] == FULL_KEY_DATA && + ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp)))) + break; + + pageno = bp[n - 1]; + bufp = __get_buf(hashp, pageno, bufp, 0); + if (!bufp) + return (0); /* Need to indicate an error! */ + bp = (u_int16_t *)bufp->page; + } + + *bpp = bufp; + if (bp[0] > 2) + return (bp[3]); + else + return (0); +} + +/* + * Return the data for the key/data pair that begins on this page at this + * index (index should always be 1). + */ +extern int +__big_return(hashp, bufp, ndx, val, set_current) + HTAB *hashp; + BUFHEAD *bufp; + int ndx; + DBT *val; + int set_current; +{ + BUFHEAD *save_p; + u_int16_t *bp, len, off, save_addr; + char *tp; + + bp = (u_int16_t *)bufp->page; + while (bp[ndx + 1] == PARTIAL_KEY) { + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + ndx = 1; + } + + if (bp[ndx + 1] == FULL_KEY) { + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + save_p = bufp; + save_addr = save_p->addr; + off = bp[1]; + len = 0; + } else + if (!FREESPACE(bp)) { + /* + * This is a hack. We can't distinguish between + * FULL_KEY_DATA that contains complete data or + * incomplete data, so we require that if the data + * is complete, there is at least 1 byte of free + * space left. + */ + off = bp[bp[0]]; + len = bp[1] - off; + save_p = bufp; + save_addr = bufp->addr; + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + } else { + /* The data is all on one page. */ + tp = (char *)bp; + off = bp[bp[0]]; + val->data = (u_char *)tp + off; + val->size = bp[1] - off; + if (set_current) { + if (bp[0] == 2) { /* No more buckets in + * chain */ + hashp->cpage = NULL; + hashp->cbucket++; + hashp->cndx = 1; + } else { + hashp->cpage = __get_buf(hashp, + bp[bp[0] - 1], bufp, 0); + if (!hashp->cpage) + return (-1); + hashp->cndx = 1; + if (!((u_int16_t *) + hashp->cpage->page)[0]) { + hashp->cbucket++; + hashp->cpage = NULL; + } + } + } + return (0); + } + + val->size = collect_data(hashp, bufp, (int)len, set_current); + if (val->size == -1) + return (-1); + if (save_p->addr != save_addr) { + /* We are pretty short on buffers. */ + errno = EINVAL; /* OUT OF BUFFERS */ + return (-1); + } + memmove(hashp->tmp_buf, (save_p->page) + off, len); + val->data = (u_char *)hashp->tmp_buf; + return (0); +} +/* + * Count how big the total datasize is by recursing through the pages. Then + * allocate a buffer and copy the data as you recurse up. + */ +static int +collect_data(hashp, bufp, len, set) + HTAB *hashp; + BUFHEAD *bufp; + int len, set; +{ + register u_int16_t *bp; + register char *p; + BUFHEAD *xbp; + u_int16_t save_addr; + int mylen, totlen; + + p = bufp->page; + bp = (u_int16_t *)p; + mylen = hashp->BSIZE - bp[1]; + save_addr = bufp->addr; + + if (bp[2] == FULL_KEY_DATA) { /* End of Data */ + totlen = len + mylen; + if (hashp->tmp_buf) + free(hashp->tmp_buf); + if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL) + return (-1); + if (set) { + hashp->cndx = 1; + if (bp[0] == 2) { /* No more buckets in chain */ + hashp->cpage = NULL; + hashp->cbucket++; + } else { + hashp->cpage = + __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!hashp->cpage) + return (-1); + else if (!((u_int16_t *)hashp->cpage->page)[0]) { + hashp->cbucket++; + hashp->cpage = NULL; + } + } + } + } else { + xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!xbp || ((totlen = + collect_data(hashp, xbp, len + mylen, set)) < 1)) + return (-1); + } + if (bufp->addr != save_addr) { + errno = EINVAL; /* Out of buffers. */ + return (-1); + } + memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen); + return (totlen); +} + +/* + * Fill in the key and data for this big pair. + */ +extern int +__big_keydata(hashp, bufp, key, val, set) + HTAB *hashp; + BUFHEAD *bufp; + DBT *key, *val; + int set; +{ + key->size = collect_key(hashp, bufp, 0, val, set); + if (key->size == -1) + return (-1); + key->data = (u_char *)hashp->tmp_key; + return (0); +} + +/* + * Count how big the total key size is by recursing through the pages. Then + * collect the data, allocate a buffer and copy the key as you recurse up. + */ +static int +collect_key(hashp, bufp, len, val, set) + HTAB *hashp; + BUFHEAD *bufp; + int len; + DBT *val; + int set; +{ + BUFHEAD *xbp; + char *p; + int mylen, totlen; + u_int16_t *bp, save_addr; + + p = bufp->page; + bp = (u_int16_t *)p; + mylen = hashp->BSIZE - bp[1]; + + save_addr = bufp->addr; + totlen = len + mylen; + if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */ + if (hashp->tmp_key != NULL) + free(hashp->tmp_key); + if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL) + return (-1); + if (__big_return(hashp, bufp, 1, val, set)) + return (-1); + } else { + xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!xbp || ((totlen = + collect_key(hashp, xbp, totlen, val, set)) < 1)) + return (-1); + } + if (bufp->addr != save_addr) { + errno = EINVAL; /* MIS -- OUT OF BUFFERS */ + return (-1); + } + memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen); + return (totlen); +} + +/* + * Returns: + * 0 => OK + * -1 => error + */ +extern int +__big_split(hashp, op, np, big_keyp, addr, obucket, ret) + HTAB *hashp; + BUFHEAD *op; /* Pointer to where to put keys that go in old bucket */ + BUFHEAD *np; /* Pointer to new bucket page */ + /* Pointer to first page containing the big key/data */ + BUFHEAD *big_keyp; + int addr; /* Address of big_keyp */ + u_int32_t obucket;/* Old Bucket */ + SPLIT_RETURN *ret; +{ + register BUFHEAD *tmpp; + register u_int16_t *tp; + BUFHEAD *bp; + DBT key, val; + u_int32_t change; + u_int16_t free_space, n, off; + + bp = big_keyp; + + /* Now figure out where the big key/data goes */ + if (__big_keydata(hashp, big_keyp, &key, &val, 0)) + return (-1); + change = (__call_hash(hashp, key.data, key.size) != obucket); + + if (ret->next_addr = __find_last_page(hashp, &big_keyp)) { + if (!(ret->nextp = + __get_buf(hashp, ret->next_addr, big_keyp, 0))) + return (-1);; + } else + ret->nextp = NULL; + + /* Now make one of np/op point to the big key/data pair */ +#ifdef DEBUG + assert(np->ovfl == NULL); +#endif + if (change) + tmpp = np; + else + tmpp = op; + + tmpp->flags |= BUF_MOD; +#ifdef DEBUG1 + (void)fprintf(stderr, + "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr, + (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0)); +#endif + tmpp->ovfl = bp; /* one of op/np point to big_keyp */ + tp = (u_int16_t *)tmpp->page; +#ifdef DEBUG + assert(FREESPACE(tp) >= OVFLSIZE); +#endif + n = tp[0]; + off = OFFSET(tp); + free_space = FREESPACE(tp); + tp[++n] = (u_int16_t)addr; + tp[++n] = OVFLPAGE; + tp[0] = n; + OFFSET(tp) = off; + FREESPACE(tp) = free_space - OVFLSIZE; + + /* + * Finally, set the new and old return values. BIG_KEYP contains a + * pointer to the last page of the big key_data pair. Make sure that + * big_keyp has no following page (2 elements) or create an empty + * following page. + */ + + ret->newp = np; + ret->oldp = op; + + tp = (u_int16_t *)big_keyp->page; + big_keyp->flags |= BUF_MOD; + if (tp[0] > 2) { + /* + * There may be either one or two offsets on this page. If + * there is one, then the overflow page is linked on normally + * and tp[4] is OVFLPAGE. If there are two, tp[4] contains + * the second offset and needs to get stuffed in after the + * next overflow page is added. + */ + n = tp[4]; + free_space = FREESPACE(tp); + off = OFFSET(tp); + tp[0] -= 2; + FREESPACE(tp) = free_space + OVFLSIZE; + OFFSET(tp) = off; + tmpp = __add_ovflpage(hashp, big_keyp); + if (!tmpp) + return (-1); + tp[4] = n; + } else + tmpp = big_keyp; + + if (change) + ret->newp = tmpp; + else + ret->oldp = tmpp; + return (0); +} diff --git a/src/util/berk_db/hash/hash_buf.c b/src/util/berk_db/hash/hash_buf.c new file mode 100644 index 000000000..92e1f933a --- /dev/null +++ b/src/util/berk_db/hash/hash_buf.c @@ -0,0 +1,355 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * PACKAGE: hash + * + * DESCRIPTION: + * Contains buffer management + * + * ROUTINES: + * External + * __buf_init + * __get_buf + * __buf_free + * __reclaim_buf + * Internal + * newbuf + */ + +#include + +#include +#include +#include +#include + +#ifdef DEBUG +#include +#endif + +#include +#include "hash.h" +#include "page.h" +#include "extern.h" + +static BUFHEAD *newbuf __P((HTAB *, u_int32_t, BUFHEAD *)); + +/* Unlink B from its place in the lru */ +#define BUF_REMOVE(B) { \ + (B)->prev->next = (B)->next; \ + (B)->next->prev = (B)->prev; \ +} + +/* Insert B after P */ +#define BUF_INSERT(B, P) { \ + (B)->next = (P)->next; \ + (B)->prev = (P); \ + (P)->next = (B); \ + (B)->next->prev = (B); \ +} + +#define MRU hashp->bufhead.next +#define LRU hashp->bufhead.prev + +#define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead) +#define LRU_INSERT(B) BUF_INSERT((B), LRU) + +/* + * We are looking for a buffer with address "addr". If prev_bp is NULL, then + * address is a bucket index. If prev_bp is not NULL, then it points to the + * page previous to an overflow page that we are trying to find. + * + * CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer + * be valid. Therefore, you must always verify that its address matches the + * address you are seeking. + */ +extern BUFHEAD * +__get_buf(hashp, addr, prev_bp, newpage) + HTAB *hashp; + u_int32_t addr; + BUFHEAD *prev_bp; + int newpage; /* If prev_bp set, indicates a new overflow page. */ +{ + register BUFHEAD *bp; + register u_int32_t is_disk_mask; + register int is_disk, segment_ndx; + SEGMENT segp; + + is_disk = 0; + is_disk_mask = 0; + if (prev_bp) { + bp = prev_bp->ovfl; + if (!bp || (bp->addr != addr)) + bp = NULL; + if (!newpage) + is_disk = BUF_DISK; + } else { + /* Grab buffer out of directory */ + segment_ndx = addr & (hashp->SGSIZE - 1); + + /* valid segment ensured by __call_hash() */ + segp = hashp->dir[addr >> hashp->SSHIFT]; +#ifdef DEBUG + assert(segp != NULL); +#endif + bp = PTROF(segp[segment_ndx]); + is_disk_mask = ISDISK(segp[segment_ndx]); + is_disk = is_disk_mask || !hashp->new_file; + } + + if (!bp) { + bp = newbuf(hashp, addr, prev_bp); + if (!bp || + __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0)) + return (NULL); + if (!prev_bp) + segp[segment_ndx] = + (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask); + } else { + BUF_REMOVE(bp); + MRU_INSERT(bp); + } + return (bp); +} + +/* + * We need a buffer for this page. Either allocate one, or evict a resident + * one (if we have as many buffers as we're allowed) and put this one in. + * + * If newbuf finds an error (returning NULL), it also sets errno. + */ +static BUFHEAD * +newbuf(hashp, addr, prev_bp) + HTAB *hashp; + u_int32_t addr; + BUFHEAD *prev_bp; +{ + register BUFHEAD *bp; /* The buffer we're going to use */ + register BUFHEAD *xbp; /* Temp pointer */ + register BUFHEAD *next_xbp; + SEGMENT segp; + int segment_ndx; + u_int16_t oaddr, *shortp; + + oaddr = 0; + bp = LRU; + /* + * If LRU buffer is pinned, the buffer pool is too small. We need to + * allocate more buffers. + */ + if (hashp->nbufs || (bp->flags & BUF_PIN)) { + /* Allocate a new one */ + if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL) + return (NULL); +#ifdef PURIFY + memset(bp, 0xff, sizeof(BUFHEAD)); +#endif + if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) { + free(bp); + return (NULL); + } +#ifdef PURIFY + memset(bp->page, 0xff, hashp->BSIZE); +#endif + if (hashp->nbufs) + hashp->nbufs--; + } else { + /* Kick someone out */ + BUF_REMOVE(bp); + /* + * If this is an overflow page with addr 0, it's already been + * flushed back in an overflow chain and initialized. + */ + if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) { + /* + * Set oaddr before __put_page so that you get it + * before bytes are swapped. + */ + shortp = (u_int16_t *)bp->page; + if (shortp[0]) + oaddr = shortp[shortp[0] - 1]; + if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page, + bp->addr, (int)IS_BUCKET(bp->flags), 0)) + return (NULL); + /* + * Update the pointer to this page (i.e. invalidate it). + * + * If this is a new file (i.e. we created it at open + * time), make sure that we mark pages which have been + * written to disk so we retrieve them from disk later, + * rather than allocating new pages. + */ + if (IS_BUCKET(bp->flags)) { + segment_ndx = bp->addr & (hashp->SGSIZE - 1); + segp = hashp->dir[bp->addr >> hashp->SSHIFT]; +#ifdef DEBUG + assert(segp != NULL); +#endif + + if (hashp->new_file && + ((bp->flags & BUF_MOD) || + ISDISK(segp[segment_ndx]))) + segp[segment_ndx] = (BUFHEAD *)BUF_DISK; + else + segp[segment_ndx] = NULL; + } + /* + * Since overflow pages can only be access by means of + * their bucket, free overflow pages associated with + * this bucket. + */ + for (xbp = bp; xbp->ovfl;) { + next_xbp = xbp->ovfl; + xbp->ovfl = 0; + xbp = next_xbp; + + /* Check that ovfl pointer is up date. */ + if (IS_BUCKET(xbp->flags) || + (oaddr != xbp->addr)) + break; + + shortp = (u_int16_t *)xbp->page; + if (shortp[0]) + /* set before __put_page */ + oaddr = shortp[shortp[0] - 1]; + if ((xbp->flags & BUF_MOD) && __put_page(hashp, + xbp->page, xbp->addr, 0, 0)) + return (NULL); + xbp->addr = 0; + xbp->flags = 0; + BUF_REMOVE(xbp); + LRU_INSERT(xbp); + } + } + } + + /* Now assign this buffer */ + bp->addr = addr; +#ifdef DEBUG1 + (void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n", + bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0); +#endif + bp->ovfl = NULL; + if (prev_bp) { + /* + * If prev_bp is set, this is an overflow page, hook it in to + * the buffer overflow links. + */ +#ifdef DEBUG1 + (void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n", + prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0), + (bp ? bp->addr : 0)); +#endif + prev_bp->ovfl = bp; + bp->flags = 0; + } else + bp->flags = BUF_BUCKET; + MRU_INSERT(bp); + return (bp); +} + +extern void +__buf_init(hashp, nbytes) + HTAB *hashp; + int nbytes; +{ + BUFHEAD *bfp; + int npages; + + bfp = &(hashp->bufhead); + npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT; + npages = MAX(npages, MIN_BUFFERS); + + hashp->nbufs = npages; + bfp->next = bfp; + bfp->prev = bfp; + /* + * This space is calloc'd so these are already null. + * + * bfp->ovfl = NULL; + * bfp->flags = 0; + * bfp->page = NULL; + * bfp->addr = 0; + */ +} + +extern int +__buf_free(hashp, do_free, to_disk) + HTAB *hashp; + int do_free, to_disk; +{ + BUFHEAD *bp; + + /* Need to make sure that buffer manager has been initialized */ + if (!LRU) + return (0); + for (bp = LRU; bp != &hashp->bufhead;) { + /* Check that the buffer is valid */ + if (bp->addr || IS_BUCKET(bp->flags)) { + if (to_disk && (bp->flags & BUF_MOD) && + __put_page(hashp, bp->page, + bp->addr, IS_BUCKET(bp->flags), 0)) + return (-1); + } + /* Check if we are freeing stuff */ + if (do_free) { + if (bp->page) + free(bp->page); + BUF_REMOVE(bp); + free(bp); + bp = LRU; + } else + bp = bp->prev; + } + return (0); +} + +extern void +__reclaim_buf(hashp, bp) + HTAB *hashp; + BUFHEAD *bp; +{ + bp->ovfl = 0; + bp->addr = 0; + bp->flags = 0; + BUF_REMOVE(bp); + LRU_INSERT(bp); +} diff --git a/src/util/berk_db/hash/hash_func.c b/src/util/berk_db/hash/hash_func.c new file mode 100644 index 000000000..a5ec434ee --- /dev/null +++ b/src/util/berk_db/hash/hash_func.c @@ -0,0 +1,212 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include "hash.h" +#include "page.h" +#include "extern.h" + +static u_int32_t hash1 __P((const void *, size_t)); +static u_int32_t hash2 __P((const void *, size_t)); +static u_int32_t hash3 __P((const void *, size_t)); +static u_int32_t hash4 __P((const void *, size_t)); + +/* Global default hash function */ +u_int32_t (*__default_hash) __P((const void *, size_t)) = hash4; + +/* + * HASH FUNCTIONS + * + * Assume that we've already split the bucket to which this key hashes, + * calculate that bucket, and check that in fact we did already split it. + * + * This came from ejb's hsearch. + */ + +#define PRIME1 37 +#define PRIME2 1048583 + +static u_int32_t +hash1(keyarg, len) + const void *keyarg; + register size_t len; +{ + register const u_char *key; + register u_int32_t h; + + /* Convert string to integer */ + for (key = keyarg, h = 0; len--;) + h = h * PRIME1 ^ (*key++ - ' '); + h %= PRIME2; + return (h); +} + +/* + * Phong's linear congruential hash + */ +#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) + +static u_int32_t +hash2(keyarg, len) + const void *keyarg; + size_t len; +{ + register const u_char *e, *key; + register u_int32_t h; + register u_char c; + + key = keyarg; + e = key + len; + for (h = 0; key != e;) { + c = *key++; + if (!c && key > e) + break; + dcharhash(h, c); + } + return (h); +} + +/* + * This is INCREDIBLY ugly, but fast. We break the string up into 8 byte + * units. On the first time through the loop we get the "leftover bytes" + * (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle + * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If + * this routine is heavily used enough, it's worth the ugly coding. + * + * OZ's original sdbm hash + */ +static u_int32_t +hash3(keyarg, len) + const void *keyarg; + register size_t len; +{ + register const u_char *key; + register size_t loop; + register u_int32_t h; + +#define HASHC h = *key++ + 65599 * h + + h = 0; + key = keyarg; + if (len > 0) { + loop = (len + 8 - 1) >> 3; + + switch (len & (8 - 1)) { + case 0: + do { + HASHC; + /* FALLTHROUGH */ + case 7: + HASHC; + /* FALLTHROUGH */ + case 6: + HASHC; + /* FALLTHROUGH */ + case 5: + HASHC; + /* FALLTHROUGH */ + case 4: + HASHC; + /* FALLTHROUGH */ + case 3: + HASHC; + /* FALLTHROUGH */ + case 2: + HASHC; + /* FALLTHROUGH */ + case 1: + HASHC; + } while (--loop); + } + } + return (h); +} + +/* Hash function from Chris Torek. */ +static u_int32_t +hash4(keyarg, len) + const void *keyarg; + register size_t len; +{ + register const u_char *key; + register size_t loop; + register u_int32_t h; + +#define HASH4a h = (h << 5) - h + *key++; +#define HASH4b h = (h << 5) + h + *key++; +#define HASH4 HASH4b + + h = 0; + key = keyarg; + if (len > 0) { + loop = (len + 8 - 1) >> 3; + + switch (len & (8 - 1)) { + case 0: + do { + HASH4; + /* FALLTHROUGH */ + case 7: + HASH4; + /* FALLTHROUGH */ + case 6: + HASH4; + /* FALLTHROUGH */ + case 5: + HASH4; + /* FALLTHROUGH */ + case 4: + HASH4; + /* FALLTHROUGH */ + case 3: + HASH4; + /* FALLTHROUGH */ + case 2: + HASH4; + /* FALLTHROUGH */ + case 1: + HASH4; + } while (--loop); + } + } + return (h); +} diff --git a/src/util/berk_db/hash/hash_log2.c b/src/util/berk_db/hash/hash_log2.c new file mode 100644 index 000000000..c8c56bff2 --- /dev/null +++ b/src/util/berk_db/hash/hash_log2.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include + +u_int32_t +__log2(num) + u_int32_t num; +{ + register u_int32_t i, limit; + + limit = 1; + for (i = 0; limit < num; limit = limit << 1, i++); + return (i); +} diff --git a/src/util/berk_db/hash/hash_page.c b/src/util/berk_db/hash/hash_page.c new file mode 100644 index 000000000..e1dfe6b8d --- /dev/null +++ b/src/util/berk_db/hash/hash_page.c @@ -0,0 +1,944 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * PACKAGE: hashing + * + * DESCRIPTION: + * Page manipulation for hashing package. + * + * ROUTINES: + * + * External + * __get_page + * __add_ovflpage + * Internal + * overflow_page + * open_temp + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif + +#include +#include "hash.h" +#include "page.h" +#include "extern.h" + +static u_int32_t *fetch_bitmap __P((HTAB *, int)); +static u_int32_t first_free __P((u_int32_t)); +static int open_temp __P((HTAB *)); +static u_int16_t overflow_page __P((HTAB *)); +static void putpair __P((char *, const DBT *, const DBT *)); +static void squeeze_key __P((u_int16_t *, const DBT *, const DBT *)); +static int ugly_split + __P((HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int)); + +#define PAGE_INIT(P) { \ + ((u_int16_t *)(P))[0] = 0; \ + ((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \ + ((u_int16_t *)(P))[2] = hashp->BSIZE; \ +} + +/* + * This is called AFTER we have verified that there is room on the page for + * the pair (PAIRFITS has returned true) so we go right ahead and start moving + * stuff on. + */ +static void +putpair(p, key, val) + char *p; + const DBT *key, *val; +{ + register u_int16_t *bp, n, off; + + bp = (u_int16_t *)p; + + /* Enter the key first. */ + n = bp[0]; + + off = OFFSET(bp) - key->size; + memmove(p + off, key->data, key->size); + bp[++n] = off; + + /* Now the data. */ + off -= val->size; + memmove(p + off, val->data, val->size); + bp[++n] = off; + + /* Adjust page info. */ + bp[0] = n; + bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t)); + bp[n + 2] = off; +} + +/* + * Returns: + * 0 OK + * -1 error + */ +extern int +__delpair(hashp, bufp, ndx) + HTAB *hashp; + BUFHEAD *bufp; + register int ndx; +{ + register u_int16_t *bp, newoff; + register int n; + u_int16_t pairlen; + + bp = (u_int16_t *)bufp->page; + n = bp[0]; + + if (bp[ndx + 1] < REAL_KEY) + return (__big_delete(hashp, bufp)); + if (ndx != 1) + newoff = bp[ndx - 1]; + else + newoff = hashp->BSIZE; + pairlen = newoff - bp[ndx + 1]; + + if (ndx != (n - 1)) { + /* Hard Case -- need to shuffle keys */ + register int i; + register char *src = bufp->page + (int)OFFSET(bp); + register char *dst = src + (int)pairlen; + memmove(dst, src, bp[ndx + 1] - OFFSET(bp)); + + /* Now adjust the pointers */ + for (i = ndx + 2; i <= n; i += 2) { + if (bp[i + 1] == OVFLPAGE) { + bp[i - 2] = bp[i]; + bp[i - 1] = bp[i + 1]; + } else { + bp[i - 2] = bp[i] + pairlen; + bp[i - 1] = bp[i + 1] + pairlen; + } + } + } + /* Finally adjust the page data */ + bp[n] = OFFSET(bp) + pairlen; + bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t); + bp[0] = n - 2; + hashp->NKEYS--; + + bufp->flags |= BUF_MOD; + return (0); +} +/* + * Returns: + * 0 ==> OK + * -1 ==> Error + */ +extern int +__split_page(hashp, obucket, nbucket) + HTAB *hashp; + u_int32_t obucket, nbucket; +{ + register BUFHEAD *new_bufp, *old_bufp; + register u_int16_t *ino; + register char *np; + DBT key, val; + int n, ndx, retval; + u_int16_t copyto, diff, off, moved; + char *op; + + copyto = (u_int16_t)hashp->BSIZE; + off = (u_int16_t)hashp->BSIZE; + old_bufp = __get_buf(hashp, obucket, NULL, 0); + if (old_bufp == NULL) + return (-1); + new_bufp = __get_buf(hashp, nbucket, NULL, 0); + if (new_bufp == NULL) + return (-1); + + old_bufp->flags |= (BUF_MOD | BUF_PIN); + new_bufp->flags |= (BUF_MOD | BUF_PIN); + + ino = (u_int16_t *)(op = old_bufp->page); + np = new_bufp->page; + + moved = 0; + + for (n = 1, ndx = 1; n < ino[0]; n += 2) { + if (ino[n + 1] < REAL_KEY) { + retval = ugly_split(hashp, obucket, old_bufp, new_bufp, + (int)copyto, (int)moved); + old_bufp->flags &= ~BUF_PIN; + new_bufp->flags &= ~BUF_PIN; + return (retval); + + } + key.data = (u_char *)op + ino[n]; + key.size = off - ino[n]; + + if (__call_hash(hashp, key.data, key.size) == obucket) { + /* Don't switch page */ + diff = copyto - off; + if (diff) { + copyto = ino[n + 1] + diff; + memmove(op + copyto, op + ino[n + 1], + off - ino[n + 1]); + ino[ndx] = copyto + ino[n] - ino[n + 1]; + ino[ndx + 1] = copyto; + } else + copyto = ino[n + 1]; + ndx += 2; + } else { + /* Switch page */ + val.data = (u_char *)op + ino[n + 1]; + val.size = ino[n] - ino[n + 1]; + putpair(np, &key, &val); + moved += 2; + } + + off = ino[n + 1]; + } + + /* Now clean up the page */ + ino[0] -= moved; + FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3); + OFFSET(ino) = copyto; + +#ifdef DEBUG3 + (void)fprintf(stderr, "split %d/%d\n", + ((u_int16_t *)np)[0] / 2, + ((u_int16_t *)op)[0] / 2); +#endif + /* unpin both pages */ + old_bufp->flags &= ~BUF_PIN; + new_bufp->flags &= ~BUF_PIN; + return (0); +} + +/* + * Called when we encounter an overflow or big key/data page during split + * handling. This is special cased since we have to begin checking whether + * the key/data pairs fit on their respective pages and because we may need + * overflow pages for both the old and new pages. + * + * The first page might be a page with regular key/data pairs in which case + * we have a regular overflow condition and just need to go on to the next + * page or it might be a big key/data pair in which case we need to fix the + * big key/data pair. + * + * Returns: + * 0 ==> success + * -1 ==> failure + */ +static int +ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved) + HTAB *hashp; + u_int32_t obucket; /* Same as __split_page. */ + BUFHEAD *old_bufp, *new_bufp; + int copyto; /* First byte on page which contains key/data values. */ + int moved; /* Number of pairs moved to new page. */ +{ + register BUFHEAD *bufp; /* Buffer header for ino */ + register u_int16_t *ino; /* Page keys come off of */ + register u_int16_t *np; /* New page */ + register u_int16_t *op; /* Page keys go on to if they aren't moving */ + + BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */ + DBT key, val; + SPLIT_RETURN ret; + u_int16_t n, off, ov_addr, scopyto; + char *cino; /* Character value of ino */ + + bufp = old_bufp; + ino = (u_int16_t *)old_bufp->page; + np = (u_int16_t *)new_bufp->page; + op = (u_int16_t *)old_bufp->page; + last_bfp = NULL; + scopyto = (u_int16_t)copyto; /* ANSI */ + + n = ino[0] - 1; + while (n < ino[0]) { + if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) { + if (__big_split(hashp, old_bufp, + new_bufp, bufp, bufp->addr, obucket, &ret)) + return (-1); + old_bufp = ret.oldp; + if (!old_bufp) + return (-1); + op = (u_int16_t *)old_bufp->page; + new_bufp = ret.newp; + if (!new_bufp) + return (-1); + np = (u_int16_t *)new_bufp->page; + bufp = ret.nextp; + if (!bufp) + return (0); + cino = (char *)bufp->page; + ino = (u_int16_t *)cino; + last_bfp = ret.nextp; + } else if (ino[n + 1] == OVFLPAGE) { + ov_addr = ino[n]; + /* + * Fix up the old page -- the extra 2 are the fields + * which contained the overflow information. + */ + ino[0] -= (moved + 2); + FREESPACE(ino) = + scopyto - sizeof(u_int16_t) * (ino[0] + 3); + OFFSET(ino) = scopyto; + + bufp = __get_buf(hashp, ov_addr, bufp, 0); + if (!bufp) + return (-1); + + ino = (u_int16_t *)bufp->page; + n = 1; + scopyto = hashp->BSIZE; + moved = 0; + + if (last_bfp) + __free_ovflpage(hashp, last_bfp); + last_bfp = bufp; + } + /* Move regular sized pairs of there are any */ + off = hashp->BSIZE; + for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) { + cino = (char *)ino; + key.data = (u_char *)cino + ino[n]; + key.size = off - ino[n]; + val.data = (u_char *)cino + ino[n + 1]; + val.size = ino[n] - ino[n + 1]; + off = ino[n + 1]; + + if (__call_hash(hashp, key.data, key.size) == obucket) { + /* Keep on old page */ + if (PAIRFITS(op, (&key), (&val))) + putpair((char *)op, &key, &val); + else { + old_bufp = + __add_ovflpage(hashp, old_bufp); + if (!old_bufp) + return (-1); + op = (u_int16_t *)old_bufp->page; + putpair((char *)op, &key, &val); + } + old_bufp->flags |= BUF_MOD; + } else { + /* Move to new page */ + if (PAIRFITS(np, (&key), (&val))) + putpair((char *)np, &key, &val); + else { + new_bufp = + __add_ovflpage(hashp, new_bufp); + if (!new_bufp) + return (-1); + np = (u_int16_t *)new_bufp->page; + putpair((char *)np, &key, &val); + } + new_bufp->flags |= BUF_MOD; + } + } + } + if (last_bfp) + __free_ovflpage(hashp, last_bfp); + return (0); +} + +/* + * Add the given pair to the page + * + * Returns: + * 0 ==> OK + * 1 ==> failure + */ +extern int +__addel(hashp, bufp, key, val) + HTAB *hashp; + BUFHEAD *bufp; + const DBT *key, *val; +{ + register u_int16_t *bp, *sop; + int do_expand; + + bp = (u_int16_t *)bufp->page; + do_expand = 0; + while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY)) + /* Exception case */ + if (bp[2] == FULL_KEY_DATA && bp[0] == 2) + /* This is the last page of a big key/data pair + and we need to add another page */ + break; + else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) { + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + } else + /* Try to squeeze key on this page */ + if (FREESPACE(bp) > PAIRSIZE(key, val)) { + squeeze_key(bp, key, val); + return (0); + } else { + bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); + if (!bufp) + return (-1); + bp = (u_int16_t *)bufp->page; + } + + if (PAIRFITS(bp, key, val)) + putpair(bufp->page, key, val); + else { + do_expand = 1; + bufp = __add_ovflpage(hashp, bufp); + if (!bufp) + return (-1); + sop = (u_int16_t *)bufp->page; + + if (PAIRFITS(sop, key, val)) + putpair((char *)sop, key, val); + else + if (__big_insert(hashp, bufp, key, val)) + return (-1); + } + bufp->flags |= BUF_MOD; + /* + * If the average number of keys per bucket exceeds the fill factor, + * expand the table. + */ + hashp->NKEYS++; + if (do_expand || + (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR)) + return (__expand_table(hashp)); + return (0); +} + +/* + * + * Returns: + * pointer on success + * NULL on error + */ +extern BUFHEAD * +__add_ovflpage(hashp, bufp) + HTAB *hashp; + BUFHEAD *bufp; +{ + register u_int16_t *sp; + u_int16_t ndx, ovfl_num; +#ifdef DEBUG1 + int tmp1, tmp2; +#endif + sp = (u_int16_t *)bufp->page; + + /* Check if we are dynamically determining the fill factor */ + if (hashp->FFACTOR == DEF_FFACTOR) { + hashp->FFACTOR = sp[0] >> 1; + if (hashp->FFACTOR < MIN_FFACTOR) + hashp->FFACTOR = MIN_FFACTOR; + } + bufp->flags |= BUF_MOD; + ovfl_num = overflow_page(hashp); +#ifdef DEBUG1 + tmp1 = bufp->addr; + tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0; +#endif + if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1))) + return (NULL); + bufp->ovfl->flags |= BUF_MOD; +#ifdef DEBUG1 + (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n", + tmp1, tmp2, bufp->ovfl->addr); +#endif + ndx = sp[0]; + /* + * Since a pair is allocated on a page only if there's room to add + * an overflow page, we know that the OVFL information will fit on + * the page. + */ + sp[ndx + 4] = OFFSET(sp); + sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE; + sp[ndx + 1] = ovfl_num; + sp[ndx + 2] = OVFLPAGE; + sp[0] = ndx + 2; +#ifdef HASH_STATISTICS + hash_overflows++; +#endif + return (bufp->ovfl); +} + +/* + * Returns: + * 0 indicates SUCCESS + * -1 indicates FAILURE + */ +extern int +__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap) + HTAB *hashp; + char *p; + u_int32_t bucket; + int is_bucket, is_disk, is_bitmap; +{ + register int fd, page, size; + int rsize; + u_int16_t *bp; + + fd = hashp->fp; + size = hashp->BSIZE; + + if ((fd == -1) || !is_disk) { + PAGE_INIT(p); + return (0); + } + if (is_bucket) + page = BUCKET_TO_PAGE(bucket); + else + page = OADDR_TO_PAGE(bucket); + if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || + ((rsize = read(fd, p, size)) == -1)) + return (-1); + bp = (u_int16_t *)p; + if (!rsize) + bp[0] = 0; /* We hit the EOF, so initialize a new page */ + else + if (rsize != size) { + errno = EFTYPE; + return (-1); + } + if (!is_bitmap && !bp[0]) { + PAGE_INIT(p); + } else + if (hashp->LORDER != BYTE_ORDER) { + register int i, max; + + if (is_bitmap) { + max = hashp->BSIZE >> 2; /* divide by 4 */ + for (i = 0; i < max; i++) + M_32_SWAP(((int *)p)[i]); + } else { + M_16_SWAP(bp[0]); + max = bp[0] + 2; + for (i = 1; i <= max; i++) + M_16_SWAP(bp[i]); + } + } + return (0); +} + +/* + * Write page p to disk + * + * Returns: + * 0 ==> OK + * -1 ==>failure + */ +extern int +__put_page(hashp, p, bucket, is_bucket, is_bitmap) + HTAB *hashp; + char *p; + u_int32_t bucket; + int is_bucket, is_bitmap; +{ + register int fd, page, size; + int wsize; + + size = hashp->BSIZE; + if ((hashp->fp == -1) && open_temp(hashp)) + return (-1); + fd = hashp->fp; + + if (hashp->LORDER != BYTE_ORDER) { + register int i; + register int max; + + if (is_bitmap) { + max = hashp->BSIZE >> 2; /* divide by 4 */ + for (i = 0; i < max; i++) + M_32_SWAP(((int *)p)[i]); + } else { + max = ((u_int16_t *)p)[0] + 2; + for (i = 0; i <= max; i++) + M_16_SWAP(((u_int16_t *)p)[i]); + } + } + if (is_bucket) + page = BUCKET_TO_PAGE(bucket); + else + page = OADDR_TO_PAGE(bucket); + if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || + ((wsize = write(fd, p, size)) == -1)) + /* Errno is set */ + return (-1); + if (wsize != size) { + errno = EFTYPE; + return (-1); + } + return (0); +} + +#define BYTE_MASK ((1 << INT_BYTE_SHIFT) -1) +/* + * Initialize a new bitmap page. Bitmap pages are left in memory + * once they are read in. + */ +extern int +__ibitmap(hashp, pnum, nbits, ndx) + HTAB *hashp; + int pnum, nbits, ndx; +{ + u_int32_t *ip; + int clearbytes, clearints; + + if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) + return (1); + hashp->nmaps++; + clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1; + clearbytes = clearints << INT_TO_BYTE; + (void)memset((char *)ip, 0, clearbytes); + (void)memset(((char *)ip) + clearbytes, 0xFF, + hashp->BSIZE - clearbytes); + ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK); + SETBIT(ip, 0); + hashp->BITMAPS[ndx] = (u_int16_t)pnum; + hashp->mapp[ndx] = ip; + return (0); +} + +static u_int32_t +first_free(map) + u_int32_t map; +{ + register u_int32_t i, mask; + + mask = 0x1; + for (i = 0; i < BITS_PER_MAP; i++) { + if (!(mask & map)) + return (i); + mask = mask << 1; + } + return (i); +} + +static u_int16_t +overflow_page(hashp) + HTAB *hashp; +{ + register u_int32_t *freep; + register int max_free, offset, splitnum; + u_int16_t addr; + int bit, first_page, free_bit, free_page, i, in_use_bits, j; +#ifdef DEBUG2 + int tmp1, tmp2; +#endif + splitnum = hashp->OVFL_POINT; + max_free = hashp->SPARES[splitnum]; + + free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT); + free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1); + + /* Look through all the free maps to find the first free block */ + first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT); + for ( i = first_page; i <= free_page; i++ ) { + if (!(freep = (u_int32_t *)hashp->mapp[i]) && + !(freep = fetch_bitmap(hashp, i))) + return (0); + if (i == free_page) + in_use_bits = free_bit; + else + in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1; + + if (i == first_page) { + bit = hashp->LAST_FREED & + ((hashp->BSIZE << BYTE_SHIFT) - 1); + j = bit / BITS_PER_MAP; + bit = bit & ~(BITS_PER_MAP - 1); + } else { + bit = 0; + j = 0; + } + for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP) + if (freep[j] != ALL_SET) + goto found; + } + + /* No Free Page Found */ + hashp->LAST_FREED = hashp->SPARES[splitnum]; + hashp->SPARES[splitnum]++; + offset = hashp->SPARES[splitnum] - + (splitnum ? hashp->SPARES[splitnum - 1] : 0); + +#define OVMSG "HASH: Out of overflow pages. Increase page size\n" + if (offset > SPLITMASK) { + if (++splitnum >= NCACHED) { + (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + return (0); + } + hashp->OVFL_POINT = splitnum; + hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; + hashp->SPARES[splitnum-1]--; + offset = 1; + } + + /* Check if we need to allocate a new bitmap page */ + if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) { + free_page++; + if (free_page >= NCACHED) { + (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + return (0); + } + /* + * This is tricky. The 1 indicates that you want the new page + * allocated with 1 clear bit. Actually, you are going to + * allocate 2 pages from this map. The first is going to be + * the map page, the second is the overflow page we were + * looking for. The init_bitmap routine automatically, sets + * the first bit of itself to indicate that the bitmap itself + * is in use. We would explicitly set the second bit, but + * don't have to if we tell init_bitmap not to leave it clear + * in the first place. + */ + if (__ibitmap(hashp, + (int)OADDR_OF(splitnum, offset), 1, free_page)) + return (0); + hashp->SPARES[splitnum]++; +#ifdef DEBUG2 + free_bit = 2; +#endif + offset++; + if (offset > SPLITMASK) { + if (++splitnum >= NCACHED) { + (void)write(STDERR_FILENO, OVMSG, + sizeof(OVMSG) - 1); + return (0); + } + hashp->OVFL_POINT = splitnum; + hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; + hashp->SPARES[splitnum-1]--; + offset = 0; + } + } else { + /* + * Free_bit addresses the last used bit. Bump it to address + * the first available bit. + */ + free_bit++; + SETBIT(freep, free_bit); + } + + /* Calculate address of the new overflow page */ + addr = OADDR_OF(splitnum, offset); +#ifdef DEBUG2 + (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", + addr, free_bit, free_page); +#endif + return (addr); + +found: + bit = bit + first_free(freep[j]); + SETBIT(freep, bit); +#ifdef DEBUG2 + tmp1 = bit; + tmp2 = i; +#endif + /* + * Bits are addressed starting with 0, but overflow pages are addressed + * beginning at 1. Bit is a bit addressnumber, so we need to increment + * it to convert it to a page number. + */ + bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT)); + if (bit >= hashp->LAST_FREED) + hashp->LAST_FREED = bit - 1; + + /* Calculate the split number for this page */ + for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++); + offset = (i ? bit - hashp->SPARES[i - 1] : bit); + if (offset >= SPLITMASK) + return (0); /* Out of overflow pages */ + addr = OADDR_OF(i, offset); +#ifdef DEBUG2 + (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", + addr, tmp1, tmp2); +#endif + + /* Allocate and return the overflow page */ + return (addr); +} + +/* + * Mark this overflow page as free. + */ +extern void +__free_ovflpage(hashp, obufp) + HTAB *hashp; + BUFHEAD *obufp; +{ + register u_int16_t addr; + u_int32_t *freep; + int bit_address, free_page, free_bit; + u_int16_t ndx; + + addr = obufp->addr; +#ifdef DEBUG1 + (void)fprintf(stderr, "Freeing %d\n", addr); +#endif + ndx = (((u_int16_t)addr) >> SPLITSHIFT); + bit_address = + (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1; + if (bit_address < hashp->LAST_FREED) + hashp->LAST_FREED = bit_address; + free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT)); + free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1); + + if (!(freep = hashp->mapp[free_page])) + freep = fetch_bitmap(hashp, free_page); +#ifdef DEBUG + /* + * This had better never happen. It means we tried to read a bitmap + * that has already had overflow pages allocated off it, and we + * failed to read it from the file. + */ + if (!freep) + assert(0); +#endif + CLRBIT(freep, free_bit); +#ifdef DEBUG2 + (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n", + obufp->addr, free_bit, free_page); +#endif + __reclaim_buf(hashp, obufp); +} + +/* + * Returns: + * 0 success + * -1 failure + */ +static int +open_temp(hashp) + HTAB *hashp; +{ + sigset_t set, oset; + static char namestr[] = "_hashXXXXXX"; + + /* Block signals; make sure file goes away at process exit. */ + (void)sigfillset(&set); + (void)sigprocmask(SIG_BLOCK, &set, &oset); + if ((hashp->fp = mkstemp(namestr)) != -1) { + (void)unlink(namestr); + (void)fcntl(hashp->fp, F_SETFD, 1); + } + (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL); + return (hashp->fp != -1 ? 0 : -1); +} + +/* + * We have to know that the key will fit, but the last entry on the page is + * an overflow pair, so we need to shift things. + */ +static void +squeeze_key(sp, key, val) + u_int16_t *sp; + const DBT *key, *val; +{ + register char *p; + u_int16_t free_space, n, off, pageno; + + p = (char *)sp; + n = sp[0]; + free_space = FREESPACE(sp); + off = OFFSET(sp); + + pageno = sp[n - 1]; + off -= key->size; + sp[n - 1] = off; + memmove(p + off, key->data, key->size); + off -= val->size; + sp[n] = off; + memmove(p + off, val->data, val->size); + sp[0] = n + 2; + sp[n + 1] = pageno; + sp[n + 2] = OVFLPAGE; + FREESPACE(sp) = free_space - PAIRSIZE(key, val); + OFFSET(sp) = off; +} + +static u_int32_t * +fetch_bitmap(hashp, ndx) + HTAB *hashp; + int ndx; +{ + if (ndx >= hashp->nmaps) + return (NULL); + if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) + return (NULL); + if (__get_page(hashp, + (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) { + free(hashp->mapp[ndx]); + return (NULL); + } + return (hashp->mapp[ndx]); +} + +#ifdef DEBUG4 +int +print_chain(addr) + int addr; +{ + BUFHEAD *bufp; + short *bp, oaddr; + + (void)fprintf(stderr, "%d ", addr); + bufp = __get_buf(hashp, addr, NULL, 0); + bp = (short *)bufp->page; + while (bp[0] && ((bp[bp[0]] == OVFLPAGE) || + ((bp[0] > 2) && bp[2] < REAL_KEY))) { + oaddr = bp[bp[0] - 1]; + (void)fprintf(stderr, "%d ", (int)oaddr); + bufp = __get_buf(hashp, (int)oaddr, bufp, 0); + bp = (short *)bufp->page; + } + (void)fprintf(stderr, "\n"); +} +#endif diff --git a/src/util/berk_db/hash/hsearch.c b/src/util/berk_db/hash/hsearch.c new file mode 100644 index 000000000..cc8f7a4aa --- /dev/null +++ b/src/util/berk_db/hash/hsearch.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hsearch.c 8.4 (Berkeley) 7/21/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include + +#include +#include "search.h" + +static DB *dbp = NULL; +static ENTRY retval; + +extern int +hcreate(nel) + u_int nel; +{ + HASHINFO info; + + info.nelem = nel; + info.bsize = 256; + info.ffactor = 8; + info.cachesize = 0; + info.hash = NULL; + info.lorder = 0; + dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0); + return ((int)dbp); +} + +extern ENTRY * +hsearch(item, action) + ENTRY item; + ACTION action; +{ + DBT key, val; + int status; + + if (!dbp) + return (NULL); + key.data = (u_char *)item.key; + key.size = strlen(item.key) + 1; + + if (action == ENTER) { + val.data = (u_char *)item.data; + val.size = strlen(item.data) + 1; + status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE); + if (status) + return (NULL); + } else { + /* FIND */ + status = (dbp->get)(dbp, &key, &val, 0); + if (status) + return (NULL); + else + item.data = (char *)val.data; + } + retval.key = item.key; + retval.data = item.data; + return (&retval); +} + +extern void +hdestroy() +{ + if (dbp) { + (void)(dbp->close)(dbp); + dbp = NULL; + } +} diff --git a/src/util/berk_db/hash/krb5_ndbm.c b/src/util/berk_db/hash/krb5_ndbm.c new file mode 100644 index 000000000..7baa0321c --- /dev/null +++ b/src/util/berk_db/hash/krb5_ndbm.c @@ -0,0 +1,245 @@ +/* + * util/berk_db/krb5_ndbm.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * krb5_ndbm.c - Customize the dbm wrapper for Kerberos. + */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * This package provides a dbm compatible interface to the new hashing + * package described in db(3). + */ + +#include + +#include +#include + +#include +#include "hash.h" + +/* + * For Kerberos, we make some generalizations about kdb records. We assume + * that records are on average KRB5_DBENT_ASIZE in length. + * + * Increasing KRB5_DB_BUCKETSIZE doesn't get you much of anything. + */ +#define KRB5_DB_BUCKETSIZE 1024 +#define KRB5_DBENT_ASIZE 512 +#define KRB5_DB_MINBUCKET 512 +#define KRB5_DB_INITSIZE 128 + +/* + * Returns: + * *DBM on success + * NULL on failure + */ +extern DBM * +db_dbm_open(file, flags, mode) + const char *file; + int flags, mode; +{ + HASHINFO info; + char path[MAXPATHLEN]; + + info.bsize = KRB5_DB_BUCKETSIZE; + /* + * if (info.bsize < KRB5_DB_MINBUCKET) info.bsize = KRB5_DB_MINBUCKET; + */ + info.ffactor = info.bsize / KRB5_DBENT_ASIZE; + info.nelem = KRB5_DB_INITSIZE; + info.cachesize = 0; + info.hash = NULL; + /* Always store databases in big endian (e.g. network order) */ + info.lorder = BIG_ENDIAN; + (void)strcpy(path, file); + (void)strcat(path, DBM_SUFFIX); + return ((DBM *)__hash_open(path, flags, mode, &info, 0)); +} + +extern void +db_dbm_close(db) + DBM *db; +{ + (void)(db->close)(db); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +extern datum +db_dbm_fetch(db, key) + DBM *db; + datum key; +{ + datum retval; + int status; + + status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); + if (status) { + retval.dptr = NULL; + retval.dsize = 0; + } + return (retval); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +extern datum +db_dbm_firstkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +extern datum +db_dbm_nextkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + return (retkey); +} +/* + * Returns: + * 0 on success + * <0 failure + */ +extern int +db_dbm_delete(db, key) + DBM *db; + datum key; +{ + int status; + + status = (db->del)(db, (DBT *)&key, 0); + if (status) + return (-1); + else + return (0); +} + +/* + * Returns: + * 0 on success + * <0 failure + * 1 if DBM_INSERT and entry exists + */ +extern int +db_dbm_store(db, key, content, flags) + DBM *db; + datum key, content; + int flags; +{ + return ((db->put)(db, (DBT *)&key, (DBT *)&content, + (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); +} + +extern int +db_dbm_error(db) + DBM *db; +{ + HTAB *hp; + + hp = (HTAB *)db->internal; + return (hp->errno); +} + +extern int +db_dbm_clearerr(db) + DBM *db; +{ + HTAB *hp; + + hp = (HTAB *)db->internal; + hp->errno = 0; + return (0); +} + +extern int +db_dbm_dirfno(db) + DBM *db; +{ + return(((HTAB *)db->internal)->fp); +} diff --git a/src/util/berk_db/hash/ndbm.c b/src/util/berk_db/hash/ndbm.c new file mode 100644 index 000000000..2cbbe9136 --- /dev/null +++ b/src/util/berk_db/hash/ndbm.c @@ -0,0 +1,202 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * This package provides a dbm compatible interface to the new hashing + * package described in db(3). + */ + +#include + +#include +#include + +#include +#include "hash.h" + +/* + * Returns: + * *DBM on success + * NULL on failure + */ +extern DBM * +dbm_open(file, flags, mode) + const char *file; + int flags, mode; +{ + HASHINFO info; + char path[MAXPATHLEN]; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = 0; + info.hash = NULL; + info.lorder = 0; + (void)strcpy(path, file); + (void)strcat(path, DBM_SUFFIX); + return ((DBM *)__hash_open(path, flags, mode, &info, 0)); +} + +extern void +dbm_close(db) + DBM *db; +{ + (void)(db->close)(db); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +extern datum +dbm_fetch(db, key) + DBM *db; + datum key; +{ + datum retval; + int status; + + status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); + if (status) { + retval.dptr = NULL; + retval.dsize = 0; + } + return (retval); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +extern datum +dbm_firstkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +extern datum +dbm_nextkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + return (retkey); +} +/* + * Returns: + * 0 on success + * <0 failure + */ +extern int +dbm_delete(db, key) + DBM *db; + datum key; +{ + int status; + + status = (db->del)(db, (DBT *)&key, 0); + if (status) + return (-1); + else + return (0); +} + +/* + * Returns: + * 0 on success + * <0 failure + * 1 if DBM_INSERT and entry exists + */ +extern int +dbm_store(db, key, content, flags) + DBM *db; + datum key, content; + int flags; +{ + return ((db->put)(db, (DBT *)&key, (DBT *)&content, + (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); +} + +extern int +dbm_error(db) + DBM *db; +{ + HTAB *hp; + + hp = (HTAB *)db->internal; + return (hp->errno); +} + +extern int +dbm_clearerr(db) + DBM *db; +{ + HTAB *hp; + + hp = (HTAB *)db->internal; + hp->errno = 0; + return (0); +} + +extern int +dbm_dirfno(db) + DBM *db; +{ + return(((HTAB *)db->internal)->fp); +} diff --git a/src/util/berk_db/hash/page.h b/src/util/berk_db/hash/page.h new file mode 100644 index 000000000..0fc0d5a3e --- /dev/null +++ b/src/util/berk_db/hash/page.h @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)page.h 8.2 (Berkeley) 5/31/94 + */ + +/* + * Definitions for hashing page file format. + */ + +/* + * routines dealing with a data page + * + * page format: + * +------------------------------+ + * p | n | keyoff | datoff | keyoff | + * +------------+--------+--------+ + * | datoff | free | ptr | --> | + * +--------+---------------------+ + * | F R E E A R E A | + * +--------------+---------------+ + * | <---- - - - | data | + * +--------+-----+----+----------+ + * | key | data | key | + * +--------+----------+----------+ + * + * Pointer to the free space is always: p[p[0] + 2] + * Amount of free space on the page is: p[p[0] + 1] + */ + +/* + * How many bytes required for this pair? + * 2 shorts in the table at the top of the page + room for the + * key and room for the data + * + * We prohibit entering a pair on a page unless there is also room to append + * an overflow page. The reason for this it that you can get in a situation + * where a single key/data pair fits on a page, but you can't append an + * overflow page and later you'd have to split the key/data and handle like + * a big pair. + * You might as well do this up front. + */ + +#define PAIRSIZE(K,D) (2*sizeof(u_int16_t) + (K)->size + (D)->size) +#define BIGOVERHEAD (4*sizeof(u_int16_t)) +#define KEYSIZE(K) (4*sizeof(u_int16_t) + (K)->size); +#define OVFLSIZE (2*sizeof(u_int16_t)) +#define FREESPACE(P) ((P)[(P)[0]+1]) +#define OFFSET(P) ((P)[(P)[0]+2]) +#define PAIRFITS(P,K,D) \ + (((P)[2] >= REAL_KEY) && \ + (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P))) +#define PAGE_META(N) (((N)+3) * sizeof(u_int16_t)) + +typedef struct { + BUFHEAD *newp; + BUFHEAD *oldp; + BUFHEAD *nextp; + u_int16_t next_addr; +} SPLIT_RETURN; diff --git a/src/util/berk_db/hash/search.h b/src/util/berk_db/hash/search.h new file mode 100644 index 000000000..4d3b9143e --- /dev/null +++ b/src/util/berk_db/hash/search.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)search.h 8.1 (Berkeley) 6/4/93 + */ + +/* Backward compatibility to hsearch interface. */ +typedef struct entry { + char *key; + char *data; +} ENTRY; + +typedef enum { + FIND, ENTER +} ACTION; + +int hcreate __P((unsigned int)); +void hdestroy __P((void)); +ENTRY *hsearch __P((ENTRY, ACTION)); diff --git a/src/util/berk_db/include/.Sanitize b/src/util/berk_db/include/.Sanitize new file mode 100644 index 000000000..1768af442 --- /dev/null +++ b/src/util/berk_db/include/.Sanitize @@ -0,0 +1,33 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +db.h +mpool.h + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/include/db.h b/src/util/berk_db/include/db.h new file mode 100644 index 000000000..47044f076 --- /dev/null +++ b/src/util/berk_db/include/db.h @@ -0,0 +1,239 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)db.h 8.7 (Berkeley) 6/16/94 + */ + +#ifndef _DB_H_ +#define _DB_H_ + +#include +#include + +#include + +#ifdef __DBINTERFACE_PRIVATE +#include +#endif + +#define RET_ERROR -1 /* Return values. */ +#define RET_SUCCESS 0 +#define RET_SPECIAL 1 + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ +typedef __signed char int8_t; +typedef unsigned char u_int8_t; +typedef short int16_t; +typedef unsigned short u_int16_t; +typedef int int32_t; +typedef unsigned int u_int32_t; +#ifdef WE_DONT_NEED_QUADS +typedef long long int64_t; +typedef unsigned long long u_int64_t; +#endif +#endif + +#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */ +typedef u_int32_t pgno_t; +#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */ +typedef u_int16_t indx_t; +#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */ +typedef u_int32_t recno_t; + +/* Key/data structure -- a Data-Base Thang. */ +typedef struct { + void *data; /* data */ + size_t size; /* data length */ +} DBT; + +/* Routine flags. */ +#define R_CURSOR 1 /* del, put, seq */ +#define __R_UNUSED 2 /* UNUSED */ +#define R_FIRST 3 /* seq */ +#define R_IAFTER 4 /* put (RECNO) */ +#define R_IBEFORE 5 /* put (RECNO) */ +#define R_LAST 6 /* seq (BTREE, RECNO) */ +#define R_NEXT 7 /* seq */ +#define R_NOOVERWRITE 8 /* put */ +#define R_PREV 9 /* seq (BTREE, RECNO) */ +#define R_SETCURSOR 10 /* put (RECNO) */ +#define R_RECNOSYNC 11 /* sync (RECNO) */ + +typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; + +/* + * !!! + * The following flags are included in the dbopen(3) call as part of the + * open(2) flags. In order to avoid conflicts with the open flags, start + * at the top of the 16 or 32-bit number space and work our way down. If + * the open flags were significantly expanded in the future, it could be + * a problem. Wish I'd left another flags word in the dbopen call. + * + * !!! + * None of this stuff is implemented yet. The only reason that it's here + * is so that the access methods can skip copying the key/data pair when + * the DB_LOCK flag isn't set. + */ +/* + * Kerberos: This used to be #if UINT_MAX > 65535, but Ultrix gags on this. + */ +#if SIZEOF_INT > 2 +#define DB_LOCK 0x20000000 /* Do locking. */ +#define DB_SHMEM 0x40000000 /* Use shared memory. */ +#define DB_TXN 0x80000000 /* Do transactions. */ +#else +#define DB_LOCK 0x2000 /* Do locking. */ +#define DB_SHMEM 0x4000 /* Use shared memory. */ +#define DB_TXN 0x8000 /* Do transactions. */ +#endif + +/* Access method description structure. */ +typedef struct __db { + DBTYPE type; /* Underlying db type. */ + int (*close) __P((struct __db *)); + int (*del) __P((const struct __db *, const DBT *, u_int)); + int (*get) __P((const struct __db *, const DBT *, DBT *, u_int)); + int (*put) __P((const struct __db *, DBT *, const DBT *, u_int)); + int (*seq) __P((const struct __db *, DBT *, DBT *, u_int)); + int (*sync) __P((const struct __db *, u_int)); + void *internal; /* Access method private. */ + int (*fd) __P((const struct __db *)); +} DB; + +#define BTREEMAGIC 0x053162 +#define BTREEVERSION 3 + +/* Structure used to pass parameters to the btree routines. */ +typedef struct { +#define R_DUP 0x01 /* duplicate keys */ + u_long flags; + u_int cachesize; /* bytes to cache */ + int maxkeypage; /* maximum keys per page */ + int minkeypage; /* minimum keys per page */ + u_int psize; /* page size */ + int (*compare) /* comparison function */ + __P((const DBT *, const DBT *)); + size_t (*prefix) /* prefix function */ + __P((const DBT *, const DBT *)); + int lorder; /* byte order */ +} BTREEINFO; + +#define HASHMAGIC 0x061561 +#define HASHVERSION 2 + +/* Structure used to pass parameters to the hashing routines. */ +typedef struct { + u_int bsize; /* bucket size */ + u_int ffactor; /* fill factor */ + u_int nelem; /* number of elements */ + u_int cachesize; /* bytes to cache */ + u_int32_t /* hash function */ + (*hash) __P((const void *, size_t)); + int lorder; /* byte order */ +} HASHINFO; + +/* Structure used to pass parameters to the record routines. */ +typedef struct { +#define R_FIXEDLEN 0x01 /* fixed-length records */ +#define R_NOKEY 0x02 /* key not required */ +#define R_SNAPSHOT 0x04 /* snapshot the input */ + u_long flags; + u_int cachesize; /* bytes to cache */ + u_int psize; /* page size */ + int lorder; /* byte order */ + size_t reclen; /* record length (fixed-length records) */ + u_char bval; /* delimiting byte (variable-length records */ + char *bfname; /* btree file name */ +} RECNOINFO; + +#ifdef __DBINTERFACE_PRIVATE +/* + * Little endian <==> big endian 32-bit swap macros. + * M_32_SWAP swap a memory location + * P_32_SWAP swap a referenced memory location + * P_32_COPY swap from one location to another + */ +#define M_32_SWAP(a) { \ + u_int32_t _tmp = a; \ + ((char *)&a)[0] = ((char *)&_tmp)[3]; \ + ((char *)&a)[1] = ((char *)&_tmp)[2]; \ + ((char *)&a)[2] = ((char *)&_tmp)[1]; \ + ((char *)&a)[3] = ((char *)&_tmp)[0]; \ +} +#define P_32_SWAP(a) { \ + u_int32_t _tmp = *(u_int32_t *)a; \ + ((char *)a)[0] = ((char *)&_tmp)[3]; \ + ((char *)a)[1] = ((char *)&_tmp)[2]; \ + ((char *)a)[2] = ((char *)&_tmp)[1]; \ + ((char *)a)[3] = ((char *)&_tmp)[0]; \ +} +#define P_32_COPY(a, b) { \ + ((char *)&(b))[0] = ((char *)&(a))[3]; \ + ((char *)&(b))[1] = ((char *)&(a))[2]; \ + ((char *)&(b))[2] = ((char *)&(a))[1]; \ + ((char *)&(b))[3] = ((char *)&(a))[0]; \ +} + +/* + * Little endian <==> big endian 16-bit swap macros. + * M_16_SWAP swap a memory location + * P_16_SWAP swap a referenced memory location + * P_16_COPY swap from one location to another + */ +#define M_16_SWAP(a) { \ + u_int16_t _tmp = a; \ + ((char *)&a)[0] = ((char *)&_tmp)[1]; \ + ((char *)&a)[1] = ((char *)&_tmp)[0]; \ +} +#define P_16_SWAP(a) { \ + u_int16_t _tmp = *(u_int16_t *)a; \ + ((char *)a)[0] = ((char *)&_tmp)[1]; \ + ((char *)a)[1] = ((char *)&_tmp)[0]; \ +} +#define P_16_COPY(a, b) { \ + ((char *)&(b))[0] = ((char *)&(a))[1]; \ + ((char *)&(b))[1] = ((char *)&(a))[0]; \ +} +#endif + +__BEGIN_DECLS +DB *dbopen __P((const char *, int, int, DBTYPE, const void *)); + +#ifdef __DBINTERFACE_PRIVATE +DB *__bt_open __P((const char *, int, int, const BTREEINFO *, int)); +DB *__hash_open __P((const char *, int, int, const HASHINFO *, int)); +DB *__rec_open __P((const char *, int, int, const RECNOINFO *, int)); +void __dbpanic __P((DB *dbp)); +#endif +__END_DECLS +#endif /* !_DB_H_ */ diff --git a/src/util/berk_db/include/mpool.h b/src/util/berk_db/include/mpool.h new file mode 100644 index 000000000..40d102230 --- /dev/null +++ b/src/util/berk_db/include/mpool.h @@ -0,0 +1,99 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + */ + +#include + +/* + * The memory pool scheme is a simple one. Each in-memory page is referenced + * by a bucket which is threaded in up to two of three ways. All active pages + * are threaded on a hash chain (hashed by page number) and an lru chain. + * Inactive pages are threaded on a free chain. Each reference to a memory + * pool is handed an opaque MPOOL cookie which stores all of this information. + */ +#define HASHSIZE 128 +#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) + +/* The BKT structures are the elements of the queues. */ +typedef struct _bkt { + CIRCLEQ_ENTRY(_bkt) hq; /* hash queue */ + CIRCLEQ_ENTRY(_bkt) q; /* lru queue */ + void *page; /* page */ + pgno_t pgno; /* page number */ + +#define MPOOL_DIRTY 0x01 /* page needs to be written */ +#define MPOOL_PINNED 0x02 /* page is pinned into memory */ + u_int8_t flags; /* flags */ +} BKT; + +typedef struct MPOOL { + CIRCLEQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */ + /* hash queue array */ + CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE]; + pgno_t curcache; /* current number of cached pages */ + pgno_t maxcache; /* max number of cached pages */ + pgno_t npages; /* number of pages in the file */ + u_long pagesize; /* file page size */ + int fd; /* file descriptor */ + /* page in conversion routine */ + void (*pgin) __P((void *, pgno_t, void *)); + /* page out conversion routine */ + void (*pgout) __P((void *, pgno_t, void *)); + void *pgcookie; /* cookie for page in/out routines */ +#ifdef STATISTICS + u_long cachehit; + u_long cachemiss; + u_long pagealloc; + u_long pageflush; + u_long pageget; + u_long pagenew; + u_long pageput; + u_long pageread; + u_long pagewrite; +#endif +} MPOOL; + +__BEGIN_DECLS +MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); +void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), + void (*)(void *, pgno_t, void *), void *)); +void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_put __P((MPOOL *, void *, u_int)); +int mpool_sync __P((MPOOL *)); +int mpool_close __P((MPOOL *)); +#ifdef STATISTICS +void mpool_stat __P((MPOOL *)); +#endif +__END_DECLS diff --git a/src/util/berk_db/man/.Sanitize b/src/util/berk_db/man/.Sanitize new file mode 100644 index 000000000..7db6c8c51 --- /dev/null +++ b/src/util/berk_db/man/.Sanitize @@ -0,0 +1,32 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +hash.3 + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/man/hash.3 b/src/util/berk_db/man/hash.3 new file mode 100644 index 000000000..436703186 --- /dev/null +++ b/src/util/berk_db/man/hash.3 @@ -0,0 +1,159 @@ +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)hash.3 8.6 (Berkeley) 8/18/94 +.\" +.TH HASH 3 "August 18, 1994" +.UC 7 +.SH NAME +hash \- hash database access method +.SH SYNOPSIS +.nf +.ft B +#include +#include +.ft R +.fi +.SH DESCRIPTION +The routine +.IR dbopen +is the library interface to database files. +One of the supported file formats is hash files. +The general description of the database access methods is in +.IR dbopen (3), +this manual page describes only the hash specific information. +.PP +The hash data structure is an extensible, dynamic hashing scheme. +.PP +The access method specific data structure provided to +.I dbopen +is defined in the include file as follows: +.sp +typedef struct { +.RS +u_int bsize; +.br +u_int ffactor; +.br +u_int nelem; +.br +u_int cachesize; +.br +u_int32_t (*hash)(const void *, size_t); +.br +int lorder; +.RE +} HASHINFO; +.PP +The elements of this structure are as follows: +.TP +bsize +.I Bsize +defines the hash table bucket size, and is, by default, 256 bytes. +It may be preferable to increase the page size for disk-resident tables +and tables with large data items. +.TP +ffactor +.I Ffactor +indicates a desired density within the hash table. +It is an approximation of the number of keys allowed to accumulate in any +one bucket, determining when the hash table grows or shrinks. +The default value is 8. +.TP +nelem +.I Nelem +is an estimate of the final size of the hash table. +If not set or set too low, hash tables will expand gracefully as keys +are entered, although a slight performance degradation may be noticed. +The default value is 1. +.TP +cachesize +A suggested maximum size, in bytes, of the memory cache. +This value is +.B only +advisory, and the access method will allocate more memory rather +than fail. +.TP +hash +.I Hash +is a user defined hash function. +Since no hash function performs equally well on all possible data, the +user may find that the built-in hash function does poorly on a particular +data set. +User specified hash functions must take two arguments (a pointer to a byte +string and a length) and return a 32-bit quantity to be used as the hash +value. +.TP +lorder +The byte order for integers in the stored database metadata. +The number should represent the order as an integer; for example, +big endian order would be the number 4,321. +If +.I lorder +is 0 (no order is specified) the current host order is used. +If the file already exists, the specified value is ignored and the +value specified when the tree was created is used. +.PP +If the file already exists (and the O_TRUNC flag is not specified), the +values specified for the parameters bsize, ffactor, lorder and nelem are +ignored and the values specified when the tree was created are used. +.PP +If a hash function is specified, +.I hash_open +will attempt to determine if the hash function specified is the same as +the one with which the database was created, and will fail if it is not. +.PP +Backward compatible interfaces to the routines described in +.IR dbm (3), +and +.IR ndbm (3) +are provided, however these interfaces are not compatible with +previous file formats. +.SH ERRORS +The +.I hash +access method routines may fail and set +.I errno +for any of the errors specified for the library routine +.IR dbopen (3). +.SH "SEE ALSO" +.IR btree (3), +.IR dbopen (3), +.IR mpool (3), +.IR recno (3) +.sp +.IR "Dynamic Hash Tables" , +Per-Ake Larson, Communications of the ACM, April 1988. +.sp +.IR "A New Hash Package for UNIX" , +Margo Seltzer, USENIX Proceedings, Winter 1991. +.SH BUGS +Only big and little endian byte order is supported. diff --git a/src/util/berk_db/test/.Sanitize b/src/util/berk_db/test/.Sanitize new file mode 100644 index 000000000..f90865d7a --- /dev/null +++ b/src/util/berk_db/test/.Sanitize @@ -0,0 +1,39 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +.cvsignore +Makefile.in +README +configure +configure.in +dbtest.c +hash.tests +run.test + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/test/.cvsignore b/src/util/berk_db/test/.cvsignore new file mode 100644 index 000000000..e8c05a6b1 --- /dev/null +++ b/src/util/berk_db/test/.cvsignore @@ -0,0 +1 @@ +configure diff --git a/src/util/berk_db/test/Makefile.in b/src/util/berk_db/test/Makefile.in new file mode 100644 index 000000000..88fbf39d8 --- /dev/null +++ b/src/util/berk_db/test/Makefile.in @@ -0,0 +1,30 @@ +PORTDIR=$(srcdir)/../PORT/krb5 +# @(#)Makefile 8.15 (Berkeley) 7/28/94 + +PROG= dbtest +OBJS= dbtest.o strerror.o + +# Uncomment the STAT line get hash and btree statistical use info. This +# also forces ld to load the btree debug functions for use by gdb, which +# is useful. The db library has to be compiled with -DSTATISTICS as well. +INC= -I${PORTDIR}/include -I${PORTDIR} -I${PORTDIR}/../../include -I${PORTDIR}/../../../include +OORG= -g +#STAT= -DSTATISTICS +CFLAGS= -D__DBINTERFACE_PRIVATE -DDEBUG ${STAT} ${OORG} ${INC} + +dbtest: ${OBJS} ../libdb.a + ${CC} -o $@ ${OBJS} ../libdb.a + +strerror.o: ${PORTDIR}/../clib/strerror.c + ${CC} -c ${PORTDIR}/../clib/strerror.c + +clean:: + rm -f dbtest.core gmon.out ${OBJS} ${PROG} t1 t2 t3 + +${OBJS}: Makefile + +check:: dbtest + /bin/sh $(srcdir)/run.test hash + +all:: + diff --git a/src/util/berk_db/test/README b/src/util/berk_db/test/README new file mode 100644 index 000000000..0c0cd13d8 --- /dev/null +++ b/src/util/berk_db/test/README @@ -0,0 +1,74 @@ +# @(#)README 8.8 (Berkeley) 7/31/94 + +To build this portably, try something like: + + make PORTDIR="../PORT/MACH" + +where MACH is the machine, i.e. "sunos.4.1.1". + +To run the tests, enter "sh run.test". If your system dictionary isn't +in /usr/share/dict/words, edit run.test to reflect the correct place. + +Fairly large files (the command files) are built in this directory during +the test runs, and even larger files (the database files) are created in +"/var/tmp". If the latter directory doesn't exist, set the environmental +variable TMPDIR to a directory where the files can be built. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +The script file consists of lines with an initial character which is +the command for that line, or an initial character indicating a key +or data entry for a previous command. + +Legal command characters are as follows: + +c: compare a record + + must be followed by [kK][dD]; the data value in the database + associated with the specified key is compared to the specified + data value. +e: echo a string + + writes out the rest of the line into the output file; if the + last character is not a carriage-return, a newline is appended. +f: set the flags for the next command + + no value zero's the flags +g: do a get command + + must be followed by [kK] + + writes out the retrieved data DBT. +o [r]: dump [reverse] + + dump the database out, if 'r' is set, in reverse order. +p: do a put command + + must be followed by [kK][dD] +r: do a del command + + must be followed by [kK] unless R_CURSOR flag set. +S: sync the database +s: do a seq command + + must be followed by [kK] if R_CURSOR flag set. + + writes out the retrieved data DBT. + +Legal key/data characters are as follows: + +D [file]: data file + + set the current data value to the contents of the file +d [data]: + + set the current key value to the contents of the line. +K [file]: key file + + set the current key value to the contents of the file +k [data]: + + set the current key value to the contents of the line. + +Blank lines, lines with leading white space, and lines with leading +hash marks (#) are ignored. + +Options to dbtest are as follows: + + -d: Set the DB_LOCK flag. + -f: Use the file argument as the database file. + -i: Use the rest of the argument to set elements in the info + structure. If the type is btree, then "-i cachesize=10240" + will set BTREEINFO.cachesize to 10240. + -o: The rest of the argument is the output file instead of + using stdout. + -s: Don't delete the database file before opening it, i.e. + use the database file from a previous run. + +Dbtest requires two arguments, the type of access "hash", "recno" +or "btree", and the script name or "-" to indicate stdin. diff --git a/src/util/berk_db/test/configure.in b/src/util/berk_db/test/configure.in new file mode 100644 index 000000000..b6f9e017a --- /dev/null +++ b/src/util/berk_db/test/configure.in @@ -0,0 +1,6 @@ +AC_INIT(configure.in) +AC_SET_BUILDTOP +WITH_CCOPTS +WITH_KRB5ROOT +CONFIG_RULES +V5_AC_OUTPUT_MAKEFILE diff --git a/src/util/berk_db/test/dbtest.c b/src/util/berk_db/test/dbtest.c new file mode 100644 index 000000000..3cc0e7772 --- /dev/null +++ b/src/util/berk_db/test/dbtest.c @@ -0,0 +1,759 @@ +/*- + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1992, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)dbtest.c 8.17 (Berkeley) 9/1/94"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA }; + +void compare __P((DBT *, DBT *)); +DBTYPE dbtype __P((char *)); +void dump __P((DB *, int)); +void err __P((const char *, ...)); +void get __P((DB *, DBT *)); +void getdata __P((DB *, DBT *, DBT *)); +void put __P((DB *, DBT *, DBT *)); +void rem __P((DB *, DBT *)); +char *sflags __P((int)); +void synk __P((DB *)); +void *rfile __P((char *, size_t *)); +void seq __P((DB *, DBT *)); +u_int setflags __P((char *)); +void *setinfo __P((DBTYPE, char *)); +void usage __P((void)); +void *xmalloc __P((char *, size_t)); + +DBTYPE type; /* Database type. */ +void *infop; /* Iflags. */ +u_long lineno; /* Current line in test script. */ +u_int flags; /* Current DB flags. */ +int ofd = STDOUT_FILENO; /* Standard output fd. */ + +DB *XXdbp; /* Global for gdb. */ +int XXlineno; /* Fast breakpoint for gdb. */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern int optind; + extern char *optarg; + enum S command, state; + DB *dbp; + DBT data, key, keydata; + size_t len; + int ch, oflags, sflag; + char *fname, *infoarg, *p, *t, buf[8 * 1024]; + + infoarg = NULL; + fname = NULL; + oflags = O_CREAT | O_RDWR; + sflag = 0; + while ((ch = getopt(argc, argv, "f:i:lo:s")) != EOF) + switch (ch) { + case 'f': + fname = optarg; + break; + case 'i': + infoarg = optarg; + break; + case 'l': + oflags |= DB_LOCK; + break; + case 'o': + if ((ofd = open(optarg, + O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) + err("%s: %s", optarg, strerror(errno)); + break; + case 's': + sflag = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 2) + usage(); + + /* Set the type. */ + type = dbtype(*argv++); + + /* Open the descriptor file. */ + if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL) + err("%s: %s", *argv, strerror(errno)); + + /* Set up the db structure as necessary. */ + if (infoarg == NULL) + infop = NULL; + else + for (p = strtok(infoarg, ",\t "); p != NULL; + p = strtok(0, ",\t ")) + if (*p != '\0') + infop = setinfo(type, p); + + /* + * Open the DB. Delete any preexisting copy, you almost never + * want it around, and it often screws up tests. + */ + if (fname == NULL) { + p = getenv("TMPDIR"); + if (p == NULL) + p = "/var/tmp"; + (void)sprintf(buf, "%s/__dbtest", p); + fname = buf; + (void)unlink(buf); + } else if (!sflag) + (void)unlink(fname); + +#ifdef MIT_notdef + if ((dbp = dbopen(fname, + oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL) + err("dbopen: %s", strerror(errno)); +#else /* MIT_notdef */ + if ((dbp = __hash_open(fname, + oflags, S_IRUSR | S_IWUSR, infop, type)) == NULL) + err("dbopen: %s", strerror(errno)); +#endif /* MIT_notdef */ + XXdbp = dbp; + + state = COMMAND; + for (lineno = 1; + (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) { + /* Delete the newline, displaying the key/data is easier. */ + if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL) + *t = '\0'; + if ((len = strlen(buf)) == 0 || isspace(*p) || *p == '#') + continue; + + /* Convenient gdb break point. */ + if (XXlineno == lineno) + XXlineno = 1; + switch (*p) { + case 'c': /* compare */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = COMPARE; + break; + case 'e': /* echo */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + /* Don't display the newline, if CR at EOL. */ + if (p[len - 2] == '\r') + --len; + if (write(ofd, p + 1, len - 1) != len - 1 || + write(ofd, "\n", 1) != 1) + err("write: %s", strerror(errno)); + break; + case 'g': /* get */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = GET; + break; + case 'p': /* put */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = PUT; + break; + case 'r': /* remove */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + if (flags == R_CURSOR) { + rem(dbp, &key); + state = COMMAND; + } else { + state = KEY; + command = REMOVE; + } + break; + case 'S': /* sync */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + synk(dbp); + state = COMMAND; + break; + case 's': /* seq */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + if (flags == R_CURSOR) { + state = KEY; + command = SEQ; + } else + seq(dbp, &key); + break; + case 'f': + flags = setflags(p + 1); + break; + case 'D': /* data file */ + if (state != DATA) + err("line %lu: not expecting data", lineno); + data.data = rfile(p + 1, &data.size); + goto ldata; + case 'd': /* data */ + if (state != DATA) + err("line %lu: not expecting data", lineno); + data.data = xmalloc(p + 1, len - 1); + data.size = len - 1; +ldata: switch (command) { + case COMPARE: + compare(&keydata, &data); + break; + case PUT: + put(dbp, &key, &data); + break; + default: + err("line %lu: command doesn't take data", + lineno); + } + if (type != DB_RECNO) + free(key.data); + free(data.data); + state = COMMAND; + break; + case 'K': /* key file */ + if (state != KEY) + err("line %lu: not expecting a key", lineno); + if (type == DB_RECNO) + err("line %lu: 'K' not available for recno", + lineno); + key.data = rfile(p + 1, &key.size); + goto lkey; + case 'k': /* key */ + if (state != KEY) + err("line %lu: not expecting a key", lineno); + if (type == DB_RECNO) { + static recno_t recno; + recno = atoi(p + 1); + key.data = &recno; + key.size = sizeof(recno); + } else { + key.data = xmalloc(p + 1, len - 1); + key.size = len - 1; + } +lkey: switch (command) { + case COMPARE: + getdata(dbp, &key, &keydata); + state = DATA; + break; + case GET: + get(dbp, &key); + if (type != DB_RECNO) + free(key.data); + state = COMMAND; + break; + case PUT: + state = DATA; + break; + case REMOVE: + rem(dbp, &key); + if ((type != DB_RECNO) && (flags != R_CURSOR)) + free(key.data); + state = COMMAND; + break; + case SEQ: + seq(dbp, &key); + if ((type != DB_RECNO) && (flags != R_CURSOR)) + free(key.data); + state = COMMAND; + break; + default: + err("line %lu: command doesn't take a key", + lineno); + } + break; + case 'o': + dump(dbp, p[1] == 'r'); + break; + default: + err("line %lu: %s: unknown command character", + lineno, p); + } + } +#ifdef STATISTICS + /* + * -l must be used (DB_LOCK must be set) for this to be + * used, otherwise a page will be locked and it will fail. + */ + if (type == DB_BTREE && oflags & DB_LOCK) + __bt_stat(dbp); +#endif + if (dbp->close(dbp)) + err("db->close: %s", strerror(errno)); + (void)close(ofd); + exit(0); +} + +#define NOOVERWRITE "put failed, would overwrite key\n" + +void +compare(db1, db2) + DBT *db1, *db2; +{ + register size_t len; + register u_char *p1, *p2; + + if (db1->size != db2->size) + printf("compare failed: key->data len %lu != data len %lu\n", + db1->size, db2->size); + + len = MIN(db1->size, db2->size); + for (p1 = db1->data, p2 = db2->data; len--;) + if (*p1++ != *p2++) { + printf("compare failed at offset %d\n", + p1 - (u_char *)db1->data); + break; + } +} + +void +get(dbp, kp) + DB *dbp; + DBT *kp; +{ + DBT data; + + switch (dbp->get(dbp, kp, &data, flags)) { + case 0: + (void)write(ofd, data.data, data.size); + if (ofd == STDOUT_FILENO) + (void)write(ofd, "\n", 1); + break; + case -1: + err("line %lu: get: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: +#define NOSUCHKEY "get failed, no such key\n" + if (ofd != STDOUT_FILENO) + (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); + else + (void)fprintf(stderr, "%d: %.*s: %s", + lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); +#undef NOSUCHKEY + break; + } +} + +void +getdata(dbp, kp, dp) + DB *dbp; + DBT *kp, *dp; +{ + switch (dbp->get(dbp, kp, dp, flags)) { + case 0: + return; + case -1: + err("line %lu: getdata: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: + err("line %lu: getdata failed, no such key", lineno); + /* NOTREACHED */ + } +} + +void +put(dbp, kp, dp) + DB *dbp; + DBT *kp, *dp; +{ + switch (dbp->put(dbp, kp, dp, flags)) { + case 0: + break; + case -1: + err("line %lu: put: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: + (void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1); + break; + } +} + +void +rem(dbp, kp) + DB *dbp; + DBT *kp; +{ + switch (dbp->del(dbp, kp, flags)) { + case 0: + break; + case -1: + err("line %lu: rem: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: +#define NOSUCHKEY "rem failed, no such key\n" + if (ofd != STDOUT_FILENO) + (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); + else if (flags != R_CURSOR) + (void)fprintf(stderr, "%d: %.*s: %s", + lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); + else + (void)fprintf(stderr, + "%d: rem of cursor failed\n", lineno); +#undef NOSUCHKEY + break; + } +} + +void +synk(dbp) + DB *dbp; +{ + switch (dbp->sync(dbp, flags)) { + case 0: + break; + case -1: + err("line %lu: synk: %s", lineno, strerror(errno)); + /* NOTREACHED */ + } +} + +void +seq(dbp, kp) + DB *dbp; + DBT *kp; +{ + DBT data; + + switch (dbp->seq(dbp, kp, &data, flags)) { + case 0: + (void)write(ofd, data.data, data.size); + if (ofd == STDOUT_FILENO) + (void)write(ofd, "\n", 1); + break; + case -1: + err("line %lu: seq: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: +#define NOSUCHKEY "seq failed, no such key\n" + if (ofd != STDOUT_FILENO) + (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); + else if (flags == R_CURSOR) + (void)fprintf(stderr, "%d: %.*s: %s", + lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); + else + (void)fprintf(stderr, + "%d: seq (%s) failed\n", lineno, sflags(flags)); +#undef NOSUCHKEY + break; + } +} + +void +dump(dbp, rev) + DB *dbp; + int rev; +{ + DBT key, data; + int flags, nflags; + + if (rev) { + flags = R_LAST; + nflags = R_PREV; + } else { + flags = R_FIRST; + nflags = R_NEXT; + } + for (;; flags = nflags) + switch (dbp->seq(dbp, &key, &data, flags)) { + case 0: + (void)write(ofd, data.data, data.size); + if (ofd == STDOUT_FILENO) + (void)write(ofd, "\n", 1); + break; + case 1: + goto done; + case -1: + err("line %lu: (dump) seq: %s", + lineno, strerror(errno)); + /* NOTREACHED */ + } +done: return; +} + +u_int +setflags(s) + char *s; +{ + char *p, *index(); + + for (; isspace(*s); ++s); + if (*s == '\n' || *s == '\0') + return (0); + if ((p = index(s, '\n')) != NULL) + *p = '\0'; + if (!strcmp(s, "R_CURSOR")) return (R_CURSOR); + if (!strcmp(s, "R_FIRST")) return (R_FIRST); + if (!strcmp(s, "R_IAFTER")) return (R_IAFTER); + if (!strcmp(s, "R_IBEFORE")) return (R_IBEFORE); + if (!strcmp(s, "R_LAST")) return (R_LAST); + if (!strcmp(s, "R_NEXT")) return (R_NEXT); + if (!strcmp(s, "R_NOOVERWRITE")) return (R_NOOVERWRITE); + if (!strcmp(s, "R_PREV")) return (R_PREV); + if (!strcmp(s, "R_SETCURSOR")) return (R_SETCURSOR); + + err("line %lu: %s: unknown flag", lineno, s); + /* NOTREACHED */ +} + +char * +sflags(flags) + int flags; +{ + switch (flags) { + case R_CURSOR: return ("R_CURSOR"); + case R_FIRST: return ("R_FIRST"); + case R_IAFTER: return ("R_IAFTER"); + case R_IBEFORE: return ("R_IBEFORE"); + case R_LAST: return ("R_LAST"); + case R_NEXT: return ("R_NEXT"); + case R_NOOVERWRITE: return ("R_NOOVERWRITE"); + case R_PREV: return ("R_PREV"); + case R_SETCURSOR: return ("R_SETCURSOR"); + } + + return ("UNKNOWN!"); +} + +DBTYPE +dbtype(s) + char *s; +{ + if (!strcmp(s, "btree")) + return (DB_BTREE); + if (!strcmp(s, "hash")) + return (DB_HASH); + if (!strcmp(s, "recno")) + return (DB_RECNO); + err("%s: unknown type (use btree, hash or recno)", s); + /* NOTREACHED */ +} + +void * +setinfo(type, s) + DBTYPE type; + char *s; +{ + static BTREEINFO ib; + static HASHINFO ih; + static RECNOINFO rh; + char *eq, *index(); + + if ((eq = index(s, '=')) == NULL) + err("%s: illegal structure set statement", s); + *eq++ = '\0'; + if (!isdigit(*eq)) + err("%s: structure set statement must be a number", s); + + switch (type) { + case DB_BTREE: + if (!strcmp("flags", s)) { + ib.flags = atoi(eq); + return (&ib); + } + if (!strcmp("cachesize", s)) { + ib.cachesize = atoi(eq); + return (&ib); + } + if (!strcmp("maxkeypage", s)) { + ib.maxkeypage = atoi(eq); + return (&ib); + } + if (!strcmp("minkeypage", s)) { + ib.minkeypage = atoi(eq); + return (&ib); + } + if (!strcmp("lorder", s)) { + ib.lorder = atoi(eq); + return (&ib); + } + if (!strcmp("psize", s)) { + ib.psize = atoi(eq); + return (&ib); + } + break; + case DB_HASH: + if (!strcmp("bsize", s)) { + ih.bsize = atoi(eq); + return (&ih); + } + if (!strcmp("ffactor", s)) { + ih.ffactor = atoi(eq); + return (&ih); + } + if (!strcmp("nelem", s)) { + ih.nelem = atoi(eq); + return (&ih); + } + if (!strcmp("cachesize", s)) { + ih.cachesize = atoi(eq); + return (&ih); + } + if (!strcmp("lorder", s)) { + ih.lorder = atoi(eq); + return (&ih); + } + break; + case DB_RECNO: + if (!strcmp("flags", s)) { + rh.flags = atoi(eq); + return (&rh); + } + if (!strcmp("cachesize", s)) { + rh.cachesize = atoi(eq); + return (&rh); + } + if (!strcmp("lorder", s)) { + rh.lorder = atoi(eq); + return (&rh); + } + if (!strcmp("reclen", s)) { + rh.reclen = atoi(eq); + return (&rh); + } + if (!strcmp("bval", s)) { + rh.bval = atoi(eq); + return (&rh); + } + if (!strcmp("psize", s)) { + rh.psize = atoi(eq); + return (&rh); + } + break; + } + err("%s: unknown structure value", s); + /* NOTREACHED */ +} + +void * +rfile(name, lenp) + char *name; + size_t *lenp; +{ + struct stat sb; + void *p; + int fd; + char *np, *index(); + + for (; isspace(*name); ++name); + if ((np = index(name, '\n')) != NULL) + *np = '\0'; + if ((fd = open(name, O_RDONLY, 0)) < 0 || + fstat(fd, &sb)) + err("%s: %s\n", name, strerror(errno)); +#ifdef NOT_PORTABLE + if (sb.st_size > (off_t)SIZE_T_MAX) + err("%s: %s\n", name, strerror(E2BIG)); +#endif + if ((p = (void *)malloc((u_int)sb.st_size)) == NULL) + err("%s", strerror(errno)); + (void)read(fd, p, (int)sb.st_size); + *lenp = sb.st_size; + (void)close(fd); + return (p); +} + +void * +xmalloc(text, len) + char *text; + size_t len; +{ + void *p; + + if ((p = (void *)malloc(len)) == NULL) + err("%s", strerror(errno)); + memmove(p, text, len); + return (p); +} + +void +usage() +{ + (void)fprintf(stderr, + "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n"); + exit(1); +} + +#if __STDC__ +#include +#else +#include +#endif + +void +#if __STDC__ +err(const char *fmt, ...) +#else +err(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)fprintf(stderr, "dbtest: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + exit(1); + /* NOTREACHED */ +} diff --git a/src/util/berk_db/test/hash.tests/.Sanitize b/src/util/berk_db/test/hash.tests/.Sanitize new file mode 100644 index 000000000..197f68c50 --- /dev/null +++ b/src/util/berk_db/test/hash.tests/.Sanitize @@ -0,0 +1,40 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +driver2.c +makedb.sh +tcreat3.c +tdel.c +testit +thash4.c +tread2.c +tseq.c +tverify.c + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/util/berk_db/test/hash.tests/driver2.c b/src/util/berk_db/test/hash.tests/driver2.c new file mode 100644 index 000000000..2008a2899 --- /dev/null +++ b/src/util/berk_db/test/hash.tests/driver2.c @@ -0,0 +1,114 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)driver2.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* + * Test driver, to try to tackle the large ugly-split problem. + */ + +#include +#include +#include "ndbm.h" + +int my_hash(key, len) + char *key; + int len; +{ + return(17); /* So I'm cruel... */ +} + +main(argc, argv) + int argc; +{ + DB *db; + DBT key, content; + char keybuf[2049]; + char contentbuf[2049]; + char buf[256]; + int i; + HASHINFO info; + + info.bsize = 1024; + info.ffactor = 5; + info.nelem = 1; + info.cachesize = NULL; +#ifdef HASH_ID_PROGRAM_SPECIFIED + info.hash_id = HASH_ID_PROGRAM_SPECIFIED; + info.hash_func = my_hash; +#else + info.hash = my_hash; +#endif + info.lorder = 0; + if (!(db = dbopen("bigtest", O_RDWR | O_CREAT, 0644, DB_HASH, &info))) { + sprintf(buf, "dbopen: failed on file bigtest"); + perror(buf); + exit(1); + } + srandom(17); + key.data = keybuf; + content.data = contentbuf; + bzero(keybuf, sizeof(keybuf)); + bzero(contentbuf, sizeof(contentbuf)); + for (i=1; i <= 500; i++) { + key.size = 128 + (random()&1023); + content.size = 128 + (random()&1023); +/* printf("%d: Key size %d, data size %d\n", i, key.size, + content.size); */ + sprintf(keybuf, "Key #%d", i); + sprintf(contentbuf, "Contents #%d", i); + if ((db->put)(db, &key, &content, R_NOOVERWRITE)) { + sprintf(buf, "dbm_store #%d", i); + perror(buf); + } + } + if ((db->close)(db)) { + perror("closing hash file"); + exit(1); + } + exit(0); +} + + + diff --git a/src/util/berk_db/test/hash.tests/makedb.sh b/src/util/berk_db/test/hash.tests/makedb.sh new file mode 100644 index 000000000..f28e281fd --- /dev/null +++ b/src/util/berk_db/test/hash.tests/makedb.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# +# @(#)makedb.sh 8.1 (Berkeley) 6/4/93 + +awk '{i++; print $0; print i;}' /usr/share/dict/words > WORDS +ls /bin /usr/bin /usr/ucb /etc | egrep '^(...|....|.....|......)$' | \ +sort | uniq | \ +awk '{ + printf "%s\n", $0 + for (i = 0; i < 1000; i++) + printf "%s+", $0 + printf "\n" +}' > LONG.DATA diff --git a/src/util/berk_db/test/hash.tests/tcreat3.c b/src/util/berk_db/test/hash.tests/tcreat3.c new file mode 100644 index 000000000..bd125ac6e --- /dev/null +++ b/src/util/berk_db/test/hash.tests/tcreat3.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tcreat3.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key; + DB *dbp; + HASHINFO ctl; + FILE *fp; + int trash; + + int i = 0; + + argv++; + ctl.hash = NULL; + ctl.bsize = atoi(*argv++); + ctl.ffactor = atoi(*argv++); + ctl.nelem = atoi(*argv++); + ctl.lorder = 0; + if (!(dbp = dbopen( "hashtest", + O_CREAT|O_TRUNC|O_RDWR, 0600, DB_HASH, &ctl))){ + /* create table */ + fprintf(stderr, "cannot create: hash table (size %d)\n", + INITIAL); + exit(1); + } + + key.data = wp1; + item.data = wp2; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + item.size = strlen(wp2); + +/* + * enter key/data pair into the table + */ + if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) { + fprintf(stderr, "cannot enter: key %s\n", + item.data); + exit(1); + } + } + + (dbp->close)(dbp); + exit(0); +} diff --git a/src/util/berk_db/test/hash.tests/tdel.c b/src/util/berk_db/test/hash.tests/tdel.c new file mode 100644 index 000000000..ed3f90ad7 --- /dev/null +++ b/src/util/berk_db/test/hash.tests/tdel.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tdel.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +/* Usage: thash pagesize fillfactor file */ +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key; + DB *dbp; + HASHINFO ctl; + FILE *fp; + int stat; + + int i = 0; + + argv++; + ctl.nelem = INITIAL; + ctl.hash = NULL; + ctl.bsize = atoi(*argv++); + ctl.ffactor = atoi(*argv++); + ctl.cachesize = 1024 * 1024; /* 1 MEG */ + ctl.lorder = 0; + argc -= 2; + if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR, 0400, DB_HASH, &ctl))) { + /* create table */ + fprintf(stderr, "cannot create: hash table size %d)\n", + INITIAL); + exit(1); + } + + key.data = wp1; + item.data = wp2; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + item.size = strlen(wp2); + +/* + * enter key/data pair into the table + */ + if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) { + fprintf(stderr, "cannot enter: key %s\n", + item.data); + exit(1); + } + } + + if ( --argc ) { + fp = fopen ( argv[0], "r"); + i = 0; + while ( fgets(wp1, 8192, fp) && + fgets(wp2, 8192, fp) && + i++ < MAXWORDS) { + key.size = strlen(wp1); + stat = (dbp->del)(dbp, &key, 0); + if (stat) { + fprintf ( stderr, "Error retrieving %s\n", key.data ); + exit(1); + } + } + fclose(fp); + } + (dbp->close)(dbp); + exit(0); +} diff --git a/src/util/berk_db/test/hash.tests/testit b/src/util/berk_db/test/hash.tests/testit new file mode 100644 index 000000000..039457a9c --- /dev/null +++ b/src/util/berk_db/test/hash.tests/testit @@ -0,0 +1,147 @@ +#!/bin/csh -f +# +# @(#)testit 8.1 (Berkeley) 6/4/93 +# + +echo "" +echo "PAGE FILL " +set name=WORDS + set i = 256 + foreach j ( 11 14 21 ) + thash4 $i $j 25000 65536 $name < $name + end + set i = 512 + foreach j ( 21 28 43 ) + thash4 $i $j 25000 65536 $name < $name + end + set i = 1024 + foreach j ( 43 57 85 ) + thash4 $i $j 25000 65536 $name < $name + end + set i = 2048 + foreach j ( 85 114 171 ) + thash4 $i $j 25000 65536 $name < $name + end + set i = 4096 + foreach j ( 171 228 341 ) + thash4 $i $j 25000 65536 $name < $name + end + set i = 8192 + foreach j ( 341 455 683 ) + thash4 $i $j 25000 65536 $name < $name + end + echo "PAGE FILL " + set i = 256 + foreach j ( 11 14 21 ) + echo "$i"_"$j" + tcreat3 $i $j 25000 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end + set i = 512 + foreach j ( 21 28 43 ) + echo "$i"_"$j" + tcreat3 $i $j 25000 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end + set i = 1024 + foreach j ( 43 57 85 ) + echo "$i"_"$j" + tcreat3 $i $j 25000 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end + set i = 2048 + foreach j ( 85 114 171 ) + echo "$i"_"$j" + tcreat3 $i $j 25000 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end + set i = 4096 + foreach j ( 171 228 341 ) + echo "$i"_"$j" + tcreat3 $i $j 25000 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end + set i = 8192 + foreach j ( 341 455 683 ) + echo "$i"_"$j" + tcreat3 $i $j 25000 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end +set name=LONG.DATA + set i = 1024 + foreach j ( 1 2 4 ) + echo thash4 $i $j 600 65536 $name + thash4 $i $j 600 65536 $name < $name + end + + set i = 2048 + foreach j ( 1 2 4 ) + echo thash4 $i $j 600 65536 $name + thash4 $i $j 600 65536 $name < $name + end + set i = 4096 + foreach j ( 1 2 4 ) + echo thash4 $i $j 600 65536 $name + thash4 $i $j 600 65536 $name < $name + end + set i = 8192 + foreach j ( 2 4 8 ) + echo thash4 $i $j 600 65536 $name + thash4 $i $j 600 65536 $name < $name + end + echo "PAGE FILL " + set i = 1024 + foreach j ( 1 2 4 ) + echo "$i"_"$j" + tcreat3 $i $j 600 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end + set i = 2048 + foreach j ( 1 2 4 ) + echo "$i"_"$j" + tcreat3 $i $j 600 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end + set i = 4096 + foreach j ( 1 2 4 ) + echo "$i"_"$j" + tcreat3 $i $j 600 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end + set i = 8192 + foreach j ( 2 4 8 ) + echo "$i"_"$j" + tcreat3 $i $j 600 $name < $name + tread2 65536 < $name + tverify $name < $name + tseq > /dev/null + tdel $i $j $name < $name + end +driver2 diff --git a/src/util/berk_db/test/hash.tests/thash4.c b/src/util/berk_db/test/hash.tests/thash4.c new file mode 100644 index 000000000..9e344cb83 --- /dev/null +++ b/src/util/berk_db/test/hash.tests/thash4.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)thash4.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +/* Usage: thash pagesize fillfactor file */ +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key, res; + DB *dbp; + HASHINFO ctl; + FILE *fp; + int stat; + time_t t; + + int i = 0; + + argv++; + ctl.hash = NULL; + ctl.bsize = atoi(*argv++); + ctl.ffactor = atoi(*argv++); + ctl.nelem = atoi(*argv++); + ctl.cachesize = atoi(*argv++); + ctl.lorder = 0; + if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR, 0400, DB_HASH, &ctl))) { + /* create table */ + fprintf(stderr, "cannot create: hash table size %d)\n", + INITIAL); + fprintf(stderr, "\terrno: %d\n", errno); + exit(1); + } + + key.data = wp1; + item.data = wp2; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + item.size = strlen(wp2); + +/* + * enter key/data pair into the table + */ + if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) { + fprintf(stderr, "cannot enter: key %s\n", + item.data); + fprintf(stderr, "\terrno: %d\n", errno); + exit(1); + } + } + + if ( --argc ) { + fp = fopen ( argv[0], "r"); + i = 0; + while ( fgets(wp1, 256, fp) && + fgets(wp2, 8192, fp) && + i++ < MAXWORDS) { + + key.size = strlen(wp1); + stat = (dbp->get)(dbp, &key, &res, 0); + if (stat < 0 ) { + fprintf ( stderr, "Error retrieving %s\n", key.data ); + fprintf(stderr, "\terrno: %d\n", errno); + exit(1); + } else if ( stat > 0 ) { + fprintf ( stderr, "%s not found\n", key.data ); + fprintf(stderr, "\terrno: %d\n", errno); + exit(1); + } + } + fclose(fp); + } + dbp->close(dbp); + exit(0); +} diff --git a/src/util/berk_db/test/hash.tests/tread2.c b/src/util/berk_db/test/hash.tests/tread2.c new file mode 100644 index 000000000..8f0155685 --- /dev/null +++ b/src/util/berk_db/test/hash.tests/tread2.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tread2.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +typedef struct { /* info to be stored */ + int num, siz; +} info; + +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key, res; + DB *dbp; + HASHINFO ctl; + int stat; + + int i = 0; + + ctl.nelem = INITIAL; + ctl.hash = NULL; + ctl.bsize = 64; + ctl.ffactor = 1; + ctl.cachesize = atoi(*argv++); + ctl.lorder = 0; + if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, &ctl))) { + /* create table */ + fprintf(stderr, "cannot open: hash table\n" ); + exit(1); + } + + key.data = wp1; + item.data = wp2; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + item.size = strlen(wp2); + + stat = (dbp->get)(dbp, &key, &res,0); + if (stat < 0) { + fprintf ( stderr, "Error retrieving %s\n", key.data ); + exit(1); + } else if ( stat > 0 ) { + fprintf ( stderr, "%s not found\n", key.data ); + exit(1); + } + } + (dbp->close)(dbp); + exit(0); +} diff --git a/src/util/berk_db/test/hash.tests/tseq.c b/src/util/berk_db/test/hash.tests/tseq.c new file mode 100644 index 000000000..f45700e5c --- /dev/null +++ b/src/util/berk_db/test/hash.tests/tseq.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tseq.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + + +char wp[8192]; +char cp[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key, res; + DB *dbp; + FILE *fp; + int stat; + + if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, NULL))) { + /* create table */ + fprintf(stderr, "cannot open: hash table\n" ); + exit(1); + } + +/* +* put info in structure, and structure in the item +*/ + for ( stat = (dbp->seq) (dbp, &res, &item, 1 ); + stat == 0; + stat = (dbp->seq) (dbp, &res, &item, 0 ) ) { + + bcopy ( res.data, wp, res.size ); + wp[res.size] = 0; + bcopy ( item.data, cp, item.size ); + cp[item.size] = 0; + + printf ( "%s %s\n", wp, cp ); + } + (dbp->close)(dbp); + exit(0); +} diff --git a/src/util/berk_db/test/hash.tests/tverify.c b/src/util/berk_db/test/hash.tests/tverify.c new file mode 100644 index 000000000..ac5d2f9ea --- /dev/null +++ b/src/util/berk_db/test/hash.tests/tverify.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tverify.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +typedef struct { /* info to be stored */ + int num, siz; +} info; + +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT key, res; + DB *dbp; + HASHINFO ctl; + int trash; + int stat; + + int i = 0; + + ctl.nelem = INITIAL; + ctl.hash = NULL; + ctl.bsize = 64; + ctl.ffactor = 1; + ctl.cachesize = 1024 * 1024; /* 1 MEG */ + ctl.lorder = 0; + if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, &ctl))) { + /* create table */ + fprintf(stderr, "cannot open: hash table\n" ); + exit(1); + } + + key.data = wp1; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + + stat = (dbp->get)(dbp, &key, &res,0); + if (stat < 0) { + fprintf ( stderr, "Error retrieving %s\n", key.data ); + exit(1); + } else if ( stat > 0 ) { + fprintf ( stderr, "%s not found\n", key.data ); + exit(1); + } + if ( memcmp ( res.data, wp2, res.size ) ) { + fprintf ( stderr, "data for %s is incorrect. Data was %s. Should have been %s\n", key.data, res.data, wp2 ); + } + } + (dbp->close)(dbp); + exit(0); +} diff --git a/src/util/berk_db/test/run.test b/src/util/berk_db/test/run.test new file mode 100644 index 000000000..81ba71e45 --- /dev/null +++ b/src/util/berk_db/test/run.test @@ -0,0 +1,705 @@ +#!/bin/sh - +# +# @(#)run.test 8.10 (Berkeley) 7/26/94 +# + +# db regression tests +main() +{ + + PROG=./dbtest + TMP1=t1 + TMP2=t2 + TMP3=t3 + + if [ -f /usr/share/dict/words ]; then + DICT=/usr/share/dict/words + elif [ -f /usr/dict/words ]; then + DICT=/usr/dict/words + else + echo 'run.test: no dictionary' + exit 1 + fi + + if [ $# -eq 0 ]; then + for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do + test$t + done + else + while [ $# -gt 0 ] + do case "$1" in + test*) + $1;; + [0-9]*) + test$1;; + btree) + for t in 1 2 3 7 8 9 10 12 13; do + test$t + done;; + hash) + for t in 1 2 3 8 13 20; do + test$t + done;; + recno) + for t in 1 2 3 4 5 6 7 10 11; do + test$t + done;; + *) + echo "run.test: unknown test $1" + echo "usage: run.test test# | type" + exit 1 + esac + shift + done + fi + rm -f $TMP1 $TMP2 $TMP3 + exit 0 +} + +# Take the first hundred entries in the dictionary, and make them +# be key/data pairs. +test1() +{ + echo "Test 1: btree, hash: small key, small data pairs" + sed 200q $DICT > $TMP1 + for type in btree hash; do + rm -f $TMP2 $TMP3 + for i in `sed 200q $DICT`; do + echo p + echo k$i + echo d$i + echo g + echo k$i + done > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test1: type $type: failed" + exit 1 + fi + done + echo "Test 1: recno: small key, small data pairs" + rm -f $TMP2 $TMP3 + sed 200q $DICT | + awk '{ + ++i; + printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test1: type recno: failed" + exit 1 + fi +} + +# Take the first 200 entries in the dictionary, and give them +# each a medium size data entry. +test2() +{ + echo "Test 2: btree, hash: small key, medium data pairs" + mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz + echo $mdata | + awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1 + for type in hash btree; do + rm -f $TMP2 $TMP3 + for i in `sed 200q $DICT`; do + echo p + echo k$i + echo d$mdata + echo g + echo k$i + done > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test2: type $type: failed" + exit 1 + fi + done + echo "Test 2: recno: small key, medium data pairs" + rm -f $TMP2 $TMP3 + echo $mdata | + awk '{ for (i = 1; i < 201; ++i) + printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test2: type recno: failed" + exit 1 + fi +} + +# Insert the programs in /bin with their paths as their keys. +test3() +{ + echo "Test 3: hash: small key, big data pairs" + rm -f $TMP1 + (find /bin -type f -print | xargs cat) > $TMP1 + for type in hash; do + rm -f $TMP2 $TMP3 + for i in `find /bin -type f -print`; do + echo p + echo k$i + echo D$i + echo g + echo k$i + done > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test3: $type: failed" + exit 1 + fi + done +# echo "Test 3: btree: small key, big data pairs" +# for psize in 512 16384 65536; do +# echo " page size $psize" +# for type in btree; do +# rm -f $TMP2 $TMP3 +# for i in `find /bin -type f -print`; do +# echo p +# echo k$i +# echo D$i +# echo g +# echo k$i +# done > $TMP2 +# $PROG -i psize=$psize -o $TMP3 $type $TMP2 +# if (cmp -s $TMP1 $TMP3) ; then : +# else +# echo "test3: $type: page size $psize: failed" +# exit 1 +# fi +# done +# done +# echo "Test 3: recno: big data pairs" +# rm -f $TMP2 $TMP3 +# find /bin -type f -print | +# awk '{ +# ++i; +# printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i); +# }' > $TMP2 +# for psize in 512 16384 65536; do +# echo " page size $psize" +# $PROG -i psize=$psize -o $TMP3 recno $TMP2 +# if (cmp -s $TMP1 $TMP3) ; then : +# else +# echo "test3: recno: page size $psize: failed" +# exit 1 +# fi +# done +} + +# Do random recno entries. +test4() +{ + echo "Test 4: recno: random entries" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 37; i <= 37 + 88 * 17; i += 17) { + if (i % 41) + s = substr($0, 1, i % 41); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + for (i = 1; i <= 15; ++i) { + if (i % 41) + s = substr($0, 1, i % 41); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + for (i = 19234; i <= 19234 + 61 * 27; i += 27) { + if (i % 41) + s = substr($0, 1, i % 41); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + exit + }' > $TMP1 + rm -f $TMP2 $TMP3 + cat $TMP1 | + awk 'BEGIN { + i = 37; + incr = 17; + } + { + printf("p\nk%d\nd%s\n", i, $0); + if (i == 19234 + 61 * 27) + exit; + if (i == 37 + 88 * 17) { + i = 1; + incr = 1; + } else if (i == 15) { + i = 19234; + incr = 27; + } else + i += incr; + } + END { + for (i = 37; i <= 37 + 88 * 17; i += 17) + printf("g\nk%d\n", i); + for (i = 1; i <= 15; ++i) + printf("g\nk%d\n", i); + for (i = 19234; i <= 19234 + 61 * 27; i += 27) + printf("g\nk%d\n", i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test4: type recno: failed" + exit 1 + fi +} + +# Do reverse order recno entries. +test5() +{ + echo "Test 5: recno: reverse order entries" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk ' { + for (i = 1500; i; --i) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + cat $TMP1 | + awk 'BEGIN { + i = 1500; + } + { + printf("p\nk%d\nd%s\n", i, $0); + --i; + } + END { + for (i = 1500; i; --i) + printf("g\nk%d\n", i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test5: type recno: failed" + exit 1 + fi +} + +# Do alternating order recno entries. +test6() +{ + echo "Test 6: recno: alternating order entries" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk ' { + for (i = 1; i < 1200; i += 2) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + for (i = 2; i < 1200; i += 2) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + cat $TMP1 | + awk 'BEGIN { + i = 1; + even = 0; + } + { + printf("p\nk%d\nd%s\n", i, $0); + i += 2; + if (i >= 1200) { + if (even == 1) + exit; + even = 1; + i = 2; + } + } + END { + for (i = 1; i < 1200; ++i) + printf("g\nk%d\n", i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + sort -o $TMP1 $TMP1 + sort -o $TMP3 $TMP3 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test6: type recno: failed" + exit 1 + fi +} + +# Delete cursor record +test7() +{ + echo "Test 7: btree, recno: delete cursor record" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 120; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + printf("%05d: input key %d: %s\n", 120, 120, $0); + printf("seq failed, no such key\n"); + printf("%05d: input key %d: %s\n", 1, 1, $0); + printf("%05d: input key %d: %s\n", 2, 2, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + for type in btree recno; do + cat $TMP1 | + awk '{ + if (i == 120) + exit; + printf("p\nk%d\nd%s\n", ++i, $0); + } + END { + printf("fR_NEXT\n"); + for (i = 1; i <= 120; ++i) + printf("s\n"); + printf("fR_CURSOR\ns\nk120\n"); + printf("r\n"); + printf("fR_NEXT\ns\n"); + printf("fR_CURSOR\ns\nk1\n"); + printf("r\n"); + printf("fR_FIRST\ns\n"); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test7: type $type: failed" + exit 1 + fi + done +} + +# Make sure that overflow pages are reused. +test8() +{ + echo "Test 8: btree, hash: repeated small key, big data pairs" + rm -f $TMP1 + echo "" | + awk 'BEGIN { + for (i = 1; i <= 10; ++i) { + printf("p\nkkey1\nD/bin/sh\n"); + printf("p\nkkey2\nD/bin/csh\n"); + if (i % 8 == 0) { + printf("c\nkkey2\nD/bin/csh\n"); + printf("c\nkkey1\nD/bin/sh\n"); + printf("e\t%d of 10 (comparison)\n", i); + } else + printf("e\t%d of 10 \n", i); + printf("r\nkkey1\nr\nkkey2\n"); + } + }' > $TMP1 + $PROG btree $TMP1 +# $PROG hash $TMP1 + # No explicit test for success. +} + +# Test btree duplicate keys +test9() +{ + echo "Test 9: btree: duplicate keys" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 543; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + for type in btree; do + cat $TMP1 | + awk '{ + if (i++ % 2) + printf("p\nkduplicatekey\nd%s\n", $0); + else + printf("p\nkunique%dkey\nd%s\n", i, $0); + } + END { + printf("o\n"); + }' > $TMP2 + $PROG -iflags=1 -o $TMP3 $type $TMP2 + sort -o $TMP3 $TMP3 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test9: type $type: failed" + exit 1 + fi + done +} + +# Test use of cursor flags without initialization +test10() +{ + echo "Test 10: btree, recno: test cursor flag use" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 20; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + # Test that R_CURSOR doesn't succeed before cursor initialized + for type in btree recno; do + cat $TMP1 | + awk '{ + if (i == 10) + exit; + printf("p\nk%d\nd%s\n", ++i, $0); + } + END { + printf("fR_CURSOR\nr\n"); + printf("eR_CURSOR SHOULD HAVE FAILED\n"); + }' > $TMP2 + $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1 + if [ -s $TMP3 ] ; then + echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED" + exit 1 + fi + done + for type in btree recno; do + cat $TMP1 | + awk '{ + if (i == 10) + exit; + printf("p\nk%d\nd%s\n", ++i, $0); + } + END { + printf("fR_CURSOR\np\nk1\ndsome data\n"); + printf("eR_CURSOR SHOULD HAVE FAILED\n"); + }' > $TMP2 + $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1 + if [ -s $TMP3 ] ; then + echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED" + exit 1 + fi + done +} + +# Test insert in reverse order. +test11() +{ + echo "Test 11: recno: reverse order insert" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 779; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + for type in recno; do + cat $TMP1 | + awk '{ + if (i == 0) { + i = 1; + printf("p\nk1\nd%s\n", $0); + printf("%s\n", "fR_IBEFORE"); + } else + printf("p\nk1\nd%s\n", $0); + } + END { + printf("or\n"); + }' > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test11: type $type: failed" + exit 1 + fi + done +} + +# Take the first 20000 entries in the dictionary, reverse them, and give +# them each a small size data entry. Use a small page size to make sure +# the btree split code gets hammered. +test12() +{ + echo "Test 12: btree: lots of keys, small page size" + mdata=abcdefghijklmnopqrstuvwxy + echo $mdata | + awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1 + for type in btree; do + rm -f $TMP2 $TMP3 + for i in `sed 20000q $DICT | rev`; do + echo p + echo k$i + echo d$mdata + echo g + echo k$i + done > $TMP2 + $PROG -i psize=512 -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test12: type $type: failed" + exit 1 + fi + done +} + +# Test different byte orders. +test13() +{ + echo "Test 13: btree, hash: differing byte orders" + sed 50q $DICT > $TMP1 + for order in 1234 4321; do + for type in btree hash; do + rm -f byte.file $TMP2 $TMP3 + for i in `sed 50q $DICT`; do + echo p + echo k$i + echo d$i + echo g + echo k$i + done > $TMP2 + $PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test13: $type/$order put failed" + exit 1 + fi + for i in `sed 50q $DICT`; do + echo g + echo k$i + done > $TMP2 + $PROG -s \ + -ilorder=$order -f byte.file -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test13: $type/$order get failed" + exit 1 + fi + done + done + rm -f byte.file +} + +# Try a variety of bucketsizes and fill factors for hashing +test20() +{ + echo\ + "Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 10000; ++i) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("%s\n", s); + } + exit; + }' > $TMP1 + sed 10000q $DICT | + awk 'BEGIN { + ds="abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" + } + { + if (++i % 34) + s = substr(ds, 1, i % 34); + else + s = substr(ds, 1); + printf("p\nk%s\nd%s\n", $0, s); + }' > $TMP2 + sed 10000q $DICT | + awk '{ + ++i; + printf("g\nk%s\n", $0); + }' >> $TMP2 + bsize=256 + for ffactor in 11 14 21; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=512 + for ffactor in 21 28 43; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=1024 + for ffactor in 43 57 85; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=2048 + for ffactor in 85 114 171; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=4096 + for ffactor in 171 228 341; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=8192 + for ffactor in 341 455 683; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done +} + +main $* -- 2.26.2